From bac4099acb0f6191fa55f68fe2a6fb4fe2dd517e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 17 Aug 2012 12:47:38 -0600 Subject: [PATCH 001/378] fix crash in findFrameMapInSimpleTable due to bug in instanceof implementation We weren't adding entries to the frame map for calls to the instanceof thunk when compiling methods. However, that thunk may trigger a GC, in which case we'll need to unwind the stack, which will lead to a crash if we don't have a frame map entry for that instruction. --- src/compile.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 50e2bfb9e2..e29f4e592a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5064,21 +5064,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object argument; Thunk thunk; - TraceElement* trace; if (LIKELY(class_)) { argument = class_; thunk = instanceOf64Thunk; - trace = 0; } else { argument = makePair(t, context->method, reference); thunk = instanceOfFromReferenceThunk; - trace = frame->trace(0, 0); } frame->pushInt (c->call (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, trace, 4, Compiler::IntegerType, + 0, frame->trace(0, 0), 4, Compiler::IntegerType, 3, c->register_(t->arch->thread()), frame->append(argument), instance)); } break; From 1f1c3c4c414a62643f279f1527c43ff06788d016 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 24 Aug 2012 18:14:01 -0600 Subject: [PATCH 002/378] allow main thread to use DetachCurrentThread When I originally implemented DetachCurrentThread, I assumed it didn't make sense for the main thread to detach itself from the VM, and I was concerned that allowing it might cause problems for any other threads still attached. However, detaching the main thread is allowed by the JNI spec as of Java 2, and OpenJDK's java command does this just before calling DestroyJavaVM. Therefore, this commit ensures that the VM doesn't abort if the main thread is detached. --- src/jnienv.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index e4abe152f5..65fb57ab1e 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -45,8 +45,6 @@ DetachCurrentThread(Machine* m) { Thread* t = static_cast(m->localThread->get()); if (t) { - expect(t, t != m->rootThread); - m->localThread->set(0); ACQUIRE_RAW(t, t->m->stateLock); From c2b53497ab41d907f05dc0e5579fced2e85f2786 Mon Sep 17 00:00:00 2001 From: Gernot Kvas Date: Sun, 26 Aug 2012 17:27:22 +0200 Subject: [PATCH 003/378] Fix stacktrace when building with MSVC --- src/classpath-common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classpath-common.h b/src/classpath-common.h index d8105b9cd7..47d11343ac 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -278,7 +278,7 @@ makeStackTraceElement(Thread* t, object e) THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, class_)); replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast(&byteArrayBody(t, class_, 0))); - class_ = makeString(t, "%s", s); + class_ = makeString(t, "%s", RUNTIME_ARRAY_BODY(s)); object method = methodName(t, traceElementMethod(t, e)); PROTECT(t, method); From 8c48a44e54400f999a8368a97ca257f94eacd164 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 29 Aug 2012 18:27:37 -0600 Subject: [PATCH 004/378] set main thread context classloader correctly for OpenJDK port sun.misc.Launcher has its own idea about what the application classloader should be, but we need to override it with the system classloader created by the VM. This is achieved by running Launcher.getLauncher (which has the side effect of setting Thread.contextClassLoader) and then overriding it. --- src/classpath-openjdk.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index a965fd676d..f4de3f9fca 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -623,6 +623,13 @@ class MyClasspath : public Classpath { t->m->processor->invoke (t, root(t, Machine::BootLoader), "java/lang/System", "initializeSystemClass", "()V", 0); + + t->m->processor->invoke + (t, root(t, Machine::BootLoader), "sun/misc/Launcher", + "getLauncher", "()Lsun/misc/Launcher;", 0); + + set(t, t->javaThread, ThreadContextClassLoader, + root(t, Machine::AppLoader)); } virtual const char* From 374bdb372650333317d4fe0359dd4ca4409ea4a8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 29 Aug 2012 18:32:45 -0600 Subject: [PATCH 005/378] implement Runtime.maxMemory for OpenJDK port Some apps refuse to run if Runtime.maxMemory returns a value that's "too small", so our stub implementation returning zero was not sufficient. Now we return the actual heap size limit in bytes. --- src/classpath-openjdk.cpp | 2 +- src/heap.cpp | 4 ++++ src/heap.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index f4de3f9fca..299441a9b7 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3116,7 +3116,7 @@ EXPORT(JVM_FreeMemory)() extern "C" JNIEXPORT jlong JNICALL EXPORT(JVM_MaxMemory)() { - return 0; + return local::globalMachine->heap->limit(); } extern "C" JNIEXPORT jint JNICALL diff --git a/src/heap.cpp b/src/heap.cpp index 0bc37862fd..b46faeda01 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -1867,6 +1867,10 @@ class MyHeap: public Heap { c.immortalHeapEnd = start + sizeInWords; } + virtual unsigned limit() { + return c.limit; + } + virtual bool limitExceeded() { return c.count > c.limit; } diff --git a/src/heap.h b/src/heap.h index c3f1f8b4c8..0ee4699914 100644 --- a/src/heap.h +++ b/src/heap.h @@ -59,6 +59,7 @@ class Heap: public Allocator { virtual void setClient(Client* client) = 0; virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) = 0; + virtual unsigned limit() = 0; virtual bool limitExceeded() = 0; virtual void collect(CollectionType type, unsigned footprint) = 0; virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, From 7534eecdb368b7f493c0206dc7343aba7f56e93a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 29 Aug 2012 18:34:28 -0600 Subject: [PATCH 006/378] implement JVM_ConstantPoolGetDoubleAt --- src/classpath-openjdk.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 299441a9b7..844739e3e3 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4678,9 +4678,27 @@ extern "C" JNIEXPORT jfloat JNICALL EXPORT(JVM_ConstantPoolGetFloatAt)(Thread*, jobject, jobject, jint) { abort(); } +uint64_t +jvmConstantPoolGetDoubleAt(Thread* t, uintptr_t* arguments) +{ + jobject pool = reinterpret_cast(arguments[0]); + jint index = arguments[1]; + + double v; memcpy(&singletonValue(t, *pool, index - 1), &v, 8); + + return doubleToBits(v); +} + extern "C" JNIEXPORT jdouble JNICALL -EXPORT(JVM_ConstantPoolGetDoubleAt)(Thread*, jobject, jobject, jint) -{ abort(); } +EXPORT(JVM_ConstantPoolGetDoubleAt)(Thread* t, jobject, jobject pool, + jint index) +{ + uintptr_t arguments[] = { reinterpret_cast(pool), + static_cast(index) }; + + return bitsToDouble + (run(t, jvmConstantPoolGetDoubleAt, arguments)); +} extern "C" JNIEXPORT jstring JNICALL EXPORT(JVM_ConstantPoolGetStringAt)(Thread*, jobject, jobject, jint) From 9ceacf16e9c020ade36dd7e4149261010c17b1f8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 29 Aug 2012 18:34:51 -0600 Subject: [PATCH 007/378] don't throw an exception from resolveClass when throw_ == false resolveClass was correctly respecting throw_ == false if the requested class was not found, but it still threw an exception if e.g. the superclass was missing. Now we catch such exceptions and return null as appropriate. --- src/machine.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index b9782ac3f0..790c9fa1aa 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3983,6 +3983,17 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size, return real; } +uint64_t +runParseClass(Thread* t, uintptr_t* arguments) +{ + object loader = reinterpret_cast(arguments[0]); + System::Region* region = reinterpret_cast(arguments[1]); + Machine::Type throwType = static_cast(arguments[2]); + + return reinterpret_cast + (parseClass(t, loader, region->start(), region->length(), throwType)); +} + object resolveSystemClass(Thread* t, object loader, object spec, bool throw_, Machine::Type throwType) @@ -4028,9 +4039,24 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_, { THREAD_RESOURCE(t, System::Region*, region, region->dispose()); + uintptr_t arguments[] = { reinterpret_cast(loader), + reinterpret_cast(region), + static_cast(throwType) }; + // parse class file - class_ = parseClass - (t, loader, region->start(), region->length(), throwType); + class_ = reinterpret_cast + (runRaw(t, runParseClass, arguments)); + + if (UNLIKELY(t->exception)) { + if (throw_) { + object e = t->exception; + t->exception = 0; + vm::throw_(t, e); + } else { + t->exception = 0; + return 0; + } + } } if (Verbose) { From 3f039864d1560a5aa570c6f4a07160761034b0d7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 29 Aug 2012 12:10:31 -0600 Subject: [PATCH 008/378] fix memcpy argument order bug in jvmConstantPoolGetDoubleAt --- src/classpath-openjdk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 844739e3e3..97c5a3372e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4684,7 +4684,7 @@ jvmConstantPoolGetDoubleAt(Thread* t, uintptr_t* arguments) jobject pool = reinterpret_cast(arguments[0]); jint index = arguments[1]; - double v; memcpy(&singletonValue(t, *pool, index - 1), &v, 8); + double v; memcpy(&v, &singletonValue(t, *pool, index - 1), 8); return doubleToBits(v); } From 24f682f5b676fd4cbf25592054022d9a410fbcc5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 3 Sep 2012 08:44:13 -0600 Subject: [PATCH 009/378] fix 64-bit shifts on x86_32 (part 2) My earlier attempt (fa5d76b) missed an important detail, and somehow I forgot to test the 32-bit OpenJDK build which made that omission obvious. Here's the fix. --- src/x86.cpp | 12 ++++++------ test/Longs.java | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 06a492dcfd..acdb8f1f71 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2186,9 +2186,9 @@ shiftLeftRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { if (TargetBytesPerWord == 4 and bSize == 8) { + Assembler::Register cx(rcx); if (a->low != rcx) { c->client->save(rcx); - Assembler::Register cx(rcx); ResolvedPromise promise(0x3F); Assembler::Constant mask(&promise); moveRR(c, 4, a, 4, &cx); @@ -2204,7 +2204,7 @@ shiftLeftRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, ResolvedPromise promise(32); Assembler::Constant constant(&promise); - compareCR(c, aSize, &constant, aSize, a); + compareCR(c, aSize, &constant, aSize, &cx); opcode(c, 0x7c); //jl c->code.append(2 + 2); @@ -2232,9 +2232,9 @@ shiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { if (TargetBytesPerWord == 4 and bSize == 8) { + Assembler::Register cx(rcx); if (a->low != rcx) { c->client->save(rcx); - Assembler::Register cx(rcx); ResolvedPromise promise(0x3F); Assembler::Constant mask(&promise); moveRR(c, 4, a, 4, &cx); @@ -2250,7 +2250,7 @@ shiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, ResolvedPromise promise(32); Assembler::Constant constant(&promise); - compareCR(c, aSize, &constant, aSize, a); + compareCR(c, aSize, &constant, aSize, &cx); opcode(c, 0x7c); //jl c->code.append(2 + 3); @@ -2281,9 +2281,9 @@ unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { if (TargetBytesPerWord == 4 and bSize == 8) { + Assembler::Register cx(rcx); if (a->low != rcx) { c->client->save(rcx); - Assembler::Register cx(rcx); ResolvedPromise promise(0x3F); Assembler::Constant mask(&promise); moveRR(c, 4, a, 4, &cx); @@ -2299,7 +2299,7 @@ unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, ResolvedPromise promise(32); Assembler::Constant constant(&promise); - compareCR(c, aSize, &constant, aSize, a); + compareCR(c, aSize, &constant, aSize, &cx); opcode(c, 0x7c); //jl c->code.append(2 + 2); diff --git a/test/Longs.java b/test/Longs.java index 649ec6b2ff..4d9395f7b0 100644 --- a/test/Longs.java +++ b/test/Longs.java @@ -385,6 +385,10 @@ public class Longs { { long b = 0xBEL; int x = 0; int y = 0xFF; expect(((b >>> x) & y) == 0xBEL); } + + { long b = 0xFFFFFFFFFFFFFFFFL; int s = 20; + expect((b >>> -s) == 0xFFFFF); + } } } From d88a33329aabd68b25b510e0c02fd4bccbdf434d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xerxes=20R=C3=A5nby?= Date: Wed, 5 Sep 2012 10:29:12 +0200 Subject: [PATCH 010/378] Add a non-versioned SONAME to Avian libjvm.so that matches the Hotspot Server/Client libjvm.so SONAME, this allow libjava.so in OpenJDK 7 to find the Avian libjvm.so during ldopen. --- makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 7782850780..d84cd678e3 100755 --- a/makefile +++ b/makefile @@ -223,6 +223,7 @@ build-lflags = -lz -lpthread -ldl lflags = $(common-lflags) -lpthread -ldl +soname-flag = -Wl,-soname -Wl,$(so-prefix)jvm$(so-suffix) version-script-flag = -Wl,--version-script=openjdk.ld build-system = posix @@ -1160,7 +1161,8 @@ ifdef msvc -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest $(mt) -manifest $(@).manifest -outputresource:"$(@);2" else - $(ld) $(^) $(version-script-flag) $(shared) $(lflags) $(bootimage-lflags) \ + $(ld) $(^) $(version-script-flag) $(soname-flag) \ + $(shared) $(lflags) $(bootimage-lflags) \ -o $(@) endif $(strip) $(strip-all) $(@) From db0c14d74238bc9fb48d88514acb525a268467e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xerxes=20R=C3=A5nby?= Date: Wed, 5 Sep 2012 14:31:30 +0200 Subject: [PATCH 011/378] Set java.vm.info based on makefile info= and set java.vm.version based on makefile version= in order to display relevant OpenJDK -version information. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matthias Klose Signed-off-by: Xerxes Rånby --- makefile | 1 + src/classpath-openjdk.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/makefile b/makefile index 7782850780..2dceb23b93 100755 --- a/makefile +++ b/makefile @@ -194,6 +194,7 @@ target-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) common-cflags = $(warnings) -fno-rtti -fno-exceptions -I$(classpath-src) \ "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) $(classpath-cflags) \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ + -DAVIAN_INFO="\"$(info)\"" \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 97c5a3372e..003b2ef1e2 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3006,6 +3006,12 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) "Avian Contributors"); local::setProperty(t, method, *properties, "java.vm.name","Avian"); +#ifdef AVIAN_VERSION + local::setProperty(t, method, *properties, "java.vm.version",AVIAN_VERSION); +#endif +#ifdef AVIAN_INFO + local::setProperty(t, method, *properties, "java.vm.info",AVIAN_INFO); +#endif local::setProperty (t, method, *properties, "java.home", From eee2ce27e412ebb2a098a3c24d9f7920f78ff00d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 7 Sep 2012 08:47:49 -0600 Subject: [PATCH 012/378] ignore DetachCurrentThread calls for the main thread My earlier commit to allow detaching the main thread (1f1c3c4) seems to have caused subtle stability problems (e.g. https://groups.google.com/group/avian/msg/d2c797c0dcf925c3), so for now we'll just ignore that operation, which leaks a bit of memory but should be harmless otherwise. --- src/jnienv.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 65fb57ab1e..f6eeb8c86f 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -45,17 +45,23 @@ DetachCurrentThread(Machine* m) { Thread* t = static_cast(m->localThread->get()); if (t) { - m->localThread->set(0); + // todo: detaching the root thread seems to cause stability + // problems which I haven't yet had a chance to investigate + // thoroughly. Meanwhile, we just ignore requests to detach it, + // which leaks a bit of memory but should be harmless otherwise. + if (m->rootThread != t) { + m->localThread->set(0); - ACQUIRE_RAW(t, t->m->stateLock); + ACQUIRE_RAW(t, t->m->stateLock); - enter(t, Thread::ActiveState); + enter(t, Thread::ActiveState); - threadPeer(t, t->javaThread) = 0; + threadPeer(t, t->javaThread) = 0; - enter(t, Thread::ZombieState); + enter(t, Thread::ZombieState); - t->state = Thread::JoinedState; + t->state = Thread::JoinedState; + } return 0; } else { From 90fa4c9b69c077e0be4320fea1b02ec4fef669ac Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 7 Sep 2012 19:05:05 -0600 Subject: [PATCH 013/378] add JNI_GetCreatedJavaVMs stub Recent versions of IcedTea will not run unless libjvm.so exports this symbol. The quick fix is to provide a stub which just always returns -1 to indicate an error. I'll leave a proper implementation for when we need to support an app that actually uses this function. --- src/jnienv.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index f6eeb8c86f..b9e1ea00a4 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3626,6 +3626,13 @@ JNI_GetDefaultJavaVMInitArgs(void*) return 0; } +extern "C" JNIEXPORT jint JNICALL +JNI_GetCreatedJavaVMs(Machine**, jsize, jsize*) +{ + // todo + return -1; +} + extern "C" JNIEXPORT jint JNICALL JNI_CreateJavaVM(Machine** m, Thread** t, void* args) { From c918cbced149a34a1d0ab78922ac21c0d04f80b8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 11 Sep 2012 19:21:51 -0600 Subject: [PATCH 014/378] fix sun.misc.Unsafe.getLongVolatile for static fields on 32-bit platforms The existing code did not handle static field lookups for synchronization on 32-bit systems, which is necessary because such systems generally don't support atomic operations on 64-bit values. --- src/classpath-openjdk.cpp | 25 +++++++++++++++++++++---- src/machine.cpp | 7 +++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 003b2ef1e2..da31d9b687 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2292,11 +2292,28 @@ fieldForOffsetInClass(Thread* t, object c, unsigned offset) object fieldForOffset(Thread* t, object o, unsigned offset) { - object field = fieldForOffsetInClass(t, objectClass(t, o), offset); - if (field) { - return field; - } else { + object c = objectClass(t, o); + if (classVmFlags(t, c) & SingletonFlag) { + c = singletonObject(t, o, 0); + object table = classFieldTable(t, c); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + object field = objectArrayBody(t, table, i); + if ((fieldFlags(t, field) & ACC_STATIC) + and fieldOffset(t, field) == offset) + { + return field; + } + } + } abort(t); + } else { + object field = fieldForOffsetInClass(t, c, offset); + if (field) { + return field; + } else { + abort(t); + } } } diff --git a/src/machine.cpp b/src/machine.cpp index 790c9fa1aa..6ae39f7b30 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1128,7 +1128,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) unsigned count = s.read2(); if (count) { - unsigned staticOffset = BytesPerWord * 2; + unsigned staticOffset = BytesPerWord * 3; unsigned staticCount = 0; object fieldTable = makeArray(t, count); @@ -1242,7 +1242,10 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) uint8_t* body = reinterpret_cast (&singletonBody(t, staticTable, 0)); - for (unsigned i = 0, offset = 0; i < staticCount; ++i) { + memcpy(body, &class_, BytesPerWord); + singletonMarkObject(t, staticTable, 0); + + for (unsigned i = 0, offset = BytesPerWord; i < staticCount; ++i) { unsigned size = fieldSize(t, RUNTIME_ARRAY_BODY(staticTypes)[i]); while (offset % size) { ++ offset; From 2190d0e99acd565df1244212f7b33909b604aa3a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 12 Sep 2012 15:25:17 -0600 Subject: [PATCH 015/378] fix reads of out-of-bounds values in tokenizer.h --- src/tokenizer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tokenizer.h b/src/tokenizer.h index 23b7788232..5699227c74 100644 --- a/src/tokenizer.h +++ b/src/tokenizer.h @@ -32,13 +32,13 @@ class Tokenizer { { } bool hasMore() { - while (*s == delimiter and s != limit) ++s; - return *s != 0 and s != limit; + while (s != limit and *s == delimiter) ++s; + return s != limit and *s != 0; } Token next() { const char* p = s; - while (*s and *s != delimiter and s != limit) ++s; + while (s != limit and *s and *s != delimiter) ++s; return Token(p, s - p); } From 3a5abaf58a9f8b3210fd4848d506eabc972f29ba Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 12 Sep 2012 17:23:19 -0600 Subject: [PATCH 016/378] fix incorrect reporting of fixie collection status in heap.cpp (part 2) My earlier fix (f8e8609) was almost -- but not quite -- sufficient. It asked the heap to mark the dead fixies too early, so some of them were marked dead even though they ultimately survived, causing us to clear weak JNI references when we shouldn't. --- src/machine.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 6ae39f7b30..24fd6c0a8e 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -273,6 +273,8 @@ killZombies(Thread* t, Thread* o) unsigned footprint(Thread* t) { + expect(t, t->criticalLevel == 0); + unsigned n = t->heapOffset + t->heapIndex + t->backupHeapIndex; for (Thread* c = t->child; c; c = c->peer) { @@ -592,6 +594,8 @@ postVisit(Thread* t, Heap::Visitor* v) m->tenuredWeakReferences = firstNewTenuredWeakReference; } + m->heap->postVisit(); + for (Reference* r = m->jniReferences; r; r = r->next) { if (r->weak) { if (m->heap->status(r->target) == Heap::Unreachable) { @@ -2693,8 +2697,6 @@ class HeapClient: public Heap::Client { virtual void visitRoots(Heap::Visitor* v) { ::visitRoots(m, v); - m->heap->postVisit(); - postVisit(m->rootThread, v); } From 2d9bbec214280af9d95ec5c16141cba3ace5002f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 14 Sep 2012 11:40:26 -0600 Subject: [PATCH 017/378] fix a couple of ByteBuffer regressions The compact() and put(ByteBuffer) methods regressed as of the recent refactoring to support direct byte buffers. --- classpath/java/nio/ArrayByteBuffer.java | 11 ++++++++--- classpath/java/nio/ByteBuffer.java | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/classpath/java/nio/ArrayByteBuffer.java b/classpath/java/nio/ArrayByteBuffer.java index 2f2e7d5024..336945c1bb 100644 --- a/classpath/java/nio/ArrayByteBuffer.java +++ b/classpath/java/nio/ArrayByteBuffer.java @@ -31,6 +31,10 @@ class ArrayByteBuffer extends ByteBuffer { return b; } + public boolean hasArray() { + return true; + } + public byte[] array() { return array; } @@ -49,9 +53,10 @@ class ArrayByteBuffer extends ByteBuffer { } public ByteBuffer put(ByteBuffer src) { - checkPut(position, src.remaining()); - src.get(array, arrayOffset + position, src.remaining()); - position += src.remaining(); + int length = src.remaining(); + checkPut(position, length); + src.get(array, arrayOffset + position, length); + position += length; return this; } diff --git a/classpath/java/nio/ByteBuffer.java b/classpath/java/nio/ByteBuffer.java index 47eec8c1dc..3a6548d2b3 100644 --- a/classpath/java/nio/ByteBuffer.java +++ b/classpath/java/nio/ByteBuffer.java @@ -53,13 +53,15 @@ public abstract class ByteBuffer } public ByteBuffer compact() { + int remaining = remaining(); + if (position != 0) { ByteBuffer b = slice(); position = 0; put(b); } - position = remaining(); + position = remaining; limit(capacity()); return this; From e20c5cd9c6f1f103aae88758f44575ab65795599 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 22 Sep 2012 20:22:33 -0600 Subject: [PATCH 018/378] fix a couple of OpenJDK reflection bugs We weren't wrapping exceptions thrown by invoked methods in InvocationTargetExceptions in JVM_InvokeMethod or JVM_NewInstanceFromConstructor. Also, JVM_GetCallerClass is supposed to ignore Method.invoke frames when walking the stack. --- src/classpath-openjdk.cpp | 18 +++++++++++++++++- src/machine.cpp | 21 +++++++++++++++++---- src/machine.h | 2 +- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index da31d9b687..47b6b12d8a 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3802,7 +3802,7 @@ EXPORT(JVM_GetCallerClass)(Thread* t, int target) { ENTER(t, Thread::ActiveState); - object method = getCaller(t, target); + object method = getCaller(t, target, true); return method ? makeLocalReference (t, getJClass(t, methodClass(t, method))) : 0; @@ -4568,6 +4568,14 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) unsigned returnCode = methodReturnCode(t, vmMethod); + THREAD_RESOURCE0(t, { + if (t->exception) { + object exception = t->exception; + t->exception = makeThrowable + (t, Machine::InvocationTargetExceptionType, 0, 0, exception); + } + }); + object result; if (args) { result = t->m->processor->invokeArray @@ -4606,6 +4614,14 @@ jvmNewInstanceFromConstructor(Thread* t, uintptr_t* arguments) (t, jclassVmClass(t, jconstructorClazz(t, *constructor))), jconstructorSlot(t, *constructor)); + THREAD_RESOURCE0(t, { + if (t->exception) { + object exception = t->exception; + t->exception = makeThrowable + (t, Machine::InvocationTargetExceptionType, 0, 0, exception); + } + }); + if (args) { t->m->processor->invokeArray(t, method, instance, *args); } else { diff --git a/src/machine.cpp b/src/machine.cpp index 24fd6c0a8e..4f01f204da 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -4839,15 +4839,27 @@ parseUtf8(Thread* t, const char* data, unsigned length) } object -getCaller(Thread* t, unsigned target) +getCaller(Thread* t, unsigned target, bool skipMethodInvoke) { class Visitor: public Processor::StackVisitor { public: - Visitor(Thread* t, unsigned target): - t(t), method(0), count(0), target(target) + Visitor(Thread* t, unsigned target, bool skipMethodInvoke): + t(t), method(0), count(0), target(target), + skipMethodInvoke(skipMethodInvoke) { } virtual bool visit(Processor::StackWalker* walker) { + if (skipMethodInvoke + and methodClass + (t, walker->method()) == type(t, Machine::JmethodType) + and strcmp + (&byteArrayBody(t, methodName(t, walker->method()), 0), + reinterpret_cast("invoke")) + == 0) + { + return true; + } + if (count == target) { method = walker->method(); return false; @@ -4861,7 +4873,8 @@ getCaller(Thread* t, unsigned target) object method; unsigned count; unsigned target; - } v(t, target); + bool skipMethodInvoke; + } v(t, target, skipMethodInvoke); t->m->processor->walkStack(t, &v); diff --git a/src/machine.h b/src/machine.h index a9cba4024e..35d07a78e9 100644 --- a/src/machine.h +++ b/src/machine.h @@ -3801,7 +3801,7 @@ populateMultiArray(Thread* t, object array, int32_t* counts, unsigned index, unsigned dimensions); object -getCaller(Thread* t, unsigned target); +getCaller(Thread* t, unsigned target, bool skipMethodInvoke = false); object defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length); From 369320191176c132c0b1be8e62da25fa9d75a1f7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 24 Sep 2012 17:43:34 -0600 Subject: [PATCH 019/378] make JVM_GetSystemPackage a bit smarter The original stub implementation just echoed back its argument, but that confused URLClassLoader when dealing with sealed JARs -- returning a non-null value for a non-system class from JVM_GetSystemPackage made URLClassloader think it had already loaded a class from a package which was supposed to be sealed, resulting in SecurityExceptions which ultimately triggered NoClassDefFoundErrors. The solution is to only return non-null values for actual system classes. --- src/classpath-avian.cpp | 6 ++++ src/classpath-openjdk.cpp | 74 +++++++++++++++++++++++++++++++++++++-- src/machine.cpp | 2 ++ src/machine.h | 4 +++ 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 5e68d2ed14..ddef6c36de 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -88,6 +88,12 @@ class MyClasspath : public Classpath { return AVIAN_CLASSPATH; } + virtual void + updatePackageMap(Thread*, object) + { + // ignore + } + virtual void dispose() { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 47b6b12d8a..dd772f2eeb 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -638,6 +638,47 @@ class MyClasspath : public Classpath { return classpath; } + virtual void + updatePackageMap(Thread* t, object class_) + { + PROTECT(t, class_); + + if (root(t, Machine::PackageMap) == 0) { + setRoot(t, Machine::PackageMap, makeHashMap(t, 0, 0)); + } + + object className = vm::className(t, class_); + if ('[' != byteArrayBody(t, className, 0)) { + THREAD_RUNTIME_ARRAY + (t, char, packageName, byteArrayLength(t, className)); + + char* s = reinterpret_cast(&byteArrayBody(t, className, 0)); + char* p = strrchr(s, '/'); + + if (p) { + int length = (p - s) + 1; + memcpy(RUNTIME_ARRAY_BODY(packageName), + &byteArrayBody(t, className, 0), + length); + RUNTIME_ARRAY_BODY(packageName)[length] = 0; + + object key = vm::makeByteArray(t, "%s", packageName); + + hashMapRemove + (t, root(t, Machine::PackageMap), key, byteArrayHash, + byteArrayEqual); + + object source = classSource(t, class_); + if (source == 0) { + source = vm::makeByteArray(t, "avian-dummy-package-source"); + } + + hashMapInsert + (t, root(t, Machine::PackageMap), key, source, byteArrayHash); + } + } + } + virtual void dispose() { @@ -3531,10 +3572,37 @@ EXPORT(JVM_ClassDepth)(Thread*, jstring) { abort(); } extern "C" JNIEXPORT jint JNICALL EXPORT(JVM_ClassLoaderDepth)(Thread*) { abort(); } -extern "C" JNIEXPORT jstring JNICALL -EXPORT(JVM_GetSystemPackage)(Thread*, jstring s) +uint64_t +jvmGetSystemPackage(Thread* t, uintptr_t* arguments) { - return s; + jstring s = reinterpret_cast(arguments[0]); + + ACQUIRE(t, t->m->classLock); + + THREAD_RUNTIME_ARRAY(t, char, chars, stringLength(t, *s) + 1); + stringChars(t, *s, RUNTIME_ARRAY_BODY(chars)); + + object key = makeByteArray(t, RUNTIME_ARRAY_BODY(chars)); + + object array = hashMapFind + (t, root(t, Machine::PackageMap), key, byteArrayHash, byteArrayEqual); + + if (array) { + return reinterpret_cast + (makeLocalReference + (t, t->m->classpath->makeString + (t, array, 0, byteArrayLength(t, array)))); + } else { + return 0; + } +} + +extern "C" JNIEXPORT jstring JNICALL +EXPORT(JVM_GetSystemPackage)(Thread* t, jstring s) +{ + uintptr_t arguments[] = { reinterpret_cast(s) }; + + return reinterpret_cast(run(t, jvmGetSystemPackage, arguments)); } uint64_t diff --git a/src/machine.cpp b/src/machine.cpp index 4f01f204da..09a314b9f2 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -4099,6 +4099,8 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_, if (class_) { hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash); + + t->m->classpath->updatePackageMap(t, class_); } else if (throw_) { throwNew(t, throwType, "%s", &byteArrayBody(t, spec, 0)); } diff --git a/src/machine.h b/src/machine.h index 35d07a78e9..52233cab3c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1206,6 +1206,7 @@ class Machine { BootLoader, AppLoader, BootstrapClassMap, + PackageMap, FindLoadedClassMethod, LoadClassMethod, MonitorMap, @@ -1550,6 +1551,9 @@ class Classpath { virtual const char* bootClasspath() = 0; + virtual void + updatePackageMap(Thread* t, object class_) = 0; + virtual void dispose() = 0; }; From 23ea8f7d76a3b9573b2041eac0faf77daeb5642d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xerxes=20R=C3=A5nby?= Date: Tue, 25 Sep 2012 15:54:32 +0200 Subject: [PATCH 020/378] Fix missing armv4 blx and bkpt compile errors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xerxes Rånby --- src/arm.S | 10 ++++++++++ src/compile-arm.S | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/src/arm.S b/src/arm.S index 01d0839079..9958fc6610 100644 --- a/src/arm.S +++ b/src/arm.S @@ -62,7 +62,12 @@ LOCAL(loop): vldmia r7, {d0-d7} #endif +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) + mov lr, pc + bx r4 +#else blx r4 // call function +#endif add sp, sp, r5 // deallocate stack #if defined(__VFP_FP__) && (! defined(__SOFTFP__)) && (! defined(__QNX__)) @@ -108,7 +113,12 @@ GLOBAL(vmRun): mov r12, r0 ldr r0, [r2, #CHECKPOINT_THREAD] +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) + mov lr, pc + bx r12 +#else blx r12 +#endif .globl GLOBAL(vmRun_returnAddress) .align 2 diff --git a/src/compile-arm.S b/src/compile-arm.S index 427378c1f8..99eb6c07a8 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -75,7 +75,12 @@ LOCAL(vmInvoke_argumentTest): mov r8, r0 // load and call function address +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) + mov lr, pc + bx r1 +#else blx r1 +#endif .globl GLOBAL(vmInvoke_returnAddress) .align 2 @@ -228,5 +233,9 @@ LOCAL(vmJumpAndInvoke_getAddress_word): #else // not AVIAN_CONTINUATIONS // vmJumpAndInvoke should only be called when continuations are // enabled +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) + // TODO: armv4 do not have bkpt +#else bkpt +#endif #endif // not AVIAN_CONTINUATIONS From 1d4c9d32fb3434c300b9833cdaef040712945292 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 28 Sep 2012 15:03:14 -0600 Subject: [PATCH 021/378] return null from JNIEnv::GetSuperclass for interfaces per spec --- src/classpath-openjdk.cpp | 11 +++++++---- src/jnienv.cpp | 14 ++++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index dd772f2eeb..938368b0d9 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2378,10 +2378,13 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Class_getSuperclass (Thread* t, object, uintptr_t* arguments) { - object super = classSuper - (t, jclassVmClass(t, reinterpret_cast(arguments[0]))); - - return super ? reinterpret_cast(getJClass(t, super)) : 0; + object class_ = jclassVmClass(t, reinterpret_cast(arguments[0])); + if (classFlags(t, class_) & ACC_INTERFACE) { + return 0; + } else { + object super = classSuper(t, class_); + return super ? reinterpret_cast(getJClass(t, super)) : 0; + } } extern "C" JNIEXPORT void diff --git a/src/jnienv.cpp b/src/jnienv.cpp index b9e1ea00a4..9e1d7e9edf 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -431,12 +431,14 @@ GetObjectClass(Thread* t, jobject o) uint64_t getSuperclass(Thread* t, uintptr_t* arguments) { - jclass c = reinterpret_cast(arguments[0]); - - object super = classSuper(t, jclassVmClass(t, *c)); - - return super ? reinterpret_cast - (makeLocalReference(t, getJClass(t, super))) : 0; + object class_ = jclassVmClass(t, *reinterpret_cast(arguments[0])); + if (classFlags(t, class_) & ACC_INTERFACE) { + return 0; + } else { + object super = classSuper(t, class_); + return super ? reinterpret_cast + (makeLocalReference(t, getJClass(t, super))) : 0; + } } jclass JNICALL From 2a15201b185a2402c69e7e0b558f0d4175f4bd25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xerxes=20R=C3=A5nby?= Date: Mon, 1 Oct 2012 13:39:18 +0200 Subject: [PATCH 022/378] gcc define __ARM_PCS_VFP for -mfloat-abi=hard, use it to detect armhf builds. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xerxes Rånby --- src/arm.S | 4 ++-- src/arm.cpp | 12 +++++++++++- src/arm.h | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/arm.S b/src/arm.S index 9958fc6610..8f19b59171 100644 --- a/src/arm.S +++ b/src/arm.S @@ -57,7 +57,7 @@ LOCAL(loop): // setup argument registers if necessary tst r6, r6 ldmneia r6, {r0-r3} -#if defined(__VFP_FP__) && (! defined(__SOFTFP__)) && (! defined(__QNX__)) +#if defined(__ARM_PCS_VFP) // and VFP registers vldmia r7, {d0-d7} #endif @@ -70,7 +70,7 @@ LOCAL(loop): #endif add sp, sp, r5 // deallocate stack -#if defined(__VFP_FP__) && (! defined(__SOFTFP__)) && (! defined(__QNX__)) +#if defined(__ARM_PCS_VFP) cmp r8,#FLOAT_TYPE bne LOCAL(double) fmrs r0,s0 diff --git a/src/arm.cpp b/src/arm.cpp index 97f9455495..74f7da63bb 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -245,7 +245,17 @@ inline int bpl(int offset) { return SETCOND(b(offset), PL); } inline int fmstat() { return fmrx(15, FPSCR); } // HARDWARE FLAGS bool vfpSupported() { - return true; // TODO + // TODO: Use at runtime detection +#if defined(__ARM_PCS_VFP) + // armhf + return true; +#else + // armel + // TODO: allow VFP use for -mfloat-abi=softfp armel builds. + // GCC -mfloat-abi=softfp flag allows use of VFP while remaining compatible + // with soft-float code. + return false; +#endif } } diff --git a/src/arm.h b/src/arm.h index 8ae057d610..15299ec762 100644 --- a/src/arm.h +++ b/src/arm.h @@ -163,7 +163,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, for (unsigned ati = 0; ati < argumentCount; ++ ati) { switch (argumentTypes[ati]) { case DOUBLE_TYPE: -#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) && !defined(__QNX__) +#if defined(__ARM_PCS_VFP) { if (vfpIndex + Alignment <= VfpCount) { if (vfpIndex % Alignment) { From ab5ec510bf5531482230ba6e9e17a9af7e9caeb5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 3 Oct 2012 08:16:41 -0600 Subject: [PATCH 023/378] handle zero length arrays properly in JNIEnv::NewString --- src/jnienv.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 9e1d7e9edf..52da9559f7 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -241,9 +241,8 @@ newString(Thread* t, uintptr_t* arguments) const jchar* chars = reinterpret_cast(arguments[0]); jsize size = arguments[1]; - object a = 0; + object a = makeCharArray(t, size); if (size) { - a = makeCharArray(t, size); memcpy(&charArrayBody(t, a, 0), chars, size * sizeof(jchar)); } From 1ce012aa68c3c6045a42f34ae474121738d7ad13 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 3 Oct 2012 09:43:51 -0600 Subject: [PATCH 024/378] fix abort in classpath-openjdk.cpp due to buffer overflow This addresses the case where -Djava.home=. https://github.com/ReadyTalk/avian/issues/15 --- src/classpath-openjdk.cpp | 78 ++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 938368b0d9..bb505051d9 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -349,48 +349,66 @@ clearInterrupted(Thread*); class MyClasspath : public Classpath { public: - static const unsigned BufferSize = 1024; - MyClasspath(System* s, Allocator* allocator, const char* javaHome, const char* embedPrefix): allocator(allocator), ranNetOnLoad(0), ranManagementOnLoad(0) { class StringBuilder { public: - StringBuilder(System* s, char* pointer, unsigned remaining): - s(s), pointer(pointer), remaining(remaining) + StringBuilder(System* s, Allocator* allocator): + s(s), + allocator(allocator), + bufferSize(1024), + buffer(static_cast(allocator->allocate(bufferSize))), + offset(0) { } + void ensure(unsigned capacity) { + if (capacity > bufferSize) { + unsigned size = max(bufferSize * 2, capacity); + char* b = static_cast(allocator->allocate(size)); + + if (offset) { + memcpy(b, buffer, offset); + } + + allocator->free(buffer, bufferSize); + + buffer = b; + bufferSize = size; + } + } + void append(const char* append) { unsigned length = strlen(append); - expect(s, remaining > length); + ensure(offset + length + 1); - strncpy(pointer, append, remaining); + strncpy(buffer + offset, append, length + 1); - remaining -= length; - pointer += length; + offset += length; } void append(char c) { - assert(s, remaining > 1); + ensure(2); - pointer[0] = c; - pointer[1] = 0; + buffer[offset] = c; + buffer[offset + 1] = 0; - -- remaining; - ++ pointer; + ++ offset; } System* s; - char* pointer; - unsigned remaining; - } sb(s, buffer, BufferSize); + Allocator* allocator; + unsigned bufferSize; + char* buffer; + unsigned offset; + } sb(s, allocator); - this->javaHome = sb.pointer; + unsigned javaHomeOffset = sb.offset; sb.append(javaHome); sb.append('\0'); - this->classpath = sb.pointer; + unsigned classpathOffset = sb.offset; sb.append(AVIAN_CLASSPATH); sb.append(s->pathSeparator()); sb.append(javaHome); @@ -409,7 +427,7 @@ class MyClasspath : public Classpath { sb.append("/lib/resources.jar"); sb.append('\0'); - this->libraryPath = sb.pointer; + unsigned libraryPathOffset = sb.offset; sb.append(javaHome); #ifdef PLATFORM_WINDOWS sb.append("/bin"); @@ -424,16 +442,24 @@ class MyClasspath : public Classpath { sb.append("/lib/i386"); #endif sb.append('\0'); - - this->tzMappings = sb.pointer; + + unsigned tzMappingsOffset = sb.offset; sb.append(javaHome); sb.append("/lib/tzmappings"); - this->tzMappingsLength = sb.pointer - tzMappings; + this->tzMappingsLength = sb.offset - tzMappingsOffset; sb.append('\0'); - this->embedPrefix = sb.pointer; + unsigned embedPrefixOffset = sb.offset; sb.append(embedPrefix); - this->embedPrefixLength = sb.pointer - this->embedPrefix; + this->embedPrefixLength = sb.offset - embedPrefixOffset; + + this->javaHome = sb.buffer + javaHomeOffset; + this->classpath = sb.buffer + classpathOffset; + this->libraryPath = sb.buffer + libraryPathOffset; + this->tzMappings = sb.buffer + tzMappingsOffset; + this->embedPrefix = sb.buffer + embedPrefixOffset; + this->buffer = sb.buffer; + this->bufferSize = sb.bufferSize; } virtual object @@ -682,6 +708,7 @@ class MyClasspath : public Classpath { virtual void dispose() { + allocator->free(buffer, bufferSize); allocator->free(this, sizeof(*this)); } @@ -691,6 +718,8 @@ class MyClasspath : public Classpath { const char* libraryPath; const char* tzMappings; const char* embedPrefix; + char* buffer; + unsigned bufferSize; unsigned tzMappingsLength; unsigned embedPrefixLength; unsigned filePathField; @@ -705,7 +734,6 @@ class MyClasspath : public Classpath { unsigned zipEntryMethodField; bool ranNetOnLoad; bool ranManagementOnLoad; - char buffer[BufferSize]; JmmInterface jmmInterface; }; From 16c526b775fa38b7877ccfc9ed6be966cc8bc060 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 3 Oct 2012 13:36:51 -0600 Subject: [PATCH 025/378] fix OS X 10.8 and iOS 6.0 builds This also adds support for Clang ARM builds, which involved removing unused functions from arm.cpp to avoid link-time warnings. --- makefile | 16 +++++-- src/arm.S | 4 ++ src/arm.cpp | 108 +--------------------------------------------- src/compile-arm.S | 26 ++++++++--- 4 files changed, 37 insertions(+), 117 deletions(-) diff --git a/makefile b/makefile index 735ab6f89d..6b611ebd2c 100755 --- a/makefile +++ b/makefile @@ -291,8 +291,13 @@ ifeq ($(arch),arm) ifneq ($(arch),$(build-arch)) ifeq ($(platform),darwin) ios-bin = $(developer-dir)/Platforms/iPhoneOS.platform/Developer/usr/bin - cxx = $(ios-bin)/g++ - cc = $(ios-bin)/gcc + ifeq ($(use-clang),true) + cxx = clang -std=c++11 + cc = clang + else + cxx = $(ios-bin)/g++ + cc = $(ios-bin)/gcc + endif ar = $(ios-bin)/ar ranlib = $(ios-bin)/ranlib strip = $(ios-bin)/strip @@ -312,8 +317,10 @@ endif ifeq ($(build-platform),darwin) build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src) - cflags += -I/System/Library/Frameworks/JavaVM.framework/Headers/ + cflags += -I/System/Library/Frameworks/JavaVM.framework/Headers/ \ + -Wno-deprecated-declarations build-lflags += -framework CoreFoundation + soname-flag = endif ifeq ($(platform),qnx) @@ -389,7 +396,8 @@ ifeq ($(platform),darwin) ifeq ($(arch),arm) ios-version := \ - $(shell if test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ + $(shell if test -d $(sdk-dir)/iPhoneOS6.0.sdk; then echo 6.0; \ + elif test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ elif test -d $(sdk-dir)/iPhoneOS4.2.sdk; then echo 4.2; \ diff --git a/src/arm.S b/src/arm.S index 8f19b59171..658df92200 100644 --- a/src/arm.S +++ b/src/arm.S @@ -56,7 +56,11 @@ LOCAL(loop): // setup argument registers if necessary tst r6, r6 +#ifdef __clang__ + ldmiane r6, {r0-r3} +#else ldmneia r6, {r0-r3} +#endif #if defined(__ARM_PCS_VFP) // and VFP registers vldmia r7, {d0-d7} diff --git a/src/arm.cpp b/src/arm.cpp index 74f7da63bb..ae657e30d5 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -49,12 +49,6 @@ inline int XFER2(int cond, int P, int U, int W, int L, int Rn, int Rd, int S, in { return cond<<28 | P<<24 | U<<23 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | 1<<7 | S<<6 | H<<5 | 1<<4 | Rm; } inline int XFER2I(int cond, int P, int U, int W, int L, int Rn, int Rd, int offsetH, int S, int H, int offsetL) { return cond<<28 | P<<24 | U<<23 | 1<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | offsetH<<8 | 1<<7 | S<<6 | H<<5 | 1<<4 | (offsetL&0xf); } -inline int BLOCKXFER(int cond, int P, int U, int S, int W, int L, int Rn, int rlist) -{ return cond<<28 | 4<<25 | P<<24 | U<<23 | S<<22 | W<<21 | L<<20 | Rn<<16 | rlist; } -inline int SWI(int cond, int imm) -{ return cond<<28 | 0x0f<<24 | (imm&0xffffff); } -inline int SWAP(int cond, int B, int Rn, int Rd, int Rm) -{ return cond<<28 | 1<<24 | B<<22 | Rn<<16 | Rd<<12 | 9<<4 | Rm; } inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm) { return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; } inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) // offset is in words, not bytes @@ -71,41 +65,29 @@ inline int b(int offset) { return BRANCH(AL, 0, offset); } inline int bl(int offset) { return BRANCH(AL, 1, offset); } inline int bx(int Rm) { return BRANCHX(AL, 0, Rm); } inline int blx(int Rm) { return BRANCHX(AL, 1, Rm); } -inline int swi(int imm) { return SWI(AL, imm); } inline int and_(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm); } inline int eor(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm); } -inline int sub(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x2, 0, Rn, Rd, shift, Sh, Rm); } inline int rsb(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm); } inline int add(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm); } inline int adc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm); } -inline int sbc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x6, 0, Rn, Rd, shift, Sh, Rm); } inline int rsc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm); } -inline int tst(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x8, 1, Rn, 0, shift, Sh, Rm); } -inline int teq(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x9, 1, Rn, 0, shift, Sh, Rm); } inline int cmp(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xa, 1, Rn, 0, shift, Sh, Rm); } -inline int cmn(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xb, 1, Rn, 0, shift, Sh, Rm); } inline int orr(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm); } inline int mov(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xd, 0, 0, Rd, shift, Sh, Rm); } -inline int bic(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xe, 0, Rn, Rd, shift, Sh, Rm); } inline int mvn(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xf, 0, 0, Rd, shift, Sh, Rm); } inline int andi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm); } -inline int eori(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x1, 0, Rn, Rd, rot, imm); } inline int subi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm); } inline int rsbi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm); } inline int addi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm); } inline int adci(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm); } inline int bici(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm); } inline int cmpi(int Rn, int imm, int rot=0) { return DATAI(AL, 0xa, 1, Rn, 0, rot, imm); } -inline int orri(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0xc, 0, Rn, Rd, rot, imm); } inline int movi(int Rd, int imm, int rot=0) { return DATAI(AL, 0xd, 0, 0, Rd, rot, imm); } inline int orrsh(int Rd, int Rn, int Rm, int Rs, int Sh) { return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm); } inline int movsh(int Rd, int Rm, int Rs, int Sh) { return DATAS(AL, 0xd, 0, 0, Rd, Rs, Sh, Rm); } inline int mul(int Rd, int Rm, int Rs) { return MULTIPLY(AL, 0, 0, Rd, 0, Rs, Rm); } inline int mla(int Rd, int Rm, int Rs, int Rn) { return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm); } inline int umull(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm); } -inline int umlal(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 5, 0, RdHi, RdLo, Rs, Rm); } -inline int smull(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 6, 0, RdHi, RdLo, Rs, Rm); } -inline int smlal(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 7, 0, RdHi, RdLo, Rs, Rm); } inline int ldr(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm); } inline int ldri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm)); } inline int ldrb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm); } @@ -122,39 +104,19 @@ inline int ldrsh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, inline int ldrshi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 1, abs(imm)&0xf); } inline int ldrsb(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm); } inline int ldrsbi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 0, abs(imm)&0xf); } -inline int pop(int Rd) { return XFERI(AL, 0, 1, 0, 0, 1, 13, Rd, 4); } -inline int ldmfd(int Rn, int rlist) { return BLOCKXFER(AL, 0, 1, 0, 1, 1, Rn, rlist); } -inline int stmfd(int Rn, int rlist) { return BLOCKXFER(AL, 1, 0, 0, 1, 0, Rn, rlist); } -inline int swp(int Rd, int Rm, int Rn) { return SWAP(AL, 0, Rn, Rd, Rm); } -inline int swpb(int Rd, int Rm, int Rn) { return SWAP(AL, 1, Rn, Rd, Rm); } // breakpoint instruction, this really has its own instruction format inline int bkpt(int16_t immed) { return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf); } // COPROCESSOR INSTRUCTIONS -inline int cdp(int coproc, int opcode_1, int CRd, int CRn, int CRm, int opcode_2) { return COOP(AL, opcode_1, CRn, CRd, coproc, opcode_2, CRm); } inline int mcr(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); } inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); } inline int mrc(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); } inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); } -inline int ldc(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 0, W, 1, Rn, CRd, coproc, offset); } -inline int ldcl(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 1, W, 1, Rn, CRd, coproc, offset); } -inline int stc(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 0, W, 0, Rn, CRd, coproc, offset); } -inline int stcl(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 1, W, 0, Rn, CRd, coproc, offset); } // VFP FLOATING-POINT INSTRUCTIONS -inline int fmacs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } -inline int fnmacs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } -inline int fmscs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|1, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } -inline int fnmscs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|1, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } inline int fmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } -inline int fnmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } -inline int fmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 0, Dm); } -inline int fnmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 2, Dm); } -inline int fmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 0, Dm); } -inline int fnmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 2, Dm); } inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); } -inline int fnmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 2, Dm); } inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } @@ -163,15 +125,8 @@ inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 2|(Sm&1), Sm>>1); } inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 6|(Sm&1), Sm>>1); } inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 2|(Sm&1), Sm>>1); } -inline int fcmpes(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 6|(Sm&1), Sm>>1); } -inline int fcmpzs(int Sd) { return COOP(AL, 0xb|(Sd&1)<<2, 5, Sd>>1, 10, 2, 0); } -inline int fcmpezs(int Sd) { return COOP(AL, 0xb|(Sd&1)<<2, 5, Sd>>1, 10, 6, 0); } inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb, 7, Dd, 10, 6|(Sm&1), Sm>>1); } -inline int fuitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 2|(Sm&1), Sm>>1); } inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 6|(Sm&1), Sm>>1); } -inline int ftouis(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 10, 2|(Sm&1), Sm>>1); } -inline int ftouizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 10, 6|(Sm&1), Sm>>1); } -inline int ftosis(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 2|(Sm&1), Sm>>1); } inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 6|(Sm&1), Sm>>1); } inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); } inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); } @@ -179,24 +134,10 @@ inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); } inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); } // double-precision comparison instructions inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); } -inline int fcmped(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 6, Dm); } -inline int fcmpzd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 2, 0); } -inline int fcmpezd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 6, 0); } // double-precision conversion instructions inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); } -inline int fuitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 2|(Sm&1), Sm>>1); } inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); } -inline int ftouid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 11, 2, Dm); } -inline int ftouizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 11, 6, Dm); } -inline int ftosid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 2, Dm); } inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); } -// these are the multiple load/store analogs for VFP, useless for now -inline int fldms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, count); } -inline int fldmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1); } -inline int fldmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1|1); } -inline int fstms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, count); } -inline int fstmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1); } -inline int fstmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1|1); } // single load/store instructions for both precision types inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); }; inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); }; @@ -205,32 +146,21 @@ inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, // move between GPRs and FPRs inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } -/* move to/from the low/high parts of double-precision registers, - seemingly redundant */ -inline int fmdlr(int Dn, int Rd) { return mcr(11, 0, Rd, Dn, 0); } -inline int fmrdl(int Rd, int Dn) { return mrc(11, 0, Rd, Dn, 0); } -inline int fmdhr(int Dn, int Rd) { return mcr(11, 1, Rd, Dn, 0); } -inline int fmrdh(int Rd, int Dn) { return mrc(11, 1, Rd, Dn, 0); } // move to/from VFP system registers -inline int fmxr(int reg, int Rd) { return mcr(10, 7, Rd, reg, 0); } inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); } // these move around pairs of single-precision registers -inline int fmsrr(int Sm, int Rd, int Rn) { return mcrr(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } -inline int fmrrs(int Rd, int Rn, int Sm) { return mrrc(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); } inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); } // FLAG SETTERS inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); } inline int SETS(int ins) { return ins | 1<<20; } // PSEUDO-INSTRUCTIONS -inline int nop() { return mov(0, 0); } inline int lsl(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSL); } inline int lsli(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSL, imm); } inline int lsr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSR); } inline int lsri(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSR, imm); } inline int asr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, ASR); } inline int asri(int Rd, int Rm, int imm) { return mov(Rd, Rm, ASR, imm); } -inline int ror(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, ROR); } inline int beq(int offset) { return SETCOND(b(offset), EQ); } inline int bne(int offset) { return SETCOND(b(offset), NE); } inline int bls(int offset) { return SETCOND(b(offset), LS); } @@ -262,28 +192,9 @@ bool vfpSupported() { const uint64_t MASK_LO32 = 0xffffffff; const unsigned MASK_LO16 = 0xffff; const unsigned MASK_LO8 = 0xff; -inline unsigned lo32(int64_t i) { return (unsigned)(i&MASK_LO32); } -inline unsigned hi32(int64_t i) { return (unsigned)(i>>32); } -inline unsigned lo16(int64_t i) { return (unsigned)(i&MASK_LO16); } -inline unsigned hi16(int64_t i) { return lo16(i>>16); } inline unsigned lo8(int64_t i) { return (unsigned)(i&MASK_LO8); } -inline unsigned hi8(int64_t i) { return lo8(i>>8); } - -inline int ha16(int32_t i) { - return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; -} -inline int unha16(int32_t high, int32_t low) { - return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; -} - -inline bool isInt8(target_intptr_t v) { return v == static_cast(v); } -inline bool isInt16(target_intptr_t v) { return v == static_cast(v); } -inline bool isInt24(target_intptr_t v) { return v == (v & 0xffffff); } -inline bool isInt32(target_intptr_t v) { return v == static_cast(v); } -inline int carry16(target_intptr_t v) { return static_cast(v) < 0 ? 1 : 0; } inline bool isOfWidth(int64_t i, int size) { return static_cast(i) >> size == 0; } -inline bool isOfWidth(int i, int size) { return static_cast(i) >> size == 0; } const int N_GPRS = 16; const int N_FPRS = 16; @@ -577,7 +488,7 @@ isBranch(TernaryOperation op) return op > FloatMin; } -bool +bool UNUSED isFloatBranch(TernaryOperation op) { return op > JumpIfNotEqual; @@ -1407,23 +1318,6 @@ moveRM(Context* con, unsigned srcSize, Assembler::Register* src, store(con, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); } -void -moveAndUpdateRM(Context* con, unsigned srcSize UNUSED, Assembler::Register* src, - unsigned dstSize UNUSED, Assembler::Memory* dst) -{ - assert(con, srcSize == TargetBytesPerWord); - assert(con, dstSize == TargetBytesPerWord); - - if (dst->index == NoRegister) { - emit(con, stri(src->low, dst->base, dst->offset, dst->offset ? 1 : 0)); - } else { - assert(con, dst->offset == 0); - assert(con, dst->scale == 1); - - emit(con, str(src->low, dst->base, dst->index, 1)); - } -} - void load(Context* con, unsigned srcSize, int base, int offset, int index, unsigned scale, unsigned dstSize, Assembler::Register* dst, diff --git a/src/compile-arm.S b/src/compile-arm.S index 99eb6c07a8..7db96279e9 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -128,11 +128,18 @@ LOCAL(vmInvoke_continuationTest): ble LOCAL(vmInvoke_continuationLoop) ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET] +#ifdef __APPLE__ + movw r11, :lower16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmInvoke_getAddress)+8)) + movt r11, :upper16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmInvoke_getAddress)+8)) +LOCAL(vmInvoke_getAddress): + add r11, pc, r11 +#else // not __APPLE__ ldr r10,LOCAL(vmInvoke_returnAddress_word) ldr r11,LOCAL(vmInvoke_getAddress_word) LOCAL(vmInvoke_getAddress): add r11,pc,r11 ldr r11,[r11,r10] +#endif // not __APPLE__ str r11,[sp,r7] ldr r7,[r5,#CONTINUATION_NEXT] @@ -215,27 +222,34 @@ LOCAL(vmJumpAndInvoke_argumentTest): mov sp,r2 // set return address to vmInvoke_returnAddress +#ifdef __APPLE__ + movw r11, :lower16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmJumpAndInvoke_getAddress)+8)) + movt r11, :upper16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmJumpAndInvoke_getAddress)+8)) +LOCAL(vmJumpAndInvoke_getAddress): + add r11, pc, r11 +#else // not __APPLE__ + ldr r10,LOCAL(vmInvoke_returnAddress_word) ldr r11,LOCAL(vmJumpAndInvoke_getAddress_word) LOCAL(vmJumpAndInvoke_getAddress): add r11,pc,r11 +#endif // not __APPLE__ ldr lr,[r11,r10] bx r1 +#ifndef __APPLE__ LOCAL(vmInvoke_returnAddress_word): .word GLOBAL(vmInvoke_returnAddress)(GOT) LOCAL(vmInvoke_getAddress_word): .word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmInvoke_getAddress)+8) LOCAL(vmJumpAndInvoke_getAddress_word): .word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmJumpAndInvoke_getAddress)+8) +#endif // not __APPLE__ #else // not AVIAN_CONTINUATIONS // vmJumpAndInvoke should only be called when continuations are - // enabled -#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) - // TODO: armv4 do not have bkpt -#else - bkpt -#endif + // enabled, so we force a crash if we reach here: + mov r1,#0 + ldr r1,[r1] #endif // not AVIAN_CONTINUATIONS From c680dd421575d871b93243cc577ed700c75fb38a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 3 Oct 2012 17:01:00 -0600 Subject: [PATCH 026/378] use ldmneia on Clang < 4 and GCC, ldmiane on Clang >= 4 I don't know why this instruction was renamed, but we have to deal with it. --- src/arm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arm.S b/src/arm.S index 658df92200..23e66cefdd 100644 --- a/src/arm.S +++ b/src/arm.S @@ -56,7 +56,7 @@ LOCAL(loop): // setup argument registers if necessary tst r6, r6 -#ifdef __clang__ +#if (defined __APPLE__) && (defined __clang_major__) && (__clang_major__ >= 4) ldmiane r6, {r0-r3} #else ldmneia r6, {r0-r3} From f8d3494b1cd7ca96e28ab6767929d8b5f4a00980 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 5 Oct 2012 10:06:01 -0600 Subject: [PATCH 027/378] clear any weak/soft/phantom references to finalizable objects before queuing If we don't clear these references, we risk finalizing objects which can still be reached by one of the special reference types. It's a bit of a chicken-and-egg problem. We need to visit finalizable objects before visiting weak references, since some of the weak references and/or their targets may become reachable once the finalizable objects are visited. However, that ordering means we have no efficient way of distinguishing between objects which are reachable from one or more normal GC roots and those which are only reachable via the finalization queue. The solution is to clear all weak references to finalizable objects before visiting them. --- src/heap.cpp | 1 + src/machine.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/heap.cpp b/src/heap.cpp index b46faeda01..2dc23e904e 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -1077,6 +1077,7 @@ update3(Context* c, void* o, bool* needsVisit) fprintf(stderr, "mark fixie %p\n", f); } f->marked(true); + f->dead(false); f->move(c, &(c->markedFixies)); } *needsVisit = false; diff --git a/src/machine.cpp b/src/machine.cpp index 09a314b9f2..743f56e41a 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -474,6 +474,25 @@ referenceTargetReachable(Thread* t, Heap::Visitor* v, object* p) } } +bool +isFinalizable(Thread* t, object o) +{ + return t->m->heap->status(o) == Heap::Unreachable + and (classVmFlags + (t, static_cast(t->m->heap->follow(objectClass(t, o)))) + & HasFinalizerFlag); +} + +void +clearTargetIfFinalizable(Thread* t, object r) +{ + if (isFinalizable + (t, static_cast(t->m->heap->follow(jreferenceTarget(t, r))))) + { + jreferenceTarget(t, r) = 0; + } +} + void postVisit(Thread* t, Heap::Visitor* v) { @@ -482,6 +501,30 @@ postVisit(Thread* t, Heap::Visitor* v) assert(t, m->finalizeQueue == 0); + m->heap->postVisit(); + + for (object p = m->weakReferences; p;) { + object r = static_cast(m->heap->follow(p)); + p = jreferenceVmNext(t, r); + clearTargetIfFinalizable(t, r); + } + + if (major) { + for (object p = m->tenuredWeakReferences; p;) { + object r = static_cast(m->heap->follow(p)); + p = jreferenceVmNext(t, r); + clearTargetIfFinalizable(t, r); + } + } + + for (Reference* r = m->jniReferences; r; r = r->next) { + if (r->weak and isFinalizable + (t, static_cast(t->m->heap->follow(r->target)))) + { + r->target = 0; + } + } + object firstNewTenuredFinalizer = 0; object lastNewTenuredFinalizer = 0; @@ -594,8 +637,6 @@ postVisit(Thread* t, Heap::Visitor* v) m->tenuredWeakReferences = firstNewTenuredWeakReference; } - m->heap->postVisit(); - for (Reference* r = m->jniReferences; r; r = r->next) { if (r->weak) { if (m->heap->status(r->target) == Heap::Unreachable) { From 45073db421a5e8566d8a68a693648448865e0371 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 5 Oct 2012 10:56:07 -0600 Subject: [PATCH 028/378] fix Call[Static]MethodA float argument marshalling --- src/interpret.cpp | 2 +- test/JNI.java | 15 +++++++++++++++ test/jni.cpp | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/interpret.cpp b/src/interpret.cpp index da3e6c7853..543363a7d3 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2823,7 +2823,7 @@ pushArguments(Thread* t, object this_, const char* spec, break; case 'F': { - pushFloat(t, arguments[index++].d); + pushFloat(t, arguments[index++].f); } break; default: diff --git a/test/JNI.java b/test/JNI.java index dc24da9b8f..b4e93c0f75 100644 --- a/test/JNI.java +++ b/test/JNI.java @@ -7,6 +7,18 @@ public class JNI { if (! v) throw new RuntimeException(); } + private static float echo(float f) { + return f; + } + + private static native float doEcho(float f); + + private static double echo(double f) { + return f; + } + + private static native double doEcho(double f); + private static native double addDoubles (double a1, double a2, double a3, double a4, double a5, double a6, double a7, double a8, double a9, double a10, double a11, double a12, @@ -40,5 +52,8 @@ public class JNI { (1.0f, 2.0d, 3.0f, 4.0d, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0d, 17.0f, 18.0f, 19.0f, 20.0f) == 210.0d); + + expect(doEcho(42.0f) == 42.0f); + expect(doEcho(42.0d) == 42.0d); } } diff --git a/test/jni.cpp b/test/jni.cpp index 8c1ea91f05..fe174edec9 100644 --- a/test/jni.cpp +++ b/test/jni.cpp @@ -37,6 +37,26 @@ Java_JNI_addMix + a14 + a15 + a16 + a17 + a18 + a19 + a20; } +extern "C" JNIEXPORT jfloat JNICALL +Java_JNI_doEcho__F(JNIEnv* e, jclass c, jfloat f) +{ + jvalue value; + value.f = f; + jvalue array[] = { value }; + return e->CallStaticFloatMethodA + (c, e->GetStaticMethodID(c, "echo", "(F)F"), array); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_JNI_doEcho__D(JNIEnv* e, jclass c, jdouble f) +{ + jvalue value; + value.d = f; + jvalue array[] = { value }; + return e->CallStaticDoubleMethodA + (c, e->GetStaticMethodID(c, "echo", "(D)D"), array); +} + extern "C" JNIEXPORT jobject JNICALL Java_Buffers_allocateNative(JNIEnv* e, jclass, jint capacity) { From 3a452309b36e3fc654d1f5a8a5d36fc20e1abde3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 6 Oct 2012 15:25:12 -0600 Subject: [PATCH 029/378] update static table class reference in updateClassTables Commit c918cbc added this reference to ensure sun.misc.Unsafe.getLongVolatile could be implemented efficiently on 32-bit platforms. However, I neglected to ensure the reference was updated to point to the final class instance instead of the temporary one used in parseClass. This led to extra memory usage and inconsistent locking behavior, plus broken bootimage builds. --- src/machine.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/machine.cpp b/src/machine.cpp index 743f56e41a..828de31fc0 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2296,6 +2296,11 @@ updateClassTables(Thread* t, object newClass, object oldClass) } } + object staticTable = classStaticTable(t, newClass); + if (staticTable) { + set(t, staticTable, SingletonBody, newClass); + } + if (classFlags(t, newClass) & ACC_INTERFACE) { object virtualTable = classVirtualTable(t, newClass); if (virtualTable) { From 7946aaf48fe08c7ffcc84269f04826645ac3b8fc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 6 Oct 2012 15:30:59 -0600 Subject: [PATCH 030/378] update static table mapping code in bootimage.cpp to match machine.cpp Commit c918cbc added a reference to ensure sun.misc.Unsafe.getLongVolatile could be implemented efficiently on 32-bit platforms, but I forgot to update bootimage.cpp to account for it. --- src/bootimage.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 4525b3ec05..492366f6c2 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -310,7 +310,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, if (endsWith(".class", name, nameSize) and (className == 0 or strncmp(name, className, nameSize - 6) == 0)) { - // fprintf(stderr, "%.*s\n", nameSize - 6, name); + // fprintf(stderr, "pass 1 %.*s\n", nameSize - 6, name); object c = resolveSystemClass (t, root(t, Machine::BootLoader), makeByteArray(t, "%.*s", nameSize - 6, name), true); @@ -412,8 +412,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, objectHash); } } - - // if (strcmp(name, "java/lang/System$Property.class") == 0) trap(); { object array = 0; PROTECT(t, array); @@ -454,7 +452,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, targetMemberOffset = TargetBytesPerWord; } - Field staticFields[count + 2]; + const unsigned StaticHeader = 3; + + Field staticFields[count + StaticHeader]; init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -462,9 +462,12 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, init(new (staticFields + 1) Field, Type_intptr_t, BytesPerWord, BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); - unsigned staticIndex = 2; - unsigned buildStaticOffset = BytesPerWord * 2; - unsigned targetStaticOffset = TargetBytesPerWord * 2; + init(new (staticFields + 2) Field, Type_object, BytesPerWord * 2, + BytesPerWord, TargetBytesPerWord * 2, TargetBytesPerWord); + + unsigned staticIndex = StaticHeader; + unsigned buildStaticOffset = BytesPerWord * StaticHeader; + unsigned targetStaticOffset = TargetBytesPerWord * StaticHeader; for (unsigned i = 0; i < vectorSize(t, fields); ++i) { object field = vectorBody(t, fields, i); @@ -535,7 +538,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, targetMemberOffset = pad(targetMemberOffset, TargetBytesPerWord); } } - + if (hashMapFind(t, typeMaps, c, objectHash, objectEqual) == 0) { object array = makeByteArray (t, TypeMap::sizeInBytes @@ -594,7 +597,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, if (endsWith(".class", name, nameSize) and (className == 0 or strncmp(name, className, nameSize - 6) == 0)) { - // fprintf(stderr, "%.*s\n", nameSize - 6, name); + // fprintf(stderr, "pass 2 %.*s\n", nameSize - 6, name); object c = resolveSystemClass (t, root(t, Machine::BootLoader), makeByteArray(t, "%.*s", nameSize - 6, name), true); From a3c4b60f43f135f156ca4d1d9b33dfbf91f4afc9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 6 Oct 2012 15:33:24 -0600 Subject: [PATCH 031/378] rename package avian.avian_vm_resource to avian.avianvmresource This package name must match the URL protocol we use for loading embedded resources, but OpenJDK's URL class won't tolerate underscores in a protocol name. Also, I had not updated the names of the native methods in avian.avianvmresource.Handler, leading to UnsatisfiedLinkErrors when they were called. --- .../Handler.java | 2 +- classpath/java/net/URL.java | 4 ++-- makefile | 2 +- openjdk.pro | 4 +++- src/builtin.cpp | 12 ++++++------ src/finder.cpp | 2 +- 6 files changed, 14 insertions(+), 12 deletions(-) rename classpath/avian/{avian_vm_resource => avianvmresource}/Handler.java (98%) diff --git a/classpath/avian/avian_vm_resource/Handler.java b/classpath/avian/avianvmresource/Handler.java similarity index 98% rename from classpath/avian/avian_vm_resource/Handler.java rename to classpath/avian/avianvmresource/Handler.java index dfad1f7964..ea776c7e92 100644 --- a/classpath/avian/avian_vm_resource/Handler.java +++ b/classpath/avian/avianvmresource/Handler.java @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -package avian.avian_vm_resource; +package avian.avianvmresource; import java.net.URL; import java.net.URLStreamHandler; diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index 3c2852f394..c311ad8c15 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -83,8 +83,8 @@ public final class URL { { if ("http".equals(protocol) || "https".equals(protocol)) { return new avian.http.Handler(); - } else if ("avian_vm_resource".equals(protocol)) { - return new avian.avian_vm_resource.Handler(); + } else if ("avianvmresource".equals(protocol)) { + return new avian.avianvmresource.Handler(); } else if ("file".equals(protocol)) { return new avian.file.Handler(); } else if ("jar".equals(protocol)) { diff --git a/makefile b/makefile index 6b611ebd2c..8330ff31e0 100755 --- a/makefile +++ b/makefile @@ -806,7 +806,7 @@ ifneq ($(classpath),avian) $(classpath-src)/avian/VMClass.java \ $(classpath-src)/avian/VMField.java \ $(classpath-src)/avian/VMMethod.java \ - $(classpath-src)/avian/avian_vm_resource/Handler.java + $(classpath-src)/avian/avianvmresource/Handler.java ifneq ($(openjdk),) classpath-sources := $(classpath-sources) \ diff --git a/openjdk.pro b/openjdk.pro index 8207016de5..165a6067af 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -208,7 +208,7 @@ -keep class sun.nio.cs.UTF_8 # loaded reflectively to handle embedded resources: --keep class avian.resource.Handler +-keep class avian.avianvmresource.Handler # refered to symbolically in MethodAccessorGenerator: -keep class sun.reflect.MethodAccessorImpl { @@ -244,3 +244,5 @@ -keep class sun.nio.fs.UnixException { UnixException(int); } + +-keep class sun.net.www.protocol.jar.Handler diff --git a/src/builtin.cpp b/src/builtin.cpp index c438aebea0..845c0cebe1 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -155,7 +155,7 @@ Avian_java_lang_Runtime_exit } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength +Avian_avian_avianvmresource_Handler_00024ResourceInputStream_getContentLength (Thread* t, object, uintptr_t* arguments) { object path = reinterpret_cast(*arguments); @@ -179,7 +179,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_resource_Handler_00024ResourceInputStream_open +Avian_avian_avianvmresource_Handler_00024ResourceInputStream_open (Thread* t, object, uintptr_t* arguments) { object path = reinterpret_cast(*arguments); @@ -200,7 +200,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_resource_Handler_00024ResourceInputStream_available +Avian_avian_avianvmresource_Handler_00024ResourceInputStream_available (Thread*, object, uintptr_t* arguments) { int64_t peer; memcpy(&peer, arguments, 8); @@ -211,7 +211,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_available } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_resource_Handler_00024ResourceInputStream_read__JI +Avian_avian_avianvmresource_Handler_00024ResourceInputStream_read__JI (Thread*, object, uintptr_t* arguments) { int64_t peer; memcpy(&peer, arguments, 8); @@ -226,7 +226,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_read__JI } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_resource_Handler_00024ResourceInputStream_read__JI_3BII +Avian_avian_avianvmresource_Handler_00024ResourceInputStream_read__JI_3BII (Thread* t, object, uintptr_t* arguments) { int64_t peer; memcpy(&peer, arguments, 8); @@ -251,7 +251,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_read__JI_3BII } extern "C" JNIEXPORT void JNICALL -Avian_avian_resource_Handler_00024ResourceInputStream_close +Avian_avian_avianvmresource_Handler_00024ResourceInputStream_close (Thread*, object, uintptr_t* arguments) { int64_t peer; memcpy(&peer, arguments, 8); diff --git a/src/finder.cpp b/src/finder.cpp index 12c8edc8eb..bfe6214a9e 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -602,7 +602,7 @@ class BuiltinElement: public JarElement { } virtual const char* urlPrefix() { - return "avian_vm_resource:"; + return "avianvmresource:"; } virtual const char* sourceUrl() { From 3e0ab35ba1e7b6544e52ae4e95f80cae4247a498 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 13 Oct 2012 09:39:14 -0600 Subject: [PATCH 032/378] fix PersistentSet.remove side-effect bug The whole point of PersistentSet is to provide non-destructive write operations, which means the add and remove methods should have no effect on previous revisions. However, a bug in remove caused shared tree nodes to be modified, corrupting any revisions with which they were shared. --- classpath/avian/PersistentSet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classpath/avian/PersistentSet.java b/classpath/avian/PersistentSet.java index 5683327aee..917607ed90 100644 --- a/classpath/avian/PersistentSet.java +++ b/classpath/avian/PersistentSet.java @@ -252,7 +252,7 @@ public class PersistentSet implements Iterable { } ancestors.next = new Cell(n, ancestors.next); - sibling = ancestors.value.right; + sibling = ancestors.value.right = new Node(ancestors.value.right); } if (! (sibling.left.red || sibling.right.red)) { @@ -303,7 +303,7 @@ public class PersistentSet implements Iterable { } ancestors.next = new Cell(n, ancestors.next); - sibling = ancestors.value.left; + sibling = ancestors.value.left = new Node(ancestors.value.left); } if (! (sibling.right.red || sibling.left.red)) { From 8f308291b05b018ecd971bd30aa31b7db4d9630b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 13 Oct 2012 09:46:12 -0600 Subject: [PATCH 033/378] eliminate call stack recursion in compile method Some OSes (notably, Windows CE) restrict the size of the call stack such that recursive compilation of branch instructions can lead to stack overflow in methods with large numbers of such instructions. In fact, a worst-case method could even lead to overflow when the stack size limit is relatively generous. The solution is to convert this recursion into iteration with an explicit stack to maintain state about alternate paths through each branch. --- src/compile.cpp | 381 +++++++++++++++++++++++++++++++++++------------- src/zone.h | 45 ++++-- 2 files changed, 314 insertions(+), 112 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index e29f4e592a..c97234363d 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1388,6 +1388,10 @@ class Frame { } ~Frame() { + dispose(); + } + + void dispose() { if (level > 1) { context->eventLog.append(PopContextEvent); } @@ -3744,21 +3748,10 @@ isReferenceTailCall(MyThread* t, object code, unsigned ip, object caller, (t, code, ip, caller, methodReferenceReturnCode(t, calleeReference)); } -void -compile(MyThread* t, Frame* initialFrame, unsigned ip, - int exceptionHandlerStart = -1); - -void -saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip) -{ - Compiler::State* state = initialFrame->c->saveState(); - compile(t, initialFrame, ip); - initialFrame->c->restoreState(state); -} - bool integerBranch(MyThread* t, Frame* frame, object code, unsigned& ip, - unsigned size, Compiler::Operand* a, Compiler::Operand* b) + unsigned size, Compiler::Operand* a, Compiler::Operand* b, + unsigned* newIpp) { if (ip + 3 > codeLength(t, code)) { return false; @@ -3802,14 +3795,14 @@ integerBranch(MyThread* t, Frame* frame, object code, unsigned& ip, return false; } - saveStateAndCompile(t, frame, newIp); + *newIpp = newIp; return true; } bool floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, unsigned size, bool lessIfUnordered, Compiler::Operand* a, - Compiler::Operand* b) + Compiler::Operand* b, unsigned* newIpp) { if (ip + 3 > codeLength(t, code)) { return false; @@ -3869,7 +3862,7 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, return false; } - saveStateAndCompile(t, frame, newIp); + *newIpp = newIp; return true; } @@ -4043,17 +4036,126 @@ targetFieldOffset(Context* context, object field) } } +class Stack { + public: + class MyResource: public Thread::Resource { + public: + MyResource(Stack* s): Resource(s->thread), s(s) { } + + virtual void release() { + s->zone.dispose(); + } + + Stack* s; + }; + + Stack(MyThread* t): + thread(t), + zone(t->m->system, t->m->heap, 0), + resource(this) + { } + + ~Stack() { + zone.dispose(); + } + + void pushValue(uintptr_t v) { + *static_cast(push(BytesPerWord)) = v; + } + + uintptr_t peekValue(unsigned offset) { + return *static_cast(peek((offset + 1) * BytesPerWord)); + } + + uintptr_t popValue() { + uintptr_t v = peekValue(0); + pop(BytesPerWord); + return v; + } + + void* push(unsigned size) { + return zone.allocate(size); + } + + void* peek(unsigned size) { + return zone.peek(size); + } + + void pop(unsigned size) { + zone.pop(size); + } + + MyThread* thread; + Zone zone; + MyResource resource; +}; + +class SwitchState { + public: + SwitchState(Compiler::State* state, + unsigned count, + unsigned defaultIp, + Compiler::Operand* key, + Promise* start, + int bottom, + int top): + state(state), + count(count), + defaultIp(defaultIp), + key(key), + start(start), + bottom(bottom), + top(top), + index(0) + { } + + Frame* frame() { + return reinterpret_cast + (reinterpret_cast(this) - pad(count * 4) - pad(sizeof(Frame))); + } + + uint32_t* ipTable() { + return reinterpret_cast + (reinterpret_cast(this) - pad(count * 4)); + } + + Compiler::State* state; + unsigned count; + unsigned defaultIp; + Compiler::Operand* key; + Promise* start; + int bottom; + int top; + unsigned index; +}; + void -compile(MyThread* t, Frame* initialFrame, unsigned ip, - int exceptionHandlerStart) +compile(MyThread* t, Frame* initialFrame, unsigned initialIp, + int exceptionHandlerStart = -1) { - THREAD_RUNTIME_ARRAY(t, uint8_t, stackMap, - codeMaxStack(t, methodCode(t, initialFrame->context->method))); - Frame myFrame(initialFrame, RUNTIME_ARRAY_BODY(stackMap)); - Frame* frame = &myFrame; + enum { + Return, + Unbranch, + Unsubroutine, + Untable0, + Untable1, + Unswitch + }; + + Frame* frame = initialFrame; Compiler* c = frame->c; Context* context = frame->context; + unsigned stackSize = codeMaxStack(t, methodCode(t, context->method)); + Stack stack(t); + unsigned ip = initialIp; + unsigned newIp; + stack.pushValue(Return); + start: + uint8_t* stackMap = static_cast(stack.push(stackSize)); + frame = new (stack.push(sizeof(Frame))) Frame(frame, stackMap); + + loop: object code = methodCode(t, context->method); PROTECT(t, code); @@ -4061,7 +4163,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (context->visitTable[ip] ++) { // we've already visited this part of the code frame->visitLogicalIp(ip); - return; + goto next; } frame->startLogicalIp(ip); @@ -4318,7 +4420,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case areturn: { handleExit(t, frame); c->return_(TargetBytesPerWord, frame->popObject()); - } return; + } goto next; case arraylength: { frame->pushInt @@ -4363,7 +4465,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (ip == codeLength(t, code)) { c->trap(); } - } return; + } goto next; case bipush: frame->pushInt @@ -4427,7 +4529,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - if (not floatBranch(t, frame, code, ip, 8, false, a, b)) { + if (floatBranch(t, frame, code, ip, 8, false, a, b, &newIp)) { + goto branch; + } else { frame->pushInt (c->call (c->constant @@ -4442,7 +4546,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - if (not floatBranch(t, frame, code, ip, 8, true, a, b)) { + if (floatBranch(t, frame, code, ip, 8, true, a, b, &newIp)) { + goto branch; + } else { frame->pushInt (c->call (c->constant @@ -4540,7 +4646,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - if (not floatBranch(t, frame, code, ip, 4, false, a, b)) { + if (floatBranch(t, frame, code, ip, 4, false, a, b, &newIp)) { + goto branch; + } else { frame->pushInt (c->call (c->constant @@ -4553,7 +4661,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - if (not floatBranch(t, frame, code, ip, 4, true, a, b)) { + if (floatBranch(t, frame, code, ip, 4, true, a, b, &newIp)) { + goto branch; + } else { frame->pushInt (c->call (c->constant @@ -4887,7 +4997,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case if_acmpeq: case if_acmpne: { uint32_t offset = codeReadInt16(t, code, ip); - uint32_t newIp = (ip - 3) + offset; + newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); Compiler::Operand* a = frame->popObject(); @@ -4899,9 +5009,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } else { c->jumpIfNotEqual(TargetBytesPerWord, a, b, target); } - - saveStateAndCompile(t, frame, newIp); - } break; + } goto branch; case if_icmpeq: case if_icmpne: @@ -4910,7 +5018,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case if_icmplt: case if_icmple: { uint32_t offset = codeReadInt16(t, code, ip); - uint32_t newIp = (ip - 3) + offset; + newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); Compiler::Operand* a = frame->popInt(); @@ -4939,9 +5047,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, default: abort(t); } - - saveStateAndCompile(t, frame, newIp); - } break; + } goto branch; case ifeq: case ifne: @@ -4950,7 +5056,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case iflt: case ifle: { uint32_t offset = codeReadInt16(t, code, ip); - uint32_t newIp = (ip - 3) + offset; + newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); Compiler::Operand* target = frame->machineIp(newIp); @@ -4980,14 +5086,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, default: abort(t); } - - saveStateAndCompile(t, frame, newIp); - } break; + } goto branch; case ifnull: case ifnonnull: { uint32_t offset = codeReadInt16(t, code, ip); - uint32_t newIp = (ip - 3) + offset; + newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); Compiler::Operand* a = c->constant(0, Compiler::ObjectType); @@ -4999,9 +5103,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } else { c->jumpIfNotEqual(TargetBytesPerWord, a, b, target); } - - saveStateAndCompile(t, frame, newIp); - } break; + } goto branch; case iinc: { uint8_t index = codeBody(t, code, ip++); @@ -5298,7 +5400,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case freturn: { handleExit(t, frame); c->return_(4, frame->popInt()); - } return; + } goto next; case ishl: { Compiler::Operand* a = frame->popInt(); @@ -5358,7 +5460,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case jsr: case jsr_w: { uint32_t thisIp; - uint32_t newIp; if (instruction == jsr) { uint32_t offset = codeReadInt16(t, code, ip); @@ -5376,10 +5477,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jmp(frame->machineIp(newIp)); - saveStateAndCompile(t, frame, newIp); - - frame->endSubroutine(start); - } break; + stack.pushValue(start); + stack.pushValue(ip); + stack.pushValue(Unsubroutine); + ip = newIp; + } goto start; case l2d: { frame->pushLong(c->i2f(8, 8, frame->popLong())); @@ -5409,7 +5511,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - if (not integerBranch(t, frame, code, ip, 8, a, b)) { + if (integerBranch(t, frame, code, ip, 8, a, b, &newIp)) { + goto branch; + } else { frame->pushInt (c->call (c->constant @@ -5567,7 +5671,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (frame->addressPromise(c->machineIp(defaultIp))); Promise* start = 0; - THREAD_RUNTIME_ARRAY(t, uint32_t, ipTable, pairCount); + uint32_t* ipTable = static_cast + (stack.push(sizeof(uint32_t) * pairCount)); for (int32_t i = 0; i < pairCount; ++i) { unsigned index = ip + (i * 8); int32_t key = codeReadInt32(t, code, index); @@ -5598,19 +5703,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, TARGET_THREAD_CODEIMAGE), address) : address); - Compiler::State* state = c->saveState(); + new (stack.push(sizeof(SwitchState))) SwitchState + (c->saveState(), pairCount, defaultIp, 0, 0, 0, 0); - for (int32_t i = 0; i < pairCount; ++i) { - compile(t, frame, RUNTIME_ARRAY_BODY(ipTable)[i]); - - c->restoreState(state); - } + goto switchloop; } else { // a switch statement with no cases, apparently c->jmp(frame->machineIp(defaultIp)); + ip = defaultIp; } - - ip = defaultIp; } break; case lor: { @@ -5635,7 +5736,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case dreturn: { handleExit(t, frame); c->return_(8, frame->popLong()); - } return; + } goto next; case lshl: { Compiler::Operand* a = frame->popInt(); @@ -6062,7 +6163,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case ret: { unsigned index = codeBody(t, code, ip); frame->returnFromSubroutine(index); - } return; + } goto next; case return_: if (needsReturnBarrier(t, context->method)) { @@ -6071,7 +6172,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, handleExit(t, frame); c->return_(0, 0); - return; + goto next; case sipush: frame->pushInt @@ -6096,7 +6197,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, int32_t top = codeReadInt32(t, code, ip); Promise* start = 0; - THREAD_RUNTIME_ARRAY(t, uint32_t, ipTable, top - bottom + 1); + unsigned count = top - bottom + 1; + uint32_t* ipTable = static_cast + (stack.push(sizeof(uint32_t) * count)); for (int32_t i = 0; i < top - bottom + 1; ++i) { unsigned index = ip + (i * 4); uint32_t newIp = base + codeReadInt32(t, code, index); @@ -6119,43 +6222,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->save(1, key); - saveStateAndCompile(t, frame, defaultIp); - - c->jumpIfGreater(4, c->constant(top, Compiler::IntegerType), key, - frame->machineIp(defaultIp)); - - c->save(1, key); - - saveStateAndCompile(t, frame, defaultIp); - - Compiler::Operand* normalizedKey - = (bottom - ? c->sub(4, c->constant(bottom, Compiler::IntegerType), key) : key); - - Compiler::Operand* entry = c->memory - (frame->absoluteAddressOperand(start), Compiler::AddressType, 0, - normalizedKey, TargetBytesPerWord); - - c->jmp - (c->load - (TargetBytesPerWord, TargetBytesPerWord, context->bootContext - ? c->add - (TargetBytesPerWord, c->memory - (c->register_(t->arch->thread()), Compiler::AddressType, - TARGET_THREAD_CODEIMAGE), entry) - : entry, - TargetBytesPerWord)); - - Compiler::State* state = c->saveState(); - - for (int32_t i = 0; i < top - bottom + 1; ++i) { - compile(t, frame, RUNTIME_ARRAY_BODY(ipTable)[i]); - - c->restoreState(state); - } + new (stack.push(sizeof(SwitchState))) SwitchState + (c->saveState(), count, defaultIp, key, start, bottom, top); + stack.pushValue(Untable0); ip = defaultIp; - } break; + } goto start; case wide: { switch (codeBody(t, code, ip++)) { @@ -6199,7 +6271,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, unsigned index = codeReadInt16(t, code, ip); c->jmp(loadLocal(context, 1, index)); frame->returnFromSubroutine(index); - } return; + } goto next; default: abort(t); } @@ -6208,6 +6280,113 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, default: abort(t); } } + + next: + frame->dispose(); + frame = 0; + stack.pop(sizeof(Frame)); + stack.pop(stackSize); + switch (stack.popValue()) { + case Return: + return; + + case Unbranch: + ip = stack.popValue(); + c->restoreState(reinterpret_cast(stack.popValue())); + frame = static_cast(stack.peek(sizeof(Frame))); + goto loop; + + case Untable0: { + SwitchState* s = static_cast + (stack.peek(sizeof(SwitchState))); + + frame = s->frame(); + + c->restoreState(s->state); + + c->jumpIfGreater(4, c->constant(s->top, Compiler::IntegerType), s->key, + frame->machineIp(s->defaultIp)); + + c->save(1, s->key); + ip = s->defaultIp; + stack.pushValue(Untable1); + } goto start; + + case Untable1: { + SwitchState* s = static_cast + (stack.peek(sizeof(SwitchState))); + + frame = s->frame(); + + c->restoreState(s->state); + + Compiler::Operand* normalizedKey + = (s->bottom + ? c->sub(4, c->constant(s->bottom, Compiler::IntegerType), s->key) + : s->key); + + Compiler::Operand* entry = c->memory + (frame->absoluteAddressOperand(s->start), Compiler::AddressType, 0, + normalizedKey, TargetBytesPerWord); + + c->jmp + (c->load + (TargetBytesPerWord, TargetBytesPerWord, context->bootContext + ? c->add + (TargetBytesPerWord, c->memory + (c->register_(t->arch->thread()), Compiler::AddressType, + TARGET_THREAD_CODEIMAGE), entry) + : entry, + TargetBytesPerWord)); + + s->state = c->saveState(); + } goto switchloop; + + case Unswitch: { + SwitchState* s = static_cast + (stack.peek(sizeof(SwitchState))); + + frame = s->frame(); + + c->restoreState + (static_cast(stack.peek(sizeof(SwitchState)))->state); + } goto switchloop; + + case Unsubroutine: { + ip = stack.popValue(); + unsigned start = stack.popValue(); + frame = reinterpret_cast(stack.peek(sizeof(Frame))); + frame->endSubroutine(start); + } goto loop; + + default: + abort(t); + } + + switchloop: { + SwitchState* s = static_cast + (stack.peek(sizeof(SwitchState))); + + if (s->index < s->count) { + ip = s->ipTable()[s->index++]; + stack.pushValue(Unswitch); + goto start; + } else { + ip = s->defaultIp; + unsigned count = s->count * 4; + stack.pop(sizeof(SwitchState)); + stack.pop(count); + frame = reinterpret_cast(stack.peek(sizeof(Frame))); + goto loop; + } + } + + branch: + stack.pushValue(reinterpret_cast(c->saveState())); + stack.pushValue(ip); + stack.pushValue(Unbranch); + ip = newIp; + goto start; } FILE* compileLog = 0; diff --git a/src/zone.h b/src/zone.h index 9e35cdcad7..900ea5d3ab 100644 --- a/src/zone.h +++ b/src/zone.h @@ -20,10 +20,13 @@ class Zone: public Allocator { public: class Segment { public: - Segment(Segment* next, unsigned size): next(next), size(size) { } + Segment(Segment* next, unsigned size): + next(next), size(size), position(0) + { } Segment* next; uintptr_t size; + uintptr_t position; uint8_t data[0]; }; @@ -31,7 +34,6 @@ class Zone: public Allocator { s(s), allocator(allocator), segment(0), - position(0), minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 : minimumFootprint - sizeof(Segment)) { } @@ -55,7 +57,7 @@ class Zone: public Allocator { } bool tryEnsure(unsigned space) { - if (segment == 0 or position + space > segment->size) { + if (segment == 0 or segment->position + space > segment->size) { unsigned size = padToPage (max (space, max @@ -72,26 +74,24 @@ class Zone: public Allocator { } segment = new (p) Segment(segment, size - sizeof(Segment)); - position = 0; } return true; } void ensure(unsigned space) { - if (segment == 0 or position + space > segment->size) { + if (segment == 0 or segment->position + space > segment->size) { unsigned size = padToPage(space + sizeof(Segment)); segment = new (allocator->allocate(size)) Segment(segment, size - sizeof(Segment)); - position = 0; } } virtual void* tryAllocate(unsigned size) { size = pad(size); if (tryEnsure(size)) { - void* r = segment->data + position; - position += size; + void* r = segment->data + segment->position; + segment->position += size; return r; } else { return 0; @@ -99,17 +99,41 @@ class Zone: public Allocator { } virtual void* allocate(unsigned size) { + size = pad(size); void* p = tryAllocate(size); if (p) { return p; } else { ensure(size); - void* r = segment->data + position; - position += size; + void* r = segment->data + segment->position; + segment->position += size; return r; } } + void* peek(unsigned size) { + size = pad(size); + Segment* s = segment; + while (s->position < size) { + size -= s->position; + s = s->next; + } + return s->data + (s->position - size); + } + + void pop(unsigned size) { + size = pad(size); + Segment* s = segment; + while (s->position < size) { + size -= s->position; + Segment* next = s->next; + allocator->free(s, sizeof(Segment) + s->size); + s = next; + } + s->position -= size; + segment = s; + } + virtual void free(const void*, unsigned) { // not supported abort(s); @@ -119,7 +143,6 @@ class Zone: public Allocator { Allocator* allocator; void* context; Segment* segment; - unsigned position; unsigned minimumFootprint; }; From 3665753d1f77b6de520438947857bb42e8b7d4d4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 13 Oct 2012 13:09:24 -0600 Subject: [PATCH 034/378] fix MSVC build regression --- src/compile.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index c97234363d..86432bb131 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5679,7 +5679,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, uint32_t newIp = base + codeReadInt32(t, code, index); assert(t, newIp < codeLength(t, code)); - RUNTIME_ARRAY_BODY(ipTable)[i] = newIp; + ipTable[i] = newIp; Promise* p = c->poolAppend(key); if (i == 0) { @@ -6205,7 +6205,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, uint32_t newIp = base + codeReadInt32(t, code, index); assert(t, newIp < codeLength(t, code)); - RUNTIME_ARRAY_BODY(ipTable)[i] = newIp; + ipTable[i] = newIp; Promise* p = c->poolAppendPromise (frame->addressPromise(c->machineIp(newIp))); From be12db20cb50db7a21fd5484098fe372ad482908 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 16 Oct 2012 08:33:35 -0600 Subject: [PATCH 035/378] preserve all methods in avian.OpenJDK from removal in openjdk.pro OpenJDK.getDeclaringClass is called from JVM_GetDeclaringClass, so we need to tell ProGuard to preserve it along with the other method we had already included. --- openjdk.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openjdk.pro b/openjdk.pro index 165a6067af..d0b8de812f 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -42,7 +42,7 @@ } -keep class avian.OpenJDK { - public static java.security.ProtectionDomain getProtectionDomain(); + ; } -keepclassmembers public class java.security.PrivilegedAction { From 4c20465294eca13c397d583fa224451f7dc1e049 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 30 Oct 2012 09:34:16 -0600 Subject: [PATCH 036/378] add basic URLClassLoader implementation --- classpath/java/net/URLClassLoader.java | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 classpath/java/net/URLClassLoader.java diff --git a/classpath/java/net/URLClassLoader.java b/classpath/java/net/URLClassLoader.java new file mode 100644 index 0000000000..d4233cfd42 --- /dev/null +++ b/classpath/java/net/URLClassLoader.java @@ -0,0 +1,57 @@ +package java.net; + +import java.io.File; + +import java.io.InputStream; +import java.io.IOException; +import java.io.ByteArrayOutputStream; + +public class URLClassLoader extends ClassLoader { + + private final File jarFile; + + public URLClassLoader(URL[] urls, ClassLoader parent) { + super(parent); + if(urls.length != 1) { + throw new UnsupportedOperationException(); + } + if(!urls[0].getProtocol().equals("file")) { + throw new UnsupportedOperationException(urls[0].getProtocol()); + } + this.jarFile = new File(urls[0].getFile()); + } + + + protected Class findClass(String name) throws ClassNotFoundException { + try { + InputStream stream = getResourceAsStream(name.replace(".", "/") + ".class"); + if(stream == null) { + throw new ClassNotFoundException("couldn't find class " + name); + } + byte[] buf = new byte[2048]; + ByteArrayOutputStream mem = new ByteArrayOutputStream(); + try { + int size; + while((size = stream.read(buf, 0, buf.length)) > 0) { + mem.write(buf, 0, size); + } + byte[] data = mem.toByteArray(); + return defineClass(name, data, 0, data.length); + } finally { + stream.close(); + } + } catch(IOException e) { + throw new ClassNotFoundException("couldn't find class " + name, e); + } + } + + public URL getResource(String path) { + try { + return new URL("jar:file:" + jarFile.getAbsolutePath() + "!/" + path); + } catch(MalformedURLException e) { + throw new RuntimeException(e); + } + } + + +} \ No newline at end of file From be952acbcbeadf041c73d19a6ecac7ac72d21ac2 Mon Sep 17 00:00:00 2001 From: Pierre Carrier Date: Sun, 4 Nov 2012 01:56:06 +0100 Subject: [PATCH 037/378] classpath: Closeable & Flushable --- classpath/java/io/Closeable.java | 16 ++++++++++++++++ classpath/java/io/Flushable.java | 16 ++++++++++++++++ classpath/java/io/InputStream.java | 2 +- classpath/java/io/OutputStream.java | 2 +- classpath/java/io/Reader.java | 2 +- classpath/java/io/Writer.java | 2 +- 6 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 classpath/java/io/Closeable.java create mode 100644 classpath/java/io/Flushable.java diff --git a/classpath/java/io/Closeable.java b/classpath/java/io/Closeable.java new file mode 100644 index 0000000000..e24a572fb5 --- /dev/null +++ b/classpath/java/io/Closeable.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2012, 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. */ + +package java.io; + +public interface Closeable { + void close() + throws IOException; +} diff --git a/classpath/java/io/Flushable.java b/classpath/java/io/Flushable.java new file mode 100644 index 0000000000..25b941d4bb --- /dev/null +++ b/classpath/java/io/Flushable.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2012, 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. */ + +package java.io; + +public interface Flushable { + void flush() + throws IOException; +} diff --git a/classpath/java/io/InputStream.java b/classpath/java/io/InputStream.java index ec29b52b7a..d6ab46c140 100644 --- a/classpath/java/io/InputStream.java +++ b/classpath/java/io/InputStream.java @@ -10,7 +10,7 @@ package java.io; -public abstract class InputStream { +public abstract class InputStream implements Closeable { public abstract int read() throws IOException; public int read(byte[] buffer) throws IOException { diff --git a/classpath/java/io/OutputStream.java b/classpath/java/io/OutputStream.java index caeccde12c..b73345ee16 100644 --- a/classpath/java/io/OutputStream.java +++ b/classpath/java/io/OutputStream.java @@ -10,7 +10,7 @@ package java.io; -public abstract class OutputStream { +public abstract class OutputStream implements Closeable, Flushable { public abstract void write(int c) throws IOException; public void write(byte[] buffer) throws IOException { diff --git a/classpath/java/io/Reader.java b/classpath/java/io/Reader.java index 2edfd70803..668f82b1cf 100644 --- a/classpath/java/io/Reader.java +++ b/classpath/java/io/Reader.java @@ -10,7 +10,7 @@ package java.io; -public abstract class Reader { +public abstract class Reader implements Closeable { public int read() throws IOException { char[] buffer = new char[1]; int c = read(buffer); diff --git a/classpath/java/io/Writer.java b/classpath/java/io/Writer.java index 0d5b8fbf85..2ea1bcba07 100644 --- a/classpath/java/io/Writer.java +++ b/classpath/java/io/Writer.java @@ -10,7 +10,7 @@ package java.io; -public abstract class Writer { +public abstract class Writer implements Closeable, Flushable { public void write(int c) throws IOException { char[] buffer = new char[] { (char) c }; write(buffer); From f8ea506021ac057b0a1b89899e155d5cb9b5ddb2 Mon Sep 17 00:00:00 2001 From: Pierre Carrier Date: Mon, 5 Nov 2012 00:10:02 +0100 Subject: [PATCH 038/378] classpath: j.l.{Integer,Long}.to{Octal,Binary}String Offer support for toOctalString and toBinaryString in Integer and Long. --- classpath/java/lang/Integer.java | 4 ++++ classpath/java/lang/Long.java | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index e524cc43c4..8ea8668ddc 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -62,6 +62,10 @@ public final class Integer extends Number implements Comparable { return Long.toString(((long) v) & 0xFFFFFFFFL, 16); } + public static String toOctalString(int v) { + return Long.toString(((long) v) & 0xFFFFFFFFL, 8); + } + public static String toBinaryString(int v) { return Long.toString(((long) v) & 0xFFFFFFFFL, 2); } diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index 033ca8b111..b7569951b7 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -94,6 +94,14 @@ public final class Long extends Number implements Comparable { return toString(v, 16); } + public static String toOctalString(long v) { + return toString(v, 8); + } + + public static String toBinaryString(long v) { + return toString(v, 2); + } + public byte byteValue() { return (byte) value; } From 74b070f9cc91112dbf2d3d863ca28292dc766046 Mon Sep 17 00:00:00 2001 From: Pierre Carrier Date: Sun, 11 Nov 2012 06:04:11 +0100 Subject: [PATCH 039/378] classpath: java.nio.ByteOrder Used by jruby. (Not saying I'm gonna implement String.format :) --- classpath/java-nio.cpp | 14 ++++++++++- classpath/java/nio/ByteOrder.java | 40 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 classpath/java/nio/ByteOrder.java diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index d5e067e1e4..dc15639dc7 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -1015,3 +1015,15 @@ Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass, } +extern "C" JNIEXPORT jboolean JNICALL +Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv *, jclass) +{ + union { + uint32_t i; + char c[4]; + } u = {0x01020304}; + + if (u.c[0] == 1) + return JNI_TRUE; + return JNI_FALSE; +} diff --git a/classpath/java/nio/ByteOrder.java b/classpath/java/nio/ByteOrder.java new file mode 100644 index 0000000000..8e2b432ed2 --- /dev/null +++ b/classpath/java/nio/ByteOrder.java @@ -0,0 +1,40 @@ +/* Copyright (c) 2012, 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. */ + +package java.nio; + +public final class ByteOrder { + public static final ByteOrder BIG_ENDIAN = new ByteOrder("BIG_ENDIAN"); + public static final ByteOrder LITTLE_ENDIAN = new ByteOrder("LITTLE_ENDIAN"); + + private static final ByteOrder NATIVE; + private static native boolean isNativeBigEndian(); + + static { + if (isNativeBigEndian()) + NATIVE = BIG_ENDIAN; + else + NATIVE = LITTLE_ENDIAN; + } + + private String name; + + private ByteOrder(String name) { + this.name = name; + } + + public String toString() { + return name; + } + + public static ByteOrder nativeOrder() { + return NATIVE; + } +} From 53b1a2423aa1bdf6d2d7d62394c379ccabfe4737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Elton=20S=C3=B8rensen?= Date: Mon, 12 Nov 2012 22:35:58 +0100 Subject: [PATCH 040/378] Accept M and K suffixes for memory sizes like the java command --- src/jnienv.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 52da9559f7..12a32fb3f5 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3345,11 +3345,11 @@ parseSize(const char* s) RUNTIME_ARRAY(char, buffer, length + 1); if (length == 0) { return 0; - } else if (s[length - 1] == 'k') { + } else if (s[length - 1] == 'k' or s[length - 1] == 'K') { memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1); RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0; return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024; - } else if (s[length - 1] == 'm') { + } else if (s[length - 1] == 'm' or s[length - 1] == 'M') { memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1); RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0; return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024 * 1024; From 571cc6a85e465438dbda40b5220dbf773d17ed80 Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Tue, 13 Nov 2012 09:11:49 +0100 Subject: [PATCH 041/378] Added new embed utility for Windows --- makefile | 47 ++++++++++++++- src/embed.cpp | 125 ++++++++++++++++++++++++++++++++++++++++ src/embed.h | 17 ++++++ src/embedded-loader.cpp | 105 +++++++++++++++++++++++++++++++++ 4 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 src/embed.cpp create mode 100644 src/embed.h create mode 100644 src/embedded-loader.cpp diff --git a/makefile b/makefile index 8330ff31e0..8e494b5595 100755 --- a/makefile +++ b/makefile @@ -496,6 +496,10 @@ ifeq ($(platform),windows) else shared += -Wl,--add-stdcall-alias endif + + embed = $(build-embed)/embed.exe + embed-loader = $(build-embed-loader)/embed-loader.exe + embed-loader-o = $(build-embed)/embed-loader.o endif ifeq ($(mode),debug) @@ -640,6 +644,15 @@ vm-asm-sources = $(src)/$(asm).S target-asm = $(asm) +build-embed = $(build)/embed +build-embed-loader = $(build)/embed-loader + +embed-loader-sources = $(src)/embedded-loader.cpp +embed-loader-objects = $(call cpp-objects,$(embed-loader-sources),$(src),$(build-embed-loader)) + +embed-sources = $(src)/embed.cpp +embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) + ifeq ($(process),compile) vm-sources += \ $(src)/compiler.cpp \ @@ -890,7 +903,7 @@ test-args = $(test-flags) $(input) .PHONY: build build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ - $(test-extra-dep) + $(test-extra-dep) $(embed) $(test-dep): $(classpath-dep) @@ -1005,6 +1018,38 @@ else $(ld) $(^) $(shared) $(lflags) -o $(@) endif +ifdef embed +$(embed): $(embed-objects) $(embed-loader-o) + @echo "building $(embed)" + $(build-cxx) $(^) -mwindows -mconsole -static -o $(@) + +$(build-embed)/%.o: $(src)/%.cpp + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(build-cxx) -D_UNICODE -DUNICODE -c $(<) -o $(@) + +$(embed-loader-o): $(embed-loader) $(converter) + @mkdir -p $(dir $(@)) + $(converter) $(<) $(@) _binary_loader_start \ + _binary_loader_end $(target-format) $(arch) + +$(embed-loader): $(embed-loader-objects) $(static-library) + @mkdir -p $(dir $(@)) + cd $(dir $(@)) && $(ar) x ../../../$(static-library) + $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(dir $(@))/*.o + $(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@))) + $(cxx) $(addsuffix .exp,$(basename $(@))) $(dir $(@))/*.o -L../win32/lib -lmingwthrd -lm -lz -lws2_32 -liphlpapi \ + -mwindows -mconsole -static -o $(@) + strip --strip-all $(@) + +$(build-embed-loader)/%.o: $(src)/%.cpp + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/win32 \ + -D_JNI_IMPLEMENTATION_ -c $(<) -o $(@) + +endif + $(build)/%.o: $(lzma)/C/%.c @echo "compiling $(@)" @mkdir -p $(dir $(@)) diff --git a/src/embed.cpp b/src/embed.cpp new file mode 100644 index 0000000000..ed02731c1a --- /dev/null +++ b/src/embed.cpp @@ -0,0 +1,125 @@ +/* Copyright (c) 2008-2012, 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 +#include +#include +#include +#include +#include + +#include "embed.h" + +extern "C" const uint8_t binary_loader_start[]; +extern "C" const uint8_t binary_loader_end[]; + +__declspec(noreturn) +void printUsage(const wchar_t* executableName) +{ + wprintf(L"Usage: %s destination.exe classes.jar package.Main\n", executableName); + exit(0); +} + +void writeDestinationFile(const wchar_t* filename) +{ + if(FILE* file = _wfopen(filename, L"wb")) + { + size_t count = binary_loader_end - binary_loader_start; + if(count == fwrite(binary_loader_start, sizeof(binary_loader_start[0]), count, file)) + { + fclose(file); + return; + } + } + + fprintf(stderr, "Unable to write to destination file\n"); + exit(EXIT_FAILURE); +} + +void readFile(std::vector* jarFile, const wchar_t* fileName) +{ + if(FILE* file = _wfopen(fileName, L"rb")) + { + fseek(file, 0, SEEK_END); + jarFile->resize(ftell(file)); + fseek(file, 0, SEEK_SET); + fread(&jarFile->at(0), 1, jarFile->size(), file); + fclose(file); + } +} + +bool mkStringSection(std::vector* stringSection, const std::vector& strings, int first, int last) +{ + stringSection->clear(); + for(int i = first; i <= last; ++i) + { + const std::wstring& s = strings.at(i); + stringSection->push_back(s.size()); + stringSection->insert(stringSection->end(), s.begin(), s.end()); + } + + // pad to 16 entries + for(int i = last - first; i < 15; ++i) + stringSection->push_back(0); + + return stringSection->size() > 16; +} + +void writeStringResources(HANDLE hDest, const std::vector& strings) +{ + for(int i = 0; i < strings.size(); i += 16) + { + std::vector stringSection; + + if(mkStringSection(&stringSection, strings, i, std::min(i + 15, strings.size() - 1))) + UpdateResourceW(hDest, RT_STRING, MAKEINTRESOURCE((i >> 4) + 1), LANG_NEUTRAL, &stringSection.at(0), sizeof(wchar_t) * stringSection.size()); + } +} + +int wmain(int argc, wchar_t* argv[]) +{ + if(argc != 4) + printUsage(argv[0]); + + const wchar_t* destinationName = argv[1]; + const wchar_t* classesName = argv[2]; + const wchar_t* mainClassName = argv[3]; + + writeDestinationFile(destinationName); + + if(HANDLE hDest = BeginUpdateResourceW(destinationName, TRUE)) + { + std::vector strings; + strings.resize(RESID_MAIN_CLASS + 1); + strings.at(RESID_MAIN_CLASS) = mainClassName; + + writeStringResources(hDest, strings); + + std::vector jarFile; + readFile(&jarFile, classesName); + UpdateResourceW(hDest, RT_RCDATA, _T(RESID_BOOT_JAR), LANG_NEUTRAL, &jarFile.at(0), jarFile.size()); + + EndUpdateResource(hDest, FALSE); + } + + + return 0; +} + +extern "C" int _CRT_glob; +extern "C" void __wgetmainargs(int*, wchar_t***, wchar_t***, int, int*); + +int main() +{ + wchar_t **enpv, **argv; + int argc, si = 0; + __wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si); + return wmain(argc, argv); +} diff --git a/src/embed.h b/src/embed.h new file mode 100644 index 0000000000..a38108e64b --- /dev/null +++ b/src/embed.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2012, 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 EMBED_H +#define EMBED_H + +#define RESID_MAIN_CLASS 100 +#define RESID_BOOT_JAR "BOOT.JAR" + +#endif diff --git a/src/embedded-loader.cpp b/src/embedded-loader.cpp new file mode 100644 index 0000000000..d34bb0bce0 --- /dev/null +++ b/src/embedded-loader.cpp @@ -0,0 +1,105 @@ +/* Copyright (c) 2008-2012, 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 +#include +#include + +#include "embed.h" +#include "jni.h" + + +#if (defined __MINGW32__) || (defined _MSC_VER) +# define EXPORT __declspec(dllexport) +#else +# define EXPORT __attribute__ ((visibility("default"))) \ + __attribute__ ((used)) +#endif + +extern "C" { + + EXPORT const uint8_t* + bootJar(unsigned* size) + { + if(HRSRC hResInfo = FindResource(NULL, _T(RESID_BOOT_JAR), RT_RCDATA)) + { + if(HGLOBAL hRes = LoadResource(NULL, hResInfo)) + { + *size = SizeofResource(NULL, hResInfo); + return (const uint8_t*)LockResource(hRes); + } + } + + fprintf(stderr, "boot.jar resource not found\n"); + + *size = 0; + return NULL; + } +} // extern "C" + +static bool getMainClass(char* pName, int maxLen) +{ + if(0 == LoadString(NULL, RESID_MAIN_CLASS, pName, maxLen)) + { + fprintf(stderr, "Main class not specified\n"); + strcpy(pName, "Main"); + } +} + +int +main(int ac, const char** av) +{ + JavaVMInitArgs vmArgs; + vmArgs.version = JNI_VERSION_1_2; + vmArgs.nOptions = 1; + vmArgs.ignoreUnrecognized = JNI_TRUE; + + JavaVMOption options[vmArgs.nOptions]; + vmArgs.options = options; + + options[0].optionString = const_cast("-Xbootclasspath:[bootJar]"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + char mainClass[256]; + getMainClass(mainClass, sizeof(mainClass)); + + jclass c = e->FindClass(mainClass); + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } else fprintf(stderr, "Couldn't create array\n"); + } else fprintf(stderr, "java.lang.String not found\n"); + } else fprintf(stderr, "main method not found\n"); + } else fprintf(stderr, "Main class not found\n"); + + int exitCode = 0; + if(e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + e->ExceptionClear(); + } + + vm->DestroyJavaVM(); + + return exitCode; +} \ No newline at end of file From 859f0ec503d4e65c42771a9418f74857e762debc Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Fri, 30 Nov 2012 11:08:54 +0100 Subject: [PATCH 042/378] Fix for C++ compile error --- src/interpret.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/interpret.cpp b/src/interpret.cpp index 543363a7d3..4a324fd084 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -92,7 +92,7 @@ inline void pushLong(Thread* t, uint64_t v) { if (DebugStack) { - fprintf(stderr, "push long %"LLD" at %d\n", v, t->sp); + fprintf(stderr, "push long %" LLD " at %d\n", v, t->sp); } pushInt(t, v >> 32); @@ -123,7 +123,7 @@ inline uint32_t popInt(Thread* t) { if (DebugStack) { - fprintf(stderr, "pop int %"ULD" at %d\n", + fprintf(stderr, "pop int %" ULD " at %d\n", t->stack[((t->sp - 1) * 2) + 1], t->sp - 1); } @@ -142,7 +142,7 @@ inline uint64_t popLong(Thread* t) { if (DebugStack) { - fprintf(stderr, "pop long %"LLD" at %d\n", + fprintf(stderr, "pop long %" LLD " at %d\n", (static_cast(t->stack[((t->sp - 2) * 2) + 1]) << 32) | static_cast(t->stack[((t->sp - 1) * 2) + 1]), t->sp - 2); @@ -178,7 +178,7 @@ inline uint32_t peekInt(Thread* t, unsigned index) { if (DebugStack) { - fprintf(stderr, "peek int %"ULD" at %d\n", + fprintf(stderr, "peek int %" ULD " at %d\n", t->stack[(index * 2) + 1], index); } @@ -192,7 +192,7 @@ inline uint64_t peekLong(Thread* t, unsigned index) { if (DebugStack) { - fprintf(stderr, "peek long %"LLD" at %d\n", + fprintf(stderr, "peek long %" LLD " at %d\n", (static_cast(t->stack[(index * 2) + 1]) << 32) | static_cast(t->stack[((index + 1) * 2) + 1]), index); @@ -228,7 +228,7 @@ inline void pokeLong(Thread* t, unsigned index, uint64_t value) { if (DebugStack) { - fprintf(stderr, "poke long %"LLD" at %d\n", value, index); + fprintf(stderr, "poke long %" LLD " at %d\n", value, index); } pokeInt(t, index, value >> 32); @@ -461,7 +461,7 @@ pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect) case DoubleField: case LongField: if (DebugRun) { - fprintf(stderr, "result: %"LLD"\n", result); + fprintf(stderr, "result: %" LLD "\n", result); } pushLong(t, result); break; From 2b44fb6b931dc01f89da879fff36a107ca92b161 Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Fri, 30 Nov 2012 11:14:35 +0100 Subject: [PATCH 043/378] Compile fix for GCC 4.7.2 in C++11 mode --- src/interpret.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/interpret.cpp b/src/interpret.cpp index 543363a7d3..4a324fd084 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -92,7 +92,7 @@ inline void pushLong(Thread* t, uint64_t v) { if (DebugStack) { - fprintf(stderr, "push long %"LLD" at %d\n", v, t->sp); + fprintf(stderr, "push long %" LLD " at %d\n", v, t->sp); } pushInt(t, v >> 32); @@ -123,7 +123,7 @@ inline uint32_t popInt(Thread* t) { if (DebugStack) { - fprintf(stderr, "pop int %"ULD" at %d\n", + fprintf(stderr, "pop int %" ULD " at %d\n", t->stack[((t->sp - 1) * 2) + 1], t->sp - 1); } @@ -142,7 +142,7 @@ inline uint64_t popLong(Thread* t) { if (DebugStack) { - fprintf(stderr, "pop long %"LLD" at %d\n", + fprintf(stderr, "pop long %" LLD " at %d\n", (static_cast(t->stack[((t->sp - 2) * 2) + 1]) << 32) | static_cast(t->stack[((t->sp - 1) * 2) + 1]), t->sp - 2); @@ -178,7 +178,7 @@ inline uint32_t peekInt(Thread* t, unsigned index) { if (DebugStack) { - fprintf(stderr, "peek int %"ULD" at %d\n", + fprintf(stderr, "peek int %" ULD " at %d\n", t->stack[(index * 2) + 1], index); } @@ -192,7 +192,7 @@ inline uint64_t peekLong(Thread* t, unsigned index) { if (DebugStack) { - fprintf(stderr, "peek long %"LLD" at %d\n", + fprintf(stderr, "peek long %" LLD " at %d\n", (static_cast(t->stack[(index * 2) + 1]) << 32) | static_cast(t->stack[((index + 1) * 2) + 1]), index); @@ -228,7 +228,7 @@ inline void pokeLong(Thread* t, unsigned index, uint64_t value) { if (DebugStack) { - fprintf(stderr, "poke long %"LLD" at %d\n", value, index); + fprintf(stderr, "poke long %" LLD " at %d\n", value, index); } pokeInt(t, index, value >> 32); @@ -461,7 +461,7 @@ pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect) case DoubleField: case LongField: if (DebugRun) { - fprintf(stderr, "result: %"LLD"\n", result); + fprintf(stderr, "result: %" LLD "\n", result); } pushLong(t, result); break; From de1f5c7b9fd0eb56ebe8b7cbe6617d83c6431705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Szymczyk?= Date: Tue, 4 Dec 2012 10:14:44 -0700 Subject: [PATCH 044/378] fix pthread mutex and condition leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi, I did some more tests with my x86 QNX Avian port and found one major problem in Avian VM while trying to run Apache Ivy. The problem manifests as follows: 1. MySystem::Thread X is created, during its creation pthread mutex and conditional variable are initialized 2. Program runs for some time 3. MySystem Thread X is disposed, it's memory is freed (during garbage collection I guess) 4. Program runs for some time 5. MySystem::Thread Y is created in exactly the same memory address as MySystem::Thread X disposed in step 3 (I suppose that's due to the way memory allocator works in Avian) 6. During MySystem::Thread Y creation pthread mutex and conditional variable initialization fail silently with EBUSY. QNX documentation says it means "The given mutex was previously initialized and hasn't been destroyed." which is correct, because it's exactly in the same memory address as mutex and conditional variable of MySystem::Thread X and they haven't been destroyed during MySystem::Thread X disposal Fortunately solution for this is easy, see the attached patch. Now Apache Ivy works without any problems. Regards, Stanisław Szymczyk --- src/posix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/posix.cpp b/src/posix.cpp index 1394a26886..da575eb8a4 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -173,6 +173,8 @@ class MySystem: public System { } virtual void dispose() { + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&condition); ::free(this); } From 36aa74316a7e8614e56af2311f44ad73e52f8ae3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 4 Dec 2012 17:37:02 -0700 Subject: [PATCH 045/378] fix Windows cross-compile build --- makefile | 11 +++++------ src/embed.cpp | 2 +- src/embedded-loader.cpp | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/makefile b/makefile index 8e494b5595..c1a2fb2b7b 100755 --- a/makefile +++ b/makefile @@ -496,7 +496,7 @@ ifeq ($(platform),windows) else shared += -Wl,--add-stdcall-alias endif - + embed = $(build-embed)/embed.exe embed-loader = $(build-embed-loader)/embed-loader.exe embed-loader-o = $(build-embed)/embed-loader.o @@ -1021,13 +1021,13 @@ endif ifdef embed $(embed): $(embed-objects) $(embed-loader-o) @echo "building $(embed)" - $(build-cxx) $(^) -mwindows -mconsole -static -o $(@) - + $(cxx) $(^) -mwindows -mconsole -static -o $(@) + $(build-embed)/%.o: $(src)/%.cpp @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(build-cxx) -D_UNICODE -DUNICODE -c $(<) -o $(@) - + $(cxx) -D_UNICODE -DUNICODE -c $(<) -o $(@) + $(embed-loader-o): $(embed-loader) $(converter) @mkdir -p $(dir $(@)) $(converter) $(<) $(@) _binary_loader_start \ @@ -1047,7 +1047,6 @@ $(build-embed-loader)/%.o: $(src)/%.cpp @mkdir -p $(dir $(@)) $(cxx) -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/win32 \ -D_JNI_IMPLEMENTATION_ -c $(<) -o $(@) - endif $(build)/%.o: $(lzma)/C/%.c diff --git a/src/embed.cpp b/src/embed.cpp index ed02731c1a..d47e4e98a9 100644 --- a/src/embed.cpp +++ b/src/embed.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include +#include #include #include #include diff --git a/src/embedded-loader.cpp b/src/embedded-loader.cpp index d34bb0bce0..0b0a2c90ab 100644 --- a/src/embedded-loader.cpp +++ b/src/embedded-loader.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include +#include #include #include @@ -102,4 +102,4 @@ main(int ac, const char** av) vm->DestroyJavaVM(); return exitCode; -} \ No newline at end of file +} From f79f32085972bbc7000994ea515d3b7983082503 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 5 Dec 2012 15:30:49 -0700 Subject: [PATCH 046/378] fix MSVC build regression --- makefile | 30 ++++++++++++++++++++++-------- src/embed.cpp | 8 +++++--- src/embed.h | 2 +- src/embedded-loader.cpp | 13 +++++++++---- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/makefile b/makefile index c1a2fb2b7b..f006ba0bf9 100755 --- a/makefile +++ b/makefile @@ -568,7 +568,10 @@ as := $(cc) ld := $(cc) build-ld := $(build-cc) +static = -static + ifdef msvc + static = no-error = windows-path = $(native-path) windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") @@ -591,7 +594,7 @@ ifdef msvc shared = -dll lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ - -DEFAULTLIB:zlib -MANIFEST -debug + -DEFAULTLIB:zlib -DEFAULTLIB:user32 -MANIFEST -debug output = -Fo$(1) ifeq ($(mode),debug) @@ -1021,12 +1024,18 @@ endif ifdef embed $(embed): $(embed-objects) $(embed-loader-o) @echo "building $(embed)" - $(cxx) $(^) -mwindows -mconsole -static -o $(@) +ifdef msvc + $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ + -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest + $(mt) -manifest $(@).manifest -outputresource:"$(@);1" +else + $(cxx) $(^) $(lflags) $(static) $(call output,$(@)) +endif $(build-embed)/%.o: $(src)/%.cpp @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) -D_UNICODE -DUNICODE -c $(<) -o $(@) + $(cxx) $(cflags) -c $(<) $(call output,$(@)) $(embed-loader-o): $(embed-loader) $(converter) @mkdir -p $(dir $(@)) @@ -1036,17 +1045,22 @@ $(embed-loader-o): $(embed-loader) $(converter) $(embed-loader): $(embed-loader-objects) $(static-library) @mkdir -p $(dir $(@)) cd $(dir $(@)) && $(ar) x ../../../$(static-library) +ifdef msvc + $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) -PDB:$(@).pdb \ + -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest + $(mt) -manifest $(@).manifest -outputresource:"$(@);1" +else $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(dir $(@))/*.o $(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@))) - $(cxx) $(addsuffix .exp,$(basename $(@))) $(dir $(@))/*.o -L../win32/lib -lmingwthrd -lm -lz -lws2_32 -liphlpapi \ - -mwindows -mconsole -static -o $(@) - strip --strip-all $(@) + $(ld) $(addsuffix .exp,$(basename $(@))) $(dir $(@))/*.o \ + $(lflags) $(bootimage-lflags) -o $(@) +endif + $(strip) $(strip-all) $(@) $(build-embed-loader)/%.o: $(src)/%.cpp @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/win32 \ - -D_JNI_IMPLEMENTATION_ -c $(<) -o $(@) + $(cxx) $(cflags) -c $(<) $(call output,$(@)) endif $(build)/%.o: $(lzma)/C/%.c diff --git a/src/embed.cpp b/src/embed.cpp index d47e4e98a9..a4a32bb6d7 100644 --- a/src/embed.cpp +++ b/src/embed.cpp @@ -74,12 +74,12 @@ bool mkStringSection(std::vector* stringSection, const std::vector& strings) { - for(int i = 0; i < strings.size(); i += 16) + for(unsigned i = 0; i < strings.size(); i += 16) { std::vector stringSection; if(mkStringSection(&stringSection, strings, i, std::min(i + 15, strings.size() - 1))) - UpdateResourceW(hDest, RT_STRING, MAKEINTRESOURCE((i >> 4) + 1), LANG_NEUTRAL, &stringSection.at(0), sizeof(wchar_t) * stringSection.size()); + UpdateResourceW(hDest, reinterpret_cast(RT_STRING), reinterpret_cast(MAKEINTRESOURCE((i >> 4) + 1)), LANG_NEUTRAL, &stringSection.at(0), sizeof(wchar_t) * stringSection.size()); } } @@ -104,7 +104,7 @@ int wmain(int argc, wchar_t* argv[]) std::vector jarFile; readFile(&jarFile, classesName); - UpdateResourceW(hDest, RT_RCDATA, _T(RESID_BOOT_JAR), LANG_NEUTRAL, &jarFile.at(0), jarFile.size()); + UpdateResourceW(hDest, reinterpret_cast(RT_RCDATA), RESID_BOOT_JAR, LANG_NEUTRAL, &jarFile.at(0), jarFile.size()); EndUpdateResource(hDest, FALSE); } @@ -113,6 +113,7 @@ int wmain(int argc, wchar_t* argv[]) return 0; } +#ifndef _MSC_VER extern "C" int _CRT_glob; extern "C" void __wgetmainargs(int*, wchar_t***, wchar_t***, int, int*); @@ -123,3 +124,4 @@ int main() __wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si); return wmain(argc, argv); } +#endif diff --git a/src/embed.h b/src/embed.h index a38108e64b..2f5b5f14ef 100644 --- a/src/embed.h +++ b/src/embed.h @@ -12,6 +12,6 @@ #define EMBED_H #define RESID_MAIN_CLASS 100 -#define RESID_BOOT_JAR "BOOT.JAR" +#define RESID_BOOT_JAR L"BOOT.JAR" #endif diff --git a/src/embedded-loader.cpp b/src/embedded-loader.cpp index 0b0a2c90ab..eb5b26f359 100644 --- a/src/embedded-loader.cpp +++ b/src/embedded-loader.cpp @@ -15,20 +15,25 @@ #include "embed.h" #include "jni.h" - #if (defined __MINGW32__) || (defined _MSC_VER) # define EXPORT __declspec(dllexport) +# ifdef _MSC_VER +# define not ! +# endif #else # define EXPORT __attribute__ ((visibility("default"))) \ __attribute__ ((used)) #endif extern "C" { + // since we aren't linking against libstdc++, we must implement this + // ourselves: + void __cxa_pure_virtual(void) { abort(); } EXPORT const uint8_t* bootJar(unsigned* size) { - if(HRSRC hResInfo = FindResource(NULL, _T(RESID_BOOT_JAR), RT_RCDATA)) + if(HRSRC hResInfo = FindResourceW(NULL, RESID_BOOT_JAR, reinterpret_cast(RT_RCDATA))) { if(HGLOBAL hRes = LoadResource(NULL, hResInfo)) { @@ -44,7 +49,7 @@ extern "C" { } } // extern "C" -static bool getMainClass(char* pName, int maxLen) +static void getMainClass(char* pName, int maxLen) { if(0 == LoadString(NULL, RESID_MAIN_CLASS, pName, maxLen)) { @@ -61,7 +66,7 @@ main(int ac, const char** av) vmArgs.nOptions = 1; vmArgs.ignoreUnrecognized = JNI_TRUE; - JavaVMOption options[vmArgs.nOptions]; + JavaVMOption options[1]; vmArgs.options = options; options[0].optionString = const_cast("-Xbootclasspath:[bootJar]"); From 663d8da975885d054f46c2e0c8cde64420b63112 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 12 Dec 2012 15:54:15 -0700 Subject: [PATCH 047/378] fix stack mapping bug for try blocks containing jsr/ret instructions In order to calculate the initial stack map of GC roots for an exception handler, we do a logical "and" of maps across all the instructions contained in the try block for that handler. This is complicated by the presence of jsr/ret instructions, though, because instructions in a subroutine may have multiple maps associated with them corresponding to all the paths from which execution might flow to them. The bug in this case was that we were using an uninitialized map in our calculation, resulting in a map with no GC roots at all. By the time the map was initialized, the damage had already been done. The solution is to treat an uninitialized map as if it has roots at all positions so that it has no effect on the calculation until it has been initialized with real data. --- src/compile.cpp | 2 +- test/Subroutine.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index 86432bb131..4c5df946d3 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -879,7 +879,7 @@ class TraceElement: public TraceHandler { flags(flags), watch(false) { - memset(map, 0, mapSize * BytesPerWord); + memset(map, 0xFF, mapSize * BytesPerWord); } virtual void handleTrace(Promise* address, unsigned argumentIndex) { diff --git a/test/Subroutine.java b/test/Subroutine.java index b02ec9ba81..d566f78095 100644 --- a/test/Subroutine.java +++ b/test/Subroutine.java @@ -15,6 +15,23 @@ public class Subroutine { if (! v) throw new RuntimeException(); } + private static void stackMap(Object x) { + while (true) { + try { + try { + System.gc(); + } catch (DummyException e) { + // ignore + } finally { + x.toString(); + } + break; + } catch (DummyException e) { + // ignore + } + } + } + private static byte[] makeTestCode(List pool) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); Stream.write2(out, 1); // max stack @@ -292,6 +309,8 @@ public class Subroutine { makeTestClass().getMethod("test", new Class[0]).invoke (null, new Object[0]); + + stackMap(new Object()); } private static class DummyException extends RuntimeException { } From 7b07b5b9a30d653767eae1f9b412f52f1a2010db Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 12 Dec 2012 16:04:26 -0700 Subject: [PATCH 048/378] print more of the stack map when DebugFrameMaps is enabled --- src/compile.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 4c5df946d3..6989d6446d 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -6595,11 +6595,11 @@ translateLineNumberTable(MyThread* t, Context* context, intptr_t start) } void -printSet(uintptr_t m, unsigned limit) +printSet(uintptr_t* m, unsigned limit) { if (limit) { - for (unsigned i = 0; i < 16; ++i) { - if ((m >> i) & 1) { + for (unsigned i = 0; i < 32; ++i) { + if ((*m >> i) & 1) { fprintf(stderr, "1"); } else { fprintf(stderr, "_"); @@ -6643,7 +6643,7 @@ calculateTryCatchRoots(Context* context, SubroutinePath* subroutinePath, if (traceRoots) { if (DebugFrameMaps) { fprintf(stderr, " use roots at ip %3d: ", te->ip); - printSet(*traceRoots, mapSize); + printSet(traceRoots, mapSize); fprintf(stderr, "\n"); } @@ -6660,7 +6660,7 @@ calculateTryCatchRoots(Context* context, SubroutinePath* subroutinePath, if (DebugFrameMaps) { fprintf(stderr, "result roots : "); - printSet(*roots, mapSize); + printSet(roots, mapSize); fprintf(stderr, "\n"); } } @@ -6714,7 +6714,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, if (DebugFrameMaps) { fprintf(stderr, " roots at ip %3d: ", ip); - printSet(*RUNTIME_ARRAY_BODY(roots), mapSize); + printSet(RUNTIME_ARRAY_BODY(roots), mapSize); fprintf(stderr, "\n"); } @@ -6743,7 +6743,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, if (DebugFrameMaps) { fprintf(stderr, " table roots at ip %3d: ", ip); - printSet(*tableRoots, mapSize); + printSet(tableRoots, mapSize); fprintf(stderr, "\n"); } } else { @@ -6797,7 +6797,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, TraceElement* te; context->eventLog.get(eventIndex, &te, BytesPerWord); if (DebugFrameMaps) { fprintf(stderr, " trace roots at ip %3d: ", ip); - printSet(*RUNTIME_ARRAY_BODY(roots), mapSize); + printSet(RUNTIME_ARRAY_BODY(roots), mapSize); if (subroutinePath) { fprintf(stderr, " "); print(subroutinePath); @@ -6896,7 +6896,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, if (resultRoots and ip != -1) { if (DebugFrameMaps) { fprintf(stderr, "result roots at ip %3d: ", ip); - printSet(*RUNTIME_ARRAY_BODY(roots), mapSize); + printSet(RUNTIME_ARRAY_BODY(roots), mapSize); if (subroutinePath) { fprintf(stderr, " "); print(subroutinePath); @@ -6965,7 +6965,7 @@ copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits, { if (DebugFrameMaps) { fprintf(stderr, " orig roots at ip %3d: ", p->ip); - printSet(src[0], ceiling(mapSizeInBits, BitsPerWord)); + printSet(src, ceiling(mapSizeInBits, BitsPerWord)); print(subroutinePath); fprintf(stderr, "\n"); From d200019d10ed47f02683270bce25e7a64b36a3ee Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 19 Dec 2012 12:39:33 -0700 Subject: [PATCH 049/378] implement JNI reflection methods These include FromReflectedMethod, ToReflectedMethod, FromReflectedField, and ToReflectedField. --- src/classpath-avian.cpp | 31 +++ src/classpath-openjdk.cpp | 401 ++++++++++++++++++++++++-------------- src/jnienv.cpp | 80 ++++++++ src/machine.h | 12 ++ test/JNI.java | 53 ++++- test/jni.cpp | 44 +++++ 6 files changed, 476 insertions(+), 145 deletions(-) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index ddef6c36de..703332c518 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -54,6 +54,37 @@ class MyClasspath : public Classpath { root(t, Machine::BootLoader), 0, 0, group, 0); } + virtual object + makeJMethod(Thread* t, object vmMethod) + { + PROTECT(t, vmMethod); + + object jmethod = makeJmethod(t, vmMethod, false); + + return byteArrayBody(t, methodName(t, vmMethod), 0) == '<' + ? makeJconstructor(t, jmethod) : jmethod; + } + + virtual object + getVMMethod(Thread* t, object jmethod) + { + return objectClass(t, jmethod) == type(t, Machine::JmethodType) + ? jmethodVmMethod(t, jmethod) + : jmethodVmMethod(t, jconstructorMethod(t, jmethod)); + } + + virtual object + makeJField(Thread* t, object vmField) + { + return makeJfield(t, vmField, false); + } + + virtual object + getVMField(Thread* t, object jfield) + { + return jfieldVmField(t, jfield); + } + virtual void clearInterrupted(Thread*) { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index bb505051d9..b06211777f 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -341,6 +341,15 @@ makeClassNameString(Thread* t, object name) return makeString(t, "%s", s); } +object +makeJmethod(Thread* t, object vmMethod, int index = -1); + +object +makeJconstructor(Thread* t, object vmMethod, int index = -1); + +object +makeJfield(Thread* t, object vmField, int index = -1); + void interceptFileOperations(Thread*); @@ -537,6 +546,44 @@ class MyClasspath : public Classpath { return thread; } + virtual object + makeJMethod(Thread* t, object vmMethod) + { + PROTECT(t, vmMethod); + + return byteArrayBody(t, methodName(t, vmMethod), 0) == '<' + ? makeJconstructor(t, vmMethod) + : makeJmethod(t, vmMethod); + } + + virtual object + getVMMethod(Thread* t, object jmethod) + { + return objectClass(t, jmethod) == type(t, Machine::JmethodType) + ? arrayBody + (t, classMethodTable + (t, jclassVmClass(t, jmethodClazz(t, jmethod))), + jmethodSlot(t, jmethod)) + : arrayBody + (t, classMethodTable + (t, jclassVmClass(t, jconstructorClazz(t, jmethod))), + jconstructorSlot(t, jmethod)); + } + + virtual object + makeJField(Thread* t, object vmField) + { + return makeJfield(t, vmField); + } + + virtual object + getVMField(Thread* t, object jfield) + { + return arrayBody + (t, classFieldTable + (t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield)); + } + virtual void clearInterrupted(Thread* t) { @@ -2260,6 +2307,213 @@ resolveExceptionJTypes(Thread* t, object loader, object addendum) return array; } +object +makeJmethod(Thread* t, object vmMethod, int index) +{ + PROTECT(t, vmMethod); + + object name = intern + (t, t->m->classpath->makeString + (t, methodName(t, vmMethod), 0, byteArrayLength + (t, methodName(t, vmMethod)) - 1)); + PROTECT(t, name); + + unsigned parameterCount; + unsigned returnTypeSpec; + object parameterTypes = local::resolveParameterJTypes + (t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod), + ¶meterCount, &returnTypeSpec); + PROTECT(t, parameterTypes); + + object returnType = local::resolveJType + (t, classLoader(t, methodClass(t, vmMethod)), reinterpret_cast + (&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)), + byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec); + PROTECT(t, returnType); + + object exceptionTypes = local::resolveExceptionJTypes + (t, classLoader(t, methodClass(t, vmMethod)), + methodAddendum(t, vmMethod)); + PROTECT(t, exceptionTypes); + + object signature; + object annotationTable; + object annotationDefault; + object addendum = methodAddendum(t, vmMethod); + if (addendum) { + signature = addendumSignature(t, addendum); + if (signature) { + signature = t->m->classpath->makeString + (t, signature, 0, byteArrayLength(t, signature) - 1); + } + + annotationTable = addendumAnnotationTable(t, addendum); + + annotationDefault = methodAddendumAnnotationDefault(t, addendum); + } else { + signature = 0; + annotationTable = 0; + annotationDefault = 0; + } + + PROTECT(t, signature); + PROTECT(t, annotationTable); + PROTECT(t, annotationDefault); + + if (annotationTable or annotationDefault) { + object runtimeData = getClassRuntimeData(t, methodClass(t, vmMethod)); + + set(t, runtimeData, ClassRuntimeDataPool, + addendumPool(t, methodAddendum(t, vmMethod))); + } + + if (index == -1) { + object table = classMethodTable(t, methodClass(t, vmMethod)); + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (vmMethod == arrayBody(t, table, i)) { + index = i; + break; + } + } + } + + expect(t, index != -1); + + object jclass = getJClass(t, methodClass(t, vmMethod)); + + return makeJmethod + (t, true, 0, jclass, index, name, returnType, parameterTypes, + exceptionTypes, methodFlags(t, vmMethod), signature, 0, annotationTable, + 0, annotationDefault, 0, 0, 0); +} + +object +makeJconstructor(Thread* t, object vmMethod, int index) +{ + PROTECT(t, vmMethod); + + unsigned parameterCount; + unsigned returnTypeSpec; + object parameterTypes = local::resolveParameterJTypes + (t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod), + ¶meterCount, &returnTypeSpec); + PROTECT(t, parameterTypes); + + object exceptionTypes = local::resolveExceptionJTypes + (t, classLoader(t, methodClass(t, vmMethod)), + methodAddendum(t, vmMethod)); + PROTECT(t, exceptionTypes); + + object signature; + object annotationTable; + object addendum = methodAddendum(t, vmMethod); + if (addendum) { + signature = addendumSignature(t, addendum); + if (signature) { + signature = t->m->classpath->makeString + (t, signature, 0, byteArrayLength(t, signature) - 1); + } + + annotationTable = addendumAnnotationTable(t, addendum); + } else { + signature = 0; + annotationTable = 0; + } + + PROTECT(t, signature); + PROTECT(t, annotationTable); + + if (annotationTable) { + object runtimeData = getClassRuntimeData(t, methodClass(t, vmMethod)); + + set(t, runtimeData, ClassRuntimeDataPool, + addendumPool(t, methodAddendum(t, vmMethod))); + } + + if (index == -1) { + object table = classMethodTable(t, methodClass(t, vmMethod)); + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (vmMethod == arrayBody(t, table, i)) { + index = i; + break; + } + } + } + + expect(t, index != -1); + + object jclass = getJClass(t, methodClass(t, vmMethod)); + + return makeJconstructor + (t, true, 0, jclass, index, parameterTypes, exceptionTypes, methodFlags + (t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0); +} + +object +makeJfield(Thread* t, object vmField, int index) +{ + PROTECT(t, vmField); + + object name = intern + (t, t->m->classpath->makeString + (t, fieldName(t, vmField), 0, byteArrayLength + (t, fieldName(t, vmField)) - 1)); + PROTECT(t, name); + + object type = local::resolveClassBySpec + (t, classLoader(t, fieldClass(t, vmField)), + reinterpret_cast + (&byteArrayBody(t, fieldSpec(t, vmField), 0)), + byteArrayLength(t, fieldSpec(t, vmField)) - 1); + PROTECT(t, type); + + type = getJClass(t, type); + + object signature; + object annotationTable; + object addendum = fieldAddendum(t, vmField); + if (addendum) { + signature = addendumSignature(t, addendum); + if (signature) { + signature = t->m->classpath->makeString + (t, signature, 0, byteArrayLength(t, signature) - 1); + } + + annotationTable = addendumAnnotationTable(t, addendum); + } else { + signature = 0; + annotationTable = 0; + } + + PROTECT(t, signature); + PROTECT(t, annotationTable); + + if (annotationTable) { + object runtimeData = getClassRuntimeData(t, fieldClass(t, vmField)); + + set(t, runtimeData, ClassRuntimeDataPool, + addendumPool(t, fieldAddendum(t, vmField))); + } + + if (index == -1) { + object table = classFieldTable(t, fieldClass(t, vmField)); + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (vmField == arrayBody(t, table, i)) { + index = i; + break; + } + } + } + + expect(t, index != -1); + + object jclass = getJClass(t, fieldClass(t, vmField)); + + return makeJfield + (t, true, 0, jclass, index, name, type, fieldFlags + (t, vmField), signature, 0, annotationTable, 0, 0, 0, 0); +} + void setProperty(Thread* t, object method, object properties, const char* name, const void* value, const char* format = "%s") @@ -4380,65 +4634,7 @@ jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments) if (((not publicOnly) or (methodFlags(t, vmMethod) & ACC_PUBLIC)) and byteArrayBody(t, methodName(t, vmMethod), 0) != '<') { - object name = intern - (t, t->m->classpath->makeString - (t, methodName(t, vmMethod), 0, byteArrayLength - (t, methodName(t, vmMethod)) - 1)); - PROTECT(t, name); - - unsigned parameterCount; - unsigned returnTypeSpec; - object parameterTypes = local::resolveParameterJTypes - (t, classLoader(t, jclassVmClass(t, *c)), methodSpec(t, vmMethod), - ¶meterCount, &returnTypeSpec); - PROTECT(t, parameterTypes); - - object returnType = local::resolveJType - (t, classLoader(t, jclassVmClass(t, *c)), reinterpret_cast - (&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)), - byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec); - PROTECT(t, returnType); - - object exceptionTypes = local::resolveExceptionJTypes - (t, classLoader(t, jclassVmClass(t, *c)), - methodAddendum(t, vmMethod)); - PROTECT(t, exceptionTypes); - - object signature; - object annotationTable; - object annotationDefault; - object addendum = methodAddendum(t, vmMethod); - if (addendum) { - signature = addendumSignature(t, addendum); - if (signature) { - signature = t->m->classpath->makeString - (t, signature, 0, byteArrayLength(t, signature) - 1); - } - - annotationTable = addendumAnnotationTable(t, addendum); - - annotationDefault = methodAddendumAnnotationDefault(t, addendum); - } else { - signature = 0; - annotationTable = 0; - annotationDefault = 0; - } - - if (annotationTable or annotationDefault) { - PROTECT(t, signature); - PROTECT(t, annotationTable); - PROTECT(t, annotationDefault); - - object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c)); - - set(t, runtimeData, ClassRuntimeDataPool, - addendumPool(t, methodAddendum(t, vmMethod))); - } - - object method = makeJmethod - (t, true, 0, *c, i, name, returnType, parameterTypes, exceptionTypes, - methodFlags(t, vmMethod), signature, 0, annotationTable, 0, - annotationDefault, 0, 0, 0); + object method = makeJmethod(t, vmMethod, i); assert(t, ai < objectArrayLength(t, array)); @@ -4483,50 +4679,7 @@ jvmGetClassDeclaredFields(Thread* t, uintptr_t* arguments) PROTECT(t, vmField); if ((not publicOnly) or (fieldFlags(t, vmField) & ACC_PUBLIC)) { - object name = intern - (t, t->m->classpath->makeString - (t, fieldName(t, vmField), 0, byteArrayLength - (t, fieldName(t, vmField)) - 1)); - PROTECT(t, name); - - object type = local::resolveClassBySpec - (t, classLoader(t, jclassVmClass(t, *c)), - reinterpret_cast - (&byteArrayBody(t, fieldSpec(t, vmField), 0)), - byteArrayLength(t, fieldSpec(t, vmField)) - 1); - PROTECT(t, type); - - type = getJClass(t, type); - - object signature; - object annotationTable; - object addendum = fieldAddendum(t, vmField); - if (addendum) { - signature = addendumSignature(t, addendum); - if (signature) { - signature = t->m->classpath->makeString - (t, signature, 0, byteArrayLength(t, signature) - 1); - } - - annotationTable = addendumAnnotationTable(t, addendum); - } else { - signature = 0; - annotationTable = 0; - } - - if (annotationTable) { - PROTECT(t, signature); - PROTECT(t, annotationTable); - - object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c)); - - set(t, runtimeData, ClassRuntimeDataPool, - addendumPool(t, fieldAddendum(t, vmField))); - } - - object field = makeJfield - (t, true, 0, *c, i, name, type, fieldFlags - (t, vmField), signature, 0, annotationTable, 0, 0, 0, 0); + object field = makeJfield(t, vmField, i); assert(t, ai < objectArrayLength(t, array)); @@ -4577,47 +4730,7 @@ jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments) (&byteArrayBody(t, methodName(t, vmMethod), 0)), "") == 0) { - unsigned parameterCount; - unsigned returnTypeSpec; - object parameterTypes = local::resolveParameterJTypes - (t, classLoader(t, jclassVmClass(t, *c)), methodSpec(t, vmMethod), - ¶meterCount, &returnTypeSpec); - PROTECT(t, parameterTypes); - - object exceptionTypes = local::resolveExceptionJTypes - (t, classLoader(t, jclassVmClass(t, *c)), - methodAddendum(t, vmMethod)); - PROTECT(t, exceptionTypes); - - object signature; - object annotationTable; - object addendum = methodAddendum(t, vmMethod); - if (addendum) { - signature = addendumSignature(t, addendum); - if (signature) { - signature = t->m->classpath->makeString - (t, signature, 0, byteArrayLength(t, signature) - 1); - } - - annotationTable = addendumAnnotationTable(t, addendum); - } else { - signature = 0; - annotationTable = 0; - } - - if (annotationTable) { - PROTECT(t, signature); - PROTECT(t, annotationTable); - - object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c)); - - set(t, runtimeData, ClassRuntimeDataPool, - addendumPool(t, methodAddendum(t, vmMethod))); - } - - object method = makeJconstructor - (t, true, 0, *c, i, parameterTypes, exceptionTypes, methodFlags - (t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0); + object method = makeJconstructor(t, vmMethod, i); assert(t, ai < objectArrayLength(t, array)); diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 12a32fb3f5..289c955bc3 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3154,6 +3154,82 @@ ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint) } } +uint64_t +fromReflectedMethod(Thread* t, uintptr_t* arguments) +{ + jobject m = reinterpret_cast(arguments[0]); + + return methodID(t, t->m->classpath->getVMMethod(t, *m)); +} + +jmethodID JNICALL +FromReflectedMethod(Thread* t, jobject method) +{ + uintptr_t arguments[] = { reinterpret_cast(method) }; + + return reinterpret_cast(run(t, fromReflectedMethod, arguments)); +} + +uint64_t +toReflectedMethod(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[1]; + jboolean isStatic = arguments[2]; + + return reinterpret_cast + (makeLocalReference + (t, t->m->classpath->makeJMethod + (t, isStatic ? getStaticMethod(t, m) : getMethod(t, m)))); +} + +jobject JNICALL +ToReflectedMethod(Thread* t, jclass c, jmethodID method, jboolean isStatic) +{ + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(method), + static_cast(isStatic) }; + + return reinterpret_cast(run(t, toReflectedMethod, arguments)); +} + +uint64_t +fromReflectedField(Thread* t, uintptr_t* arguments) +{ + jobject f = reinterpret_cast(arguments[0]); + + return fieldID(t, t->m->classpath->getVMField(t, *f)); +} + +jfieldID JNICALL +FromReflectedField(Thread* t, jobject field) +{ + uintptr_t arguments[] = { reinterpret_cast(field) }; + + return reinterpret_cast(run(t, fromReflectedField, arguments)); +} + +uint64_t +toReflectedField(Thread* t, uintptr_t* arguments) +{ + jfieldID f = arguments[1]; + jboolean isStatic = arguments[2]; + + return reinterpret_cast + (makeLocalReference + (t, t->m->classpath->makeJField + (t, isStatic ? getStaticField(t, f) : getField(t, f)))); +} + +jobject JNICALL +ToReflectedField(Thread* t, jclass c, jfieldID field, jboolean isStatic) +{ + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(field), + static_cast(isStatic) }; + + return reinterpret_cast(run(t, toReflectedField, arguments)); +} + uint64_t registerNatives(Thread* t, uintptr_t* arguments) { @@ -3607,6 +3683,10 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) envTable->IsSameObject = local::IsSameObject; envTable->PushLocalFrame = local::PushLocalFrame; envTable->PopLocalFrame = local::PopLocalFrame; + envTable->FromReflectedMethod = local::FromReflectedMethod; + envTable->ToReflectedMethod = local::ToReflectedMethod; + envTable->FromReflectedField = local::FromReflectedField; + envTable->ToReflectedField = local::ToReflectedField; } } // namespace vm diff --git a/src/machine.h b/src/machine.h index 52233cab3c..f71788572d 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1536,6 +1536,18 @@ class Classpath { virtual object makeThread(Thread* t, Thread* parent) = 0; + virtual object + makeJMethod(Thread* t, object vmMethod) = 0; + + virtual object + getVMMethod(Thread* t, object jmethod) = 0; + + virtual object + makeJField(Thread* t, object vmField) = 0; + + virtual object + getVMField(Thread* t, object jfield) = 0; + virtual void clearInterrupted(Thread* t) = 0; diff --git a/test/JNI.java b/test/JNI.java index b4e93c0f75..cbb17cc925 100644 --- a/test/JNI.java +++ b/test/JNI.java @@ -1,3 +1,7 @@ +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; + public class JNI { static { System.loadLibrary("test"); @@ -37,7 +41,27 @@ public class JNI { float a13, float a14, float a15, double a16, float a17, float a18, float a19, float a20); - public static void main(String[] args) { + private static native long fromReflectedMethod(Object m); + + private static native Object toReflectedMethod(Class c, long id, + boolean isStatic); + + private static native int callStaticIntMethod(Class c, long id); + + private static native Object newObject(Class c, long id); + + private static native long fromReflectedField(Field f); + + private static native Field toReflectedField(Class c, long id, + boolean isStatic); + + private static native int getStaticIntField(Class c, long id); + + public static int method242() { return 242; } + + public static final int field950 = 950; + + public static void main(String[] args) throws Exception { expect(addDoubles (1.0d, 2.0d, 3.0d, 4.0d, 5.0d, 6.0d, 7.0d, 8.0d, 9.0d, 10.0d, 11.0d, 12.0d, 13.0d, 14.0d, 15.0d, 16.0d, 17.0d, 18.0d, 19.0d, 20.0d) @@ -55,5 +79,32 @@ public class JNI { expect(doEcho(42.0f) == 42.0f); expect(doEcho(42.0d) == 42.0d); + + expect(callStaticIntMethod + (JNI.class, fromReflectedMethod + (JNI.class.getMethod("method242"))) == 242); + + expect(((Method) toReflectedMethod + (JNI.class, fromReflectedMethod + (JNI.class.getMethod("method242")), true)) + .getName().equals("method242")); + + expect(newObject + (JNI.class, fromReflectedMethod + (JNI.class.getConstructor())) instanceof JNI); + + expect(((Constructor) toReflectedMethod + (JNI.class, fromReflectedMethod + (JNI.class.getConstructor()), false)) + .getDeclaringClass().equals(JNI.class)); + + expect(getStaticIntField + (JNI.class, fromReflectedField + (JNI.class.getField("field950"))) == 950); + + expect(toReflectedField + (JNI.class, fromReflectedField + (JNI.class.getField("field950")), true) + .getName().equals("field950")); } } diff --git a/test/jni.cpp b/test/jni.cpp index fe174edec9..eacf9e31bc 100644 --- a/test/jni.cpp +++ b/test/jni.cpp @@ -57,6 +57,50 @@ Java_JNI_doEcho__D(JNIEnv* e, jclass c, jdouble f) (c, e->GetStaticMethodID(c, "echo", "(D)D"), array); } +extern "C" JNIEXPORT jlong JNICALL +Java_JNI_fromReflectedMethod(JNIEnv* e, jclass, jobject method) +{ + return reinterpret_cast(e->FromReflectedMethod(method)); +} + +extern "C" JNIEXPORT jobject JNICALL +Java_JNI_toReflectedMethod(JNIEnv* e, jclass, jclass c, jlong id, + jboolean isStatic) +{ + return e->ToReflectedMethod(c, reinterpret_cast(id), isStatic); +} + +extern "C" JNIEXPORT jint JNICALL +Java_JNI_callStaticIntMethod(JNIEnv* e, jclass, jclass c, jlong id) +{ + return e->CallStaticIntMethod(c, reinterpret_cast(id)); +} + +extern "C" JNIEXPORT jobject JNICALL +Java_JNI_newObject(JNIEnv* e, jclass, jclass c, jlong id) +{ + return e->NewObject(c, reinterpret_cast(id)); +} + +extern "C" JNIEXPORT jlong JNICALL +Java_JNI_fromReflectedField(JNIEnv* e, jclass, jobject field) +{ + return reinterpret_cast(e->FromReflectedField(field)); +} + +extern "C" JNIEXPORT jobject JNICALL +Java_JNI_toReflectedField(JNIEnv* e, jclass, jclass c, jlong id, + jboolean isStatic) +{ + return e->ToReflectedField(c, reinterpret_cast(id), isStatic); +} + +extern "C" JNIEXPORT jint JNICALL +Java_JNI_getStaticIntField(JNIEnv* e, jclass, jclass c, jlong id) +{ + return e->GetStaticIntField(c, reinterpret_cast(id)); +} + extern "C" JNIEXPORT jobject JNICALL Java_Buffers_allocateNative(JNIEnv* e, jclass, jint capacity) { From 5d36fd84cd0566ac36a1c5ea13515b53f2e08796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Elton=20S=C3=B8rensen?= Date: Wed, 19 Dec 2012 23:08:50 +0100 Subject: [PATCH 050/378] Changed reinterpret_cast to static_cast --- src/jnienv.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 289c955bc3..15631e51e4 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3167,7 +3167,7 @@ FromReflectedMethod(Thread* t, jobject method) { uintptr_t arguments[] = { reinterpret_cast(method) }; - return reinterpret_cast(run(t, fromReflectedMethod, arguments)); + return static_cast(run(t, fromReflectedMethod, arguments)); } uint64_t @@ -3205,7 +3205,7 @@ FromReflectedField(Thread* t, jobject field) { uintptr_t arguments[] = { reinterpret_cast(field) }; - return reinterpret_cast(run(t, fromReflectedField, arguments)); + return static_cast(run(t, fromReflectedField, arguments)); } uint64_t From 1094483a7c2d14cdd803d142e69b6b4d8b8aa3aa Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 19 Dec 2012 16:48:20 -0700 Subject: [PATCH 051/378] fix 32-bit build regression --- src/jnienv.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 289c955bc3..9d73a233df 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3167,7 +3167,7 @@ FromReflectedMethod(Thread* t, jobject method) { uintptr_t arguments[] = { reinterpret_cast(method) }; - return reinterpret_cast(run(t, fromReflectedMethod, arguments)); + return static_cast(run(t, fromReflectedMethod, arguments)); } uint64_t @@ -3186,7 +3186,7 @@ jobject JNICALL ToReflectedMethod(Thread* t, jclass c, jmethodID method, jboolean isStatic) { uintptr_t arguments[] = { reinterpret_cast(c), - reinterpret_cast(method), + static_cast(method), static_cast(isStatic) }; return reinterpret_cast(run(t, toReflectedMethod, arguments)); @@ -3205,7 +3205,7 @@ FromReflectedField(Thread* t, jobject field) { uintptr_t arguments[] = { reinterpret_cast(field) }; - return reinterpret_cast(run(t, fromReflectedField, arguments)); + return static_cast(run(t, fromReflectedField, arguments)); } uint64_t @@ -3224,7 +3224,7 @@ jobject JNICALL ToReflectedField(Thread* t, jclass c, jfieldID field, jboolean isStatic) { uintptr_t arguments[] = { reinterpret_cast(c), - reinterpret_cast(field), + static_cast(field), static_cast(isStatic) }; return reinterpret_cast(run(t, toReflectedField, arguments)); From 4a98b6ac1368ae8596cf3698574e92d9c54b5f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Elton=20S=C3=B8rensen?= Date: Thu, 20 Dec 2012 08:52:05 +0100 Subject: [PATCH 052/378] Fixed compiler error casts --- src/jnienv.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 15631e51e4..9d73a233df 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3186,7 +3186,7 @@ jobject JNICALL ToReflectedMethod(Thread* t, jclass c, jmethodID method, jboolean isStatic) { uintptr_t arguments[] = { reinterpret_cast(c), - reinterpret_cast(method), + static_cast(method), static_cast(isStatic) }; return reinterpret_cast(run(t, toReflectedMethod, arguments)); @@ -3224,7 +3224,7 @@ jobject JNICALL ToReflectedField(Thread* t, jclass c, jfieldID field, jboolean isStatic) { uintptr_t arguments[] = { reinterpret_cast(c), - reinterpret_cast(field), + static_cast(field), static_cast(isStatic) }; return reinterpret_cast(run(t, toReflectedField, arguments)); From b75497c8ffbfae5eed0c1372530d8c412cb4feff Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 20 Dec 2012 09:05:30 -0700 Subject: [PATCH 053/378] implement JNIEnv::NewLocalRef --- src/jnienv.cpp | 9 +++++++++ test/JNI.java | 6 ++++++ test/jni.cpp | 6 ++++++ 3 files changed, 21 insertions(+) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 9d73a233df..f8a0ff3987 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -396,6 +396,14 @@ Throw(Thread* t, jthrowable throwable) return 0; } +jobject JNICALL +NewLocalRef(Thread* t, jobject o) +{ + ENTER(t, Thread::ActiveState); + + return makeLocalReference(t, *o); +} + void JNICALL DeleteLocalRef(Thread* t, jobject r) { @@ -3513,6 +3521,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) envTable->NewDirectByteBuffer = local::NewDirectByteBuffer; envTable->GetDirectBufferAddress = local::GetDirectBufferAddress; envTable->GetDirectBufferCapacity = local::GetDirectBufferCapacity; + envTable->NewLocalRef = local::NewLocalRef; envTable->DeleteLocalRef = local::DeleteLocalRef; envTable->GetObjectClass = local::GetObjectClass; envTable->GetSuperclass = local::GetSuperclass; diff --git a/test/JNI.java b/test/JNI.java index cbb17cc925..955bfc9052 100644 --- a/test/JNI.java +++ b/test/JNI.java @@ -57,6 +57,8 @@ public class JNI { private static native int getStaticIntField(Class c, long id); + private static native Object testLocalRef(Object o); + public static int method242() { return 242; } public static final int field950 = 950; @@ -106,5 +108,9 @@ public class JNI { (JNI.class, fromReflectedField (JNI.class.getField("field950")), true) .getName().equals("field950")); + + { Object o = new Object(); + expect(testLocalRef(o) == o); + } } } diff --git a/test/jni.cpp b/test/jni.cpp index eacf9e31bc..8b8d6dc8c9 100644 --- a/test/jni.cpp +++ b/test/jni.cpp @@ -101,6 +101,12 @@ Java_JNI_getStaticIntField(JNIEnv* e, jclass, jclass c, jlong id) return e->GetStaticIntField(c, reinterpret_cast(id)); } +extern "C" JNIEXPORT jobject JNICALL +Java_JNI_testLocalRef(JNIEnv* e, jclass, jobject o) +{ + return e->NewLocalRef(o); +} + extern "C" JNIEXPORT jobject JNICALL Java_Buffers_allocateNative(JNIEnv* e, jclass, jint capacity) { From 9f22a701cc26b68a597e78faf652124fab25fec9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 20 Dec 2012 12:25:13 -0700 Subject: [PATCH 054/378] load libmawt.so proactively when booting the VM for OpenJDK This library is placed in the xawt subdirectory of jre/lib/$arch on POSIX systems, so it isn't found automatically when third-party libraries which depend on it are loaded. The simplest way to ensure that it's found seems to be to just load it when the VM starts up. --- src/classpath-openjdk.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index b06211777f..4842ab8581 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -439,17 +439,20 @@ class MyClasspath : public Classpath { unsigned libraryPathOffset = sb.offset; sb.append(javaHome); #ifdef PLATFORM_WINDOWS - sb.append("/bin"); +# define LIB_DIR "/bin" #elif defined __APPLE__ - sb.append("/lib"); +# define LIB_DIR "/lib" #elif defined ARCH_x86_64 - sb.append("/lib/amd64"); +# define LIB_DIR "/lib/amd64" #elif defined ARCH_arm - sb.append("/lib/arm"); +# define LIB_DIR "/lib/arm" #else // todo: handle other architectures - sb.append("/lib/i386"); +# define LIB_DIR "/lib/i386" #endif + sb.append(LIB_DIR ":"); + sb.append(javaHome); + sb.append(LIB_DIR "/xawt"); sb.append('\0'); unsigned tzMappingsOffset = sb.offset; @@ -635,6 +638,7 @@ class MyClasspath : public Classpath { #else // not AVIAN_OPENJDK_SRC expect(t, loadLibrary(t, libraryPath, "verify", true, true)); expect(t, loadLibrary(t, libraryPath, "java", true, true)); + loadLibrary(t, libraryPath, "mawt", true, true); #endif // not AVIAN_OPENJDK_SRC { object assertionLock = resolveField From 5f66f7396171f65d576acbbce815070bbedcd1f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Elton=20S=C3=B8rensen?= Date: Fri, 21 Dec 2012 09:56:21 +0100 Subject: [PATCH 055/378] Handle null pointer in PopLocalFrame --- src/jnienv.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index f8a0ff3987..2a70b10855 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3370,12 +3370,21 @@ PushLocalFrame(Thread* t, jint capacity) uint64_t popLocalFrame(Thread* t, uintptr_t* arguments) { - object result = *reinterpret_cast(arguments[0]); - PROTECT(t, result); + uint64_t r; + jobject presult = reinterpret_cast(arguments[0]); + if(presult != NULL) { + object result = *presult; + PROTECT(t, result); - t->m->processor->popLocalFrame(t); - - return reinterpret_cast(makeLocalReference(t, result)); + t->m->processor->popLocalFrame(t); + + r = reinterpret_cast(makeLocalReference(t, result)); + } else { + t->m->processor->popLocalFrame(t); + r = 0; + } + + return r; } jobject JNICALL From 887a32bc108bf6c9f8af7bf0d7b5f468ebf41ad7 Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Fri, 21 Dec 2012 14:18:41 +0100 Subject: [PATCH 056/378] Added some members that should not be removed or renamed --- openjdk.pro | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/openjdk.pro b/openjdk.pro index d0b8de812f..3ffce4f58f 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -246,3 +246,39 @@ } -keep class sun.net.www.protocol.jar.Handler + +# These concurrent classes refer to certain members reflectively in their static initializers +-keepclassmembers class java.util.concurrent.ConcurrentHashMap$HashEntry { + *** next; +} + +-keepclassmembers class java.util.concurrent.CopyOnWriteArrayList { + *** lock; +} + +-keepclassmembers class java.util.concurrent.CountDownLatch { + *** allocationSpinLock; +} + +-keepclassmembers class java.util.concurrent.PriorityBlockingQueue { + *** allocationSpinLock; +} + +-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack { + *** head; +} + +-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue { + *** head; + *** tail; +} + +-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue$Node { + *** item; + *** next; +} + +-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack$SNode { + *** match; + *** next; +} \ No newline at end of file From cad4719f7dcf2d239b3b39afd3cc7943503dbd4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Elton=20S=C3=B8rensen?= Date: Fri, 21 Dec 2012 09:56:21 +0100 Subject: [PATCH 057/378] Handle null pointer in PopLocalFrame --- src/jnienv.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index f8a0ff3987..2a70b10855 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3370,12 +3370,21 @@ PushLocalFrame(Thread* t, jint capacity) uint64_t popLocalFrame(Thread* t, uintptr_t* arguments) { - object result = *reinterpret_cast(arguments[0]); - PROTECT(t, result); + uint64_t r; + jobject presult = reinterpret_cast(arguments[0]); + if(presult != NULL) { + object result = *presult; + PROTECT(t, result); - t->m->processor->popLocalFrame(t); - - return reinterpret_cast(makeLocalReference(t, result)); + t->m->processor->popLocalFrame(t); + + r = reinterpret_cast(makeLocalReference(t, result)); + } else { + t->m->processor->popLocalFrame(t); + r = 0; + } + + return r; } jobject JNICALL From 5061d7fe4df365e8ca4f00511e782a4c08d7ed2d Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 25 Dec 2012 18:12:03 -0700 Subject: [PATCH 058/378] Making Thread's isInterrupted() non-static and make it use the current instance's interrupted variable. --- classpath/java/lang/Thread.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 936351c809..3abfd3238e 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -151,8 +151,8 @@ public class Thread implements Runnable { private static native boolean interrupted(long peer); - public static boolean isInterrupted() { - return currentThread().interrupted; + public boolean isInterrupted() { + return interrupted; } public static void sleep(long milliseconds) throws InterruptedException { From a0cd542fcfddd5f8a5da3637ce3df84c4bfa767c Mon Sep 17 00:00:00 2001 From: Seth Goings Date: Wed, 26 Dec 2012 15:30:45 -0700 Subject: [PATCH 059/378] Update readme.txt --- readme.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index e9185b2c85..213c138485 100644 --- a/readme.txt +++ b/readme.txt @@ -12,13 +12,13 @@ on Mac OS X: $ build/darwin-i386/avian -cp build/darwin-i386/test Hello on Windows (MSYS): - $ git clone git://oss.readytalk.com/win32.git ../win32 + $ git clone git@github.com:ReadyTalk/win32.git ../win32 $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" $ make $ build/windows-i386/avian -cp build/windows-i386/test Hello on Windows (Cygwin): - $ git clone git://oss.readytalk.com/win32.git ../win32 + $ git clone git@github.com:ReadyTalk/win32.git ../win32 $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" $ make $ build/windows-i386/avian -cp build/windows-i386/test Hello @@ -191,13 +191,13 @@ Installing Cygwin: You may also find our win32 repository useful: (run this from the directory containing the avian directory) - $ git clone git://oss.readytalk.com/win32.git + $ git clone git@github.com:ReadyTalk/win32.git This gives you the Windows JNI headers, zlib headers and library, and a few other useful libraries like OpenSSL, libjpeg, and libpng. There's also a win64 repository for 64-bit builds: - $ git clone git://oss.readytalk.com/win64.git + $ git clone git@github.com:ReadyTalk/win64.git Building with the Microsoft Visual C++ Compiler From dd685de6e61fc4eb0044eb8f32169cdad9cb3518 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 31 Dec 2012 11:07:26 -0700 Subject: [PATCH 060/378] add extra empty line before heading in readme.txt This makes it consistent with the other headings. --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 213c138485..eb1916f2a5 100644 --- a/readme.txt +++ b/readme.txt @@ -56,6 +56,7 @@ Avian can currently target the following platforms: Mac OS X (i386, x86_64 and 32-bit PowerPC) Apple iOS (i386 and ARM) + Building -------- From e8f560895b155a85099879c9c2eac7009a0624d4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 31 Dec 2012 11:56:35 -0700 Subject: [PATCH 061/378] preserve sun.misc.Launcher.getLauncher in openjdk.pro The VM calls this method when booting, so we need to tell ProGuard to retain it. --- openjdk.pro | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openjdk.pro b/openjdk.pro index 3ffce4f58f..69b4646090 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -14,6 +14,10 @@ public static void setProperties(java.util.Properties); } +-keep class sun.misc.Launcher { + public static sun.misc.Launcher getLauncher(); + } + -keep class java.lang.ClassLoader { private static java.lang.ClassLoader scl; private static boolean sclSet; @@ -281,4 +285,4 @@ -keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack$SNode { *** match; *** next; -} \ No newline at end of file +} From ccbe01c16a7f9e92c06b8b45299c69a387625f67 Mon Sep 17 00:00:00 2001 From: terekcampbell Date: Fri, 4 Jan 2013 14:03:15 -0700 Subject: [PATCH 062/378] Edit the top --- readme.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/readme.txt b/readme.txt index eb1916f2a5..1087777f81 100644 --- a/readme.txt +++ b/readme.txt @@ -1,3 +1,8 @@ +Avian - a lightweight Java virtual machine (JVM) +================================================ + +// Put travis thing here + Quick Start ----------- From dfbc34c3a4c8fcd6322ccf2a933afacd2627f0c0 Mon Sep 17 00:00:00 2001 From: terekcampbell Date: Fri, 4 Jan 2013 16:09:54 -0700 Subject: [PATCH 063/378] Will now look pretty when converted to .md --- readme.txt | 811 ++++++++++++++++++++++++++--------------------------- 1 file changed, 404 insertions(+), 407 deletions(-) diff --git a/readme.txt b/readme.txt index 1087777f81..0ebfc4540b 100644 --- a/readme.txt +++ b/readme.txt @@ -1,32 +1,30 @@ -Avian - a lightweight Java virtual machine (JVM) +Avian - A lightweight Java Virtual Machine (JVM) ================================================ -// Put travis thing here - Quick Start ----------- -on Linux: - $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed - $ make - $ build/linux-i386/avian -cp build/linux-i386/test Hello +#### on Linux: + $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed + $ make + $ build/linux-i386/avian -cp build/linux-i386/test Hello -on Mac OS X: - $ export JAVA_HOME=/Library/Java/Home - $ make - $ build/darwin-i386/avian -cp build/darwin-i386/test Hello +#### on Mac OS X: + $ export JAVA_HOME=/Library/Java/Home + $ make + $ build/darwin-i386/avian -cp build/darwin-i386/test Hello -on Windows (MSYS): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello +#### on Windows (MSYS): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello -on Windows (Cygwin): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello +#### on Windows (Cygwin): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello Adjust JAVA_HOME according to your system, but be sure to use forward slashes in the path. @@ -38,14 +36,10 @@ Introduction Avian is a lightweight virtual machine and class library designed to provide a useful subset of Java's features, suitable for building self-contained applications. More information is available at the -project web site: - - http://oss.readytalk.com/avian +project [web site](http://oss.readytalk.com/avian). If you have any trouble building, running, or embedding Avian, please -post a message to our discussion group: - - http://groups.google.com/group/avian +post a message to our [discussion group](http://groups.google.com/group/avian). That's also the place for any other questions, comments, or suggestions you might have. @@ -56,10 +50,10 @@ Supported Platforms Avian can currently target the following platforms: - Linux (i386, x86_64, ARM, and 32-bit PowerPC) - Windows (i386 and x86_64) - Mac OS X (i386, x86_64 and 32-bit PowerPC) - Apple iOS (i386 and ARM) + * Linux (i386, x86_64, ARM, and 32-bit PowerPC) + * Windows (i386 and x86_64) + * Mac OS X (i386, x86_64 and 32-bit PowerPC) + * Apple iOS (i386 and ARM) Building @@ -80,130 +74,129 @@ been tested. The build is directed by a single makefile and may be influenced via certain flags described below, all of which are optional. - $ make \ - platform={linux,windows,darwin} \ - arch={i386,x86_64,powerpc,arm} \ - process={compile,interpret} \ - mode={debug,debug-fast,fast,small} \ - lzma= \ - ios={true,false} \ - bootimage={true,false} \ - heapdump={true,false} \ - tails={true,false} \ - continuations={true,false} \ - use-clang={true,false} \ - openjdk= \ - openjdk-src= + $ make \ + platform={linux,windows,darwin} \ + arch={i386,x86_64,powerpc,arm} \ + process={compile,interpret} \ + mode={debug,debug-fast,fast,small} \ + lzma= \ + ios={true,false} \ + bootimage={true,false} \ + heapdump={true,false} \ + tails={true,false} \ + continuations={true,false} \ + use-clang={true,false} \ + openjdk= \ + openjdk-src= - * platform - the target platform - default: output of $(uname -s | tr [:upper:] [:lower:]), - normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows) + * `platform` - the target platform + * _default:_ output of $(uname -s | tr [:upper:] [:lower:]), +normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows) - * arch - the target architecture - default: output of $(uname -m), normalized in some cases - (e.g. i686 -> i386) + * `arch` - the target architecture + * _default:_ output of $(uname -m), normalized in some cases +(e.g. i686 -> i386) - * process - choice between pure interpreter or JIT compiler - default: compile + * `process` - choice between pure interpreter or JIT compiler + * _default:_ compile - * mode - which set of compilation flags to use to determine - optimization level, debug symbols, and whether to enable - assertions - default: fast + * `mode` - which set of compilation flags to use to determine +optimization level, debug symbols, and whether to enable +assertions + * _default:_ fast - * lzma - if set, support use of LZMA to compress embedded JARs and - boot images. The value of this option should be a directory - containing a recent LZMA SDK (available at - http://www.7-zip.org/sdk.html). Currently, only version 9.20 of - the SDK has been tested, but other versions might work. - default: not set + * `lzma` - if set, support use of LZMA to compress embedded JARs and +boot images. The value of this option should be a directory +containing a recent LZMA SDK (available [here](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of +the SDK has been tested, but other versions might work. + * _default:_ not set - * ios - if true, cross-compile for iOS on OS X. Note that - non-jailbroken iOS devices do not allow JIT compilation, so only - process=interpret or bootimage=true builds will run on such - devices. See https://github.com/ReadyTalk/hello-ios for an - example of an Xcode project for iOS which uses Avian. - default: false + * `ios` - if true, cross-compile for iOS on OS X. Note that +non-jailbroken iOS devices do not allow JIT compilation, so only +process=interpret or bootimage=true builds will run on such +devices. See [here](https://github.com/ReadyTalk/hello-ios) for an +example of an Xcode project for iOS which uses Avian. + * _default:_ false - * bootimage - if true, create a boot image containing the pre-parsed - class library and ahead-of-time compiled methods. This option is - only valid for process=compile builds. Note that you may need to - specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems - where "uname -m" prints "i386". - default: false + * `bootimage` - if true, create a boot image containing the pre-parsed +class library and ahead-of-time compiled methods. This option is +only valid for process=compile builds. Note that you may need to +specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems +where "uname -m" prints "i386". + * _default:_ false - * heapdump - if true, implement avian.Machine.dumpHeap(String), - which, when called, will generate a snapshot of the heap in a - simple, ad-hoc format for memory profiling purposes. See - heapdump.cpp for details. - default: false + * `heapdump` - if true, implement avian.Machine.dumpHeap(String), +which, when called, will generate a snapshot of the heap in a +simple, ad-hoc format for memory profiling purposes. See +heapdump.cpp for details. + * _default:_ false - * tails - if true, optimize each tail call by replacing the caller's - stack frame with the callee's. This convention ensures proper - tail recursion, suitable for languages such as Scheme. This - option is only valid for process=compile builds. - default: false + * `tails` - if true, optimize each tail call by replacing the caller's +stack frame with the callee's. This convention ensures proper +tail recursion, suitable for languages such as Scheme. This +option is only valid for process=compile builds. + * _default:_ false - * continuations - if true, support continuations via the - avian.Continuations methods callWithCurrentContinuation and - dynamicWind. See Continuations.java for details. This option is - only valid for process=compile builds. - default: false + * `continuations` - if true, support continuations via the +avian.Continuations methods callWithCurrentContinuation and +dynamicWind. See Continuations.java for details. This option is +only valid for process=compile builds. + * _default:_ false - * use-clang - if true, use LLVM's clang instead of GCC to build. - Note that this does not currently affect cross compiles, only - native builds. - default: false + * `use-clang` - if true, use LLVM's clang instead of GCC to build. +Note that this does not currently affect cross compiles, only +native builds. + * _default:_ false - * openjdk - if set, use OpenJDK class library instead of the default - Avian class library. See "Building with the OpenJDK Class - Library" below for details. - default: not set + * `openjdk` - if set, use OpenJDK class library instead of the default +Avian class library. See "Building with the OpenJDK Class +Library" below for details. + * _default:_ not set - * openjdk-src - if this and the openjdk option above are both set, - build an embeddable VM using the OpenJDK class library. The JNI - components of the OpenJDK class library will be built from the - sources found under the specified directory. See "Building with - the OpenJDK Class Library" below for details. - default: not set + * `openjdk-src` - if this and the openjdk option above are both set, +build an embeddable VM using the OpenJDK class library. The JNI +components of the OpenJDK class library will be built from the +sources found under the specified directory. See "Building with +the OpenJDK Class Library" below for details. + * _default:_ not set These flags determine the name of the directory used for the build. -The name always starts with ${platform}-${arch}, and each non-default +The name always starts with _${platform}-${arch}_, and each non-default build option is appended to the name. For example, a debug build with bootimage enabled on Linux/i386 would be built in -build/linux-i386-debug-bootimage. This allows you to build with +_build/linux-i386-debug-bootimage_. This allows you to build with several different sets of options independently and even simultaneously without doing a clean build each time. If you are compiling for Windows, you may either cross-compile using MinGW or build natively on Windows under MSYS or Cygwin. -Installing MSYS: +#### Installing MSYS: - 1. Download and install the current MinGW and MSYS packages from + __1.__ Download and install the current MinGW and MSYS packages from mingw.org, selecting the C and C++ compilers when prompted. Use the post-install script to create the filesystem link to the compiler. - 2. Download GNU Make 3.81 from the MSYS download page + __2.__ Download GNU Make 3.81 from the MSYS download page (make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into - e.g. c:/msys/1.0. + _e.g. c:/msys/1.0_. -Installing Cygwin: +#### Installing Cygwin: - 1. Download and run setup.exe from cygwin.com, installing the base + __1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), installing the base system and these packages: make, gcc-mingw-g++, mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git. You may also find our win32 repository useful: (run this from the directory containing the avian directory) - $ git clone git@github.com:ReadyTalk/win32.git + $ git clone git@github.com:ReadyTalk/win32.git This gives you the Windows JNI headers, zlib headers and library, and a few other useful libraries like OpenSSL, libjpeg, and libpng. There's also a win64 repository for 64-bit builds: - $ git clone git@github.com:ReadyTalk/win64.git + $ git clone git@github.com:ReadyTalk/win64.git Building with the Microsoft Visual C++ Compiler @@ -221,23 +214,18 @@ versions 8, 9, and 10. Other versions may also work. To build with MSVC, install Cygwin as described above and set the following environment variables: - $ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem" - - $ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;" - - $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" - - $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" - - $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;" + $ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem" + $ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;" + $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" + $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" + $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;" Adjust these definitions as necessary according to your MSVC installation. Finally, build with the msvc flag set to the MSVC tool directory: - $ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC" - + $ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC" Building with the OpenJDK Class Library --------------------------------------- @@ -249,23 +237,23 @@ features beyond that subset, you may want to tell Avian to use OpenJDK's class library instead. To do so, specify the directory where OpenJDK is installed, e.g.: - $ make openjdk=/usr/lib/jvm/java-7-openjdk + $ make openjdk=/usr/lib/jvm/java-7-openjdk This will build Avian as a conventional JVM (e.g. libjvm.so) which loads its boot class library and native libraries (e.g. libjava.so) -from /usr/lib/jvm/java-7-openjdk/jre at runtime. To run an +from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. To run an application in this configuration, you'll need to make sure the VM is in your library search path. For example: - $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ - build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ - com.example.MyApplication + $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ + build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ + com.example.MyApplication Alternatively, you can enable a stand-alone build using OpenJDK by specifying the location of the OpenJDK source code, e.g.: - $ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \ - openjdk-src=$(pwd)/../jdk7/jdk/src + $ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../jdk7/jdk/src You must ensure that the path specified for openjdk-src does not have any spaces in it; make gets confused when dependency paths include @@ -278,61 +266,65 @@ specified paths are used only at build time; anything needed at runtime is embedded in the binary. Thus, the process of running an application is simplified: - $ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \ - com.example.MyApplication + $ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \ + com.example.MyApplication Note that the resulting binary will be very large due to the size of OpenJDK's class library. This can be mitigated using UPX, preferably an LZMA-enabled version: - $ upx --lzma --best build/linux-x86_64-openjdk-src/avian + $ upx --lzma --best build/linux-x86_64-openjdk-src/avian You can reduce the size futher for embedded builds by using ProGuard and the supplied openjdk.pro configuration file (see "Embedding with ProGuard and a Boot Image" below). Note that you'll still need to use vm.pro in that case -- openjdk.pro just adds additional constraints specific to the OpenJDK port. Also see app.mk in -git://oss.readytalk.com/avian-swt-examples.git for an example of using +_git://oss.readytalk.com/avian-swt-examples.git_ for an example of using Avian, OpenJDK, ProGuard, and UPX in concert. Here are some examples of how to install OpenJDK and build Avian with it on various OSes: - Debian-based Linux: - # conventional build: - apt-get install openjdk-7-jdk - make openjdk=/usr/lib/jvm/java-7-openjdk test +#### Debian-based Linux: +_Conventional build:_ - # stand-alone build: - apt-get install openjdk-7-jdk - apt-get source openjdk-7-jdk - apt-get build-dep openjdk-7-jdk + $ apt-get install openjdk-7-jdk + $ make openjdk=/usr/lib/jvm/java-7-openjdk test + +_Stand-alone build:_ + + $ apt-get install openjdk-7-jdk + $ apt-get source openjdk-7-jdk + $ apt-get build-dep openjdk-7-jdk (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) - make openjdk=/usr/lib/jvm/java-7-openjdk \ - openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ - test + $ make openjdk=/usr/lib/jvm/java-7-openjdk \ + openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ + test - Mac OS X: - # Prerequisite: build OpenJDK 7 according to - # https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port +####Mac OS X: +_Prerequisite:_ Build OpenJDK 7 according to [this site](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port). - # conventional build: - make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test +_Conventional build:_ - # stand-alone build: - make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ - openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test - Windows (Cygwin): - # Prerequisite: build OpenJDK 7 according to - # http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction +_Stand-alone build:_ - # conventional build: - make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test - # stand-alone build: - make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ - openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test +####Windows (Cygwin): +_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). + +_Conventional build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test + +_Stand-alone build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test Currently, only OpenJDK 7 is supported. Later versions might work, but have not yet been tested. @@ -344,7 +336,7 @@ Installing Installing Avian is as simple as copying the executable to the desired directory: - $ cp build/${platform}-${arch}/avian ~/bin/ + $ cp build/${platform}-${arch}/avian ~/bin/ Embedding @@ -357,158 +349,163 @@ Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or "i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands below (e.g. x86_64-w64-mingw32-gcc). -Step 1: Build Avian, create a new directory, and populate it with the +__1.__ Build Avian, create a new directory, and populate it with the VM object files and bootstrap classpath jar. - $ make - $ mkdir hello - $ cd hello - $ ar x ../build/${platform}-${arch}/libavian.a - $ cp ../build/${platform}-${arch}/classpath.jar boot.jar + $ make + $ mkdir hello + $ cd hello + $ ar x ../build/${platform}-${arch}/libavian.a + $ cp ../build/${platform}-${arch}/classpath.jar boot.jar -Step 2: Build the Java code and add it to the jar. +__2.__ Build the Java code and add it to the jar. - $ cat >Hello.java <Hello.java <embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(env); - - jclass c = e->FindClass("Hello"); - if (not e->ExceptionCheck()) { - jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); - if (not e->ExceptionCheck()) { - jclass stringClass = e->FindClass("java/lang/String"); + $ cat >embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); if (not e->ExceptionCheck()) { - jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); if (not e->ExceptionCheck()) { - for (int i = 1; i < ac; ++i) { - e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } } - - e->CallStaticVoidMethod(c, m, a); } } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; } - } + EOF - int exitCode = 0; - if (e->ExceptionCheck()) { - exitCode = -1; - e->ExceptionDescribe(); - } +__on Linux:__ - vm->DestroyJavaVM(); + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o - return exitCode; -} -EOF +__on Mac OS X:__ -on Linux: - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ - -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + $ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ + -o main.o -on Mac OS X: - $ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ - -o main.o +__on Windows:__ -on Windows: - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \ - -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o -Step 5: Link the objects produced above to produce the final +__5.__ Link the objects produced above to produce the final executable, and optionally strip its symbols. -on Linux: - $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello - $ strip --strip-all hello +__on Linux:__ -on Mac OS X: - $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation - $ strip -S -x hello + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello -on Windows: - $ dlltool -z hello.def *.o - $ dlltool -d hello.def -e hello.exp - $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ - -mwindows -mconsole -o hello.exe - $ strip --strip-all hello.exe +__on Mac OS X:__ + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation + $ strip -S -x hello + +__on Windows:__ + + $ dlltool -z hello.def *.o + $ dlltool -d hello.def -e hello.exp + $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ + -mwindows -mconsole -o hello.exe + $ strip --strip-all hello.exe Embedding with ProGuard and a Boot Image ---------------------------------------- @@ -547,45 +544,45 @@ as desired. The following instructions assume we are building for Linux/i386. Please refer to the previous example for guidance on other platforms. -Step 1: Build Avian, create a new directory, and populate it with the +__1.__ Build Avian, create a new directory, and populate it with the VM object files. - $ make bootimage=true - $ mkdir hello - $ cd hello - $ ar x ../build/linux-i386-bootimage/libavian.a + $ make bootimage=true + $ mkdir hello + $ cd hello + $ ar x ../build/linux-i386-bootimage/libavian.a -Step 2: Create a stage1 directory and extract the contents of the +__2.__ Create a stage1 directory and extract the contents of the class library jar into it. - $ mkdir stage1 - $ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar) + $ mkdir stage1 + $ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar) -Step 3: Build the Java code and add it to stage1. +__3.__ Build the Java code and add it to stage1. - $ cat >Hello.java <Hello.java <hello.pro <hello.pro <bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); - - options[1].optionString - = const_cast("-Davian.codeimage=codeimageBin"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(env); - - jclass c = e->FindClass("Hello"); - if (not e->ExceptionCheck()) { - jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); - if (not e->ExceptionCheck()) { - jclass stringClass = e->FindClass("java/lang/String"); + $ cat >bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); + + options[1].optionString + = const_cast("-Davian.codeimage=codeimageBin"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); if (not e->ExceptionCheck()) { - jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); if (not e->ExceptionCheck()) { - for (int i = 1; i < ac; ++i) { - e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } } - - e->CallStaticVoidMethod(c, m, a); } } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; } - } + EOF + + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ + -D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o - int exitCode = 0; - if (e->ExceptionCheck()) { - exitCode = -1; - e->ExceptionDescribe(); - } +__8.__ Link the objects produced above to produce the final + executable, and optionally strip its symbols. - vm->DestroyJavaVM(); - - return exitCode; -} -EOF - - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ - -D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o - -Step 8: Link the objects produced above to produce the final -executable, and optionally strip its symbols. - - $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello - $ strip --strip-all hello + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello Trademarks From cca7ade32e59eb9be08a23ec126017f04a18626c Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Fri, 4 Jan 2013 16:42:11 -0700 Subject: [PATCH 064/378] Changed the readme file to a Markdown file --- README.md | 732 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 732 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..8d27542f88 --- /dev/null +++ b/README.md @@ -0,0 +1,732 @@ +Avian - A lightweight Java Virtual Machine (JVM) +================================================ + +[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) + +Quick Start +----------- + +#### on Linux: + $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed + $ make + $ build/linux-i386/avian -cp build/linux-i386/test Hello + +#### on Mac OS X: + $ export JAVA_HOME=/Library/Java/Home + $ make + $ build/darwin-i386/avian -cp build/darwin-i386/test Hello + +#### on Windows (MSYS): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello + +#### on Windows (Cygwin): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello + +Adjust JAVA_HOME according to your system, but be sure to use forward +slashes in the path. + + +Introduction +------------ + +Avian is a lightweight virtual machine and class library designed to +provide a useful subset of Java's features, suitable for building +self-contained applications. More information is available at the +project [web site](http://oss.readytalk.com/avian). + +If you have any trouble building, running, or embedding Avian, please +post a message to our [discussion group](http://groups.google.com/group/avian). + +That's also the place for any other questions, comments, or +suggestions you might have. + + +Supported Platforms +------------------- + +Avian can currently target the following platforms: + + * Linux (i386, x86_64, ARM, and 32-bit PowerPC) + * Windows (i386 and x86_64) + * Mac OS X (i386, x86_64 and 32-bit PowerPC) + * Apple iOS (i386 and ARM) + + +Building +-------- + +Build requirements include: + + * GNU make 3.80 or later + * GCC 3.4 or later (4.5.1 or later for Windows/x86_64) + or LLVM Clang 3.1 or later (see use-clang option below) + * JDK 1.5 or later + * MinGW 3.4 or later (only if compiling for Windows) + * zlib 1.2.3 or later + +Earlier versions of some of these packages may also work but have not +been tested. + +The build is directed by a single makefile and may be influenced via +certain flags described below, all of which are optional. + + $ make \ + platform={linux,windows,darwin} \ + arch={i386,x86_64,powerpc,arm} \ + process={compile,interpret} \ + mode={debug,debug-fast,fast,small} \ + lzma= \ + ios={true,false} \ + bootimage={true,false} \ + heapdump={true,false} \ + tails={true,false} \ + continuations={true,false} \ + use-clang={true,false} \ + openjdk= \ + openjdk-src= + + * `platform` - the target platform + * _default:_ output of $(uname -s | tr [:upper:] [:lower:]), +normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows) + + * `arch` - the target architecture + * _default:_ output of $(uname -m), normalized in some cases +(e.g. i686 -> i386) + + * `process` - choice between pure interpreter or JIT compiler + * _default:_ compile + + * `mode` - which set of compilation flags to use to determine +optimization level, debug symbols, and whether to enable +assertions + * _default:_ fast + + * `lzma` - if set, support use of LZMA to compress embedded JARs and +boot images. The value of this option should be a directory +containing a recent LZMA SDK (available [here](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of +the SDK has been tested, but other versions might work. + * _default:_ not set + + * `ios` - if true, cross-compile for iOS on OS X. Note that +non-jailbroken iOS devices do not allow JIT compilation, so only +process=interpret or bootimage=true builds will run on such +devices. See [here](https://github.com/ReadyTalk/hello-ios) for an +example of an Xcode project for iOS which uses Avian. + * _default:_ false + + * `bootimage` - if true, create a boot image containing the pre-parsed +class library and ahead-of-time compiled methods. This option is +only valid for process=compile builds. Note that you may need to +specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems +where "uname -m" prints "i386". + * _default:_ false + + * `heapdump` - if true, implement avian.Machine.dumpHeap(String), +which, when called, will generate a snapshot of the heap in a +simple, ad-hoc format for memory profiling purposes. See +heapdump.cpp for details. + * _default:_ false + + * `tails` - if true, optimize each tail call by replacing the caller's +stack frame with the callee's. This convention ensures proper +tail recursion, suitable for languages such as Scheme. This +option is only valid for process=compile builds. + * _default:_ false + + * `continuations` - if true, support continuations via the +avian.Continuations methods callWithCurrentContinuation and +dynamicWind. See Continuations.java for details. This option is +only valid for process=compile builds. + * _default:_ false + + * `use-clang` - if true, use LLVM's clang instead of GCC to build. +Note that this does not currently affect cross compiles, only +native builds. + * _default:_ false + + * `openjdk` - if set, use OpenJDK class library instead of the default +Avian class library. See "Building with the OpenJDK Class +Library" below for details. + * _default:_ not set + + * `openjdk-src` - if this and the openjdk option above are both set, +build an embeddable VM using the OpenJDK class library. The JNI +components of the OpenJDK class library will be built from the +sources found under the specified directory. See "Building with +the OpenJDK Class Library" below for details. + * _default:_ not set + +These flags determine the name of the directory used for the build. +The name always starts with _${platform}-${arch}_, and each non-default +build option is appended to the name. For example, a debug build with +bootimage enabled on Linux/i386 would be built in +_build/linux-i386-debug-bootimage_. This allows you to build with +several different sets of options independently and even +simultaneously without doing a clean build each time. + +If you are compiling for Windows, you may either cross-compile using +MinGW or build natively on Windows under MSYS or Cygwin. + +#### Installing MSYS: + + __1.__ Download and install the current MinGW and MSYS packages from + mingw.org, selecting the C and C++ compilers when prompted. Use the + post-install script to create the filesystem link to the compiler. + + __2.__ Download GNU Make 3.81 from the MSYS download page + (make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into + _e.g. c:/msys/1.0_. + +#### Installing Cygwin: + + __1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), installing the base + system and these packages: make, gcc-mingw-g++, + mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git. + +You may also find our win32 repository useful: (run this from the +directory containing the avian directory) + + $ git clone git@github.com:ReadyTalk/win32.git + +This gives you the Windows JNI headers, zlib headers and library, and +a few other useful libraries like OpenSSL, libjpeg, and libpng. +There's also a win64 repository for 64-bit builds: + + $ git clone git@github.com:ReadyTalk/win64.git + + +Building with the Microsoft Visual C++ Compiler +----------------------------------------------- + +You can also build using the MSVC compiler, which makes debugging with +tools like WinDbg and Visual Studio much easier. Note that you will +still need to have GCC installed - MSVC is only used to compile the +C++ portions of the VM, while the assembly code and helper tools are +built using GCC. + +The MSVC build has been tested with Visual Studio Express Edition +versions 8, 9, and 10. Other versions may also work. + +To build with MSVC, install Cygwin as described above and set the +following environment variables: + + $ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem" + $ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;" + $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" + $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" + $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;" + +Adjust these definitions as necessary according to your MSVC +installation. + +Finally, build with the msvc flag set to the MSVC tool directory: + + $ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC" + +Building with the OpenJDK Class Library +--------------------------------------- + +By default, Avian uses its own lightweight class library. However, +that library only contains a relatively small subset of the classes +and methods included in the JRE. If your application requires +features beyond that subset, you may want to tell Avian to use +OpenJDK's class library instead. To do so, specify the directory +where OpenJDK is installed, e.g.: + + $ make openjdk=/usr/lib/jvm/java-7-openjdk + +This will build Avian as a conventional JVM (e.g. libjvm.so) which +loads its boot class library and native libraries (e.g. libjava.so) +from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. To run an +application in this configuration, you'll need to make sure the VM is +in your library search path. For example: + + $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ + build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ + com.example.MyApplication + +Alternatively, you can enable a stand-alone build using OpenJDK by +specifying the location of the OpenJDK source code, e.g.: + + $ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../jdk7/jdk/src + +You must ensure that the path specified for openjdk-src does not have +any spaces in it; make gets confused when dependency paths include +spaces, and we haven't found away around that except to avoid paths +with spaces entirely. + +The result of such a build is a self-contained binary which does not +depend on external libraries, jars, or other files. In this case, the +specified paths are used only at build time; anything needed at +runtime is embedded in the binary. Thus, the process of running an +application is simplified: + + $ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \ + com.example.MyApplication + +Note that the resulting binary will be very large due to the size of +OpenJDK's class library. This can be mitigated using UPX, preferably +an LZMA-enabled version: + + $ upx --lzma --best build/linux-x86_64-openjdk-src/avian + +You can reduce the size futher for embedded builds by using ProGuard +and the supplied openjdk.pro configuration file (see "Embedding with +ProGuard and a Boot Image" below). Note that you'll still need to use +vm.pro in that case -- openjdk.pro just adds additional constraints +specific to the OpenJDK port. Also see app.mk in +_git://oss.readytalk.com/avian-swt-examples.git_ for an example of using +Avian, OpenJDK, ProGuard, and UPX in concert. + +Here are some examples of how to install OpenJDK and build Avian with +it on various OSes: + +#### Debian-based Linux: +_Conventional build:_ + + $ apt-get install openjdk-7-jdk + $ make openjdk=/usr/lib/jvm/java-7-openjdk test + +_Stand-alone build:_ + + $ apt-get install openjdk-7-jdk + $ apt-get source openjdk-7-jdk + $ apt-get build-dep openjdk-7-jdk + (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) + $ make openjdk=/usr/lib/jvm/java-7-openjdk \ + openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ + test + +####Mac OS X: +_Prerequisite:_ Build OpenJDK 7 according to [this site](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port). + +_Conventional build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test + +_Stand-alone build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + +####Windows (Cygwin): +_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). + +_Conventional build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test + +_Stand-alone build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + +Currently, only OpenJDK 7 is supported. Later versions might work, +but have not yet been tested. + + +Installing +---------- + +Installing Avian is as simple as copying the executable to the desired +directory: + + $ cp build/${platform}-${arch}/avian ~/bin/ + + +Embedding +--------- + +The following series of commands illustrates how to produce a +stand-alone executable out of a Java application using Avian. + +Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or +"i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands +below (e.g. x86_64-w64-mingw32-gcc). + +__1.__ Build Avian, create a new directory, and populate it with the +VM object files and bootstrap classpath jar. + + $ make + $ mkdir hello + $ cd hello + $ ar x ../build/${platform}-${arch}/libavian.a + $ cp ../build/${platform}-${arch}/classpath.jar boot.jar + +__2.__ Build the Java code and add it to the jar. + + $ cat >Hello.java <embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } + } + } + } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; + } + EOF + +__on Linux:__ + + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + +__on Mac OS X:__ + + $ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ + -o main.o + +__on Windows:__ + + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + +__5.__ Link the objects produced above to produce the final +executable, and optionally strip its symbols. + +__on Linux:__ + + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello + +__on Mac OS X:__ + + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation + $ strip -S -x hello + +__on Windows:__ + + $ dlltool -z hello.def *.o + $ dlltool -d hello.def -e hello.exp + $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ + -mwindows -mconsole -o hello.exe + $ strip --strip-all hello.exe + +Embedding with ProGuard and a Boot Image +---------------------------------------- + +The following illustrates how to embed an application as above, except +this time we preprocess the code using ProGuard and build a boot image +from it for quicker startup. The pros and cons of using ProGuard are +as follow: + + * Pros: ProGuard will eliminate unused code, optimize the rest, and + obfuscate it as well for maximum space savings + + * Cons: increased build time, especially for large applications, and + extra effort needed to configure it for applications which rely + heavily on reflection and/or calls to Java from native code + +For boot image builds: + + * Pros: the boot image build pre-parses all the classes and compiles + all the methods, obviating the need for JIT compilation at runtime. + This also makes garbage collection faster, since the pre-parsed + classes are never visited. + + * Cons: the pre-parsed classes and AOT-compiled methods take up more + space in the executable than the equivalent class files. In + practice, this can make the executable 30-50% larger. Also, AOT + compilation does not yet yield significantly faster or smaller code + than JIT compilation. Finally, floating point code may be slower + on 32-bit x86 since the compiler cannot assume SSE2 support will be + available at runtime, and the x87 FPU is not supported except via + out-of-line helper functions. + +Note you can use ProGuard without using a boot image and vice-versa, +as desired. + +The following instructions assume we are building for Linux/i386. +Please refer to the previous example for guidance on other platforms. + +__1.__ Build Avian, create a new directory, and populate it with the +VM object files. + + $ make bootimage=true + $ mkdir hello + $ cd hello + $ ar x ../build/linux-i386-bootimage/libavian.a + +__2.__ Create a stage1 directory and extract the contents of the +class library jar into it. + + $ mkdir stage1 + $ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar) + +__3.__ Build the Java code and add it to stage1. + + $ cat >Hello.java <hello.pro <bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); + + options[1].optionString + = const_cast("-Davian.codeimage=codeimageBin"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } + } + } + } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; + } + EOF + + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ + -D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o + +__8.__ Link the objects produced above to produce the final + executable, and optionally strip its symbols. + + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello + + +Trademarks +---------- + +Oracle and Java are registered trademarks of Oracle and/or its +affiliates. Other names may be trademarks of their respective owners. + +The Avian project is not affiliated with Oracle. \ No newline at end of file From 7caa479084bbcad5a1d3315dc74296f50f5e0935 Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Fri, 4 Jan 2013 16:45:47 -0700 Subject: [PATCH 065/378] Deleted the old readme.txt file --- readme.txt | 730 ----------------------------------------------------- 1 file changed, 730 deletions(-) delete mode 100644 readme.txt diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 0ebfc4540b..0000000000 --- a/readme.txt +++ /dev/null @@ -1,730 +0,0 @@ -Avian - A lightweight Java Virtual Machine (JVM) -================================================ - -Quick Start ------------ - -#### on Linux: - $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed - $ make - $ build/linux-i386/avian -cp build/linux-i386/test Hello - -#### on Mac OS X: - $ export JAVA_HOME=/Library/Java/Home - $ make - $ build/darwin-i386/avian -cp build/darwin-i386/test Hello - -#### on Windows (MSYS): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello - -#### on Windows (Cygwin): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello - -Adjust JAVA_HOME according to your system, but be sure to use forward -slashes in the path. - - -Introduction ------------- - -Avian is a lightweight virtual machine and class library designed to -provide a useful subset of Java's features, suitable for building -self-contained applications. More information is available at the -project [web site](http://oss.readytalk.com/avian). - -If you have any trouble building, running, or embedding Avian, please -post a message to our [discussion group](http://groups.google.com/group/avian). - -That's also the place for any other questions, comments, or -suggestions you might have. - - -Supported Platforms -------------------- - -Avian can currently target the following platforms: - - * Linux (i386, x86_64, ARM, and 32-bit PowerPC) - * Windows (i386 and x86_64) - * Mac OS X (i386, x86_64 and 32-bit PowerPC) - * Apple iOS (i386 and ARM) - - -Building --------- - -Build requirements include: - - * GNU make 3.80 or later - * GCC 3.4 or later (4.5.1 or later for Windows/x86_64) - or LLVM Clang 3.1 or later (see use-clang option below) - * JDK 1.5 or later - * MinGW 3.4 or later (only if compiling for Windows) - * zlib 1.2.3 or later - -Earlier versions of some of these packages may also work but have not -been tested. - -The build is directed by a single makefile and may be influenced via -certain flags described below, all of which are optional. - - $ make \ - platform={linux,windows,darwin} \ - arch={i386,x86_64,powerpc,arm} \ - process={compile,interpret} \ - mode={debug,debug-fast,fast,small} \ - lzma= \ - ios={true,false} \ - bootimage={true,false} \ - heapdump={true,false} \ - tails={true,false} \ - continuations={true,false} \ - use-clang={true,false} \ - openjdk= \ - openjdk-src= - - * `platform` - the target platform - * _default:_ output of $(uname -s | tr [:upper:] [:lower:]), -normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows) - - * `arch` - the target architecture - * _default:_ output of $(uname -m), normalized in some cases -(e.g. i686 -> i386) - - * `process` - choice between pure interpreter or JIT compiler - * _default:_ compile - - * `mode` - which set of compilation flags to use to determine -optimization level, debug symbols, and whether to enable -assertions - * _default:_ fast - - * `lzma` - if set, support use of LZMA to compress embedded JARs and -boot images. The value of this option should be a directory -containing a recent LZMA SDK (available [here](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of -the SDK has been tested, but other versions might work. - * _default:_ not set - - * `ios` - if true, cross-compile for iOS on OS X. Note that -non-jailbroken iOS devices do not allow JIT compilation, so only -process=interpret or bootimage=true builds will run on such -devices. See [here](https://github.com/ReadyTalk/hello-ios) for an -example of an Xcode project for iOS which uses Avian. - * _default:_ false - - * `bootimage` - if true, create a boot image containing the pre-parsed -class library and ahead-of-time compiled methods. This option is -only valid for process=compile builds. Note that you may need to -specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems -where "uname -m" prints "i386". - * _default:_ false - - * `heapdump` - if true, implement avian.Machine.dumpHeap(String), -which, when called, will generate a snapshot of the heap in a -simple, ad-hoc format for memory profiling purposes. See -heapdump.cpp for details. - * _default:_ false - - * `tails` - if true, optimize each tail call by replacing the caller's -stack frame with the callee's. This convention ensures proper -tail recursion, suitable for languages such as Scheme. This -option is only valid for process=compile builds. - * _default:_ false - - * `continuations` - if true, support continuations via the -avian.Continuations methods callWithCurrentContinuation and -dynamicWind. See Continuations.java for details. This option is -only valid for process=compile builds. - * _default:_ false - - * `use-clang` - if true, use LLVM's clang instead of GCC to build. -Note that this does not currently affect cross compiles, only -native builds. - * _default:_ false - - * `openjdk` - if set, use OpenJDK class library instead of the default -Avian class library. See "Building with the OpenJDK Class -Library" below for details. - * _default:_ not set - - * `openjdk-src` - if this and the openjdk option above are both set, -build an embeddable VM using the OpenJDK class library. The JNI -components of the OpenJDK class library will be built from the -sources found under the specified directory. See "Building with -the OpenJDK Class Library" below for details. - * _default:_ not set - -These flags determine the name of the directory used for the build. -The name always starts with _${platform}-${arch}_, and each non-default -build option is appended to the name. For example, a debug build with -bootimage enabled on Linux/i386 would be built in -_build/linux-i386-debug-bootimage_. This allows you to build with -several different sets of options independently and even -simultaneously without doing a clean build each time. - -If you are compiling for Windows, you may either cross-compile using -MinGW or build natively on Windows under MSYS or Cygwin. - -#### Installing MSYS: - - __1.__ Download and install the current MinGW and MSYS packages from - mingw.org, selecting the C and C++ compilers when prompted. Use the - post-install script to create the filesystem link to the compiler. - - __2.__ Download GNU Make 3.81 from the MSYS download page - (make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into - _e.g. c:/msys/1.0_. - -#### Installing Cygwin: - - __1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), installing the base - system and these packages: make, gcc-mingw-g++, - mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git. - -You may also find our win32 repository useful: (run this from the -directory containing the avian directory) - - $ git clone git@github.com:ReadyTalk/win32.git - -This gives you the Windows JNI headers, zlib headers and library, and -a few other useful libraries like OpenSSL, libjpeg, and libpng. -There's also a win64 repository for 64-bit builds: - - $ git clone git@github.com:ReadyTalk/win64.git - - -Building with the Microsoft Visual C++ Compiler ------------------------------------------------ - -You can also build using the MSVC compiler, which makes debugging with -tools like WinDbg and Visual Studio much easier. Note that you will -still need to have GCC installed - MSVC is only used to compile the -C++ portions of the VM, while the assembly code and helper tools are -built using GCC. - -The MSVC build has been tested with Visual Studio Express Edition -versions 8, 9, and 10. Other versions may also work. - -To build with MSVC, install Cygwin as described above and set the -following environment variables: - - $ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem" - $ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;" - $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" - $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" - $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;" - -Adjust these definitions as necessary according to your MSVC -installation. - -Finally, build with the msvc flag set to the MSVC tool directory: - - $ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC" - -Building with the OpenJDK Class Library ---------------------------------------- - -By default, Avian uses its own lightweight class library. However, -that library only contains a relatively small subset of the classes -and methods included in the JRE. If your application requires -features beyond that subset, you may want to tell Avian to use -OpenJDK's class library instead. To do so, specify the directory -where OpenJDK is installed, e.g.: - - $ make openjdk=/usr/lib/jvm/java-7-openjdk - -This will build Avian as a conventional JVM (e.g. libjvm.so) which -loads its boot class library and native libraries (e.g. libjava.so) -from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. To run an -application in this configuration, you'll need to make sure the VM is -in your library search path. For example: - - $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ - build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ - com.example.MyApplication - -Alternatively, you can enable a stand-alone build using OpenJDK by -specifying the location of the OpenJDK source code, e.g.: - - $ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \ - openjdk-src=$(pwd)/../jdk7/jdk/src - -You must ensure that the path specified for openjdk-src does not have -any spaces in it; make gets confused when dependency paths include -spaces, and we haven't found away around that except to avoid paths -with spaces entirely. - -The result of such a build is a self-contained binary which does not -depend on external libraries, jars, or other files. In this case, the -specified paths are used only at build time; anything needed at -runtime is embedded in the binary. Thus, the process of running an -application is simplified: - - $ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \ - com.example.MyApplication - -Note that the resulting binary will be very large due to the size of -OpenJDK's class library. This can be mitigated using UPX, preferably -an LZMA-enabled version: - - $ upx --lzma --best build/linux-x86_64-openjdk-src/avian - -You can reduce the size futher for embedded builds by using ProGuard -and the supplied openjdk.pro configuration file (see "Embedding with -ProGuard and a Boot Image" below). Note that you'll still need to use -vm.pro in that case -- openjdk.pro just adds additional constraints -specific to the OpenJDK port. Also see app.mk in -_git://oss.readytalk.com/avian-swt-examples.git_ for an example of using -Avian, OpenJDK, ProGuard, and UPX in concert. - -Here are some examples of how to install OpenJDK and build Avian with -it on various OSes: - -#### Debian-based Linux: -_Conventional build:_ - - $ apt-get install openjdk-7-jdk - $ make openjdk=/usr/lib/jvm/java-7-openjdk test - -_Stand-alone build:_ - - $ apt-get install openjdk-7-jdk - $ apt-get source openjdk-7-jdk - $ apt-get build-dep openjdk-7-jdk - (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) - $ make openjdk=/usr/lib/jvm/java-7-openjdk \ - openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ - test - -####Mac OS X: -_Prerequisite:_ Build OpenJDK 7 according to [this site](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port). - -_Conventional build:_ - - $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test - -_Stand-alone build:_ - - $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ - openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test - -####Windows (Cygwin): -_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). - -_Conventional build:_ - - $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test - -_Stand-alone build:_ - - $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ - openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test - -Currently, only OpenJDK 7 is supported. Later versions might work, -but have not yet been tested. - - -Installing ----------- - -Installing Avian is as simple as copying the executable to the desired -directory: - - $ cp build/${platform}-${arch}/avian ~/bin/ - - -Embedding ---------- - -The following series of commands illustrates how to produce a -stand-alone executable out of a Java application using Avian. - -Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or -"i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands -below (e.g. x86_64-w64-mingw32-gcc). - -__1.__ Build Avian, create a new directory, and populate it with the -VM object files and bootstrap classpath jar. - - $ make - $ mkdir hello - $ cd hello - $ ar x ../build/${platform}-${arch}/libavian.a - $ cp ../build/${platform}-${arch}/classpath.jar boot.jar - -__2.__ Build the Java code and add it to the jar. - - $ cat >Hello.java <embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(env); - - jclass c = e->FindClass("Hello"); - if (not e->ExceptionCheck()) { - jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); - if (not e->ExceptionCheck()) { - jclass stringClass = e->FindClass("java/lang/String"); - if (not e->ExceptionCheck()) { - jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); - if (not e->ExceptionCheck()) { - for (int i = 1; i < ac; ++i) { - e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); - } - - e->CallStaticVoidMethod(c, m, a); - } - } - } - } - - int exitCode = 0; - if (e->ExceptionCheck()) { - exitCode = -1; - e->ExceptionDescribe(); - } - - vm->DestroyJavaVM(); - - return exitCode; - } - EOF - -__on Linux:__ - - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ - -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o - -__on Mac OS X:__ - - $ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ - -o main.o - -__on Windows:__ - - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \ - -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o - -__5.__ Link the objects produced above to produce the final -executable, and optionally strip its symbols. - -__on Linux:__ - - $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello - $ strip --strip-all hello - -__on Mac OS X:__ - - $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation - $ strip -S -x hello - -__on Windows:__ - - $ dlltool -z hello.def *.o - $ dlltool -d hello.def -e hello.exp - $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ - -mwindows -mconsole -o hello.exe - $ strip --strip-all hello.exe - -Embedding with ProGuard and a Boot Image ----------------------------------------- - -The following illustrates how to embed an application as above, except -this time we preprocess the code using ProGuard and build a boot image -from it for quicker startup. The pros and cons of using ProGuard are -as follow: - - * Pros: ProGuard will eliminate unused code, optimize the rest, and - obfuscate it as well for maximum space savings - - * Cons: increased build time, especially for large applications, and - extra effort needed to configure it for applications which rely - heavily on reflection and/or calls to Java from native code - -For boot image builds: - - * Pros: the boot image build pre-parses all the classes and compiles - all the methods, obviating the need for JIT compilation at runtime. - This also makes garbage collection faster, since the pre-parsed - classes are never visited. - - * Cons: the pre-parsed classes and AOT-compiled methods take up more - space in the executable than the equivalent class files. In - practice, this can make the executable 30-50% larger. Also, AOT - compilation does not yet yield significantly faster or smaller code - than JIT compilation. Finally, floating point code may be slower - on 32-bit x86 since the compiler cannot assume SSE2 support will be - available at runtime, and the x87 FPU is not supported except via - out-of-line helper functions. - -Note you can use ProGuard without using a boot image and vice-versa, -as desired. - -The following instructions assume we are building for Linux/i386. -Please refer to the previous example for guidance on other platforms. - -__1.__ Build Avian, create a new directory, and populate it with the -VM object files. - - $ make bootimage=true - $ mkdir hello - $ cd hello - $ ar x ../build/linux-i386-bootimage/libavian.a - -__2.__ Create a stage1 directory and extract the contents of the -class library jar into it. - - $ mkdir stage1 - $ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar) - -__3.__ Build the Java code and add it to stage1. - - $ cat >Hello.java <hello.pro <bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); - - options[1].optionString - = const_cast("-Davian.codeimage=codeimageBin"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(env); - - jclass c = e->FindClass("Hello"); - if (not e->ExceptionCheck()) { - jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); - if (not e->ExceptionCheck()) { - jclass stringClass = e->FindClass("java/lang/String"); - if (not e->ExceptionCheck()) { - jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); - if (not e->ExceptionCheck()) { - for (int i = 1; i < ac; ++i) { - e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); - } - - e->CallStaticVoidMethod(c, m, a); - } - } - } - } - - int exitCode = 0; - if (e->ExceptionCheck()) { - exitCode = -1; - e->ExceptionDescribe(); - } - - vm->DestroyJavaVM(); - - return exitCode; - } - EOF - - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ - -D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o - -__8.__ Link the objects produced above to produce the final - executable, and optionally strip its symbols. - - $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello - $ strip --strip-all hello - - -Trademarks ----------- - -Oracle and Java are registered trademarks of Oracle and/or its -affiliates. Other names may be trademarks of their respective owners. - -The Avian project is not affiliated with Oracle. From ab0310d781f11b119909ff2f2d3f1f12e14eff58 Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Mon, 7 Jan 2013 09:29:31 -0700 Subject: [PATCH 066/378] Added the travis.yml file --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..954dbe7ab0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: java +jdk: + - openjdk6 + - openjdk7 + - oraclejdk7 \ No newline at end of file From 3010aa13a5599229bb23314b38f7ce828c65a870 Mon Sep 17 00:00:00 2001 From: terekcampbell Date: Mon, 7 Jan 2013 09:38:02 -0700 Subject: [PATCH 067/378] Updated README for Travis CI --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d27542f88..60dd05c4cf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Avian - A lightweight Java Virtual Machine (JVM) ================================================ -[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) +[![Build Status](https://travis-ci.org/terekcampbell/avian.png?branch=master)](https://travis-ci.org/terekcampbell/avian) Quick Start ----------- @@ -729,4 +729,4 @@ Trademarks Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. -The Avian project is not affiliated with Oracle. \ No newline at end of file +The Avian project is not affiliated with Oracle. From ff08a658fe1226bf4b8ff23e4899ab2427b97d1c Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Mon, 7 Jan 2013 09:39:25 -0700 Subject: [PATCH 068/378] Further changes to travis.yml --- .travis.yml | 6 +----- README.md | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 954dbe7ab0..f5c99a7f66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1 @@ -language: java -jdk: - - openjdk6 - - openjdk7 - - oraclejdk7 \ No newline at end of file +language: java \ No newline at end of file diff --git a/README.md b/README.md index 8d27542f88..a22229755e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Avian - A lightweight Java Virtual Machine (JVM) ================================================ -[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) +[![Build Status](https://travis-ci.org/terekcampbell/avian.png?branch=master)](https://travis-ci.org/terekcampbell/avian) Quick Start ----------- From d53920a188c0b3f3c61f692566357e44a82a3826 Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Mon, 7 Jan 2013 10:57:50 -0700 Subject: [PATCH 069/378] Edit README.md to work with ReadyTalk's Travis CI --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60dd05c4cf..f01811b4e1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Avian - A lightweight Java Virtual Machine (JVM) ================================================ -[![Build Status](https://travis-ci.org/terekcampbell/avian.png?branch=master)](https://travis-ci.org/terekcampbell/avian) +[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) Quick Start ----------- From 548a40ea3af42ce03b4fff09e7e5faeba667ec3a Mon Sep 17 00:00:00 2001 From: Seth Goings Date: Mon, 7 Jan 2013 11:36:34 -0700 Subject: [PATCH 070/378] Update .travis.yml Use make to build this project in Travis instead of the Java default --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f5c99a7f66..f9d431f824 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1 +1,2 @@ -language: java \ No newline at end of file +language: c++ +script: "make test" From 6e6ee31128229b4333a7cbdf9f2614ac3b4859b2 Mon Sep 17 00:00:00 2001 From: Seth Goings Date: Mon, 7 Jan 2013 11:37:01 -0700 Subject: [PATCH 071/378] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f9d431f824..e2d152d5f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,2 @@ -language: c++ +language: cpp script: "make test" From ccbdd6723a3b0608ef4039d78467db6352d832d0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Jan 2013 14:08:07 -0700 Subject: [PATCH 072/378] specify CodeCapacity based on target arch, not build arch --- src/bootimage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 492366f6c2..ed7a271cb2 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1991,7 +1991,8 @@ main(int ac, const char** av) // in a branch instruction for the target architecture (~32MB on // PowerPC and ARM). When that limitation is removed, we'll be able // to specify a capacity as large as we like here: -#if (defined ARCH_x86_64) || (defined ARCH_x86_32) +#if (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64) \ + || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_32) const unsigned CodeCapacity = 128 * 1024 * 1024; #else const unsigned CodeCapacity = 30 * 1024 * 1024; From 2a45a5919ce4a933caae6336e48e9495c1c155d8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Jan 2013 14:10:31 -0700 Subject: [PATCH 073/378] return XToolkit from iOS getPreferredToolkit stub This is necessary to prevent an NPE in Hashtable.put when System.initProperites tries to put a null value in the map for java.awt.graphicsenv. --- src/openjdk/my_java_props_macosx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openjdk/my_java_props_macosx.c b/src/openjdk/my_java_props_macosx.c index 8a1850010f..19de63cb35 100644 --- a/src/openjdk/my_java_props_macosx.c +++ b/src/openjdk/my_java_props_macosx.c @@ -3,7 +3,7 @@ PreferredToolkit getPreferredToolkit() { - return unset; + return XToolkit; } void From 0adccdc99c80f76833ee696438150672a17c0091 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 24 Jan 2013 12:12:00 -0700 Subject: [PATCH 074/378] return unadorned filename from JVM_GetSystemPackage Package.defineSystemPackage expects a filename, not a URL. --- src/classpath-openjdk.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 4842ab8581..348a739cfe 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -746,7 +746,20 @@ class MyClasspath : public Classpath { byteArrayEqual); object source = classSource(t, class_); - if (source == 0) { + if (source) { + // note that we strip the "file:" prefix, since + // Package.defineSystemPackage expects an unadorned + // filename: + const unsigned PrefixLength = 5; + unsigned sourceNameLength = byteArrayLength(t, source) + - PrefixLength; + THREAD_RUNTIME_ARRAY(t, char, sourceName, sourceNameLength); + memcpy(RUNTIME_ARRAY_BODY(sourceName), + &byteArrayBody(t, source, PrefixLength), + sourceNameLength); + + source = vm::makeByteArray(t, "%s", sourceName); + } else { source = vm::makeByteArray(t, "avian-dummy-package-source"); } From 36eee724c913b6b8ea046a200814b9fcf331ff5b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 24 Jan 2013 12:13:42 -0700 Subject: [PATCH 075/378] check argument types in JVM_InvokeMethod Method.invoke must throw an IllegalArgumentException if it receives the wrong number or types of arguments, and since this isn't done by the OpenJDK class library, we must do it in the VM. --- src/classpath-openjdk.cpp | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 348a739cfe..75c49b9bf7 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4795,6 +4795,59 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) instance = 0; } + if ((args == 0 ? 0 : objectArrayLength(t, *args)) + != methodParameterCount(t, vmMethod)) + { + throwNew(t, Machine::IllegalArgumentExceptionType); + } + + if (methodParameterCount(t, vmMethod)) { + PROTECT(t, vmMethod); + + unsigned specLength = byteArrayLength(t, methodSpec(t, vmMethod)); + THREAD_RUNTIME_ARRAY(t, char, spec, specLength); + memcpy(spec, &byteArrayBody(t, methodSpec(t, vmMethod), 0), specLength); + unsigned i = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + object type; + bool objectType = false; + const char* p = it.next(); + switch (*p) { + case 'Z': type = vm::type(t, Machine::BooleanType); break; + case 'B': type = vm::type(t, Machine::ByteType); break; + case 'S': type = vm::type(t, Machine::ShortType); break; + case 'C': type = vm::type(t, Machine::CharType); break; + case 'I': type = vm::type(t, Machine::IntType); break; + case 'F': type = vm::type(t, Machine::FloatType); break; + case 'J': type = vm::type(t, Machine::LongType); break; + case 'D': type = vm::type(t, Machine::DoubleType); break; + + case 'L': ++ p; + case '[': { + objectType = true; + unsigned nameLength = it.s - p; + THREAD_RUNTIME_ARRAY(t, char, name, nameLength); + memcpy(name, p, nameLength - 1); + name[nameLength - 1] = 0; + type = resolveClass + (t, classLoader(t, methodClass(t, vmMethod)), name); + } break; + + default: + abort(); + } + + object arg = objectArrayBody(t, *args, i++); + if ((arg == 0 and (not objectType)) + or (arg and (not instanceOf(t, type, arg)))) + { + // fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast(""), &byteArrayBody(t, className(t, type), 0)); + + throwNew(t, Machine::IllegalArgumentExceptionType); + } + } + } + unsigned returnCode = methodReturnCode(t, vmMethod); THREAD_RESOURCE0(t, { From 844520a4026b2a57e22a67d7880cc12867507156 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 25 Jan 2013 07:57:57 -0700 Subject: [PATCH 076/378] fix embed.cpp build for 64-bit Windows --- src/embed.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/embed.cpp b/src/embed.cpp index a4a32bb6d7..293169ce78 100644 --- a/src/embed.cpp +++ b/src/embed.cpp @@ -17,8 +17,14 @@ #include "embed.h" -extern "C" const uint8_t binary_loader_start[]; -extern "C" const uint8_t binary_loader_end[]; +#ifdef __x86_64__ +# define BINARY_LOADER(x) _binary_loader_##x +#else +# define BINARY_LOADER(x) binary_loader_##x +#endif + +extern "C" const uint8_t BINARY_LOADER(start)[]; +extern "C" const uint8_t BINARY_LOADER(end)[]; __declspec(noreturn) void printUsage(const wchar_t* executableName) @@ -31,8 +37,8 @@ void writeDestinationFile(const wchar_t* filename) { if(FILE* file = _wfopen(filename, L"wb")) { - size_t count = binary_loader_end - binary_loader_start; - if(count == fwrite(binary_loader_start, sizeof(binary_loader_start[0]), count, file)) + size_t count = BINARY_LOADER(end) - BINARY_LOADER(start); + if(count == fwrite(BINARY_LOADER(start), sizeof(BINARY_LOADER(start)[0]), count, file)) { fclose(file); return; From 2131adf3aa2f14172f6372e748a44d468b4abe66 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 25 Jan 2013 08:07:47 -0700 Subject: [PATCH 077/378] fix Windows OpenJDK build --- src/classpath-openjdk.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 75c49b9bf7..a1a13efa22 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -46,7 +46,8 @@ # define O_RDONLY _O_RDONLY -# ifdef AVIAN_OPENJDK_SRC +# if (defined AVIAN_OPENJDK_SRC) \ + || ((defined __x86_64__) && (defined __MINGW32__)) # define EXPORT(x) x # else # define EXPORT(x) _##x @@ -450,9 +451,14 @@ class MyClasspath : public Classpath { // todo: handle other architectures # define LIB_DIR "/lib/i386" #endif + +#ifdef PLATFORM_WINDOWS + sb.append(LIB_DIR); +#else sb.append(LIB_DIR ":"); sb.append(javaHome); sb.append(LIB_DIR "/xawt"); +#endif sb.append('\0'); unsigned tzMappingsOffset = sb.offset; @@ -638,7 +644,9 @@ class MyClasspath : public Classpath { #else // not AVIAN_OPENJDK_SRC expect(t, loadLibrary(t, libraryPath, "verify", true, true)); expect(t, loadLibrary(t, libraryPath, "java", true, true)); +# ifndef PLATFORM_WINDOWS loadLibrary(t, libraryPath, "mawt", true, true); +# endif #endif // not AVIAN_OPENJDK_SRC { object assertionLock = resolveField From 1a44ec9eeffbc4b95241277fdc6f95a36639a1ed Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 25 Jan 2013 16:47:31 -0700 Subject: [PATCH 078/378] fix incorrect macro name in bootimage.cpp --- src/bootimage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index ed7a271cb2..edb82b0527 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1992,9 +1992,10 @@ main(int ac, const char** av) // PowerPC and ARM). When that limitation is removed, we'll be able // to specify a capacity as large as we like here: #if (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64) \ - || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_32) + || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) const unsigned CodeCapacity = 128 * 1024 * 1024; #else +# error "wtf?" const unsigned CodeCapacity = 30 * 1024 * 1024; #endif From 70a7a50a498a108b46844223eaeef1afd46ade52 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 17:15:15 -0700 Subject: [PATCH 079/378] fix int-to-long conversions from memory on x86_32 The instruction for 32-bit-to-64-bit sign extension on x86_32 requires that the input value be placed in EAX and the sign extension in EDX. However, the compiler can get confused if the input value is in memory addressed via one of those registers and doesn't know how to move it. This patch works around that limitation by doing the move explicitly in MemoryEvent::compile if necessary. --- src/compiler.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 8e118008bb..988cdb33fb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2003,6 +2003,13 @@ class MemorySite: public Site { } } + bool conflicts(const SiteMask& mask) { + return (mask.typeMask & (1 << RegisterOperand)) != 0 + and (((1 << base) & mask.registerMask) == 0 + or (index != NoRegister + and ((1 << index) & mask.registerMask) == 0)); + } + virtual bool match(Context* c, const SiteMask& mask) { assert(c, acquired); @@ -4574,8 +4581,20 @@ class OperationEvent: public Event { void appendOperation(Context* c, Operation op) { - append - (c, new(c->zone) OperationEvent(c, op)); + append(c, new(c->zone) OperationEvent(c, op)); +} + +void +moveIfConflict(Context* c, Value* v, MemorySite* s) +{ + if (v->reads) { + SiteMask mask(1 << RegisterOperand, ~0, AnyFrameIndex); + v->reads->intersect(&mask); + if (s->conflicts(mask)) { + maybeMove(c, v->reads, true, false); + removeSite(c, v, s); + } + } } class MemoryEvent: public Event { @@ -4626,22 +4645,24 @@ class MemoryEvent: public Event { popRead(c, this, index); } - Site* site = memorySite + MemorySite* site = memorySite (c, baseRegister, displacement, indexRegister, scale); - Site* low; + MemorySite* low; if (result->nextWord != result) { - Site* high = site->copyHigh(c); - low = site->copyLow(c); + MemorySite* high = static_cast(site->copyHigh(c)); + low = static_cast(site->copyLow(c)); result->nextWord->target = high; addSite(c, result->nextWord, high); + moveIfConflict(c, result->nextWord, high); } else { low = site; } result->target = low; addSite(c, result, low); + moveIfConflict(c, result, low); } Value* base; From dec2095c6328d39ce7f2c3b9e432aeb72d092ada Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 18:01:34 -0700 Subject: [PATCH 080/378] fix openjdk bootimage cross builds We need to extract the OpenJDK classes into the build classpath directory for the target platform before running the bootimage-generator, or else it won't be able to find the classes. --- makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index f006ba0bf9..46bbd9b8ff 100755 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -MAKEFLAGS = -s +#MAKEFLAGS = -s name = avian version = 0.6 @@ -1158,7 +1158,8 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(ar) cru $(@) $(^) $(ranlib) $(@) -$(bootimage-object) $(codeimage-object): $(bootimage-generator) +$(bootimage-object) $(codeimage-object): $(bootimage-generator) \ + $(build)/classpath.jar $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end From 75f5921b3ed2d231d182a5f225a62ff5b7cad3bb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 20:07:18 -0700 Subject: [PATCH 081/378] revert accidental makefile change --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 46bbd9b8ff..b3cbd88a57 100755 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s name = avian version = 0.6 From 67fd7072543e6c100bab2901576d731efcad6f51 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 22:06:53 -0700 Subject: [PATCH 082/378] fix handling of unusual exception handler layout Scala sometimes generates bytecode such that the scope of an exception handler starts at another exception handler, e.g.: Exception table: from to target type 290 372 382 any 382 451 451 any 290 372 451 any Avian's compiler was incorrectly initializing the stack frame for the second handler in this case. This commit fixes the problem. --- src/compiler.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 988cdb33fb..8d0c1bd2f9 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -672,6 +672,8 @@ class Event { virtual bool allExits() { return false; } + virtual Local* locals() { return localsBefore; } + Event* next; Stack* stackBefore; Local* localsBefore; @@ -5183,8 +5185,9 @@ appendSaveLocals(Context* c) class DummyEvent: public Event { public: - DummyEvent(Context* c): - Event(c) + DummyEvent(Context* c, Local* locals): + Event(c), + locals_(locals) { } virtual const char* name() { @@ -5192,6 +5195,12 @@ class DummyEvent: public Event { } virtual void compile(Context*) { } + + virtual Local* locals() { + return locals_; + } + + Local* locals_; }; void @@ -5204,7 +5213,7 @@ appendDummy(Context* c) c->stack = i->stack; c->locals = i->locals; - append(c, new(c->zone) DummyEvent(c)); + append(c, new(c->zone) DummyEvent(c, locals)); c->stack = stack; c->locals = locals; @@ -6449,14 +6458,14 @@ class MyCompiler: public Compiler { Event* e = c.logicalCode[logicalIp]->firstEvent; for (int i = 0; i < static_cast(c.localFootprint); ++i) { - Local* local = e->localsBefore + i; + Local* local = e->locals() + i; if (local->value) { initLocal (1, i, local->value->type == ValueGeneral ? IntegerType : FloatType); } } - linkLocals(&c, e->localsBefore, newLocals); + linkLocals(&c, e->locals(), newLocals); } virtual void storeLocal(unsigned footprint, Operand* src, unsigned index) { From 0c5471d25e98ffba42e23efaa4a7e2bab52d3c6b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 28 Jan 2013 16:24:08 -0700 Subject: [PATCH 083/378] remove temporary #error used for debugging Sorry, that wasn't supposed to be checked in. --- src/bootimage.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index edb82b0527..f82e73f9f5 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1995,7 +1995,6 @@ main(int ac, const char** av) || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) const unsigned CodeCapacity = 128 * 1024 * 1024; #else -# error "wtf?" const unsigned CodeCapacity = 30 * 1024 * 1024; #endif From b1eb4b9718b193446ab8403f2cc0235f4be53e10 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Wed, 30 Jan 2013 04:21:11 +0100 Subject: [PATCH 084/378] Adds code to get the Scala REPL working --- classpath/java/io/File.java | 7 ++- classpath/java/lang/Integer.java | 23 +++++++- classpath/java/lang/Long.java | 8 ++- classpath/java/math/BigInteger.java | 44 +++++++++++++++ classpath/java/math/MathContext.java | 71 +++++++++++++++++++++++++ classpath/java/math/RoundingMode.java | 36 +++++++++++++ classpath/java/util/jar/Attributes.java | 27 ++++++++++ 7 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 classpath/java/math/BigInteger.java create mode 100644 classpath/java/math/MathContext.java create mode 100644 classpath/java/math/RoundingMode.java create mode 100644 classpath/java/util/jar/Attributes.java diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index 187549ebfd..b66aa03ff9 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2012, Avian Contributors +/* Copyright (c) 2008-2013, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -16,6 +16,11 @@ public class File implements Serializable { public static final String separator = FileSeparator; + private static final String PathSeparator + = System.getProperty("path.separator"); + + public static final String pathSeparator = PathSeparator; + // static { // System.loadLibrary("natives"); // } diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index 8ea8668ddc..9bd399f227 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2013, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -94,6 +94,27 @@ public final class Integer extends Number implements Comparable { return (double) value; } + public static int signum(int v) { + if (v == 0) return 0; + else if (v > 0) return 1; + else return -1; + } + + // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + public static int bitCount(int v) { + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; + } + + public static int reverseBytes(int v) { + int byte3 = v >>> 24; + int byte2 = (v >>> 8) & 0xFF00; + int byte1 = (v << 8) & 0xFF00; + int byte0 = v << 24; + return (byte0 | byte1 | byte2 | byte3); + } + public static int parseInt(String s) { return parseInt(s, 10); } diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index b7569951b7..425e68383a 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2013, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -126,6 +126,12 @@ public final class Long extends Number implements Comparable { return (double) value; } + public static int signum(long v) { + if (v == 0) return 0; + else if (v > 0) return 1; + else return -1; + } + private static long pow(long a, long b) { long c = 1; for (int i = 0; i < b; ++i) c *= a; diff --git a/classpath/java/math/BigInteger.java b/classpath/java/math/BigInteger.java new file mode 100644 index 0000000000..319b01707b --- /dev/null +++ b/classpath/java/math/BigInteger.java @@ -0,0 +1,44 @@ +/* Copyright (c) 2013, 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. */ + +package java.math; + +import java.io.Serializable; + +public class BigInteger implements Serializable { + + private int sign; + private int[] value; + + private BigInteger(int sign, long value) { + this.sign = sign; + int upperBits = (int) (value >>> 32); + if (upperBits == 0) + // Array with one element + this.value = new int[] { (int) value }; + else + // Array with two elements + this.value = new int[] { (int) value, upperBits }; + } + + public static final BigInteger ZERO = new BigInteger(0, 0); + public static final BigInteger ONE = new BigInteger(1, 1); + public static final BigInteger TEN = new BigInteger(1, 10); + + public static BigInteger valueOf(long num) { + int signum = Long.signum(num); + if (signum == 0) + return BigInteger.ZERO; + else if (signum > 0) + return new BigInteger(signum, num); + else + return new BigInteger(signum, -num); + } +} diff --git a/classpath/java/math/MathContext.java b/classpath/java/math/MathContext.java new file mode 100644 index 0000000000..7ff24d8b12 --- /dev/null +++ b/classpath/java/math/MathContext.java @@ -0,0 +1,71 @@ +/* Copyright (c) 2013, 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. */ + +package java.math; + +import java.io.Serializable; + +public final class MathContext implements Serializable { + + public static final MathContext DECIMAL32 = new MathContext( 7, RoundingMode.HALF_EVEN); + public static final MathContext DECIMAL64 = new MathContext(16, RoundingMode.HALF_EVEN); + public static final MathContext DECIMAL128 = new MathContext(34, RoundingMode.HALF_EVEN); + public static final MathContext UNLIMITED = new MathContext(0, RoundingMode.HALF_UP); + + private int precision; + private RoundingMode roundingMode; + + public MathContext(int precision, RoundingMode roundingMode) { + if (precision < 0) + throw new IllegalArgumentException(); + if (roundingMode == null) + throw new NullPointerException(); + this.precision = precision; + this.roundingMode = roundingMode; + } + + public MathContext(int precision) { + this(precision, RoundingMode.HALF_UP); + } + + public int getPrecision() { + return precision; + } + + public RoundingMode getRoundingMode() { + return roundingMode; + } + + @Override + public boolean equals(Object that) { + return + (that instanceof MathContext) && + (precision == ((MathContext) that).getPrecision()) && + (roundingMode == ((MathContext) that).getRoundingMode()); + } + + @Override + public int hashCode() { + return + roundingMode.ordinal() | + (precision << 4); + } + + private final static String precisionString = "precision="; + private final static String roundingModeString = " roundingMode="; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(48); + sb.append(precisionString).append(precision); + sb.append(roundingModeString).append(roundingMode); + return sb.toString(); + } +} diff --git a/classpath/java/math/RoundingMode.java b/classpath/java/math/RoundingMode.java new file mode 100644 index 0000000000..22bfd69757 --- /dev/null +++ b/classpath/java/math/RoundingMode.java @@ -0,0 +1,36 @@ +/* Copyright (c) 2013, 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. */ + +package java.math; + +public enum RoundingMode { + + UP (0), + DOWN (1), + CEILING (2), + FLOOR (3), + HALF_UP (4), + HALF_DOWN (5), + HALF_EVEN (6), + UNNECESSARY(7); + + RoundingMode(int rm) { + roundingMode = rm; + } + + private final int roundingMode; + + public static RoundingMode valueOf(int roundingMode) { + final RoundingMode[] values = values(); + if (roundingMode < 0 || roundingMode >= values.length) + throw new IllegalArgumentException(); + return values[roundingMode]; + } +} diff --git a/classpath/java/util/jar/Attributes.java b/classpath/java/util/jar/Attributes.java new file mode 100644 index 0000000000..806fdb5b98 --- /dev/null +++ b/classpath/java/util/jar/Attributes.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2013, 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. */ + +package java.util.jar; + +public class Attributes { + public static class Name { + private final String name; + + private static final int MAX_NAME_LENGTH = 70; + + public Name(String s) { + int len = s.length(); + if (len == 0 || len > MAX_NAME_LENGTH) + throw new IllegalArgumentException(); + + name = s; + } + } +} From 1db67e463f6fb39e616e02819b3b949fc0e3c56e Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Sun, 3 Feb 2013 15:39:31 +0100 Subject: [PATCH 085/378] Add Class#isEnum and improve error handling in Enum.valueOf --- classpath/java/lang/Class.java | 9 +++++++-- classpath/java/lang/Enum.java | 9 ++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index eb183260d6..dcef601f12 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -37,7 +37,8 @@ import java.security.Permissions; import java.security.AllPermission; public final class Class implements Type, AnnotatedElement { - private static final int PrimitiveFlag = 1 << 5; + private static final int PrimitiveFlag = 1 << 5; + private static final int EnumFlag = 1 << 14; public final VMClass vmClass; @@ -555,6 +556,10 @@ public final class Class implements Type, AnnotatedElement { return (vmClass.vmFlags & PrimitiveFlag) != 0; } + public boolean isEnum() { + return getSuperclass() == Enum.class && (vmClass.flags & EnumFlag) != 0; + } + public URL getResource(String path) { if (! path.startsWith("/")) { String name = new String @@ -626,7 +631,7 @@ public final class Class implements Type, AnnotatedElement { for (VMClass c = vmClass; c != null; c = c.super_) { if (c.addendum != null && c.addendum.annotationTable != null) { Classes.link(c, c.loader); - + Object[] table = (Object[]) c.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; diff --git a/classpath/java/lang/Enum.java b/classpath/java/lang/Enum.java index 8d0d4756b0..a70b2074a9 100644 --- a/classpath/java/lang/Enum.java +++ b/classpath/java/lang/Enum.java @@ -30,7 +30,9 @@ public abstract class Enum> implements Comparable { } public static > T valueOf(Class enumType, String name) { - if (name == null) throw new NullPointerException(); + if (name == null) throw new NullPointerException("name"); + if (!enumType.isEnum()) + throw new IllegalArgumentException(enumType.getCanonicalName() + " is not an enum."); try { Method method = enumType.getMethod("values"); @@ -41,10 +43,11 @@ public abstract class Enum> implements Comparable { } } } catch (Exception ex) { - throw new RuntimeException(ex); + // Cannot happen + throw new Error(ex); } - throw new IllegalArgumentException(name); + throw new IllegalArgumentException(enumType.getCanonicalName() + "." + name + " is not an enum constant."); } public int ordinal() { From 1890e348fb7d596c75051329f5f0059c20419a8d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 14:09:29 -0700 Subject: [PATCH 086/378] fix handling of classe, method, and field names with non-ASCII characters --- src/classpath-openjdk.cpp | 4 +- src/machine.cpp | 80 ++++++++++++++++++++++++++++++++++----- src/machine.h | 3 ++ src/stream.h | 30 +++++++++++---- test/Misc.java | 13 +++++++ 5 files changed, 113 insertions(+), 17 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index a1a13efa22..9869538cf6 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -504,6 +504,8 @@ class MyClasspath : public Classpath { object charArray = makeCharArray(t, length); for (int i = 0; i < length; ++i) { + expect(t, (byteArrayBody(t, array, offset + i) & 0x80) == 0); + charArrayBody(t, charArray, i) = byteArrayBody(t, array, offset + i); } @@ -5039,7 +5041,7 @@ jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) jobject pool = reinterpret_cast(arguments[0]); jint index = arguments[1]; - object array = singletonObject(t, *pool, index - 1); + object array = parseUtf8(t, singletonObject(t, *pool, index - 1)); return reinterpret_cast (makeLocalReference diff --git a/src/machine.cpp b/src/machine.cpp index 828de31fc0..0d0ad96865 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -727,7 +727,7 @@ finalizeObject(Thread* t, object o, const char* name) } unsigned -readByte(Stream& s, unsigned* value) +readByte(AbstractStream& s, unsigned* value) { if (*value == NoByte) { return s.read1(); @@ -739,8 +739,9 @@ readByte(Stream& s, unsigned* value) } object -parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, - unsigned sourceIndex, unsigned byteA, unsigned byteB) +parseUtf8NonAscii(Thread* t, AbstractStream& s, object bytesSoFar, + unsigned byteCount, unsigned sourceIndex, unsigned byteA, + unsigned byteB) { PROTECT(t, bytesSoFar); @@ -792,7 +793,7 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, } object -parseUtf8(Thread* t, Stream& s, unsigned length) +parseUtf8(Thread* t, AbstractStream& s, unsigned length) { object value = makeByteArray(t, length + 1); unsigned vi = 0; @@ -830,6 +831,14 @@ parseUtf8(Thread* t, Stream& s, unsigned length) return value; } +object +makeByteArray(Thread* t, Stream& s, unsigned length) +{ + object value = makeByteArray(t, length + 1); + s.read(reinterpret_cast(&byteArrayBody(t, value, 0)), length); + return value; +} + void removeByteArray(Thread* t, object o) { @@ -885,10 +894,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) case CONSTANT_Utf8: { if (singletonObject(t, pool, i) == 0) { - object value = parseUtf8(t, s, s.read2()); - if (objectClass(t, value) == type(t, Machine::ByteArrayType)) { - value = internByteArray(t, value); - } + object value = internByteArray(t, makeByteArray(t, s, s.read2())); set(t, pool, SingletonBody + (i * BytesPerWord), value); if(DebugClassReader) { @@ -916,7 +922,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) unsigned si = s.read2() - 1; parsePoolEntry(t, s, index, pool, si); - object value = singletonObject(t, pool, si); + object value = parseUtf8(t, singletonObject(t, pool, si)); value = t->m->classpath->makeString (t, value, 0, cast(value, BytesPerWord) - 1); value = intern(t, value); @@ -4886,6 +4892,62 @@ parseUtf8(Thread* t, const char* data, unsigned length) return ::parseUtf8(t, s, length); } +object +parseUtf8(Thread* t, object array) +{ + for (unsigned i = 0; i < byteArrayLength(t, array) - 1; ++i) { + if (byteArrayBody(t, array, i) & 0x80) { + goto slow_path; + } + } + + return array; + + slow_path: + class Client: public Stream::Client { + public: + Client(Thread* t): t(t) { } + + virtual void handleError() { + // vm::abort(t); + } + + private: + Thread* t; + } client(t); + + class MyStream: public AbstractStream { + public: + class MyProtector: public Thread::Protector { + public: + MyProtector(Thread* t, MyStream* s): + Protector(t), s(s) + { } + + virtual void visit(Heap::Visitor* v) { + v->visit(&(s->array)); + } + + MyStream* s; + }; + + MyStream(Thread* t, Client* client, object array): + AbstractStream(client, byteArrayLength(t, array) - 1), + array(array), + protector(t, this) + { } + + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) { + memcpy(dst, &byteArrayBody(protector.t, array, offset), size); + } + + object array; + MyProtector protector; + } s(t, &client, array); + + return ::parseUtf8(t, s, byteArrayLength(t, array) - 1); +} + object getCaller(Thread* t, unsigned target, bool skipMethodInvoke) { diff --git a/src/machine.h b/src/machine.h index f71788572d..08eab4c894 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2525,6 +2525,9 @@ emptyMethod(Thread* t, object method) object parseUtf8(Thread* t, const char* data, unsigned length); +object +parseUtf8(Thread* t, object array); + object parseClass(Thread* t, object loader, const uint8_t* data, unsigned length, Machine::Type throwType = Machine::NoClassDefFoundErrorType); diff --git a/src/stream.h b/src/stream.h index a08bf3b1a0..a46ad315d8 100644 --- a/src/stream.h +++ b/src/stream.h @@ -15,15 +15,15 @@ namespace vm { -class Stream { +class AbstractStream { public: class Client { public: virtual void handleError() = 0; }; - Stream(Client* client, const uint8_t* data, unsigned size): - client(client), data(data), size(size), position_(0) + AbstractStream(Client* client, unsigned size): + client(client), size(size), position_(0) { } unsigned position() { @@ -42,13 +42,13 @@ class Stream { } } - void read(uint8_t* data, unsigned size) { + void read(uint8_t* dst, unsigned size) { if (size > this->size - position_) { - memset(data, 0, size); + memset(dst, 0, size); client->handleError(); } else { - memcpy(data, this->data + position_, size); + copy(dst, position_, size); position_ += size; } } @@ -85,13 +85,29 @@ class Stream { return read8(); } + protected: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) = 0; + private: Client* client; - const uint8_t* data; unsigned size; unsigned position_; }; +class Stream: public AbstractStream { + public: + Stream(Client* client, const uint8_t* data, unsigned size): + AbstractStream(client, size), data(data) + { } + + private: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) { + memcpy(dst, data + offset, size); + } + + const uint8_t* data; +}; + } // namespace vm #endif//STREAM_H diff --git a/test/Misc.java b/test/Misc.java index 450f23d2b0..620897332f 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -1,4 +1,12 @@ public class Misc { + private static class μClass { + public int μField; + + public void μMethod(int i) { + μField = i; + } + } + private interface Bar { public int baz(); } @@ -237,5 +245,10 @@ public class Misc { System.out.println(new char[] { 'h', 'i' }); expect(! (((Object) new int[0]) instanceof Object[])); + + { μClass μInstance = new μClass(); + μInstance.μMethod(8933); + expect(μInstance.μField == 8933); + } } } From 80c8940b7f19dbb4394d9dfd07b2475296173c49 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:18:32 -0700 Subject: [PATCH 087/378] ensure joining threads are always notified when a thread exits Previously, we'd only do this if the thread exited without throwing an exception. Now we do it regardless. --- src/classpath-openjdk.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 9869538cf6..49750e7fb7 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -604,15 +604,21 @@ class MyClasspath : public Classpath { virtual void runThread(Thread* t) { + // force monitor creation so we don't get an OutOfMemory error + // later when we try to acquire it: + objectMonitor(t, t->javaThread, true); + + THREAD_RESOURCE0(t, { + vm::acquire(t, t->javaThread); + t->flags &= ~Thread::ActiveFlag; + vm::notifyAll(t, t->javaThread); + vm::release(t, t->javaThread); + }); + object method = resolveMethod (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V"); t->m->processor->invoke(t, method, t->javaThread); - - acquire(t, t->javaThread); - t->flags &= ~Thread::ActiveFlag; - notifyAll(t, t->javaThread); - release(t, t->javaThread); } virtual void From 3db9e73aa10870ba37d26edfcd8ea9907ddac709 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:19:35 -0700 Subject: [PATCH 088/378] fix GC safety issues in classpath-openjdk.cpp --- src/classpath-openjdk.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 49750e7fb7..bf1dee5050 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2376,6 +2376,8 @@ makeJmethod(Thread* t, object vmMethod, int index) if (addendum) { signature = addendumSignature(t, addendum); if (signature) { + PROTECT(t, addendum); + signature = t->m->classpath->makeString (t, signature, 0, byteArrayLength(t, signature) - 1); } @@ -2443,6 +2445,8 @@ makeJconstructor(Thread* t, object vmMethod, int index) if (addendum) { signature = addendumSignature(t, addendum); if (signature) { + PROTECT(t, addendum); + signature = t->m->classpath->makeString (t, signature, 0, byteArrayLength(t, signature) - 1); } @@ -2508,6 +2512,8 @@ makeJfield(Thread* t, object vmField, int index) if (addendum) { signature = addendumSignature(t, addendum); if (signature) { + PROTECT(t, addendum); + signature = t->m->classpath->makeString (t, signature, 0, byteArrayLength(t, signature) - 1); } From 23bb2e87433b5dd8db56c19891824b6e42a81c37 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:20:53 -0700 Subject: [PATCH 089/378] force a GC in allocate3 if the heap limit has been exceeded Otherwise, we'll throw an OOME even though there may be enough unreachable objects eligible for collection to get back below the limit. --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index 0d0ad96865..7986a5be78 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3519,7 +3519,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, break; } - if (t->heap == 0) { + if (t->heap == 0 or t->m->heap->limitExceeded()) { // fprintf(stderr, "gc"); // vmPrintTrace(t); collect(t, Heap::MinorCollection); From e8f8ebdc67a4309ce43e94c1e826bf55159a8e22 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:53:36 -0700 Subject: [PATCH 090/378] fail quickly if an object allocation cannot be satisfied Previously, we would blithely exceed the heap ceiling and force the next allocation to deal with the problem, including a major GC and possible OutOfMemoryError. As of this commit, we throw an error immediately if we find that the allocation will push us over the ceiling. --- src/heap.cpp | 44 +++++++++++++++++++++++++++++++++----------- src/heap.h | 10 +++++----- src/machine.cpp | 32 ++++++++++++++++++++------------ src/machine.h | 4 ++-- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/heap.cpp b/src/heap.cpp index 2dc23e904e..0cc13ba7dc 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -1895,21 +1895,43 @@ class MyHeap: public Heap { local::collect(&c); } - virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, - bool objectMask, unsigned* totalInBytes) + void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask, unsigned* totalInBytes, + Fixie** handle, bool immortal) { - *totalInBytes = Fixie::totalSize(sizeInWords, objectMask); - return (new (allocator->allocate(*totalInBytes)) - Fixie(&c, sizeInWords, objectMask, &(c.fixies), false))->body(); + *totalInBytes = 0; + + if (limitExceeded()) { + return 0; + } + + unsigned total = Fixie::totalSize(sizeInWords, objectMask); + void* p = allocator->tryAllocate(total); + if (p == 0) { + return 0; + } else if (limitExceeded()) { + allocator->free(p, total); + return 0; + } else { + *totalInBytes = total; + return (new (p) Fixie(&c, sizeInWords, objectMask, handle, immortal)) + ->body(); + } } - virtual void* allocateImmortalFixed(Allocator* allocator, - unsigned sizeInWords, bool objectMask, - unsigned* totalInBytes) + virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask, unsigned* totalInBytes) { - *totalInBytes = Fixie::totalSize(sizeInWords, objectMask); - return (new (allocator->allocate(*totalInBytes)) - Fixie(&c, sizeInWords, objectMask, 0, true))->body(); + return tryAllocateFixed + (allocator, sizeInWords, objectMask, totalInBytes, &(c.fixies), false); + } + + virtual void* tryAllocateImmortalFixed(Allocator* allocator, + unsigned sizeInWords, bool objectMask, + unsigned* totalInBytes) + { + return tryAllocateFixed + (allocator, sizeInWords, objectMask, totalInBytes, 0, true); } bool needsMark(void* p) { diff --git a/src/heap.h b/src/heap.h index 0ee4699914..2a6734438d 100644 --- a/src/heap.h +++ b/src/heap.h @@ -62,11 +62,11 @@ class Heap: public Allocator { virtual unsigned limit() = 0; virtual bool limitExceeded() = 0; virtual void collect(CollectionType type, unsigned footprint) = 0; - virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, - bool objectMask, unsigned* totalInBytes) = 0; - virtual void* allocateImmortalFixed(Allocator* allocator, - unsigned sizeInWords, bool objectMask, - unsigned* totalInBytes) = 0; + virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask, unsigned* totalInBytes) = 0; + virtual void* tryAllocateImmortalFixed(Allocator* allocator, + unsigned sizeInWords, bool objectMask, + unsigned* totalInBytes) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void pad(void* p) = 0; virtual void* follow(void* p) = 0; diff --git a/src/machine.cpp b/src/machine.cpp index 7986a5be78..c06d8c8159 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3531,7 +3531,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, } while (type == Machine::MovableAllocation and t->heapIndex + ceiling(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords); - + switch (type) { case Machine::MovableAllocation: { return allocateSmall(t, sizeInBytes); @@ -3540,29 +3540,37 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, case Machine::FixedAllocation: { unsigned total; object o = static_cast - (t->m->heap->allocateFixed + (t->m->heap->tryAllocateFixed (allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); - memset(o, 0, sizeInBytes); + if (o) { + memset(o, 0, sizeInBytes); - alias(o, 0) = FixedMark; - - t->m->fixedFootprint += total; - - return o; + alias(o, 0) = FixedMark; + + t->m->fixedFootprint += total; + + return o; + } else { + throw_(t, root(t, Machine::OutOfMemoryError)); + } } case Machine::ImmortalAllocation: { unsigned total; object o = static_cast - (t->m->heap->allocateImmortalFixed + (t->m->heap->tryAllocateImmortalFixed (allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); - memset(o, 0, sizeInBytes); + if (o) { + memset(o, 0, sizeInBytes); - alias(o, 0) = FixedMark; + alias(o, 0) = FixedMark; - return o; + return o; + } else { + throw_(t, root(t, Machine::OutOfMemoryError)); + } } default: abort(t); diff --git a/src/machine.h b/src/machine.h index 08eab4c894..2924a13fb7 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1784,8 +1784,8 @@ class FixedAllocator: public Allocator { s(s), base(base), offset(0), capacity(capacity) { } - virtual void* tryAllocate(unsigned) { - abort(s); + virtual void* tryAllocate(unsigned size) { + return allocate(size); } void* allocate(unsigned size, unsigned padAlignment) { From 5dcf6eae5a96d24fc045bebca8f13d59e18d46a4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 20:29:24 -0700 Subject: [PATCH 091/378] fix GC safety issue in MyClasspath::updatePackageMap --- src/classpath-openjdk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index bf1dee5050..cab2d85ba0 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -756,6 +756,7 @@ class MyClasspath : public Classpath { RUNTIME_ARRAY_BODY(packageName)[length] = 0; object key = vm::makeByteArray(t, "%s", packageName); + PROTECT(t, key); hashMapRemove (t, root(t, Machine::PackageMap), key, byteArrayHash, From 57a67fb3124d8bd8a2de09ef4311e8a50febd522 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Mon, 4 Feb 2013 14:09:02 +0100 Subject: [PATCH 092/378] Fix field names, add getters to j.l.Package --- classpath/java/lang/Package.java | 68 +++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/classpath/java/lang/Package.java b/classpath/java/lang/Package.java index ed1e4e2985..0b4be0d78f 100644 --- a/classpath/java/lang/Package.java +++ b/classpath/java/lang/Package.java @@ -17,34 +17,66 @@ public class Package { private final String implementationTitle; private final String implementationVendor; private final String implementationVersion; - private final String specementationTitle; - private final String specementationVendor; - private final String specementationVersion; + private final String specificationTitle; + private final String specificationVendor; + private final String specificationVersion; private final URL sealed; private final ClassLoader loader; Package(String name, - String implementationTitle, - String implementationVendor, - String implementationVersion, - String specementationTitle, - String specementationVendor, - String specementationVersion, - URL sealed, + String implementationTitle, + String implementationVendor, + String implementationVersion, + String specificationTitle, + String specificationVendor, + String specificationVersion, + URL sealed, ClassLoader loader) { - this.name = name; - this.implementationTitle = implementationTitle; - this.implementationVendor = implementationVendor; + this.name = name; + this.implementationTitle = implementationTitle; + this.implementationVendor = implementationVendor; this.implementationVersion = implementationVersion; - this.specementationTitle = specementationTitle; - this.specementationVendor = specementationVendor; - this.specementationVersion = specementationVersion; - this.sealed = sealed; - this.loader = loader; + this.specificationTitle = specificationTitle; + this.specificationVendor = specificationVendor; + this.specificationVersion = specificationVersion; + this.sealed = sealed; + this.loader = loader; } public String getName() { return name; } + + public String getImplementationTitle() { + return implementationTitle; + } + + public String getImplementationVendor() { + return implementationVendor; + } + + public String getImplementationVersion() { + return implementationVersion; + } + + public String getSpecificationTitle() { + return specificationTitle; + } + + public String getSpecificationVendor() { + return specificationVendor; + } + + public String getSpecificationVersion() { + return specificationVersion; + } + + public boolean isSealed() { + return sealed != null; + } + + public boolean isSealed(URL url) { + return sealed.equals(url); + } } From 757d8427ea61ce57ac7530c0f12512d9b382610f Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Tue, 5 Feb 2013 11:36:09 +0100 Subject: [PATCH 093/378] Add missing classes for Windows XP --- openjdk-src.mk | 5 +++++ openjdk.pro | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/openjdk-src.mk b/openjdk-src.mk index fbbce2e5e8..f588f471a8 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -196,6 +196,8 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/java/net/NetworkInterface_winXP.c \ $(openjdk-src)/windows/native/java/net/SocketInputStream.c \ $(openjdk-src)/windows/native/java/net/SocketOutputStream.c \ + $(openjdk-src)/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c \ + $(openjdk-src)/windows/native/java/net/TwoStacksPlainSocketImpl.c \ $(openjdk-src)/windows/native/java/util/WindowsPreferences.c \ $(openjdk-src)/windows/native/java/util/logging.c \ $(openjdk-src)/windows/native/java/util/TimeZone_md.c \ @@ -216,6 +218,9 @@ ifeq ($(platform),windows) openjdk-headers-classes += \ java.net.DualStackPlainSocketImpl \ + java.net.SocketImpl \ + java.net.TwoStacksPlainDatagramSocketImpl \ + java.net.TwoStacksPlainSocketImpl \ java.lang.ProcessImpl \ sun.io.Win32ErrorMode \ sun.nio.ch.WindowsSelectorImpl \ diff --git a/openjdk.pro b/openjdk.pro index 69b4646090..71bc20aadd 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -141,6 +141,24 @@ ; } +-keepclassmembers class java.net.TwoStacksPlainSocketImpl { + *** fd1; + *** lastfd; +} + +-keepclassmembers class java.net.AbstractPlainSocketImpl { + *** timeout; + *** trafficClass; +} + +-keepclassmembers class java.net.SocketImpl { + *** serverSocket; + *** fd; + *** address; + *** port; + *** localport; +} + -keepclassmembers class java.io.FileInputStream { private java.io.FileDescriptor fd; } From 5a07e04d56df634e8abaf2ce1bb25fbbe7ad3fda Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Feb 2013 09:48:20 -0700 Subject: [PATCH 094/378] assert that there are no outstanding Get*Critical requests during allocation When GetStringCritical or GetPrimitiveArrayCritical are called, the VM cannot risk new Java heap allocations until the corresponding release method is called because allocations may result in GC, which cannot happen while a string or array is pinned in memory. We already have a check for this latter in the footprint function used during GC, but it's best to catch the problem as early as possible. --- src/machine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/machine.cpp b/src/machine.cpp index c06d8c8159..5e08655898 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3458,6 +3458,8 @@ object allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, unsigned sizeInBytes, bool objectMask) { + expect(t, t->criticalLevel == 0); + if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) { expect(t, t->backupHeapIndex + ceiling(sizeInBytes, BytesPerWord) <= ThreadBackupHeapSizeInWords); From ce9d7c35bbb1656095faa8e1faad8237f289c117 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 6 Feb 2013 07:54:04 -0700 Subject: [PATCH 095/378] mention FreeBSD support in README.md Courtesy of Damjan Jovanovic. --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f01811b4e1..c09ec39db6 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,11 @@ Quick Start $ make $ build/windows-i386/avian -cp build/windows-i386/test Hello +#### on FreeBSD: + $ export JAVA_HOME=/usr/local/openjdk7 # or wherever you have the JDK installed + $ gmake + $ build/freebsd-x86_64/avian -cp build/freebsd-x86_64/test Hello + Adjust JAVA_HOME according to your system, but be sure to use forward slashes in the path. @@ -56,6 +61,7 @@ Avian can currently target the following platforms: * Windows (i386 and x86_64) * Mac OS X (i386, x86_64 and 32-bit PowerPC) * Apple iOS (i386 and ARM) + * FreeBSD (i386, x86_64) Building @@ -77,7 +83,7 @@ The build is directed by a single makefile and may be influenced via certain flags described below, all of which are optional. $ make \ - platform={linux,windows,darwin} \ + platform={linux,windows,darwin,freebsd} \ arch={i386,x86_64,powerpc,arm} \ process={compile,interpret} \ mode={debug,debug-fast,fast,small} \ From 13848cb520fe589fa0d59556a6a3baa8d4d65eba Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 21 Jan 2013 18:19:55 +0200 Subject: [PATCH 096/378] java.lang.Math.log() and java.lang.Math.tan() --- classpath/java-lang.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 865f3c3fb4..a671a53d1d 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -785,6 +785,12 @@ Java_java_lang_Math_cos(JNIEnv*, jclass, jdouble val) return cos(val); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_tan(JNIEnv*, jclass, jdouble val) +{ + return tan(val); +} + extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val) { @@ -797,6 +803,12 @@ Java_java_lang_Math_pow(JNIEnv*, jclass, jdouble val, jdouble exp) return pow(val, exp); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_log(JNIEnv*, jclass, jdouble val) +{ + return log(val); +} + extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val) { From 7699c12597d81bf6848056a791210ae98992eb1b Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Mon, 21 Jan 2013 22:43:29 +0100 Subject: [PATCH 097/378] Add java lang math methods --- classpath/java-lang.cpp | 38 +++++++++++++++++++++++++ classpath/java/io/RandomAccessFile.java | 6 ++++ classpath/java/lang/Math.java | 6 ++++ 3 files changed, 50 insertions(+) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index a671a53d1d..6a33a7b7c1 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -791,6 +791,44 @@ Java_java_lang_Math_tan(JNIEnv*, jclass, jdouble val) return tan(val); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_asin(JNIEnv*, jclass, jdouble val) +{ + return asin(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_acos(JNIEnv*, jclass, jdouble val) +{ + return acos(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_atan(JNIEnv*, jclass, jdouble val) +{ + return atan(val); +} + + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_sinh(JNIEnv*, jclass, jdouble val) +{ + return sinh(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_cosh(JNIEnv*, jclass, jdouble val) +{ + return cosh(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_tanh(JNIEnv*, jclass, jdouble val) +{ + return tanh(val); +} + + extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val) { diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index b6e88dd00e..6ed7eeaceb 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -56,6 +56,12 @@ public class RandomAccessFile { this.position = position; } + public int skipBytes(int count) throws IOException { + if (position + count > length()) throw new IOException(); + this.position = position + count; + return count; + } + public void readFully(byte[] buffer, int offset, int length) throws IOException { diff --git a/classpath/java/lang/Math.java b/classpath/java/lang/Math.java index 44eea9db17..5f4933244d 100644 --- a/classpath/java/lang/Math.java +++ b/classpath/java/lang/Math.java @@ -93,6 +93,12 @@ public final class Math { public static native double tan(double v); + public static native double cosh(double v); + + public static native double sinh(double v); + + public static native double tanh(double v); + public static native double acos(double v); public static native double asin(double v); From 57f4463c4c7a8e602f069ed27b2e6a6fcc5455b3 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 22 Jan 2013 21:10:16 +0200 Subject: [PATCH 098/378] RandomAccessFile --- classpath/java-io.cpp | 153 ++++++------------------ classpath/java/io/RandomAccessFile.java | 73 ++++++++--- 2 files changed, 90 insertions(+), 136 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 86020f57c8..b016c5c17a 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -155,69 +155,9 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length) } } + #ifdef PLATFORM_WINDOWS -class Mapping { - public: - Mapping(uint8_t* start, size_t length, HANDLE mapping, HANDLE file): - start(start), - length(length), - mapping(mapping), - file(file) - { } - - uint8_t* start; - size_t length; - HANDLE mapping; - HANDLE file; -}; - -inline Mapping* -map(JNIEnv* e, string_t path) -{ - Mapping* result = 0; - HANDLE file = CreateFileW(path, FILE_READ_DATA, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, - OPEN_EXISTING, 0, 0); - if (file != INVALID_HANDLE_VALUE) { - unsigned size = GetFileSize(file, 0); - if (size != INVALID_FILE_SIZE) { - HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0); - if (mapping) { - void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); - if (data) { - void* p = allocate(e, sizeof(Mapping)); - if (not e->ExceptionCheck()) { - result = new (p) - Mapping(static_cast(data), size, file, mapping); - } - } - - if (result == 0) { - CloseHandle(mapping); - } - } - } - - if (result == 0) { - CloseHandle(file); - } - } - if (result == 0 and not e->ExceptionCheck()) { - throwNew(e, "java/io/IOException", "%d", GetLastError()); - } - return result; -} - -inline void -unmap(JNIEnv*, Mapping* mapping) -{ - UnmapViewOfFile(mapping->start); - CloseHandle(mapping->mapping); - CloseHandle(mapping->file); - free(mapping); -} - class Directory { public: Directory(): handle(0), findNext(false) { } @@ -250,51 +190,9 @@ class Directory { #else // not PLATFORM_WINDOWS -class Mapping { - public: - Mapping(uint8_t* start, size_t length): - start(start), - length(length) - { } - - uint8_t* start; - size_t length; -}; - -inline Mapping* -map(JNIEnv* e, string_t path) -{ - Mapping* result = 0; - int fd = open(path, O_RDONLY); - if (fd != -1) { - struct stat s; - int r = fstat(fd, &s); - if (r != -1) { - void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (data) { - void* p = allocate(e, sizeof(Mapping)); - if (not e->ExceptionCheck()) { - result = new (p) Mapping(static_cast(data), s.st_size); - } - } - } - close(fd); - } - if (result == 0 and not e->ExceptionCheck()) { - throwNewErrno(e, "java/io/IOException"); - } - return result; -} - -inline void -unmap(JNIEnv*, Mapping* mapping) -{ - munmap(mapping->start, mapping->length); - free(mapping); -} - #endif // not PLATFORM_WINDOWS + } // namespace inline string_t getChars(JNIEnv* e, jstring path) { @@ -785,35 +683,54 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, { string_t chars = getChars(e, path); if (chars) { - Mapping* mapping = map(e, chars); + int fd = ::open((const char*)chars, O_RDONLY); + releaseChars(e, path, chars); + if (fd == -1) { + throwNewErrno(e, "java/io/IOException"); + return; + } + struct ::stat fileStats; + if(::fstat(fd, &fileStats) == -1) { + ::close(fd); + throwNewErrno(e, "java/io/IOException"); + return; + } - jlong peer = reinterpret_cast(mapping); + jlong peer = fd; e->SetLongArrayRegion(result, 0, 1, &peer); - jlong length = (mapping ? mapping->length : 0); + jlong length = fileStats.st_size; e->SetLongArrayRegion(result, 1, 1, &length); - - releaseChars(e, path, chars); } } -extern "C" JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_copy(JNIEnv* e, jclass, jlong peer, +extern "C" JNIEXPORT jint JNICALL +Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, jlong position, jbyteArray buffer, int offset, int length) { + int fd = (int)peer; + if(::lseek(fd, position, SEEK_SET) == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); - - memcpy(dst + offset, - reinterpret_cast(peer)->start + position, - length); - + ssize_t bytesRead = ::read(fd, dst + offset, length); e->ReleasePrimitiveArrayCritical(buffer, dst, 0); + + if(bytesRead == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + return (jint)bytesRead; } extern "C" JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_close(JNIEnv* e, jclass, jlong peer) +Java_java_io_RandomAccessFile_close(JNIEnv*/* e*/, jclass, jlong peer) { - unmap(e, reinterpret_cast(peer)); + int fd = (int)peer; + ::close(fd); } diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index 6ed7eeaceb..18bacb99f3 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -10,6 +10,8 @@ package java.io; +import java.lang.IllegalArgumentException; + public class RandomAccessFile { private long peer; private File file; @@ -61,27 +63,62 @@ public class RandomAccessFile { this.position = position + count; return count; } - - public void readFully(byte[] buffer, int offset, int length) - throws IOException - { - if (peer == 0) throw new IOException(); - - if (length == 0) return; - - if (position + length > this.length) { - if (position + length > length()) throw new EOFException(); - } - - if (offset < 0 || offset + length > buffer.length) + + public int read(byte b[], int off, int len) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(len == 0) + return 0; + if (position + len > this.length) + throw new EOFException(); + if (off < 0 || off + len > b.length) throw new ArrayIndexOutOfBoundsException(); - - copy(peer, position, buffer, offset, length); - - position += length; + int bytesRead = readBytes(peer, position, b, off, len); + position += bytesRead; + return bytesRead; + } + + public int read(byte b[]) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(b.length == 0) + return 0; + if (position + b.length > this.length) + throw new EOFException(); + int bytesRead = readBytes(peer, position, b, 0, b.length); + position += bytesRead; + return bytesRead; } - private static native void copy(long peer, long position, byte[] buffer, + public void readFully(byte b[], int off, int len) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(len == 0) + return; + if (position + len > this.length) + throw new EOFException(); + if (off < 0 || off + len > b.length) + throw new ArrayIndexOutOfBoundsException(); + int n = 0; + do { + int count = readBytes(peer, position, b, off + n, len - n); + if (count < 0) + throw new EOFException(); + n += count; + } while (n < len); + } + + public void readFully(byte b[]) throws IOException { + readFully(b, 0, b.length); + } + + private static native int readBytes(long peer, long position, byte[] buffer, int offset, int length); public void close() throws IOException { From eea079ea701349f109f924c9d201390a5b3baa22 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Tue, 22 Jan 2013 20:25:37 +0100 Subject: [PATCH 099/378] Fix RAF --- classpath/java/io/RandomAccessFile.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index 18bacb99f3..da9a8356b6 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -108,7 +108,8 @@ public class RandomAccessFile { int n = 0; do { int count = readBytes(peer, position, b, off + n, len - n); - if (count < 0) + position += count; + if (count == 0) throw new EOFException(); n += count; } while (n < len); From 4cd8ab59100c87801caa5177dc2c775d94c0aad1 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 24 Jan 2013 00:55:23 +0100 Subject: [PATCH 100/378] Add android platform --- classpath/java-lang.cpp | 2 ++ makefile | 15 +++++++++++++++ src/posix.cpp | 15 +++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 6a33a7b7c1..4cafd5e6cc 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -54,7 +54,9 @@ # include "signal.h" # include "sys/time.h" # include "sys/types.h" +# ifndef __ANDROID__ # include "sys/sysctl.h" +# endif # include "sys/utsname.h" # include "sys/wait.h" diff --git a/makefile b/makefile index b3cbd88a57..ab9031331b 100755 --- a/makefile +++ b/makefile @@ -353,6 +353,21 @@ ifeq ($(platform),freebsd) "-I$(JAVA_HOME)/include/freebsd" -I$(src) -pthread cflags = $(build-cflags) endif +ifeq ($(platform),android) + asm = arm + pointer-size = 4 + no-psabi = -Wno-psabi + toolchain = $(ANDROID_NDK)/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/ + cflags = -std=gnu++0x -I$(ANDROID_NDK)/platforms/android-5/arch-arm/usr/include \ + -I$(toolchain)/lib/gcc/arm-linux-androideabi/4.7/include $(common-cflags) + cflags += -marm $(no-psabi) + + cxx = $(toolchain)/bin/arm-linux-androideabi-g++ + cc = $(toolchain)/bin/arm-linux-androideabi-gcc + ar = $(toolchain)/bin/arm-linux-androideabi-ar + ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib + strip = $(toolchain)/bin/arm-linux-androideabi-strip +endif ifeq ($(platform),darwin) target-format = macho diff --git a/src/posix.cpp b/src/posix.cpp index da575eb8a4..c033956ad5 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -12,10 +12,21 @@ # define __STDC_CONSTANT_MACROS #endif +#include "sys/types.h" #ifdef __APPLE__ # include "CoreFoundation/CoreFoundation.h" # include "sys/ucontext.h" # undef assert +#elif defined __ANDROID__ +# include /* for sigcontext */ +# include /* for stack_t */ +typedef struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + unsigned long uc_sigmask; +} ucontext_t; #else # if defined __FreeBSD__ # include "limits.h" @@ -24,7 +35,7 @@ #endif #include "sys/mman.h" -#include "sys/types.h" + #include "sys/stat.h" #include "sys/time.h" #include "time.h" @@ -37,10 +48,10 @@ #include "stdint.h" #include "dirent.h" #include "sched.h" - #include "arch.h" #include "system.h" + #define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x) using namespace vm; From b0cae77b2a49b66dc5df3c0d6b4e1aeb4ce9145d Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 24 Jan 2013 16:17:52 +0200 Subject: [PATCH 101/378] Android toolchain --- makefile | 41 +++++++++++++++++++++++++++++++++-------- src/arm.h | 4 ++++ src/posix.cpp | 16 ++++++++-------- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/makefile b/makefile index ab9031331b..60b34a11f3 100755 --- a/makefile +++ b/makefile @@ -357,13 +357,34 @@ ifeq ($(platform),android) asm = arm pointer-size = 4 no-psabi = -Wno-psabi - toolchain = $(ANDROID_NDK)/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/ - cflags = -std=gnu++0x -I$(ANDROID_NDK)/platforms/android-5/arch-arm/usr/include \ - -I$(toolchain)/lib/gcc/arm-linux-androideabi/4.7/include $(common-cflags) - cflags += -marm $(no-psabi) + use-lto = false + ifeq ($(build-platform),cygwin) + ndk = "$$(cygpath -u "$(ANDROID_NDK)")" + else + ndk = $(ANDROID_NDK) + endif + + build-cflags = $(common-cflags) -I$(src) + ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) + build-system = windows + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + build-lflags = -lz -lpthread + sysroot = "$$(cygpath -w "$(ndk)/platforms/android-5/arch-arm")" + build-cflags += "-I$(JAVA_HOME)/include/win32" + else + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-$(build-arch) + sysroot = $(ndk)/platforms/android-5/arch-arm + build-cflags += "-I$(JAVA_HOME)/include/linux" + endif + toolchain = $(ndk)/toolchains/arm-linux-androideabi-4.7/prebuilt/$(toolchain-host-platform) + cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 -marm $(no-psabi) + lflags = $(common-lflags) -ldl + use-lto = false - cxx = $(toolchain)/bin/arm-linux-androideabi-g++ - cc = $(toolchain)/bin/arm-linux-androideabi-gcc + cxx = $(toolchain)/bin/arm-linux-androideabi-g++ --sysroot="$(sysroot)" + cc = $(toolchain)/bin/arm-linux-androideabi-gcc --sysroot="$(sysroot)" ar = $(toolchain)/bin/arm-linux-androideabi-ar ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib strip = $(toolchain)/bin/arm-linux-androideabi-strip @@ -540,7 +561,9 @@ ifeq ($(mode),fast) else optimization-cflags = -O3 -g3 -DNDEBUG endif - use-lto = true + ifeq ($(use-lto),) + use-lto = true + endif endif ifeq ($(mode),small) ifeq ($(use-clang),true) @@ -548,7 +571,9 @@ ifeq ($(mode),small) else optimization-cflags = -Os -g3 -DNDEBUG endif - use-lto = true + ifeq ($(use-lto),) + use-lto = true + endif endif ifeq ($(use-lto),true) diff --git a/src/arm.h b/src/arm.h index 15299ec762..7e7a4d61dd 100644 --- a/src/arm.h +++ b/src/arm.h @@ -98,6 +98,10 @@ loadMemoryBarrier() memoryBarrier(); } +#if defined(__ANDROID__) +// http://code.google.com/p/android/issues/detail?id=1803 +extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__))); +#endif inline void syncInstructionCache(const void* start, unsigned size) { diff --git a/src/posix.cpp b/src/posix.cpp index c033956ad5..95c4286b60 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -17,16 +17,16 @@ # include "CoreFoundation/CoreFoundation.h" # include "sys/ucontext.h" # undef assert -#elif defined __ANDROID__ +#elif defined(__ANDROID__) # include /* for sigcontext */ # include /* for stack_t */ -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - unsigned long uc_sigmask; -} ucontext_t; + typedef struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + unsigned long uc_sigmask; + } ucontext_t; #else # if defined __FreeBSD__ # include "limits.h" From 62104e843c3c0c6d67b55fad6002a063a2c78280 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 24 Jan 2013 06:39:14 -0800 Subject: [PATCH 102/378] Path fix --- makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index 60b34a11f3..707ab486a6 100755 --- a/makefile +++ b/makefile @@ -365,26 +365,27 @@ ifeq ($(platform),android) endif build-cflags = $(common-cflags) -I$(src) + build-lflags = -lz -lpthread ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) build-system = windows build-cxx = i686-w64-mingw32-g++ build-cc = i686-w64-mingw32-gcc - build-lflags = -lz -lpthread sysroot = "$$(cygpath -w "$(ndk)/platforms/android-5/arch-arm")" build-cflags += "-I$(JAVA_HOME)/include/win32" else - toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-$(build-arch) + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-* sysroot = $(ndk)/platforms/android-5/arch-arm build-cflags += "-I$(JAVA_HOME)/include/linux" endif toolchain = $(ndk)/toolchains/arm-linux-androideabi-4.7/prebuilt/$(toolchain-host-platform) cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 -marm $(no-psabi) - lflags = $(common-lflags) -ldl + lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -ldl use-lto = false cxx = $(toolchain)/bin/arm-linux-androideabi-g++ --sysroot="$(sysroot)" cc = $(toolchain)/bin/arm-linux-androideabi-gcc --sysroot="$(sysroot)" + as = $(toolchain)/bin/arm-linux-androideabi-as --sysroot="$(sysroot)" ar = $(toolchain)/bin/arm-linux-androideabi-ar ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib strip = $(toolchain)/bin/arm-linux-androideabi-strip From 8da990f593e4fc44666668ff5d5b6b2de05f16fd Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Fri, 25 Jan 2013 23:36:13 +0100 Subject: [PATCH 103/378] Fix android makefile --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 707ab486a6..9b4ffb954a 100755 --- a/makefile +++ b/makefile @@ -365,7 +365,7 @@ ifeq ($(platform),android) endif build-cflags = $(common-cflags) -I$(src) - build-lflags = -lz -lpthread + #build-lflags = -lz -lpthread -ldl ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) build-system = windows From ba807611282bd8072ecf1be64506c727d71d618c Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sat, 26 Jan 2013 20:51:46 +0100 Subject: [PATCH 104/378] Add android redirect to logcat --- classpath/java-io.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index b016c5c17a..1e9acdef76 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -644,6 +644,9 @@ Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path, jboolean app return -1; } } +#ifdef __ANDROID__ +#include +#endif extern "C" JNIEXPORT void JNICALL Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c) @@ -657,13 +660,18 @@ Java_java_io_FileOutputStream_write__I_3BII (JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length) { jbyte* data = static_cast(malloc(length)); + if (data == 0) { throwNew(e, "java/lang/OutOfMemoryError", 0); return; } e->GetByteArrayRegion(b, offset, length, data); - + #ifdef __ANDROID__ + if(fd == 1) { + __android_log_print(ANDROID_LOG_WARN, "net.osmand:native", "%.*s",length, data); + } + #endif if (not e->ExceptionCheck()) { doWrite(e, fd, data, length); } From ed94eafe16ed69b916e66b54cd8499ac95ae36a8 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sat, 26 Jan 2013 21:33:43 +0100 Subject: [PATCH 105/378] Fix proguard warnings Conflicts: TODO.if.merge --- vm.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/vm.pro b/vm.pro index 4cdb1654ee..8d1ab22177 100644 --- a/vm.pro +++ b/vm.pro @@ -71,6 +71,7 @@ -keep public class java.io.IOException -keep public class java.io.FileNotFoundException -keep public class java.net.SocketException +-keep public class java.util.Locale # ClassLoader.getSystemClassloader() depends on the existence of this class: From 0cbaad649589b92fb756458e232a67dcb7e2a3a7 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 28 Jan 2013 17:20:52 +0200 Subject: [PATCH 106/378] Windows Phone 8 / Windows RT initial support Conflicts: makefile --- classpath/java-io.cpp | 39 +++- classpath/java-lang.cpp | 71 ++++++- makefile | 401 ++++++++++++++++++++++++++++++-------- src/arm.h | 28 ++- src/arm.masm | 77 ++++++++ src/binaryToObject/pe.cpp | 33 ++-- src/bootimage.cpp | 44 +++-- src/common.h | 8 +- src/interpret.cpp | 19 +- src/machine.h | 3 + src/system.h | 6 + src/windows.cpp | 143 +++++++++++++- src/x86.masm | 166 ++++++++++++++++ 13 files changed, 912 insertions(+), 126 deletions(-) create mode 100644 src/arm.masm create mode 100644 src/x86.masm diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 1e9acdef76..db9882e051 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -83,6 +83,16 @@ typedef char char_t; #endif // not PLATFORM_WINDOWS +#ifndef WINAPI_FAMILY +# ifndef WINAPI_PARTITION_DESKTOP +# define WINAPI_PARTITION_DESKTOP 1 +# endif + +# ifndef WINAPI_FAMILY_PARTITION +# define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#endif // WINAPI_FAMILY + inline void* operator new(size_t, void* p) throw() { return p; } typedef const char_t* string_t; @@ -214,6 +224,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) { #ifdef PLATFORM_WINDOWS +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) string_t chars = getChars(e, path); if (chars) { const unsigned BufferSize = MAX_PATH; @@ -228,6 +239,11 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) } return path; +# else + // WinRT has no concept of full paths + throwNewErrno(e, "java/io/IOException"); + return path; +# endif #else jstring result = path; string_t chars = getChars(e, path); @@ -256,11 +272,24 @@ Java_java_io_File_length(JNIEnv* e, jclass, jstring path) LARGE_INTEGER fileSize; string_t chars = getChars(e, path); + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE file = CreateFileW (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + #else + HANDLE file = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + #endif releaseChars(e, path, chars); if (file != INVALID_HANDLE_VALUE) + { + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) GetFileSizeEx(file, &fileSize); + #else + FILE_STANDARD_INFO info; + if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + fileSize = info.EndOfFile; + #endif + } else return 0; CloseHandle(file); return static_cast(fileSize.QuadPart); @@ -496,7 +525,11 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) releaseChars(e, path, chars); Directory* d = new (malloc(sizeof(Directory))) Directory; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data)); + #else + d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, NULL, 0); + #endif if (d->handle == INVALID_HANDLE_VALUE) { d->dispose(); d = 0; @@ -725,7 +758,11 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) ssize_t bytesRead = ::read(fd, dst + offset, length); +#else + auto bytesRead = ::read(fd, dst + offset, length); +#endif e->ReleasePrimitiveArrayCritical(buffer, dst, 0); if(bytesRead == -1) { @@ -737,7 +774,7 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, } extern "C" JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_close(JNIEnv*/* e*/, jclass, jlong peer) +Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer) { int fd = (int)peer; ::close(fd); diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 4cafd5e6cc..0414216194 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -62,6 +62,16 @@ #endif // not PLATFORM_WINDOWS +#ifndef WINAPI_FAMILY +# ifndef WINAPI_PARTITION_DESKTOP +# define WINAPI_PARTITION_DESKTOP 1 +# endif + +# ifndef WINAPI_FAMILY_PARTITION +# define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#endif // WINAPI_FAMILY + namespace { #ifdef PLATFORM_WINDOWS char* getErrorStr(DWORD err){ @@ -70,7 +80,8 @@ namespace { snprintf(errStr, 9, "%d", (int) err); return errStr; - // The better way to do this, if I could figure out how to convert LPTSTR to char* + //TODO: + // The better way to do this, if I could figure out how to convert LPTSTR to char* //char* errStr; //LPTSTR s; //if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -83,6 +94,7 @@ namespace { //return errStr; } +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void makePipe(JNIEnv* e, HANDLE p[2]) { SECURITY_ATTRIBUTES sa; @@ -95,6 +107,7 @@ namespace { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); } } +#endif int descriptor(JNIEnv* e, HANDLE h) { @@ -196,7 +209,7 @@ extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { - +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i){ jstring element = (jstring) e->GetObjectArrayElement(command, i); @@ -267,11 +280,15 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass, e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif } extern "C" JNIEXPORT jint JNICALL Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) DWORD exitCode; WaitForSingleObject(reinterpret_cast(pid), INFINITE); BOOL success = GetExitCodeProcess(reinterpret_cast(pid), &exitCode); @@ -283,14 +300,23 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) CloseHandle(reinterpret_cast(tid)); return exitCode; +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); + return -1; +#endif } extern "C" JNIEXPORT void JNICALL -Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid) { +Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TerminateProcess(reinterpret_cast(pid), 1); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif } Locale getLocale() { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) const char* lang = ""; const char* reg = ""; unsigned langid = GetUserDefaultUILanguage(); @@ -362,8 +388,11 @@ Locale getLocale() { default: lang = "en"; } - Locale locale(lang, reg); - return locale; + return Locale(lang, reg); +#else + //TODO: CultureInfo.CurrentCulture + return Locale("en", "US"); +#endif } #else extern "C" JNIEXPORT void JNICALL @@ -531,8 +560,15 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, } else if (strcmp(chars, "file.separator") == 0) { r = e->NewStringUTF("\\"); } else if (strcmp(chars, "os.name") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) r = e->NewStringUTF("Windows"); +# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + r = e->NewStringUTF("Windows Phone"); +# else + r = e->NewStringUTF("Windows RT"); +# endif } else if (strcmp(chars, "os.version") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) unsigned size = 32; RUNTIME_ARRAY(char, buffer, size); OSVERSIONINFO OSversion; @@ -540,6 +576,10 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, ::GetVersionEx(&OSversion); snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%i.%i", (int)OSversion.dwMajorVersion, (int)OSversion.dwMinorVersion); r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer)); +# else + // Currently there is no alternative on WinRT/WP8 + r = e->NewStringUTF("8.0"); +# endif } else if (strcmp(chars, "os.arch") == 0) { #ifdef ARCH_x86_32 r = e->NewStringUTF("x86"); @@ -551,15 +591,28 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = e->NewStringUTF("arm"); #endif } else if (strcmp(chars, "java.io.tmpdir") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TCHAR buffer[MAX_PATH]; GetTempPath(MAX_PATH, buffer); r = e->NewStringUTF(buffer); +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.Storage.ApplicationData.Current.TemporaryFolder + r = 0; +# endif } else if (strcmp(chars, "user.dir") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TCHAR buffer[MAX_PATH]; GetCurrentDirectory(MAX_PATH, buffer); r = e->NewStringUTF(buffer); +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.ApplicationModel.Package.Current.InstalledLocation + r = 0; +# endif } else if (strcmp(chars, "user.home") == 0) { # ifdef _MSC_VER +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) WCHAR buffer[MAX_PATH]; size_t needed; if (_wgetenv_s(&needed, buffer, MAX_PATH, L"USERPROFILE") == 0) { @@ -567,6 +620,11 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, } else { r = 0; } +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.Storage.KnownFolders.DocumentsLibrary; + r = 0; +# endif # else LPWSTR home = _wgetenv(L"USERPROFILE"); r = e->NewString(reinterpret_cast(home), lstrlenW(home)); @@ -654,6 +712,9 @@ namespace { #elif defined __APPLE__ # include # define environ (*_NSGetEnviron()) +#elif defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +// WinRT/WP8 does not provide alternative for environment variables +char* environ[] = { 0 }; #else extern char** environ; #endif diff --git a/makefile b/makefile index 9b4ffb954a..28ef8be401 100755 --- a/makefile +++ b/makefile @@ -51,7 +51,7 @@ ifeq ($(continuations),true) endif root := $(shell (cd .. && pwd)) -build = build/$(platform)-$(arch)$(options) +build = $(build-prefix)build/$(platform)-$(arch)$(options) classpath-build = $(build)/classpath test-build = $(build)/test src = src @@ -59,6 +59,8 @@ classpath-src = classpath test = test win32 ?= $(root)/win32 win64 ?= $(root)/win64 +winrt ?= $(root)/winrt +wp8 ?= $(root)/wp8 classpath = avian @@ -183,6 +185,18 @@ strip-all = --strip-all rdynamic = -rdynamic +cflags_debug = -O0 -g3 +cflags_debug_fast = -O0 -g3 +cflags_stress = -O0 -g3 +cflags_stress_major = -O0 -g3 +ifeq ($(use-clang),true) + cflags_fast = -O4 -g3 + cflags_small = -Oz -g3 +else + cflags_fast = -O3 -g3 + cflags_small = -Os -g3 +endif + # note that we suppress the non-virtual-dtor warning because we never # use the delete operator, which means we don't need virtual # destructors: @@ -198,7 +212,7 @@ common-cflags = $(warnings) -fno-rtti -fno-exceptions -I$(classpath-src) \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags) -asmflags = $(target-cflags) +asmflags = $(target-cflags) -I$(src) ifneq (,$(filter i386 x86_64,$(arch))) ifeq ($(use-frame-pointer),true) @@ -237,6 +251,18 @@ pointer-size = 8 so-prefix = lib so-suffix = .so +static-prefix = lib +static-suffix = .a + +output = -o $(1) +asm-output = -o $(1) +asm-input = -c $(1) +asm-format = S +as = $(cc) +ld = $(cxx) +build-ld = $(build-cc) + +static = -static shared = -shared no-error = -Wno-error @@ -244,6 +270,8 @@ no-error = -Wno-error openjdk-extra-cflags = -fvisibility=hidden bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) +bootimage-symbols = _binary_bootimage_bin_start:_binary_bootimage_bin_end +codeimage-symbols = _binary_codeimage_bin_start:_binary_codeimage_bin_end developer-dir := $(shell if test -d /Developer; then echo /Developer; \ else echo /Applications/Xcode.app/Contents/Developer; fi) @@ -354,41 +382,68 @@ ifeq ($(platform),freebsd) cflags = $(build-cflags) endif ifeq ($(platform),android) - asm = arm - pointer-size = 4 - no-psabi = -Wno-psabi - use-lto = false - ifeq ($(build-platform),cygwin) + ifeq ($(build-platform),cygwin) ndk = "$$(cygpath -u "$(ANDROID_NDK)")" else ndk = $(ANDROID_NDK) endif + ifeq ($(android-version),) + android-version = 5 + endif + + ifeq ($(android-toolchain),) + android-toolchain = 4.7 + endif + + ifeq ($(arch),arm) + android-toolchain-name = arm-linux-androideabi + android-toolchain-prefix = arm-linux-androideabi- + endif + ifeq ($(arch),i386) + android-toolchain-name = x86 + android-toolchain-prefix = i686-linux-android- + endif + + ifeq ($(android-arm-arch),) + android-arm-arch = armv5 + endif + + options := $(options)-api$(android-version)-$(android-toolchain)-$(android-arm-arch) + build-cflags = $(common-cflags) -I$(src) - #build-lflags = -lz -lpthread -ldl + build-lflags = -lz -lpthread ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) build-system = windows build-cxx = i686-w64-mingw32-g++ build-cc = i686-w64-mingw32-gcc - sysroot = "$$(cygpath -w "$(ndk)/platforms/android-5/arch-arm")" + sysroot = "$$(cygpath -w "$(ndk)/platforms/android-$(android-version)/arch-arm")" build-cflags += "-I$(JAVA_HOME)/include/win32" else toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-* - sysroot = $(ndk)/platforms/android-5/arch-arm + sysroot = $(ndk)/platforms/android-$(android-version)/arch-arm build-cflags += "-I$(JAVA_HOME)/include/linux" + build-lflags += -ldl endif - toolchain = $(ndk)/toolchains/arm-linux-androideabi-4.7/prebuilt/$(toolchain-host-platform) - cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 -marm $(no-psabi) - lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -ldl + toolchain = $(ndk)/toolchains/$(android-toolchain-name)-$(android-toolchain)/prebuilt/$(toolchain-host-platform) + cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 $(no-psabi) + lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -llog + target-format = elf use-lto = false - cxx = $(toolchain)/bin/arm-linux-androideabi-g++ --sysroot="$(sysroot)" - cc = $(toolchain)/bin/arm-linux-androideabi-gcc --sysroot="$(sysroot)" - as = $(toolchain)/bin/arm-linux-androideabi-as --sysroot="$(sysroot)" - ar = $(toolchain)/bin/arm-linux-androideabi-ar - ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib - strip = $(toolchain)/bin/arm-linux-androideabi-strip + ifeq ($(arch),arm) + cflags += -marm -march=$(android-arm-arch) -ftree-vectorize -ffast-math -mfloat-abi=softfp + endif + ifeq ($(arch),i386) + endif + + cxx = $(toolchain)/bin/$(android-toolchain-prefix)g++ --sysroot="$(sysroot)" + cc = $(toolchain)/bin/$(android-toolchain-prefix)gcc --sysroot="$(sysroot)" + as = $(cxx) + ar = $(toolchain)/bin/$(android-toolchain-prefix)ar + ranlib = $(toolchain)/bin/$(android-toolchain-prefix)ranlib + strip = $(toolchain)/bin/$(android-toolchain-prefix)strip endif ifeq ($(platform),darwin) @@ -475,7 +530,9 @@ ifeq ($(platform),darwin) endif ifeq ($(platform),windows) - target-format = pe + ifeq ($(target-format),) + target-format = pe + endif inc = "$(win32)/include" lib = "$(win32)/lib" @@ -488,7 +545,8 @@ ifeq ($(platform),windows) so-suffix = .dll exe-suffix = .exe - lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mwindows -mconsole + lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mconsole + bootimage-generator-lflags = -static-libstdc++ -static-libgcc cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 ifeq (,$(filter mingw32 cygwin,$(build-platform))) @@ -539,39 +597,197 @@ ifeq ($(platform),windows) embed-loader-o = $(build-embed)/embed-loader.o endif +ifeq ($(platform),wp8) + ifeq ($(shell uname -s | grep -i -c WOW64),1) + programFiles = Program Files (x86) + else + programFiles = Program Files + endif + ifeq ($(MSVS_ROOT),) + # Environment variable MSVS_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0" + MSVS_ROOT = C:\$(programFiles)\Microsoft Visual Studio 11.0 + endif + ifeq ($(MSVC_ROOT),) + # Environment variable MSVC_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0\VC" + MSVC_ROOT = $(MSVS_ROOT)\VC + endif + ifeq ($(WP80_SDK),) + # Environment variable WP8_SDK not found. It should be something like + # "C:\Program Files[ (x86)]\Microsoft Visual Studio 11.0\VC\WPSDK\WP80" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_SDK = C:\$(programFiles)\Microsoft Visual Studio 11.0\VC\WPSDK\WP80 + endif + ifeq ($(WP80_KIT),) + # Environment variable WP8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Phone Kits\8.0" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_KIT = C:\$(programFiles)\Windows Phone Kits\8.0 + endif + ifeq ($(WIN8_KIT),) + # Environment variable WIN8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Kits\8.0" + WIN8_KIT = C:\$(programFiles)\Windows Kits\8.0 + endif + ifeq ($(build-platform),cygwin) + windows-path = cygpath -w + else + windows-path = $(native-path) + endif + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + target-format = pe + ms_cl_compiler = wp8 + use-lto = false + supports_avian_executable = false + process = interpret + ifneq ($(process),compile) + options := -$(process) + endif + bootimage = true + ifeq ($(bootimage),true) + options := $(options)-bootimage + endif + system = windows + build-system = windows + static-prefix = + static-suffix = .lib + so-prefix = + so-suffix = .dll + exe-suffix = .exe + + ifeq ($(arch),arm) + wp8_arch = \x86_arm + vc_arch = \arm + w8kit_arch = arm + deps_arch = ARM + as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" + asmflags = -machine ARM -32 + asm-output = -o $(1) + asm-input = $(1) + machine_type = ARM + bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end + codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end + endif + ifeq ($(arch),i386) + wp8_arch = + vc_arch = + w8kit_arch = x86 + deps_arch = x86 + as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" + asmflags += -nologo + asm-output = $(output) + machine_type = X86 + endif + + PATH := $(shell cygpath -u "$(MSVS_ROOT)\Common7\IDE"):$(shell cygpath -u "$(WP80_SDK)\bin$(wp8_arch)"):$(shell cygpath -u "$(WP80_SDK)\bin"):${PATH} + + build-cflags = $(common-cflags) -I$(src) -I$(inc) -mthreads + build-lflags = -lz -lpthread + + cflags = -nologo \ + -I"$(WP80_SDK)\include" -I"$(WP80_KIT)\Include" -I"$(WP80_KIT)\Include\minwin" -I"$(WP80_KIT)\Include\mincore" \ + -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP \ + -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ + -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" \ + -Fd$(build)/$(name).pdb -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ + -I"$(build)" \ + -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ + -DTARGET_BYTES_PER_WORD=$(pointer-size) + + common-lflags = $(classpath-lflags) + + arflags = -MACHINE:$(machine_type) + lflags = $(common-lflags) -nologo \ + -MACHINE:$(machine_type) \ + -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ + ws2_32.lib \ + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\ThreadEmulation.lib")" + + cc = $(cxx) + asm-format = masm + shared = -dll + ar = "$$(cygpath -u "$(WP80_SDK)\bin\lib.exe")" + arflags += -nologo + ifeq ($(build-platform),cygwin) + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + dlltool = i686-w64-mingw32-dlltool + ranlib = + strip = + endif + output = -Fo$(1) + + cflags_debug = -Od -Zi -MDd + cflags_debug_fast = -Od -Zi -MDd + cflags_stress = -O0 -g3 -MD + cflags_stress_major = -O0 -g3 -MD + cflags_fast = -O2 -Zi -MD + cflags_small = -O1s -Zi -MD + # -GL [whole program optimization] in 'fast' and 'small' breaks compilation for some reason + + ifeq ($(mode),debug) + cflags += + lflags += + endif + ifeq ($(mode),debug-fast) + cflags += -DNDEBUG + lflags += + endif + ifeq ($(mode),stress_major) + cflags += + lflags += + endif + ifeq ($(mode),fast) + cflags += + lflags += + endif + # -LTCG is needed only if -GL is used + ifeq ($(mode),fast) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + ifeq ($(mode),small) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + + strip = : +endif + ifeq ($(mode),debug) - optimization-cflags = -O0 -g3 - converter-cflags += -O0 -g3 + optimization-cflags = $(cflags_debug) + converter-cflags += $(cflags_debug) strip = : endif ifeq ($(mode),debug-fast) - optimization-cflags = -O0 -g3 -DNDEBUG + optimization-cflags = $(cflags_debug_fast) -DNDEBUG strip = : endif ifeq ($(mode),stress) - optimization-cflags = -O0 -g3 -DVM_STRESS + optimization-cflags = $(cflags_stress) -DVM_STRESS strip = : endif ifeq ($(mode),stress-major) - optimization-cflags = -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR + optimization-cflags = $(cflags_stress_major) -DVM_STRESS -DVM_STRESS_MAJOR strip = : endif ifeq ($(mode),fast) - ifeq ($(use-clang),true) - optimization-cflags = -O4 -g3 -DNDEBUG - else - optimization-cflags = -O3 -g3 -DNDEBUG - endif + optimization-cflags = $(cflags_fast) -DNDEBUG ifeq ($(use-lto),) use-lto = true endif endif ifeq ($(mode),small) - ifeq ($(use-clang),true) - optimization-cflags = -Oz -g3 -DNDEBUG - else - optimization-cflags = -Os -g3 -DNDEBUG - endif + optimization-cflags = $(cflags_small) -DNDEBUG ifeq ($(use-lto),) use-lto = true endif @@ -596,6 +812,7 @@ endif cflags += $(optimization-cflags) +ifndef ms_cl_compiler ifneq ($(platform),darwin) ifeq ($(arch),i386) # this is necessary to support __sync_bool_compare_and_swap: @@ -603,16 +820,9 @@ ifeq ($(arch),i386) lflags += -march=i586 endif endif - -output = -o $(1) -as := $(cc) -ld := $(cc) -build-ld := $(build-cc) - -static = -static +endif ifdef msvc - static = no-error = windows-path = $(native-path) windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") @@ -621,6 +831,7 @@ ifdef msvc cc = $(cxx) ld = "$(msvc)/BIN/link.exe" mt = "mt.exe" + manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ @@ -629,7 +840,7 @@ ifdef msvc -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ -DTARGET_BYTES_PER_WORD=$(pointer-size) - ifneq ($(lzma),) + ifneq ($(lzma),) cflags += -I$(shell $(windows-path) "$(lzma)") endif @@ -656,9 +867,11 @@ ifdef msvc strip = : endif +build-cflags += -DAVIAN_HOST_TARGET + c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) -asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x))) +asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.$(asm-format),$(3)/%-asm.o,$(x))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) generated-code = \ @@ -684,7 +897,7 @@ vm-sources = \ $(src)/jnienv.cpp \ $(src)/process.cpp -vm-asm-sources = $(src)/$(asm).S +vm-asm-sources = $(src)/$(asm).$(asm-format) target-asm = $(asm) @@ -702,8 +915,9 @@ ifeq ($(process),compile) $(src)/compiler.cpp \ $(src)/$(target-asm).cpp - vm-asm-sources += $(src)/compile-$(asm).S + vm-asm-sources += $(src)/compile-$(asm).$(asm-format) endif +cflags += -DAVIAN_PROCESS_$(process) vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(build)) vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build)) @@ -835,7 +1049,7 @@ converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) converter = $(build)/binaryToObject/binaryToObject -static-library = $(build)/lib$(name).a +static-library = $(build)/$(static-prefix)$(name)${static-suffix} executable = $(build)/$(name)${exe-suffix} dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) executable-dynamic = $(build)/$(name)-dynamic${exe-suffix} @@ -945,9 +1159,15 @@ test-flags = -Djava.library.path=$(build) -cp $(build)/test test-args = $(test-flags) $(input) .PHONY: build +ifneq ($(supports_avian_executable),false) build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ $(test-extra-dep) $(embed) +else +build: $(static-library) $(dynamic-library) $(lzma-loader) \ + $(lzma-encoder) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(embed) +endif $(test-dep): $(classpath-dep) @@ -992,7 +1212,7 @@ clean: @echo "removing build" rm -rf build -$(build)/compile-x86-asm.o: $(src)/continuations-x86.S +$(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) @@ -1043,7 +1263,7 @@ endef define compile-asm-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(as) -I$(src) $(asmflags) -c $(<) -o $(@) + $(as) $(asmflags) $(call asm-output,$(@)) $(call asm-input,$(<)) endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) @@ -1054,10 +1274,12 @@ $(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) $(test-library): $(test-cpp-objects) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(test-build)/$(name).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);2" + -IMPLIB:$(test-build)/$(name).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif else $(ld) $(^) $(shared) $(lflags) -o $(@) endif @@ -1065,10 +1287,12 @@ endif ifdef embed $(embed): $(embed-objects) $(embed-loader-o) @echo "building $(embed)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(cxx) $(^) $(lflags) $(static) $(call output,$(@)) endif @@ -1086,10 +1310,12 @@ $(embed-loader-o): $(embed-loader) $(converter) $(embed-loader): $(embed-loader-objects) $(static-library) @mkdir -p $(dir $(@)) cd $(dir $(@)) && $(ar) x ../../../$(static-library) -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(dir $(@))/*.o $(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@))) @@ -1109,7 +1335,7 @@ $(build)/%.o: $(lzma)/C/%.c @mkdir -p $(dir $(@)) $(cxx) $(cflags) $(no-error) -c $$($(windows-path) $(<)) $(call output,$(@)) -$(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S +$(vm-asm-objects): $(build)/%-asm.o: $(src)/%.$(asm-format) $(compile-asm-object) $(bootimage-generator-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) @@ -1196,14 +1422,18 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) @echo "creating $(@)" rm -rf $(@) +ifdef ms_cl_compiler + $(ar) $(arflags) $(^) -out:$(@) +else $(ar) cru $(@) $(^) $(ranlib) $(@) +endif -$(bootimage-object) $(codeimage-object): $(bootimage-generator) \ - $(build)/classpath.jar +$(bootimage-object) $(codeimage-object): $(bootimage-generator) + @echo "generating bootimage and codeimage binaries using $(<)" $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ - -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ - -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end + -bootimage-symbols $(bootimage-symbols) \ + -codeimage-symbols $(codeimage-symbols) executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ @@ -1212,10 +1442,12 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(executable): $(executable-objects) @echo "linking $(@)" ifeq ($(platform),windows) -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(executable-objects) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(@).def $(executable-objects) $(dlltool) -d $(@).def -e $(@).exp @@ -1229,6 +1461,7 @@ endif $(bootimage-generator): $(bootimage-generator-objects) echo arch=$(arch) platform=$(platform) $(MAKE) mode=$(mode) \ + build-prefix=$(build)/host/ \ arch=$(build-arch) \ target-arch=$(arch) \ platform=$(bootimage-platform) \ @@ -1247,17 +1480,19 @@ $(build-bootimage-generator): \ $(lzma-decode-objects) $(lzma-encode-objects) @echo "linking $(@)" ifeq ($(platform),windows) -ifdef msvc - $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb -IMPLIB:$(@).lib \ - -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" +ifdef ms_cl_compiler + $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(@).def $(^) $(dlltool) -d $(@).def -e $(@).exp - $(ld) $(@).exp $(^) $(lflags) -o $(@) + $(ld) $(@).exp $(^) $(bootimage-generator-lflags) $(lflags) -o $(@) endif else - $(ld) $(^) $(rdynamic) $(lflags) -o $(@) + $(ld) $(^) $(rdynamic) $(bootimage-generator-lflags) $(lflags) -o $(@) endif $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ @@ -1265,10 +1500,12 @@ $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(classpath-libraries) $(javahome-object) $(boot-javahome-object) \ $(lzma-decode-objects) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);2" + -IMPLIB:$(build)/$(name).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif else $(ld) $(^) $(version-script-flag) $(soname-flag) \ $(shared) $(lflags) $(bootimage-lflags) \ @@ -1280,11 +1517,13 @@ endif # Ubuntu 11.10 which may be fixable without disabling LTO. $(executable-dynamic): $(driver-dynamic-objects) $(dynamic-library) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) -LIBPATH:$(build) -DEFAULTLIB:$(name) \ - -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) -out:$(@) \ - -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) \ + -out:$(@) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) -o $(@) endif diff --git a/src/arm.h b/src/arm.h index 7e7a4d61dd..adfd92b4ad 100644 --- a/src/arm.h +++ b/src/arm.h @@ -71,33 +71,53 @@ namespace vm { inline void trap() { +#ifdef _MSC_VER + __debugbreak(); +#else asm("bkpt"); +#endif } +#ifndef _MSC_VER inline void memoryBarrier() { asm("nop"); } +#endif inline void storeStoreMemoryBarrier() { +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else memoryBarrier(); +#endif } inline void storeLoadMemoryBarrier() { +#ifdef _MSC_VER + MemoryBarrier(); +#else memoryBarrier(); +#endif } inline void loadMemoryBarrier() { +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else memoryBarrier(); +#endif } +#if defined(AVIAN_PROCESS_compile) + #if defined(__ANDROID__) // http://code.google.com/p/android/issues/detail?id=1803 extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__))); @@ -116,6 +136,8 @@ syncInstructionCache(const void* start, unsigned size) #endif } +#endif // AVIAN_PROCESS_compile + #ifndef __APPLE__ typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); # define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) @@ -160,7 +182,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, unsigned vfpIndex = 0; unsigned vfpBackfillIndex UNUSED = 0; - uintptr_t stack[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding + uintptr_t* stack = new uintptr_t[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding unsigned stackIndex = 0; unsigned ai = 0; @@ -250,10 +272,12 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, } unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2); - return vmNativeCall + auto retVal = vmNativeCall (function, stackSize, stack, stackIndex * BytesPerWord, (gprIndex ? gprTable : 0), (vfpIndex ? vfpTable : 0), returnType); + delete[] stack; + return retVal; } } // namespace vm diff --git a/src/arm.masm b/src/arm.masm new file mode 100644 index 0000000000..8fc09eb875 --- /dev/null +++ b/src/arm.masm @@ -0,0 +1,77 @@ + AREA text, CODE, ARM + + EXPORT vmNativeCall [FUNC] +vmNativeCall + ; arguments: + ; r0 -> r4 : function + ; r1 -> r5 : stackTotal + ; r2 : memoryTable + ; r3 : memoryCount + ; [sp, #0] -> r6 : gprTable + + mov ip, sp ; save stack frame + stmfd sp!, {r4-r6, lr} ; save clobbered non-volatile regs + + ; mv args into non-volatile regs + mov r4, r0 + mov r5, r1 + ldr r6, [ip] + + ; setup stack arguments if necessary + sub sp, sp, r5 ; allocate stack + mov ip, sp +loop + tst r3, r3 + ldrne r0, [r2], #4 + strne r0, [ip], #4 + subne r3, r3, #4 + bne loop + + ; setup argument registers if necessary + tst r6, r6 + ldmneia r6, {r0-r3} + + blx r4 ; call function + add sp, sp, r5 ; deallocate stack + + ldmfd sp!, {r4-r6, pc} ; restore non-volatile regs and return + + EXPORT vmJump [FUNC] +vmJump + mov lr, r0 + ldr r0, [sp] + ldr r1, [sp, #4] + mov sp, r2 + mov r8, r3 + bx lr + +CHECKPOINT_THREAD EQU 4 +CHECKPOINT_STACK EQU 24 + + EXPORT vmRun [FUNC] +vmRun + ; r0: function + ; r1: arguments + ; r2: checkpoint + stmfd sp!, {r4-r11, lr} + ; align stack + sub sp, sp, #12 + + str sp, [r2, #CHECKPOINT_STACK] + + mov r12, r0 + ldr r0, [r2, #CHECKPOINT_THREAD] + + blx r12 + + EXPORT vmRun_returnAddress [FUNC] +vmRun_returnAddress + add sp, sp, #12 + ldmfd sp!, {r4-r11, lr} + bx lr + + EXPORT vmTrap [FUNC] +vmTrap + bkpt 3 + + END \ No newline at end of file diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 8d5d5fc444..186e491447 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -17,13 +17,17 @@ namespace { -#define IMAGE_SIZEOF_SHORT_NAME 8 +// --- winnt.h ---- +#define IMAGE_SIZEOF_SHORT_NAME 8 -#define IMAGE_FILE_RELOCS_STRIPPED 1 -#define IMAGE_FILE_LINE_NUMS_STRIPPED 4 -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_32BIT_MACHINE 256 +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) +#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. #define IMAGE_SCN_ALIGN_1BYTES 0x100000 #define IMAGE_SCN_ALIGN_2BYTES 0x200000 @@ -73,6 +77,7 @@ struct IMAGE_SYMBOL { uint8_t StorageClass; uint8_t NumberOfAuxSymbols; } __attribute__((packed)); +// --- winnt.h ---- inline unsigned pad(unsigned n) @@ -82,7 +87,7 @@ pad(unsigned n) using namespace avian::tools; -template +template class WindowsPlatform : public Platform { public: @@ -202,12 +207,15 @@ public: int machine; int machineMask; - if (BytesPerWord == 8) { + if (Architecture == PlatformInfo::x86_64) { machine = IMAGE_FILE_MACHINE_AMD64; machineMask = 0; - } else { // if (BytesPerWord == 8) + } else if (Architecture == PlatformInfo::x86) { machine = IMAGE_FILE_MACHINE_I386; machineMask = IMAGE_FILE_32BIT_MACHINE; + } else if (Architecture == PlatformInfo::Arm) { + machine = IMAGE_FILE_MACHINE_ARMNT; + machineMask = IMAGE_FILE_32BIT_MACHINE; } int sectionMask; @@ -269,10 +277,11 @@ public: } WindowsPlatform(): - Platform(PlatformInfo(PlatformInfo::Pe, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {} + Platform(PlatformInfo(PlatformInfo::Pe, Architecture)) {} }; -WindowsPlatform<4> windows32Platform; -WindowsPlatform<8> windows64Platform; +WindowsPlatform<4, PlatformInfo::x86> windows32Platform; +WindowsPlatform<8, PlatformInfo::x86_64> windows64Platform; +WindowsPlatform<4, PlatformInfo::Arm> windowsRtPlatform; // Windows Phone 8 and Windows RT } // namespace diff --git a/src/bootimage.cpp b/src/bootimage.cpp index f82e73f9f5..ec04196ca0 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -342,7 +342,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, unsigned count = s.read2() - 1; if (count) { - Type types[count + 2]; + Type* types = new Type[count + 2]; types[0] = Type_object; types[1] = Type_intptr_t; @@ -410,6 +410,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, (t, typeMaps, hashMapFind (t, root(t, Machine::PoolMap), c, objectHash, objectEqual), array, objectHash); + + delete[] types; + types = 0; } } @@ -420,7 +423,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object fields = allFields(t, typeMaps, c, &count, &array); PROTECT(t, fields); - Field memberFields[count + 1]; + Field* memberFields = new Field[count + 1]; unsigned memberIndex; unsigned buildMemberOffset; @@ -454,7 +457,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, const unsigned StaticHeader = 3; - Field staticFields[count + StaticHeader]; + Field* staticFields = new Field[count + StaticHeader]; init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -586,6 +589,12 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, hashMapInsert (t, typeMaps, classStaticTable(t, c), array, objectHash); } + + delete[] memberFields; + memberFields = 0; + + delete[] staticFields; + staticFields = 0; } } } @@ -1334,7 +1343,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp } ++ count; - Field fields[count]; + Field* fields = new Field[count]; init(new (fields) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -1462,6 +1471,9 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp hashMapInsert (t, typeMaps, vm::type(t, static_cast(i)), array, objectHash); + + delete[] fields; + fields = 0; } constants = makeCodeImage @@ -1646,10 +1658,10 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp Platform* platform = Platform::getPlatform(PlatformInfo((PlatformInfo::Format)AVIAN_TARGET_FORMAT, (PlatformInfo::Architecture)AVIAN_TARGET_ARCH)); - // if(!platform) { - // fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); - // return false; - // } + if(!platform) { + fprintf(stderr, "unsupported platform: target-format = %d / target-arch = %d\n", AVIAN_TARGET_FORMAT, AVIAN_TARGET_ARCH); + abort(); + } SymbolInfo bootimageSymbols[] = { SymbolInfo(0, bootimageStart), @@ -1768,7 +1780,7 @@ bool ArgParser::parse(int ac, const char** av) { } bool found = false; for(Arg* arg = first; arg; arg = arg->next) { - if(strcmp(arg->name, &av[i][1]) == 0) { + if(::strcmp(arg->name, &av[i][1]) == 0) { found = true; if (arg->desc == 0) { arg->value = "true"; @@ -1905,20 +1917,26 @@ public: exit(1); } +# if AVIAN_TARGET_FORMAT != AVIAN_FORMAT_PE +# define SYMBOL_PREFIX "_" +# else +# define SYMBOL_PREFIX +# endif + if(!bootimageStart) { - bootimageStart = strdup("_binary_bootimage_bin_start"); + bootimageStart = strdup(SYMBOL_PREFIX"binary_bootimage_bin_start"); } if(!bootimageEnd) { - bootimageEnd = strdup("_binary_bootimage_bin_end"); + bootimageEnd = strdup(SYMBOL_PREFIX"binary_bootimage_bin_end"); } if(!codeimageStart) { - codeimageStart = strdup("_binary_codeimage_bin_start"); + codeimageStart = strdup(SYMBOL_PREFIX"binary_codeimage_bin_start"); } if(!codeimageEnd) { - codeimageEnd = strdup("_binary_codeimage_bin_end"); + codeimageEnd = strdup(SYMBOL_PREFIX"binary_codeimage_bin_end"); } } diff --git a/src/common.h b/src/common.h index adab2f587f..c99f23410e 100644 --- a/src/common.h +++ b/src/common.h @@ -94,7 +94,13 @@ typedef int64_t intptr_t; typedef uint64_t uintptr_t; # define UINT64_C(x) x##L # define ARCH_x86_64 -@ define BYTES_PER_WORD 8 +# define BYTES_PER_WORD 8 +# elif defined _M_ARM_FP +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +# define UINT64_C(x) x##LL +# define ARCH_arm +# define BYTES_PER_WORD 4 # else # error "unsupported architecture" # endif diff --git a/src/interpret.cpp b/src/interpret.cpp index 4a324fd084..9399e96657 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -18,7 +18,7 @@ using namespace vm; -namespace { +namespace local { const unsigned FrameBaseOffset = 0; const unsigned FrameNextOffset = 1; @@ -2321,7 +2321,7 @@ interpret3(Thread* t, const int base) object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); PROTECT(t, class_); - int32_t counts[dimensions]; + int32_t* counts = new int32_t[dimensions]; for (int i = dimensions - 1; i >= 0; --i) { counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { @@ -2338,6 +2338,9 @@ interpret3(Thread* t, const int base) populateMultiArray(t, array, counts, 0, dimensions); pushObject(t, array); + + delete[] counts; + counts = 0; } goto loop; case new_: { @@ -3100,7 +3103,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3124,7 +3127,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3148,7 +3151,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, indirectObjects, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3174,7 +3177,7 @@ class MyProcessor: public Processor { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object getStackTrace(vm::Thread* t, vm::Thread*) { @@ -3254,8 +3257,8 @@ namespace vm { Processor* makeProcessor(System* system, Allocator* allocator, bool) { - return new (allocator->allocate(sizeof(MyProcessor))) - MyProcessor(system, allocator); + return new (allocator->allocate(sizeof(local::MyProcessor))) + local::MyProcessor(system, allocator); } } // namespace vm diff --git a/src/machine.h b/src/machine.h index 2924a13fb7..420a0192cb 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1325,6 +1325,9 @@ checkDaemon(Thread* t); object& root(Thread* t, Machine::Root root); +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) +# define vmRun vmRun_ +#endif extern "C" uint64_t vmRun(uint64_t (*function)(Thread*, uintptr_t*), uintptr_t* arguments, void* checkpoint); diff --git a/src/system.h b/src/system.h index c36aefacd9..14a29c7272 100644 --- a/src/system.h +++ b/src/system.h @@ -97,11 +97,13 @@ class System { virtual void disposeAll() = 0; }; +#if defined(AVIAN_PROCESS_compile) class SignalHandler { public: virtual bool handleSignal(void** ip, void** frame, void** stack, void** thread) = 0; }; +#endif class MonitorResource { public: @@ -121,17 +123,21 @@ class System { virtual bool success(Status) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0; virtual void free(const void* p) = 0; +#if defined(AVIAN_PROCESS_compile) virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0; virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0; +#endif virtual Status attach(Runnable*) = 0; virtual Status start(Runnable*) = 0; virtual Status make(Mutex**) = 0; virtual Status make(Monitor**) = 0; virtual Status make(Local**) = 0; +#if defined(AVIAN_PROCESS_compile) virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleDivideByZero(SignalHandler* handler) = 0; virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor) = 0; +#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0; diff --git a/src/windows.cpp b/src/windows.cpp index 532b66e161..2d8c4c16c4 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -26,6 +26,71 @@ #include "arch.h" #include "system.h" +#if defined(WINAPI_FAMILY) + +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#define WaitForSingleObject(hHandle, dwMilliseconds) \ + WaitForSingleObjectEx((hHandle), (dwMilliseconds), FALSE) + +#define CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) \ + CreateEventEx((lpEventAttributes), (lpName), ((bManualReset)?CREATE_EVENT_MANUAL_RESET:0)|((bInitialState)?CREATE_EVENT_INITIAL_SET:0), EVENT_MODIFY_STATE) + +#define CreateMutex(lpEventAttributes, bInitialOwner, lpName) \ + CreateMutexEx((lpEventAttributes), (lpName), (bInitialOwner)?CREATE_MUTEX_INITIAL_OWNER:0, MUTEX_MODIFY_STATE) + +#include "thread-emulation.h" + +#endif + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) +// Headers in Windows Phone 8 DevKit contain severe error, so let's define needed functions on our own +extern "C" +{ +WINBASEAPI +_Ret_maybenull_ +HANDLE +WINAPI +CreateFileMappingFromApp( + _In_ HANDLE hFile, + _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, + _In_ ULONG PageProtection, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name + ); + +WINBASEAPI +_Ret_maybenull_ __out_data_source(FILE) +PVOID +WINAPI +MapViewOfFileFromApp( + _In_ HANDLE hFileMappingObject, + _In_ ULONG DesiredAccess, + _In_ ULONG64 FileOffset, + _In_ SIZE_T NumberOfBytesToMap + ); + +WINBASEAPI +BOOL +WINAPI +UnmapViewOfFile( + _In_ LPCVOID lpBaseAddress + ); +} +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + +#else + +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif + +#endif + #define ACQUIRE(s, x) MutexResource MAKE_NAME(mutexResource_) (s, x) using namespace vm; @@ -49,16 +114,20 @@ class MutexResource { HANDLE m; }; +#if defined(AVIAN_PROCESS_compile) const unsigned SegFaultIndex = 0; const unsigned DivideByZeroIndex = 1; const unsigned HandlerCount = 2; +#endif class MySystem; MySystem* system; +#if defined(AVIAN_PROCESS_compile) LONG CALLBACK handleException(LPEXCEPTION_POINTERS e); +#endif DWORD WINAPI run(void* r) @@ -559,18 +628,22 @@ class MySystem: public System { }; MySystem(const char* crashDumpDirectory): +#if defined(AVIAN_PROCESS_compile) oldHandler(0), +#endif crashDumpDirectory(crashDumpDirectory) { expect(this, system == 0); system = this; +#if defined(AVIAN_PROCESS_compile) memset(handlers, 0, sizeof(handlers)); +#endif mutex = CreateMutex(0, false, 0); assert(this, mutex); } - +#if defined(AVIAN_PROCESS_compile) bool findHandler() { for (unsigned i = 0; i < HandlerCount; ++i) { if (handlers[i]) return true; @@ -578,6 +651,7 @@ class MySystem: public System { return false; } + //TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx int registerHandler(System::SignalHandler* handler, int index) { if (handler) { handlers[index] = handler; @@ -609,7 +683,7 @@ class MySystem: public System { return 1; } } - +#endif virtual void* tryAllocate(unsigned sizeInBytes) { return malloc(sizeInBytes); } @@ -618,6 +692,7 @@ class MySystem: public System { if (p) ::free(const_cast(p)); } + #if defined(AVIAN_PROCESS_compile) virtual void* tryAllocateExecutable(unsigned sizeInBytes) { return VirtualAlloc (0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); @@ -627,6 +702,7 @@ class MySystem: public System { int r UNUSED = VirtualFree(const_cast(p), 0, MEM_RELEASE); assert(this, r); } + #endif virtual bool success(Status s) { return s == 0; @@ -666,6 +742,7 @@ class MySystem: public System { return 0; } +#if defined(AVIAN_PROCESS_compile) virtual Status handleSegFault(SignalHandler* handler) { return registerHandler(handler, SegFaultIndex); } @@ -710,6 +787,7 @@ class MySystem: public System { return (success ? 0 : 1); } +#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) @@ -719,15 +797,39 @@ class MySystem: public System { virtual Status map(System::Region** region, const char* name) { Status status = 1; - +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE file = CreateFile(name, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); +#else + size_t nameLen = strlen(name); + wchar_t* wideName = new wchar_t[nameLen + 1]; + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); + HANDLE file = CreateFile2(wideName, GENERIC_READ, FILE_SHARE_READ, + OPEN_EXISTING, 0); + delete[] wideName; +#endif if (file != INVALID_HANDLE_VALUE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) unsigned size = GetFileSize(file, 0); +#else + FILE_STANDARD_INFO info; + unsigned size = INVALID_FILE_SIZE; + if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + size = info.EndOfFile.QuadPart; +#endif if (size != INVALID_FILE_SIZE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0); +#else + HANDLE mapping = CreateFileMappingFromApp(file, 0, PAGE_READONLY, size, 0); +#endif if (mapping) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); +#else + void* data = MapViewOfFileFromApp(mapping, FILE_MAP_READ, 0, 0); +#endif if (data) { *region = new (allocate(this, sizeof(Region))) Region(this, static_cast(data), size, file, mapping); @@ -757,7 +859,12 @@ class MySystem: public System { memcpy(RUNTIME_ARRAY_BODY(buffer) + length, "\\*", 3); Directory* d = new (allocate(this, sizeof(Directory))) Directory(this); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) d->handle = FindFirstFile(RUNTIME_ARRAY_BODY(buffer), &(d->data)); +#else + d->handle = FindFirstFileEx(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, 0, 0); +#endif if (d->handle == INVALID_HANDLE_VALUE) { d->dispose(); } else { @@ -797,6 +904,7 @@ class MySystem: public System { } virtual const char* toAbsolutePath(Allocator* allocator, const char* name) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) if (strncmp(name, "//", 2) == 0 or strncmp(name, "\\\\", 2) == 0 or strncmp(name + 1, ":/", 2) == 0 @@ -808,6 +916,11 @@ class MySystem: public System { GetCurrentDirectory(MAX_PATH, buffer); return append(allocator, buffer, "\\", name); } +#else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.ApplicationModel.Package.Current.InstalledLocation + return name; +#endif } virtual Status load(System::Library** lib, @@ -816,9 +929,23 @@ class MySystem: public System { HMODULE handle; unsigned nameLength = (name ? strlen(name) : 0); if (name) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) handle = LoadLibrary(name); +#else + size_t nameLen = strlen(name); + wchar_t* wideName = new wchar_t[nameLen + 1]; + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); + handle = LoadPackagedLibrary(wideName, 0); + delete[] wideName; +#endif } else { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) handle = GetModuleHandle(0); +#else + // Most of WinRT/WP8 applications can not host native object files inside main executable + assert(this, false); +#endif } if (handle) { @@ -866,7 +993,11 @@ class MySystem: public System { } virtual void yield() { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) SwitchToThread(); +#else + YieldProcessor(); +#endif } virtual void exit(int code) { @@ -886,11 +1017,15 @@ class MySystem: public System { } HANDLE mutex; +#if defined(AVIAN_PROCESS_compile) SignalHandler* handlers[HandlerCount]; LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; +#endif const char* crashDumpDirectory; }; +#if defined(AVIAN_PROCESS_compile) + #pragma pack(push,4) struct MINIDUMP_EXCEPTION_INFORMATION { DWORD thread; @@ -1005,6 +1140,8 @@ handleException(LPEXCEPTION_POINTERS e) return EXCEPTION_CONTINUE_SEARCH; } +#endif + } // namespace namespace vm { diff --git a/src/x86.masm b/src/x86.masm new file mode 100644 index 0000000000..715669f8c1 --- /dev/null +++ b/src/x86.masm @@ -0,0 +1,166 @@ +comment # + Copyright (c) 2008-2011, 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. +# + +.586 +.MODEL FLAT, C + +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +CHECKPOINT_THREAD equ 4 +CHECKPOINT_STACK equ 24 +CHECKPOINT_BASE equ 28 + +_TEXT SEGMENT + +public C detectFeature +detectFeature: + push ebp + mov ebp,esp + push edx + push ecx + push ebx + push esi + push edi + mov esi,ds:dword ptr[12+ebp] + mov edi,ds:dword ptr[8+ebp] + mov eax,1 + cpuid + and edx,esi + and ecx,edi + or ecx,edx + test ecx,ecx + je LNOSSE + mov eax,1 + jmp LSSEEND + +LNOSSE: + mov eax,0 + +LSSEEND: + pop edi + pop esi + pop ebx + pop ecx + pop edx + mov esp,ebp + pop ebp + ret + +public C vmNativeCall +vmNativeCall: + push ebp + mov ebp,esp + mov ecx,ds:dword ptr[16+ebp] + sub esp,ecx + mov ecx,0 + jmp Ltest + +Lloop: + mov eax,ecx + mov edx,ecx + add edx,esp + add eax,ds:dword ptr[12+ebp] + mov eax,ds:dword ptr[eax] + mov ds:dword ptr[edx],eax + add ecx,4 + +Ltest: + cmp ecx,ds:dword ptr[16+ebp] + jb Lloop + call dword ptr[8+ebp] + mov ecx,ds:dword ptr[20+ebp] + +Lvoid: + cmp ecx,offset VOID_TYPE + jne Lint64 + jmp Lexit + +Lint64: + cmp ecx,offset INT64_TYPE + jne Lfloat + jmp Lexit + +Lfloat: + cmp ecx,offset FLOAT_TYPE + jne Ldouble + fstp ds:dword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + jmp Lexit + +Ldouble: + cmp ecx,offset DOUBLE_TYPE + jne Lexit + fstp ds:dword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + mov edx,ds:dword ptr[12+ebp] + +Lexit: + mov esp,ebp + pop ebp + ret + +public C vmJump +vmJump: + mov esi,ds:dword ptr[4+esp] + mov ebp,ds:dword ptr[8+esp] + mov ebx,ds:dword ptr[16+esp] + mov eax,ds:dword ptr[20+esp] + mov edx,ds:dword ptr[24+esp] + mov esp,ds:dword ptr[12+esp] + jmp esi + +VMRUN_FRAME_SIZE equ 24 + +public C vmRun_ +vmRun_: + ; 8(%ebp): function + ; 12(%ebp): arguments + ; 16(%ebp): checkpoint + push ebp + mov ebp,esp + sub esp,offset VMRUN_FRAME_SIZE + + mov ds:dword ptr[8+esp],ebx + mov ds:dword ptr[12+esp],esi + mov ds:dword ptr[16+esp],edi + + mov eax,ds:dword ptr[12+ebp] + mov ds:dword ptr[4+esp],eax + + mov ecx,ds:dword ptr[16+ebp] + mov eax,ds:dword ptr[CHECKPOINT_THREAD+ecx] + mov ds:dword ptr[0+esp],eax + + mov ds:dword ptr[CHECKPOINT_STACK+ecx],esp + + call dword ptr[8+ebp] + +public C vmRun_returnAddress +vmRun_returnAddress: + + mov ebx,ds:dword ptr[8+esp] + mov esi,ds:dword ptr[12+esp] + mov edi,ds:dword ptr[16+esp] + + add esp,offset VMRUN_FRAME_SIZE + pop ebp + ret + +_TEXT ENDS +END \ No newline at end of file From c5adad9dce69d6c280289b1804d972a9a96950f2 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 28 Jan 2013 19:15:29 +0200 Subject: [PATCH 107/378] Makefile fix --- makefile | 16 ++++++++++------ src/arm.h | 4 ++-- src/system.h | 6 +++--- src/windows.cpp | 18 +++++++++--------- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/makefile b/makefile index 28ef8be401..066b4327c3 100755 --- a/makefile +++ b/makefile @@ -51,7 +51,8 @@ ifeq ($(continuations),true) endif root := $(shell (cd .. && pwd)) -build = $(build-prefix)build/$(platform)-$(arch)$(options) +build = build/$(platform)-$(arch)$(options) +host-build-root = $(build)/host classpath-build = $(build)/classpath test-build = $(build)/test src = src @@ -135,7 +136,7 @@ ifneq ($(openjdk),) javahome = "$$($(native-path) "$(openjdk)/jre")" endif - classpath = openjdk + classpath = openjdk boot-classpath := "$(boot-classpath)$(path-separator)$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" build-javahome = $(openjdk)/jre endif @@ -640,7 +641,7 @@ ifeq ($(platform),wp8) ms_cl_compiler = wp8 use-lto = false supports_avian_executable = false - process = interpret + process = compile ifneq ($(process),compile) options := -$(process) endif @@ -918,6 +919,9 @@ ifeq ($(process),compile) vm-asm-sources += $(src)/compile-$(asm).$(asm-format) endif cflags += -DAVIAN_PROCESS_$(process) +ifdef aot_only + cflags += -DAVIAN_AOT_ONLY +endif vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(build)) vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build)) @@ -1430,7 +1434,7 @@ else endif $(bootimage-object) $(codeimage-object): $(bootimage-generator) - @echo "generating bootimage and codeimage binaries using $(<)" + @echo "generating bootimage and codeimage binaries from $(classpath-build) using $(<)" $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ -bootimage-symbols $(bootimage-symbols) \ -codeimage-symbols $(codeimage-symbols) @@ -1459,9 +1463,9 @@ endif $(strip) $(strip-all) $(@) $(bootimage-generator): $(bootimage-generator-objects) - echo arch=$(arch) platform=$(platform) + echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform) $(MAKE) mode=$(mode) \ - build-prefix=$(build)/host/ \ + build=$(host-build-root) \ arch=$(build-arch) \ target-arch=$(arch) \ platform=$(bootimage-platform) \ diff --git a/src/arm.h b/src/arm.h index adfd92b4ad..302355c453 100644 --- a/src/arm.h +++ b/src/arm.h @@ -116,7 +116,7 @@ loadMemoryBarrier() #endif } -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) #if defined(__ANDROID__) // http://code.google.com/p/android/issues/detail?id=1803 @@ -136,7 +136,7 @@ syncInstructionCache(const void* start, unsigned size) #endif } -#endif // AVIAN_PROCESS_compile +#endif // AVIAN_AOT_ONLY #ifndef __APPLE__ typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); diff --git a/src/system.h b/src/system.h index 14a29c7272..ee80d2a7cb 100644 --- a/src/system.h +++ b/src/system.h @@ -97,7 +97,7 @@ class System { virtual void disposeAll() = 0; }; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) class SignalHandler { public: virtual bool handleSignal(void** ip, void** frame, void** stack, @@ -123,7 +123,7 @@ class System { virtual bool success(Status) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0; virtual void free(const void* p) = 0; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0; virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0; #endif @@ -132,7 +132,7 @@ class System { virtual Status make(Mutex**) = 0; virtual Status make(Monitor**) = 0; virtual Status make(Local**) = 0; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleDivideByZero(SignalHandler* handler) = 0; virtual Status visit(Thread* thread, Thread* target, diff --git a/src/windows.cpp b/src/windows.cpp index 2d8c4c16c4..f6b9627254 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -114,7 +114,7 @@ class MutexResource { HANDLE m; }; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) const unsigned SegFaultIndex = 0; const unsigned DivideByZeroIndex = 1; @@ -124,7 +124,7 @@ const unsigned HandlerCount = 2; class MySystem; MySystem* system; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) LONG CALLBACK handleException(LPEXCEPTION_POINTERS e); #endif @@ -628,7 +628,7 @@ class MySystem: public System { }; MySystem(const char* crashDumpDirectory): -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) oldHandler(0), #endif crashDumpDirectory(crashDumpDirectory) @@ -636,14 +636,14 @@ class MySystem: public System { expect(this, system == 0); system = this; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) memset(handlers, 0, sizeof(handlers)); #endif mutex = CreateMutex(0, false, 0); assert(this, mutex); } -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) bool findHandler() { for (unsigned i = 0; i < HandlerCount; ++i) { if (handlers[i]) return true; @@ -692,7 +692,7 @@ class MySystem: public System { if (p) ::free(const_cast(p)); } - #if defined(AVIAN_PROCESS_compile) + #if !defined(AVIAN_AOT_ONLY) virtual void* tryAllocateExecutable(unsigned sizeInBytes) { return VirtualAlloc (0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); @@ -742,7 +742,7 @@ class MySystem: public System { return 0; } -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) { return registerHandler(handler, SegFaultIndex); } @@ -1017,14 +1017,14 @@ class MySystem: public System { } HANDLE mutex; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) SignalHandler* handlers[HandlerCount]; LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; #endif const char* crashDumpDirectory; }; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) #pragma pack(push,4) struct MINIDUMP_EXCEPTION_INFORMATION { From a78959a480a7ae5c862d358fcb1942f32485242e Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 28 Jan 2013 20:51:35 +0200 Subject: [PATCH 108/378] Replaced TODO comments with messages ; More correct AVIAN_AOT_ONLY usage --- classpath/java-lang.cpp | 15 +++++------ makefile | 1 + src/arm.cpp | 26 ++++++++++--------- src/arm.masm | 12 +++++++++ src/compile.cpp | 7 +++++- src/system.h | 4 --- src/windows.cpp | 55 ++++++++++++++++++++++------------------- src/x86.masm | 2 ++ 8 files changed, 72 insertions(+), 50 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 0414216194..9d2562e265 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -80,8 +80,8 @@ namespace { snprintf(errStr, 9, "%d", (int) err); return errStr; - //TODO: - // The better way to do this, if I could figure out how to convert LPTSTR to char* + #pragma message("TODO") + // The better way to do this, if I could figure out how to convert LPTSTR to char* //char* errStr; //LPTSTR s; //if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -390,7 +390,7 @@ Locale getLocale() { return Locale(lang, reg); #else - //TODO: CultureInfo.CurrentCulture + #pragma message("TODO: CultureInfo.CurrentCulture") return Locale("en", "US"); #endif } @@ -596,8 +596,7 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetTempPath(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.Storage.ApplicationData.Current.TemporaryFolder + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.ApplicationData.Current.TemporaryFolder") r = 0; # endif } else if (strcmp(chars, "user.dir") == 0) { @@ -606,8 +605,7 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetCurrentDirectory(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.ApplicationModel.Package.Current.InstalledLocation + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") r = 0; # endif } else if (strcmp(chars, "user.home") == 0) { @@ -621,8 +619,7 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = 0; } # else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.Storage.KnownFolders.DocumentsLibrary; + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.KnownFolders.DocumentsLibrary") r = 0; # endif # else diff --git a/makefile b/makefile index 066b4327c3..5f28ef4b3a 100755 --- a/makefile +++ b/makefile @@ -642,6 +642,7 @@ ifeq ($(platform),wp8) use-lto = false supports_avian_executable = false process = compile + aot_only = true ifneq ($(process),compile) options := -$(process) endif diff --git a/src/arm.cpp b/src/arm.cpp index ae657e30d5..1d4dbc8dd1 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -18,7 +18,7 @@ using namespace vm; -namespace { +namespace local { namespace isa { // SYSTEM REGISTERS @@ -252,7 +252,7 @@ class MyBlock: public Assembler::Block { this->start = start; this->next = static_cast(next); - ::resolve(this); + local::resolve(this); return start + size + padding(this, size); } @@ -2150,7 +2150,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentFootprint(unsigned footprint) { - return ::argumentFootprint(footprint); + return local::argumentFootprint(footprint); } virtual bool argumentAlignment() { @@ -2239,7 +2239,7 @@ class MyArchitecture: public Assembler::Architecture { unsigned targetParameterFootprint, void** ip, void** stack) { - ::nextFrame(&con, static_cast(start), size, footprint, link, + local::nextFrame(&con, static_cast(start), size, footprint, link, mostRecent, targetParameterFootprint, ip, stack); } @@ -2550,11 +2550,12 @@ class MyAssembler: public Assembler { } virtual void pushFrame(unsigned argumentCount, ...) { - struct { + struct Argument { unsigned size; OperandType type; Operand* operand; - } arguments[argumentCount]; + }; + Argument* arguments = new Argument[argumentCount]; va_list a; va_start(a, argumentCount); unsigned footprint = 0; @@ -2589,6 +2590,9 @@ class MyAssembler: public Assembler { offset += ceiling(arguments[i].size, TargetBytesPerWord); } } + + delete[] arguments; + arguments = 0; } virtual void allocateFrame(unsigned footprint) { @@ -2798,7 +2802,7 @@ class MyAssembler: public Assembler { bool jump = needJump(b); if (jump) { write4 - (dst + dstOffset, ::b((poolSize + TargetBytesPerWord - 8) >> 2)); + (dst + dstOffset, isa::b((poolSize + TargetBytesPerWord - 8) >> 2)); } dstOffset += poolSize + (jump ? TargetBytesPerWord : 0); @@ -2832,7 +2836,7 @@ class MyAssembler: public Assembler { } virtual Promise* offset(bool forTrace) { - return ::offset(&con, forTrace); + return local::offset(&con, forTrace); } virtual Block* endBlock(bool startNew) { @@ -2903,15 +2907,15 @@ namespace vm { Assembler::Architecture* makeArchitecture(System* system, bool) { - return new (allocate(system, sizeof(MyArchitecture))) MyArchitecture(system); + return new (allocate(system, sizeof(local::MyArchitecture))) local::MyArchitecture(system); } Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new(zone) MyAssembler(system, allocator, zone, - static_cast(architecture)); + return new(zone) local::MyAssembler(system, allocator, zone, + static_cast(architecture)); } } // namespace vm diff --git a/src/arm.masm b/src/arm.masm index 8fc09eb875..2af5048ec7 100644 --- a/src/arm.masm +++ b/src/arm.masm @@ -1,3 +1,15 @@ +; Copyright (c) 2008-2011, 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. +; +; ORIGIN: https://github.com/gkvas/avian/tree/wince + AREA text, CODE, ARM EXPORT vmNativeCall [FUNC] diff --git a/src/compile.cpp b/src/compile.cpp index 6989d6446d..7fa51817c7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -7389,8 +7389,9 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) { trap(); } - +#if !defined(AVIAN_AOT_ONLY) syncInstructionCache(start, codeSize); +#endif } void @@ -9152,7 +9153,9 @@ class MyProcessor: public Processor { virtual void dispose() { if (codeAllocator.base) { +#if !defined(AVIAN_AOT_ONLY) s->freeExecutable(codeAllocator.base, codeAllocator.capacity); +#endif } compilationHandlers->dispose(allocator); @@ -9313,11 +9316,13 @@ class MyProcessor: public Processor { } virtual void boot(Thread* t, BootImage* image, uint8_t* code) { +#if !defined(AVIAN_AOT_ONLY) if (codeAllocator.base == 0) { codeAllocator.base = static_cast (s->tryAllocateExecutable(ExecutableAreaSizeInBytes)); codeAllocator.capacity = ExecutableAreaSizeInBytes; } +#endif if (image and code) { local::boot(static_cast(t), image, code); diff --git a/src/system.h b/src/system.h index ee80d2a7cb..ef69317f0b 100644 --- a/src/system.h +++ b/src/system.h @@ -97,13 +97,11 @@ class System { virtual void disposeAll() = 0; }; -#if !defined(AVIAN_AOT_ONLY) class SignalHandler { public: virtual bool handleSignal(void** ip, void** frame, void** stack, void** thread) = 0; }; -#endif class MonitorResource { public: @@ -132,12 +130,10 @@ class System { virtual Status make(Mutex**) = 0; virtual Status make(Monitor**) = 0; virtual Status make(Local**) = 0; -#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleDivideByZero(SignalHandler* handler) = 0; virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor) = 0; -#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0; diff --git a/src/windows.cpp b/src/windows.cpp index f6b9627254..8c7512eab1 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -114,17 +114,15 @@ class MutexResource { HANDLE m; }; -#if !defined(AVIAN_AOT_ONLY) const unsigned SegFaultIndex = 0; const unsigned DivideByZeroIndex = 1; const unsigned HandlerCount = 2; -#endif class MySystem; MySystem* system; -#if !defined(AVIAN_AOT_ONLY) +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) LONG CALLBACK handleException(LPEXCEPTION_POINTERS e); #endif @@ -628,7 +626,7 @@ class MySystem: public System { }; MySystem(const char* crashDumpDirectory): -#if !defined(AVIAN_AOT_ONLY) +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) oldHandler(0), #endif crashDumpDirectory(crashDumpDirectory) @@ -636,14 +634,12 @@ class MySystem: public System { expect(this, system == 0); system = this; -#if !defined(AVIAN_AOT_ONLY) memset(handlers, 0, sizeof(handlers)); -#endif mutex = CreateMutex(0, false, 0); assert(this, mutex); } -#if !defined(AVIAN_AOT_ONLY) + bool findHandler() { for (unsigned i = 0; i < HandlerCount; ++i) { if (handlers[i]) return true; @@ -651,31 +647,38 @@ class MySystem: public System { return false; } - //TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx int registerHandler(System::SignalHandler* handler, int index) { if (handler) { handlers[index] = handler; - + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) if (oldHandler == 0) { -#ifdef ARCH_x86_32 +# ifdef ARCH_x86_32 oldHandler = SetUnhandledExceptionFilter(handleException); -#elif defined ARCH_x86_64 +# elif defined ARCH_x86_64 AddVectoredExceptionHandler(1, handleException); oldHandler = reinterpret_cast(1); -#endif +# endif } +#else + #pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") +#endif return 0; } else if (handlers[index]) { handlers[index] = 0; if (not findHandler()) { -#ifdef ARCH_x86_32 +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# ifdef ARCH_x86_32 SetUnhandledExceptionFilter(oldHandler); oldHandler = 0; -#elif defined ARCH_x86_64 +# elif defined ARCH_x86_64 // do nothing, handlers are never "unregistered" anyway -#endif +# endif +#else + #pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") +#endif } return 0; @@ -683,7 +686,7 @@ class MySystem: public System { return 1; } } -#endif + virtual void* tryAllocate(unsigned sizeInBytes) { return malloc(sizeInBytes); } @@ -742,7 +745,6 @@ class MySystem: public System { return 0; } -#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) { return registerHandler(handler, SegFaultIndex); } @@ -754,6 +756,7 @@ class MySystem: public System { virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget, ThreadVisitor* visitor) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) assert(this, st != sTarget); Thread* target = static_cast(sTarget); @@ -769,15 +772,15 @@ class MySystem: public System { rv = GetThreadContext(target->thread, &context); if (rv) { -#ifdef ARCH_x86_32 +# ifdef ARCH_x86_32 visitor->visit(reinterpret_cast(context.Eip), reinterpret_cast(context.Ebp), reinterpret_cast(context.Esp)); -#elif defined ARCH_x86_64 +# elif defined ARCH_x86_64 visitor->visit(reinterpret_cast(context.Rip), reinterpret_cast(context.Rbp), reinterpret_cast(context.Rsp)); -#endif +# endif success = true; } @@ -786,8 +789,11 @@ class MySystem: public System { } return (success ? 0 : 1); - } +#else + #pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") + return false; #endif + } virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) @@ -917,8 +923,7 @@ class MySystem: public System { return append(allocator, buffer, "\\", name); } #else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.ApplicationModel.Package.Current.InstalledLocation + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") return name; #endif } @@ -1017,14 +1022,14 @@ class MySystem: public System { } HANDLE mutex; -#if !defined(AVIAN_AOT_ONLY) SignalHandler* handlers[HandlerCount]; +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; #endif const char* crashDumpDirectory; }; -#if !defined(AVIAN_AOT_ONLY) +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #pragma pack(push,4) struct MINIDUMP_EXCEPTION_INFORMATION { diff --git a/src/x86.masm b/src/x86.masm index 715669f8c1..640637d5af 100644 --- a/src/x86.masm +++ b/src/x86.masm @@ -8,6 +8,8 @@ comment # There is NO WARRANTY for this software. See license.txt for details. + + ORIGIN: https://github.com/gkvas/avian/tree/wince # .586 From 9c67acfaf1567ab59772af575409772423f2674b Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 09:40:29 +0200 Subject: [PATCH 109/378] WinRT/WP8 process=compile --- makefile | 2 + src/arm.masm | 10 +- src/compile-arm.masm | 252 +++++++++++++++++++++++++++++++++++++++++++ src/compile-x86.masm | 173 +++++++++++++++++++++++++++++ 4 files changed, 432 insertions(+), 5 deletions(-) create mode 100644 src/compile-arm.masm create mode 100644 src/compile-x86.masm diff --git a/makefile b/makefile index 5f28ef4b3a..b4512c010f 100755 --- a/makefile +++ b/makefile @@ -1217,7 +1217,9 @@ clean: @echo "removing build" rm -rf build +ifeq ($(continuations),true) $(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) +endif gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) diff --git a/src/arm.masm b/src/arm.masm index 2af5048ec7..e7bd2d864c 100644 --- a/src/arm.masm +++ b/src/arm.masm @@ -12,7 +12,7 @@ AREA text, CODE, ARM - EXPORT vmNativeCall [FUNC] + EXPORT vmNativeCall vmNativeCall ; arguments: ; r0 -> r4 : function @@ -48,7 +48,7 @@ loop ldmfd sp!, {r4-r6, pc} ; restore non-volatile regs and return - EXPORT vmJump [FUNC] + EXPORT vmJump vmJump mov lr, r0 ldr r0, [sp] @@ -60,7 +60,7 @@ vmJump CHECKPOINT_THREAD EQU 4 CHECKPOINT_STACK EQU 24 - EXPORT vmRun [FUNC] + EXPORT vmRun vmRun ; r0: function ; r1: arguments @@ -76,13 +76,13 @@ vmRun blx r12 - EXPORT vmRun_returnAddress [FUNC] + EXPORT vmRun_returnAddress vmRun_returnAddress add sp, sp, #12 ldmfd sp!, {r4-r11, lr} bx lr - EXPORT vmTrap [FUNC] + EXPORT vmTrap vmTrap bkpt 3 diff --git a/src/compile-arm.masm b/src/compile-arm.masm new file mode 100644 index 0000000000..a9c1e59cef --- /dev/null +++ b/src/compile-arm.masm @@ -0,0 +1,252 @@ +; Copyright (c) 2008-2011, 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. +; +; ORIGIN: https://github.com/gkvas/avian/tree/wince + +; types.inc +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +; target-fields.inc +;TARGET_BYTES_PER_WORD = 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + AREA text, CODE, ARM + +BYTES_PER_WORD equ 4 + +CONTINUATION_NEXT equ 4 +CONTINUATION_ADDRESS equ 16 +CONTINUATION_RETURN_ADDRESS_OFFSET equ 20 +CONTINUATION_FRAME_POINTER_OFFSET equ 24 +CONTINUATION_LENGTH equ 28 +CONTINUATION_BODY equ 32 + + EXPORT vmInvoke +vmInvoke + + ; arguments + ; r0 : thread + ; r1 : function + ; r2 : arguments + ; r3 : argumentFootprint + ; [sp, #0] : frameSize (not used) + ; [sp, #4] : returnType + + + ; save all non-volatile registers + stmfd sp!, {r4-r11, lr} + + ; save return type + ldr r4, [sp, #4] + str r4, [sp, #-4]! + + str sp, [r0, #TARGET_THREAD_SCRATCH] + + ; align stack, if necessary + eor r4, sp, r3 + tst r4, #4 + subne sp, sp, #4 + + ; copy arguments into place + sub sp, sp, r3 + mov r4, #0 + b vmInvoke_argumentTest + +vmInvoke_argumentLoop + ldr r5, [r2, r4] + str r5, [sp, r4] + add r4, r4, #BYTES_PER_WORD + +vmInvoke_argumentTest + cmp r4, r3 + blt vmInvoke_argumentLoop + + ; we use r8 to hold the thread pointer, by convention + mov r8, r0 + + ; load and call function address + blx r1 + + EXPORT vmInvoke_returnAddress +vmInvoke_returnAddress + ; restore stack pointer + ldr sp, [r8, #TARGET_THREAD_SCRATCH] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov r5, #0 + str r5, [r8, #TARGET_THREAD_STACK] + + EXPORT vmInvoke_safeStack +vmInvoke_safeStack + +;if AVIAN_CONTINUATIONS +; ; call the next continuation, if any +; ldr r5,[r8,#TARGET_THREAD_CONTINUATION] +; cmp r5,#0 +; beq vmInvoke_exit) +; +; ldr r6,[r5,#CONTINUATION_LENGTH] +; lsl r6,r6,#2 +; neg r7,r6 +; add r7,r7,#-80 +; mov r4,sp +; str r4,[sp,r7]! +; +; add r7,r5,#CONTINUATION_BODY +; +; mov r11,#0 +; b vmInvoke_continuationTest +; +;vmInvoke_continuationLoop +; ldr r9,[r7,r11] +; str r9,[sp,r11] +; add r11,r11,#4 +; +;vmInvoke_continuationTest +; cmp r11,r6 +; ble vmInvoke_continuationLoop) +; +; ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET] +; ldr r10,vmInvoke_returnAddress_word +; ldr r11,vmInvoke_getAddress_word +;vmInvoke_getAddress +; add r11,pc,r11 +; ldr r11,[r11,r10] +; str r11,[sp,r7] +; +; ldr r7,[r5,#CONTINUATION_NEXT] +; str r7,[r8,#TARGET_THREAD_CONTINUATION] +; +; ; call the continuation unless we're handling an exception +; ldr r7,[r8,#TARGET_THREAD_EXCEPTION] +; cmp r7,#0 +; bne vmInvoke_handleException) +; ldr r7,[r5,#CONTINUATION_ADDRESS] +; bx r7 +; +;vmInvoke_handleException +; ; we're handling an exception - call the exception handler instead +; mov r11,#0 +; str r11,[r8,#TARGET_THREAD_EXCEPTION] +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] +; ldr r9,[sp] +; neg r11,r11 +; str r9,[sp,r11]! +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONOFFSET] +; str r7,[sp,r11] +; +; ldr r7,[r8,#TARGET_THREAD_EXCEPTIONHANDLER] +; bx r7 +; +;vmInvoke_exit +;endif ; AVIAN_CONTINUATIONS + + mov ip, #0 + str ip, [r8, #TARGET_THREAD_STACK] + + ; restore return type + ldr ip, [sp], #4 + + ; restore callee-saved registers + ldmfd sp!, {r4-r11, lr} + +vmInvoke_return + bx lr + + EXPORT vmJumpAndInvoke +vmJumpAndInvoke +;if :DEF:AVIAN_CONTINUATIONS +; ; r0: thread +; ; r1: address +; ; r2: stack +; ; r3: argumentFootprint +; ; [sp,#0]: arguments +; ; [sp,#4]: frameSize +; +; ldr r5,[sp,#0] +; ldr r6,[sp,#4] +; +; ; allocate new frame, adding room for callee-saved registers, plus +; ; 4 bytes of padding since the calculation of frameSize assumes 4 +; ; bytes have already been allocated to save the return address, +; ; which is not true in this case +; sub r2,r2,r6 +; sub r2,r2,#84 +; +; mov r8,r0 +; +; ; copy arguments into place +; mov r6,#0 +; b vmJumpAndInvoke_argumentTest +; +;vmJumpAndInvoke_argumentLoop +; ldr r12,[r5,r6] +; str r12,[r2,r6] +; add r6,r6,#4 +; +;vmJumpAndInvoke_argumentTest +; cmp r6,r3 +; ble vmJumpAndInvoke_argumentLoop +; +; ; the arguments have been copied, so we can set the real stack +; ; pointer now +; mov sp,r2 +; +; ; set return address to vmInvoke_returnAddress +; ldr r10,vmInvoke_returnAddress_word) +; ldr r11,vmJumpAndInvoke_getAddress_word) +;vmJumpAndInvoke_getAddress +; add r11,pc,r11 +; ldr lr,[r11,r10] +; +; bx r1 +; +;vmInvoke_returnAddress_word +; .word GLOBAL(vmInvoke_returnAddress)(GOT) +;vmInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmInvoke_getAddress)+8) +;vmJumpAndInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmJumpAndInvoke_getAddress)+8) +; +;else ; not AVIAN_CONTINUATIONS + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + bkpt 0 +;endif ; not AVIAN_CONTINUATIONS + + END \ No newline at end of file diff --git a/src/compile-x86.masm b/src/compile-x86.masm new file mode 100644 index 0000000000..f07d799faf --- /dev/null +++ b/src/compile-x86.masm @@ -0,0 +1,173 @@ +comment # + Copyright (c) 2008-2011, 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. + + ORIGIN: https://github.com/gkvas/avian/tree/wince +# + +.586 +.MODEL FLAT, C + +comment # types.h # +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +comment # target-fields.h # +ifdef TARGET_BYTES_PER_WORD + if TARGET_BYTES_PER_WORD eq 8 + +TARGET_THREAD_EXCEPTION equ 80 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2256 +TARGET_THREAD_EXCEPTIONOFFSET equ 2264 +TARGET_THREAD_EXCEPTIONHANDLER equ 2272 + +TARGET_THREAD_IP equ 2216 +TARGET_THREAD_STACK equ 2224 +TARGET_THREAD_NEWSTACK equ 2232 +TARGET_THREAD_SCRATCH equ 2240 +TARGET_THREAD_CONTINUATION equ 2248 +TARGET_THREAD_TAILADDRESS equ 2280 +TARGET_THREAD_VIRTUALCALLTARGET equ 2288 +TARGET_THREAD_VIRTUALCALLINDEX equ 2296 +TARGET_THREAD_HEAPIMAGE equ 2304 +TARGET_THREAD_CODEIMAGE equ 2312 +TARGET_THREAD_THUNKTABLE equ 2320 +TARGET_THREAD_STACKLIMIT equ 2368 + + elseif TARGET_BYTES_PER_WORD eq 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + else + error + endif +else + error +endif + +ifdef AVIAN_USE_FRAME_POINTER + ALIGNMENT_ADJUSTMENT equ 0 +else + ALIGNMENT_ADJUSTMENT equ 12 +endif + +CALLEE_SAVED_REGISTER_FOOTPRINT equ 16 + ALIGNMENT_ADJUSTMENT + +_TEXT SEGMENT + +public C vmInvoke +vmInvoke: + push ebp + mov ebp,esp + + ; 8(%ebp): thread + ; 12(%ebp): function + ; 16(%ebp): arguments + ; 20(%ebp): argumentFootprint + ; 24(%ebp): frameSize + ; 28(%ebp): returnType + + ; allocate stack space for callee-saved registers + sub esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + ; remember this stack position, since we won't be able to rely on + ; %rbp being restored when the call returns + mov eax,ds:dword ptr[8+ebp] + mov ds:dword ptr[TARGET_THREAD_SCRATCH+eax],esp + + mov ds:dword ptr[0+esp],ebx + mov ds:dword ptr[4+esp],esi + mov ds:dword ptr[8+esp],edi + + ; allocate stack space for arguments + sub esp,ds:dword ptr[24+ebp] + + ; we use ebx to hold the thread pointer, by convention + mov ebx,eax + + ; copy arguments into place + mov ecx,0 + mov edx,ds:dword ptr[16+ebp] + jmp LvmInvoke_argumentTest + +LvmInvoke_argumentLoop: + mov eax,ds:dword ptr[edx+ecx*1] + mov ds:dword ptr[esp+ecx*1],eax + add ecx,4 + +LvmInvoke_argumentTest: + cmp ecx,ds:dword ptr[20+ebp] + jb LvmInvoke_argumentLoop + + ; call function + call dword ptr[12+ebp] + +public vmInvoke_returnAddress +vmInvoke_returnAddress: + ; restore stack pointer + mov esp,ds:dword ptr[TARGET_THREAD_SCRATCH+ebx] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov ds:dword ptr[TARGET_THREAD_STACK+ebx],0 + +public vmInvoke_safeStack +vmInvoke_safeStack: + + ; restore callee-saved registers + mov ebx,ds:dword ptr[0+esp] + mov esi,ds:dword ptr[4+esp] + mov edi,ds:dword ptr[8+esp] + + add esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + mov ecx,ds:dword ptr[28+esp] + + pop ebp + ret + +LgetPC: + mov esi,ds:dword ptr[esp] + ret + +public vmJumpAndInvoke +vmJumpAndInvoke: + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + int 3 + +_TEXT ENDS + +END From ce1f76a3e99b279269d548f5a235d245befa09af Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Mon, 28 Jan 2013 01:46:15 +0100 Subject: [PATCH 110/378] Add last modified to file --- classpath/java-io.cpp | 22 ++++++++++++++++++++++ classpath/java/io/File.java | 7 +++++++ 2 files changed, 29 insertions(+) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index db9882e051..c12ee64368 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -541,6 +541,28 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) } } +extern "C" JNIEXPORT jlong JNICALL +Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + #ifdef PLATFORM_WINDOWS + # error "Implementation of last modified :)" + #else + struct stat st; + if (stat(chars, &st)) { + return 0; + } else { + return (static_cast(st.st_mtim.tv_sec) * 1000) + + (static_cast(st.st_mtim.tv_nsec) / (1000*1000)); + } + + #endif + } else { + return 0; + } +} + extern "C" JNIEXPORT jstring JNICALL Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle) { diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index b66aa03ff9..8eceed4b71 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -294,12 +294,19 @@ public class File implements Serializable { } } + public long lastModified() { + return lastModified(path); + } private static native long openDir(String path); + private static native long lastModified(String path); + private static native String readDir(long handle); private static native long closeDir(long handle); + + private static class Pair { public final String value; public final Pair next; From 1590bd0554ed2c7a9c134b4ac4341e1b9a4a19dc Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 12:44:55 +0200 Subject: [PATCH 111/378] Fix library overwriting ; proper assembler flags --- makefile | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/makefile b/makefile index b4512c010f..d15ac115a5 100755 --- a/makefile +++ b/makefile @@ -666,7 +666,7 @@ ifeq ($(platform),wp8) as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" - asmflags = -machine ARM -32 + asmflags = $(target-cflags) -machine ARM -32 asm-output = -o $(1) asm-input = $(1) machine_type = ARM @@ -678,6 +678,7 @@ ifeq ($(platform),wp8) vc_arch = w8kit_arch = x86 deps_arch = x86 + asmflags = $(target-cflags) -safeseh as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" @@ -705,12 +706,31 @@ ifeq ($(platform),wp8) common-lflags = $(classpath-lflags) + ifeq ($(mode),debug) + build-type = Debug + endif + ifeq ($(mode),debug-fast) + build-type = Debug + endif + ifeq ($(mode),stress_major) + build-type = Release + endif + ifeq ($(mode),fast) + build-type = Release + endif + ifeq ($(mode),fast) + build-type = Release + endif + ifeq ($(mode),small) + build-type = Release + endif + arflags = -MACHINE:$(machine_type) lflags = $(common-lflags) -nologo \ -MACHINE:$(machine_type) \ -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ ws2_32.lib \ - "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\ThreadEmulation.lib")" + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" cc = $(cxx) asm-format = masm @@ -1508,8 +1528,8 @@ $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(lzma-decode-objects) @echo "linking $(@)" ifdef ms_cl_compiler - $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(build)/$(name).lib $(manifest-flags) + $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(subst .dll,.pdb,$(@)) \ + -IMPLIB:$(subst .dll,.lib,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" endif From 4840f4a01946507f1f0e8003caac0bc77f3d9d36 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 14:21:02 +0200 Subject: [PATCH 112/378] Fixes to WP8/WinRT support --- classpath/java-io.cpp | 3 ++- makefile | 4 +--- src/bootimage.cpp | 14 ++++---------- src/windows.cpp | 4 ++-- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index c12ee64368..3860e67ecd 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -547,7 +547,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) string_t chars = getChars(e, path); if (chars) { #ifdef PLATFORM_WINDOWS - # error "Implementation of last modified :)" + # pragma message("Implementation of last modified") + return 0; #else struct stat st; if (stat(chars, &st)) { diff --git a/makefile b/makefile index d15ac115a5..8106406a22 100755 --- a/makefile +++ b/makefile @@ -618,7 +618,7 @@ ifeq ($(platform),wp8) # Environment variable WP8_SDK not found. It should be something like # "C:\Program Files[ (x86)]\Microsoft Visual Studio 11.0\VC\WPSDK\WP80" # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 - WP80_SDK = C:\$(programFiles)\Microsoft Visual Studio 11.0\VC\WPSDK\WP80 + WP80_SDK = $(MSVS_ROOT)\VC\WPSDK\WP80 endif ifeq ($(WP80_KIT),) # Environment variable WP8_KIT not found. It should be something like @@ -670,8 +670,6 @@ ifeq ($(platform),wp8) asm-output = -o $(1) asm-input = $(1) machine_type = ARM - bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end - codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end endif ifeq ($(arch),i386) wp8_arch = diff --git a/src/bootimage.cpp b/src/bootimage.cpp index ec04196ca0..5b725f5058 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1917,26 +1917,20 @@ public: exit(1); } -# if AVIAN_TARGET_FORMAT != AVIAN_FORMAT_PE -# define SYMBOL_PREFIX "_" -# else -# define SYMBOL_PREFIX -# endif - if(!bootimageStart) { - bootimageStart = strdup(SYMBOL_PREFIX"binary_bootimage_bin_start"); + bootimageStart = strdup("_binary_bootimage_bin_start"); } if(!bootimageEnd) { - bootimageEnd = strdup(SYMBOL_PREFIX"binary_bootimage_bin_end"); + bootimageEnd = strdup("_binary_bootimage_bin_end"); } if(!codeimageStart) { - codeimageStart = strdup(SYMBOL_PREFIX"binary_codeimage_bin_start"); + codeimageStart = strdup("_binary_codeimage_bin_start"); } if(!codeimageEnd) { - codeimageEnd = strdup(SYMBOL_PREFIX"binary_codeimage_bin_end"); + codeimageEnd = strdup("_binary_codeimage_bin_end"); } } diff --git a/src/windows.cpp b/src/windows.cpp index 8c7512eab1..d0b5228368 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -34,10 +34,10 @@ WaitForSingleObjectEx((hHandle), (dwMilliseconds), FALSE) #define CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) \ - CreateEventEx((lpEventAttributes), (lpName), ((bManualReset)?CREATE_EVENT_MANUAL_RESET:0)|((bInitialState)?CREATE_EVENT_INITIAL_SET:0), EVENT_MODIFY_STATE) + CreateEventEx((lpEventAttributes), (lpName), ((bManualReset)?CREATE_EVENT_MANUAL_RESET:0)|((bInitialState)?CREATE_EVENT_INITIAL_SET:0), EVENT_ALL_ACCESS) #define CreateMutex(lpEventAttributes, bInitialOwner, lpName) \ - CreateMutexEx((lpEventAttributes), (lpName), (bInitialOwner)?CREATE_MUTEX_INITIAL_OWNER:0, MUTEX_MODIFY_STATE) + CreateMutexEx((lpEventAttributes), (lpName), (bInitialOwner)?CREATE_MUTEX_INITIAL_OWNER:0, MUTEX_ALL_ACCESS) #include "thread-emulation.h" From fa034c75261ac1c4747188e0abdf333b62d9c4f4 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 19:23:22 +0200 Subject: [PATCH 113/378] Additional AOT_ONLY ifdef --- src/compile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compile.cpp b/src/compile.cpp index 7fa51817c7..d0cf31cfec 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -9339,11 +9339,15 @@ class MyProcessor: public Processor { root(t, MethodTreeSentinal)); } +#ifdef AVIAN_AOT_ONLY + thunks = bootThunks; +#else local::compileThunks(static_cast(t), &codeAllocator); if (not (image and code)) { bootThunks = thunks; } +#endif segFaultHandler.m = t->m; expect(t, t->m->system->success From d6ba068b4bab6b386ea4c4f881d6efbc6bd37d57 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Wed, 30 Jan 2013 07:31:02 +0200 Subject: [PATCH 114/378] Makefile changes, added additional compiler flags --- makefile | 110 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/makefile b/makefile index 8106406a22..f24997fed7 100755 --- a/makefile +++ b/makefile @@ -50,6 +50,7 @@ ifeq ($(continuations),true) options := $(options)-continuations endif +aot-only = false root := $(shell (cd .. && pwd)) build = build/$(platform)-$(arch)$(options) host-build-root = $(build)/host @@ -539,7 +540,6 @@ ifeq ($(platform),windows) lib = "$(win32)/lib" embed-prefix = c:/avian-embedded - system = windows so-prefix = @@ -642,7 +642,7 @@ ifeq ($(platform),wp8) use-lto = false supports_avian_executable = false process = compile - aot_only = true + aot-only = true ifneq ($(process),compile) options := -$(process) endif @@ -676,11 +676,16 @@ ifeq ($(platform),wp8) vc_arch = w8kit_arch = x86 deps_arch = x86 - asmflags = $(target-cflags) -safeseh + asmflags = $(target-cflags) -safeseh -nologo -Gd as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" - asmflags += -nologo + ifeq ($(mode),debug) + asmflags += -Zd + endif + ifeq ($(mode),debug-fast) + asmflags += -Zd + endif asm-output = $(output) machine_type = X86 endif @@ -700,7 +705,8 @@ ifeq ($(platform),wp8) -Fd$(build)/$(name).pdb -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ - -DTARGET_BYTES_PER_WORD=$(pointer-size) + -DTARGET_BYTES_PER_WORD=$(pointer-size) \ + -Gd common-lflags = $(classpath-lflags) @@ -783,6 +789,52 @@ ifeq ($(platform),wp8) strip = : endif +ifdef msvc + no-error = + windows-path = $(native-path) + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + zlib := $(shell $(windows-path) "$(win32)/msvc") + ms_cl_compiler = regular + cxx = "$(msvc)/BIN/cl.exe" + cc = $(cxx) + ld = "$(msvc)/BIN/link.exe" + mt = "mt.exe" + manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest + cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ + -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I$(classpath-src) \ + -I"$(build)" \ + -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ + -DTARGET_BYTES_PER_WORD=$(pointer-size) + + ifneq ($(lzma),) + cflags += -I$(shell $(windows-path) "$(lzma)") + endif + + shared = -dll + lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ + -DEFAULTLIB:zlib -DEFAULTLIB:user32 -MANIFEST -debug + output = -Fo$(1) + + ifeq ($(mode),debug) + cflags += -Od -Zi -MDd + endif + ifeq ($(mode),debug-fast) + cflags += -Od -Zi -DNDEBUG + endif + ifeq ($(mode),fast) + cflags += -O2 -GL -Zi -DNDEBUG + lflags += -LTCG + endif + ifeq ($(mode),small) + cflags += -O1s -Zi -GL -DNDEBUG + lflags += -LTCG + endif + + strip = : +endif + ifeq ($(mode),debug) optimization-cflags = $(cflags_debug) converter-cflags += $(cflags_debug) @@ -842,51 +894,6 @@ endif endif endif -ifdef msvc - no-error = - windows-path = $(native-path) - windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") - zlib := $(shell $(windows-path) "$(win32)/msvc") - cxx = "$(msvc)/BIN/cl.exe" - cc = $(cxx) - ld = "$(msvc)/BIN/link.exe" - mt = "mt.exe" - manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest - cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ - -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ - -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ - -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I$(classpath-src) \ - -I"$(build)" \ - -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ - -DTARGET_BYTES_PER_WORD=$(pointer-size) - - ifneq ($(lzma),) - cflags += -I$(shell $(windows-path) "$(lzma)") - endif - - shared = -dll - lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ - -DEFAULTLIB:zlib -DEFAULTLIB:user32 -MANIFEST -debug - output = -Fo$(1) - - ifeq ($(mode),debug) - cflags += -Od -Zi -MDd - endif - ifeq ($(mode),debug-fast) - cflags += -Od -Zi -DNDEBUG - endif - ifeq ($(mode),fast) - cflags += -O2 -GL -Zi -DNDEBUG - lflags += -LTCG - endif - ifeq ($(mode),small) - cflags += -O1s -Zi -GL -DNDEBUG - lflags += -LTCG - endif - - strip = : -endif - build-cflags += -DAVIAN_HOST_TARGET c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) @@ -938,7 +945,7 @@ ifeq ($(process),compile) vm-asm-sources += $(src)/compile-$(asm).$(asm-format) endif cflags += -DAVIAN_PROCESS_$(process) -ifdef aot_only +ifeq ($(aot-only),true) cflags += -DAVIAN_AOT_ONLY endif @@ -1488,6 +1495,7 @@ $(bootimage-generator): $(bootimage-generator-objects) $(MAKE) mode=$(mode) \ build=$(host-build-root) \ arch=$(build-arch) \ + aot-only=false \ target-arch=$(arch) \ platform=$(bootimage-platform) \ target-format=$(target-format) \ From 5a1b478b89f426a54308b3ef4ee0ec68d269842e Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Wed, 30 Jan 2013 10:42:05 +0200 Subject: [PATCH 115/378] Allow output of exceptions to debugger. Generate WinMD file --- makefile | 46 ++++++++++++++++++++++++++++------------------ src/machine.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/makefile b/makefile index f24997fed7..d150eb7270 100755 --- a/makefile +++ b/makefile @@ -593,8 +593,8 @@ ifeq ($(platform),windows) shared += -Wl,--add-stdcall-alias endif - embed = $(build-embed)/embed.exe - embed-loader = $(build-embed-loader)/embed-loader.exe + embed = $(build-embed)/embed$(exe-suffix) + embed-loader = $(build-embed-loader)/embed-loader$(exe-suffix) embed-loader-o = $(build-embed)/embed-loader.o endif @@ -657,6 +657,7 @@ ifeq ($(platform),wp8) so-prefix = so-suffix = .dll exe-suffix = .exe + manifest-flags = -MANIFEST:NO ifeq ($(arch),arm) wp8_arch = \x86_arm @@ -696,8 +697,9 @@ ifeq ($(platform),wp8) build-lflags = -lz -lpthread cflags = -nologo \ + -AI"$(WP80_KIT)\Windows Metadata" \ -I"$(WP80_SDK)\include" -I"$(WP80_KIT)\Include" -I"$(WP80_KIT)\Include\minwin" -I"$(WP80_KIT)\Include\mincore" \ - -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP \ + -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP -D_USRDLL -D_WINDLL \ -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ @@ -735,6 +737,11 @@ ifeq ($(platform),wp8) -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ ws2_32.lib \ "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" + lflags += -NXCOMPAT -DYNAMICBASE -SUBSYSTEM:CONSOLE -TLBID:1 + lflags += -NODEFAULTLIB:"ole32.lib" WindowsPhoneCore.lib + lflags += -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) + #lflags += -WINMD:NO + #lflags += -APPCONTAINER cc = $(cxx) asm-format = masm @@ -750,6 +757,7 @@ ifeq ($(platform),wp8) endif output = -Fo$(1) + #TODO: -MT or -ZW? cflags_debug = -Od -Zi -MDd cflags_debug_fast = -Od -Zi -MDd cflags_stress = -O0 -g3 -MD @@ -1079,10 +1087,10 @@ converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) converter = $(build)/binaryToObject/binaryToObject -static-library = $(build)/$(static-prefix)$(name)${static-suffix} +static-library = $(build)/$(static-prefix)$(name)$(static-suffix) executable = $(build)/$(name)${exe-suffix} dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) -executable-dynamic = $(build)/$(name)-dynamic${exe-suffix} +executable-dynamic = $(build)/$(name)-dynamic$(exe-suffix) ifneq ($(classpath),avian) # Assembler, ConstantPool, and Stream are not technically needed for a @@ -1307,7 +1315,8 @@ $(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) $(test-library): $(test-cpp-objects) @echo "linking $(@)" ifdef ms_cl_compiler - $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ + $(ld) $(shared) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(so-suffix),.pdb,$(@)) \ -IMPLIB:$(test-build)/$(name).lib $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" @@ -1320,8 +1329,8 @@ ifdef embed $(embed): $(embed-objects) $(embed-loader-o) @echo "building $(embed)" ifdef ms_cl_compiler - $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1343,8 +1352,8 @@ $(embed-loader): $(embed-loader-objects) $(static-library) @mkdir -p $(dir $(@)) cd $(dir $(@)) && $(ar) x ../../../$(static-library) ifdef ms_cl_compiler - $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1475,8 +1484,8 @@ $(executable): $(executable-objects) @echo "linking $(@)" ifeq ($(platform),windows) ifdef ms_cl_compiler - $(ld) $(lflags) $(executable-objects) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(lflags) $(executable-objects) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1514,8 +1523,8 @@ $(build-bootimage-generator): \ @echo "linking $(@)" ifeq ($(platform),windows) ifdef ms_cl_compiler - $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(bootimage-generator-lflags) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1534,8 +1543,9 @@ $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(lzma-decode-objects) @echo "linking $(@)" ifdef ms_cl_compiler - $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(subst .dll,.pdb,$(@)) \ - -IMPLIB:$(subst .dll,.lib,$(@)) $(manifest-flags) + $(ld) $(shared) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(so-suffix),.pdb,$(@)) \ + -IMPLIB:$(subst $(so-suffix),.lib,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" endif @@ -1552,8 +1562,8 @@ $(executable-dynamic): $(driver-dynamic-objects) $(dynamic-library) @echo "linking $(@)" ifdef ms_cl_compiler $(ld) $(lflags) -LIBPATH:$(build) -DEFAULTLIB:$(name) \ - -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) \ - -out:$(@) $(manifest-flags) + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) + $(driver-dynamic-objects) -out:$(@) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif diff --git a/src/machine.cpp b/src/machine.cpp index 5e08655898..c3c398bd92 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -17,6 +17,11 @@ #include "arch.h" #include "lzma.h" +#if defined(PLATFORM_WINDOWS) +# define WIN32_LEAN_AND_MEAN +# include +#endif + using namespace vm; namespace { @@ -4741,18 +4746,33 @@ printTrace(Thread* t, object exception) for (object e = exception; e; e = throwableCause(t, e)) { if (e != exception) { fprintf(errorLog(t), "caused by: "); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("caused by: "); +#endif } fprintf(errorLog(t), "%s", &byteArrayBody (t, className(t, objectClass(t, e)), 0)); - +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA((const CHAR*)&byteArrayBody + (t, className(t, objectClass(t, e)), 0)); +#endif + if (throwableMessage(t, e)) { object m = throwableMessage(t, e); THREAD_RUNTIME_ARRAY(t, char, message, stringLength(t, m) + 1); stringChars(t, m, RUNTIME_ARRAY_BODY(message)); fprintf(errorLog(t), ": %s\n", RUNTIME_ARRAY_BODY(message)); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA(": "); + OutputDebugStringA(RUNTIME_ARRAY_BODY(message)); + OutputDebugStringA("\n"); +#endif } else { fprintf(errorLog(t), "\n"); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("\n"); +#endif } object trace = throwableTrace(t, e); @@ -4767,16 +4787,35 @@ printTrace(Thread* t, object exception) (t, traceElementMethod(t, e), traceElementIp(t, e)); fprintf(errorLog(t), " at %s.%s ", class_, method); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA(" at "); + OutputDebugStringA((const CHAR*)class_); + OutputDebugStringA("."); + OutputDebugStringA((const CHAR*)method); + OutputDebugStringA(" "); +#endif switch (line) { case NativeLine: fprintf(errorLog(t), "(native)\n"); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("(native)\n"); +#endif break; case UnknownLine: fprintf(errorLog(t), "(unknown line)\n"); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("(unknown line)\n"); +#endif break; default: fprintf(errorLog(t), "(line %d)\n", line); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("(line "); + char buf[35]; + OutputDebugStringA(itoa(line, buf, 10)); + OutputDebugStringA(")\n"); +#endif } } } From 7cd194b5de0b24f701578c0add8c12a4fd0dd9b2 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Wed, 30 Jan 2013 11:31:06 +0200 Subject: [PATCH 116/378] Finally, proper jvm.dll linking for WP8 --- makefile | 8 +++----- src/machine.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/makefile b/makefile index d150eb7270..ab404633c1 100755 --- a/makefile +++ b/makefile @@ -734,14 +734,12 @@ ifeq ($(platform),wp8) arflags = -MACHINE:$(machine_type) lflags = $(common-lflags) -nologo \ -MACHINE:$(machine_type) \ - -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ + -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WP80_SDK)\lib$(vc_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" \ ws2_32.lib \ "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" lflags += -NXCOMPAT -DYNAMICBASE -SUBSYSTEM:CONSOLE -TLBID:1 - lflags += -NODEFAULTLIB:"ole32.lib" WindowsPhoneCore.lib - lflags += -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) - #lflags += -WINMD:NO - #lflags += -APPCONTAINER + lflags += -NODEFAULTLIB:"ole32.lib" -NODEFAULTLIB:"kernel32.lib" + lflags += PhoneAppModelHost.lib WindowsPhoneCore.lib -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) cc = $(cxx) asm-format = masm diff --git a/src/machine.h b/src/machine.h index 420a0192cb..5a2812c2b7 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2695,7 +2695,7 @@ throw_(Thread* t, object e) t->exception = e; - // printTrace(t, e); + printTrace(t, e); popResources(t); From d468d7eabacfaf9ce59440a34b6c7a705744edba Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 12:54:51 +0200 Subject: [PATCH 117/378] Fix WP8/WinRT ARM build --- makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index ab404633c1..f0cb5494fb 100755 --- a/makefile +++ b/makefile @@ -667,10 +667,12 @@ ifeq ($(platform),wp8) as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" - asmflags = $(target-cflags) -machine ARM -32 + asmflags = -machine ARM -32 asm-output = -o $(1) asm-input = $(1) machine_type = ARM + bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end + codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end endif ifeq ($(arch),i386) wp8_arch = From 9b9bc1de00b89b6130102f5d666da3c3e48a492f Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 12:55:12 +0200 Subject: [PATCH 118/378] Fix crash on memory validation --- src/windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows.cpp b/src/windows.cpp index d0b5228368..98fc8e5d96 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -924,7 +924,7 @@ class MySystem: public System { } #else #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") - return name; + return copy(allocator, name); #endif } From e523547b1939f07f5feef30fe50deb9a3513380b Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 14:54:23 +0200 Subject: [PATCH 119/378] Allow avian.bootstrap to accept multiple libraries --- src/jnienv.cpp | 10 ---------- src/jnienv.h | 10 ++++++++++ src/machine.cpp | 23 ++++++++++++++++++++++- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 2a70b10855..c8f27fb0b7 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3709,16 +3709,6 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) } // namespace vm -#define BOOTSTRAP_PROPERTY "avian.bootstrap" -#define CRASHDIR_PROPERTY "avian.crash.dir" -#define EMBED_PREFIX_PROPERTY "avian.embed.prefix" -#define CLASSPATH_PROPERTY "java.class.path" -#define JAVA_HOME_PROPERTY "java.home" -#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" -#define BOOTCLASSPATH_OPTION "bootclasspath" -#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" -#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" - extern "C" JNIEXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void*) { diff --git a/src/jnienv.h b/src/jnienv.h index 5b8c46685b..8dbd1f8c7d 100644 --- a/src/jnienv.h +++ b/src/jnienv.h @@ -13,6 +13,16 @@ #include "machine.h" +#define BOOTSTRAP_PROPERTY "avian.bootstrap" +#define CRASHDIR_PROPERTY "avian.crash.dir" +#define EMBED_PREFIX_PROPERTY "avian.embed.prefix" +#define CLASSPATH_PROPERTY "java.class.path" +#define JAVA_HOME_PROPERTY "java.home" +#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" +#define BOOTCLASSPATH_OPTION "bootclasspath" +#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" +#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" + namespace vm { void diff --git a/src/machine.cpp b/src/machine.cpp index c3c398bd92..e060cd0a9e 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3008,6 +3008,13 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, populateJNITables(&javaVMVTable, &jniEnvVTable); + const char* bootstrapProperty = strdup(findProperty(this, BOOTSTRAP_PROPERTY)); + const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); + char* codeLibraryName = (char*)bootstrapProperty; + char* codeLibraryNameEnd = 0; + if (codeLibraryName && (codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()))) + *codeLibraryNameEnd = 0; + if (not system->success(system->make(&localThread)) or not system->success(system->make(&stateLock)) or not system->success(system->make(&heapLock)) or @@ -3015,10 +3022,24 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, not system->success(system->make(&referenceLock)) or not system->success(system->make(&shutdownLock)) or not system->success - (system->load(&libraries, findProperty(this, "avian.bootstrap")))) + (system->load(&libraries, bootstrapProperty))) { system->abort(); } + + System::Library* additionalLibrary = 0; + while (codeLibraryNameEnd && codeLibraryNameEnd + 1 < bootstrapPropertyEnd) { + codeLibraryName = codeLibraryNameEnd + 1; + codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()); + if (codeLibraryNameEnd) + *codeLibraryNameEnd = 0; + + if (!system->success(system->load(&additionalLibrary, codeLibraryName))) + system->abort(); + libraries->setNext(additionalLibrary); + } + + free((void*)bootstrapProperty); } void From 2e3856211b3433f502f88be3f0095e71a480602f Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:06:35 +0200 Subject: [PATCH 120/378] Fix crash if no avian.boostrap is specified --- src/machine.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index e060cd0a9e..a0cd3184ce 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3008,7 +3008,8 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, populateJNITables(&javaVMVTable, &jniEnvVTable); - const char* bootstrapProperty = strdup(findProperty(this, BOOTSTRAP_PROPERTY)); + const char* bootstrapProperty = findProperty(this, BOOTSTRAP_PROPERTY); + const char* bootstrapPropertyDup = bootstrapProperty ? strdup(bootstrapProperty) : 0; const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); char* codeLibraryName = (char*)bootstrapProperty; char* codeLibraryNameEnd = 0; @@ -3039,7 +3040,8 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, libraries->setNext(additionalLibrary); } - free((void*)bootstrapProperty); + if(bootstrapPropertyDup) + free((void*)bootstrapPropertyDup); } void From 8e879f80a757bc9e47dcd597e4ba7777f21728e8 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:07:56 +0200 Subject: [PATCH 121/378] Fix crash if no avian.boostrap is specified (oops) --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index a0cd3184ce..dce3bfe185 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3011,7 +3011,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, const char* bootstrapProperty = findProperty(this, BOOTSTRAP_PROPERTY); const char* bootstrapPropertyDup = bootstrapProperty ? strdup(bootstrapProperty) : 0; const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); - char* codeLibraryName = (char*)bootstrapProperty; + char* codeLibraryName = (char*)bootstrapPropertyDup; char* codeLibraryNameEnd = 0; if (codeLibraryName && (codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()))) *codeLibraryNameEnd = 0; From ba0ec3759d139cc793f54a0836ba20ae89f1205c Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:08:26 +0200 Subject: [PATCH 122/378] Fix crash if no avian.boostrap is specified (oops) --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index dce3bfe185..84a34caf67 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3010,7 +3010,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, const char* bootstrapProperty = findProperty(this, BOOTSTRAP_PROPERTY); const char* bootstrapPropertyDup = bootstrapProperty ? strdup(bootstrapProperty) : 0; - const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); + const char* bootstrapPropertyEnd = bootstrapPropertyDup + (bootstrapPropertyDup ? strlen(bootstrapPropertyDup) : 0); char* codeLibraryName = (char*)bootstrapPropertyDup; char* codeLibraryNameEnd = 0; if (codeLibraryName && (codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()))) From 3287b1354a247d732c0a101af999514ae88eb839 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:10:42 +0200 Subject: [PATCH 123/378] Fix crash if no avian.boostrap is specified (oops) --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index 84a34caf67..d2d225e7e5 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3023,7 +3023,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, not system->success(system->make(&referenceLock)) or not system->success(system->make(&shutdownLock)) or not system->success - (system->load(&libraries, bootstrapProperty))) + (system->load(&libraries, bootstrapPropertyDup))) { system->abort(); } From a03fda0c1d69d49fbbfa47d57990964c7d61156d Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 16:36:29 +0200 Subject: [PATCH 124/378] Instead of throwing exception, just return initial file name --- classpath/java-io.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 3860e67ecd..580efe96d2 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -240,8 +240,8 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else - // WinRT has no concept of full paths - throwNewErrno(e, "java/io/IOException"); + // WinRT has no concept of full paths, so any file + // accessed should already have full path, or it has explicit origin return path; # endif #else From 3f22c6d8e3223a46b6db1975eed7ee7e59d9716a Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 16:40:12 +0200 Subject: [PATCH 125/378] Remove debug code --- classpath/java-io.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 580efe96d2..bb1adce8b3 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -700,9 +700,6 @@ Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path, jboolean app return -1; } } -#ifdef __ANDROID__ -#include -#endif extern "C" JNIEXPORT void JNICALL Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c) @@ -723,11 +720,6 @@ Java_java_io_FileOutputStream_write__I_3BII } e->GetByteArrayRegion(b, offset, length, data); - #ifdef __ANDROID__ - if(fd == 1) { - __android_log_print(ANDROID_LOG_WARN, "net.osmand:native", "%.*s",length, data); - } - #endif if (not e->ExceptionCheck()) { doWrite(e, fd, data, length); } From ebf6277660472f9fb1fde8c5c349781b59130905 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 16:55:37 +0200 Subject: [PATCH 126/378] java.io.RandomAccessFile for WinPhone8 / WinRT --- classpath/java-io.cpp | 57 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index bb1adce8b3..39186a0274 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -739,6 +739,9 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, { string_t chars = getChars(e, path); if (chars) { + jlong peer = 0; + jlong length = 0; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int fd = ::open((const char*)chars, O_RDONLY); releaseChars(e, path, chars); if (fd == -1) { @@ -751,11 +754,27 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, throwNewErrno(e, "java/io/IOException"); return; } + peer = fd; + length = fileStats.st_size; + #else + HANDLE hFile = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + if (hFile == INVALID_HANDLE_VALUE) { + throwNewErrno(e, "java/io/IOException"); + return; + } + + FILE_STANDARD_INFO info; + if(!GetFileInformationByHandleEx(hFile, FileStandardInfo, &info, sizeof(info))) { + throwNewErrno(e, "java/io/IOException"); + return; + } + + peer = (jlong)hFile; + length = info.EndOfFile.QuadPart; + #endif - jlong peer = fd; e->SetLongArrayRegion(result, 0, 1, &peer); - - jlong length = fileStats.st_size; e->SetLongArrayRegion(result, 1, 1, &length); } } @@ -765,6 +784,7 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, jlong position, jbyteArray buffer, int offset, int length) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int fd = (int)peer; if(::lseek(fd, position, SEEK_SET) == -1) { throwNewErrno(e, "java/io/IOException"); @@ -773,24 +793,45 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); -#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + ssize_t bytesRead = ::read(fd, dst + offset, length); -#else - auto bytesRead = ::read(fd, dst + offset, length); -#endif e->ReleasePrimitiveArrayCritical(buffer, dst, 0); if(bytesRead == -1) { throwNewErrno(e, "java/io/IOException"); return -1; } - +#else + HANDLE hFile = (HANDLE)peer; + LARGE_INTEGER lPos; + lPos.QuadPart = position; + if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + uint8_t* dst = reinterpret_cast + (e->GetPrimitiveArrayCritical(buffer, 0)); + + DWORD bytesRead = 0; + if(!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); +#endif + return (jint)bytesRead; } extern "C" JNIEXPORT void JNICALL Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int fd = (int)peer; ::close(fd); +#else + HANDLE hFile = (HANDLE)peer; + CloseHandle(hFile); +#endif } From cb46cb0ba871f9354fb3bda685affc022e730021 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 17:49:08 +0200 Subject: [PATCH 127/378] WP8/WinRT : Proper absolute path WP8/WinRT : Last modified time --- classpath/java-io.cpp | 122 +++++++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 31 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 39186a0274..880d91cf56 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -240,8 +240,29 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else - // WinRT has no concept of full paths, so any file - // accessed should already have full path, or it has explicit origin + string_t chars = getChars(e, path); + if(chars) { + LARGE_INTEGER fileSize; + HANDLE file = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + releaseChars(e, path, chars); + + if (file == INVALID_HANDLE_VALUE) + return path; + + uint8_t buffer[sizeof(FILE_NAME_INFO) + sizeof(WCHAR)*MAX_PATH]; + memset(&buffer[0], 0, sizeof(buffer)); + FILE_NAME_INFO* pInfo = reinterpret_cast(&buffer[0]); + if(!GetFileInformationByHandleEx(file, FileNameInfo, pInfo, sizeof(buffer))) + { + CloseHandle(file); + return path; + } + CloseHandle(file); + + return e->NewString + (reinterpret_cast(pInfo->FileName), pInfo->FileNameLength / sizeof(WCHAR)); + } return path; # endif #else @@ -267,33 +288,40 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) extern "C" JNIEXPORT jlong JNICALL Java_java_io_File_length(JNIEnv* e, jclass, jstring path) { - #ifdef PLATFORM_WINDOWS - LARGE_INTEGER fileSize; string_t chars = getChars(e, path); - #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - HANDLE file = CreateFileW - (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); - #else - HANDLE file = CreateFile2 - (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); - #endif - releaseChars(e, path, chars); - if (file != INVALID_HANDLE_VALUE) - { + if(chars) { + LARGE_INTEGER fileSize; #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - GetFileSizeEx(file, &fileSize); + HANDLE file = CreateFileW + (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + #else + HANDLE file = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + #endif + releaseChars(e, path, chars); + if (file == INVALID_HANDLE_VALUE) + return 0; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + if(!GetFileSizeEx(file, &fileSize)) + { + CloseHandle(file); + return 0; + } #else FILE_STANDARD_INFO info; - if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) - fileSize = info.EndOfFile; + if(!GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + { + CloseHandle(file); + return 0; + } + fileSize = info.EndOfFile; #endif - } - else return 0; - CloseHandle(file); - return static_cast(fileSize.QuadPart); + CloseHandle(file); + return static_cast(fileSize.QuadPart); + } #else string_t chars = getChars(e, path); @@ -547,21 +575,52 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) string_t chars = getChars(e, path); if (chars) { #ifdef PLATFORM_WINDOWS - # pragma message("Implementation of last modified") - return 0; - #else - struct stat st; - if (stat(chars, &st)) { + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + HANDLE hFile = CreateFileW + (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + #else + HANDLE hFile = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + #endif + releaseChars(e, path, chars); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + LARGE_INTEGER fileDate, filetimeToUnixEpochAdjustment; + filetimeToUnixEpochAdjustment.QuadPart = 11644473600000L * 10000L; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + FILETIME fileLastWriteTime; + if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime)) + { + CloseHandle(hFile); + return 0; + } + fileDate.HighPart = fileLastWriteTime.dwHighDateTime; + fileDate.LowPart = fileLastWriteTime.dwLowDateTime; + #else + FILE_BASIC_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo))) + { + CloseHandle(hFile); + return 0; + } + fileDate = fileInfo.ChangeTime; + #endif + CloseHandle(hFile); + fileDate.QuadPart -= filetimeToUnixEpochAdjustment.QuadPart; + return fileDate.QuadPart / 10000000L; + #else + struct stat fileStat; + if (stat(chars, &fileStat) == -1) { + releaseChars(e, path, chars); return 0; - } else { - return (static_cast(st.st_mtim.tv_sec) * 1000) + - (static_cast(st.st_mtim.tv_nsec) / (1000*1000)); } + return (static_cast(st.st_mtim.tv_sec) * 1000) + + (static_cast(st.st_mtim.tv_nsec) / (1000*1000)); #endif - } else { - return 0; } + + return 0; } extern "C" JNIEXPORT jstring JNICALL @@ -766,6 +825,7 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, FILE_STANDARD_INFO info; if(!GetFileInformationByHandleEx(hFile, FileStandardInfo, &info, sizeof(info))) { + CloseHandle(hFile); throwNewErrno(e, "java/io/IOException"); return; } From c33c148b6b5c7295f3881df29def2b920cee4c47 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 18:18:52 +0200 Subject: [PATCH 128/378] Add notifications about improvements possible --- classpath/java-io.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 880d91cf56..74f2ab9617 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -289,7 +289,8 @@ extern "C" JNIEXPORT jlong JNICALL Java_java_io_File_length(JNIEnv* e, jclass, jstring path) { #ifdef PLATFORM_WINDOWS - + // Option: without opening file + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx string_t chars = getChars(e, path); if(chars) { LARGE_INTEGER fileSize; @@ -575,6 +576,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) string_t chars = getChars(e, path); if (chars) { #ifdef PLATFORM_WINDOWS + // Option: without opening file + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE hFile = CreateFileW (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); From 34179f33322029f7c6409f8b0d82675d1f6fdc30 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 20:54:15 +0200 Subject: [PATCH 129/378] Added comments regarding java.io.File.toAbsolute() and WinRT/WP8 --- classpath/java-io.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 74f2ab9617..3d26a49f02 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -240,6 +240,13 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else +// This could have worked, if GetFileInformationByHandleEx() returned volume information also +// There is a chance to get it, or using GetFullPathName, that is claimed to be unsupported +// or from System.IO.Path.GetFullPath(), but it's CLR and I see no way of calling it from +// C++/CX code +// Best wishes to everyone who will win this fight, +// Alexey Pelykh +/* string_t chars = getChars(e, path); if(chars) { LARGE_INTEGER fileSize; @@ -263,6 +270,7 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return e->NewString (reinterpret_cast(pInfo->FileName), pInfo->FileNameLength / sizeof(WCHAR)); } +*/ return path; # endif #else From 41c726989627b903e6572c872ad1395eb0895c7e Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 09:38:03 +0200 Subject: [PATCH 130/378] Support new WinRT interop --- classpath/java-io.cpp | 38 ++++++++++++++------------------------ makefile | 9 +++++---- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 3d26a49f02..ba4812a5a4 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -55,6 +55,15 @@ typedef wchar_t char_t; +#if defined(WINAPI_FAMILY) +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#include "avian-interop.h" +#define SKIP_OPERATOR_NEW + +#endif +#endif + #else // not PLATFORM_WINDOWS # include @@ -93,7 +102,9 @@ typedef char char_t; # endif #endif // WINAPI_FAMILY +#if !defined(SKIP_OPERATOR_NEW) inline void* operator new(size_t, void* p) throw() { return p; } +#endif typedef const char_t* string_t; @@ -240,37 +251,16 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else -// This could have worked, if GetFileInformationByHandleEx() returned volume information also -// There is a chance to get it, or using GetFullPathName, that is claimed to be unsupported -// or from System.IO.Path.GetFullPath(), but it's CLR and I see no way of calling it from -// C++/CX code -// Best wishes to everyone who will win this fight, -// Alexey Pelykh -/* string_t chars = getChars(e, path); if(chars) { - LARGE_INTEGER fileSize; - HANDLE file = CreateFile2 - (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + std::wstring partialPath = chars; releaseChars(e, path, chars); - if (file == INVALID_HANDLE_VALUE) - return path; - - uint8_t buffer[sizeof(FILE_NAME_INFO) + sizeof(WCHAR)*MAX_PATH]; - memset(&buffer[0], 0, sizeof(buffer)); - FILE_NAME_INFO* pInfo = reinterpret_cast(&buffer[0]); - if(!GetFileInformationByHandleEx(file, FileNameInfo, pInfo, sizeof(buffer))) - { - CloseHandle(file); - return path; - } - CloseHandle(file); + std::wstring fullPath = AvianInterop::GetFullPath(partialPath); return e->NewString - (reinterpret_cast(pInfo->FileName), pInfo->FileNameLength / sizeof(WCHAR)); + (reinterpret_cast(fullPath.c_str()), fullPath.length()); } -*/ return path; # endif #else diff --git a/makefile b/makefile index f0cb5494fb..73f5c69936 100755 --- a/makefile +++ b/makefile @@ -705,12 +705,12 @@ ifeq ($(platform),wp8) -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ - -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" \ - -Fd$(build)/$(name).pdb -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ + -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" -I"$(shell $(windows-path) "$(wp8)/interop/avian-interop-client")" \ + -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ -DTARGET_BYTES_PER_WORD=$(pointer-size) \ - -Gd + -Gd -EHsc common-lflags = $(classpath-lflags) @@ -738,7 +738,8 @@ ifeq ($(platform),wp8) -MACHINE:$(machine_type) \ -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WP80_SDK)\lib$(vc_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" \ ws2_32.lib \ - "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" \ + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\AvianInteropClient.lib")" lflags += -NXCOMPAT -DYNAMICBASE -SUBSYSTEM:CONSOLE -TLBID:1 lflags += -NODEFAULTLIB:"ole32.lib" -NODEFAULTLIB:"kernel32.lib" lflags += PhoneAppModelHost.lib WindowsPhoneCore.lib -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) From 2362235b4c033976ca38ed54714050424923eff0 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 10:14:47 +0200 Subject: [PATCH 131/378] getErrorStr() for Windows platforms --- classpath/java-lang.cpp | 45 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 9d2562e265..dc54af5fed 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -74,25 +74,36 @@ namespace { #ifdef PLATFORM_WINDOWS - char* getErrorStr(DWORD err){ - // The poor man's error string, just print the error code - char * errStr = (char*) malloc(9 * sizeof(char)); - snprintf(errStr, 9, "%d", (int) err); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + char* getErrorStr(DWORD err) { + LPSTR errorStr = 0; + if(!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, (LPSTR)&errorStr, 0, 0)) + { + char* errStr = (char*) malloc(9 * sizeof(char)); + snprintf(errStr, 9, "%d", (int) err); + return errStr; + } + char* errStr = strdup(errorStr); + LocalFree(errorStr); return errStr; - - #pragma message("TODO") - // The better way to do this, if I could figure out how to convert LPTSTR to char* - //char* errStr; - //LPTSTR s; - //if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - // FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, &s, 0, NULL) == 0) - //{ - // errStr.Format("Unknown error occurred (%08x)", err); - //} else { - // errStr = s; - //} - //return errStr; } +#else + char* getErrorStr(DWORD err) { + LPSTR errorStr = (LPSTR)malloc(4096); //NOTE: something constant + if(!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, errorStr, 0, 0)) + { + free(errorStr); + + char* errStr = (char*) malloc(9 * sizeof(char)); + snprintf(errStr, 9, "%d", (int) err); + return errStr; + } + char* errStr = strdup(errorStr); + free(errorStr); + return errStr; + } +#endif #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void makePipe(JNIEnv* e, HANDLE p[2]) From 0ff703d1c0227e905fd64f9059082459d2d583a9 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 11:00:33 +0200 Subject: [PATCH 132/378] Culture fixes ; Path extensions --- classpath/java-lang.cpp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index dc54af5fed..704e2ae6a5 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -69,6 +69,12 @@ # ifndef WINAPI_FAMILY_PARTITION # define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#else +# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +# include "avian-interop.h" + # endif #endif // WINAPI_FAMILY @@ -401,8 +407,20 @@ Locale getLocale() { return Locale(lang, reg); #else - #pragma message("TODO: CultureInfo.CurrentCulture") - return Locale("en", "US"); + std::wstring culture = AvianInterop::GetCurrentUICulture(); + char* cultureName = strdup(std::string(culture.begin(), culture.end()).c_str()); + char* delimiter = strchr(cultureName, '-'); + if(!delimiter) + { + free(cultureName); + return Locale("en", "US"); + } + const char* lang = cultureName; + const char* reg = delimiter + 1; + *delimiter = 0; + Locale locale(lang, reg); + free(cultureName); + return locale; #endif } #else @@ -607,8 +625,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetTempPath(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.ApplicationData.Current.TemporaryFolder") - r = 0; + std::wstring tmpDir = AvianInterop::GetTemporaryFolder(); + r = e->NewString((const jchar*)tmpDir.c_str(), tmpDir.length()); # endif } else if (strcmp(chars, "user.dir") == 0) { # if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -616,8 +634,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetCurrentDirectory(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") - r = 0; + std::wstring userDir = AvianInterop::GetInstalledLocation(); + r = e->NewString((const jchar*)userDir.c_str(), userDir.length()); # endif } else if (strcmp(chars, "user.home") == 0) { # ifdef _MSC_VER @@ -630,8 +648,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = 0; } # else - #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.KnownFolders.DocumentsLibrary") - r = 0; + std::wstring userHome = AvianInterop::GetDocumentsLibraryLocation(); + r = e->NewString((const jchar*)userHome.c_str(), userHome.length()); # endif # else LPWSTR home = _wgetenv(L"USERPROFILE"); From 1d60ababd3683e9e83b468c082cd7650d127959d Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 12:27:36 +0200 Subject: [PATCH 133/378] Support built-in jars when wusing multi-library --- src/jnienv.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index c8f27fb0b7..4295c7e0a3 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3729,7 +3729,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) unsigned heapLimit = 0; unsigned stackLimit = 0; - const char* bootLibrary = 0; + const char* bootLibraries = 0; const char* classpath = 0; const char* javaHome = AVIAN_JAVA_HOME; const char* embedPrefix = AVIAN_EMBED_PREFIX; @@ -3765,7 +3765,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) if (strncmp(p, BOOTSTRAP_PROPERTY "=", sizeof(BOOTSTRAP_PROPERTY)) == 0) { - bootLibrary = p + sizeof(BOOTSTRAP_PROPERTY); + bootLibraries = p + sizeof(BOOTSTRAP_PROPERTY); } else if (strncmp(p, CRASHDIR_PROPERTY "=", sizeof(CRASHDIR_PROPERTY)) == 0) { @@ -3819,9 +3819,16 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) *RUNTIME_ARRAY_BODY(bootClasspathBuffer) = 0; } + char* bootLibrary = bootLibraries ? strdup(bootLibraries) : 0; + char* bootLibraryEnd = bootLibrary ? strchr(bootLibrary, PATH_SEPARATOR) : 0; + if(bootLibraryEnd) + *bootLibraryEnd = 0; + Finder* bf = makeFinder (s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary); Finder* af = makeFinder(s, h, classpath, bootLibrary); + if(bootLibrary) + free(bootLibrary); Processor* p = makeProcessor(s, h, true); const char** properties = static_cast From 023af5102efc4c7754ae865a35c4114fe2299419 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 19:42:47 +0200 Subject: [PATCH 134/378] Remove empty lines Conflicts: classpath/java-lang.cpp --- classpath/java-lang.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 704e2ae6a5..88a4cf5ef6 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -898,6 +898,11 @@ Java_java_lang_Math_atan(JNIEnv*, jclass, jdouble val) return atan(val); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_atan2(JNIEnv*, jclass, jdouble y, jdouble x) +{ + return atan2(y, x); +} extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sinh(JNIEnv*, jclass, jdouble val) @@ -917,7 +922,6 @@ Java_java_lang_Math_tanh(JNIEnv*, jclass, jdouble val) return tanh(val); } - extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val) { From 33d4f008f42a7d62dff17476ef1999d1853acd81 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 20:09:28 +0200 Subject: [PATCH 135/378] Fix dword<>qword mistake --- src/x86.masm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.masm b/src/x86.masm index 640637d5af..2f9dedcbd2 100644 --- a/src/x86.masm +++ b/src/x86.masm @@ -108,7 +108,7 @@ Lfloat: Ldouble: cmp ecx,offset DOUBLE_TYPE jne Lexit - fstp ds:dword ptr[8+ebp] + fstp ds:qword ptr[8+ebp] mov eax,ds:dword ptr[8+ebp] mov edx,ds:dword ptr[12+ebp] From 18cb5ba3792e43589302c4ea242681c2f414c9ae Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sun, 3 Feb 2013 12:27:30 +0200 Subject: [PATCH 136/378] Make clean target more robust Conflicts: .gitignore --- .gitignore | 1 + makefile | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 201518bb12..588446f90d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build bin /lib /distrib +*.pdb diff --git a/makefile b/makefile index 73f5c69936..af5533815f 100755 --- a/makefile +++ b/makefile @@ -1248,6 +1248,11 @@ javadoc: .PHONY: clean clean: + @echo "removing $(build)" + rm -rf $(build) + +.PHONY: clean-all +clean-all: @echo "removing build" rm -rf build From edbea8ac2be4dd5dd3ae2b02f7b14b0d85c8048e Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 4 Feb 2013 19:45:06 +0200 Subject: [PATCH 137/378] Comment out printTrace --- src/machine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.h b/src/machine.h index 5a2812c2b7..420a0192cb 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2695,7 +2695,7 @@ throw_(Thread* t, object e) t->exception = e; - printTrace(t, e); + // printTrace(t, e); popResources(t); From e6fc4e3bea0c84087133e488beaf103430da2b8b Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 4 Feb 2013 20:02:46 +0200 Subject: [PATCH 138/378] RUNTIME_ARRAY usage --- src/arm.cpp | 5 +---- src/arm.h | 6 ++---- src/bootimage.cpp | 42 +++++++++++++++--------------------------- src/common.h | 4 ++++ src/interpret.cpp | 5 +---- 5 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 1d4dbc8dd1..3016c4658b 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -2555,7 +2555,7 @@ class MyAssembler: public Assembler { OperandType type; Operand* operand; }; - Argument* arguments = new Argument[argumentCount]; + RUNTIME_ARRAY(Argument, arguments, argumentCount); va_list a; va_start(a, argumentCount); unsigned footprint = 0; @@ -2590,9 +2590,6 @@ class MyAssembler: public Assembler { offset += ceiling(arguments[i].size, TargetBytesPerWord); } } - - delete[] arguments; - arguments = 0; } virtual void allocateFrame(unsigned footprint) { diff --git a/src/arm.h b/src/arm.h index 302355c453..5593c86f92 100644 --- a/src/arm.h +++ b/src/arm.h @@ -182,7 +182,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, unsigned vfpIndex = 0; unsigned vfpBackfillIndex UNUSED = 0; - uintptr_t* stack = new uintptr_t[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding + RUNTIME_ARRAY(uintptr_t, stack, (argumentCount * 8) / BytesPerWord); // is > argumentSize to account for padding unsigned stackIndex = 0; unsigned ai = 0; @@ -272,12 +272,10 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, } unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2); - auto retVal = vmNativeCall + return vmNativeCall (function, stackSize, stack, stackIndex * BytesPerWord, (gprIndex ? gprTable : 0), (vfpIndex ? vfpTable : 0), returnType); - delete[] stack; - return retVal; } } // namespace vm diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 5b725f5058..5ec14b51e6 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -342,7 +342,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, unsigned count = s.read2() - 1; if (count) { - Type* types = new Type[count + 2]; + RUNTIME_ARRAY(Type, types, count + 2); types[0] = Type_object; types[1] = Type_intptr_t; @@ -410,9 +410,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, (t, typeMaps, hashMapFind (t, root(t, Machine::PoolMap), c, objectHash, objectEqual), array, objectHash); - - delete[] types; - types = 0; } } @@ -423,7 +420,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object fields = allFields(t, typeMaps, c, &count, &array); PROTECT(t, fields); - Field* memberFields = new Field[count + 1]; + RUNTIME_ARRAY(Field, memberFields, count + 1); unsigned memberIndex; unsigned buildMemberOffset; @@ -447,7 +444,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ++ memberIndex; } } else { - init(new (memberFields) Field, Type_object, 0, BytesPerWord, 0, + init(new (&memberFields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); memberIndex = 1; @@ -457,15 +454,15 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, const unsigned StaticHeader = 3; - Field* staticFields = new Field[count + StaticHeader]; + RUNTIME_ARRAY(Field, staticFields, count + StaticHeader); - init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, + init(new (&staticFields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); - init(new (staticFields + 1) Field, Type_intptr_t, BytesPerWord, + init(new (&staticFields[1]) Field, Type_intptr_t, BytesPerWord, BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); - init(new (staticFields + 2) Field, Type_object, BytesPerWord * 2, + init(new (&staticFields[2]) Field, Type_object, BytesPerWord * 2, BytesPerWord, TargetBytesPerWord * 2, TargetBytesPerWord); unsigned staticIndex = StaticHeader; @@ -515,7 +512,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildStaticOffset = fieldOffset(t, field); - init(new (staticFields + staticIndex) Field, type, + init(new (&staticFields[staticIndex]) Field, type, buildStaticOffset, buildSize, targetStaticOffset, targetSize); @@ -529,7 +526,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildMemberOffset = fieldOffset(t, field); - init(new (memberFields + memberIndex) Field, type, + init(new (&memberFields[memberIndex]) Field, type, buildMemberOffset, buildSize, targetMemberOffset, targetSize); @@ -552,7 +549,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ceiling(targetMemberOffset, TargetBytesPerWord), memberIndex); for (unsigned i = 0; i < memberIndex; ++i) { - Field* f = memberFields + i; + Field* f = &memberFields[i]; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -576,7 +573,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, TypeMap::SingletonKind); for (unsigned i = 0; i < staticIndex; ++i) { - Field* f = staticFields + i; + Field* f = &staticFields[i]; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -589,12 +586,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, hashMapInsert (t, typeMaps, classStaticTable(t, c), array, objectHash); } - - delete[] memberFields; - memberFields = 0; - - delete[] staticFields; - staticFields = 0; } } } @@ -1343,9 +1334,9 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp } ++ count; - Field* fields = new Field[count]; + RUNTIME_ARRAY(Field, fields, count); - init(new (fields) Field, Type_object, 0, BytesPerWord, 0, + init(new (&fields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); unsigned buildOffset = BytesPerWord; @@ -1423,7 +1414,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp ++ targetOffset; } - init(new (fields + j) Field, type, buildOffset, buildSize, + init(new (&fields[j]) Field, type, buildOffset, buildSize, targetOffset, targetSize); buildOffset += buildSize; @@ -1458,7 +1449,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp targetArrayElementSize, arrayElementType); for (unsigned j = 0; j < fixedFieldCount; ++j) { - Field* f = fields + j; + Field* f = &fields[j]; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -1471,9 +1462,6 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp hashMapInsert (t, typeMaps, vm::type(t, static_cast(i)), array, objectHash); - - delete[] fields; - fields = 0; } constants = makeCodeImage diff --git a/src/common.h b/src/common.h index c99f23410e..6803fe4c34 100644 --- a/src/common.h +++ b/src/common.h @@ -243,6 +243,10 @@ class RuntimeArray { free(body); } + T& operator[] (const unsigned index) { + return body[index]; + } + T* body; }; diff --git a/src/interpret.cpp b/src/interpret.cpp index 9399e96657..42183e98f0 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2321,7 +2321,7 @@ interpret3(Thread* t, const int base) object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); PROTECT(t, class_); - int32_t* counts = new int32_t[dimensions]; + RUNTIME_ARRAY(int32_t, counts, dimensions); for (int i = dimensions - 1; i >= 0; --i) { counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { @@ -2338,9 +2338,6 @@ interpret3(Thread* t, const int base) populateMultiArray(t, array, counts, 0, dimensions); pushObject(t, array); - - delete[] counts; - counts = 0; } goto loop; case new_: { From 9e4144f92baa6ce3b2ff5954492e8073df8690b5 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 5 Feb 2013 08:41:37 +0200 Subject: [PATCH 139/378] Trace writeout refactor --- src/machine.cpp | 73 ++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index d2d225e7e5..46f331c32d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -4759,6 +4759,27 @@ visitRoots(Machine* m, Heap::Visitor* v) } } +void +logTrace(FILE* f, const char* fmt, ...) +{ + va_list a; + va_start(a, fmt); +#ifdef PLATFORM_WINDOWS + const unsigned length = _vscprintf(fmt, a); +#else + const unsigned length = vsnprintf(0, 0, fmt, a); +#endif + RUNTIME_ARRAY(char, buffer, length + 1); + vsnprintf(&buffer[0], length, fmt, a); + buffer[length] = 0; + va_end(a); + + ::fprintf(f, "%s", &buffer[0]); +#ifdef PLATFORM_WINDOWS + ::OutputDebugStringA(&buffer[0]); +#endif +} + void printTrace(Thread* t, object exception) { @@ -4768,34 +4789,19 @@ printTrace(Thread* t, object exception) for (object e = exception; e; e = throwableCause(t, e)) { if (e != exception) { - fprintf(errorLog(t), "caused by: "); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("caused by: "); -#endif + logTrace(errorLog(t), "caused by: "); } - fprintf(errorLog(t), "%s", &byteArrayBody + logTrace(errorLog(t), "%s", &byteArrayBody (t, className(t, objectClass(t, e)), 0)); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA((const CHAR*)&byteArrayBody - (t, className(t, objectClass(t, e)), 0)); -#endif if (throwableMessage(t, e)) { object m = throwableMessage(t, e); THREAD_RUNTIME_ARRAY(t, char, message, stringLength(t, m) + 1); stringChars(t, m, RUNTIME_ARRAY_BODY(message)); - fprintf(errorLog(t), ": %s\n", RUNTIME_ARRAY_BODY(message)); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA(": "); - OutputDebugStringA(RUNTIME_ARRAY_BODY(message)); - OutputDebugStringA("\n"); -#endif + logTrace(errorLog(t), ": %s\n", RUNTIME_ARRAY_BODY(message)); } else { - fprintf(errorLog(t), "\n"); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("\n"); -#endif + logTrace(errorLog(t), "\n"); } object trace = throwableTrace(t, e); @@ -4809,36 +4815,17 @@ printTrace(Thread* t, object exception) int line = t->m->processor->lineNumber (t, traceElementMethod(t, e), traceElementIp(t, e)); - fprintf(errorLog(t), " at %s.%s ", class_, method); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA(" at "); - OutputDebugStringA((const CHAR*)class_); - OutputDebugStringA("."); - OutputDebugStringA((const CHAR*)method); - OutputDebugStringA(" "); -#endif + logTrace(errorLog(t), " at %s.%s ", class_, method); switch (line) { case NativeLine: - fprintf(errorLog(t), "(native)\n"); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("(native)\n"); -#endif + logTrace(errorLog(t), "(native)\n"); break; case UnknownLine: - fprintf(errorLog(t), "(unknown line)\n"); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("(unknown line)\n"); -#endif + logTrace(errorLog(t), "(unknown line)\n"); break; default: - fprintf(errorLog(t), "(line %d)\n", line); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("(line "); - char buf[35]; - OutputDebugStringA(itoa(line, buf, 10)); - OutputDebugStringA(")\n"); -#endif + logTrace(errorLog(t), "(line %d)\n", line); } } } @@ -4848,7 +4835,7 @@ printTrace(Thread* t, object exception) } } - fflush(errorLog(t)); + ::fflush(errorLog(t)); } object From f2d2c9af294654821dbfb6a35261f48190c426c7 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 7 Feb 2013 11:43:39 +0200 Subject: [PATCH 140/378] Fix for windows ::open --- classpath/java-io.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index ba4812a5a4..acc0582feb 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -802,7 +802,11 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, jlong peer = 0; jlong length = 0; #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + #if defined(PLATFORM_WINDOWS) + int fd = ::_wopen(chars, O_RDONLY); + #else int fd = ::open((const char*)chars, O_RDONLY); + #endif releaseChars(e, path, chars); if (fd == -1) { throwNewErrno(e, "java/io/IOException"); From d97fe5304f431fc43ccd0c1bbf62090c362ffeac Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Feb 2013 10:13:59 -0700 Subject: [PATCH 141/378] use THREAD_RUNTIME_ARRAY instead of RUNTIME_ARRAY where appropriate This ensures that if the stack is unwound for an exception we'll still release the memory. --- src/bootimage.cpp | 8 ++++---- src/interpret.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 5ec14b51e6..45dd4e3364 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -342,7 +342,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, unsigned count = s.read2() - 1; if (count) { - RUNTIME_ARRAY(Type, types, count + 2); + THREAD_RUNTIME_ARRAY(t, Type, types, count + 2); types[0] = Type_object; types[1] = Type_intptr_t; @@ -420,7 +420,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object fields = allFields(t, typeMaps, c, &count, &array); PROTECT(t, fields); - RUNTIME_ARRAY(Field, memberFields, count + 1); + THREAD_RUNTIME_ARRAY(t, Field, memberFields, count + 1); unsigned memberIndex; unsigned buildMemberOffset; @@ -454,7 +454,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, const unsigned StaticHeader = 3; - RUNTIME_ARRAY(Field, staticFields, count + StaticHeader); + THREAD_RUNTIME_ARRAY(t, Field, staticFields, count + StaticHeader); init(new (&staticFields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -1334,7 +1334,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp } ++ count; - RUNTIME_ARRAY(Field, fields, count); + THREAD_RUNTIME_ARRAY(t, Field, fields, count); init(new (&fields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); diff --git a/src/interpret.cpp b/src/interpret.cpp index 42183e98f0..4b5b3cd006 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -647,7 +647,7 @@ invokeNative(Thread* t, object method) { THREAD_RESOURCE0(t, popFrame(static_cast(t))); unsigned footprint = methodParameterFootprint(t, method); - RUNTIME_ARRAY(uintptr_t, args, footprint); + THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint); unsigned sp = frameBase(t, t->frame); unsigned argOffset = 0; if ((methodFlags(t, method) & ACC_STATIC) == 0) { @@ -2321,7 +2321,7 @@ interpret3(Thread* t, const int base) object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); PROTECT(t, class_); - RUNTIME_ARRAY(int32_t, counts, dimensions); + THREAD_RUNTIME_ARRAY(t, int32_t, counts, dimensions); for (int i = dimensions - 1; i >= 0; --i) { counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { From 82d4ced1600371fa70c2bb8b26db31e44e8bedf2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 6 Feb 2013 10:04:55 -0700 Subject: [PATCH 142/378] specify UTF-8 encoding to javac This fixes "illegal character" errors when compiling e.g. Misc.java on systems where the default encoding is not UTF-8. --- makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index af5533815f..e5fd4dd16b 100755 --- a/makefile +++ b/makefile @@ -179,7 +179,7 @@ dlltool = dlltool vg = nice valgrind --num-callers=32 --db-attach=yes --freelist-vol=100000000 vg += --leak-check=full --suppressions=valgrind.supp db = gdb --args -javac = "$(JAVA_HOME)/bin/javac" +javac = "$(JAVA_HOME)/bin/javac" -encoding UTF-8 javah = "$(JAVA_HOME)/bin/javah" jar = "$(JAVA_HOME)/bin/jar" strip = strip @@ -433,7 +433,7 @@ ifeq ($(platform),android) lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -llog target-format = elf use-lto = false - + ifeq ($(arch),arm) cflags += -marm -march=$(android-arm-arch) -ftree-vectorize -ffast-math -mfloat-abi=softfp endif From ef11cd1d8da77d83f059c5d34a26f4c6aa23c770 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 6 Feb 2013 11:38:30 -0700 Subject: [PATCH 143/378] rename clean to clean-current, and clean-all back to clean This way, the clean target continues to do what it always did: delete the whole build directory. You can use clean-current to just delete the currently-configured build directory. --- makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/makefile b/makefile index e5fd4dd16b..f7da20fd08 100755 --- a/makefile +++ b/makefile @@ -1246,13 +1246,13 @@ javadoc: -header "Avian v$(version)" \ -bottom "http://oss.readytalk.com/avian" -.PHONY: clean -clean: +.PHONY: clean-current +clean-current: @echo "removing $(build)" rm -rf $(build) -.PHONY: clean-all -clean-all: +.PHONY: clean +clean: @echo "removing build" rm -rf build From 524166046365ded0f192c8593f4cfe880c80f203 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 6 Feb 2013 11:40:06 -0700 Subject: [PATCH 144/378] fix SIGSEGV and off-by-one error in logDebug We must use separate va_start/va_end pairs for each call to vsnprintf on Linux and possibly other platforms in order to avoid a crash. Also, we need to give it room to null terminate the string at the right point. --- src/machine.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 46f331c32d..83b8c88620 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -4769,11 +4769,14 @@ logTrace(FILE* f, const char* fmt, ...) #else const unsigned length = vsnprintf(0, 0, fmt, a); #endif - RUNTIME_ARRAY(char, buffer, length + 1); - vsnprintf(&buffer[0], length, fmt, a); - buffer[length] = 0; va_end(a); + RUNTIME_ARRAY(char, buffer, length + 1); + va_start(a, fmt); + vsnprintf(&buffer[0], length + 1, fmt, a); + va_end(a); + buffer[length] = 0; + ::fprintf(f, "%s", &buffer[0]); #ifdef PLATFORM_WINDOWS ::OutputDebugStringA(&buffer[0]); From b38eecbefa3a55c878d8af7bf82c43c1ce225d0d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 7 Feb 2013 11:35:48 -0700 Subject: [PATCH 145/378] specify O_BINARY when opening files on Windows --- classpath/java-io.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index acc0582feb..f2e9fd3c18 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -803,9 +803,9 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, jlong length = 0; #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #if defined(PLATFORM_WINDOWS) - int fd = ::_wopen(chars, O_RDONLY); + int fd = ::_wopen(chars, O_RDONLY | OPEN_MASK); #else - int fd = ::open((const char*)chars, O_RDONLY); + int fd = ::open((const char*)chars, O_RDONLY | OPEN_MASK); #endif releaseChars(e, path, chars); if (fd == -1) { From 6d4f797b66e217549ed23f4173a3a1e1847d9fc5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 7 Feb 2013 11:39:04 -0700 Subject: [PATCH 146/378] fix handling of non-ascii characters in filenames on Windows --- src/windows.cpp | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/src/windows.cpp b/src/windows.cpp index 98fc8e5d96..e6e189671d 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -803,17 +803,15 @@ class MySystem: public System { virtual Status map(System::Region** region, const char* name) { Status status = 1; + size_t nameLen = strlen(name) * 2; + RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); + MultiByteToWideChar(CP_UTF8, 0, name, -1, wideName, nameLen + 1); #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - HANDLE file = CreateFile(name, FILE_READ_DATA, FILE_SHARE_READ, 0, - OPEN_EXISTING, 0, 0); + HANDLE file = CreateFileW(wideName, FILE_READ_DATA, FILE_SHARE_READ, 0, + OPEN_EXISTING, 0, 0); #else - size_t nameLen = strlen(name); - wchar_t* wideName = new wchar_t[nameLen + 1]; - size_t convertedChars = 0; - mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); HANDLE file = CreateFile2(wideName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0); - delete[] wideName; #endif if (file != INVALID_HANDLE_VALUE) { #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -882,21 +880,21 @@ class MySystem: public System { } virtual FileType stat(const char* name, unsigned* length) { - struct _stat s; - int r = _stat(name, &s); - if (r == 0) { - if (S_ISREG(s.st_mode)) { - *length = s.st_size; - return TypeFile; - } else if (S_ISDIR(s.st_mode)) { - *length = 0; + size_t nameLen = strlen(name) * 2; + RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); + MultiByteToWideChar(CP_UTF8, 0, name, -1, wideName, nameLen + 1); + WIN32_FILE_ATTRIBUTE_DATA data; + if (GetFileAttributesExW + (wideName, GetFileExInfoStandard, &data)) + { + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { return TypeDirectory; } else { - *length = 0; - return TypeUnknown; + *length = (data.nFileSizeHigh * static_cast(MAXDWORD + 1)) + + data.nFileSizeLow; + return TypeFile; } } else { - *length = 0; return TypeDoesNotExist; } } @@ -934,15 +932,14 @@ class MySystem: public System { HMODULE handle; unsigned nameLength = (name ? strlen(name) : 0); if (name) { + size_t nameLen = nameLength * 2; + RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); + MultiByteToWideChar(CP_UTF8, 0, name, -1, wideName, nameLen + 1); + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - handle = LoadLibrary(name); + handle = LoadLibraryW(wideName); #else - size_t nameLen = strlen(name); - wchar_t* wideName = new wchar_t[nameLen + 1]; - size_t convertedChars = 0; - mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); handle = LoadPackagedLibrary(wideName, 0); - delete[] wideName; #endif } else { #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) From f9b3be03019202f56847e41682383d31fcd89b79 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 8 Feb 2013 08:24:06 -0700 Subject: [PATCH 147/378] fix format string in loadLibrary call to snprintf "%*s" means "at least", whereas "%.*s" means at most, and the latter is what I intended. This only became noticable as of 9f22a70, when I added another directory to the library path, which caused loadLibrary to fail to find libraries in either directory. --- src/classpath-common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classpath-common.h b/src/classpath-common.h index 47d11343ac..aff9f8c40c 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -221,7 +221,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1); snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1, - "%*s/%s", token.length, token.s, name); + "%.*s/%s", token.length, token.s, name); lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName)); if (lib) break; From 07e3294937e8792cd25f513606a8a5607afe73e8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 8 Feb 2013 09:34:26 -0700 Subject: [PATCH 148/378] use rpath=$ORIGIN instead of LD_LIBRARY_PATH Hi If libjvm.so is in the same directory as avian-dynamic, then there's no need for LD_LIBRARY_PATH to include that directory, we can just set the rpath in avian-dynamic to $ORIGIN when linking it. Working patch attached. Regards Damjan --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index b3cbd88a57..fe83a35381 100755 --- a/makefile +++ b/makefile @@ -1245,7 +1245,7 @@ ifdef msvc -MANIFESTFILE:$(@).manifest $(mt) -manifest $(@).manifest -outputresource:"$(@);1" else - $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) -o $(@) + $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) -Wl,-rpath=\$$ORIGIN -z origin -o $(@) endif $(strip) $(strip-all) $(@) From 85ce7696ca78c532a33adc657c561c416b5d9e52 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 21 Jan 2013 18:19:55 +0200 Subject: [PATCH 149/378] java.lang.Math.log() and java.lang.Math.tan() --- classpath/java-lang.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 865f3c3fb4..a671a53d1d 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -785,6 +785,12 @@ Java_java_lang_Math_cos(JNIEnv*, jclass, jdouble val) return cos(val); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_tan(JNIEnv*, jclass, jdouble val) +{ + return tan(val); +} + extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val) { @@ -797,6 +803,12 @@ Java_java_lang_Math_pow(JNIEnv*, jclass, jdouble val, jdouble exp) return pow(val, exp); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_log(JNIEnv*, jclass, jdouble val) +{ + return log(val); +} + extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val) { From d6aff87ef967fe4dd43ece7e159aab1508de3e1b Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Mon, 21 Jan 2013 22:43:29 +0100 Subject: [PATCH 150/378] Add java lang math methods --- classpath/java-lang.cpp | 38 +++++++++++++++++++++++++ classpath/java/io/RandomAccessFile.java | 6 ++++ classpath/java/lang/Math.java | 6 ++++ 3 files changed, 50 insertions(+) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index a671a53d1d..6a33a7b7c1 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -791,6 +791,44 @@ Java_java_lang_Math_tan(JNIEnv*, jclass, jdouble val) return tan(val); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_asin(JNIEnv*, jclass, jdouble val) +{ + return asin(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_acos(JNIEnv*, jclass, jdouble val) +{ + return acos(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_atan(JNIEnv*, jclass, jdouble val) +{ + return atan(val); +} + + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_sinh(JNIEnv*, jclass, jdouble val) +{ + return sinh(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_cosh(JNIEnv*, jclass, jdouble val) +{ + return cosh(val); +} + +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_tanh(JNIEnv*, jclass, jdouble val) +{ + return tanh(val); +} + + extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val) { diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index b6e88dd00e..6ed7eeaceb 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -56,6 +56,12 @@ public class RandomAccessFile { this.position = position; } + public int skipBytes(int count) throws IOException { + if (position + count > length()) throw new IOException(); + this.position = position + count; + return count; + } + public void readFully(byte[] buffer, int offset, int length) throws IOException { diff --git a/classpath/java/lang/Math.java b/classpath/java/lang/Math.java index 44eea9db17..5f4933244d 100644 --- a/classpath/java/lang/Math.java +++ b/classpath/java/lang/Math.java @@ -93,6 +93,12 @@ public final class Math { public static native double tan(double v); + public static native double cosh(double v); + + public static native double sinh(double v); + + public static native double tanh(double v); + public static native double acos(double v); public static native double asin(double v); From f1b2b3f78d3e9b2ae48990fb41f65205276a0a20 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 22 Jan 2013 21:10:16 +0200 Subject: [PATCH 151/378] RandomAccessFile --- classpath/java-io.cpp | 153 ++++++------------------ classpath/java/io/RandomAccessFile.java | 73 ++++++++--- 2 files changed, 90 insertions(+), 136 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 86020f57c8..b016c5c17a 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -155,69 +155,9 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length) } } + #ifdef PLATFORM_WINDOWS -class Mapping { - public: - Mapping(uint8_t* start, size_t length, HANDLE mapping, HANDLE file): - start(start), - length(length), - mapping(mapping), - file(file) - { } - - uint8_t* start; - size_t length; - HANDLE mapping; - HANDLE file; -}; - -inline Mapping* -map(JNIEnv* e, string_t path) -{ - Mapping* result = 0; - HANDLE file = CreateFileW(path, FILE_READ_DATA, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, - OPEN_EXISTING, 0, 0); - if (file != INVALID_HANDLE_VALUE) { - unsigned size = GetFileSize(file, 0); - if (size != INVALID_FILE_SIZE) { - HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0); - if (mapping) { - void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); - if (data) { - void* p = allocate(e, sizeof(Mapping)); - if (not e->ExceptionCheck()) { - result = new (p) - Mapping(static_cast(data), size, file, mapping); - } - } - - if (result == 0) { - CloseHandle(mapping); - } - } - } - - if (result == 0) { - CloseHandle(file); - } - } - if (result == 0 and not e->ExceptionCheck()) { - throwNew(e, "java/io/IOException", "%d", GetLastError()); - } - return result; -} - -inline void -unmap(JNIEnv*, Mapping* mapping) -{ - UnmapViewOfFile(mapping->start); - CloseHandle(mapping->mapping); - CloseHandle(mapping->file); - free(mapping); -} - class Directory { public: Directory(): handle(0), findNext(false) { } @@ -250,51 +190,9 @@ class Directory { #else // not PLATFORM_WINDOWS -class Mapping { - public: - Mapping(uint8_t* start, size_t length): - start(start), - length(length) - { } - - uint8_t* start; - size_t length; -}; - -inline Mapping* -map(JNIEnv* e, string_t path) -{ - Mapping* result = 0; - int fd = open(path, O_RDONLY); - if (fd != -1) { - struct stat s; - int r = fstat(fd, &s); - if (r != -1) { - void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (data) { - void* p = allocate(e, sizeof(Mapping)); - if (not e->ExceptionCheck()) { - result = new (p) Mapping(static_cast(data), s.st_size); - } - } - } - close(fd); - } - if (result == 0 and not e->ExceptionCheck()) { - throwNewErrno(e, "java/io/IOException"); - } - return result; -} - -inline void -unmap(JNIEnv*, Mapping* mapping) -{ - munmap(mapping->start, mapping->length); - free(mapping); -} - #endif // not PLATFORM_WINDOWS + } // namespace inline string_t getChars(JNIEnv* e, jstring path) { @@ -785,35 +683,54 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, { string_t chars = getChars(e, path); if (chars) { - Mapping* mapping = map(e, chars); + int fd = ::open((const char*)chars, O_RDONLY); + releaseChars(e, path, chars); + if (fd == -1) { + throwNewErrno(e, "java/io/IOException"); + return; + } + struct ::stat fileStats; + if(::fstat(fd, &fileStats) == -1) { + ::close(fd); + throwNewErrno(e, "java/io/IOException"); + return; + } - jlong peer = reinterpret_cast(mapping); + jlong peer = fd; e->SetLongArrayRegion(result, 0, 1, &peer); - jlong length = (mapping ? mapping->length : 0); + jlong length = fileStats.st_size; e->SetLongArrayRegion(result, 1, 1, &length); - - releaseChars(e, path, chars); } } -extern "C" JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_copy(JNIEnv* e, jclass, jlong peer, +extern "C" JNIEXPORT jint JNICALL +Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, jlong position, jbyteArray buffer, int offset, int length) { + int fd = (int)peer; + if(::lseek(fd, position, SEEK_SET) == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); - - memcpy(dst + offset, - reinterpret_cast(peer)->start + position, - length); - + ssize_t bytesRead = ::read(fd, dst + offset, length); e->ReleasePrimitiveArrayCritical(buffer, dst, 0); + + if(bytesRead == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + return (jint)bytesRead; } extern "C" JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_close(JNIEnv* e, jclass, jlong peer) +Java_java_io_RandomAccessFile_close(JNIEnv*/* e*/, jclass, jlong peer) { - unmap(e, reinterpret_cast(peer)); + int fd = (int)peer; + ::close(fd); } diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index 6ed7eeaceb..18bacb99f3 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -10,6 +10,8 @@ package java.io; +import java.lang.IllegalArgumentException; + public class RandomAccessFile { private long peer; private File file; @@ -61,27 +63,62 @@ public class RandomAccessFile { this.position = position + count; return count; } - - public void readFully(byte[] buffer, int offset, int length) - throws IOException - { - if (peer == 0) throw new IOException(); - - if (length == 0) return; - - if (position + length > this.length) { - if (position + length > length()) throw new EOFException(); - } - - if (offset < 0 || offset + length > buffer.length) + + public int read(byte b[], int off, int len) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(len == 0) + return 0; + if (position + len > this.length) + throw new EOFException(); + if (off < 0 || off + len > b.length) throw new ArrayIndexOutOfBoundsException(); - - copy(peer, position, buffer, offset, length); - - position += length; + int bytesRead = readBytes(peer, position, b, off, len); + position += bytesRead; + return bytesRead; + } + + public int read(byte b[]) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(b.length == 0) + return 0; + if (position + b.length > this.length) + throw new EOFException(); + int bytesRead = readBytes(peer, position, b, 0, b.length); + position += bytesRead; + return bytesRead; } - private static native void copy(long peer, long position, byte[] buffer, + public void readFully(byte b[], int off, int len) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(len == 0) + return; + if (position + len > this.length) + throw new EOFException(); + if (off < 0 || off + len > b.length) + throw new ArrayIndexOutOfBoundsException(); + int n = 0; + do { + int count = readBytes(peer, position, b, off + n, len - n); + if (count < 0) + throw new EOFException(); + n += count; + } while (n < len); + } + + public void readFully(byte b[]) throws IOException { + readFully(b, 0, b.length); + } + + private static native int readBytes(long peer, long position, byte[] buffer, int offset, int length); public void close() throws IOException { From c8ca83836a906eee2aa59c8694dd5e3757cc0555 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Tue, 22 Jan 2013 20:25:37 +0100 Subject: [PATCH 152/378] Fix RAF --- classpath/java/io/RandomAccessFile.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index 18bacb99f3..da9a8356b6 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -108,7 +108,8 @@ public class RandomAccessFile { int n = 0; do { int count = readBytes(peer, position, b, off + n, len - n); - if (count < 0) + position += count; + if (count == 0) throw new EOFException(); n += count; } while (n < len); From 3a42db9f6f59a4b73eae16d6a620d8716b4cbe17 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 24 Jan 2013 00:55:23 +0100 Subject: [PATCH 153/378] Add android platform --- classpath/java-lang.cpp | 2 ++ makefile | 15 +++++++++++++++ src/posix.cpp | 15 +++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 6a33a7b7c1..4cafd5e6cc 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -54,7 +54,9 @@ # include "signal.h" # include "sys/time.h" # include "sys/types.h" +# ifndef __ANDROID__ # include "sys/sysctl.h" +# endif # include "sys/utsname.h" # include "sys/wait.h" diff --git a/makefile b/makefile index fe83a35381..f6c474c0dc 100755 --- a/makefile +++ b/makefile @@ -353,6 +353,21 @@ ifeq ($(platform),freebsd) "-I$(JAVA_HOME)/include/freebsd" -I$(src) -pthread cflags = $(build-cflags) endif +ifeq ($(platform),android) + asm = arm + pointer-size = 4 + no-psabi = -Wno-psabi + toolchain = $(ANDROID_NDK)/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/ + cflags = -std=gnu++0x -I$(ANDROID_NDK)/platforms/android-5/arch-arm/usr/include \ + -I$(toolchain)/lib/gcc/arm-linux-androideabi/4.7/include $(common-cflags) + cflags += -marm $(no-psabi) + + cxx = $(toolchain)/bin/arm-linux-androideabi-g++ + cc = $(toolchain)/bin/arm-linux-androideabi-gcc + ar = $(toolchain)/bin/arm-linux-androideabi-ar + ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib + strip = $(toolchain)/bin/arm-linux-androideabi-strip +endif ifeq ($(platform),darwin) target-format = macho diff --git a/src/posix.cpp b/src/posix.cpp index da575eb8a4..c033956ad5 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -12,10 +12,21 @@ # define __STDC_CONSTANT_MACROS #endif +#include "sys/types.h" #ifdef __APPLE__ # include "CoreFoundation/CoreFoundation.h" # include "sys/ucontext.h" # undef assert +#elif defined __ANDROID__ +# include /* for sigcontext */ +# include /* for stack_t */ +typedef struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + unsigned long uc_sigmask; +} ucontext_t; #else # if defined __FreeBSD__ # include "limits.h" @@ -24,7 +35,7 @@ #endif #include "sys/mman.h" -#include "sys/types.h" + #include "sys/stat.h" #include "sys/time.h" #include "time.h" @@ -37,10 +48,10 @@ #include "stdint.h" #include "dirent.h" #include "sched.h" - #include "arch.h" #include "system.h" + #define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x) using namespace vm; From b1990ba55f4af59a51802ba869dc82427638e97a Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 24 Jan 2013 16:17:52 +0200 Subject: [PATCH 154/378] Android toolchain --- makefile | 41 +++++++++++++++++++++++++++++++++-------- src/arm.h | 4 ++++ src/posix.cpp | 16 ++++++++-------- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/makefile b/makefile index f6c474c0dc..ece9a050c4 100755 --- a/makefile +++ b/makefile @@ -357,13 +357,34 @@ ifeq ($(platform),android) asm = arm pointer-size = 4 no-psabi = -Wno-psabi - toolchain = $(ANDROID_NDK)/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/ - cflags = -std=gnu++0x -I$(ANDROID_NDK)/platforms/android-5/arch-arm/usr/include \ - -I$(toolchain)/lib/gcc/arm-linux-androideabi/4.7/include $(common-cflags) - cflags += -marm $(no-psabi) + use-lto = false + ifeq ($(build-platform),cygwin) + ndk = "$$(cygpath -u "$(ANDROID_NDK)")" + else + ndk = $(ANDROID_NDK) + endif + + build-cflags = $(common-cflags) -I$(src) + ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) + build-system = windows + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + build-lflags = -lz -lpthread + sysroot = "$$(cygpath -w "$(ndk)/platforms/android-5/arch-arm")" + build-cflags += "-I$(JAVA_HOME)/include/win32" + else + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-$(build-arch) + sysroot = $(ndk)/platforms/android-5/arch-arm + build-cflags += "-I$(JAVA_HOME)/include/linux" + endif + toolchain = $(ndk)/toolchains/arm-linux-androideabi-4.7/prebuilt/$(toolchain-host-platform) + cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 -marm $(no-psabi) + lflags = $(common-lflags) -ldl + use-lto = false - cxx = $(toolchain)/bin/arm-linux-androideabi-g++ - cc = $(toolchain)/bin/arm-linux-androideabi-gcc + cxx = $(toolchain)/bin/arm-linux-androideabi-g++ --sysroot="$(sysroot)" + cc = $(toolchain)/bin/arm-linux-androideabi-gcc --sysroot="$(sysroot)" ar = $(toolchain)/bin/arm-linux-androideabi-ar ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib strip = $(toolchain)/bin/arm-linux-androideabi-strip @@ -540,7 +561,9 @@ ifeq ($(mode),fast) else optimization-cflags = -O3 -g3 -DNDEBUG endif - use-lto = true + ifeq ($(use-lto),) + use-lto = true + endif endif ifeq ($(mode),small) ifeq ($(use-clang),true) @@ -548,7 +571,9 @@ ifeq ($(mode),small) else optimization-cflags = -Os -g3 -DNDEBUG endif - use-lto = true + ifeq ($(use-lto),) + use-lto = true + endif endif ifeq ($(use-lto),true) diff --git a/src/arm.h b/src/arm.h index 15299ec762..7e7a4d61dd 100644 --- a/src/arm.h +++ b/src/arm.h @@ -98,6 +98,10 @@ loadMemoryBarrier() memoryBarrier(); } +#if defined(__ANDROID__) +// http://code.google.com/p/android/issues/detail?id=1803 +extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__))); +#endif inline void syncInstructionCache(const void* start, unsigned size) { diff --git a/src/posix.cpp b/src/posix.cpp index c033956ad5..95c4286b60 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -17,16 +17,16 @@ # include "CoreFoundation/CoreFoundation.h" # include "sys/ucontext.h" # undef assert -#elif defined __ANDROID__ +#elif defined(__ANDROID__) # include /* for sigcontext */ # include /* for stack_t */ -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - unsigned long uc_sigmask; -} ucontext_t; + typedef struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + unsigned long uc_sigmask; + } ucontext_t; #else # if defined __FreeBSD__ # include "limits.h" From 1f77d150401fd5fa6aad41b198a55133b84cd995 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 24 Jan 2013 06:39:14 -0800 Subject: [PATCH 155/378] Path fix --- makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index ece9a050c4..5333c7ebb7 100755 --- a/makefile +++ b/makefile @@ -365,26 +365,27 @@ ifeq ($(platform),android) endif build-cflags = $(common-cflags) -I$(src) + build-lflags = -lz -lpthread ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) build-system = windows build-cxx = i686-w64-mingw32-g++ build-cc = i686-w64-mingw32-gcc - build-lflags = -lz -lpthread sysroot = "$$(cygpath -w "$(ndk)/platforms/android-5/arch-arm")" build-cflags += "-I$(JAVA_HOME)/include/win32" else - toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-$(build-arch) + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-* sysroot = $(ndk)/platforms/android-5/arch-arm build-cflags += "-I$(JAVA_HOME)/include/linux" endif toolchain = $(ndk)/toolchains/arm-linux-androideabi-4.7/prebuilt/$(toolchain-host-platform) cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 -marm $(no-psabi) - lflags = $(common-lflags) -ldl + lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -ldl use-lto = false cxx = $(toolchain)/bin/arm-linux-androideabi-g++ --sysroot="$(sysroot)" cc = $(toolchain)/bin/arm-linux-androideabi-gcc --sysroot="$(sysroot)" + as = $(toolchain)/bin/arm-linux-androideabi-as --sysroot="$(sysroot)" ar = $(toolchain)/bin/arm-linux-androideabi-ar ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib strip = $(toolchain)/bin/arm-linux-androideabi-strip From c368a8b74aee3b0a6c84fc1d3c635b34cdc3a241 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Fri, 25 Jan 2013 23:36:13 +0100 Subject: [PATCH 156/378] Fix android makefile --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 5333c7ebb7..5d8aa9f6e6 100755 --- a/makefile +++ b/makefile @@ -365,7 +365,7 @@ ifeq ($(platform),android) endif build-cflags = $(common-cflags) -I$(src) - build-lflags = -lz -lpthread + #build-lflags = -lz -lpthread -ldl ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) build-system = windows From 51e8a00f5879db30176c9953b34a33fa430e24a7 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sat, 26 Jan 2013 20:51:46 +0100 Subject: [PATCH 157/378] Add android redirect to logcat --- classpath/java-io.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index b016c5c17a..1e9acdef76 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -644,6 +644,9 @@ Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path, jboolean app return -1; } } +#ifdef __ANDROID__ +#include +#endif extern "C" JNIEXPORT void JNICALL Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c) @@ -657,13 +660,18 @@ Java_java_io_FileOutputStream_write__I_3BII (JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length) { jbyte* data = static_cast(malloc(length)); + if (data == 0) { throwNew(e, "java/lang/OutOfMemoryError", 0); return; } e->GetByteArrayRegion(b, offset, length, data); - + #ifdef __ANDROID__ + if(fd == 1) { + __android_log_print(ANDROID_LOG_WARN, "net.osmand:native", "%.*s",length, data); + } + #endif if (not e->ExceptionCheck()) { doWrite(e, fd, data, length); } From cc237b94c4222447b0a07c436d5c296373047425 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sat, 26 Jan 2013 21:33:43 +0100 Subject: [PATCH 158/378] Fix proguard warnings Conflicts: TODO.if.merge --- vm.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/vm.pro b/vm.pro index 4cdb1654ee..8d1ab22177 100644 --- a/vm.pro +++ b/vm.pro @@ -71,6 +71,7 @@ -keep public class java.io.IOException -keep public class java.io.FileNotFoundException -keep public class java.net.SocketException +-keep public class java.util.Locale # ClassLoader.getSystemClassloader() depends on the existence of this class: From 2f2cac556c603d13283f38d0fc59fe91b8a21e2d Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 28 Jan 2013 17:20:52 +0200 Subject: [PATCH 159/378] Windows Phone 8 / Windows RT initial support Conflicts: makefile --- classpath/java-io.cpp | 39 +++- classpath/java-lang.cpp | 71 ++++++- makefile | 401 ++++++++++++++++++++++++++++++-------- src/arm.h | 28 ++- src/arm.masm | 77 ++++++++ src/binaryToObject/pe.cpp | 33 ++-- src/bootimage.cpp | 44 +++-- src/common.h | 8 +- src/interpret.cpp | 19 +- src/machine.h | 3 + src/system.h | 6 + src/windows.cpp | 143 +++++++++++++- src/x86.masm | 166 ++++++++++++++++ 13 files changed, 912 insertions(+), 126 deletions(-) create mode 100644 src/arm.masm create mode 100644 src/x86.masm diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 1e9acdef76..db9882e051 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -83,6 +83,16 @@ typedef char char_t; #endif // not PLATFORM_WINDOWS +#ifndef WINAPI_FAMILY +# ifndef WINAPI_PARTITION_DESKTOP +# define WINAPI_PARTITION_DESKTOP 1 +# endif + +# ifndef WINAPI_FAMILY_PARTITION +# define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#endif // WINAPI_FAMILY + inline void* operator new(size_t, void* p) throw() { return p; } typedef const char_t* string_t; @@ -214,6 +224,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) { #ifdef PLATFORM_WINDOWS +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) string_t chars = getChars(e, path); if (chars) { const unsigned BufferSize = MAX_PATH; @@ -228,6 +239,11 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) } return path; +# else + // WinRT has no concept of full paths + throwNewErrno(e, "java/io/IOException"); + return path; +# endif #else jstring result = path; string_t chars = getChars(e, path); @@ -256,11 +272,24 @@ Java_java_io_File_length(JNIEnv* e, jclass, jstring path) LARGE_INTEGER fileSize; string_t chars = getChars(e, path); + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE file = CreateFileW (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + #else + HANDLE file = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + #endif releaseChars(e, path, chars); if (file != INVALID_HANDLE_VALUE) + { + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) GetFileSizeEx(file, &fileSize); + #else + FILE_STANDARD_INFO info; + if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + fileSize = info.EndOfFile; + #endif + } else return 0; CloseHandle(file); return static_cast(fileSize.QuadPart); @@ -496,7 +525,11 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) releaseChars(e, path, chars); Directory* d = new (malloc(sizeof(Directory))) Directory; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data)); + #else + d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, NULL, 0); + #endif if (d->handle == INVALID_HANDLE_VALUE) { d->dispose(); d = 0; @@ -725,7 +758,11 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) ssize_t bytesRead = ::read(fd, dst + offset, length); +#else + auto bytesRead = ::read(fd, dst + offset, length); +#endif e->ReleasePrimitiveArrayCritical(buffer, dst, 0); if(bytesRead == -1) { @@ -737,7 +774,7 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, } extern "C" JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_close(JNIEnv*/* e*/, jclass, jlong peer) +Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer) { int fd = (int)peer; ::close(fd); diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 4cafd5e6cc..0414216194 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -62,6 +62,16 @@ #endif // not PLATFORM_WINDOWS +#ifndef WINAPI_FAMILY +# ifndef WINAPI_PARTITION_DESKTOP +# define WINAPI_PARTITION_DESKTOP 1 +# endif + +# ifndef WINAPI_FAMILY_PARTITION +# define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#endif // WINAPI_FAMILY + namespace { #ifdef PLATFORM_WINDOWS char* getErrorStr(DWORD err){ @@ -70,7 +80,8 @@ namespace { snprintf(errStr, 9, "%d", (int) err); return errStr; - // The better way to do this, if I could figure out how to convert LPTSTR to char* + //TODO: + // The better way to do this, if I could figure out how to convert LPTSTR to char* //char* errStr; //LPTSTR s; //if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -83,6 +94,7 @@ namespace { //return errStr; } +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void makePipe(JNIEnv* e, HANDLE p[2]) { SECURITY_ATTRIBUTES sa; @@ -95,6 +107,7 @@ namespace { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); } } +#endif int descriptor(JNIEnv* e, HANDLE h) { @@ -196,7 +209,7 @@ extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { - +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i){ jstring element = (jstring) e->GetObjectArrayElement(command, i); @@ -267,11 +280,15 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass, e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif } extern "C" JNIEXPORT jint JNICALL Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) DWORD exitCode; WaitForSingleObject(reinterpret_cast(pid), INFINITE); BOOL success = GetExitCodeProcess(reinterpret_cast(pid), &exitCode); @@ -283,14 +300,23 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) CloseHandle(reinterpret_cast(tid)); return exitCode; +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); + return -1; +#endif } extern "C" JNIEXPORT void JNICALL -Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid) { +Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TerminateProcess(reinterpret_cast(pid), 1); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif } Locale getLocale() { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) const char* lang = ""; const char* reg = ""; unsigned langid = GetUserDefaultUILanguage(); @@ -362,8 +388,11 @@ Locale getLocale() { default: lang = "en"; } - Locale locale(lang, reg); - return locale; + return Locale(lang, reg); +#else + //TODO: CultureInfo.CurrentCulture + return Locale("en", "US"); +#endif } #else extern "C" JNIEXPORT void JNICALL @@ -531,8 +560,15 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, } else if (strcmp(chars, "file.separator") == 0) { r = e->NewStringUTF("\\"); } else if (strcmp(chars, "os.name") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) r = e->NewStringUTF("Windows"); +# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + r = e->NewStringUTF("Windows Phone"); +# else + r = e->NewStringUTF("Windows RT"); +# endif } else if (strcmp(chars, "os.version") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) unsigned size = 32; RUNTIME_ARRAY(char, buffer, size); OSVERSIONINFO OSversion; @@ -540,6 +576,10 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, ::GetVersionEx(&OSversion); snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%i.%i", (int)OSversion.dwMajorVersion, (int)OSversion.dwMinorVersion); r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer)); +# else + // Currently there is no alternative on WinRT/WP8 + r = e->NewStringUTF("8.0"); +# endif } else if (strcmp(chars, "os.arch") == 0) { #ifdef ARCH_x86_32 r = e->NewStringUTF("x86"); @@ -551,15 +591,28 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = e->NewStringUTF("arm"); #endif } else if (strcmp(chars, "java.io.tmpdir") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TCHAR buffer[MAX_PATH]; GetTempPath(MAX_PATH, buffer); r = e->NewStringUTF(buffer); +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.Storage.ApplicationData.Current.TemporaryFolder + r = 0; +# endif } else if (strcmp(chars, "user.dir") == 0) { +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) TCHAR buffer[MAX_PATH]; GetCurrentDirectory(MAX_PATH, buffer); r = e->NewStringUTF(buffer); +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.ApplicationModel.Package.Current.InstalledLocation + r = 0; +# endif } else if (strcmp(chars, "user.home") == 0) { # ifdef _MSC_VER +# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) WCHAR buffer[MAX_PATH]; size_t needed; if (_wgetenv_s(&needed, buffer, MAX_PATH, L"USERPROFILE") == 0) { @@ -567,6 +620,11 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, } else { r = 0; } +# else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.Storage.KnownFolders.DocumentsLibrary; + r = 0; +# endif # else LPWSTR home = _wgetenv(L"USERPROFILE"); r = e->NewString(reinterpret_cast(home), lstrlenW(home)); @@ -654,6 +712,9 @@ namespace { #elif defined __APPLE__ # include # define environ (*_NSGetEnviron()) +#elif defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +// WinRT/WP8 does not provide alternative for environment variables +char* environ[] = { 0 }; #else extern char** environ; #endif diff --git a/makefile b/makefile index 5d8aa9f6e6..5ca549e988 100755 --- a/makefile +++ b/makefile @@ -51,7 +51,7 @@ ifeq ($(continuations),true) endif root := $(shell (cd .. && pwd)) -build = build/$(platform)-$(arch)$(options) +build = $(build-prefix)build/$(platform)-$(arch)$(options) classpath-build = $(build)/classpath test-build = $(build)/test src = src @@ -59,6 +59,8 @@ classpath-src = classpath test = test win32 ?= $(root)/win32 win64 ?= $(root)/win64 +winrt ?= $(root)/winrt +wp8 ?= $(root)/wp8 classpath = avian @@ -183,6 +185,18 @@ strip-all = --strip-all rdynamic = -rdynamic +cflags_debug = -O0 -g3 +cflags_debug_fast = -O0 -g3 +cflags_stress = -O0 -g3 +cflags_stress_major = -O0 -g3 +ifeq ($(use-clang),true) + cflags_fast = -O4 -g3 + cflags_small = -Oz -g3 +else + cflags_fast = -O3 -g3 + cflags_small = -Os -g3 +endif + # note that we suppress the non-virtual-dtor warning because we never # use the delete operator, which means we don't need virtual # destructors: @@ -198,7 +212,7 @@ common-cflags = $(warnings) -fno-rtti -fno-exceptions -I$(classpath-src) \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags) -asmflags = $(target-cflags) +asmflags = $(target-cflags) -I$(src) ifneq (,$(filter i386 x86_64,$(arch))) ifeq ($(use-frame-pointer),true) @@ -237,6 +251,18 @@ pointer-size = 8 so-prefix = lib so-suffix = .so +static-prefix = lib +static-suffix = .a + +output = -o $(1) +asm-output = -o $(1) +asm-input = -c $(1) +asm-format = S +as = $(cc) +ld = $(cxx) +build-ld = $(build-cc) + +static = -static shared = -shared no-error = -Wno-error @@ -244,6 +270,8 @@ no-error = -Wno-error openjdk-extra-cflags = -fvisibility=hidden bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) +bootimage-symbols = _binary_bootimage_bin_start:_binary_bootimage_bin_end +codeimage-symbols = _binary_codeimage_bin_start:_binary_codeimage_bin_end developer-dir := $(shell if test -d /Developer; then echo /Developer; \ else echo /Applications/Xcode.app/Contents/Developer; fi) @@ -354,41 +382,68 @@ ifeq ($(platform),freebsd) cflags = $(build-cflags) endif ifeq ($(platform),android) - asm = arm - pointer-size = 4 - no-psabi = -Wno-psabi - use-lto = false - ifeq ($(build-platform),cygwin) + ifeq ($(build-platform),cygwin) ndk = "$$(cygpath -u "$(ANDROID_NDK)")" else ndk = $(ANDROID_NDK) endif + ifeq ($(android-version),) + android-version = 5 + endif + + ifeq ($(android-toolchain),) + android-toolchain = 4.7 + endif + + ifeq ($(arch),arm) + android-toolchain-name = arm-linux-androideabi + android-toolchain-prefix = arm-linux-androideabi- + endif + ifeq ($(arch),i386) + android-toolchain-name = x86 + android-toolchain-prefix = i686-linux-android- + endif + + ifeq ($(android-arm-arch),) + android-arm-arch = armv5 + endif + + options := $(options)-api$(android-version)-$(android-toolchain)-$(android-arm-arch) + build-cflags = $(common-cflags) -I$(src) - #build-lflags = -lz -lpthread -ldl + build-lflags = -lz -lpthread ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) build-system = windows build-cxx = i686-w64-mingw32-g++ build-cc = i686-w64-mingw32-gcc - sysroot = "$$(cygpath -w "$(ndk)/platforms/android-5/arch-arm")" + sysroot = "$$(cygpath -w "$(ndk)/platforms/android-$(android-version)/arch-arm")" build-cflags += "-I$(JAVA_HOME)/include/win32" else toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-* - sysroot = $(ndk)/platforms/android-5/arch-arm + sysroot = $(ndk)/platforms/android-$(android-version)/arch-arm build-cflags += "-I$(JAVA_HOME)/include/linux" + build-lflags += -ldl endif - toolchain = $(ndk)/toolchains/arm-linux-androideabi-4.7/prebuilt/$(toolchain-host-platform) - cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 -marm $(no-psabi) - lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -ldl + toolchain = $(ndk)/toolchains/$(android-toolchain-name)-$(android-toolchain)/prebuilt/$(toolchain-host-platform) + cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 $(no-psabi) + lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -llog + target-format = elf use-lto = false - cxx = $(toolchain)/bin/arm-linux-androideabi-g++ --sysroot="$(sysroot)" - cc = $(toolchain)/bin/arm-linux-androideabi-gcc --sysroot="$(sysroot)" - as = $(toolchain)/bin/arm-linux-androideabi-as --sysroot="$(sysroot)" - ar = $(toolchain)/bin/arm-linux-androideabi-ar - ranlib = $(toolchain)/bin/arm-linux-androideabi-ranlib - strip = $(toolchain)/bin/arm-linux-androideabi-strip + ifeq ($(arch),arm) + cflags += -marm -march=$(android-arm-arch) -ftree-vectorize -ffast-math -mfloat-abi=softfp + endif + ifeq ($(arch),i386) + endif + + cxx = $(toolchain)/bin/$(android-toolchain-prefix)g++ --sysroot="$(sysroot)" + cc = $(toolchain)/bin/$(android-toolchain-prefix)gcc --sysroot="$(sysroot)" + as = $(cxx) + ar = $(toolchain)/bin/$(android-toolchain-prefix)ar + ranlib = $(toolchain)/bin/$(android-toolchain-prefix)ranlib + strip = $(toolchain)/bin/$(android-toolchain-prefix)strip endif ifeq ($(platform),darwin) @@ -475,7 +530,9 @@ ifeq ($(platform),darwin) endif ifeq ($(platform),windows) - target-format = pe + ifeq ($(target-format),) + target-format = pe + endif inc = "$(win32)/include" lib = "$(win32)/lib" @@ -488,7 +545,8 @@ ifeq ($(platform),windows) so-suffix = .dll exe-suffix = .exe - lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mwindows -mconsole + lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mconsole + bootimage-generator-lflags = -static-libstdc++ -static-libgcc cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 ifeq (,$(filter mingw32 cygwin,$(build-platform))) @@ -539,39 +597,197 @@ ifeq ($(platform),windows) embed-loader-o = $(build-embed)/embed-loader.o endif +ifeq ($(platform),wp8) + ifeq ($(shell uname -s | grep -i -c WOW64),1) + programFiles = Program Files (x86) + else + programFiles = Program Files + endif + ifeq ($(MSVS_ROOT),) + # Environment variable MSVS_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0" + MSVS_ROOT = C:\$(programFiles)\Microsoft Visual Studio 11.0 + endif + ifeq ($(MSVC_ROOT),) + # Environment variable MSVC_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0\VC" + MSVC_ROOT = $(MSVS_ROOT)\VC + endif + ifeq ($(WP80_SDK),) + # Environment variable WP8_SDK not found. It should be something like + # "C:\Program Files[ (x86)]\Microsoft Visual Studio 11.0\VC\WPSDK\WP80" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_SDK = C:\$(programFiles)\Microsoft Visual Studio 11.0\VC\WPSDK\WP80 + endif + ifeq ($(WP80_KIT),) + # Environment variable WP8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Phone Kits\8.0" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_KIT = C:\$(programFiles)\Windows Phone Kits\8.0 + endif + ifeq ($(WIN8_KIT),) + # Environment variable WIN8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Kits\8.0" + WIN8_KIT = C:\$(programFiles)\Windows Kits\8.0 + endif + ifeq ($(build-platform),cygwin) + windows-path = cygpath -w + else + windows-path = $(native-path) + endif + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + target-format = pe + ms_cl_compiler = wp8 + use-lto = false + supports_avian_executable = false + process = interpret + ifneq ($(process),compile) + options := -$(process) + endif + bootimage = true + ifeq ($(bootimage),true) + options := $(options)-bootimage + endif + system = windows + build-system = windows + static-prefix = + static-suffix = .lib + so-prefix = + so-suffix = .dll + exe-suffix = .exe + + ifeq ($(arch),arm) + wp8_arch = \x86_arm + vc_arch = \arm + w8kit_arch = arm + deps_arch = ARM + as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" + asmflags = -machine ARM -32 + asm-output = -o $(1) + asm-input = $(1) + machine_type = ARM + bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end + codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end + endif + ifeq ($(arch),i386) + wp8_arch = + vc_arch = + w8kit_arch = x86 + deps_arch = x86 + as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" + asmflags += -nologo + asm-output = $(output) + machine_type = X86 + endif + + PATH := $(shell cygpath -u "$(MSVS_ROOT)\Common7\IDE"):$(shell cygpath -u "$(WP80_SDK)\bin$(wp8_arch)"):$(shell cygpath -u "$(WP80_SDK)\bin"):${PATH} + + build-cflags = $(common-cflags) -I$(src) -I$(inc) -mthreads + build-lflags = -lz -lpthread + + cflags = -nologo \ + -I"$(WP80_SDK)\include" -I"$(WP80_KIT)\Include" -I"$(WP80_KIT)\Include\minwin" -I"$(WP80_KIT)\Include\mincore" \ + -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP \ + -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ + -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" \ + -Fd$(build)/$(name).pdb -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ + -I"$(build)" \ + -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ + -DTARGET_BYTES_PER_WORD=$(pointer-size) + + common-lflags = $(classpath-lflags) + + arflags = -MACHINE:$(machine_type) + lflags = $(common-lflags) -nologo \ + -MACHINE:$(machine_type) \ + -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ + ws2_32.lib \ + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\ThreadEmulation.lib")" + + cc = $(cxx) + asm-format = masm + shared = -dll + ar = "$$(cygpath -u "$(WP80_SDK)\bin\lib.exe")" + arflags += -nologo + ifeq ($(build-platform),cygwin) + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + dlltool = i686-w64-mingw32-dlltool + ranlib = + strip = + endif + output = -Fo$(1) + + cflags_debug = -Od -Zi -MDd + cflags_debug_fast = -Od -Zi -MDd + cflags_stress = -O0 -g3 -MD + cflags_stress_major = -O0 -g3 -MD + cflags_fast = -O2 -Zi -MD + cflags_small = -O1s -Zi -MD + # -GL [whole program optimization] in 'fast' and 'small' breaks compilation for some reason + + ifeq ($(mode),debug) + cflags += + lflags += + endif + ifeq ($(mode),debug-fast) + cflags += -DNDEBUG + lflags += + endif + ifeq ($(mode),stress_major) + cflags += + lflags += + endif + ifeq ($(mode),fast) + cflags += + lflags += + endif + # -LTCG is needed only if -GL is used + ifeq ($(mode),fast) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + ifeq ($(mode),small) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + + strip = : +endif + ifeq ($(mode),debug) - optimization-cflags = -O0 -g3 - converter-cflags += -O0 -g3 + optimization-cflags = $(cflags_debug) + converter-cflags += $(cflags_debug) strip = : endif ifeq ($(mode),debug-fast) - optimization-cflags = -O0 -g3 -DNDEBUG + optimization-cflags = $(cflags_debug_fast) -DNDEBUG strip = : endif ifeq ($(mode),stress) - optimization-cflags = -O0 -g3 -DVM_STRESS + optimization-cflags = $(cflags_stress) -DVM_STRESS strip = : endif ifeq ($(mode),stress-major) - optimization-cflags = -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR + optimization-cflags = $(cflags_stress_major) -DVM_STRESS -DVM_STRESS_MAJOR strip = : endif ifeq ($(mode),fast) - ifeq ($(use-clang),true) - optimization-cflags = -O4 -g3 -DNDEBUG - else - optimization-cflags = -O3 -g3 -DNDEBUG - endif + optimization-cflags = $(cflags_fast) -DNDEBUG ifeq ($(use-lto),) use-lto = true endif endif ifeq ($(mode),small) - ifeq ($(use-clang),true) - optimization-cflags = -Oz -g3 -DNDEBUG - else - optimization-cflags = -Os -g3 -DNDEBUG - endif + optimization-cflags = $(cflags_small) -DNDEBUG ifeq ($(use-lto),) use-lto = true endif @@ -596,6 +812,7 @@ endif cflags += $(optimization-cflags) +ifndef ms_cl_compiler ifneq ($(platform),darwin) ifeq ($(arch),i386) # this is necessary to support __sync_bool_compare_and_swap: @@ -603,16 +820,9 @@ ifeq ($(arch),i386) lflags += -march=i586 endif endif - -output = -o $(1) -as := $(cc) -ld := $(cc) -build-ld := $(build-cc) - -static = -static +endif ifdef msvc - static = no-error = windows-path = $(native-path) windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") @@ -621,6 +831,7 @@ ifdef msvc cc = $(cxx) ld = "$(msvc)/BIN/link.exe" mt = "mt.exe" + manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ @@ -629,7 +840,7 @@ ifdef msvc -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ -DTARGET_BYTES_PER_WORD=$(pointer-size) - ifneq ($(lzma),) + ifneq ($(lzma),) cflags += -I$(shell $(windows-path) "$(lzma)") endif @@ -656,9 +867,11 @@ ifdef msvc strip = : endif +build-cflags += -DAVIAN_HOST_TARGET + c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) -asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x))) +asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.$(asm-format),$(3)/%-asm.o,$(x))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) generated-code = \ @@ -684,7 +897,7 @@ vm-sources = \ $(src)/jnienv.cpp \ $(src)/process.cpp -vm-asm-sources = $(src)/$(asm).S +vm-asm-sources = $(src)/$(asm).$(asm-format) target-asm = $(asm) @@ -702,8 +915,9 @@ ifeq ($(process),compile) $(src)/compiler.cpp \ $(src)/$(target-asm).cpp - vm-asm-sources += $(src)/compile-$(asm).S + vm-asm-sources += $(src)/compile-$(asm).$(asm-format) endif +cflags += -DAVIAN_PROCESS_$(process) vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(build)) vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build)) @@ -835,7 +1049,7 @@ converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) converter = $(build)/binaryToObject/binaryToObject -static-library = $(build)/lib$(name).a +static-library = $(build)/$(static-prefix)$(name)${static-suffix} executable = $(build)/$(name)${exe-suffix} dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) executable-dynamic = $(build)/$(name)-dynamic${exe-suffix} @@ -945,9 +1159,15 @@ test-flags = -Djava.library.path=$(build) -cp $(build)/test test-args = $(test-flags) $(input) .PHONY: build +ifneq ($(supports_avian_executable),false) build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ $(test-extra-dep) $(embed) +else +build: $(static-library) $(dynamic-library) $(lzma-loader) \ + $(lzma-encoder) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(embed) +endif $(test-dep): $(classpath-dep) @@ -992,7 +1212,7 @@ clean: @echo "removing build" rm -rf build -$(build)/compile-x86-asm.o: $(src)/continuations-x86.S +$(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) @@ -1043,7 +1263,7 @@ endef define compile-asm-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(as) -I$(src) $(asmflags) -c $(<) -o $(@) + $(as) $(asmflags) $(call asm-output,$(@)) $(call asm-input,$(<)) endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) @@ -1054,10 +1274,12 @@ $(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) $(test-library): $(test-cpp-objects) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(test-build)/$(name).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);2" + -IMPLIB:$(test-build)/$(name).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif else $(ld) $(^) $(shared) $(lflags) -o $(@) endif @@ -1065,10 +1287,12 @@ endif ifdef embed $(embed): $(embed-objects) $(embed-loader-o) @echo "building $(embed)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(cxx) $(^) $(lflags) $(static) $(call output,$(@)) endif @@ -1086,10 +1310,12 @@ $(embed-loader-o): $(embed-loader) $(converter) $(embed-loader): $(embed-loader-objects) $(static-library) @mkdir -p $(dir $(@)) cd $(dir $(@)) && $(ar) x ../../../$(static-library) -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(dir $(@))/*.o $(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@))) @@ -1109,7 +1335,7 @@ $(build)/%.o: $(lzma)/C/%.c @mkdir -p $(dir $(@)) $(cxx) $(cflags) $(no-error) -c $$($(windows-path) $(<)) $(call output,$(@)) -$(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S +$(vm-asm-objects): $(build)/%-asm.o: $(src)/%.$(asm-format) $(compile-asm-object) $(bootimage-generator-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) @@ -1196,14 +1422,18 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) @echo "creating $(@)" rm -rf $(@) +ifdef ms_cl_compiler + $(ar) $(arflags) $(^) -out:$(@) +else $(ar) cru $(@) $(^) $(ranlib) $(@) +endif -$(bootimage-object) $(codeimage-object): $(bootimage-generator) \ - $(build)/classpath.jar +$(bootimage-object) $(codeimage-object): $(bootimage-generator) + @echo "generating bootimage and codeimage binaries using $(<)" $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ - -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ - -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end + -bootimage-symbols $(bootimage-symbols) \ + -codeimage-symbols $(codeimage-symbols) executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ @@ -1212,10 +1442,12 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(executable): $(executable-objects) @echo "linking $(@)" ifeq ($(platform),windows) -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) $(executable-objects) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(@).def $(executable-objects) $(dlltool) -d $(@).def -e $(@).exp @@ -1229,6 +1461,7 @@ endif $(bootimage-generator): $(bootimage-generator-objects) echo arch=$(arch) platform=$(platform) $(MAKE) mode=$(mode) \ + build-prefix=$(build)/host/ \ arch=$(build-arch) \ target-arch=$(arch) \ platform=$(bootimage-platform) \ @@ -1247,17 +1480,19 @@ $(build-bootimage-generator): \ $(lzma-decode-objects) $(lzma-encode-objects) @echo "linking $(@)" ifeq ($(platform),windows) -ifdef msvc - $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb -IMPLIB:$(@).lib \ - -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" +ifdef ms_cl_compiler + $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ + -IMPLIB:$(@).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(dlltool) -z $(@).def $(^) $(dlltool) -d $(@).def -e $(@).exp - $(ld) $(@).exp $(^) $(lflags) -o $(@) + $(ld) $(@).exp $(^) $(bootimage-generator-lflags) $(lflags) -o $(@) endif else - $(ld) $(^) $(rdynamic) $(lflags) -o $(@) + $(ld) $(^) $(rdynamic) $(bootimage-generator-lflags) $(lflags) -o $(@) endif $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ @@ -1265,10 +1500,12 @@ $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(classpath-libraries) $(javahome-object) $(boot-javahome-object) \ $(lzma-decode-objects) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);2" + -IMPLIB:$(build)/$(name).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif else $(ld) $(^) $(version-script-flag) $(soname-flag) \ $(shared) $(lflags) $(bootimage-lflags) \ @@ -1280,11 +1517,13 @@ endif # Ubuntu 11.10 which may be fixable without disabling LTO. $(executable-dynamic): $(driver-dynamic-objects) $(dynamic-library) @echo "linking $(@)" -ifdef msvc +ifdef ms_cl_compiler $(ld) $(lflags) -LIBPATH:$(build) -DEFAULTLIB:$(name) \ - -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) -out:$(@) \ - -MANIFESTFILE:$(@).manifest - $(mt) -manifest $(@).manifest -outputresource:"$(@);1" + -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) \ + -out:$(@) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif else $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) -Wl,-rpath=\$$ORIGIN -z origin -o $(@) endif diff --git a/src/arm.h b/src/arm.h index 7e7a4d61dd..adfd92b4ad 100644 --- a/src/arm.h +++ b/src/arm.h @@ -71,33 +71,53 @@ namespace vm { inline void trap() { +#ifdef _MSC_VER + __debugbreak(); +#else asm("bkpt"); +#endif } +#ifndef _MSC_VER inline void memoryBarrier() { asm("nop"); } +#endif inline void storeStoreMemoryBarrier() { +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else memoryBarrier(); +#endif } inline void storeLoadMemoryBarrier() { +#ifdef _MSC_VER + MemoryBarrier(); +#else memoryBarrier(); +#endif } inline void loadMemoryBarrier() { +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else memoryBarrier(); +#endif } +#if defined(AVIAN_PROCESS_compile) + #if defined(__ANDROID__) // http://code.google.com/p/android/issues/detail?id=1803 extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__))); @@ -116,6 +136,8 @@ syncInstructionCache(const void* start, unsigned size) #endif } +#endif // AVIAN_PROCESS_compile + #ifndef __APPLE__ typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); # define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) @@ -160,7 +182,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, unsigned vfpIndex = 0; unsigned vfpBackfillIndex UNUSED = 0; - uintptr_t stack[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding + uintptr_t* stack = new uintptr_t[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding unsigned stackIndex = 0; unsigned ai = 0; @@ -250,10 +272,12 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, } unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2); - return vmNativeCall + auto retVal = vmNativeCall (function, stackSize, stack, stackIndex * BytesPerWord, (gprIndex ? gprTable : 0), (vfpIndex ? vfpTable : 0), returnType); + delete[] stack; + return retVal; } } // namespace vm diff --git a/src/arm.masm b/src/arm.masm new file mode 100644 index 0000000000..8fc09eb875 --- /dev/null +++ b/src/arm.masm @@ -0,0 +1,77 @@ + AREA text, CODE, ARM + + EXPORT vmNativeCall [FUNC] +vmNativeCall + ; arguments: + ; r0 -> r4 : function + ; r1 -> r5 : stackTotal + ; r2 : memoryTable + ; r3 : memoryCount + ; [sp, #0] -> r6 : gprTable + + mov ip, sp ; save stack frame + stmfd sp!, {r4-r6, lr} ; save clobbered non-volatile regs + + ; mv args into non-volatile regs + mov r4, r0 + mov r5, r1 + ldr r6, [ip] + + ; setup stack arguments if necessary + sub sp, sp, r5 ; allocate stack + mov ip, sp +loop + tst r3, r3 + ldrne r0, [r2], #4 + strne r0, [ip], #4 + subne r3, r3, #4 + bne loop + + ; setup argument registers if necessary + tst r6, r6 + ldmneia r6, {r0-r3} + + blx r4 ; call function + add sp, sp, r5 ; deallocate stack + + ldmfd sp!, {r4-r6, pc} ; restore non-volatile regs and return + + EXPORT vmJump [FUNC] +vmJump + mov lr, r0 + ldr r0, [sp] + ldr r1, [sp, #4] + mov sp, r2 + mov r8, r3 + bx lr + +CHECKPOINT_THREAD EQU 4 +CHECKPOINT_STACK EQU 24 + + EXPORT vmRun [FUNC] +vmRun + ; r0: function + ; r1: arguments + ; r2: checkpoint + stmfd sp!, {r4-r11, lr} + ; align stack + sub sp, sp, #12 + + str sp, [r2, #CHECKPOINT_STACK] + + mov r12, r0 + ldr r0, [r2, #CHECKPOINT_THREAD] + + blx r12 + + EXPORT vmRun_returnAddress [FUNC] +vmRun_returnAddress + add sp, sp, #12 + ldmfd sp!, {r4-r11, lr} + bx lr + + EXPORT vmTrap [FUNC] +vmTrap + bkpt 3 + + END \ No newline at end of file diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 8d5d5fc444..186e491447 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -17,13 +17,17 @@ namespace { -#define IMAGE_SIZEOF_SHORT_NAME 8 +// --- winnt.h ---- +#define IMAGE_SIZEOF_SHORT_NAME 8 -#define IMAGE_FILE_RELOCS_STRIPPED 1 -#define IMAGE_FILE_LINE_NUMS_STRIPPED 4 -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_32BIT_MACHINE 256 +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) +#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. #define IMAGE_SCN_ALIGN_1BYTES 0x100000 #define IMAGE_SCN_ALIGN_2BYTES 0x200000 @@ -73,6 +77,7 @@ struct IMAGE_SYMBOL { uint8_t StorageClass; uint8_t NumberOfAuxSymbols; } __attribute__((packed)); +// --- winnt.h ---- inline unsigned pad(unsigned n) @@ -82,7 +87,7 @@ pad(unsigned n) using namespace avian::tools; -template +template class WindowsPlatform : public Platform { public: @@ -202,12 +207,15 @@ public: int machine; int machineMask; - if (BytesPerWord == 8) { + if (Architecture == PlatformInfo::x86_64) { machine = IMAGE_FILE_MACHINE_AMD64; machineMask = 0; - } else { // if (BytesPerWord == 8) + } else if (Architecture == PlatformInfo::x86) { machine = IMAGE_FILE_MACHINE_I386; machineMask = IMAGE_FILE_32BIT_MACHINE; + } else if (Architecture == PlatformInfo::Arm) { + machine = IMAGE_FILE_MACHINE_ARMNT; + machineMask = IMAGE_FILE_32BIT_MACHINE; } int sectionMask; @@ -269,10 +277,11 @@ public: } WindowsPlatform(): - Platform(PlatformInfo(PlatformInfo::Pe, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {} + Platform(PlatformInfo(PlatformInfo::Pe, Architecture)) {} }; -WindowsPlatform<4> windows32Platform; -WindowsPlatform<8> windows64Platform; +WindowsPlatform<4, PlatformInfo::x86> windows32Platform; +WindowsPlatform<8, PlatformInfo::x86_64> windows64Platform; +WindowsPlatform<4, PlatformInfo::Arm> windowsRtPlatform; // Windows Phone 8 and Windows RT } // namespace diff --git a/src/bootimage.cpp b/src/bootimage.cpp index f82e73f9f5..ec04196ca0 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -342,7 +342,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, unsigned count = s.read2() - 1; if (count) { - Type types[count + 2]; + Type* types = new Type[count + 2]; types[0] = Type_object; types[1] = Type_intptr_t; @@ -410,6 +410,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, (t, typeMaps, hashMapFind (t, root(t, Machine::PoolMap), c, objectHash, objectEqual), array, objectHash); + + delete[] types; + types = 0; } } @@ -420,7 +423,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object fields = allFields(t, typeMaps, c, &count, &array); PROTECT(t, fields); - Field memberFields[count + 1]; + Field* memberFields = new Field[count + 1]; unsigned memberIndex; unsigned buildMemberOffset; @@ -454,7 +457,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, const unsigned StaticHeader = 3; - Field staticFields[count + StaticHeader]; + Field* staticFields = new Field[count + StaticHeader]; init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -586,6 +589,12 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, hashMapInsert (t, typeMaps, classStaticTable(t, c), array, objectHash); } + + delete[] memberFields; + memberFields = 0; + + delete[] staticFields; + staticFields = 0; } } } @@ -1334,7 +1343,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp } ++ count; - Field fields[count]; + Field* fields = new Field[count]; init(new (fields) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); @@ -1462,6 +1471,9 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp hashMapInsert (t, typeMaps, vm::type(t, static_cast(i)), array, objectHash); + + delete[] fields; + fields = 0; } constants = makeCodeImage @@ -1646,10 +1658,10 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp Platform* platform = Platform::getPlatform(PlatformInfo((PlatformInfo::Format)AVIAN_TARGET_FORMAT, (PlatformInfo::Architecture)AVIAN_TARGET_ARCH)); - // if(!platform) { - // fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); - // return false; - // } + if(!platform) { + fprintf(stderr, "unsupported platform: target-format = %d / target-arch = %d\n", AVIAN_TARGET_FORMAT, AVIAN_TARGET_ARCH); + abort(); + } SymbolInfo bootimageSymbols[] = { SymbolInfo(0, bootimageStart), @@ -1768,7 +1780,7 @@ bool ArgParser::parse(int ac, const char** av) { } bool found = false; for(Arg* arg = first; arg; arg = arg->next) { - if(strcmp(arg->name, &av[i][1]) == 0) { + if(::strcmp(arg->name, &av[i][1]) == 0) { found = true; if (arg->desc == 0) { arg->value = "true"; @@ -1905,20 +1917,26 @@ public: exit(1); } +# if AVIAN_TARGET_FORMAT != AVIAN_FORMAT_PE +# define SYMBOL_PREFIX "_" +# else +# define SYMBOL_PREFIX +# endif + if(!bootimageStart) { - bootimageStart = strdup("_binary_bootimage_bin_start"); + bootimageStart = strdup(SYMBOL_PREFIX"binary_bootimage_bin_start"); } if(!bootimageEnd) { - bootimageEnd = strdup("_binary_bootimage_bin_end"); + bootimageEnd = strdup(SYMBOL_PREFIX"binary_bootimage_bin_end"); } if(!codeimageStart) { - codeimageStart = strdup("_binary_codeimage_bin_start"); + codeimageStart = strdup(SYMBOL_PREFIX"binary_codeimage_bin_start"); } if(!codeimageEnd) { - codeimageEnd = strdup("_binary_codeimage_bin_end"); + codeimageEnd = strdup(SYMBOL_PREFIX"binary_codeimage_bin_end"); } } diff --git a/src/common.h b/src/common.h index adab2f587f..c99f23410e 100644 --- a/src/common.h +++ b/src/common.h @@ -94,7 +94,13 @@ typedef int64_t intptr_t; typedef uint64_t uintptr_t; # define UINT64_C(x) x##L # define ARCH_x86_64 -@ define BYTES_PER_WORD 8 +# define BYTES_PER_WORD 8 +# elif defined _M_ARM_FP +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +# define UINT64_C(x) x##LL +# define ARCH_arm +# define BYTES_PER_WORD 4 # else # error "unsupported architecture" # endif diff --git a/src/interpret.cpp b/src/interpret.cpp index 4a324fd084..9399e96657 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -18,7 +18,7 @@ using namespace vm; -namespace { +namespace local { const unsigned FrameBaseOffset = 0; const unsigned FrameNextOffset = 1; @@ -2321,7 +2321,7 @@ interpret3(Thread* t, const int base) object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); PROTECT(t, class_); - int32_t counts[dimensions]; + int32_t* counts = new int32_t[dimensions]; for (int i = dimensions - 1; i >= 0; --i) { counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { @@ -2338,6 +2338,9 @@ interpret3(Thread* t, const int base) populateMultiArray(t, array, counts, 0, dimensions); pushObject(t, array); + + delete[] counts; + counts = 0; } goto loop; case new_: { @@ -3100,7 +3103,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3124,7 +3127,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3148,7 +3151,7 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); pushArguments(t, this_, spec, indirectObjects, arguments); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object @@ -3174,7 +3177,7 @@ class MyProcessor: public Processor { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); - return ::invoke(t, method); + return local::invoke(t, method); } virtual object getStackTrace(vm::Thread* t, vm::Thread*) { @@ -3254,8 +3257,8 @@ namespace vm { Processor* makeProcessor(System* system, Allocator* allocator, bool) { - return new (allocator->allocate(sizeof(MyProcessor))) - MyProcessor(system, allocator); + return new (allocator->allocate(sizeof(local::MyProcessor))) + local::MyProcessor(system, allocator); } } // namespace vm diff --git a/src/machine.h b/src/machine.h index 2924a13fb7..420a0192cb 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1325,6 +1325,9 @@ checkDaemon(Thread* t); object& root(Thread* t, Machine::Root root); +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) +# define vmRun vmRun_ +#endif extern "C" uint64_t vmRun(uint64_t (*function)(Thread*, uintptr_t*), uintptr_t* arguments, void* checkpoint); diff --git a/src/system.h b/src/system.h index c36aefacd9..14a29c7272 100644 --- a/src/system.h +++ b/src/system.h @@ -97,11 +97,13 @@ class System { virtual void disposeAll() = 0; }; +#if defined(AVIAN_PROCESS_compile) class SignalHandler { public: virtual bool handleSignal(void** ip, void** frame, void** stack, void** thread) = 0; }; +#endif class MonitorResource { public: @@ -121,17 +123,21 @@ class System { virtual bool success(Status) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0; virtual void free(const void* p) = 0; +#if defined(AVIAN_PROCESS_compile) virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0; virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0; +#endif virtual Status attach(Runnable*) = 0; virtual Status start(Runnable*) = 0; virtual Status make(Mutex**) = 0; virtual Status make(Monitor**) = 0; virtual Status make(Local**) = 0; +#if defined(AVIAN_PROCESS_compile) virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleDivideByZero(SignalHandler* handler) = 0; virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor) = 0; +#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0; diff --git a/src/windows.cpp b/src/windows.cpp index 532b66e161..2d8c4c16c4 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -26,6 +26,71 @@ #include "arch.h" #include "system.h" +#if defined(WINAPI_FAMILY) + +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#define WaitForSingleObject(hHandle, dwMilliseconds) \ + WaitForSingleObjectEx((hHandle), (dwMilliseconds), FALSE) + +#define CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) \ + CreateEventEx((lpEventAttributes), (lpName), ((bManualReset)?CREATE_EVENT_MANUAL_RESET:0)|((bInitialState)?CREATE_EVENT_INITIAL_SET:0), EVENT_MODIFY_STATE) + +#define CreateMutex(lpEventAttributes, bInitialOwner, lpName) \ + CreateMutexEx((lpEventAttributes), (lpName), (bInitialOwner)?CREATE_MUTEX_INITIAL_OWNER:0, MUTEX_MODIFY_STATE) + +#include "thread-emulation.h" + +#endif + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) +// Headers in Windows Phone 8 DevKit contain severe error, so let's define needed functions on our own +extern "C" +{ +WINBASEAPI +_Ret_maybenull_ +HANDLE +WINAPI +CreateFileMappingFromApp( + _In_ HANDLE hFile, + _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, + _In_ ULONG PageProtection, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name + ); + +WINBASEAPI +_Ret_maybenull_ __out_data_source(FILE) +PVOID +WINAPI +MapViewOfFileFromApp( + _In_ HANDLE hFileMappingObject, + _In_ ULONG DesiredAccess, + _In_ ULONG64 FileOffset, + _In_ SIZE_T NumberOfBytesToMap + ); + +WINBASEAPI +BOOL +WINAPI +UnmapViewOfFile( + _In_ LPCVOID lpBaseAddress + ); +} +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + +#else + +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif + +#endif + #define ACQUIRE(s, x) MutexResource MAKE_NAME(mutexResource_) (s, x) using namespace vm; @@ -49,16 +114,20 @@ class MutexResource { HANDLE m; }; +#if defined(AVIAN_PROCESS_compile) const unsigned SegFaultIndex = 0; const unsigned DivideByZeroIndex = 1; const unsigned HandlerCount = 2; +#endif class MySystem; MySystem* system; +#if defined(AVIAN_PROCESS_compile) LONG CALLBACK handleException(LPEXCEPTION_POINTERS e); +#endif DWORD WINAPI run(void* r) @@ -559,18 +628,22 @@ class MySystem: public System { }; MySystem(const char* crashDumpDirectory): +#if defined(AVIAN_PROCESS_compile) oldHandler(0), +#endif crashDumpDirectory(crashDumpDirectory) { expect(this, system == 0); system = this; +#if defined(AVIAN_PROCESS_compile) memset(handlers, 0, sizeof(handlers)); +#endif mutex = CreateMutex(0, false, 0); assert(this, mutex); } - +#if defined(AVIAN_PROCESS_compile) bool findHandler() { for (unsigned i = 0; i < HandlerCount; ++i) { if (handlers[i]) return true; @@ -578,6 +651,7 @@ class MySystem: public System { return false; } + //TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx int registerHandler(System::SignalHandler* handler, int index) { if (handler) { handlers[index] = handler; @@ -609,7 +683,7 @@ class MySystem: public System { return 1; } } - +#endif virtual void* tryAllocate(unsigned sizeInBytes) { return malloc(sizeInBytes); } @@ -618,6 +692,7 @@ class MySystem: public System { if (p) ::free(const_cast(p)); } + #if defined(AVIAN_PROCESS_compile) virtual void* tryAllocateExecutable(unsigned sizeInBytes) { return VirtualAlloc (0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); @@ -627,6 +702,7 @@ class MySystem: public System { int r UNUSED = VirtualFree(const_cast(p), 0, MEM_RELEASE); assert(this, r); } + #endif virtual bool success(Status s) { return s == 0; @@ -666,6 +742,7 @@ class MySystem: public System { return 0; } +#if defined(AVIAN_PROCESS_compile) virtual Status handleSegFault(SignalHandler* handler) { return registerHandler(handler, SegFaultIndex); } @@ -710,6 +787,7 @@ class MySystem: public System { return (success ? 0 : 1); } +#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) @@ -719,15 +797,39 @@ class MySystem: public System { virtual Status map(System::Region** region, const char* name) { Status status = 1; - +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE file = CreateFile(name, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); +#else + size_t nameLen = strlen(name); + wchar_t* wideName = new wchar_t[nameLen + 1]; + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); + HANDLE file = CreateFile2(wideName, GENERIC_READ, FILE_SHARE_READ, + OPEN_EXISTING, 0); + delete[] wideName; +#endif if (file != INVALID_HANDLE_VALUE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) unsigned size = GetFileSize(file, 0); +#else + FILE_STANDARD_INFO info; + unsigned size = INVALID_FILE_SIZE; + if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + size = info.EndOfFile.QuadPart; +#endif if (size != INVALID_FILE_SIZE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0); +#else + HANDLE mapping = CreateFileMappingFromApp(file, 0, PAGE_READONLY, size, 0); +#endif if (mapping) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); +#else + void* data = MapViewOfFileFromApp(mapping, FILE_MAP_READ, 0, 0); +#endif if (data) { *region = new (allocate(this, sizeof(Region))) Region(this, static_cast(data), size, file, mapping); @@ -757,7 +859,12 @@ class MySystem: public System { memcpy(RUNTIME_ARRAY_BODY(buffer) + length, "\\*", 3); Directory* d = new (allocate(this, sizeof(Directory))) Directory(this); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) d->handle = FindFirstFile(RUNTIME_ARRAY_BODY(buffer), &(d->data)); +#else + d->handle = FindFirstFileEx(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, 0, 0); +#endif if (d->handle == INVALID_HANDLE_VALUE) { d->dispose(); } else { @@ -797,6 +904,7 @@ class MySystem: public System { } virtual const char* toAbsolutePath(Allocator* allocator, const char* name) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) if (strncmp(name, "//", 2) == 0 or strncmp(name, "\\\\", 2) == 0 or strncmp(name + 1, ":/", 2) == 0 @@ -808,6 +916,11 @@ class MySystem: public System { GetCurrentDirectory(MAX_PATH, buffer); return append(allocator, buffer, "\\", name); } +#else + //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ + //Windows.ApplicationModel.Package.Current.InstalledLocation + return name; +#endif } virtual Status load(System::Library** lib, @@ -816,9 +929,23 @@ class MySystem: public System { HMODULE handle; unsigned nameLength = (name ? strlen(name) : 0); if (name) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) handle = LoadLibrary(name); +#else + size_t nameLen = strlen(name); + wchar_t* wideName = new wchar_t[nameLen + 1]; + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, wideName, nameLen + 1, name, nameLen); + handle = LoadPackagedLibrary(wideName, 0); + delete[] wideName; +#endif } else { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) handle = GetModuleHandle(0); +#else + // Most of WinRT/WP8 applications can not host native object files inside main executable + assert(this, false); +#endif } if (handle) { @@ -866,7 +993,11 @@ class MySystem: public System { } virtual void yield() { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) SwitchToThread(); +#else + YieldProcessor(); +#endif } virtual void exit(int code) { @@ -886,11 +1017,15 @@ class MySystem: public System { } HANDLE mutex; +#if defined(AVIAN_PROCESS_compile) SignalHandler* handlers[HandlerCount]; LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; +#endif const char* crashDumpDirectory; }; +#if defined(AVIAN_PROCESS_compile) + #pragma pack(push,4) struct MINIDUMP_EXCEPTION_INFORMATION { DWORD thread; @@ -1005,6 +1140,8 @@ handleException(LPEXCEPTION_POINTERS e) return EXCEPTION_CONTINUE_SEARCH; } +#endif + } // namespace namespace vm { diff --git a/src/x86.masm b/src/x86.masm new file mode 100644 index 0000000000..715669f8c1 --- /dev/null +++ b/src/x86.masm @@ -0,0 +1,166 @@ +comment # + Copyright (c) 2008-2011, 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. +# + +.586 +.MODEL FLAT, C + +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +CHECKPOINT_THREAD equ 4 +CHECKPOINT_STACK equ 24 +CHECKPOINT_BASE equ 28 + +_TEXT SEGMENT + +public C detectFeature +detectFeature: + push ebp + mov ebp,esp + push edx + push ecx + push ebx + push esi + push edi + mov esi,ds:dword ptr[12+ebp] + mov edi,ds:dword ptr[8+ebp] + mov eax,1 + cpuid + and edx,esi + and ecx,edi + or ecx,edx + test ecx,ecx + je LNOSSE + mov eax,1 + jmp LSSEEND + +LNOSSE: + mov eax,0 + +LSSEEND: + pop edi + pop esi + pop ebx + pop ecx + pop edx + mov esp,ebp + pop ebp + ret + +public C vmNativeCall +vmNativeCall: + push ebp + mov ebp,esp + mov ecx,ds:dword ptr[16+ebp] + sub esp,ecx + mov ecx,0 + jmp Ltest + +Lloop: + mov eax,ecx + mov edx,ecx + add edx,esp + add eax,ds:dword ptr[12+ebp] + mov eax,ds:dword ptr[eax] + mov ds:dword ptr[edx],eax + add ecx,4 + +Ltest: + cmp ecx,ds:dword ptr[16+ebp] + jb Lloop + call dword ptr[8+ebp] + mov ecx,ds:dword ptr[20+ebp] + +Lvoid: + cmp ecx,offset VOID_TYPE + jne Lint64 + jmp Lexit + +Lint64: + cmp ecx,offset INT64_TYPE + jne Lfloat + jmp Lexit + +Lfloat: + cmp ecx,offset FLOAT_TYPE + jne Ldouble + fstp ds:dword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + jmp Lexit + +Ldouble: + cmp ecx,offset DOUBLE_TYPE + jne Lexit + fstp ds:dword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + mov edx,ds:dword ptr[12+ebp] + +Lexit: + mov esp,ebp + pop ebp + ret + +public C vmJump +vmJump: + mov esi,ds:dword ptr[4+esp] + mov ebp,ds:dword ptr[8+esp] + mov ebx,ds:dword ptr[16+esp] + mov eax,ds:dword ptr[20+esp] + mov edx,ds:dword ptr[24+esp] + mov esp,ds:dword ptr[12+esp] + jmp esi + +VMRUN_FRAME_SIZE equ 24 + +public C vmRun_ +vmRun_: + ; 8(%ebp): function + ; 12(%ebp): arguments + ; 16(%ebp): checkpoint + push ebp + mov ebp,esp + sub esp,offset VMRUN_FRAME_SIZE + + mov ds:dword ptr[8+esp],ebx + mov ds:dword ptr[12+esp],esi + mov ds:dword ptr[16+esp],edi + + mov eax,ds:dword ptr[12+ebp] + mov ds:dword ptr[4+esp],eax + + mov ecx,ds:dword ptr[16+ebp] + mov eax,ds:dword ptr[CHECKPOINT_THREAD+ecx] + mov ds:dword ptr[0+esp],eax + + mov ds:dword ptr[CHECKPOINT_STACK+ecx],esp + + call dword ptr[8+ebp] + +public C vmRun_returnAddress +vmRun_returnAddress: + + mov ebx,ds:dword ptr[8+esp] + mov esi,ds:dword ptr[12+esp] + mov edi,ds:dword ptr[16+esp] + + add esp,offset VMRUN_FRAME_SIZE + pop ebp + ret + +_TEXT ENDS +END \ No newline at end of file From 1b43caf8155758fee761b4ee7b127797d5e97cdc Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 28 Jan 2013 19:15:29 +0200 Subject: [PATCH 160/378] Makefile fix --- makefile | 16 ++++++++++------ src/arm.h | 4 ++-- src/system.h | 6 +++--- src/windows.cpp | 18 +++++++++--------- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/makefile b/makefile index 5ca549e988..074095eff6 100755 --- a/makefile +++ b/makefile @@ -51,7 +51,8 @@ ifeq ($(continuations),true) endif root := $(shell (cd .. && pwd)) -build = $(build-prefix)build/$(platform)-$(arch)$(options) +build = build/$(platform)-$(arch)$(options) +host-build-root = $(build)/host classpath-build = $(build)/classpath test-build = $(build)/test src = src @@ -135,7 +136,7 @@ ifneq ($(openjdk),) javahome = "$$($(native-path) "$(openjdk)/jre")" endif - classpath = openjdk + classpath = openjdk boot-classpath := "$(boot-classpath)$(path-separator)$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" build-javahome = $(openjdk)/jre endif @@ -640,7 +641,7 @@ ifeq ($(platform),wp8) ms_cl_compiler = wp8 use-lto = false supports_avian_executable = false - process = interpret + process = compile ifneq ($(process),compile) options := -$(process) endif @@ -918,6 +919,9 @@ ifeq ($(process),compile) vm-asm-sources += $(src)/compile-$(asm).$(asm-format) endif cflags += -DAVIAN_PROCESS_$(process) +ifdef aot_only + cflags += -DAVIAN_AOT_ONLY +endif vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(build)) vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build)) @@ -1430,7 +1434,7 @@ else endif $(bootimage-object) $(codeimage-object): $(bootimage-generator) - @echo "generating bootimage and codeimage binaries using $(<)" + @echo "generating bootimage and codeimage binaries from $(classpath-build) using $(<)" $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ -bootimage-symbols $(bootimage-symbols) \ -codeimage-symbols $(codeimage-symbols) @@ -1459,9 +1463,9 @@ endif $(strip) $(strip-all) $(@) $(bootimage-generator): $(bootimage-generator-objects) - echo arch=$(arch) platform=$(platform) + echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform) $(MAKE) mode=$(mode) \ - build-prefix=$(build)/host/ \ + build=$(host-build-root) \ arch=$(build-arch) \ target-arch=$(arch) \ platform=$(bootimage-platform) \ diff --git a/src/arm.h b/src/arm.h index adfd92b4ad..302355c453 100644 --- a/src/arm.h +++ b/src/arm.h @@ -116,7 +116,7 @@ loadMemoryBarrier() #endif } -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) #if defined(__ANDROID__) // http://code.google.com/p/android/issues/detail?id=1803 @@ -136,7 +136,7 @@ syncInstructionCache(const void* start, unsigned size) #endif } -#endif // AVIAN_PROCESS_compile +#endif // AVIAN_AOT_ONLY #ifndef __APPLE__ typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); diff --git a/src/system.h b/src/system.h index 14a29c7272..ee80d2a7cb 100644 --- a/src/system.h +++ b/src/system.h @@ -97,7 +97,7 @@ class System { virtual void disposeAll() = 0; }; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) class SignalHandler { public: virtual bool handleSignal(void** ip, void** frame, void** stack, @@ -123,7 +123,7 @@ class System { virtual bool success(Status) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0; virtual void free(const void* p) = 0; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0; virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0; #endif @@ -132,7 +132,7 @@ class System { virtual Status make(Mutex**) = 0; virtual Status make(Monitor**) = 0; virtual Status make(Local**) = 0; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleDivideByZero(SignalHandler* handler) = 0; virtual Status visit(Thread* thread, Thread* target, diff --git a/src/windows.cpp b/src/windows.cpp index 2d8c4c16c4..f6b9627254 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -114,7 +114,7 @@ class MutexResource { HANDLE m; }; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) const unsigned SegFaultIndex = 0; const unsigned DivideByZeroIndex = 1; @@ -124,7 +124,7 @@ const unsigned HandlerCount = 2; class MySystem; MySystem* system; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) LONG CALLBACK handleException(LPEXCEPTION_POINTERS e); #endif @@ -628,7 +628,7 @@ class MySystem: public System { }; MySystem(const char* crashDumpDirectory): -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) oldHandler(0), #endif crashDumpDirectory(crashDumpDirectory) @@ -636,14 +636,14 @@ class MySystem: public System { expect(this, system == 0); system = this; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) memset(handlers, 0, sizeof(handlers)); #endif mutex = CreateMutex(0, false, 0); assert(this, mutex); } -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) bool findHandler() { for (unsigned i = 0; i < HandlerCount; ++i) { if (handlers[i]) return true; @@ -692,7 +692,7 @@ class MySystem: public System { if (p) ::free(const_cast(p)); } - #if defined(AVIAN_PROCESS_compile) + #if !defined(AVIAN_AOT_ONLY) virtual void* tryAllocateExecutable(unsigned sizeInBytes) { return VirtualAlloc (0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); @@ -742,7 +742,7 @@ class MySystem: public System { return 0; } -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) { return registerHandler(handler, SegFaultIndex); } @@ -1017,14 +1017,14 @@ class MySystem: public System { } HANDLE mutex; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) SignalHandler* handlers[HandlerCount]; LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; #endif const char* crashDumpDirectory; }; -#if defined(AVIAN_PROCESS_compile) +#if !defined(AVIAN_AOT_ONLY) #pragma pack(push,4) struct MINIDUMP_EXCEPTION_INFORMATION { From 4d03650544f2d6bbc7879c6697e594639d7b94ed Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 28 Jan 2013 20:51:35 +0200 Subject: [PATCH 161/378] Replaced TODO comments with messages ; More correct AVIAN_AOT_ONLY usage --- classpath/java-lang.cpp | 15 +++++------ makefile | 1 + src/arm.cpp | 26 ++++++++++--------- src/arm.masm | 12 +++++++++ src/compile.cpp | 7 +++++- src/system.h | 4 --- src/windows.cpp | 55 ++++++++++++++++++++++------------------- src/x86.masm | 2 ++ 8 files changed, 72 insertions(+), 50 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 0414216194..9d2562e265 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -80,8 +80,8 @@ namespace { snprintf(errStr, 9, "%d", (int) err); return errStr; - //TODO: - // The better way to do this, if I could figure out how to convert LPTSTR to char* + #pragma message("TODO") + // The better way to do this, if I could figure out how to convert LPTSTR to char* //char* errStr; //LPTSTR s; //if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -390,7 +390,7 @@ Locale getLocale() { return Locale(lang, reg); #else - //TODO: CultureInfo.CurrentCulture + #pragma message("TODO: CultureInfo.CurrentCulture") return Locale("en", "US"); #endif } @@ -596,8 +596,7 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetTempPath(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.Storage.ApplicationData.Current.TemporaryFolder + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.ApplicationData.Current.TemporaryFolder") r = 0; # endif } else if (strcmp(chars, "user.dir") == 0) { @@ -606,8 +605,7 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetCurrentDirectory(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.ApplicationModel.Package.Current.InstalledLocation + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") r = 0; # endif } else if (strcmp(chars, "user.home") == 0) { @@ -621,8 +619,7 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = 0; } # else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.Storage.KnownFolders.DocumentsLibrary; + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.KnownFolders.DocumentsLibrary") r = 0; # endif # else diff --git a/makefile b/makefile index 074095eff6..ddaa378425 100755 --- a/makefile +++ b/makefile @@ -642,6 +642,7 @@ ifeq ($(platform),wp8) use-lto = false supports_avian_executable = false process = compile + aot_only = true ifneq ($(process),compile) options := -$(process) endif diff --git a/src/arm.cpp b/src/arm.cpp index ae657e30d5..1d4dbc8dd1 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -18,7 +18,7 @@ using namespace vm; -namespace { +namespace local { namespace isa { // SYSTEM REGISTERS @@ -252,7 +252,7 @@ class MyBlock: public Assembler::Block { this->start = start; this->next = static_cast(next); - ::resolve(this); + local::resolve(this); return start + size + padding(this, size); } @@ -2150,7 +2150,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentFootprint(unsigned footprint) { - return ::argumentFootprint(footprint); + return local::argumentFootprint(footprint); } virtual bool argumentAlignment() { @@ -2239,7 +2239,7 @@ class MyArchitecture: public Assembler::Architecture { unsigned targetParameterFootprint, void** ip, void** stack) { - ::nextFrame(&con, static_cast(start), size, footprint, link, + local::nextFrame(&con, static_cast(start), size, footprint, link, mostRecent, targetParameterFootprint, ip, stack); } @@ -2550,11 +2550,12 @@ class MyAssembler: public Assembler { } virtual void pushFrame(unsigned argumentCount, ...) { - struct { + struct Argument { unsigned size; OperandType type; Operand* operand; - } arguments[argumentCount]; + }; + Argument* arguments = new Argument[argumentCount]; va_list a; va_start(a, argumentCount); unsigned footprint = 0; @@ -2589,6 +2590,9 @@ class MyAssembler: public Assembler { offset += ceiling(arguments[i].size, TargetBytesPerWord); } } + + delete[] arguments; + arguments = 0; } virtual void allocateFrame(unsigned footprint) { @@ -2798,7 +2802,7 @@ class MyAssembler: public Assembler { bool jump = needJump(b); if (jump) { write4 - (dst + dstOffset, ::b((poolSize + TargetBytesPerWord - 8) >> 2)); + (dst + dstOffset, isa::b((poolSize + TargetBytesPerWord - 8) >> 2)); } dstOffset += poolSize + (jump ? TargetBytesPerWord : 0); @@ -2832,7 +2836,7 @@ class MyAssembler: public Assembler { } virtual Promise* offset(bool forTrace) { - return ::offset(&con, forTrace); + return local::offset(&con, forTrace); } virtual Block* endBlock(bool startNew) { @@ -2903,15 +2907,15 @@ namespace vm { Assembler::Architecture* makeArchitecture(System* system, bool) { - return new (allocate(system, sizeof(MyArchitecture))) MyArchitecture(system); + return new (allocate(system, sizeof(local::MyArchitecture))) local::MyArchitecture(system); } Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new(zone) MyAssembler(system, allocator, zone, - static_cast(architecture)); + return new(zone) local::MyAssembler(system, allocator, zone, + static_cast(architecture)); } } // namespace vm diff --git a/src/arm.masm b/src/arm.masm index 8fc09eb875..2af5048ec7 100644 --- a/src/arm.masm +++ b/src/arm.masm @@ -1,3 +1,15 @@ +; Copyright (c) 2008-2011, 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. +; +; ORIGIN: https://github.com/gkvas/avian/tree/wince + AREA text, CODE, ARM EXPORT vmNativeCall [FUNC] diff --git a/src/compile.cpp b/src/compile.cpp index 6989d6446d..7fa51817c7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -7389,8 +7389,9 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) { trap(); } - +#if !defined(AVIAN_AOT_ONLY) syncInstructionCache(start, codeSize); +#endif } void @@ -9152,7 +9153,9 @@ class MyProcessor: public Processor { virtual void dispose() { if (codeAllocator.base) { +#if !defined(AVIAN_AOT_ONLY) s->freeExecutable(codeAllocator.base, codeAllocator.capacity); +#endif } compilationHandlers->dispose(allocator); @@ -9313,11 +9316,13 @@ class MyProcessor: public Processor { } virtual void boot(Thread* t, BootImage* image, uint8_t* code) { +#if !defined(AVIAN_AOT_ONLY) if (codeAllocator.base == 0) { codeAllocator.base = static_cast (s->tryAllocateExecutable(ExecutableAreaSizeInBytes)); codeAllocator.capacity = ExecutableAreaSizeInBytes; } +#endif if (image and code) { local::boot(static_cast(t), image, code); diff --git a/src/system.h b/src/system.h index ee80d2a7cb..ef69317f0b 100644 --- a/src/system.h +++ b/src/system.h @@ -97,13 +97,11 @@ class System { virtual void disposeAll() = 0; }; -#if !defined(AVIAN_AOT_ONLY) class SignalHandler { public: virtual bool handleSignal(void** ip, void** frame, void** stack, void** thread) = 0; }; -#endif class MonitorResource { public: @@ -132,12 +130,10 @@ class System { virtual Status make(Mutex**) = 0; virtual Status make(Monitor**) = 0; virtual Status make(Local**) = 0; -#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleDivideByZero(SignalHandler* handler) = 0; virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor) = 0; -#endif virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0; diff --git a/src/windows.cpp b/src/windows.cpp index f6b9627254..8c7512eab1 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -114,17 +114,15 @@ class MutexResource { HANDLE m; }; -#if !defined(AVIAN_AOT_ONLY) const unsigned SegFaultIndex = 0; const unsigned DivideByZeroIndex = 1; const unsigned HandlerCount = 2; -#endif class MySystem; MySystem* system; -#if !defined(AVIAN_AOT_ONLY) +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) LONG CALLBACK handleException(LPEXCEPTION_POINTERS e); #endif @@ -628,7 +626,7 @@ class MySystem: public System { }; MySystem(const char* crashDumpDirectory): -#if !defined(AVIAN_AOT_ONLY) +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) oldHandler(0), #endif crashDumpDirectory(crashDumpDirectory) @@ -636,14 +634,12 @@ class MySystem: public System { expect(this, system == 0); system = this; -#if !defined(AVIAN_AOT_ONLY) memset(handlers, 0, sizeof(handlers)); -#endif mutex = CreateMutex(0, false, 0); assert(this, mutex); } -#if !defined(AVIAN_AOT_ONLY) + bool findHandler() { for (unsigned i = 0; i < HandlerCount; ++i) { if (handlers[i]) return true; @@ -651,31 +647,38 @@ class MySystem: public System { return false; } - //TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx int registerHandler(System::SignalHandler* handler, int index) { if (handler) { handlers[index] = handler; - + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) if (oldHandler == 0) { -#ifdef ARCH_x86_32 +# ifdef ARCH_x86_32 oldHandler = SetUnhandledExceptionFilter(handleException); -#elif defined ARCH_x86_64 +# elif defined ARCH_x86_64 AddVectoredExceptionHandler(1, handleException); oldHandler = reinterpret_cast(1); -#endif +# endif } +#else + #pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") +#endif return 0; } else if (handlers[index]) { handlers[index] = 0; if (not findHandler()) { -#ifdef ARCH_x86_32 +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# ifdef ARCH_x86_32 SetUnhandledExceptionFilter(oldHandler); oldHandler = 0; -#elif defined ARCH_x86_64 +# elif defined ARCH_x86_64 // do nothing, handlers are never "unregistered" anyway -#endif +# endif +#else + #pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") +#endif } return 0; @@ -683,7 +686,7 @@ class MySystem: public System { return 1; } } -#endif + virtual void* tryAllocate(unsigned sizeInBytes) { return malloc(sizeInBytes); } @@ -742,7 +745,6 @@ class MySystem: public System { return 0; } -#if !defined(AVIAN_AOT_ONLY) virtual Status handleSegFault(SignalHandler* handler) { return registerHandler(handler, SegFaultIndex); } @@ -754,6 +756,7 @@ class MySystem: public System { virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget, ThreadVisitor* visitor) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) assert(this, st != sTarget); Thread* target = static_cast(sTarget); @@ -769,15 +772,15 @@ class MySystem: public System { rv = GetThreadContext(target->thread, &context); if (rv) { -#ifdef ARCH_x86_32 +# ifdef ARCH_x86_32 visitor->visit(reinterpret_cast(context.Eip), reinterpret_cast(context.Ebp), reinterpret_cast(context.Esp)); -#elif defined ARCH_x86_64 +# elif defined ARCH_x86_64 visitor->visit(reinterpret_cast(context.Rip), reinterpret_cast(context.Rbp), reinterpret_cast(context.Rsp)); -#endif +# endif success = true; } @@ -786,8 +789,11 @@ class MySystem: public System { } return (success ? 0 : 1); - } +#else + #pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") + return false; #endif + } virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) @@ -917,8 +923,7 @@ class MySystem: public System { return append(allocator, buffer, "\\", name); } #else - //TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ - //Windows.ApplicationModel.Package.Current.InstalledLocation + #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") return name; #endif } @@ -1017,14 +1022,14 @@ class MySystem: public System { } HANDLE mutex; -#if !defined(AVIAN_AOT_ONLY) SignalHandler* handlers[HandlerCount]; +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; #endif const char* crashDumpDirectory; }; -#if !defined(AVIAN_AOT_ONLY) +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #pragma pack(push,4) struct MINIDUMP_EXCEPTION_INFORMATION { diff --git a/src/x86.masm b/src/x86.masm index 715669f8c1..640637d5af 100644 --- a/src/x86.masm +++ b/src/x86.masm @@ -8,6 +8,8 @@ comment # There is NO WARRANTY for this software. See license.txt for details. + + ORIGIN: https://github.com/gkvas/avian/tree/wince # .586 From dca12d3cd0e44716ab0c0a27d1b086840eafd679 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 09:40:29 +0200 Subject: [PATCH 162/378] WinRT/WP8 process=compile --- makefile | 2 + src/arm.masm | 10 +- src/compile-arm.masm | 252 +++++++++++++++++++++++++++++++++++++++++++ src/compile-x86.masm | 173 +++++++++++++++++++++++++++++ 4 files changed, 432 insertions(+), 5 deletions(-) create mode 100644 src/compile-arm.masm create mode 100644 src/compile-x86.masm diff --git a/makefile b/makefile index ddaa378425..29465173c1 100755 --- a/makefile +++ b/makefile @@ -1217,7 +1217,9 @@ clean: @echo "removing build" rm -rf build +ifeq ($(continuations),true) $(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) +endif gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) diff --git a/src/arm.masm b/src/arm.masm index 2af5048ec7..e7bd2d864c 100644 --- a/src/arm.masm +++ b/src/arm.masm @@ -12,7 +12,7 @@ AREA text, CODE, ARM - EXPORT vmNativeCall [FUNC] + EXPORT vmNativeCall vmNativeCall ; arguments: ; r0 -> r4 : function @@ -48,7 +48,7 @@ loop ldmfd sp!, {r4-r6, pc} ; restore non-volatile regs and return - EXPORT vmJump [FUNC] + EXPORT vmJump vmJump mov lr, r0 ldr r0, [sp] @@ -60,7 +60,7 @@ vmJump CHECKPOINT_THREAD EQU 4 CHECKPOINT_STACK EQU 24 - EXPORT vmRun [FUNC] + EXPORT vmRun vmRun ; r0: function ; r1: arguments @@ -76,13 +76,13 @@ vmRun blx r12 - EXPORT vmRun_returnAddress [FUNC] + EXPORT vmRun_returnAddress vmRun_returnAddress add sp, sp, #12 ldmfd sp!, {r4-r11, lr} bx lr - EXPORT vmTrap [FUNC] + EXPORT vmTrap vmTrap bkpt 3 diff --git a/src/compile-arm.masm b/src/compile-arm.masm new file mode 100644 index 0000000000..a9c1e59cef --- /dev/null +++ b/src/compile-arm.masm @@ -0,0 +1,252 @@ +; Copyright (c) 2008-2011, 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. +; +; ORIGIN: https://github.com/gkvas/avian/tree/wince + +; types.inc +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +; target-fields.inc +;TARGET_BYTES_PER_WORD = 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + AREA text, CODE, ARM + +BYTES_PER_WORD equ 4 + +CONTINUATION_NEXT equ 4 +CONTINUATION_ADDRESS equ 16 +CONTINUATION_RETURN_ADDRESS_OFFSET equ 20 +CONTINUATION_FRAME_POINTER_OFFSET equ 24 +CONTINUATION_LENGTH equ 28 +CONTINUATION_BODY equ 32 + + EXPORT vmInvoke +vmInvoke + + ; arguments + ; r0 : thread + ; r1 : function + ; r2 : arguments + ; r3 : argumentFootprint + ; [sp, #0] : frameSize (not used) + ; [sp, #4] : returnType + + + ; save all non-volatile registers + stmfd sp!, {r4-r11, lr} + + ; save return type + ldr r4, [sp, #4] + str r4, [sp, #-4]! + + str sp, [r0, #TARGET_THREAD_SCRATCH] + + ; align stack, if necessary + eor r4, sp, r3 + tst r4, #4 + subne sp, sp, #4 + + ; copy arguments into place + sub sp, sp, r3 + mov r4, #0 + b vmInvoke_argumentTest + +vmInvoke_argumentLoop + ldr r5, [r2, r4] + str r5, [sp, r4] + add r4, r4, #BYTES_PER_WORD + +vmInvoke_argumentTest + cmp r4, r3 + blt vmInvoke_argumentLoop + + ; we use r8 to hold the thread pointer, by convention + mov r8, r0 + + ; load and call function address + blx r1 + + EXPORT vmInvoke_returnAddress +vmInvoke_returnAddress + ; restore stack pointer + ldr sp, [r8, #TARGET_THREAD_SCRATCH] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov r5, #0 + str r5, [r8, #TARGET_THREAD_STACK] + + EXPORT vmInvoke_safeStack +vmInvoke_safeStack + +;if AVIAN_CONTINUATIONS +; ; call the next continuation, if any +; ldr r5,[r8,#TARGET_THREAD_CONTINUATION] +; cmp r5,#0 +; beq vmInvoke_exit) +; +; ldr r6,[r5,#CONTINUATION_LENGTH] +; lsl r6,r6,#2 +; neg r7,r6 +; add r7,r7,#-80 +; mov r4,sp +; str r4,[sp,r7]! +; +; add r7,r5,#CONTINUATION_BODY +; +; mov r11,#0 +; b vmInvoke_continuationTest +; +;vmInvoke_continuationLoop +; ldr r9,[r7,r11] +; str r9,[sp,r11] +; add r11,r11,#4 +; +;vmInvoke_continuationTest +; cmp r11,r6 +; ble vmInvoke_continuationLoop) +; +; ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET] +; ldr r10,vmInvoke_returnAddress_word +; ldr r11,vmInvoke_getAddress_word +;vmInvoke_getAddress +; add r11,pc,r11 +; ldr r11,[r11,r10] +; str r11,[sp,r7] +; +; ldr r7,[r5,#CONTINUATION_NEXT] +; str r7,[r8,#TARGET_THREAD_CONTINUATION] +; +; ; call the continuation unless we're handling an exception +; ldr r7,[r8,#TARGET_THREAD_EXCEPTION] +; cmp r7,#0 +; bne vmInvoke_handleException) +; ldr r7,[r5,#CONTINUATION_ADDRESS] +; bx r7 +; +;vmInvoke_handleException +; ; we're handling an exception - call the exception handler instead +; mov r11,#0 +; str r11,[r8,#TARGET_THREAD_EXCEPTION] +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] +; ldr r9,[sp] +; neg r11,r11 +; str r9,[sp,r11]! +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONOFFSET] +; str r7,[sp,r11] +; +; ldr r7,[r8,#TARGET_THREAD_EXCEPTIONHANDLER] +; bx r7 +; +;vmInvoke_exit +;endif ; AVIAN_CONTINUATIONS + + mov ip, #0 + str ip, [r8, #TARGET_THREAD_STACK] + + ; restore return type + ldr ip, [sp], #4 + + ; restore callee-saved registers + ldmfd sp!, {r4-r11, lr} + +vmInvoke_return + bx lr + + EXPORT vmJumpAndInvoke +vmJumpAndInvoke +;if :DEF:AVIAN_CONTINUATIONS +; ; r0: thread +; ; r1: address +; ; r2: stack +; ; r3: argumentFootprint +; ; [sp,#0]: arguments +; ; [sp,#4]: frameSize +; +; ldr r5,[sp,#0] +; ldr r6,[sp,#4] +; +; ; allocate new frame, adding room for callee-saved registers, plus +; ; 4 bytes of padding since the calculation of frameSize assumes 4 +; ; bytes have already been allocated to save the return address, +; ; which is not true in this case +; sub r2,r2,r6 +; sub r2,r2,#84 +; +; mov r8,r0 +; +; ; copy arguments into place +; mov r6,#0 +; b vmJumpAndInvoke_argumentTest +; +;vmJumpAndInvoke_argumentLoop +; ldr r12,[r5,r6] +; str r12,[r2,r6] +; add r6,r6,#4 +; +;vmJumpAndInvoke_argumentTest +; cmp r6,r3 +; ble vmJumpAndInvoke_argumentLoop +; +; ; the arguments have been copied, so we can set the real stack +; ; pointer now +; mov sp,r2 +; +; ; set return address to vmInvoke_returnAddress +; ldr r10,vmInvoke_returnAddress_word) +; ldr r11,vmJumpAndInvoke_getAddress_word) +;vmJumpAndInvoke_getAddress +; add r11,pc,r11 +; ldr lr,[r11,r10] +; +; bx r1 +; +;vmInvoke_returnAddress_word +; .word GLOBAL(vmInvoke_returnAddress)(GOT) +;vmInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmInvoke_getAddress)+8) +;vmJumpAndInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmJumpAndInvoke_getAddress)+8) +; +;else ; not AVIAN_CONTINUATIONS + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + bkpt 0 +;endif ; not AVIAN_CONTINUATIONS + + END \ No newline at end of file diff --git a/src/compile-x86.masm b/src/compile-x86.masm new file mode 100644 index 0000000000..f07d799faf --- /dev/null +++ b/src/compile-x86.masm @@ -0,0 +1,173 @@ +comment # + Copyright (c) 2008-2011, 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. + + ORIGIN: https://github.com/gkvas/avian/tree/wince +# + +.586 +.MODEL FLAT, C + +comment # types.h # +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +comment # target-fields.h # +ifdef TARGET_BYTES_PER_WORD + if TARGET_BYTES_PER_WORD eq 8 + +TARGET_THREAD_EXCEPTION equ 80 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2256 +TARGET_THREAD_EXCEPTIONOFFSET equ 2264 +TARGET_THREAD_EXCEPTIONHANDLER equ 2272 + +TARGET_THREAD_IP equ 2216 +TARGET_THREAD_STACK equ 2224 +TARGET_THREAD_NEWSTACK equ 2232 +TARGET_THREAD_SCRATCH equ 2240 +TARGET_THREAD_CONTINUATION equ 2248 +TARGET_THREAD_TAILADDRESS equ 2280 +TARGET_THREAD_VIRTUALCALLTARGET equ 2288 +TARGET_THREAD_VIRTUALCALLINDEX equ 2296 +TARGET_THREAD_HEAPIMAGE equ 2304 +TARGET_THREAD_CODEIMAGE equ 2312 +TARGET_THREAD_THUNKTABLE equ 2320 +TARGET_THREAD_STACKLIMIT equ 2368 + + elseif TARGET_BYTES_PER_WORD eq 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + else + error + endif +else + error +endif + +ifdef AVIAN_USE_FRAME_POINTER + ALIGNMENT_ADJUSTMENT equ 0 +else + ALIGNMENT_ADJUSTMENT equ 12 +endif + +CALLEE_SAVED_REGISTER_FOOTPRINT equ 16 + ALIGNMENT_ADJUSTMENT + +_TEXT SEGMENT + +public C vmInvoke +vmInvoke: + push ebp + mov ebp,esp + + ; 8(%ebp): thread + ; 12(%ebp): function + ; 16(%ebp): arguments + ; 20(%ebp): argumentFootprint + ; 24(%ebp): frameSize + ; 28(%ebp): returnType + + ; allocate stack space for callee-saved registers + sub esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + ; remember this stack position, since we won't be able to rely on + ; %rbp being restored when the call returns + mov eax,ds:dword ptr[8+ebp] + mov ds:dword ptr[TARGET_THREAD_SCRATCH+eax],esp + + mov ds:dword ptr[0+esp],ebx + mov ds:dword ptr[4+esp],esi + mov ds:dword ptr[8+esp],edi + + ; allocate stack space for arguments + sub esp,ds:dword ptr[24+ebp] + + ; we use ebx to hold the thread pointer, by convention + mov ebx,eax + + ; copy arguments into place + mov ecx,0 + mov edx,ds:dword ptr[16+ebp] + jmp LvmInvoke_argumentTest + +LvmInvoke_argumentLoop: + mov eax,ds:dword ptr[edx+ecx*1] + mov ds:dword ptr[esp+ecx*1],eax + add ecx,4 + +LvmInvoke_argumentTest: + cmp ecx,ds:dword ptr[20+ebp] + jb LvmInvoke_argumentLoop + + ; call function + call dword ptr[12+ebp] + +public vmInvoke_returnAddress +vmInvoke_returnAddress: + ; restore stack pointer + mov esp,ds:dword ptr[TARGET_THREAD_SCRATCH+ebx] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov ds:dword ptr[TARGET_THREAD_STACK+ebx],0 + +public vmInvoke_safeStack +vmInvoke_safeStack: + + ; restore callee-saved registers + mov ebx,ds:dword ptr[0+esp] + mov esi,ds:dword ptr[4+esp] + mov edi,ds:dword ptr[8+esp] + + add esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + mov ecx,ds:dword ptr[28+esp] + + pop ebp + ret + +LgetPC: + mov esi,ds:dword ptr[esp] + ret + +public vmJumpAndInvoke +vmJumpAndInvoke: + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + int 3 + +_TEXT ENDS + +END From 2d11e7ccd40fa27194d3e97b81b8ada9269ac730 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Mon, 28 Jan 2013 01:46:15 +0100 Subject: [PATCH 163/378] Add last modified to file --- classpath/java-io.cpp | 22 ++++++++++++++++++++++ classpath/java/io/File.java | 7 +++++++ 2 files changed, 29 insertions(+) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index db9882e051..c12ee64368 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -541,6 +541,28 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) } } +extern "C" JNIEXPORT jlong JNICALL +Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + #ifdef PLATFORM_WINDOWS + # error "Implementation of last modified :)" + #else + struct stat st; + if (stat(chars, &st)) { + return 0; + } else { + return (static_cast(st.st_mtim.tv_sec) * 1000) + + (static_cast(st.st_mtim.tv_nsec) / (1000*1000)); + } + + #endif + } else { + return 0; + } +} + extern "C" JNIEXPORT jstring JNICALL Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle) { diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index b66aa03ff9..8eceed4b71 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -294,12 +294,19 @@ public class File implements Serializable { } } + public long lastModified() { + return lastModified(path); + } private static native long openDir(String path); + private static native long lastModified(String path); + private static native String readDir(long handle); private static native long closeDir(long handle); + + private static class Pair { public final String value; public final Pair next; From 5e0b073eff7466e5535f006ef61c1b8fae952f70 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 12:44:55 +0200 Subject: [PATCH 164/378] Fix library overwriting ; proper assembler flags --- makefile | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/makefile b/makefile index 29465173c1..d21344e852 100755 --- a/makefile +++ b/makefile @@ -666,7 +666,7 @@ ifeq ($(platform),wp8) as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" - asmflags = -machine ARM -32 + asmflags = $(target-cflags) -machine ARM -32 asm-output = -o $(1) asm-input = $(1) machine_type = ARM @@ -678,6 +678,7 @@ ifeq ($(platform),wp8) vc_arch = w8kit_arch = x86 deps_arch = x86 + asmflags = $(target-cflags) -safeseh as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" @@ -705,12 +706,31 @@ ifeq ($(platform),wp8) common-lflags = $(classpath-lflags) + ifeq ($(mode),debug) + build-type = Debug + endif + ifeq ($(mode),debug-fast) + build-type = Debug + endif + ifeq ($(mode),stress_major) + build-type = Release + endif + ifeq ($(mode),fast) + build-type = Release + endif + ifeq ($(mode),fast) + build-type = Release + endif + ifeq ($(mode),small) + build-type = Release + endif + arflags = -MACHINE:$(machine_type) lflags = $(common-lflags) -nologo \ -MACHINE:$(machine_type) \ -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ ws2_32.lib \ - "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\ThreadEmulation.lib")" + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" cc = $(cxx) asm-format = masm @@ -1508,8 +1528,8 @@ $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(lzma-decode-objects) @echo "linking $(@)" ifdef ms_cl_compiler - $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(build)/$(name).lib $(manifest-flags) + $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(subst .dll,.pdb,$(@)) \ + -IMPLIB:$(subst .dll,.lib,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" endif From acdd297fb2662f6a86fa202076ca4033b4b0ee73 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 14:21:02 +0200 Subject: [PATCH 165/378] Fixes to WP8/WinRT support --- classpath/java-io.cpp | 3 ++- makefile | 4 +--- src/bootimage.cpp | 14 ++++---------- src/windows.cpp | 4 ++-- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index c12ee64368..3860e67ecd 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -547,7 +547,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) string_t chars = getChars(e, path); if (chars) { #ifdef PLATFORM_WINDOWS - # error "Implementation of last modified :)" + # pragma message("Implementation of last modified") + return 0; #else struct stat st; if (stat(chars, &st)) { diff --git a/makefile b/makefile index d21344e852..5044abd4d5 100755 --- a/makefile +++ b/makefile @@ -618,7 +618,7 @@ ifeq ($(platform),wp8) # Environment variable WP8_SDK not found. It should be something like # "C:\Program Files[ (x86)]\Microsoft Visual Studio 11.0\VC\WPSDK\WP80" # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 - WP80_SDK = C:\$(programFiles)\Microsoft Visual Studio 11.0\VC\WPSDK\WP80 + WP80_SDK = $(MSVS_ROOT)\VC\WPSDK\WP80 endif ifeq ($(WP80_KIT),) # Environment variable WP8_KIT not found. It should be something like @@ -670,8 +670,6 @@ ifeq ($(platform),wp8) asm-output = -o $(1) asm-input = $(1) machine_type = ARM - bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end - codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end endif ifeq ($(arch),i386) wp8_arch = diff --git a/src/bootimage.cpp b/src/bootimage.cpp index ec04196ca0..5b725f5058 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1917,26 +1917,20 @@ public: exit(1); } -# if AVIAN_TARGET_FORMAT != AVIAN_FORMAT_PE -# define SYMBOL_PREFIX "_" -# else -# define SYMBOL_PREFIX -# endif - if(!bootimageStart) { - bootimageStart = strdup(SYMBOL_PREFIX"binary_bootimage_bin_start"); + bootimageStart = strdup("_binary_bootimage_bin_start"); } if(!bootimageEnd) { - bootimageEnd = strdup(SYMBOL_PREFIX"binary_bootimage_bin_end"); + bootimageEnd = strdup("_binary_bootimage_bin_end"); } if(!codeimageStart) { - codeimageStart = strdup(SYMBOL_PREFIX"binary_codeimage_bin_start"); + codeimageStart = strdup("_binary_codeimage_bin_start"); } if(!codeimageEnd) { - codeimageEnd = strdup(SYMBOL_PREFIX"binary_codeimage_bin_end"); + codeimageEnd = strdup("_binary_codeimage_bin_end"); } } diff --git a/src/windows.cpp b/src/windows.cpp index 8c7512eab1..d0b5228368 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -34,10 +34,10 @@ WaitForSingleObjectEx((hHandle), (dwMilliseconds), FALSE) #define CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) \ - CreateEventEx((lpEventAttributes), (lpName), ((bManualReset)?CREATE_EVENT_MANUAL_RESET:0)|((bInitialState)?CREATE_EVENT_INITIAL_SET:0), EVENT_MODIFY_STATE) + CreateEventEx((lpEventAttributes), (lpName), ((bManualReset)?CREATE_EVENT_MANUAL_RESET:0)|((bInitialState)?CREATE_EVENT_INITIAL_SET:0), EVENT_ALL_ACCESS) #define CreateMutex(lpEventAttributes, bInitialOwner, lpName) \ - CreateMutexEx((lpEventAttributes), (lpName), (bInitialOwner)?CREATE_MUTEX_INITIAL_OWNER:0, MUTEX_MODIFY_STATE) + CreateMutexEx((lpEventAttributes), (lpName), (bInitialOwner)?CREATE_MUTEX_INITIAL_OWNER:0, MUTEX_ALL_ACCESS) #include "thread-emulation.h" From 4228f69a0d3b9bf8adaeba995ef98d8398a8ff4a Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 29 Jan 2013 19:23:22 +0200 Subject: [PATCH 166/378] Additional AOT_ONLY ifdef --- src/compile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compile.cpp b/src/compile.cpp index 7fa51817c7..d0cf31cfec 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -9339,11 +9339,15 @@ class MyProcessor: public Processor { root(t, MethodTreeSentinal)); } +#ifdef AVIAN_AOT_ONLY + thunks = bootThunks; +#else local::compileThunks(static_cast(t), &codeAllocator); if (not (image and code)) { bootThunks = thunks; } +#endif segFaultHandler.m = t->m; expect(t, t->m->system->success From aaa60aebff56a545f2fc08db751773f1efdedb2f Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Wed, 30 Jan 2013 07:31:02 +0200 Subject: [PATCH 167/378] Makefile changes, added additional compiler flags --- makefile | 110 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/makefile b/makefile index 5044abd4d5..5db25dbe11 100755 --- a/makefile +++ b/makefile @@ -50,6 +50,7 @@ ifeq ($(continuations),true) options := $(options)-continuations endif +aot-only = false root := $(shell (cd .. && pwd)) build = build/$(platform)-$(arch)$(options) host-build-root = $(build)/host @@ -539,7 +540,6 @@ ifeq ($(platform),windows) lib = "$(win32)/lib" embed-prefix = c:/avian-embedded - system = windows so-prefix = @@ -642,7 +642,7 @@ ifeq ($(platform),wp8) use-lto = false supports_avian_executable = false process = compile - aot_only = true + aot-only = true ifneq ($(process),compile) options := -$(process) endif @@ -676,11 +676,16 @@ ifeq ($(platform),wp8) vc_arch = w8kit_arch = x86 deps_arch = x86 - asmflags = $(target-cflags) -safeseh + asmflags = $(target-cflags) -safeseh -nologo -Gd as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" - asmflags += -nologo + ifeq ($(mode),debug) + asmflags += -Zd + endif + ifeq ($(mode),debug-fast) + asmflags += -Zd + endif asm-output = $(output) machine_type = X86 endif @@ -700,7 +705,8 @@ ifeq ($(platform),wp8) -Fd$(build)/$(name).pdb -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ - -DTARGET_BYTES_PER_WORD=$(pointer-size) + -DTARGET_BYTES_PER_WORD=$(pointer-size) \ + -Gd common-lflags = $(classpath-lflags) @@ -783,6 +789,52 @@ ifeq ($(platform),wp8) strip = : endif +ifdef msvc + no-error = + windows-path = $(native-path) + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + zlib := $(shell $(windows-path) "$(win32)/msvc") + ms_cl_compiler = regular + cxx = "$(msvc)/BIN/cl.exe" + cc = $(cxx) + ld = "$(msvc)/BIN/link.exe" + mt = "mt.exe" + manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest + cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ + -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I$(classpath-src) \ + -I"$(build)" \ + -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ + -DTARGET_BYTES_PER_WORD=$(pointer-size) + + ifneq ($(lzma),) + cflags += -I$(shell $(windows-path) "$(lzma)") + endif + + shared = -dll + lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ + -DEFAULTLIB:zlib -DEFAULTLIB:user32 -MANIFEST -debug + output = -Fo$(1) + + ifeq ($(mode),debug) + cflags += -Od -Zi -MDd + endif + ifeq ($(mode),debug-fast) + cflags += -Od -Zi -DNDEBUG + endif + ifeq ($(mode),fast) + cflags += -O2 -GL -Zi -DNDEBUG + lflags += -LTCG + endif + ifeq ($(mode),small) + cflags += -O1s -Zi -GL -DNDEBUG + lflags += -LTCG + endif + + strip = : +endif + ifeq ($(mode),debug) optimization-cflags = $(cflags_debug) converter-cflags += $(cflags_debug) @@ -842,51 +894,6 @@ endif endif endif -ifdef msvc - no-error = - windows-path = $(native-path) - windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") - zlib := $(shell $(windows-path) "$(win32)/msvc") - cxx = "$(msvc)/BIN/cl.exe" - cc = $(cxx) - ld = "$(msvc)/BIN/link.exe" - mt = "mt.exe" - manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest - cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ - -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ - -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ - -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I$(classpath-src) \ - -I"$(build)" \ - -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ - -DTARGET_BYTES_PER_WORD=$(pointer-size) - - ifneq ($(lzma),) - cflags += -I$(shell $(windows-path) "$(lzma)") - endif - - shared = -dll - lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ - -DEFAULTLIB:zlib -DEFAULTLIB:user32 -MANIFEST -debug - output = -Fo$(1) - - ifeq ($(mode),debug) - cflags += -Od -Zi -MDd - endif - ifeq ($(mode),debug-fast) - cflags += -Od -Zi -DNDEBUG - endif - ifeq ($(mode),fast) - cflags += -O2 -GL -Zi -DNDEBUG - lflags += -LTCG - endif - ifeq ($(mode),small) - cflags += -O1s -Zi -GL -DNDEBUG - lflags += -LTCG - endif - - strip = : -endif - build-cflags += -DAVIAN_HOST_TARGET c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) @@ -938,7 +945,7 @@ ifeq ($(process),compile) vm-asm-sources += $(src)/compile-$(asm).$(asm-format) endif cflags += -DAVIAN_PROCESS_$(process) -ifdef aot_only +ifeq ($(aot-only),true) cflags += -DAVIAN_AOT_ONLY endif @@ -1488,6 +1495,7 @@ $(bootimage-generator): $(bootimage-generator-objects) $(MAKE) mode=$(mode) \ build=$(host-build-root) \ arch=$(build-arch) \ + aot-only=false \ target-arch=$(arch) \ platform=$(bootimage-platform) \ target-format=$(target-format) \ From d51db00136422d464ece304a489f5b3cbbe5ea47 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Wed, 30 Jan 2013 10:42:05 +0200 Subject: [PATCH 168/378] Allow output of exceptions to debugger. Generate WinMD file --- makefile | 46 ++++++++++++++++++++++++++++------------------ src/machine.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/makefile b/makefile index 5db25dbe11..7c5123f33f 100755 --- a/makefile +++ b/makefile @@ -593,8 +593,8 @@ ifeq ($(platform),windows) shared += -Wl,--add-stdcall-alias endif - embed = $(build-embed)/embed.exe - embed-loader = $(build-embed-loader)/embed-loader.exe + embed = $(build-embed)/embed$(exe-suffix) + embed-loader = $(build-embed-loader)/embed-loader$(exe-suffix) embed-loader-o = $(build-embed)/embed-loader.o endif @@ -657,6 +657,7 @@ ifeq ($(platform),wp8) so-prefix = so-suffix = .dll exe-suffix = .exe + manifest-flags = -MANIFEST:NO ifeq ($(arch),arm) wp8_arch = \x86_arm @@ -696,8 +697,9 @@ ifeq ($(platform),wp8) build-lflags = -lz -lpthread cflags = -nologo \ + -AI"$(WP80_KIT)\Windows Metadata" \ -I"$(WP80_SDK)\include" -I"$(WP80_KIT)\Include" -I"$(WP80_KIT)\Include\minwin" -I"$(WP80_KIT)\Include\mincore" \ - -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP \ + -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP -D_USRDLL -D_WINDLL \ -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ @@ -735,6 +737,11 @@ ifeq ($(platform),wp8) -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ ws2_32.lib \ "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" + lflags += -NXCOMPAT -DYNAMICBASE -SUBSYSTEM:CONSOLE -TLBID:1 + lflags += -NODEFAULTLIB:"ole32.lib" WindowsPhoneCore.lib + lflags += -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) + #lflags += -WINMD:NO + #lflags += -APPCONTAINER cc = $(cxx) asm-format = masm @@ -750,6 +757,7 @@ ifeq ($(platform),wp8) endif output = -Fo$(1) + #TODO: -MT or -ZW? cflags_debug = -Od -Zi -MDd cflags_debug_fast = -Od -Zi -MDd cflags_stress = -O0 -g3 -MD @@ -1079,10 +1087,10 @@ converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) converter = $(build)/binaryToObject/binaryToObject -static-library = $(build)/$(static-prefix)$(name)${static-suffix} +static-library = $(build)/$(static-prefix)$(name)$(static-suffix) executable = $(build)/$(name)${exe-suffix} dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) -executable-dynamic = $(build)/$(name)-dynamic${exe-suffix} +executable-dynamic = $(build)/$(name)-dynamic$(exe-suffix) ifneq ($(classpath),avian) # Assembler, ConstantPool, and Stream are not technically needed for a @@ -1307,7 +1315,8 @@ $(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) $(test-library): $(test-cpp-objects) @echo "linking $(@)" ifdef ms_cl_compiler - $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ + $(ld) $(shared) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(so-suffix),.pdb,$(@)) \ -IMPLIB:$(test-build)/$(name).lib $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" @@ -1320,8 +1329,8 @@ ifdef embed $(embed): $(embed-objects) $(embed-loader-o) @echo "building $(embed)" ifdef ms_cl_compiler - $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1343,8 +1352,8 @@ $(embed-loader): $(embed-loader-objects) $(static-library) @mkdir -p $(dir $(@)) cd $(dir $(@)) && $(ar) x ../../../$(static-library) ifdef ms_cl_compiler - $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1475,8 +1484,8 @@ $(executable): $(executable-objects) @echo "linking $(@)" ifeq ($(platform),windows) ifdef ms_cl_compiler - $(ld) $(lflags) $(executable-objects) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(lflags) $(executable-objects) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1514,8 +1523,8 @@ $(build-bootimage-generator): \ @echo "linking $(@)" ifeq ($(platform),windows) ifdef ms_cl_compiler - $(ld) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ - -IMPLIB:$(@).lib $(manifest-flags) + $(ld) $(bootimage-generator-lflags) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif @@ -1534,8 +1543,9 @@ $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(lzma-decode-objects) @echo "linking $(@)" ifdef ms_cl_compiler - $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(subst .dll,.pdb,$(@)) \ - -IMPLIB:$(subst .dll,.lib,$(@)) $(manifest-flags) + $(ld) $(shared) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(so-suffix),.pdb,$(@)) \ + -IMPLIB:$(subst $(so-suffix),.lib,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" endif @@ -1552,8 +1562,8 @@ $(executable-dynamic): $(driver-dynamic-objects) $(dynamic-library) @echo "linking $(@)" ifdef ms_cl_compiler $(ld) $(lflags) -LIBPATH:$(build) -DEFAULTLIB:$(name) \ - -PDB:$(@).pdb -IMPLIB:$(@).lib $(driver-dynamic-objects) \ - -out:$(@) $(manifest-flags) + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) + $(driver-dynamic-objects) -out:$(@) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif diff --git a/src/machine.cpp b/src/machine.cpp index 5e08655898..c3c398bd92 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -17,6 +17,11 @@ #include "arch.h" #include "lzma.h" +#if defined(PLATFORM_WINDOWS) +# define WIN32_LEAN_AND_MEAN +# include +#endif + using namespace vm; namespace { @@ -4741,18 +4746,33 @@ printTrace(Thread* t, object exception) for (object e = exception; e; e = throwableCause(t, e)) { if (e != exception) { fprintf(errorLog(t), "caused by: "); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("caused by: "); +#endif } fprintf(errorLog(t), "%s", &byteArrayBody (t, className(t, objectClass(t, e)), 0)); - +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA((const CHAR*)&byteArrayBody + (t, className(t, objectClass(t, e)), 0)); +#endif + if (throwableMessage(t, e)) { object m = throwableMessage(t, e); THREAD_RUNTIME_ARRAY(t, char, message, stringLength(t, m) + 1); stringChars(t, m, RUNTIME_ARRAY_BODY(message)); fprintf(errorLog(t), ": %s\n", RUNTIME_ARRAY_BODY(message)); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA(": "); + OutputDebugStringA(RUNTIME_ARRAY_BODY(message)); + OutputDebugStringA("\n"); +#endif } else { fprintf(errorLog(t), "\n"); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("\n"); +#endif } object trace = throwableTrace(t, e); @@ -4767,16 +4787,35 @@ printTrace(Thread* t, object exception) (t, traceElementMethod(t, e), traceElementIp(t, e)); fprintf(errorLog(t), " at %s.%s ", class_, method); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA(" at "); + OutputDebugStringA((const CHAR*)class_); + OutputDebugStringA("."); + OutputDebugStringA((const CHAR*)method); + OutputDebugStringA(" "); +#endif switch (line) { case NativeLine: fprintf(errorLog(t), "(native)\n"); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("(native)\n"); +#endif break; case UnknownLine: fprintf(errorLog(t), "(unknown line)\n"); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("(unknown line)\n"); +#endif break; default: fprintf(errorLog(t), "(line %d)\n", line); +#if defined(PLATFORM_WINDOWS) + OutputDebugStringA("(line "); + char buf[35]; + OutputDebugStringA(itoa(line, buf, 10)); + OutputDebugStringA(")\n"); +#endif } } } From c6694287e93467181ed2508835f114580238c041 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Wed, 30 Jan 2013 11:31:06 +0200 Subject: [PATCH 169/378] Finally, proper jvm.dll linking for WP8 --- makefile | 8 +++----- src/machine.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/makefile b/makefile index 7c5123f33f..7d6200c476 100755 --- a/makefile +++ b/makefile @@ -734,14 +734,12 @@ ifeq ($(platform),wp8) arflags = -MACHINE:$(machine_type) lflags = $(common-lflags) -nologo \ -MACHINE:$(machine_type) \ - -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" -LIBPATH:"$(MSVC_ROOT)\lib$(vc_arch)" \ + -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WP80_SDK)\lib$(vc_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" \ ws2_32.lib \ "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" lflags += -NXCOMPAT -DYNAMICBASE -SUBSYSTEM:CONSOLE -TLBID:1 - lflags += -NODEFAULTLIB:"ole32.lib" WindowsPhoneCore.lib - lflags += -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) - #lflags += -WINMD:NO - #lflags += -APPCONTAINER + lflags += -NODEFAULTLIB:"ole32.lib" -NODEFAULTLIB:"kernel32.lib" + lflags += PhoneAppModelHost.lib WindowsPhoneCore.lib -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) cc = $(cxx) asm-format = masm diff --git a/src/machine.h b/src/machine.h index 420a0192cb..5a2812c2b7 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2695,7 +2695,7 @@ throw_(Thread* t, object e) t->exception = e; - // printTrace(t, e); + printTrace(t, e); popResources(t); From 71052fa50c4a836901883730765c4221013e4255 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 12:54:51 +0200 Subject: [PATCH 170/378] Fix WP8/WinRT ARM build --- makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 7d6200c476..355589ec02 100755 --- a/makefile +++ b/makefile @@ -667,10 +667,12 @@ ifeq ($(platform),wp8) as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" - asmflags = $(target-cflags) -machine ARM -32 + asmflags = -machine ARM -32 asm-output = -o $(1) asm-input = $(1) machine_type = ARM + bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end + codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end endif ifeq ($(arch),i386) wp8_arch = From c13149088ec630460e225aed010bec3a0d39c450 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 12:55:12 +0200 Subject: [PATCH 171/378] Fix crash on memory validation --- src/windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows.cpp b/src/windows.cpp index d0b5228368..98fc8e5d96 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -924,7 +924,7 @@ class MySystem: public System { } #else #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") - return name; + return copy(allocator, name); #endif } From 9ed312451a220a970041b4182e00cc9b87ce5841 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 14:54:23 +0200 Subject: [PATCH 172/378] Allow avian.bootstrap to accept multiple libraries --- src/jnienv.cpp | 10 ---------- src/jnienv.h | 10 ++++++++++ src/machine.cpp | 23 ++++++++++++++++++++++- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 2a70b10855..c8f27fb0b7 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3709,16 +3709,6 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) } // namespace vm -#define BOOTSTRAP_PROPERTY "avian.bootstrap" -#define CRASHDIR_PROPERTY "avian.crash.dir" -#define EMBED_PREFIX_PROPERTY "avian.embed.prefix" -#define CLASSPATH_PROPERTY "java.class.path" -#define JAVA_HOME_PROPERTY "java.home" -#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" -#define BOOTCLASSPATH_OPTION "bootclasspath" -#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" -#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" - extern "C" JNIEXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void*) { diff --git a/src/jnienv.h b/src/jnienv.h index 5b8c46685b..8dbd1f8c7d 100644 --- a/src/jnienv.h +++ b/src/jnienv.h @@ -13,6 +13,16 @@ #include "machine.h" +#define BOOTSTRAP_PROPERTY "avian.bootstrap" +#define CRASHDIR_PROPERTY "avian.crash.dir" +#define EMBED_PREFIX_PROPERTY "avian.embed.prefix" +#define CLASSPATH_PROPERTY "java.class.path" +#define JAVA_HOME_PROPERTY "java.home" +#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" +#define BOOTCLASSPATH_OPTION "bootclasspath" +#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" +#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" + namespace vm { void diff --git a/src/machine.cpp b/src/machine.cpp index c3c398bd92..e060cd0a9e 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3008,6 +3008,13 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, populateJNITables(&javaVMVTable, &jniEnvVTable); + const char* bootstrapProperty = strdup(findProperty(this, BOOTSTRAP_PROPERTY)); + const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); + char* codeLibraryName = (char*)bootstrapProperty; + char* codeLibraryNameEnd = 0; + if (codeLibraryName && (codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()))) + *codeLibraryNameEnd = 0; + if (not system->success(system->make(&localThread)) or not system->success(system->make(&stateLock)) or not system->success(system->make(&heapLock)) or @@ -3015,10 +3022,24 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, not system->success(system->make(&referenceLock)) or not system->success(system->make(&shutdownLock)) or not system->success - (system->load(&libraries, findProperty(this, "avian.bootstrap")))) + (system->load(&libraries, bootstrapProperty))) { system->abort(); } + + System::Library* additionalLibrary = 0; + while (codeLibraryNameEnd && codeLibraryNameEnd + 1 < bootstrapPropertyEnd) { + codeLibraryName = codeLibraryNameEnd + 1; + codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()); + if (codeLibraryNameEnd) + *codeLibraryNameEnd = 0; + + if (!system->success(system->load(&additionalLibrary, codeLibraryName))) + system->abort(); + libraries->setNext(additionalLibrary); + } + + free((void*)bootstrapProperty); } void From bde33c97f8852fbdf78cce2adc3f35bc47e47138 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:06:35 +0200 Subject: [PATCH 173/378] Fix crash if no avian.boostrap is specified --- src/machine.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index e060cd0a9e..a0cd3184ce 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3008,7 +3008,8 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, populateJNITables(&javaVMVTable, &jniEnvVTable); - const char* bootstrapProperty = strdup(findProperty(this, BOOTSTRAP_PROPERTY)); + const char* bootstrapProperty = findProperty(this, BOOTSTRAP_PROPERTY); + const char* bootstrapPropertyDup = bootstrapProperty ? strdup(bootstrapProperty) : 0; const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); char* codeLibraryName = (char*)bootstrapProperty; char* codeLibraryNameEnd = 0; @@ -3039,7 +3040,8 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, libraries->setNext(additionalLibrary); } - free((void*)bootstrapProperty); + if(bootstrapPropertyDup) + free((void*)bootstrapPropertyDup); } void From bd2a836395b649fb491bf9596d495faec93c4918 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:07:56 +0200 Subject: [PATCH 174/378] Fix crash if no avian.boostrap is specified (oops) --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index a0cd3184ce..dce3bfe185 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3011,7 +3011,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, const char* bootstrapProperty = findProperty(this, BOOTSTRAP_PROPERTY); const char* bootstrapPropertyDup = bootstrapProperty ? strdup(bootstrapProperty) : 0; const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); - char* codeLibraryName = (char*)bootstrapProperty; + char* codeLibraryName = (char*)bootstrapPropertyDup; char* codeLibraryNameEnd = 0; if (codeLibraryName && (codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()))) *codeLibraryNameEnd = 0; From d0ac63292cb1b62a1cb315fac415b1d06cde702c Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:08:26 +0200 Subject: [PATCH 175/378] Fix crash if no avian.boostrap is specified (oops) --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index dce3bfe185..84a34caf67 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3010,7 +3010,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, const char* bootstrapProperty = findProperty(this, BOOTSTRAP_PROPERTY); const char* bootstrapPropertyDup = bootstrapProperty ? strdup(bootstrapProperty) : 0; - const char* bootstrapPropertyEnd = bootstrapProperty + (bootstrapProperty ? strlen(bootstrapProperty) : 0); + const char* bootstrapPropertyEnd = bootstrapPropertyDup + (bootstrapPropertyDup ? strlen(bootstrapPropertyDup) : 0); char* codeLibraryName = (char*)bootstrapPropertyDup; char* codeLibraryNameEnd = 0; if (codeLibraryName && (codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()))) From 74c9f60b98d92590d780f37a87db19b795168a2a Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 31 Jan 2013 22:10:42 +0200 Subject: [PATCH 176/378] Fix crash if no avian.boostrap is specified (oops) --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index 84a34caf67..d2d225e7e5 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3023,7 +3023,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, not system->success(system->make(&referenceLock)) or not system->success(system->make(&shutdownLock)) or not system->success - (system->load(&libraries, bootstrapProperty))) + (system->load(&libraries, bootstrapPropertyDup))) { system->abort(); } From c3b437a381d4a8201f39d514c8a86c632bc5159f Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 16:36:29 +0200 Subject: [PATCH 177/378] Instead of throwing exception, just return initial file name --- classpath/java-io.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 3860e67ecd..580efe96d2 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -240,8 +240,8 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else - // WinRT has no concept of full paths - throwNewErrno(e, "java/io/IOException"); + // WinRT has no concept of full paths, so any file + // accessed should already have full path, or it has explicit origin return path; # endif #else From 9d8c825cbc2c3090cbe0dfca3e919a32e62a48c5 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 16:40:12 +0200 Subject: [PATCH 178/378] Remove debug code --- classpath/java-io.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 580efe96d2..bb1adce8b3 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -700,9 +700,6 @@ Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path, jboolean app return -1; } } -#ifdef __ANDROID__ -#include -#endif extern "C" JNIEXPORT void JNICALL Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c) @@ -723,11 +720,6 @@ Java_java_io_FileOutputStream_write__I_3BII } e->GetByteArrayRegion(b, offset, length, data); - #ifdef __ANDROID__ - if(fd == 1) { - __android_log_print(ANDROID_LOG_WARN, "net.osmand:native", "%.*s",length, data); - } - #endif if (not e->ExceptionCheck()) { doWrite(e, fd, data, length); } From 11eda6af3e532794d4ee42863958f29a58358e9e Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 16:55:37 +0200 Subject: [PATCH 179/378] java.io.RandomAccessFile for WinPhone8 / WinRT --- classpath/java-io.cpp | 57 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index bb1adce8b3..39186a0274 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -739,6 +739,9 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, { string_t chars = getChars(e, path); if (chars) { + jlong peer = 0; + jlong length = 0; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int fd = ::open((const char*)chars, O_RDONLY); releaseChars(e, path, chars); if (fd == -1) { @@ -751,11 +754,27 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, throwNewErrno(e, "java/io/IOException"); return; } + peer = fd; + length = fileStats.st_size; + #else + HANDLE hFile = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + if (hFile == INVALID_HANDLE_VALUE) { + throwNewErrno(e, "java/io/IOException"); + return; + } + + FILE_STANDARD_INFO info; + if(!GetFileInformationByHandleEx(hFile, FileStandardInfo, &info, sizeof(info))) { + throwNewErrno(e, "java/io/IOException"); + return; + } + + peer = (jlong)hFile; + length = info.EndOfFile.QuadPart; + #endif - jlong peer = fd; e->SetLongArrayRegion(result, 0, 1, &peer); - - jlong length = fileStats.st_size; e->SetLongArrayRegion(result, 1, 1, &length); } } @@ -765,6 +784,7 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, jlong position, jbyteArray buffer, int offset, int length) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int fd = (int)peer; if(::lseek(fd, position, SEEK_SET) == -1) { throwNewErrno(e, "java/io/IOException"); @@ -773,24 +793,45 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); -#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + ssize_t bytesRead = ::read(fd, dst + offset, length); -#else - auto bytesRead = ::read(fd, dst + offset, length); -#endif e->ReleasePrimitiveArrayCritical(buffer, dst, 0); if(bytesRead == -1) { throwNewErrno(e, "java/io/IOException"); return -1; } - +#else + HANDLE hFile = (HANDLE)peer; + LARGE_INTEGER lPos; + lPos.QuadPart = position; + if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + uint8_t* dst = reinterpret_cast + (e->GetPrimitiveArrayCritical(buffer, 0)); + + DWORD bytesRead = 0; + if(!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); +#endif + return (jint)bytesRead; } extern "C" JNIEXPORT void JNICALL Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int fd = (int)peer; ::close(fd); +#else + HANDLE hFile = (HANDLE)peer; + CloseHandle(hFile); +#endif } From e358a681b2714b8e7b3030f0071cc0199625bb75 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 17:49:08 +0200 Subject: [PATCH 180/378] WP8/WinRT : Proper absolute path WP8/WinRT : Last modified time --- classpath/java-io.cpp | 122 +++++++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 31 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 39186a0274..880d91cf56 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -240,8 +240,29 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else - // WinRT has no concept of full paths, so any file - // accessed should already have full path, or it has explicit origin + string_t chars = getChars(e, path); + if(chars) { + LARGE_INTEGER fileSize; + HANDLE file = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + releaseChars(e, path, chars); + + if (file == INVALID_HANDLE_VALUE) + return path; + + uint8_t buffer[sizeof(FILE_NAME_INFO) + sizeof(WCHAR)*MAX_PATH]; + memset(&buffer[0], 0, sizeof(buffer)); + FILE_NAME_INFO* pInfo = reinterpret_cast(&buffer[0]); + if(!GetFileInformationByHandleEx(file, FileNameInfo, pInfo, sizeof(buffer))) + { + CloseHandle(file); + return path; + } + CloseHandle(file); + + return e->NewString + (reinterpret_cast(pInfo->FileName), pInfo->FileNameLength / sizeof(WCHAR)); + } return path; # endif #else @@ -267,33 +288,40 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) extern "C" JNIEXPORT jlong JNICALL Java_java_io_File_length(JNIEnv* e, jclass, jstring path) { - #ifdef PLATFORM_WINDOWS - LARGE_INTEGER fileSize; string_t chars = getChars(e, path); - #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - HANDLE file = CreateFileW - (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); - #else - HANDLE file = CreateFile2 - (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); - #endif - releaseChars(e, path, chars); - if (file != INVALID_HANDLE_VALUE) - { + if(chars) { + LARGE_INTEGER fileSize; #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - GetFileSizeEx(file, &fileSize); + HANDLE file = CreateFileW + (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + #else + HANDLE file = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + #endif + releaseChars(e, path, chars); + if (file == INVALID_HANDLE_VALUE) + return 0; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + if(!GetFileSizeEx(file, &fileSize)) + { + CloseHandle(file); + return 0; + } #else FILE_STANDARD_INFO info; - if(GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) - fileSize = info.EndOfFile; + if(!GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info))) + { + CloseHandle(file); + return 0; + } + fileSize = info.EndOfFile; #endif - } - else return 0; - CloseHandle(file); - return static_cast(fileSize.QuadPart); + CloseHandle(file); + return static_cast(fileSize.QuadPart); + } #else string_t chars = getChars(e, path); @@ -547,21 +575,52 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) string_t chars = getChars(e, path); if (chars) { #ifdef PLATFORM_WINDOWS - # pragma message("Implementation of last modified") - return 0; - #else - struct stat st; - if (stat(chars, &st)) { + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + HANDLE hFile = CreateFileW + (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + #else + HANDLE hFile = CreateFile2 + (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + #endif + releaseChars(e, path, chars); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + LARGE_INTEGER fileDate, filetimeToUnixEpochAdjustment; + filetimeToUnixEpochAdjustment.QuadPart = 11644473600000L * 10000L; + #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + FILETIME fileLastWriteTime; + if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime)) + { + CloseHandle(hFile); + return 0; + } + fileDate.HighPart = fileLastWriteTime.dwHighDateTime; + fileDate.LowPart = fileLastWriteTime.dwLowDateTime; + #else + FILE_BASIC_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo))) + { + CloseHandle(hFile); + return 0; + } + fileDate = fileInfo.ChangeTime; + #endif + CloseHandle(hFile); + fileDate.QuadPart -= filetimeToUnixEpochAdjustment.QuadPart; + return fileDate.QuadPart / 10000000L; + #else + struct stat fileStat; + if (stat(chars, &fileStat) == -1) { + releaseChars(e, path, chars); return 0; - } else { - return (static_cast(st.st_mtim.tv_sec) * 1000) + - (static_cast(st.st_mtim.tv_nsec) / (1000*1000)); } + return (static_cast(st.st_mtim.tv_sec) * 1000) + + (static_cast(st.st_mtim.tv_nsec) / (1000*1000)); #endif - } else { - return 0; } + + return 0; } extern "C" JNIEXPORT jstring JNICALL @@ -766,6 +825,7 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, FILE_STANDARD_INFO info; if(!GetFileInformationByHandleEx(hFile, FileStandardInfo, &info, sizeof(info))) { + CloseHandle(hFile); throwNewErrno(e, "java/io/IOException"); return; } From 234bba59271a7cd0b95d6c880823b0556a3d34e0 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 18:18:52 +0200 Subject: [PATCH 181/378] Add notifications about improvements possible --- classpath/java-io.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 880d91cf56..74f2ab9617 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -289,7 +289,8 @@ extern "C" JNIEXPORT jlong JNICALL Java_java_io_File_length(JNIEnv* e, jclass, jstring path) { #ifdef PLATFORM_WINDOWS - + // Option: without opening file + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx string_t chars = getChars(e, path); if(chars) { LARGE_INTEGER fileSize; @@ -575,6 +576,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) string_t chars = getChars(e, path); if (chars) { #ifdef PLATFORM_WINDOWS + // Option: without opening file + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE hFile = CreateFileW (chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); From 6376a491b6170544259b1a00640e9112d1a0b236 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Fri, 1 Feb 2013 20:54:15 +0200 Subject: [PATCH 182/378] Added comments regarding java.io.File.toAbsolute() and WinRT/WP8 --- classpath/java-io.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 74f2ab9617..3d26a49f02 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -240,6 +240,13 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else +// This could have worked, if GetFileInformationByHandleEx() returned volume information also +// There is a chance to get it, or using GetFullPathName, that is claimed to be unsupported +// or from System.IO.Path.GetFullPath(), but it's CLR and I see no way of calling it from +// C++/CX code +// Best wishes to everyone who will win this fight, +// Alexey Pelykh +/* string_t chars = getChars(e, path); if(chars) { LARGE_INTEGER fileSize; @@ -263,6 +270,7 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return e->NewString (reinterpret_cast(pInfo->FileName), pInfo->FileNameLength / sizeof(WCHAR)); } +*/ return path; # endif #else From 362f4aaa89fd09f784294a8703a14438105dd3af Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 09:38:03 +0200 Subject: [PATCH 183/378] Support new WinRT interop --- classpath/java-io.cpp | 38 ++++++++++++++------------------------ makefile | 9 +++++---- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 3d26a49f02..ba4812a5a4 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -55,6 +55,15 @@ typedef wchar_t char_t; +#if defined(WINAPI_FAMILY) +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#include "avian-interop.h" +#define SKIP_OPERATOR_NEW + +#endif +#endif + #else // not PLATFORM_WINDOWS # include @@ -93,7 +102,9 @@ typedef char char_t; # endif #endif // WINAPI_FAMILY +#if !defined(SKIP_OPERATOR_NEW) inline void* operator new(size_t, void* p) throw() { return p; } +#endif typedef const char_t* string_t; @@ -240,37 +251,16 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) return path; # else -// This could have worked, if GetFileInformationByHandleEx() returned volume information also -// There is a chance to get it, or using GetFullPathName, that is claimed to be unsupported -// or from System.IO.Path.GetFullPath(), but it's CLR and I see no way of calling it from -// C++/CX code -// Best wishes to everyone who will win this fight, -// Alexey Pelykh -/* string_t chars = getChars(e, path); if(chars) { - LARGE_INTEGER fileSize; - HANDLE file = CreateFile2 - (chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + std::wstring partialPath = chars; releaseChars(e, path, chars); - if (file == INVALID_HANDLE_VALUE) - return path; - - uint8_t buffer[sizeof(FILE_NAME_INFO) + sizeof(WCHAR)*MAX_PATH]; - memset(&buffer[0], 0, sizeof(buffer)); - FILE_NAME_INFO* pInfo = reinterpret_cast(&buffer[0]); - if(!GetFileInformationByHandleEx(file, FileNameInfo, pInfo, sizeof(buffer))) - { - CloseHandle(file); - return path; - } - CloseHandle(file); + std::wstring fullPath = AvianInterop::GetFullPath(partialPath); return e->NewString - (reinterpret_cast(pInfo->FileName), pInfo->FileNameLength / sizeof(WCHAR)); + (reinterpret_cast(fullPath.c_str()), fullPath.length()); } -*/ return path; # endif #else diff --git a/makefile b/makefile index 355589ec02..5877510956 100755 --- a/makefile +++ b/makefile @@ -705,12 +705,12 @@ ifeq ($(platform),wp8) -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ - -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" \ - -Fd$(build)/$(name).pdb -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ + -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" -I"$(shell $(windows-path) "$(wp8)/interop/avian-interop-client")" \ + -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ -DTARGET_BYTES_PER_WORD=$(pointer-size) \ - -Gd + -Gd -EHsc common-lflags = $(classpath-lflags) @@ -738,7 +738,8 @@ ifeq ($(platform),wp8) -MACHINE:$(machine_type) \ -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WP80_SDK)\lib$(vc_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" \ ws2_32.lib \ - "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" \ + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\AvianInteropClient.lib")" lflags += -NXCOMPAT -DYNAMICBASE -SUBSYSTEM:CONSOLE -TLBID:1 lflags += -NODEFAULTLIB:"ole32.lib" -NODEFAULTLIB:"kernel32.lib" lflags += PhoneAppModelHost.lib WindowsPhoneCore.lib -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) From d6a5544f2b5144a09605e31a2cca3cbd36b7b4c5 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 10:14:47 +0200 Subject: [PATCH 184/378] getErrorStr() for Windows platforms --- classpath/java-lang.cpp | 45 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 9d2562e265..dc54af5fed 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -74,25 +74,36 @@ namespace { #ifdef PLATFORM_WINDOWS - char* getErrorStr(DWORD err){ - // The poor man's error string, just print the error code - char * errStr = (char*) malloc(9 * sizeof(char)); - snprintf(errStr, 9, "%d", (int) err); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + char* getErrorStr(DWORD err) { + LPSTR errorStr = 0; + if(!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, (LPSTR)&errorStr, 0, 0)) + { + char* errStr = (char*) malloc(9 * sizeof(char)); + snprintf(errStr, 9, "%d", (int) err); + return errStr; + } + char* errStr = strdup(errorStr); + LocalFree(errorStr); return errStr; - - #pragma message("TODO") - // The better way to do this, if I could figure out how to convert LPTSTR to char* - //char* errStr; - //LPTSTR s; - //if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - // FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, &s, 0, NULL) == 0) - //{ - // errStr.Format("Unknown error occurred (%08x)", err); - //} else { - // errStr = s; - //} - //return errStr; } +#else + char* getErrorStr(DWORD err) { + LPSTR errorStr = (LPSTR)malloc(4096); //NOTE: something constant + if(!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, errorStr, 0, 0)) + { + free(errorStr); + + char* errStr = (char*) malloc(9 * sizeof(char)); + snprintf(errStr, 9, "%d", (int) err); + return errStr; + } + char* errStr = strdup(errorStr); + free(errorStr); + return errStr; + } +#endif #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) void makePipe(JNIEnv* e, HANDLE p[2]) From e7ad04fc7a4026fad8682b993502b5c3a2f7abbc Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 11:00:33 +0200 Subject: [PATCH 185/378] Culture fixes ; Path extensions --- classpath/java-lang.cpp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index dc54af5fed..704e2ae6a5 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -69,6 +69,12 @@ # ifndef WINAPI_FAMILY_PARTITION # define WINAPI_FAMILY_PARTITION(x) (x) +# endif +#else +# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +# include "avian-interop.h" + # endif #endif // WINAPI_FAMILY @@ -401,8 +407,20 @@ Locale getLocale() { return Locale(lang, reg); #else - #pragma message("TODO: CultureInfo.CurrentCulture") - return Locale("en", "US"); + std::wstring culture = AvianInterop::GetCurrentUICulture(); + char* cultureName = strdup(std::string(culture.begin(), culture.end()).c_str()); + char* delimiter = strchr(cultureName, '-'); + if(!delimiter) + { + free(cultureName); + return Locale("en", "US"); + } + const char* lang = cultureName; + const char* reg = delimiter + 1; + *delimiter = 0; + Locale locale(lang, reg); + free(cultureName); + return locale; #endif } #else @@ -607,8 +625,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetTempPath(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.ApplicationData.Current.TemporaryFolder") - r = 0; + std::wstring tmpDir = AvianInterop::GetTemporaryFolder(); + r = e->NewString((const jchar*)tmpDir.c_str(), tmpDir.length()); # endif } else if (strcmp(chars, "user.dir") == 0) { # if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -616,8 +634,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, GetCurrentDirectory(MAX_PATH, buffer); r = e->NewStringUTF(buffer); # else - #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") - r = 0; + std::wstring userDir = AvianInterop::GetInstalledLocation(); + r = e->NewString((const jchar*)userDir.c_str(), userDir.length()); # endif } else if (strcmp(chars, "user.home") == 0) { # ifdef _MSC_VER @@ -630,8 +648,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = 0; } # else - #pragma message("TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.Storage.KnownFolders.DocumentsLibrary") - r = 0; + std::wstring userHome = AvianInterop::GetDocumentsLibraryLocation(); + r = e->NewString((const jchar*)userHome.c_str(), userHome.length()); # endif # else LPWSTR home = _wgetenv(L"USERPROFILE"); From b918389672f80208585a9cb424642b52a236a1b5 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 12:27:36 +0200 Subject: [PATCH 186/378] Support built-in jars when wusing multi-library --- src/jnienv.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index c8f27fb0b7..4295c7e0a3 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3729,7 +3729,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) unsigned heapLimit = 0; unsigned stackLimit = 0; - const char* bootLibrary = 0; + const char* bootLibraries = 0; const char* classpath = 0; const char* javaHome = AVIAN_JAVA_HOME; const char* embedPrefix = AVIAN_EMBED_PREFIX; @@ -3765,7 +3765,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) if (strncmp(p, BOOTSTRAP_PROPERTY "=", sizeof(BOOTSTRAP_PROPERTY)) == 0) { - bootLibrary = p + sizeof(BOOTSTRAP_PROPERTY); + bootLibraries = p + sizeof(BOOTSTRAP_PROPERTY); } else if (strncmp(p, CRASHDIR_PROPERTY "=", sizeof(CRASHDIR_PROPERTY)) == 0) { @@ -3819,9 +3819,16 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) *RUNTIME_ARRAY_BODY(bootClasspathBuffer) = 0; } + char* bootLibrary = bootLibraries ? strdup(bootLibraries) : 0; + char* bootLibraryEnd = bootLibrary ? strchr(bootLibrary, PATH_SEPARATOR) : 0; + if(bootLibraryEnd) + *bootLibraryEnd = 0; + Finder* bf = makeFinder (s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary); Finder* af = makeFinder(s, h, classpath, bootLibrary); + if(bootLibrary) + free(bootLibrary); Processor* p = makeProcessor(s, h, true); const char** properties = static_cast From 24e1e1a74561e1168e7c51d086cc3b3f25d62e14 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 19:42:47 +0200 Subject: [PATCH 187/378] Remove empty lines Conflicts: classpath/java-lang.cpp --- classpath/java-lang.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 704e2ae6a5..88a4cf5ef6 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -898,6 +898,11 @@ Java_java_lang_Math_atan(JNIEnv*, jclass, jdouble val) return atan(val); } +extern "C" JNIEXPORT jdouble JNICALL +Java_java_lang_Math_atan2(JNIEnv*, jclass, jdouble y, jdouble x) +{ + return atan2(y, x); +} extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sinh(JNIEnv*, jclass, jdouble val) @@ -917,7 +922,6 @@ Java_java_lang_Math_tanh(JNIEnv*, jclass, jdouble val) return tanh(val); } - extern "C" JNIEXPORT jdouble JNICALL Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val) { From f3c443dbfa5496738aa71f547c9ef8276a2d2a55 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 2 Feb 2013 20:09:28 +0200 Subject: [PATCH 188/378] Fix dword<>qword mistake --- src/x86.masm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.masm b/src/x86.masm index 640637d5af..2f9dedcbd2 100644 --- a/src/x86.masm +++ b/src/x86.masm @@ -108,7 +108,7 @@ Lfloat: Ldouble: cmp ecx,offset DOUBLE_TYPE jne Lexit - fstp ds:dword ptr[8+ebp] + fstp ds:qword ptr[8+ebp] mov eax,ds:dword ptr[8+ebp] mov edx,ds:dword ptr[12+ebp] From 197d4f7f8957f7f1227b308b965d34591e3bee96 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sun, 3 Feb 2013 12:27:30 +0200 Subject: [PATCH 189/378] Make clean target more robust Conflicts: .gitignore --- .gitignore | 1 + makefile | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 201518bb12..588446f90d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build bin /lib /distrib +*.pdb diff --git a/makefile b/makefile index 5877510956..6c846335fa 100755 --- a/makefile +++ b/makefile @@ -1248,6 +1248,11 @@ javadoc: .PHONY: clean clean: + @echo "removing $(build)" + rm -rf $(build) + +.PHONY: clean-all +clean-all: @echo "removing build" rm -rf build From e4bd01f7f36524fe7186e1c6bda5223d2ce8c51c Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 4 Feb 2013 19:45:06 +0200 Subject: [PATCH 190/378] Comment out printTrace --- src/machine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.h b/src/machine.h index 5a2812c2b7..420a0192cb 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2695,7 +2695,7 @@ throw_(Thread* t, object e) t->exception = e; - printTrace(t, e); + // printTrace(t, e); popResources(t); From 83e55ce9cc33b470365bf62b999fcb563c1f7ec1 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 4 Feb 2013 20:02:46 +0200 Subject: [PATCH 191/378] RUNTIME_ARRAY usage --- src/arm.cpp | 5 +---- src/arm.h | 6 ++---- src/bootimage.cpp | 42 +++++++++++++++--------------------------- src/common.h | 4 ++++ src/interpret.cpp | 5 +---- 5 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 1d4dbc8dd1..3016c4658b 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -2555,7 +2555,7 @@ class MyAssembler: public Assembler { OperandType type; Operand* operand; }; - Argument* arguments = new Argument[argumentCount]; + RUNTIME_ARRAY(Argument, arguments, argumentCount); va_list a; va_start(a, argumentCount); unsigned footprint = 0; @@ -2590,9 +2590,6 @@ class MyAssembler: public Assembler { offset += ceiling(arguments[i].size, TargetBytesPerWord); } } - - delete[] arguments; - arguments = 0; } virtual void allocateFrame(unsigned footprint) { diff --git a/src/arm.h b/src/arm.h index 302355c453..5593c86f92 100644 --- a/src/arm.h +++ b/src/arm.h @@ -182,7 +182,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, unsigned vfpIndex = 0; unsigned vfpBackfillIndex UNUSED = 0; - uintptr_t* stack = new uintptr_t[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding + RUNTIME_ARRAY(uintptr_t, stack, (argumentCount * 8) / BytesPerWord); // is > argumentSize to account for padding unsigned stackIndex = 0; unsigned ai = 0; @@ -272,12 +272,10 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, } unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2); - auto retVal = vmNativeCall + return vmNativeCall (function, stackSize, stack, stackIndex * BytesPerWord, (gprIndex ? gprTable : 0), (vfpIndex ? vfpTable : 0), returnType); - delete[] stack; - return retVal; } } // namespace vm diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 5b725f5058..5ec14b51e6 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -342,7 +342,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, unsigned count = s.read2() - 1; if (count) { - Type* types = new Type[count + 2]; + RUNTIME_ARRAY(Type, types, count + 2); types[0] = Type_object; types[1] = Type_intptr_t; @@ -410,9 +410,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, (t, typeMaps, hashMapFind (t, root(t, Machine::PoolMap), c, objectHash, objectEqual), array, objectHash); - - delete[] types; - types = 0; } } @@ -423,7 +420,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object fields = allFields(t, typeMaps, c, &count, &array); PROTECT(t, fields); - Field* memberFields = new Field[count + 1]; + RUNTIME_ARRAY(Field, memberFields, count + 1); unsigned memberIndex; unsigned buildMemberOffset; @@ -447,7 +444,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ++ memberIndex; } } else { - init(new (memberFields) Field, Type_object, 0, BytesPerWord, 0, + init(new (&memberFields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); memberIndex = 1; @@ -457,15 +454,15 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, const unsigned StaticHeader = 3; - Field* staticFields = new Field[count + StaticHeader]; + RUNTIME_ARRAY(Field, staticFields, count + StaticHeader); - init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, + init(new (&staticFields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); - init(new (staticFields + 1) Field, Type_intptr_t, BytesPerWord, + init(new (&staticFields[1]) Field, Type_intptr_t, BytesPerWord, BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); - init(new (staticFields + 2) Field, Type_object, BytesPerWord * 2, + init(new (&staticFields[2]) Field, Type_object, BytesPerWord * 2, BytesPerWord, TargetBytesPerWord * 2, TargetBytesPerWord); unsigned staticIndex = StaticHeader; @@ -515,7 +512,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildStaticOffset = fieldOffset(t, field); - init(new (staticFields + staticIndex) Field, type, + init(new (&staticFields[staticIndex]) Field, type, buildStaticOffset, buildSize, targetStaticOffset, targetSize); @@ -529,7 +526,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildMemberOffset = fieldOffset(t, field); - init(new (memberFields + memberIndex) Field, type, + init(new (&memberFields[memberIndex]) Field, type, buildMemberOffset, buildSize, targetMemberOffset, targetSize); @@ -552,7 +549,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ceiling(targetMemberOffset, TargetBytesPerWord), memberIndex); for (unsigned i = 0; i < memberIndex; ++i) { - Field* f = memberFields + i; + Field* f = &memberFields[i]; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -576,7 +573,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, TypeMap::SingletonKind); for (unsigned i = 0; i < staticIndex; ++i) { - Field* f = staticFields + i; + Field* f = &staticFields[i]; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -589,12 +586,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, hashMapInsert (t, typeMaps, classStaticTable(t, c), array, objectHash); } - - delete[] memberFields; - memberFields = 0; - - delete[] staticFields; - staticFields = 0; } } } @@ -1343,9 +1334,9 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp } ++ count; - Field* fields = new Field[count]; + RUNTIME_ARRAY(Field, fields, count); - init(new (fields) Field, Type_object, 0, BytesPerWord, 0, + init(new (&fields[0]) Field, Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); unsigned buildOffset = BytesPerWord; @@ -1423,7 +1414,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp ++ targetOffset; } - init(new (fields + j) Field, type, buildOffset, buildSize, + init(new (&fields[j]) Field, type, buildOffset, buildSize, targetOffset, targetSize); buildOffset += buildSize; @@ -1458,7 +1449,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp targetArrayElementSize, arrayElementType); for (unsigned j = 0; j < fixedFieldCount; ++j) { - Field* f = fields + j; + Field* f = &fields[j]; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -1471,9 +1462,6 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp hashMapInsert (t, typeMaps, vm::type(t, static_cast(i)), array, objectHash); - - delete[] fields; - fields = 0; } constants = makeCodeImage diff --git a/src/common.h b/src/common.h index c99f23410e..6803fe4c34 100644 --- a/src/common.h +++ b/src/common.h @@ -243,6 +243,10 @@ class RuntimeArray { free(body); } + T& operator[] (const unsigned index) { + return body[index]; + } + T* body; }; diff --git a/src/interpret.cpp b/src/interpret.cpp index 9399e96657..42183e98f0 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2321,7 +2321,7 @@ interpret3(Thread* t, const int base) object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); PROTECT(t, class_); - int32_t* counts = new int32_t[dimensions]; + RUNTIME_ARRAY(int32_t, counts, dimensions); for (int i = dimensions - 1; i >= 0; --i) { counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { @@ -2338,9 +2338,6 @@ interpret3(Thread* t, const int base) populateMultiArray(t, array, counts, 0, dimensions); pushObject(t, array); - - delete[] counts; - counts = 0; } goto loop; case new_: { From d5d2e50ac71883d9764094d7c536182c8e2dbba1 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Tue, 5 Feb 2013 08:41:37 +0200 Subject: [PATCH 192/378] Trace writeout refactor --- src/machine.cpp | 73 ++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index d2d225e7e5..46f331c32d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -4759,6 +4759,27 @@ visitRoots(Machine* m, Heap::Visitor* v) } } +void +logTrace(FILE* f, const char* fmt, ...) +{ + va_list a; + va_start(a, fmt); +#ifdef PLATFORM_WINDOWS + const unsigned length = _vscprintf(fmt, a); +#else + const unsigned length = vsnprintf(0, 0, fmt, a); +#endif + RUNTIME_ARRAY(char, buffer, length + 1); + vsnprintf(&buffer[0], length, fmt, a); + buffer[length] = 0; + va_end(a); + + ::fprintf(f, "%s", &buffer[0]); +#ifdef PLATFORM_WINDOWS + ::OutputDebugStringA(&buffer[0]); +#endif +} + void printTrace(Thread* t, object exception) { @@ -4768,34 +4789,19 @@ printTrace(Thread* t, object exception) for (object e = exception; e; e = throwableCause(t, e)) { if (e != exception) { - fprintf(errorLog(t), "caused by: "); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("caused by: "); -#endif + logTrace(errorLog(t), "caused by: "); } - fprintf(errorLog(t), "%s", &byteArrayBody + logTrace(errorLog(t), "%s", &byteArrayBody (t, className(t, objectClass(t, e)), 0)); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA((const CHAR*)&byteArrayBody - (t, className(t, objectClass(t, e)), 0)); -#endif if (throwableMessage(t, e)) { object m = throwableMessage(t, e); THREAD_RUNTIME_ARRAY(t, char, message, stringLength(t, m) + 1); stringChars(t, m, RUNTIME_ARRAY_BODY(message)); - fprintf(errorLog(t), ": %s\n", RUNTIME_ARRAY_BODY(message)); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA(": "); - OutputDebugStringA(RUNTIME_ARRAY_BODY(message)); - OutputDebugStringA("\n"); -#endif + logTrace(errorLog(t), ": %s\n", RUNTIME_ARRAY_BODY(message)); } else { - fprintf(errorLog(t), "\n"); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("\n"); -#endif + logTrace(errorLog(t), "\n"); } object trace = throwableTrace(t, e); @@ -4809,36 +4815,17 @@ printTrace(Thread* t, object exception) int line = t->m->processor->lineNumber (t, traceElementMethod(t, e), traceElementIp(t, e)); - fprintf(errorLog(t), " at %s.%s ", class_, method); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA(" at "); - OutputDebugStringA((const CHAR*)class_); - OutputDebugStringA("."); - OutputDebugStringA((const CHAR*)method); - OutputDebugStringA(" "); -#endif + logTrace(errorLog(t), " at %s.%s ", class_, method); switch (line) { case NativeLine: - fprintf(errorLog(t), "(native)\n"); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("(native)\n"); -#endif + logTrace(errorLog(t), "(native)\n"); break; case UnknownLine: - fprintf(errorLog(t), "(unknown line)\n"); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("(unknown line)\n"); -#endif + logTrace(errorLog(t), "(unknown line)\n"); break; default: - fprintf(errorLog(t), "(line %d)\n", line); -#if defined(PLATFORM_WINDOWS) - OutputDebugStringA("(line "); - char buf[35]; - OutputDebugStringA(itoa(line, buf, 10)); - OutputDebugStringA(")\n"); -#endif + logTrace(errorLog(t), "(line %d)\n", line); } } } @@ -4848,7 +4835,7 @@ printTrace(Thread* t, object exception) } } - fflush(errorLog(t)); + ::fflush(errorLog(t)); } object From 0a1743ebf2cc53d68c0b4b524d882d584b97ccd9 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 7 Feb 2013 11:43:39 +0200 Subject: [PATCH 193/378] Fix for windows ::open --- classpath/java-io.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index ba4812a5a4..acc0582feb 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -802,7 +802,11 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path, jlong peer = 0; jlong length = 0; #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + #if defined(PLATFORM_WINDOWS) + int fd = ::_wopen(chars, O_RDONLY); + #else int fd = ::open((const char*)chars, O_RDONLY); + #endif releaseChars(e, path, chars); if (fd == -1) { throwNewErrno(e, "java/io/IOException"); From 837e2847ece5ba6858f91f8365f59f82517f3177 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 9 Feb 2013 13:09:58 +0200 Subject: [PATCH 194/378] WP8 target refine --- makefile | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/makefile b/makefile index 6c846335fa..f020bb4b37 100755 --- a/makefile +++ b/makefile @@ -641,14 +641,9 @@ ifeq ($(platform),wp8) ms_cl_compiler = wp8 use-lto = false supports_avian_executable = false - process = compile aot-only = true - ifneq ($(process),compile) - options := -$(process) - endif - bootimage = true - ifeq ($(bootimage),true) - options := $(options)-bootimage + ifneq ($(bootimage),true) + $(error Windows Phone 8 target requires bootimage=true) endif system = windows build-system = windows From dd14b10d8d6a5484f0ed515b467f5bbb84edadd3 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 9 Feb 2013 13:18:39 +0200 Subject: [PATCH 195/378] Lost assignment --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index f020bb4b37..9b3034eb37 100755 --- a/makefile +++ b/makefile @@ -643,7 +643,7 @@ ifeq ($(platform),wp8) supports_avian_executable = false aot-only = true ifneq ($(bootimage),true) - $(error Windows Phone 8 target requires bootimage=true) + x := $(error Windows Phone 8 target requires bootimage=true) endif system = windows build-system = windows From 5d35d64c80b39b251dca93051940f061da58319e Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sun, 10 Feb 2013 09:31:41 +0200 Subject: [PATCH 196/378] Disable operator new warning --- src/common.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common.h b/src/common.h index 6803fe4c34..907a8375b4 100644 --- a/src/common.h +++ b/src/common.h @@ -220,8 +220,17 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t; type name; \ } MAKE_NAME(resource_)(name); +#ifdef _MSC_VER +# pragma warning( push ) +# pragma warning( disable : 4291 ) +#endif + inline void* operator new(size_t, void* p) throw() { return p; } +#ifdef _MSC_VER +# pragma warning( pop ) +#endif + namespace vm { inline intptr_alias_t& From 9c632b778b382f18db3413c2bcaa44d883967fed Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sun, 10 Feb 2013 09:41:46 +0200 Subject: [PATCH 197/378] Proper warning disabling --- src/common.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/common.h b/src/common.h index 907a8375b4..1f74d3382e 100644 --- a/src/common.h +++ b/src/common.h @@ -221,16 +221,10 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t; } MAKE_NAME(resource_)(name); #ifdef _MSC_VER -# pragma warning( push ) # pragma warning( disable : 4291 ) #endif - inline void* operator new(size_t, void* p) throw() { return p; } -#ifdef _MSC_VER -# pragma warning( pop ) -#endif - namespace vm { inline intptr_alias_t& From d26d8fdb9f33a551fe3b09ca37c5814445c8d211 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 10 Feb 2013 18:06:15 -0700 Subject: [PATCH 198/378] rename ceiling -> ceilingDivide --- src/arm.cpp | 6 +++--- src/bootimage-template.cpp | 4 ++-- src/bootimage.cpp | 20 ++++++++++---------- src/common.h | 2 +- src/compile.cpp | 20 ++++++++++---------- src/compiler.cpp | 18 +++++++++--------- src/heap.cpp | 4 ++-- src/machine.cpp | 28 ++++++++++++++-------------- src/machine.h | 20 ++++++++++---------- src/posix.cpp | 2 +- src/powerpc.cpp | 8 ++++---- src/x86.cpp | 4 ++-- 12 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index ae657e30d5..8809cdb479 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -2562,7 +2562,7 @@ class MyAssembler: public Assembler { arguments[i].size = va_arg(a, unsigned); arguments[i].type = static_cast(va_arg(a, int)); arguments[i].operand = va_arg(a, Operand*); - footprint += ceiling(arguments[i].size, TargetBytesPerWord); + footprint += ceilingDivide(arguments[i].size, TargetBytesPerWord); } va_end(a); @@ -2578,7 +2578,7 @@ class MyAssembler: public Assembler { pad(arguments[i].size, TargetBytesPerWord), RegisterOperand, &dst); - offset += ceiling(arguments[i].size, TargetBytesPerWord); + offset += ceilingDivide(arguments[i].size, TargetBytesPerWord); } else { Memory dst(StackRegister, offset * TargetBytesPerWord); @@ -2586,7 +2586,7 @@ class MyAssembler: public Assembler { arguments[i].size, arguments[i].type, arguments[i].operand, pad(arguments[i].size, TargetBytesPerWord), MemoryOperand, &dst); - offset += ceiling(arguments[i].size, TargetBytesPerWord); + offset += ceilingDivide(arguments[i].size, TargetBytesPerWord); } } } diff --git a/src/bootimage-template.cpp b/src/bootimage-template.cpp index d96a586fcd..72374f3392 100644 --- a/src/bootimage-template.cpp +++ b/src/bootimage-template.cpp @@ -9,13 +9,13 @@ const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1); inline unsigned LABEL(codeMapSize)(unsigned codeSize) { - return ceiling(codeSize, TargetBitsPerWord) * TargetBytesPerWord; + return ceilingDivide(codeSize, TargetBitsPerWord) * TargetBytesPerWord; } inline unsigned LABEL(heapMapSize)(unsigned heapSize) { - return ceiling(heapSize, TargetBitsPerWord * TargetBytesPerWord) + return ceilingDivide(heapSize, TargetBitsPerWord * TargetBytesPerWord) * TargetBytesPerWord; } diff --git a/src/bootimage.cpp b/src/bootimage.cpp index f82e73f9f5..51ddc5d866 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -542,11 +542,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, if (hashMapFind(t, typeMaps, c, objectHash, objectEqual) == 0) { object array = makeByteArray (t, TypeMap::sizeInBytes - (ceiling(classFixedSize(t, c), BytesPerWord), memberIndex)); + (ceilingDivide(classFixedSize(t, c), BytesPerWord), memberIndex)); TypeMap* map = new (&byteArrayBody(t, array, 0)) TypeMap - (ceiling(classFixedSize(t, c), BytesPerWord), - ceiling(targetMemberOffset, TargetBytesPerWord), memberIndex); + (ceilingDivide(classFixedSize(t, c), BytesPerWord), + ceilingDivide(targetMemberOffset, TargetBytesPerWord), memberIndex); for (unsigned i = 0; i < memberIndex; ++i) { Field* f = memberFields + i; @@ -569,7 +569,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, TypeMap* map = new (&byteArrayBody(t, array, 0)) TypeMap (singletonCount(t, classStaticTable(t, c)) + 2, - ceiling(targetStaticOffset, TargetBytesPerWord), staticIndex, + ceilingDivide(targetStaticOffset, TargetBytesPerWord), staticIndex, TypeMap::SingletonKind); for (unsigned i = 0; i < staticIndex; ++i) { @@ -739,7 +739,7 @@ targetSize(Thread* t, object typeMaps, object p) if (map->targetArrayElementSizeInBytes) { return map->targetFixedSizeInWords - + ceiling(map->targetArrayElementSizeInBytes + + ceilingDivide(map->targetArrayElementSizeInBytes * cast (p, (map->buildFixedSizeInWords - 1) * BytesPerWord), TargetBytesPerWord); @@ -1069,7 +1069,7 @@ copy(Thread* t, object typeMaps, object referer, unsigned refererOffset, memset(dst, 0, TargetBytesPerWord); - unsigned length = ceiling(objectMaskCount(map), 32); + unsigned length = ceilingDivide(objectMaskCount(map), 32); target_uintptr_t targetLength = targetVW(length); @@ -1164,7 +1164,7 @@ makeHeapImage(Thread* t, BootImage* image, target_uintptr_t* heap, target_uintptr_t* dst = heap + position + TargetFixieSizeInWords; - unsigned maskSize = ceiling(size, TargetBitsPerWord); + unsigned maskSize = ceilingDivide(size, TargetBitsPerWord); unsigned total = TargetFixieSizeInWords + size + maskSize; @@ -1440,11 +1440,11 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp object array = makeByteArray (t, TypeMap::sizeInBytes - (ceiling(buildOffset, BytesPerWord), fixedFieldCount)); + (ceilingDivide(buildOffset, BytesPerWord), fixedFieldCount)); TypeMap* map = new (&byteArrayBody(t, array, 0)) TypeMap - (ceiling(buildOffset, BytesPerWord), - ceiling(targetOffset, TargetBytesPerWord), + (ceilingDivide(buildOffset, BytesPerWord), + ceilingDivide(targetOffset, TargetBytesPerWord), fixedFieldCount, TypeMap::NormalKind, buildArrayElementSize, targetArrayElementSize, arrayElementType); diff --git a/src/common.h b/src/common.h index adab2f587f..33e960cd44 100644 --- a/src/common.h +++ b/src/common.h @@ -350,7 +350,7 @@ padWord(uintptr_t n) } inline unsigned -ceiling(unsigned n, unsigned d) +ceilingDivide(unsigned n, unsigned d) { return (n + d - 1) / d; } diff --git a/src/compile.cpp b/src/compile.cpp index 6989d6446d..365ea267b4 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -940,7 +940,7 @@ frameMapSizeInBits(MyThread* t, object method) unsigned frameMapSizeInWords(MyThread* t, object method) { - return ceiling(frameMapSizeInBits(t, method), BitsPerWord); + return ceilingDivide(frameMapSizeInBits(t, method), BitsPerWord); } uint16_t* @@ -6928,7 +6928,7 @@ unsigned simpleFrameMapTableSize(MyThread* t, object method, object map) { int size = frameMapSizeInBits(t, method); - return ceiling(intArrayLength(t, map) * size, 32 + size); + return ceilingDivide(intArrayLength(t, map) * size, 32 + size); } uint8_t* @@ -6965,7 +6965,7 @@ copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits, { if (DebugFrameMaps) { fprintf(stderr, " orig roots at ip %3d: ", p->ip); - printSet(src, ceiling(mapSizeInBits, BitsPerWord)); + printSet(src, ceilingDivide(mapSizeInBits, BitsPerWord)); print(subroutinePath); fprintf(stderr, "\n"); @@ -7068,7 +7068,7 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start, unsigned indexOffset = sizeof(FrameMapTableHeader); unsigned mapsOffset = indexOffset + (elementCount * sizeof(FrameMapTableIndexElement)); - unsigned pathsOffset = mapsOffset + (ceiling(mapCount * mapSize, 32) * 4); + unsigned pathsOffset = mapsOffset + (ceilingDivide(mapCount * mapSize, 32) * 4); object table = makeByteArray(t, pathsOffset + pathFootprint); @@ -7143,7 +7143,7 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start, sizeof(SubroutineTrace*), compareSubroutineTracePointers); for (unsigned i = 0; i < p->subroutineTraceCount; ++i) { - assert(t, mapsOffset + ceiling(nextMapIndex + mapSize, 32) * 4 + assert(t, mapsOffset + ceilingDivide(nextMapIndex + mapSize, 32) * 4 <= pathsOffset); copyFrameMap(reinterpret_cast(body + mapsOffset), @@ -7155,7 +7155,7 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start, } else { pathIndex = 0; - assert(t, mapsOffset + ceiling(nextMapIndex + mapSize, 32) * 4 + assert(t, mapsOffset + ceilingDivide(nextMapIndex + mapSize, 32) * 4 <= pathsOffset); copyFrameMap(reinterpret_cast(body + mapsOffset), p->map, @@ -7185,7 +7185,7 @@ makeSimpleFrameMapTable(MyThread* t, Context* context, uint8_t* start, { unsigned mapSize = frameMapSizeInBits(t, context->method); object table = makeIntArray - (t, elementCount + ceiling(elementCount * mapSize, 32)); + (t, elementCount + ceilingDivide(elementCount * mapSize, 32)); assert(t, intArrayLength(t, table) == elementCount + simpleFrameMapTableSize(t, context->method, table)); @@ -7196,7 +7196,7 @@ makeSimpleFrameMapTable(MyThread* t, Context* context, uint8_t* start, intArrayBody(t, table, i) = static_cast(p->address->value()) - reinterpret_cast(start); - assert(t, elementCount + ceiling((i + 1) * mapSize, 32) + assert(t, elementCount + ceilingDivide((i + 1) * mapSize, 32) <= intArrayLength(t, table)); if (mapSize) { @@ -9925,7 +9925,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) uintptr_t* heapMap = reinterpret_cast (padWord(reinterpret_cast(callTable + (image->callCount * 2)))); - unsigned heapMapSizeInWords = ceiling + unsigned heapMapSizeInWords = ceilingDivide (heapMapSize(image->heapSize), BytesPerWord); uintptr_t* heap = heapMap + heapMapSizeInWords; @@ -9934,7 +9934,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) t->heapImage = p->heapImage = heap; // fprintf(stderr, "heap from %p to %p\n", - // heap, heap + ceiling(image->heapSize, BytesPerWord)); + // heap, heap + ceilingDivide(image->heapSize, BytesPerWord)); t->codeImage = p->codeImage = code; p->codeImageSize = image->codeSize; diff --git a/src/compiler.cpp b/src/compiler.cpp index 8d0c1bd2f9..a216663de7 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4417,11 +4417,11 @@ appendCombine(Context* c, TernaryOperation type, intptr_t handler = c->client->getThunk (type, firstSize, resultSize, &threadParameter); - unsigned stackSize = ceiling(secondSize, TargetBytesPerWord) - + ceiling(firstSize, TargetBytesPerWord); + unsigned stackSize = ceilingDivide(secondSize, TargetBytesPerWord) + + ceilingDivide(firstSize, TargetBytesPerWord); - local::push(c, ceiling(secondSize, TargetBytesPerWord), second); - local::push(c, ceiling(firstSize, TargetBytesPerWord), first); + local::push(c, ceilingDivide(secondSize, TargetBytesPerWord), second); + local::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); if (threadParameter) { ++ stackSize; @@ -4543,7 +4543,7 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, if (thunk) { Stack* oldStack = c->stack; - local::push(c, ceiling(firstSize, TargetBytesPerWord), first); + local::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -4553,7 +4553,7 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, (c, ValueGeneral, constantSite (c, c->client->getThunk(type, firstSize, resultSize))), 0, 0, result, resultSize, argumentStack, - ceiling(firstSize, TargetBytesPerWord), 0); + ceilingDivide(firstSize, TargetBytesPerWord), 0); } else { append(c, new(c->zone) TranslateEvent @@ -4892,8 +4892,8 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, assert(c, not threadParameter); - local::push(c, ceiling(size, TargetBytesPerWord), second); - local::push(c, ceiling(size, TargetBytesPerWord), first); + local::push(c, ceilingDivide(size, TargetBytesPerWord), second); + local::push(c, ceilingDivide(size, TargetBytesPerWord), first); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -4902,7 +4902,7 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, appendCall (c, value (c, ValueGeneral, constantSite(c, handler)), 0, 0, result, 4, - argumentStack, ceiling(size, TargetBytesPerWord) * 2, 0); + argumentStack, ceilingDivide(size, TargetBytesPerWord) * 2, 0); appendBranch(c, thunkBranch(c, type), 4, value (c, ValueGeneral, constantSite(c, static_cast(0))), diff --git a/src/heap.cpp b/src/heap.cpp index 0cc13ba7dc..39e1b3c572 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -223,7 +223,7 @@ class Segment { unsigned scale, unsigned bitsPerRecord) { unsigned result - = ceiling(ceiling(capacity, scale) * bitsPerRecord, BitsPerWord); + = ceilingDivide(ceilingDivide(capacity, scale) * bitsPerRecord, BitsPerWord); assert(c, result); return result; } @@ -531,7 +531,7 @@ class Fixie { } static unsigned maskSize(unsigned size, bool hasMask) { - return hasMask * ceiling(size, BitsPerWord) * BytesPerWord; + return hasMask * ceilingDivide(size, BitsPerWord) * BytesPerWord; } static unsigned totalSize(unsigned size, bool hasMask) { diff --git a/src/machine.cpp b/src/machine.cpp index 5e08655898..6660ae891e 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -307,9 +307,9 @@ bool walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize, unsigned arrayElementSize, unsigned arrayLength, unsigned start) { - unsigned fixedSizeInWords = ceiling(fixedSize, BytesPerWord); + unsigned fixedSizeInWords = ceilingDivide(fixedSize, BytesPerWord); unsigned arrayElementSizeInWords - = ceiling(arrayElementSize, BytesPerWord); + = ceilingDivide(arrayElementSize, BytesPerWord); for (unsigned i = start; i < fixedSizeInWords; ++i) { if (mask[i / 32] & (static_cast(1) << (i % 32))) { @@ -1286,7 +1286,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) set(t, class_, ClassFieldTable, fieldTable); if (staticCount) { - unsigned footprint = ceiling(staticOffset - (BytesPerWord * 2), + unsigned footprint = ceilingDivide(staticOffset - (BytesPerWord * 2), BytesPerWord); object staticTable = makeSingletonOfSize(t, footprint); @@ -1357,7 +1357,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) classObjectMask(t, classSuper(t, class_))); } else { object mask = makeIntArray - (t, ceiling(classFixedSize(t, class_), 32 * BytesPerWord)); + (t, ceilingDivide(classFixedSize(t, class_), 32 * BytesPerWord)); intArrayBody(t, mask, 0) = 1; object superMask = 0; @@ -1366,7 +1366,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) if (superMask) { memcpy(&intArrayBody(t, mask, 0), &intArrayBody(t, superMask, 0), - ceiling(classFixedSize(t, classSuper(t, class_)), + ceilingDivide(classFixedSize(t, classSuper(t, class_)), 32 * BytesPerWord) * 4); } @@ -3449,7 +3449,7 @@ allocate2(Thread* t, unsigned sizeInBytes, bool objectMask) { return allocate3 (t, t->m->heap, - ceiling(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords ? + ceilingDivide(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords ? Machine::FixedAllocation : Machine::MovableAllocation, sizeInBytes, objectMask); } @@ -3461,15 +3461,15 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, expect(t, t->criticalLevel == 0); if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) { - expect(t, t->backupHeapIndex + ceiling(sizeInBytes, BytesPerWord) + expect(t, t->backupHeapIndex + ceilingDivide(sizeInBytes, BytesPerWord) <= ThreadBackupHeapSizeInWords); object o = reinterpret_cast(t->backupHeap + t->backupHeapIndex); - t->backupHeapIndex += ceiling(sizeInBytes, BytesPerWord); + t->backupHeapIndex += ceilingDivide(sizeInBytes, BytesPerWord); cast(o, 0) = 0; return o; } else if (UNLIKELY(t->flags & Thread::TracingFlag)) { - expect(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + expect(t, t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) <= ThreadHeapSizeInWords); return allocateSmall(t, sizeInBytes); } @@ -3489,7 +3489,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, do { switch (type) { case Machine::MovableAllocation: - if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + if (t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords) { t->heap = 0; @@ -3531,7 +3531,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, throw_(t, root(t, Machine::OutOfMemoryError)); } } while (type == Machine::MovableAllocation - and t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + and t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords); switch (type) { @@ -3543,7 +3543,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, unsigned total; object o = static_cast (t->m->heap->tryAllocateFixed - (allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); + (allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask, &total)); if (o) { memset(o, 0, sizeInBytes); @@ -3562,7 +3562,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, unsigned total; object o = static_cast (t->m->heap->tryAllocateImmortalFixed - (allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); + (allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask, &total)); if (o) { memset(o, 0, sizeInBytes); @@ -5054,7 +5054,7 @@ populateMultiArray(Thread* t, object array, int32_t* counts, for (int32_t i = 0; i < counts[index]; ++i) { object a = makeArray - (t, ceiling + (t, ceilingDivide (counts[index + 1] * classArrayElementSize(t, class_), BytesPerWord)); arrayLength(t, a) = counts[index + 1]; setObjectClass(t, a, class_); diff --git a/src/machine.h b/src/machine.h index 2924a13fb7..c315661ddb 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1818,7 +1818,7 @@ class FixedAllocator: public Allocator { inline bool ensure(Thread* t, unsigned sizeInBytes) { - if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + if (t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords) { if (sizeInBytes <= ThreadBackupHeapSizeInBytes) { @@ -1845,11 +1845,11 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, inline object allocateSmall(Thread* t, unsigned sizeInBytes) { - assert(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + assert(t, t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) <= ThreadHeapSizeInWords); object o = reinterpret_cast(t->heap + t->heapIndex); - t->heapIndex += ceiling(sizeInBytes, BytesPerWord); + t->heapIndex += ceilingDivide(sizeInBytes, BytesPerWord); return o; } @@ -1858,7 +1858,7 @@ allocate(Thread* t, unsigned sizeInBytes, bool objectMask) { stress(t); - if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord) + if (UNLIKELY(t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords or t->m->exclusive)) { @@ -2149,8 +2149,8 @@ baseSize(Thread* t, object o, object class_) { assert(t, classFixedSize(t, class_) >= BytesPerWord); - return ceiling(classFixedSize(t, class_), BytesPerWord) - + ceiling(classArrayElementSize(t, class_) + return ceilingDivide(classFixedSize(t, class_), BytesPerWord) + + ceilingDivide(classArrayElementSize(t, class_) * cast(o, classFixedSize(t, class_) - BytesPerWord), BytesPerWord); } @@ -3349,7 +3349,7 @@ inline unsigned singletonMaskSize(unsigned count, unsigned bitsPerWord) { if (count) { - return ceiling(count + 2, bitsPerWord); + return ceilingDivide(count + 2, bitsPerWord); } return 0; } @@ -3365,7 +3365,7 @@ singletonMaskSize(Thread* t, object singleton) { unsigned length = singletonLength(t, singleton); if (length) { - return ceiling(length + 2, BitsPerWord + 1); + return ceilingDivide(length + 2, BitsPerWord + 1); } return 0; } @@ -3448,7 +3448,7 @@ singletonBit(Thread* t, object singleton, unsigned start, unsigned index) inline unsigned poolMaskSize(unsigned count, unsigned bitsPerWord) { - return ceiling(count, bitsPerWord); + return ceilingDivide(count, bitsPerWord); } inline unsigned @@ -3460,7 +3460,7 @@ poolMaskSize(unsigned count) inline unsigned poolMaskSize(Thread* t, object pool) { - return ceiling(singletonCount(t, pool), BitsPerWord + 1); + return ceilingDivide(singletonCount(t, pool), BitsPerWord + 1); } inline unsigned diff --git a/src/posix.cpp b/src/posix.cpp index da575eb8a4..482b77c22a 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -816,7 +816,7 @@ class MySystem: public System { // been unable to track it down so far. The workaround is to give // it 8 words more than it should need, where 8 is a number I just // made up and seems to work. - void* array[ceiling(sizeof(struct stat), sizeof(void*)) + 8]; + void* array[ceilingDivide(sizeof(struct stat), sizeof(void*)) + 8]; struct stat* s = reinterpret_cast(array); #endif diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 6a329a2f6e..1c34c85291 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -2238,7 +2238,7 @@ class MyArchitecture: public Assembler::Architecture { virtual unsigned alignFrameSize(unsigned sizeInWords) { const unsigned alignment = StackAlignmentInWords; - return (ceiling(sizeInWords + FrameFooterSize, alignment) * alignment); + return (ceilingDivide(sizeInWords + FrameFooterSize, alignment) * alignment); } virtual void nextFrame(void* start, unsigned size, unsigned footprint, @@ -2513,7 +2513,7 @@ class MyAssembler: public Assembler { arguments[i].size = va_arg(a, unsigned); arguments[i].type = static_cast(va_arg(a, int)); arguments[i].operand = va_arg(a, Operand*); - footprint += ceiling(arguments[i].size, TargetBytesPerWord); + footprint += ceilingDivide(arguments[i].size, TargetBytesPerWord); } va_end(a); @@ -2529,7 +2529,7 @@ class MyAssembler: public Assembler { pad(arguments[i].size, TargetBytesPerWord), RegisterOperand, &dst); - offset += ceiling(arguments[i].size, TargetBytesPerWord); + offset += ceilingDivide(arguments[i].size, TargetBytesPerWord); } else { Memory dst (ThreadRegister, (offset + FrameFooterSize) * TargetBytesPerWord); @@ -2538,7 +2538,7 @@ class MyAssembler: public Assembler { arguments[i].size, arguments[i].type, arguments[i].operand, pad(arguments[i].size, TargetBytesPerWord), MemoryOperand, &dst); - offset += ceiling(arguments[i].size, TargetBytesPerWord); + offset += ceilingDivide(arguments[i].size, TargetBytesPerWord); } } } diff --git a/src/x86.cpp b/src/x86.cpp index acdb8f1f71..fc92e661f2 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -3444,7 +3444,7 @@ class MyAssembler: public Assembler { RUNTIME_ARRAY_BODY(arguments)[i].type = static_cast(va_arg(a, int)); RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, Operand*); - footprint += ceiling + footprint += ceilingDivide (RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord); } va_end(a); @@ -3471,7 +3471,7 @@ class MyAssembler: public Assembler { pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), MemoryOperand, &dst); - offset += ceiling + offset += ceilingDivide (RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord); } } From 2a1834e48ade62df2b4e6807987f6b6bece15aaa Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 10 Feb 2013 17:14:16 -0700 Subject: [PATCH 199/378] rename mask -> maskAlignedPointer --- src/common.h | 2 +- src/heap.cpp | 22 +++++++++++----------- src/machine.cpp | 8 ++++---- src/machine.h | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/common.h b/src/common.h index 33e960cd44..4aa47d7ab8 100644 --- a/src/common.h +++ b/src/common.h @@ -483,7 +483,7 @@ cast(void* p, unsigned offset) template inline T* -mask(T* p) +maskAlignedPointer(T* p) { return reinterpret_cast(reinterpret_cast(p) & PointerMask); } diff --git a/src/heap.cpp b/src/heap.cpp index 39e1b3c572..5c87de8b88 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -80,7 +80,7 @@ markBitAtomic(uintptr_t* map, unsigned i) inline void* get(void* o, unsigned offsetInWords) { - return mask(cast(o, offsetInWords * BytesPerWord)); + return maskAlignedPointer(cast(o, offsetInWords * BytesPerWord)); } inline void** @@ -1179,12 +1179,12 @@ updateHeapMap(Context* c, void* p, void* target, unsigned offset, void* result) void* update(Context* c, void** p, void* target, unsigned offset, bool* needsVisit) { - if (mask(*p) == 0) { + if (maskAlignedPointer(*p) == 0) { *needsVisit = false; return 0; } - void* result = update2(c, mask(*p), needsVisit); + void* result = update2(c, maskAlignedPointer(*p), needsVisit); if (result) { updateHeapMap(c, p, target, offset, result); @@ -1297,20 +1297,20 @@ bitsetNext(Context* c, uintptr_t* p) void collect(Context* c, void** p, void* target, unsigned offset) { - void* original = mask(*p); + void* original = maskAlignedPointer(*p); void* parent_ = 0; if (Debug) { fprintf(stderr, "update %p (%s) at %p (%s)\n", - mask(*p), segment(c, *p), p, segment(c, p)); + maskAlignedPointer(*p), segment(c, *p), p, segment(c, p)); } bool needsVisit; - local::set(p, update(c, mask(p), target, offset, &needsVisit)); + local::set(p, update(c, maskAlignedPointer(p), target, offset, &needsVisit)); if (Debug) { fprintf(stderr, " result: %p (%s) (visit? %d)\n", - mask(*p), segment(c, *p), needsVisit); + maskAlignedPointer(*p), segment(c, *p), needsVisit); } if (not needsVisit) return; @@ -1966,10 +1966,10 @@ class MyHeap: public Heap { bool dirty = false; for (unsigned i = 0; i < count; ++i) { void** target = static_cast(p) + offset + i; - if (targetNeedsMark(mask(*target))) { + if (targetNeedsMark(maskAlignedPointer(*target))) { if (DebugFixies) { fprintf(stderr, "dirty fixie %p at %d (%p): %p\n", - f, offset, f->body() + offset, mask(*target)); + f, offset, f->body() + offset, maskAlignedPointer(*target)); } dirty = true; @@ -1994,7 +1994,7 @@ class MyHeap: public Heap { for (unsigned i = 0; i < count; ++i) { void** target = static_cast(p) + offset + i; - if (targetNeedsMark(mask(*target))) { + if (targetNeedsMark(maskAlignedPointer(*target))) { #ifdef USE_ATOMIC_OPERATIONS map->markAtomic(target); #else @@ -2041,7 +2041,7 @@ class MyHeap: public Heap { } virtual Status status(void* p) { - p = mask(p); + p = maskAlignedPointer(p); if (p == 0) { return Null; diff --git a/src/machine.cpp b/src/machine.cpp index 6660ae891e..eda7f87259 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2763,7 +2763,7 @@ class HeapClient: public Heap::Client { virtual unsigned sizeInWords(void* p) { Thread* t = m->rootThread; - object o = static_cast(m->heap->follow(mask(p))); + object o = static_cast(m->heap->follow(maskAlignedPointer(p))); unsigned n = baseSize(t, o, static_cast (m->heap->follow(objectClass(t, o)))); @@ -2778,7 +2778,7 @@ class HeapClient: public Heap::Client { virtual unsigned copiedSizeInWords(void* p) { Thread* t = m->rootThread; - object o = static_cast(m->heap->follow(mask(p))); + object o = static_cast(m->heap->follow(maskAlignedPointer(p))); assert(t, not objectFixed(t, o)); unsigned n = baseSize(t, o, static_cast @@ -2794,7 +2794,7 @@ class HeapClient: public Heap::Client { virtual void copy(void* srcp, void* dstp) { Thread* t = m->rootThread; - object src = static_cast(m->heap->follow(mask(srcp))); + object src = static_cast(m->heap->follow(maskAlignedPointer(srcp))); assert(t, not objectFixed(t, src)); object class_ = static_cast @@ -2815,7 +2815,7 @@ class HeapClient: public Heap::Client { } virtual void walk(void* p, Heap::Walker* w) { - object o = static_cast(m->heap->follow(mask(p))); + object o = static_cast(m->heap->follow(maskAlignedPointer(p))); ::walk(m->rootThread, w, o, 0); } diff --git a/src/machine.h b/src/machine.h index c315661ddb..e972a3be9d 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1611,7 +1611,7 @@ typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*); inline object objectClass(Thread*, object o) { - return mask(cast(o, 0)); + return maskAlignedPointer(cast(o, 0)); } inline unsigned From 5dd770d7ea02c75b3f12101614f572f3c93591db Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 10 Feb 2013 17:38:51 -0700 Subject: [PATCH 200/378] rename cast -> fieldAtOffset --- src/bootimage.cpp | 6 +- src/builtin.cpp | 6 +- src/classpath-avian.cpp | 38 ++++++------ src/classpath-common.h | 8 +-- src/classpath-openjdk.cpp | 122 +++++++++++++++++++------------------- src/common.h | 2 +- src/compile.cpp | 24 ++++---- src/heap.cpp | 12 ++-- src/heapwalk.cpp | 2 +- src/interpret.cpp | 32 +++++----- src/jnienv.cpp | 72 +++++++++++----------- src/machine.cpp | 6 +- src/machine.h | 20 +++---- 13 files changed, 175 insertions(+), 175 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 51ddc5d866..894871af83 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -740,7 +740,7 @@ targetSize(Thread* t, object typeMaps, object p) if (map->targetArrayElementSizeInBytes) { return map->targetFixedSizeInWords + ceilingDivide(map->targetArrayElementSizeInBytes - * cast + * fieldAtOffset (p, (map->buildFixedSizeInWords - 1) * BytesPerWord), TargetBytesPerWord); } else { @@ -888,7 +888,7 @@ nonObjectsEqual(TypeMap* map, uint8_t* src, uint8_t* dst) if (map->targetArrayElementSizeInBytes) { unsigned fixedSize = map->buildFixedSizeInWords * BytesPerWord; - unsigned count = cast(src, fixedSize - BytesPerWord); + unsigned count = fieldAtOffset(src, fixedSize - BytesPerWord); for (unsigned i = 0; i < count; ++i) { if (not nonObjectsEqual @@ -919,7 +919,7 @@ copy(Thread* t, object typeMaps, object p, uint8_t* dst) if (map->targetArrayElementSizeInBytes) { unsigned fixedSize = map->buildFixedSizeInWords * BytesPerWord; - unsigned count = cast(p, fixedSize - BytesPerWord); + unsigned count = fieldAtOffset(p, fixedSize - BytesPerWord); for (unsigned i = 0; i < count; ++i) { copy(t, src + fixedSize + (i * map->buildArrayElementSizeInBytes), diff --git a/src/builtin.cpp b/src/builtin.cpp index 845c0cebe1..1edec99bef 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -365,7 +365,7 @@ Avian_sun_misc_Unsafe_setMemory ACQUIRE(t, t->m->referenceLock); if (base) { - memset(&cast(base, offset), value, count); + memset(&fieldAtOffset(base, offset), value, count); } else { memset(reinterpret_cast(offset), value, count); } @@ -528,11 +528,11 @@ Avian_sun_misc_Unsafe_copyMemory ACQUIRE(t, t->m->referenceLock); void* src = srcBase - ? &cast(srcBase, srcOffset) + ? &fieldAtOffset(srcBase, srcOffset) : reinterpret_cast(srcOffset); void* dst = dstBase - ? &cast(dstBase, dstOffset) + ? &fieldAtOffset(dstBase, dstOffset) : reinterpret_cast(dstOffset); memcpy(dst, src, count); diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 703332c518..09fca657ef 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -250,21 +250,21 @@ Avian_java_lang_reflect_Field_getPrimitive switch (code) { case ByteField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); case BooleanField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); case CharField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); case ShortField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); case IntField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); case LongField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); case FloatField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); case DoubleField: - return cast(instance, offset); + return fieldAtOffset(instance, offset); default: abort(t); } @@ -277,7 +277,7 @@ Avian_java_lang_reflect_Field_getObject object instance = reinterpret_cast(arguments[0]); int offset = arguments[1]; - return reinterpret_cast(cast(instance, offset)); + return reinterpret_cast(fieldAtOffset(instance, offset)); } extern "C" JNIEXPORT void JNICALL @@ -291,28 +291,28 @@ Avian_java_lang_reflect_Field_setPrimitive switch (code) { case ByteField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; case BooleanField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; case CharField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; case ShortField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; case IntField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; case LongField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; case FloatField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; case DoubleField: - cast(instance, offset) = static_cast(value); + fieldAtOffset(instance, offset) = static_cast(value); break; default: abort(t); @@ -379,7 +379,7 @@ Avian_java_lang_reflect_Array_getLength unsigned elementSize = classArrayElementSize(t, objectClass(t, array)); if (LIKELY(elementSize)) { - return cast(array, BytesPerWord); + return fieldAtOffset(array, BytesPerWord); } else { throwNew(t, Machine::IllegalArgumentExceptionType); } @@ -666,7 +666,7 @@ Avian_avian_Atomic_compareAndSwapObject uintptr_t update = arguments[4]; bool success = atomicCompareAndSwap - (&cast(target, offset), expect, update); + (&fieldAtOffset(target, offset), expect, update); if (success) { mark(t, target, offset); diff --git a/src/classpath-common.h b/src/classpath-common.h index aff9f8c40c..dad0fd3559 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -77,14 +77,14 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst, unsigned elementSize = classArrayElementSize(t, objectClass(t, src)); if (LIKELY(elementSize)) { - intptr_t sl = cast(src, BytesPerWord); - intptr_t dl = cast(dst, BytesPerWord); + intptr_t sl = fieldAtOffset(src, BytesPerWord); + intptr_t dl = fieldAtOffset(dst, BytesPerWord); if (LIKELY(length > 0)) { if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and dstOffset >= 0 and dstOffset + length <= dl)) { - uint8_t* sbody = &cast(src, ArrayBody); - uint8_t* dbody = &cast(dst, ArrayBody); + uint8_t* sbody = &fieldAtOffset(src, ArrayBody); + uint8_t* dbody = &fieldAtOffset(dst, ArrayBody); if (src == dst) { memmove(dbody + (dstOffset * elementSize), sbody + (srcOffset * elementSize), diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index cab2d85ba0..074f3cf5f3 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -709,7 +709,7 @@ class MyClasspath : public Classpath { set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)), fieldOffset(t, scl), root(t, Machine::AppLoader)); - cast(classStaticTable(t, type(t, Machine::ClassLoaderType)), + fieldAtOffset(classStaticTable(t, type(t, Machine::ClassLoaderType)), fieldOffset(t, sclSet)) = true; } @@ -950,7 +950,7 @@ getFileAttributes MyClasspath* cp = static_cast(t->m->classpath); object file = reinterpret_cast(arguments[1]); - object path = cast(file, cp->filePathField); + object path = fieldAtOffset(file, cp->filePathField); THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); @@ -999,7 +999,7 @@ checkFileAccess object file = reinterpret_cast(arguments[1]); unsigned mask = arguments[2]; - object path = cast(file, cp->filePathField); + object path = fieldAtOffset(file, cp->filePathField); THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); @@ -1045,7 +1045,7 @@ getFileLength MyClasspath* cp = static_cast(t->m->classpath); object file = reinterpret_cast(arguments[1]); - object path = cast(file, cp->filePathField); + object path = fieldAtOffset(file, cp->filePathField); THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); @@ -1131,8 +1131,8 @@ openFile(Thread* t, object method, uintptr_t* arguments) set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord), region); - cast - (cast + fieldAtOffset + (fieldAtOffset (this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField) = index + VirtualFileBase; } else { @@ -1150,8 +1150,8 @@ readByteFromFile(Thread* t, object method, uintptr_t* arguments) MyClasspath* cp = static_cast(t->m->classpath); - int fd = cast - (cast + int fd = fieldAtOffset + (fieldAtOffset (this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField); if (fd >= VirtualFileBase) { @@ -1191,8 +1191,8 @@ readBytesFromFile(Thread* t, object method, uintptr_t* arguments) MyClasspath* cp = static_cast(t->m->classpath); - int fd = cast - (cast + int fd = fieldAtOffset + (fieldAtOffset (this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField); if (fd >= VirtualFileBase) { @@ -1243,8 +1243,8 @@ skipBytesInFile(Thread* t, object method, uintptr_t* arguments) MyClasspath* cp = static_cast(t->m->classpath); - int fd = cast - (cast + int fd = fieldAtOffset + (fieldAtOffset (this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField); if (fd >= VirtualFileBase) { @@ -1284,8 +1284,8 @@ availableBytesInFile(Thread* t, object method, uintptr_t* arguments) MyClasspath* cp = static_cast(t->m->classpath); - int fd = cast - (cast + int fd = fieldAtOffset + (fieldAtOffset (this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField); if (fd >= VirtualFileBase) { @@ -1317,8 +1317,8 @@ closeFile(Thread* t, object method, uintptr_t* arguments) MyClasspath* cp = static_cast(t->m->classpath); - int fd = cast - (cast + int fd = fieldAtOffset + (fieldAtOffset (this_, cp->fileInputStreamFdField), cp->fileDescriptorFdField); if (fd >= VirtualFileBase) { @@ -1623,15 +1623,15 @@ initializeZipEntryFields(Thread* t, object method, uintptr_t* arguments) set(t, this_, cp->zipEntryNameField, name); - cast(this_, cp->zipEntryTimeField) + fieldAtOffset(this_, cp->zipEntryTimeField) = fileTime(entry->start); - cast(this_, cp->zipEntryCrcField) + fieldAtOffset(this_, cp->zipEntryCrcField) = fileCRC(entry->start); - cast(this_, cp->zipEntrySizeField) + fieldAtOffset(this_, cp->zipEntrySizeField) = uncompressedSize(entry->start); - cast(this_, cp->zipEntryCsizeField) + fieldAtOffset(this_, cp->zipEntryCsizeField) = compressedSize(entry->start); - cast(this_, cp->zipEntryMethodField) + fieldAtOffset(this_, cp->zipEntryMethodField) = compressionMethod(entry->start); } else { t->m->processor->invoke @@ -1771,7 +1771,7 @@ getJarFileMetaInfEntryNames(Thread* t, object method, uintptr_t* arguments) MyClasspath* cp = static_cast(t->m->classpath); - int64_t peer = cast(this_, cp->zipFileJzfileField); + int64_t peer = fieldAtOffset(this_, cp->zipFileJzfileField); ZipFile* file = reinterpret_cast(peer); if (file->region) { return 0; @@ -2839,7 +2839,7 @@ Avian_sun_misc_Unsafe_getObject object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return fieldAtOffset(o, offset); } extern "C" JNIEXPORT void JNICALL @@ -2860,7 +2860,7 @@ Avian_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return fieldAtOffset(o, offset); } extern "C" JNIEXPORT int64_t JNICALL @@ -2870,7 +2870,7 @@ Avian_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return fieldAtOffset(o, offset); } extern "C" JNIEXPORT int64_t JNICALL @@ -2880,7 +2880,7 @@ Avian_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return fieldAtOffset(o, offset); } extern "C" JNIEXPORT int64_t JNICALL @@ -2890,7 +2890,7 @@ Avian_sun_misc_Unsafe_getIntVolatile object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - int32_t result = cast(o, offset); + int32_t result = fieldAtOffset(o, offset); loadMemoryBarrier(); return result; } @@ -2902,7 +2902,7 @@ Avian_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return fieldAtOffset(o, offset); } extern "C" JNIEXPORT int64_t JNICALL @@ -2928,7 +2928,7 @@ Avian_sun_misc_Unsafe_getLongVolatile acquire(t, field); } - int64_t result = cast(o, offset); + int64_t result = fieldAtOffset(o, offset); if (BytesPerWord < 8) { release(t, field); @@ -2947,7 +2947,7 @@ Avian_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB int64_t offset; memcpy(&offset, arguments + 2, 8); int8_t value = arguments[4]; - cast(o, offset) = value; + fieldAtOffset(o, offset) = value; } extern "C" JNIEXPORT void JNICALL @@ -2958,7 +2958,7 @@ Avian_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS int64_t offset; memcpy(&offset, arguments + 2, 8); int16_t value = arguments[4]; - cast(o, offset) = value; + fieldAtOffset(o, offset) = value; } extern "C" JNIEXPORT void JNICALL @@ -2969,7 +2969,7 @@ Avian_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI int64_t offset; memcpy(&offset, arguments + 2, 8); int32_t value = arguments[4]; - cast(o, offset) = value; + fieldAtOffset(o, offset) = value; } extern "C" JNIEXPORT void JNICALL @@ -2980,7 +2980,7 @@ Avian_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF int64_t offset; memcpy(&offset, arguments + 2, 8); int32_t value = arguments[4]; - cast(o, offset) = value; + fieldAtOffset(o, offset) = value; } extern "C" JNIEXPORT int64_t JNICALL @@ -2990,7 +2990,7 @@ Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return fieldAtOffset(o, offset); } extern "C" JNIEXPORT int64_t JNICALL @@ -3009,7 +3009,7 @@ Avian_sun_misc_Unsafe_putBoolean__Ljava_lang_Object_2JZ int64_t offset; memcpy(&offset, arguments + 2, 8); uint8_t value = arguments[4]; - cast(o, offset) = value; + fieldAtOffset(o, offset) = value; } extern "C" JNIEXPORT void JNICALL @@ -3020,7 +3020,7 @@ Avian_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ int64_t offset; memcpy(&offset, arguments + 2, 8); int64_t value; memcpy(&value, arguments + 4, 8); - cast(o, offset) = value; + fieldAtOffset(o, offset) = value; } extern "C" JNIEXPORT int64_t JNICALL @@ -3030,7 +3030,7 @@ Avian_sun_misc_Unsafe_getObjectVolatile object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - uintptr_t value = cast(o, offset); + uintptr_t value = fieldAtOffset(o, offset); loadMemoryBarrier(); return value; } @@ -3065,7 +3065,7 @@ Avian_sun_misc_Unsafe_compareAndSwapInt uint32_t update = arguments[5]; return atomicCompareAndSwap32 - (&cast(target, offset), expect, update); + (&fieldAtOffset(target, offset), expect, update); } extern "C" JNIEXPORT int64_t JNICALL @@ -3078,7 +3078,7 @@ Avian_sun_misc_Unsafe_compareAndSwapObject uintptr_t update = arguments[5]; bool success = atomicCompareAndSwap - (&cast(target, offset), expect, update); + (&fieldAtOffset(target, offset), expect, update); if (success) { mark(t, target, offset); @@ -3098,11 +3098,11 @@ Avian_sun_misc_Unsafe_compareAndSwapLong #ifdef AVIAN_HAS_CAS64 return atomicCompareAndSwap64 - (&cast(target, offset), expect, update); + (&fieldAtOffset(target, offset), expect, update); #else ACQUIRE_FIELD_FOR_WRITE(t, local::fieldForOffset(t, target, offset)); - if (cast(target, offset) == expect) { - cast(target, offset) = update; + if (fieldAtOffset(target, offset) == expect) { + fieldAtOffset(target, offset) = update; return true; } else { return false; @@ -3999,7 +3999,7 @@ EXPORT(JVM_GetArrayLength)(Thread* t, jobject array) { ENTER(t, Thread::ActiveState); - return cast(*array, BytesPerWord); + return fieldAtOffset(*array, BytesPerWord); } uint64_t @@ -4012,40 +4012,40 @@ jvmGetArrayElement(Thread* t, uintptr_t* arguments) case 'Z': return reinterpret_cast (makeLocalReference - (t, makeBoolean(t, cast(*array, ArrayBody + index)))); + (t, makeBoolean(t, fieldAtOffset(*array, ArrayBody + index)))); case 'B': return reinterpret_cast (makeLocalReference - (t, makeByte(t, cast(*array, ArrayBody + index)))); + (t, makeByte(t, fieldAtOffset(*array, ArrayBody + index)))); case 'C': return reinterpret_cast (makeLocalReference - (t, makeChar(t, cast(*array, ArrayBody + (index * 2))))); + (t, makeChar(t, fieldAtOffset(*array, ArrayBody + (index * 2))))); case 'S': return reinterpret_cast (makeLocalReference - (t, makeShort(t, cast(*array, ArrayBody + (index * 2))))); + (t, makeShort(t, fieldAtOffset(*array, ArrayBody + (index * 2))))); case 'I': return reinterpret_cast (makeLocalReference - (t, makeInt(t, cast(*array, ArrayBody + (index * 4))))); + (t, makeInt(t, fieldAtOffset(*array, ArrayBody + (index * 4))))); case 'F': return reinterpret_cast (makeLocalReference - (t, makeFloat(t, cast(*array, ArrayBody + (index * 4))))); + (t, makeFloat(t, fieldAtOffset(*array, ArrayBody + (index * 4))))); case 'J': return reinterpret_cast (makeLocalReference - (t, makeLong(t, cast(*array, ArrayBody + (index * 8))))); + (t, makeLong(t, fieldAtOffset(*array, ArrayBody + (index * 8))))); case 'D': return reinterpret_cast (makeLocalReference - (t, makeDouble(t, cast(*array, ArrayBody + (index * 8))))); + (t, makeDouble(t, fieldAtOffset(*array, ArrayBody + (index * 8))))); case 'L': case '[': return reinterpret_cast (makeLocalReference - (t, cast(*array, ArrayBody + (index * BytesPerWord)))); + (t, fieldAtOffset(*array, ArrayBody + (index * BytesPerWord)))); default: abort(t); } @@ -4071,28 +4071,28 @@ EXPORT(JVM_SetArrayElement)(Thread* t, jobject array, jint index, switch (byteArrayBody(t, className(t, objectClass(t, *array)), 1)) { case 'Z': - cast(*array, ArrayBody + index) = booleanValue(t, *value); + fieldAtOffset(*array, ArrayBody + index) = booleanValue(t, *value); break; case 'B': - cast(*array, ArrayBody + index) = byteValue(t, *value); + fieldAtOffset(*array, ArrayBody + index) = byteValue(t, *value); break; case 'C': - cast(*array, ArrayBody + (index * 2)) = charValue(t, *value); + fieldAtOffset(*array, ArrayBody + (index * 2)) = charValue(t, *value); break; case 'S': - cast(*array, ArrayBody + (index * 2)) = shortValue(t, *value); + fieldAtOffset(*array, ArrayBody + (index * 2)) = shortValue(t, *value); break; case 'I': - cast(*array, ArrayBody + (index * 4)) = intValue(t, *value); + fieldAtOffset(*array, ArrayBody + (index * 4)) = intValue(t, *value); break; case 'F': - cast(*array, ArrayBody + (index * 4)) = floatValue(t, *value); + fieldAtOffset(*array, ArrayBody + (index * 4)) = floatValue(t, *value); break; case 'J': - cast(*array, ArrayBody + (index * 8)) = longValue(t, *value); + fieldAtOffset(*array, ArrayBody + (index * 8)) = longValue(t, *value); break; case 'D': - cast(*array, ArrayBody + (index * 8)) = doubleValue(t, *value); + fieldAtOffset(*array, ArrayBody + (index * 8)) = doubleValue(t, *value); break; case 'L': case '[': @@ -5059,7 +5059,7 @@ jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) return reinterpret_cast (makeLocalReference (t, t->m->classpath->makeString - (t, array, 0, cast(array, BytesPerWord) - 1))); + (t, array, 0, fieldAtOffset(array, BytesPerWord) - 1))); } extern "C" JNIEXPORT jstring JNICALL diff --git a/src/common.h b/src/common.h index 4aa47d7ab8..3032bafae7 100644 --- a/src/common.h +++ b/src/common.h @@ -476,7 +476,7 @@ getBits(T* map, unsigned bitsPerRecord, unsigned index) template inline T& -cast(void* p, unsigned offset) +fieldAtOffset(void* p, unsigned offset) { return *reinterpret_cast(static_cast(p) + offset); } diff --git a/src/compile.cpp b/src/compile.cpp index 365ea267b4..9e387aff19 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3047,22 +3047,22 @@ getFieldValue(Thread* t, object target, object field) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - return cast(target, fieldOffset(t, field)); + return fieldAtOffset(target, fieldOffset(t, field)); case CharField: case ShortField: - return cast(target, fieldOffset(t, field)); + return fieldAtOffset(target, fieldOffset(t, field)); case FloatField: case IntField: - return cast(target, fieldOffset(t, field)); + return fieldAtOffset(target, fieldOffset(t, field)); case DoubleField: case LongField: - return cast(target, fieldOffset(t, field)); + return fieldAtOffset(target, fieldOffset(t, field)); case ObjectField: - return cast(target, fieldOffset(t, field)); + return fieldAtOffset(target, fieldOffset(t, field)); default: abort(t); @@ -3105,7 +3105,7 @@ setStaticLongFieldValueFromReference(MyThread* t, object pair, uint64_t value) ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, fieldClass(t, field)), fieldOffset(t, field)) = value; } @@ -3120,7 +3120,7 @@ setLongFieldValueFromReference(MyThread* t, object pair, object instance, ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(instance, fieldOffset(t, field)) = value; + fieldAtOffset(instance, fieldOffset(t, field)) = value; } void @@ -3160,17 +3160,17 @@ setFieldValue(MyThread* t, object target, object field, uint32_t value) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - cast(target, fieldOffset(t, field)) = value; + fieldAtOffset(target, fieldOffset(t, field)) = value; break; case CharField: case ShortField: - cast(target, fieldOffset(t, field)) = value; + fieldAtOffset(target, fieldOffset(t, field)) = value; break; case FloatField: case IntField: - cast(target, fieldOffset(t, field)) = value; + fieldAtOffset(target, fieldOffset(t, field)) = value; break; default: @@ -8498,11 +8498,11 @@ class ArgumentList { case 'J': case 'D': - addLong(cast(objectArrayBody(t, arguments, index++), 8)); + addLong(fieldAtOffset(objectArrayBody(t, arguments, index++), 8)); break; default: - addInt(cast(objectArrayBody(t, arguments, index++), + addInt(fieldAtOffset(objectArrayBody(t, arguments, index++), BytesPerWord)); break; } diff --git a/src/heap.cpp b/src/heap.cpp index 5c87de8b88..f706bca253 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -80,13 +80,13 @@ markBitAtomic(uintptr_t* map, unsigned i) inline void* get(void* o, unsigned offsetInWords) { - return maskAlignedPointer(cast(o, offsetInWords * BytesPerWord)); + return maskAlignedPointer(fieldAtOffset(o, offsetInWords * BytesPerWord)); } inline void** getp(void* o, unsigned offsetInWords) { - return &cast(o, offsetInWords * BytesPerWord); + return &fieldAtOffset(o, offsetInWords * BytesPerWord); } inline void @@ -862,21 +862,21 @@ inline void* follow(Context* c UNUSED, void* o) { assert(c, wasCollected(c, o)); - return cast(o, 0); + return fieldAtOffset(o, 0); } inline void*& parent(Context* c UNUSED, void* o) { assert(c, wasCollected(c, o)); - return cast(o, BytesPerWord); + return fieldAtOffset(o, BytesPerWord); } inline uintptr_t* bitset(Context* c UNUSED, void* o) { assert(c, wasCollected(c, o)); - return &cast(o, BytesPerWord * 2); + return &fieldAtOffset(o, BytesPerWord * 2); } void @@ -1059,7 +1059,7 @@ copy(Context* c, void* o) } // leave a pointer to the copy in the original - cast(o, 0) = r; + fieldAtOffset(o, 0) = r; return r; } diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index 811382a825..69840abf16 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -228,7 +228,7 @@ inline object get(object o, unsigned offsetInWords) { return static_cast - (mask(cast(o, offsetInWords * BytesPerWord))); + (mask(fieldAtOffset(o, offsetInWords * BytesPerWord))); } unsigned diff --git a/src/interpret.cpp b/src/interpret.cpp index 4a324fd084..cb6adf28d3 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -733,26 +733,26 @@ pushField(Thread* t, object target, object field) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - pushInt(t, cast(target, fieldOffset(t, field))); + pushInt(t, fieldAtOffset(target, fieldOffset(t, field))); break; case CharField: case ShortField: - pushInt(t, cast(target, fieldOffset(t, field))); + pushInt(t, fieldAtOffset(target, fieldOffset(t, field))); break; case FloatField: case IntField: - pushInt(t, cast(target, fieldOffset(t, field))); + pushInt(t, fieldAtOffset(target, fieldOffset(t, field))); break; case DoubleField: case LongField: - pushLong(t, cast(target, fieldOffset(t, field))); + pushLong(t, fieldAtOffset(target, fieldOffset(t, field))); break; case ObjectField: - pushObject(t, cast(target, fieldOffset(t, field))); + pushObject(t, fieldAtOffset(target, fieldOffset(t, field))); break; default: @@ -902,7 +902,7 @@ interpret3(Thread* t, const int base) case arraylength: { object array = popObject(t); if (LIKELY(array)) { - pushInt(t, cast(array, BytesPerWord)); + pushInt(t, fieldAtOffset(array, BytesPerWord)); } else { exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; @@ -2436,17 +2436,17 @@ interpret3(Thread* t, const int base) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - cast(o, fieldOffset(t, field)) = value; + fieldAtOffset(o, fieldOffset(t, field)) = value; break; case CharField: case ShortField: - cast(o, fieldOffset(t, field)) = value; + fieldAtOffset(o, fieldOffset(t, field)) = value; break; case FloatField: case IntField: - cast(o, fieldOffset(t, field)) = value; + fieldAtOffset(o, fieldOffset(t, field)) = value; break; } } else { @@ -2459,7 +2459,7 @@ interpret3(Thread* t, const int base) int64_t value = popLong(t); object o = popObject(t); if (LIKELY(o)) { - cast(o, fieldOffset(t, field)) = value; + fieldAtOffset(o, fieldOffset(t, field)) = value; } else { exception = makeThrowable(t, Machine::NullPointerExceptionType); } @@ -2510,24 +2510,24 @@ interpret3(Thread* t, const int base) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - cast(table, fieldOffset(t, field)) = value; + fieldAtOffset(table, fieldOffset(t, field)) = value; break; case CharField: case ShortField: - cast(table, fieldOffset(t, field)) = value; + fieldAtOffset(table, fieldOffset(t, field)) = value; break; case FloatField: case IntField: - cast(table, fieldOffset(t, field)) = value; + fieldAtOffset(table, fieldOffset(t, field)) = value; break; } } break; case DoubleField: case LongField: { - cast(table, fieldOffset(t, field)) = popLong(t); + fieldAtOffset(table, fieldOffset(t, field)) = popLong(t); } break; case ObjectField: { @@ -2850,11 +2850,11 @@ pushArguments(Thread* t, object this_, const char* spec, object a) case 'J': case 'D': - pushLong(t, cast(objectArrayBody(t, a, index++), 8)); + pushLong(t, fieldAtOffset(objectArrayBody(t, a, index++), 8)); break; default: - pushInt(t, cast(objectArrayBody(t, a, index++), + pushInt(t, fieldAtOffset(objectArrayBody(t, a, index++), BytesPerWord)); break; } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 2a70b10855..3a61046473 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -232,7 +232,7 @@ GetArrayLength(Thread* t, jarray array) { ENTER(t, Thread::ActiveState); - return cast(*array, BytesPerWord); + return fieldAtOffset(*array, BytesPerWord); } uint64_t @@ -271,7 +271,7 @@ newStringUTF(Thread* t, uintptr_t* arguments) return reinterpret_cast (makeLocalReference (t, t->m->classpath->makeString - (t, array, 0, cast(array, BytesPerWord) - 1))); + (t, array, 0, fieldAtOffset(array, BytesPerWord) - 1))); } jstring JNICALL @@ -1532,7 +1532,7 @@ getObjectField(Thread* t, uintptr_t* arguments) ACQUIRE_FIELD_FOR_READ(t, field); return reinterpret_cast - (makeLocalReference(t, cast(*o, fieldOffset(t, field)))); + (makeLocalReference(t, fieldAtOffset(*o, fieldOffset(t, field)))); } jobject JNICALL @@ -1553,7 +1553,7 @@ getBooleanField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast(*o, fieldOffset(t, field)); + return fieldAtOffset(*o, fieldOffset(t, field)); } jboolean JNICALL @@ -1574,7 +1574,7 @@ getByteField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast(*o, fieldOffset(t, field)); + return fieldAtOffset(*o, fieldOffset(t, field)); } jbyte JNICALL @@ -1595,7 +1595,7 @@ getCharField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast(*o, fieldOffset(t, field)); + return fieldAtOffset(*o, fieldOffset(t, field)); } jchar JNICALL @@ -1616,7 +1616,7 @@ getShortField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast(*o, fieldOffset(t, field)); + return fieldAtOffset(*o, fieldOffset(t, field)); } jshort JNICALL @@ -1637,7 +1637,7 @@ getIntField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast(*o, fieldOffset(t, field)); + return fieldAtOffset(*o, fieldOffset(t, field)); } jint JNICALL @@ -1658,7 +1658,7 @@ getLongField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast(*o, fieldOffset(t, field)); + return fieldAtOffset(*o, fieldOffset(t, field)); } jlong JNICALL @@ -1679,7 +1679,7 @@ getFloatField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return floatToBits(cast(*o, fieldOffset(t, field))); + return floatToBits(fieldAtOffset(*o, fieldOffset(t, field))); } jfloat JNICALL @@ -1700,7 +1700,7 @@ getDoubleField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return doubleToBits(cast(*o, fieldOffset(t, field))); + return doubleToBits(fieldAtOffset(*o, fieldOffset(t, field))); } jdouble JNICALL @@ -1747,7 +1747,7 @@ setBooleanField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1772,7 +1772,7 @@ setByteField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1797,7 +1797,7 @@ setCharField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1822,7 +1822,7 @@ setShortField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1847,7 +1847,7 @@ setIntField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1872,7 +1872,7 @@ setLongField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1898,7 +1898,7 @@ setFloatField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1923,7 +1923,7 @@ setDoubleField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast(*o, fieldOffset(t, field)) = v; + fieldAtOffset(*o, fieldOffset(t, field)) = v; return 1; } @@ -1965,7 +1965,7 @@ getStaticObjectField(Thread* t, uintptr_t* arguments) return reinterpret_cast (makeLocalReference - (t, cast + (t, fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)))); } @@ -1990,7 +1990,7 @@ getStaticBooleanField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast + return fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)); } @@ -2015,7 +2015,7 @@ getStaticByteField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast + return fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)); } @@ -2040,7 +2040,7 @@ getStaticCharField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast + return fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)); } @@ -2065,7 +2065,7 @@ getStaticShortField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast + return fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)); } @@ -2090,7 +2090,7 @@ getStaticIntField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast + return fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)); } @@ -2115,7 +2115,7 @@ getStaticLongField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_READ(t, field); - return cast + return fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)); } @@ -2141,7 +2141,7 @@ getStaticFloatField(Thread* t, uintptr_t* arguments) ACQUIRE_FIELD_FOR_READ(t, field); return floatToBits - (cast + (fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field))); } @@ -2167,7 +2167,7 @@ getStaticDoubleField(Thread* t, uintptr_t* arguments) ACQUIRE_FIELD_FOR_READ(t, field); return doubleToBits - (cast + (fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field))); } @@ -2222,7 +2222,7 @@ setStaticBooleanField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; @@ -2251,7 +2251,7 @@ setStaticByteField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; @@ -2280,7 +2280,7 @@ setStaticCharField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; @@ -2309,7 +2309,7 @@ setStaticShortField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; @@ -2338,7 +2338,7 @@ setStaticIntField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; @@ -2367,7 +2367,7 @@ setStaticLongField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; @@ -2397,7 +2397,7 @@ setStaticFloatField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; @@ -2426,7 +2426,7 @@ setStaticDoubleField(Thread* t, uintptr_t* arguments) PROTECT(t, field); ACQUIRE_FIELD_FOR_WRITE(t, field); - cast + fieldAtOffset (classStaticTable(t, jclassVmClass(t, *c)), fieldOffset(t, field)) = v; return 1; diff --git a/src/machine.cpp b/src/machine.cpp index eda7f87259..fb66d5a87d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -924,7 +924,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object value = parseUtf8(t, singletonObject(t, pool, si)); value = t->m->classpath->makeString - (t, value, 0, cast(value, BytesPerWord) - 1); + (t, value, 0, fieldAtOffset(value, BytesPerWord) - 1); value = intern(t, value); set(t, pool, SingletonBody + (i * BytesPerWord), value); @@ -3466,7 +3466,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, object o = reinterpret_cast(t->backupHeap + t->backupHeapIndex); t->backupHeapIndex += ceilingDivide(sizeInBytes, BytesPerWord); - cast(o, 0) = 0; + fieldAtOffset(o, 0) = 0; return o; } else if (UNLIKELY(t->flags & Thread::TracingFlag)) { expect(t, t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) @@ -4670,7 +4670,7 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start) unsigned arrayElementSize = classArrayElementSize(t, class_); unsigned arrayLength = (arrayElementSize ? - cast(o, fixedSize - BytesPerWord) : 0); + fieldAtOffset(o, fixedSize - BytesPerWord) : 0); THREAD_RUNTIME_ARRAY(t, uint32_t, mask, intArrayLength(t, objectMask)); memcpy(RUNTIME_ARRAY_BODY(mask), &intArrayBody(t, objectMask, 0), diff --git a/src/machine.h b/src/machine.h index e972a3be9d..7e75fa0efc 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1611,7 +1611,7 @@ typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*); inline object objectClass(Thread*, object o) { - return maskAlignedPointer(cast(o, 0)); + return maskAlignedPointer(fieldAtOffset(o, 0)); } inline unsigned @@ -1883,18 +1883,18 @@ mark(Thread* t, object o, unsigned offset) inline void set(Thread* t, object target, unsigned offset, object value) { - cast(target, offset) = value; + fieldAtOffset(target, offset) = value; mark(t, target, offset); } inline void setObjectClass(Thread*, object o, object value) { - cast(o, 0) + fieldAtOffset(o, 0) = reinterpret_cast (reinterpret_cast(value) | (reinterpret_cast - (cast(o, 0)) & (~PointerMask))); + (fieldAtOffset(o, 0)) & (~PointerMask))); } inline const char* @@ -2151,7 +2151,7 @@ baseSize(Thread* t, object o, object class_) return ceilingDivide(classFixedSize(t, class_), BytesPerWord) + ceilingDivide(classArrayElementSize(t, class_) - * cast(o, classFixedSize(t, class_) - BytesPerWord), + * fieldAtOffset(o, classFixedSize(t, class_) - BytesPerWord), BytesPerWord); } @@ -2290,7 +2290,7 @@ inline uintptr_t& extendedWord(Thread* t UNUSED, object o, unsigned baseSize) { assert(t, objectExtended(t, o)); - return cast(o, baseSize * BytesPerWord); + return fieldAtOffset(o, baseSize * BytesPerWord); } inline unsigned @@ -2792,7 +2792,7 @@ objectArrayLength(Thread* t UNUSED, object array) { assert(t, classFixedSize(t, objectClass(t, array)) == BytesPerWord * 2); assert(t, classArrayElementSize(t, objectClass(t, array)) == BytesPerWord); - return cast(array, BytesPerWord); + return fieldAtOffset(array, BytesPerWord); } inline object& @@ -2803,7 +2803,7 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index) assert(t, classObjectMask(t, objectClass(t, array)) == classObjectMask(t, arrayBody (t, t->m->types, Machine::ArrayType))); - return cast(array, ArrayBody + (index * BytesPerWord)); + return fieldAtOffset(array, ArrayBody + (index * BytesPerWord)); } unsigned @@ -2839,7 +2839,7 @@ inline bool atomicCompareAndSwapObject(Thread* t, object target, unsigned offset, object old, object new_) { - if (atomicCompareAndSwap(&cast(target, offset), + if (atomicCompareAndSwap(&fieldAtOffset(target, offset), reinterpret_cast(old), reinterpret_cast(new_))) { @@ -3473,7 +3473,7 @@ inline object resolveClassInObject(Thread* t, object loader, object container, unsigned classOffset, bool throw_ = true) { - object o = cast(container, classOffset); + object o = fieldAtOffset(container, classOffset); loadMemoryBarrier(); From 964d0541179fb78a245bd52beeabbf631eb6ebfb Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 10 Feb 2013 17:51:59 -0700 Subject: [PATCH 201/378] move RUNTIME_ARRAY into it's own header --- classpath/jni-util.h | 27 ++------------------------- src/builtin.cpp | 2 ++ src/classpath-avian.cpp | 2 ++ src/classpath-common.h | 2 ++ src/common.h | 20 -------------------- src/compile.cpp | 2 ++ src/compiler.cpp | 2 ++ src/finder.cpp | 2 ++ src/jnienv.cpp | 2 ++ src/machine.cpp | 2 ++ src/main.cpp | 24 ++---------------------- src/process.cpp | 2 ++ src/util/runtime-array.h | 40 ++++++++++++++++++++++++++++++++++++++++ src/x86.cpp | 2 ++ 14 files changed, 64 insertions(+), 67 deletions(-) create mode 100644 src/util/runtime-array.h diff --git a/classpath/jni-util.h b/classpath/jni-util.h index 57e545a14b..a73905fadf 100644 --- a/classpath/jni-util.h +++ b/classpath/jni-util.h @@ -15,6 +15,8 @@ #include "stdlib.h" #include "string.h" +#include "util/runtime-array.h" + #undef JNIEXPORT #if (defined __MINGW32__) || (defined _MSC_VER) @@ -121,30 +123,5 @@ allocate(JNIEnv* e, unsigned size) } return p; } -#ifdef _MSC_VER - -template -class RuntimeArray { - public: - RuntimeArray(unsigned size): - body(static_cast(malloc(size * sizeof(T)))) - { } - - ~RuntimeArray() { - free(body); - } - - T* body; -}; - -# define RUNTIME_ARRAY(type, name, size) RuntimeArray name(size); -# define RUNTIME_ARRAY_BODY(name) name.body - -#else // not _MSC_VER - -# define RUNTIME_ARRAY(type, name, size) type name[size]; -# define RUNTIME_ARRAY_BODY(name) name - -#endif // not _MSC_VER #endif//JNI_UTIL diff --git a/src/builtin.cpp b/src/builtin.cpp index 1edec99bef..eaa66ed101 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -13,6 +13,8 @@ #include "processor.h" #include "util.h" +#include "util/runtime-array.h" + using namespace vm; namespace { diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 09fca657ef..f313bffa01 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -12,6 +12,8 @@ #include "classpath-common.h" #include "process.h" +#include "util/runtime-array.h" + using namespace vm; namespace { diff --git a/src/classpath-common.h b/src/classpath-common.h index dad0fd3559..11c22b913f 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -13,6 +13,8 @@ #include "tokenizer.h" +#include "util/runtime-array.h" + namespace vm { object diff --git a/src/common.h b/src/common.h index 3032bafae7..f401a22ecd 100644 --- a/src/common.h +++ b/src/common.h @@ -226,23 +226,6 @@ alias(void* p, unsigned offset) #ifdef _MSC_VER -template -class RuntimeArray { - public: - RuntimeArray(unsigned size): - body(static_cast(malloc(size * sizeof(T)))) - { } - - ~RuntimeArray() { - free(body); - } - - T* body; -}; - -# define RUNTIME_ARRAY(type, name, size) RuntimeArray name(size); -# define RUNTIME_ARRAY_BODY(name) name.body - inline int vsnprintf(char* dst, size_t size, const char* format, va_list a) { @@ -272,9 +255,6 @@ fopen(const char* name, const char* mode) #else // not _MSC_VER -# define RUNTIME_ARRAY(type, name, size) type name[size]; -# define RUNTIME_ARRAY_BODY(name) name - inline int vsnprintf(char* dst, size_t size, const char* format, va_list a) { diff --git a/src/compile.cpp b/src/compile.cpp index 9e387aff19..51d141e990 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -17,6 +17,8 @@ #include "compiler.h" #include "arch.h" +#include "util/runtime-array.h" + using namespace vm; extern "C" uint64_t diff --git a/src/compiler.cpp b/src/compiler.cpp index a216663de7..90efb622b8 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -12,6 +12,8 @@ #include "assembler.h" #include "target.h" +#include "util/runtime-array.h" + using namespace vm; namespace { diff --git a/src/finder.cpp b/src/finder.cpp index bfe6214a9e..479761c19f 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -14,6 +14,8 @@ #include "finder.h" #include "lzma.h" +#include "util/runtime-array.h" + using namespace vm; namespace { diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 3a61046473..966494320d 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -14,6 +14,8 @@ #include "processor.h" #include "constants.h" +#include "util/runtime-array.h" + using namespace vm; namespace { diff --git a/src/machine.cpp b/src/machine.cpp index fb66d5a87d..cb4f4c066c 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -17,6 +17,8 @@ #include "arch.h" #include "lzma.h" +#include "util/runtime-array.h" + using namespace vm; namespace { diff --git a/src/main.cpp b/src/main.cpp index fe2793c10d..e70555e73e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,8 @@ #include "system.h" #include "finder.h" +#include "util/runtime-array.h" + #if (defined __MINGW32__) || (defined _MSC_VER) # define PATH_SEPARATOR ';' #else @@ -29,28 +31,6 @@ # define and && # define xor ^ -template -class RuntimeArray { - public: - RuntimeArray(unsigned size): - body(static_cast(malloc(size * sizeof(T)))) - { } - - ~RuntimeArray() { - free(body); - } - - T* body; -}; - -# define RUNTIME_ARRAY(type, name, size) RuntimeArray name(size); -# define RUNTIME_ARRAY_BODY(name) name.body - -#else // not _MSC_VER - -# define RUNTIME_ARRAY(type, name, size) type name[size]; -# define RUNTIME_ARRAY_BODY(name) name - #endif // not _MSC_VER #ifdef BOOT_LIBRARY diff --git a/src/process.cpp b/src/process.cpp index ac1c21917e..b13aa7ca4f 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -10,6 +10,8 @@ #include "process.h" +#include "util/runtime-array.h" + using namespace vm; namespace { diff --git a/src/util/runtime-array.h b/src/util/runtime-array.h new file mode 100644 index 0000000000..378718708d --- /dev/null +++ b/src/util/runtime-array.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2012, 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 UTIL_RUNTIME_ARRAY_H +#define UTIL_RUNTIME_ARRAY_H + +#ifdef _MSC_VER + +template +class RuntimeArray { + public: + RuntimeArray(unsigned size): + body(static_cast(malloc(size * sizeof(T)))) + { } + + ~RuntimeArray() { + free(body); + } + + T* body; +}; + +# define RUNTIME_ARRAY(type, name, size) RuntimeArray name(size); +# define RUNTIME_ARRAY_BODY(name) name.body + +#else // not _MSC_VER + +# define RUNTIME_ARRAY(type, name, size) type name[size]; +# define RUNTIME_ARRAY_BODY(name) name + +#endif + +#endif \ No newline at end of file diff --git a/src/x86.cpp b/src/x86.cpp index fc92e661f2..3a3942dca7 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -13,6 +13,8 @@ #include "target.h" #include "vector.h" +#include "util/runtime-array.h" + #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) #define CAST_BRANCH(x) reinterpret_cast(x) From 68776e5d73ac2545bb6571b7702013bb09a731be Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 10 Feb 2013 18:55:38 -0700 Subject: [PATCH 202/378] move all codegen source in to codegen/ dir --- makefile | 6 +++--- src/{vector.h => alloc-vector.h} | 0 src/{arm.cpp => codegen/arm/assembler.cpp} | 2 +- src/{ => codegen}/assembler.h | 0 src/{ => codegen}/compiler.cpp | 0 src/{ => codegen}/compiler.h | 0 src/{powerpc.cpp => codegen/powerpc/assembler.cpp} | 2 +- src/{x86.cpp => codegen/x86/assembler.cpp} | 5 +++-- src/compile.cpp | 6 +++--- src/processor.h | 3 ++- src/target.h | 1 + 11 files changed, 14 insertions(+), 11 deletions(-) rename src/{vector.h => alloc-vector.h} (100%) rename src/{arm.cpp => codegen/arm/assembler.cpp} (99%) rename src/{ => codegen}/assembler.h (100%) rename src/{ => codegen}/compiler.cpp (100%) rename src/{ => codegen}/compiler.h (100%) rename src/{powerpc.cpp => codegen/powerpc/assembler.cpp} (99%) rename src/{x86.cpp => codegen/x86/assembler.cpp} (99%) diff --git a/makefile b/makefile index b3cbd88a57..bdce03c7c3 100755 --- a/makefile +++ b/makefile @@ -629,7 +629,7 @@ generated-code = \ $(build)/type-name-initializations.cpp \ $(build)/type-maps.cpp -vm-depends := $(generated-code) $(wildcard $(src)/*.h) +vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) vm-sources = \ $(src)/$(system).cpp \ @@ -658,8 +658,8 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) ifeq ($(process),compile) vm-sources += \ - $(src)/compiler.cpp \ - $(src)/$(target-asm).cpp + $(src)/codegen/compiler.cpp \ + $(src)/codegen/$(target-asm)/assembler.cpp vm-asm-sources += $(src)/compile-$(asm).S endif diff --git a/src/vector.h b/src/alloc-vector.h similarity index 100% rename from src/vector.h rename to src/alloc-vector.h diff --git a/src/arm.cpp b/src/codegen/arm/assembler.cpp similarity index 99% rename from src/arm.cpp rename to src/codegen/arm/assembler.cpp index 8809cdb479..e0e3751839 100644 --- a/src/arm.cpp +++ b/src/codegen/arm/assembler.cpp @@ -9,7 +9,7 @@ details. */ #include "assembler.h" -#include "vector.h" +#include "alloc-vector.h" #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) diff --git a/src/assembler.h b/src/codegen/assembler.h similarity index 100% rename from src/assembler.h rename to src/codegen/assembler.h diff --git a/src/compiler.cpp b/src/codegen/compiler.cpp similarity index 100% rename from src/compiler.cpp rename to src/codegen/compiler.cpp diff --git a/src/compiler.h b/src/codegen/compiler.h similarity index 100% rename from src/compiler.h rename to src/codegen/compiler.h diff --git a/src/powerpc.cpp b/src/codegen/powerpc/assembler.cpp similarity index 99% rename from src/powerpc.cpp rename to src/codegen/powerpc/assembler.cpp index 1c34c85291..d70cb36bef 100644 --- a/src/powerpc.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -9,7 +9,7 @@ details. */ #include "assembler.h" -#include "vector.h" +#include "alloc-vector.h" #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) diff --git a/src/x86.cpp b/src/codegen/x86/assembler.cpp similarity index 99% rename from src/x86.cpp rename to src/codegen/x86/assembler.cpp index 3a3942dca7..4270207eea 100644 --- a/src/x86.cpp +++ b/src/codegen/x86/assembler.cpp @@ -9,9 +9,10 @@ details. */ #include "environment.h" -#include "assembler.h" #include "target.h" -#include "vector.h" +#include "alloc-vector.h" + +#include "codegen/assembler.h" #include "util/runtime-array.h" diff --git a/src/compile.cpp b/src/compile.cpp index 51d141e990..1a17e62e1b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -10,11 +10,11 @@ #include "machine.h" #include "util.h" -#include "vector.h" +#include "alloc-vector.h" #include "process.h" -#include "assembler.h" #include "target.h" -#include "compiler.h" +#include "codegen/assembler.h" +#include "codegen/compiler.h" #include "arch.h" #include "util/runtime-array.h" diff --git a/src/processor.h b/src/processor.h index 6da91dddce..ab9d68e1aa 100644 --- a/src/processor.h +++ b/src/processor.h @@ -17,10 +17,11 @@ #include "bootimage.h" #include "heapwalk.h" #include "zone.h" -#include "assembler.h" namespace vm { +class DelayedPromise; + class Processor { public: class StackWalker; diff --git a/src/target.h b/src/target.h index 996d76348f..f75e575eef 100644 --- a/src/target.h +++ b/src/target.h @@ -12,6 +12,7 @@ #define TARGET_H #include "target-fields.h" +#include "common.h" namespace vm { From dc943c250a249f3e75614f95fca769d9ea9ba934 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Feb 2013 08:15:39 -0700 Subject: [PATCH 203/378] delay incrementing Thread::criticalLevel until after entering ActiveState If we increment the value while we're still in IdleState, another thread may try to GC before we are able to enter ActiveState, which will lead to an assertion failure when the footprint function is called. --- src/jnienv.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 2a70b10855..e512b18066 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -160,10 +160,12 @@ GetStringRegion(Thread* t, jstring s, jsize start, jsize length, jchar* dst) const jchar* JNICALL GetStringCritical(Thread* t, jstring s, jboolean* isCopy) { - if ((t->criticalLevel ++) == 0) { + if (t->criticalLevel == 0) { enter(t, Thread::ActiveState); } + ++ t->criticalLevel; + if (isCopy) { *isCopy = true; } @@ -3141,9 +3143,11 @@ SetDoubleArrayRegion(Thread* t, jdoubleArray array, jint offset, jint length, void* JNICALL GetPrimitiveArrayCritical(Thread* t, jarray array, jboolean* isCopy) { - if ((t->criticalLevel ++) == 0) { + if (t->criticalLevel == 0) { enter(t, Thread::ActiveState); } + + ++ t->criticalLevel; if (isCopy) { *isCopy = true; From d1a7b660856ab9f3827604d0d09e565cf7d9341a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Feb 2013 08:22:21 -0700 Subject: [PATCH 204/378] don't specify -Wl,-rpath argument on Darwin or Windows It remains to be seen what form that argument should take on those operating systems; for now, it only causes trouble, so we'll just leave it out. --- makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index fe83a35381..362d4a756d 100755 --- a/makefile +++ b/makefile @@ -239,6 +239,8 @@ so-suffix = .so shared = -shared +rpath = -Wl,-rpath=\$$ORIGIN + no-error = -Wno-error openjdk-extra-cflags = -fvisibility=hidden @@ -391,6 +393,7 @@ ifeq ($(platform),darwin) strip-all = -S -x so-suffix = .dylib shared = -dynamiclib + rpath = sdk-dir = $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs @@ -450,6 +453,7 @@ ifeq ($(platform),windows) so-prefix = so-suffix = .dll exe-suffix = .exe + rpath = lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mwindows -mconsole cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 @@ -1245,7 +1249,7 @@ ifdef msvc -MANIFESTFILE:$(@).manifest $(mt) -manifest $(@).manifest -outputresource:"$(@);1" else - $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) -Wl,-rpath=\$$ORIGIN -z origin -o $(@) + $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) $(rpath) -z origin -o $(@) endif $(strip) $(strip-all) $(@) From 752d02e7786b807185e3f4cd254ee988c01f830f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Feb 2013 09:22:17 -0700 Subject: [PATCH 205/378] make bootimage-object depend on openjdk-jar-dep This ensures that the OpenJDK classes have been extracted prior to bootimage creation. --- makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index f7da20fd08..6106d2b08b 100755 --- a/makefile +++ b/makefile @@ -1476,7 +1476,8 @@ else $(ranlib) $(@) endif -$(bootimage-object) $(codeimage-object): $(bootimage-generator) +$(bootimage-object) $(codeimage-object): $(bootimage-generator) \ + $(openjdk-jar-dep) @echo "generating bootimage and codeimage binaries from $(classpath-build) using $(<)" $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ -bootimage-symbols $(bootimage-symbols) \ From 937343d0d3967a176899f7c1a03294a0f36d77fb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Feb 2013 09:27:47 -0700 Subject: [PATCH 206/378] don't specify -Wl,-rpath argument on Darwin or Windows (take 2) --- makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index bfe755c23a..7ca50ab600 100755 --- a/makefile +++ b/makefile @@ -267,7 +267,7 @@ build-ld = $(build-cc) static = -static shared = -shared -rpath = -Wl,-rpath=\$$ORIGIN +rpath = -Wl,-rpath=\$$ORIGIN -Wl,-z,origin no-error = -Wno-error @@ -1573,7 +1573,7 @@ ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif else - $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) $(rpath) -z origin -o $(@) + $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) $(rpath) -o $(@) endif $(strip) $(strip-all) $(@) From 3812d012a35b2af495561beac20adfd92b086133 Mon Sep 17 00:00:00 2001 From: Damjan Jovanovic Date: Tue, 12 Feb 2013 11:00:52 -0700 Subject: [PATCH 207/378] update documentation to indicate that LD_LIBRARY_PATH is not (always) needed --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c09ec39db6..1e35318627 100644 --- a/README.md +++ b/README.md @@ -249,12 +249,11 @@ where OpenJDK is installed, e.g.: This will build Avian as a conventional JVM (e.g. libjvm.so) which loads its boot class library and native libraries (e.g. libjava.so) -from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. To run an -application in this configuration, you'll need to make sure the VM is -in your library search path. For example: +from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. In this configuration, +OpenJDK needs to remain installed for Avian to work, and you can run +applications like this: - $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ - build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ + $ build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ com.example.MyApplication Alternatively, you can enable a stand-alone build using OpenJDK by From f7b49ddb06cf7d24c9a9622c11076fa68e3b32db Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 12 Feb 2013 08:15:30 -0700 Subject: [PATCH 208/378] allow codegen targets (Architectures and Assemblers) to co-exist The primary motivation behind this is to allow all the different Assemblers to be built at once, on a single machine. This should dramatically reduce the time required to make sure that a particular change doesn't break the build for one of the not-so-common architectures (arm, powerpc) Simply pass "codegen-targets=all" to make to compile all src/codegen//assembler.cpp. Note that while these architectures are built, they will not be fully- functional. Certain stuff is assumed to be the same across the entire build (such as TargetBytesPerWord), but this isn't the case anymore. --- makefile | 18 ++++++++++++++- src/codegen/arm/assembler.cpp | 24 ++++++++++---------- src/codegen/assembler.h | 11 +++------ src/codegen/powerpc/assembler.cpp | 25 ++++++++++----------- src/codegen/targets.cpp | 37 +++++++++++++++++++++++++++++++ src/codegen/targets.h | 28 +++++++++++++++++++++++ src/codegen/x86/assembler.cpp | 25 ++++++++++----------- src/compile.cpp | 7 +++--- 8 files changed, 125 insertions(+), 50 deletions(-) create mode 100644 src/codegen/targets.cpp create mode 100644 src/codegen/targets.h diff --git a/makefile b/makefile index bdce03c7c3..e679fd7d97 100755 --- a/makefile +++ b/makefile @@ -25,6 +25,8 @@ bootimage-platform = \ $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) platform = $(bootimage-platform) +codegen-targets = native + mode = fast process = compile @@ -49,6 +51,9 @@ endif ifeq ($(continuations),true) options := $(options)-continuations endif +ifeq ($(codegen-targets),all) + options := $(options)-all +endif root := $(shell (cd .. && pwd)) build = build/$(platform)-$(arch)$(options) @@ -659,7 +664,18 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) ifeq ($(process),compile) vm-sources += \ $(src)/codegen/compiler.cpp \ - $(src)/codegen/$(target-asm)/assembler.cpp + $(src)/codegen/targets.cpp + + ifeq ($(codegen-targets),native) + vm-sources += \ + $(src)/codegen/$(target-asm)/assembler.cpp + endif + ifeq ($(codegen-targets),all) + vm-sources += \ + $(src)/codegen/x86/assembler.cpp \ + $(src)/codegen/arm/assembler.cpp \ + $(src)/codegen/powerpc/assembler.cpp + endif vm-asm-sources += $(src)/compile-$(asm).S endif diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index e0e3751839..bb7328726e 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "assembler.h" +#include "codegen/assembler.h" #include "alloc-vector.h" #define CAST1(x) reinterpret_cast(x) @@ -2500,6 +2500,8 @@ class MyArchitecture: public Assembler::Architecture { } } + virtual Assembler* makeAssembler(Allocator* allocator, Zone* zone); + virtual void acquire() { ++ referenceCount; } @@ -2896,22 +2898,20 @@ class MyAssembler: public Assembler { MyArchitecture* arch_; }; +Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { + return new(zone) MyAssembler(this->con.s, allocator, zone, this); +} + } // namespace -namespace vm { +namespace avian { +namespace codegen { Assembler::Architecture* -makeArchitecture(System* system, bool) +makeArchitectureArm(System* system, bool) { return new (allocate(system, sizeof(MyArchitecture))) MyArchitecture(system); } -Assembler* -makeAssembler(System* system, Allocator* allocator, Zone* zone, - Assembler::Architecture* architecture) -{ - return new(zone) MyAssembler(system, allocator, zone, - static_cast(architecture)); -} - -} // namespace vm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/assembler.h b/src/codegen/assembler.h index d2ba2caf5d..fbe03b70ac 100644 --- a/src/codegen/assembler.h +++ b/src/codegen/assembler.h @@ -408,7 +408,9 @@ class Assembler { (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) = 0; + unsigned cSize, uint8_t* cTypeMask, uint64_t* cRegisterMask) = 0; + + virtual Assembler* makeAssembler(Allocator*, Zone*) = 0; virtual void acquire() = 0; virtual void release() = 0; @@ -466,13 +468,6 @@ class Assembler { virtual void dispose() = 0; }; -Assembler::Architecture* -makeArchitecture(System* system, bool useNativeFeatures); - -Assembler* -makeAssembler(System* system, Allocator* allocator, Zone* zone, - Assembler::Architecture* architecture); - } // namespace vm #endif//ASSEMBLER_H diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index d70cb36bef..415ef3fa54 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "assembler.h" +#include "codegen/assembler.h" #include "alloc-vector.h" #define CAST1(x) reinterpret_cast(x) @@ -2446,6 +2446,8 @@ class MyArchitecture: public Assembler::Architecture { } } + virtual Assembler* makeAssembler(Allocator* allocator, Zone* zone); + virtual void acquire() { ++ referenceCount; } @@ -2858,23 +2860,20 @@ class MyAssembler: public Assembler { MyArchitecture* arch_; }; +Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { + return new(zone) MyAssembler(this->c.s, allocator, zone, this); +} + } // namespace -namespace vm { +namespace avian { +namespace codegen { Assembler::Architecture* -makeArchitecture(System* system, bool) +makeArchitecturePowerpc(System* system, bool) { return new (allocate(system, sizeof(MyArchitecture))) MyArchitecture(system); } -Assembler* -makeAssembler(System* system, Allocator* allocator, Zone* zone, - Assembler::Architecture* architecture) -{ - return - new(zone) MyAssembler(system, allocator, zone, - static_cast(architecture)); -} - -} // namespace vm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/targets.cpp b/src/codegen/targets.cpp new file mode 100644 index 0000000000..64b5a0f630 --- /dev/null +++ b/src/codegen/targets.cpp @@ -0,0 +1,37 @@ +/* Copyright (c) 2008-2012, 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 "codegen/targets.h" +#include "environment.h" + +namespace avian { +namespace codegen { + +vm::Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures UNUSED) { +#ifndef AVIAN_TARGET_ARCH + #error "Must specify native target!" +#endif + +#if AVIAN_TARGET_ARCH == AVIAN_ARCH_UNKNOWN + system->abort(); + return 0; +#elif (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64) + return makeArchitectureX86(system, useNativeFeatures); +#elif AVIAN_TARGET_ARCH == AVIAN_ARCH_ARM + return makeArchitectureArm(system, useNativeFeatures); +#elif AVIAN_TARGET_ARCH == AVIAN_ARCH_POWERPC + return makeArchitecturePowerpc(system, useNativeFeatures); +#else + #error "Unsupported codegen target" +#endif +} + +} // namespace codegen +} // namespace avian diff --git a/src/codegen/targets.h b/src/codegen/targets.h new file mode 100644 index 0000000000..c4070b4641 --- /dev/null +++ b/src/codegen/targets.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_TARGETS_H +#define AVIAN_CODEGEN_TARGETS_H + +#include "codegen/assembler.h" + +namespace avian { +namespace codegen { + +vm::Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures); + +vm::Assembler::Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures); +vm::Assembler::Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures); +vm::Assembler::Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures); + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_TARGETS_H diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 4270207eea..e1f107dc32 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -3387,6 +3387,8 @@ class MyArchitecture: public Assembler::Architecture { } } + virtual Assembler* makeAssembler(Allocator* allocator, Zone* zone); + virtual void acquire() { ++ referenceCount; } @@ -3732,26 +3734,23 @@ class MyAssembler: public Assembler { MyArchitecture* arch_; }; +Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { + return + new(zone) MyAssembler(c.s, allocator, zone, this); +} + } // namespace local } // namespace -namespace vm { +namespace avian { +namespace codegen { -Assembler::Architecture* -makeArchitecture(System* system, bool useNativeFeatures) +Assembler::Architecture* makeArchitectureX86(System* system, bool useNativeFeatures) { return new (allocate(system, sizeof(local::MyArchitecture))) local::MyArchitecture(system, useNativeFeatures); } -Assembler* -makeAssembler(System* system, Allocator* allocator, Zone* zone, - Assembler::Architecture* architecture) -{ - return - new(zone) local::MyAssembler(system, allocator, zone, - static_cast(architecture)); -} - -} // namespace vm +} // namespace codegen +} // namespace avian diff --git a/src/compile.cpp b/src/compile.cpp index 1a17e62e1b..bae11823d5 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -15,6 +15,7 @@ #include "target.h" #include "codegen/assembler.h" #include "codegen/compiler.h" +#include "codegen/targets.h" #include "arch.h" #include "util/runtime-array.h" @@ -264,7 +265,7 @@ class MyThread: public Thread { reference(0), arch(parent ? parent->arch - : makeArchitecture(m->system, useNativeFeatures)), + : avian::codegen::makeArchitectureNative(m->system, useNativeFeatures)), transition(0), traceContext(0), stackLimit(0), @@ -1225,7 +1226,7 @@ class Context { Context(MyThread* t, BootContext* bootContext, object method): thread(t), zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes), - assembler(makeAssembler(t->m->system, t->m->heap, &zone, t->arch)), + assembler(t->arch->makeAssembler(t->m->heap, &zone)), client(t), compiler(makeCompiler(t->m->system, assembler, &zone, &client)), method(method), @@ -1251,7 +1252,7 @@ class Context { Context(MyThread* t): thread(t), zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes), - assembler(makeAssembler(t->m->system, t->m->heap, &zone, t->arch)), + assembler(t->arch->makeAssembler(t->m->heap, &zone)), client(t), compiler(0), method(0), From aacfb9ec858d948c6743117ec97d38a7c9575d31 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 12 Feb 2013 12:18:09 -0700 Subject: [PATCH 209/378] fix unused function warnings in codegen/powerpc/assembler.cpp when building with clang --- src/codegen/powerpc/assembler.cpp | 50 ++++++++++++++----------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 415ef3fa54..6517e59264 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -23,26 +23,26 @@ namespace { namespace isa { // INSTRUCTION FORMATS inline int D(int op, int rt, int ra, int d) { return op<<26|rt<<21|ra<<16|(d & 0xFFFF); } -inline int DS(int op, int rt, int ra, int ds, int xo) { return op<<26|rt<<21|ra<<16|ds<<2|xo; } +// inline int DS(int op, int rt, int ra, int ds, int xo) { return op<<26|rt<<21|ra<<16|ds<<2|xo; } inline int I(int op, int li, int aa, int lk) { return op<<26|(li & 0x3FFFFFC)|aa<<1|lk; } inline int B(int op, int bo, int bi, int bd, int aa, int lk) { return op<<26|bo<<21|bi<<16|(bd & 0xFFFC)|aa<<1|lk; } -inline int SC(int op, int lev) { return op<<26|lev<<5|2; } +// inline int SC(int op, int lev) { return op<<26|lev<<5|2; } inline int X(int op, int rt, int ra, int rb, int xo, int rc) { return op<<26|rt<<21|ra<<16|rb<<11|xo<<1|rc; } inline int XL(int op, int bt, int ba, int bb, int xo, int lk) { return op<<26|bt<<21|ba<<16|bb<<11|xo<<1|lk; } inline int XFX(int op, int rt, int spr, int xo) { return op<<26|rt<<21|((spr >> 5) | ((spr << 5) & 0x3E0))<<11|xo<<1; } -inline int XFL(int op, int flm, int frb, int xo, int rc) { return op<<26|flm<<17|frb<<11|xo<<1|rc; } -inline int XS(int op, int rs, int ra, int sh, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|xo<<2|sh2<<1|rc; } +// inline int XFL(int op, int flm, int frb, int xo, int rc) { return op<<26|flm<<17|frb<<11|xo<<1|rc; } +// inline int XS(int op, int rs, int ra, int sh, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|xo<<2|sh2<<1|rc; } inline int XO(int op, int rt, int ra, int rb, int oe, int xo, int rc) { return op<<26|rt<<21|ra<<16|rb<<11|oe<<10|xo<<1|rc; } -inline int A(int op, int frt, int fra, int frb, int frc, int xo, int rc) { return op<<26|frt<<21|fra<<16|frb<<11|frc<<6|xo<<1|rc; } +// inline int A(int op, int frt, int fra, int frb, int frc, int xo, int rc) { return op<<26|frt<<21|fra<<16|frb<<11|frc<<6|xo<<1|rc; } inline int M(int op, int rs, int ra, int rb, int mb, int me, int rc) { return op<<26|rs<<21|ra<<16|rb<<11|mb<<6|me<<1|rc; } -inline int MD(int op, int rs, int ra, int sh, int mb, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|mb<<5|xo<<2|sh2<<1|rc; } -inline int MDS(int op, int rs, int ra, int rb, int mb, int xo, int rc) { return op<<26|rs<<21|ra<<16|rb<<11|mb<<5|xo<<1|rc; } +// inline int MD(int op, int rs, int ra, int sh, int mb, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|mb<<5|xo<<2|sh2<<1|rc; } +// inline int MDS(int op, int rs, int ra, int rb, int mb, int xo, int rc) { return op<<26|rs<<21|ra<<16|rb<<11|mb<<5|xo<<1|rc; } // INSTRUCTIONS inline int lbz(int rt, int ra, int i) { return D(34, rt, ra, i); } inline int lbzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 87, 0); } inline int lha(int rt, int ra, int i) { return D(42, rt, ra, i); } inline int lhax(int rt, int ra, int rb) { return X(31, rt, ra, rb, 343, 0); } -inline int lhz(int rt, int ra, int i) { return D(40, rt, ra, i); } +// inline int lhz(int rt, int ra, int i) { return D(40, rt, ra, i); } inline int lhzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 279, 0); } inline int lwz(int rt, int ra, int i) { return D(32, rt, ra, i); } inline int lwzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 23, 0); } @@ -66,13 +66,13 @@ inline int subfe(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 136, 0); inline int subfic(int rt, int ra, int i) { return D(8, rt, ra, i); } inline int subfze(int rt, int ra) { return XO(31, rt, ra, 0, 0, 200, 0); } inline int mullw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 235, 0); } -inline int mulhw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 75, 0); } +// inline int mulhw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 75, 0); } inline int mulhwu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 11, 0); } -inline int mulli(int rt, int ra, int i) { return D(7, rt, ra, i); } +// inline int mulli(int rt, int ra, int i) { return D(7, rt, ra, i); } inline int divw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 491, 0); } -inline int divwu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 459, 0); } -inline int divd(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 489, 0); } -inline int divdu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 457, 0); } +// inline int divwu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 459, 0); } +// inline int divd(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 489, 0); } +// inline int divdu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 457, 0); } inline int neg(int rt, int ra) { return XO(31, rt, ra, 0, 0, 104, 0); } inline int and_(int rt, int ra, int rb) { return X(31, ra, rt, rb, 28, 0); } inline int andi(int rt, int ra, int i) { return D(28, ra, rt, i); } @@ -86,7 +86,7 @@ inline int xoris(int rt, int ra, int i) { return D(27, rt, ra, i); } inline int rlwinm(int rt, int ra, int i, int mb, int me) { return M(21, ra, rt, i, mb, me, 0); } inline int rlwimi(int rt, int ra, int i, int mb, int me) { return M(20, ra, rt, i, mb, me, 0); } inline int slw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 24, 0); } -inline int sld(int rt, int ra, int rb) { return X(31, ra, rt, rb, 27, 0); } +// inline int sld(int rt, int ra, int rb) { return X(31, ra, rt, rb, 27, 0); } inline int srw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 536, 0); } inline int sraw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 792, 0); } inline int srawi(int rt, int ra, int sh) { return X(31, ra, rt, sh, 824, 0); } @@ -109,10 +109,10 @@ inline int li(int rt, int i) { return addi(rt, 0, i); } inline int lis(int rt, int i) { return addis(rt, 0, i); } inline int slwi(int rt, int ra, int i) { return rlwinm(rt, ra, i, 0, 31-i); } inline int srwi(int rt, int ra, int i) { return rlwinm(rt, ra, 32-i, i, 31); } -inline int sub(int rt, int ra, int rb) { return subf(rt, rb, ra); } -inline int subc(int rt, int ra, int rb) { return subfc(rt, rb, ra); } -inline int subi(int rt, int ra, int i) { return addi(rt, ra, -i); } -inline int subis(int rt, int ra, int i) { return addis(rt, ra, -i); } +// inline int sub(int rt, int ra, int rb) { return subf(rt, rb, ra); } +// inline int subc(int rt, int ra, int rb) { return subfc(rt, rb, ra); } +// inline int subi(int rt, int ra, int i) { return addi(rt, ra, -i); } +// inline int subis(int rt, int ra, int i) { return addis(rt, ra, -i); } inline int mr(int rt, int ra) { return or_(rt, ra, ra); } inline int mflr(int rx) { return mfspr(rx, 8); } inline int mtlr(int rx) { return mtspr(8, rx); } @@ -136,12 +136,12 @@ inline int trap() { return 0x7fe00008; } // todo: macro-ify const int64_t MASK_LO32 = 0x0ffffffff; const int MASK_LO16 = 0x0ffff; const int MASK_LO8 = 0x0ff; -inline int lo32(int64_t i) { return (int)(i & MASK_LO32); } -inline int hi32(int64_t i) { return lo32(i >> 32); } +// inline int lo32(int64_t i) { return (int)(i & MASK_LO32); } +// inline int hi32(int64_t i) { return lo32(i >> 32); } inline int lo16(int64_t i) { return (int)(i & MASK_LO16); } inline int hi16(int64_t i) { return lo16(i >> 16); } -inline int lo8(int64_t i) { return (int)(i & MASK_LO8); } -inline int hi8(int64_t i) { return lo8(i >> 8); } +// inline int lo8(int64_t i) { return (int)(i & MASK_LO8); } +// inline int hi8(int64_t i) { return lo8(i >> 8); } inline int ha16(int32_t i) { return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; @@ -634,12 +634,6 @@ isBranch(TernaryOperation op) return op > FloatMin; } -bool -isFloatBranch(TernaryOperation op) -{ - return op > JumpIfNotEqual; -} - inline unsigned index(ArchitectureContext* c UNUSED, TernaryOperation operation, From d7f088c9e7bf64041fe88d7520454aa368e8307c Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 11 Feb 2013 08:07:46 -0700 Subject: [PATCH 210/378] adjust package structure in codegen (vm -> avian::codegen and avian::codegen::lir) The eventual intent with the lir namespace is to formalize some of the important bits of Assembler interface, to be tested, debug-printed, and potentially, serialized. Also, group arguments to apply(...) in OperandInfos --- src/codegen/arm/assembler.cpp | 872 ++++++++++---------- src/codegen/assembler.h | 341 +------- src/codegen/compiler.cpp | 791 +++++++++--------- src/codegen/compiler.h | 14 +- src/codegen/lir-ops.inc.cpp | 62 ++ src/codegen/lir.cpp | 35 + src/codegen/lir.h | 174 ++++ src/codegen/powerpc/assembler.cpp | 783 +++++++++--------- src/codegen/promise.h | 159 ++++ src/codegen/targets.cpp | 2 +- src/codegen/targets.h | 8 +- src/codegen/x86/assembler.cpp | 1235 ++++++++++++++--------------- src/compile.cpp | 416 +++++----- src/processor.h | 10 +- 14 files changed, 2530 insertions(+), 2372 deletions(-) create mode 100644 src/codegen/lir-ops.inc.cpp create mode 100644 src/codegen/lir.cpp create mode 100644 src/codegen/lir.h create mode 100644 src/codegen/promise.h diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index 849a53b0cd..ecaad31007 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -20,6 +20,7 @@ #define CAST_BRANCH(x) reinterpret_cast(x) using namespace vm; +using namespace avian::codegen; namespace local { @@ -208,14 +209,14 @@ const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32; // making the following const somehow breaks debug symbol output in GDB /* const */ uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32; -inline bool isFpr(Assembler::Register* reg) { +inline bool isFpr(lir::Register* reg) { return reg->low >= N_GPRS; } inline int fpr64(int reg) { return reg - N_GPRS; } -inline int fpr64(Assembler::Register* reg) { return fpr64(reg->low); } +inline int fpr64(lir::Register* reg) { return fpr64(reg->low); } inline int fpr32(int reg) { return fpr64(reg) << 1; } -inline int fpr32(Assembler::Register* reg) { return fpr64(reg) << 1; } +inline int fpr32(lir::Register* reg) { return fpr64(reg) << 1; } const unsigned FrameHeaderSize = 1; @@ -310,33 +311,33 @@ class Task { typedef void (*OperationType)(Context*); -typedef void (*UnaryOperationType)(Context*, unsigned, Assembler::Operand*); +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); typedef void (*BinaryOperationType) -(Context*, unsigned, Assembler::Operand*, unsigned, Assembler::Operand*); +(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); typedef void (*TernaryOperationType) -(Context*, unsigned, Assembler::Operand*, Assembler::Operand*, - Assembler::Operand*); +(Context*, unsigned, lir::Operand*, lir::Operand*, + lir::Operand*); typedef void (*BranchOperationType) -(Context*, TernaryOperation, unsigned, Assembler::Operand*, - Assembler::Operand*, Assembler::Operand*); +(Context*, lir::TernaryOperation, unsigned, lir::Operand*, + lir::Operand*, lir::Operand*); class ArchitectureContext { public: ArchitectureContext(System* s): s(s) { } System* s; - OperationType operations[OperationCount]; - UnaryOperationType unaryOperations[UnaryOperationCount - * OperandTypeCount]; + OperationType operations[lir::OperationCount]; + UnaryOperationType unaryOperations[lir::UnaryOperationCount + * lir::OperandTypeCount]; BinaryOperationType binaryOperations - [BinaryOperationCount * OperandTypeCount * OperandTypeCount]; + [lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; TernaryOperationType ternaryOperations - [NonBranchTernaryOperationCount * OperandTypeCount]; + [lir::NonBranchTernaryOperationCount * lir::OperandTypeCount]; BranchOperationType branchOperations - [BranchOperationCount * OperandTypeCount * OperandTypeCount]; + [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; }; inline void NO_RETURN @@ -469,49 +470,37 @@ appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) } inline unsigned -index(ArchitectureContext*, UnaryOperation operation, OperandType operand) +index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) { - return operation + (UnaryOperationCount * operand); + return operation + (lir::UnaryOperationCount * operand); } inline unsigned index(ArchitectureContext*, - BinaryOperation operation, - OperandType operand1, - OperandType operand2) + lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2) { return operation - + (BinaryOperationCount * operand1) - + (BinaryOperationCount * OperandTypeCount * operand2); -} - -bool -isBranch(TernaryOperation op) -{ - return op > FloatMin; -} - -bool UNUSED -isFloatBranch(TernaryOperation op) -{ - return op > JumpIfNotEqual; + + (lir::BinaryOperationCount * operand1) + + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); } inline unsigned index(ArchitectureContext* con UNUSED, - TernaryOperation operation, - OperandType operand1) + lir::TernaryOperation operation, + lir::OperandType operand1) { assert(con, not isBranch(operation)); - return operation + (NonBranchTernaryOperationCount * operand1); + return operation + (lir::NonBranchTernaryOperationCount * operand1); } unsigned -branchIndex(ArchitectureContext* con UNUSED, OperandType operand1, - OperandType operand2) +branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1, + lir::OperandType operand2) { - return operand1 + (OperandTypeCount * operand2); + return operand1 + (lir::OperandTypeCount * operand2); } // BEGIN OPERATION COMPILERS @@ -533,23 +522,23 @@ inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } -inline int64_t getValue(Assembler::Constant* con) { +inline int64_t getValue(lir::Constant* con) { return con->value->value(); } -inline Assembler::Register makeTemp(Context* con) { - Assembler::Register tmp(newTemp(con)); +inline lir::Register makeTemp(Context* con) { + lir::Register tmp(newTemp(con)); return tmp; } -inline Assembler::Register makeTemp64(Context* con) { - Assembler::Register tmp(newTemp(con), newTemp(con)); +inline lir::Register makeTemp64(Context* con) { + lir::Register tmp(newTemp(con), newTemp(con)); return tmp; } -inline void freeTemp(Context* con, const Assembler::Register& tmp) { - if (tmp.low != NoRegister) freeTemp(con, tmp.low); - if (tmp.high != NoRegister) freeTemp(con, tmp.high); +inline void freeTemp(Context* con, const lir::Register& tmp) { + if (tmp.low != lir::NoRegister) freeTemp(con, tmp.low); + if (tmp.high != lir::NoRegister) freeTemp(con, tmp.high); } inline void @@ -559,16 +548,16 @@ write4(uint8_t* dst, uint32_t v) } void -andC(Context* con, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst); +andC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); -void shiftLeftR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) +void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); ResolvedPromise maskPromise(0x3F); - Assembler::Constant mask(&maskPromise); - Assembler::Register dst(tmp3); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp3); andC(con, 4, &mask, a, &dst); emit(con, lsl(tmp1, b->high, tmp3)); emit(con, rsbi(tmp2, tmp3, 32)); @@ -581,8 +570,8 @@ void shiftLeftR(Context* con, unsigned size, Assembler::Register* a, Assembler:: } else { int tmp = newTemp(con); ResolvedPromise maskPromise(0x1F); - Assembler::Constant mask(&maskPromise); - Assembler::Register dst(tmp); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp); andC(con, size, &mask, a, &dst); emit(con, lsl(t->low, b->low, tmp)); freeTemp(con, tmp); @@ -590,10 +579,10 @@ void shiftLeftR(Context* con, unsigned size, Assembler::Register* a, Assembler:: } void -moveRR(Context* con, unsigned srcSize, Assembler::Register* src, - unsigned dstSize, Assembler::Register* dst); +moveRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); -void shiftLeftC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) +void shiftLeftC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) { assert(con, size == TargetBytesPerWord); if (getValue(a) & 0x1F) { @@ -603,13 +592,13 @@ void shiftLeftC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Asse } } -void shiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) +void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); ResolvedPromise maskPromise(0x3F); - Assembler::Constant mask(&maskPromise); - Assembler::Register dst(tmp3); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp3); andC(con, 4, &mask, a, &dst); emit(con, lsr(tmp1, b->low, tmp3)); emit(con, rsbi(tmp2, tmp3, 32)); @@ -622,15 +611,15 @@ void shiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler: } else { int tmp = newTemp(con); ResolvedPromise maskPromise(0x1F); - Assembler::Constant mask(&maskPromise); - Assembler::Register dst(tmp); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp); andC(con, size, &mask, a, &dst); emit(con, asr(t->low, b->low, tmp)); freeTemp(con, tmp); } } -void shiftRightC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) +void shiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) { assert(con, size == TargetBytesPerWord); if (getValue(a) & 0x1F) { @@ -640,12 +629,12 @@ void shiftRightC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Ass } } -void unsignedShiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) +void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { int tmpShift = newTemp(con); ResolvedPromise maskPromise(size == 8 ? 0x3F : 0x1F); - Assembler::Constant mask(&maskPromise); - Assembler::Register dst(tmpShift); + lir::Constant mask(&maskPromise); + lir::Register dst(tmpShift); andC(con, 4, &mask, a, &dst); emit(con, lsr(t->low, b->low, tmpShift)); if (size == 8) { @@ -662,7 +651,7 @@ void unsignedShiftRightR(Context* con, unsigned size, Assembler::Register* a, As freeTemp(con, tmpShift); } -void unsignedShiftRightC(Context* con, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) +void unsignedShiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) { assert(con, size == TargetBytesPerWord); if (getValue(a) & 0x1F) { @@ -873,20 +862,20 @@ resolve(MyBlock* b) } void -jumpR(Context* con, unsigned size UNUSED, Assembler::Register* target) +jumpR(Context* con, unsigned size UNUSED, lir::Register* target) { assert(con, size == TargetBytesPerWord); emit(con, bx(target->low)); } void -swapRR(Context* con, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b) +swapRR(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { assert(con, aSize == TargetBytesPerWord); assert(con, bSize == TargetBytesPerWord); - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); moveRR(con, aSize, a, bSize, &tmp); moveRR(con, bSize, b, aSize, a); moveRR(con, bSize, &tmp, bSize, b); @@ -894,8 +883,8 @@ swapRR(Context* con, unsigned aSize, Assembler::Register* a, } void -moveRR(Context* con, unsigned srcSize, Assembler::Register* src, - unsigned dstSize, Assembler::Register* dst) +moveRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst) { bool srcIsFpr = isFpr(src); bool dstIsFpr = isFpr(dst); @@ -932,8 +921,8 @@ moveRR(Context* con, unsigned srcSize, Assembler::Register* src, moveRR(con, 4, src, 4, dst); emit(con, asri(dst->high, src->low, 31)); } else if (srcSize == 8 and dstSize == 8) { - Assembler::Register srcHigh(src->high); - Assembler::Register dstHigh(dst->high); + lir::Register srcHigh(src->high); + lir::Register dstHigh(dst->high); if (src->high == dst->low) { if (src->low == dst->high) { @@ -956,8 +945,8 @@ moveRR(Context* con, unsigned srcSize, Assembler::Register* src, } void -moveZRR(Context* con, unsigned srcSize, Assembler::Register* src, - unsigned, Assembler::Register* dst) +moveZRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned, lir::Register* dst) { switch (srcSize) { case 2: @@ -969,15 +958,15 @@ moveZRR(Context* con, unsigned srcSize, Assembler::Register* src, } } -void moveCR(Context* con, unsigned size, Assembler::Constant* src, - unsigned, Assembler::Register* dst); +void moveCR(Context* con, unsigned size, lir::Constant* src, + unsigned, lir::Register* dst); void -moveCR2(Context* con, unsigned size, Assembler::Constant* src, - Assembler::Register* dst, Promise* callOffset) +moveCR2(Context* con, unsigned size, lir::Constant* src, + lir::Register* dst, Promise* callOffset) { if (isFpr(dst)) { // floating-point - Assembler::Register tmp = size > 4 ? makeTemp64(con) : + lir::Register tmp = size > 4 ? makeTemp64(con) : makeTemp(con); moveCR(con, size, src, size, &tmp); moveRR(con, size, &tmp, size, dst); @@ -985,10 +974,10 @@ moveCR2(Context* con, unsigned size, Assembler::Constant* src, } else if (size > 4) { uint64_t value = (uint64_t)src->value->value(); ResolvedPromise loBits(value & MASK_LO32); - Assembler::Constant srcLo(&loBits); + lir::Constant srcLo(&loBits); ResolvedPromise hiBits(value >> 32); - Assembler::Constant srcHi(&hiBits); - Assembler::Register dstHi(dst->high); + lir::Constant srcHi(&hiBits); + lir::Register dstHi(dst->high); moveCR(con, 4, &srcLo, 4, dst); moveCR(con, 4, &srcHi, 4, &dstHi); } else if (src->value->resolved() and isOfWidth(getValue(src), 8)) { @@ -1000,13 +989,13 @@ moveCR2(Context* con, unsigned size, Assembler::Constant* src, } void -moveCR(Context* con, unsigned size, Assembler::Constant* src, - unsigned, Assembler::Register* dst) +moveCR(Context* con, unsigned size, lir::Constant* src, + unsigned, lir::Register* dst) { moveCR2(con, size, src, dst, 0); } -void addR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { emit(con, SETS(add(t->low, a->low, b->low))); emit(con, adc(t->high, a->high, b->high)); @@ -1015,7 +1004,7 @@ void addR(Context* con, unsigned size, Assembler::Register* a, Assembler::Regist } } -void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { emit(con, SETS(rsb(t->low, a->low, b->low))); emit(con, rsc(t->high, a->high, b->high)); @@ -1025,8 +1014,8 @@ void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Regist } void -addC(Context* con, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst) +addC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { assert(con, size == TargetBytesPerWord); @@ -1046,8 +1035,8 @@ addC(Context* con, unsigned size, Assembler::Constant* a, } void -subC(Context* con, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst) +subC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { assert(con, size == TargetBytesPerWord); @@ -1066,7 +1055,7 @@ subC(Context* con, unsigned size, Assembler::Constant* a, } } -void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { bool useTemporaries = b->low == t->low; int tmpLow = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->low; @@ -1087,7 +1076,7 @@ void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::R } } -void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { +void floatAbsoluteRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { if (size == 8) { emit(con, fabsd(fpr64(b), fpr64(a))); } else { @@ -1095,7 +1084,7 @@ void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsign } } -void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { +void floatNegateRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { if (size == 8) { emit(con, fnegd(fpr64(b), fpr64(a))); } else { @@ -1103,7 +1092,7 @@ void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned } } -void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { +void float2FloatRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { if (size == 8) { emit(con, fcvtsd(fpr32(b), fpr64(a))); } else { @@ -1111,7 +1100,7 @@ void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned } } -void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { +void float2IntRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { int tmp = newTemp(con, FPR_MASK); int ftmp = fpr32(tmp); if (size == 8) { // double to int @@ -1123,7 +1112,7 @@ void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned, freeTemp(con, tmp); } -void int2FloatRR(Context* con, unsigned, Assembler::Register* a, unsigned size, Assembler::Register* b) { +void int2FloatRR(Context* con, unsigned, lir::Register* a, unsigned size, lir::Register* b) { emit(con, fmsr(fpr32(b), a->low)); if (size == 8) { // int to double emit(con, fsitod(fpr64(b), fpr32(b))); @@ -1132,7 +1121,7 @@ void int2FloatRR(Context* con, unsigned, Assembler::Register* a, unsigned size, } // else thunked } -void floatSqrtRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { +void floatSqrtRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { if (size == 8) { emit(con, fsqrtd(fpr64(b), fpr64(a))); } else { @@ -1140,7 +1129,7 @@ void floatSqrtRR(Context* con, unsigned size, Assembler::Register* a, unsigned, } } -void floatAddR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void floatAddR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { emit(con, faddd(fpr64(t), fpr64(a), fpr64(b))); } else { @@ -1148,7 +1137,7 @@ void floatAddR(Context* con, unsigned size, Assembler::Register* a, Assembler::R } } -void floatSubtractR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void floatSubtractR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { emit(con, fsubd(fpr64(t), fpr64(b), fpr64(a))); } else { @@ -1156,7 +1145,7 @@ void floatSubtractR(Context* con, unsigned size, Assembler::Register* a, Assembl } } -void floatMultiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void floatMultiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { emit(con, fmuld(fpr64(t), fpr64(a), fpr64(b))); } else { @@ -1164,7 +1153,7 @@ void floatMultiplyR(Context* con, unsigned size, Assembler::Register* a, Assembl } } -void floatDivideR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void floatDivideR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if (size == 8) { emit(con, fdivd(fpr64(t), fpr64(b), fpr64(a))); } else { @@ -1177,7 +1166,7 @@ normalize(Context* con, int offset, int index, unsigned scale, bool* preserveIndex, bool* release) { if (offset != 0 or scale != 1) { - Assembler::Register normalizedIndex + lir::Register normalizedIndex (*preserveIndex ? con->client->acquireTemporary(GPR_MASK) : index); if (*preserveIndex) { @@ -1190,10 +1179,10 @@ normalize(Context* con, int offset, int index, unsigned scale, int scaled; if (scale != 1) { - Assembler::Register unscaledIndex(index); + lir::Register unscaledIndex(index); ResolvedPromise scalePromise(log(scale)); - Assembler::Constant scaleConstant(&scalePromise); + lir::Constant scaleConstant(&scalePromise); shiftLeftC(con, TargetBytesPerWord, &scaleConstant, &unscaledIndex, &normalizedIndex); @@ -1204,12 +1193,12 @@ normalize(Context* con, int offset, int index, unsigned scale, } if (offset != 0) { - Assembler::Register untranslatedIndex(scaled); + lir::Register untranslatedIndex(scaled); ResolvedPromise offsetPromise(offset); - Assembler::Constant offsetConstant(&offsetPromise); + lir::Constant offsetConstant(&offsetPromise); - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); addR(con, TargetBytesPerWord, &tmp, &untranslatedIndex, &normalizedIndex); con->client->releaseTemporary(tmp.low); @@ -1223,10 +1212,10 @@ normalize(Context* con, int offset, int index, unsigned scale, } void -store(Context* con, unsigned size, Assembler::Register* src, +store(Context* con, unsigned size, lir::Register* src, int base, int offset, int index, unsigned scale, bool preserveIndex) { - if (index != NoRegister) { + if (index != lir::NoRegister) { bool release; int normalized = normalize (con, offset, index, scale, &preserveIndex, &release); @@ -1246,7 +1235,7 @@ store(Context* con, unsigned size, Assembler::Register* src, break; case 8: { // split into 2 32-bit stores - Assembler::Register srcHigh(src->high); + lir::Register srcHigh(src->high); store(con, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); store(con, 4, src, base, 4, normalized, 1, preserveIndex); } break; @@ -1254,7 +1243,7 @@ store(Context* con, unsigned size, Assembler::Register* src, default: abort(con); } } else { // FPR store - Assembler::Register base_(base), + lir::Register base_(base), normalized_(normalized), absAddr = makeTemp(con); // FPR stores have only bases, so we must add the index @@ -1286,9 +1275,9 @@ store(Context* con, unsigned size, Assembler::Register* src, break; case 8: { // split into 2 32-bit stores - Assembler::Register srcHigh(src->high); - store(con, 4, &srcHigh, base, offset, NoRegister, 1, false); - store(con, 4, src, base, offset + 4, NoRegister, 1, false); + lir::Register srcHigh(src->high); + store(con, 4, &srcHigh, base, offset, lir::NoRegister, 1, false); + store(con, 4, src, base, offset + 4, lir::NoRegister, 1, false); } break; default: abort(con); @@ -1300,9 +1289,9 @@ store(Context* con, unsigned size, Assembler::Register* src, else emit(con, fsts(fpr32(src), base, offset)); } } else { - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); ResolvedPromise offsetPromise(offset); - Assembler::Constant offsetConstant(&offsetPromise); + lir::Constant offsetConstant(&offsetPromise); moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); @@ -1313,8 +1302,8 @@ store(Context* con, unsigned size, Assembler::Register* src, } void -moveRM(Context* con, unsigned srcSize, Assembler::Register* src, - unsigned dstSize UNUSED, Assembler::Memory* dst) +moveRM(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst) { assert(con, srcSize == dstSize); @@ -1323,10 +1312,10 @@ moveRM(Context* con, unsigned srcSize, Assembler::Register* src, void load(Context* con, unsigned srcSize, int base, int offset, int index, - unsigned scale, unsigned dstSize, Assembler::Register* dst, + unsigned scale, unsigned dstSize, lir::Register* dst, bool preserveIndex, bool signExtend) { - if (index != NoRegister) { + if (index != lir::NoRegister) { bool release; int normalized = normalize (con, offset, index, scale, &preserveIndex, &release); @@ -1356,7 +1345,7 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, false); moveRR(con, 4, dst, 8, dst); } else if (srcSize == 8 and dstSize == 8) { - Assembler::Register dstHigh(dst->high); + lir::Register dstHigh(dst->high); load(con, 4, base, 0, normalized, 1, 4, &dstHigh, preserveIndex, false); load(con, 4, base, 4, normalized, 1, 4, dst, preserveIndex, @@ -1369,7 +1358,7 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, default: abort(con); } } else { // FPR load - Assembler::Register base_(base), + lir::Register base_(base), normalized_(normalized), absAddr = makeTemp(con); // VFP loads only have bases, so we must add the index @@ -1412,10 +1401,10 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, case 8: { if (dstSize == 8) { - Assembler::Register dstHigh(dst->high); - load(con, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, + lir::Register dstHigh(dst->high); + load(con, 4, base, offset, lir::NoRegister, 1, 4, &dstHigh, false, false); - load(con, 4, base, offset + 4, NoRegister, 1, 4, dst, false, + load(con, 4, base, offset + 4, lir::NoRegister, 1, 4, dst, false, false); } else { emit(con, ldri(dst->low, base, offset)); @@ -1431,9 +1420,9 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, else emit(con, flds(fpr32(dst), base, offset)); } } else { - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); ResolvedPromise offsetPromise(offset); - Assembler::Constant offsetConstant(&offsetPromise); + lir::Constant offsetConstant(&offsetPromise); moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); @@ -1445,44 +1434,44 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, } void -moveMR(Context* con, unsigned srcSize, Assembler::Memory* src, - unsigned dstSize, Assembler::Register* dst) +moveMR(Context* con, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) { load(con, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, true); } void -moveZMR(Context* con, unsigned srcSize, Assembler::Memory* src, - unsigned dstSize, Assembler::Register* dst) +moveZMR(Context* con, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) { load(con, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, false); } void -andR(Context* con, unsigned size, Assembler::Register* a, - Assembler::Register* b, Assembler::Register* dst) +andR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { if (size == 8) emit(con, and_(dst->high, a->high, b->high)); emit(con, and_(dst->low, a->low, b->low)); } void -andC(Context* con, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst) +andC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { int64_t v = a->value->value(); if (size == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); - Assembler::Register dh(dst->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); andC(con, 4, &al, b, dst); andC(con, 4, &ah, &bh, &dh); @@ -1498,7 +1487,7 @@ andC(Context* con, unsigned size, Assembler::Constant* a, // instruction bool useTemporary = b->low == dst->low; - Assembler::Register tmp(dst->low); + lir::Register tmp(dst->low); if (useTemporary) { tmp.low = con->client->acquireTemporary(GPR_MASK); } @@ -1517,44 +1506,44 @@ andC(Context* con, unsigned size, Assembler::Constant* a, } void -orR(Context* con, unsigned size, Assembler::Register* a, - Assembler::Register* b, Assembler::Register* dst) +orR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { if (size == 8) emit(con, orr(dst->high, a->high, b->high)); emit(con, orr(dst->low, a->low, b->low)); } void -xorR(Context* con, unsigned size, Assembler::Register* a, - Assembler::Register* b, Assembler::Register* dst) +xorR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { if (size == 8) emit(con, eor(dst->high, a->high, b->high)); emit(con, eor(dst->low, a->low, b->low)); } void -moveAR2(Context* con, unsigned srcSize, Assembler::Address* src, - unsigned dstSize, Assembler::Register* dst) +moveAR2(Context* con, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst) { assert(con, srcSize == 4 and dstSize == 4); - Assembler::Constant constant(src->address); + lir::Constant constant(src->address); moveCR(con, srcSize, &constant, dstSize, dst); - Assembler::Memory memory(dst->low, 0, -1, 0); + lir::Memory memory(dst->low, 0, -1, 0); moveMR(con, dstSize, &memory, dstSize, dst); } void -moveAR(Context* con, unsigned srcSize, Assembler::Address* src, - unsigned dstSize, Assembler::Register* dst) +moveAR(Context* con, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst) { moveAR2(con, srcSize, src, dstSize, dst); } void -compareRR(Context* con, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +compareRR(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type @@ -1571,8 +1560,8 @@ compareRR(Context* con, unsigned aSize, Assembler::Register* a, } void -compareCR(Context* con, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +compareCR(Context* con, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(con, aSize == 4 and bSize == 4); @@ -1580,7 +1569,7 @@ compareCR(Context* con, unsigned aSize, Assembler::Constant* a, isOfWidth(a->value->value(), 8)) { emit(con, cmpi(b->low, a->value->value())); } else { - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); moveCR(con, aSize, a, bSize, &tmp); compareRR(con, bSize, &tmp, bSize, b); con->client->releaseTemporary(tmp.low); @@ -1588,63 +1577,63 @@ compareCR(Context* con, unsigned aSize, Assembler::Constant* a, } void -compareCM(Context* con, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Memory* b) +compareCM(Context* con, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b) { assert(con, aSize == 4 and bSize == 4); - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); moveMR(con, bSize, b, bSize, &tmp); compareCR(con, aSize, a, bSize, &tmp); con->client->releaseTemporary(tmp.low); } void -compareRM(Context* con, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Memory* b) +compareRM(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Memory* b) { assert(con, aSize == 4 and bSize == 4); - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); moveMR(con, bSize, b, bSize, &tmp); compareRR(con, aSize, a, bSize, &tmp); con->client->releaseTemporary(tmp.low); } int32_t -branch(Context* con, TernaryOperation op) +branch(Context* con, lir::TernaryOperation op) { switch (op) { - case JumpIfEqual: - case JumpIfFloatEqual: + case lir::JumpIfEqual: + case lir::JumpIfFloatEqual: return beq(0); - case JumpIfNotEqual: - case JumpIfFloatNotEqual: + case lir::JumpIfNotEqual: + case lir::JumpIfFloatNotEqual: return bne(0); - case JumpIfLess: - case JumpIfFloatLess: - case JumpIfFloatLessOrUnordered: + case lir::JumpIfLess: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatLessOrUnordered: return blt(0); - case JumpIfGreater: - case JumpIfFloatGreater: + case lir::JumpIfGreater: + case lir::JumpIfFloatGreater: return bgt(0); - case JumpIfLessOrEqual: - case JumpIfFloatLessOrEqual: - case JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfLessOrEqual: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqualOrUnordered: return ble(0); - case JumpIfGreaterOrEqual: - case JumpIfFloatGreaterOrEqual: + case lir::JumpIfGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: return bge(0); - case JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: return bhi(0); - case JumpIfFloatGreaterOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: return bpl(0); default: @@ -1653,22 +1642,22 @@ branch(Context* con, TernaryOperation op) } void -conditional(Context* con, int32_t branch, Assembler::Constant* target) +conditional(Context* con, int32_t branch, lir::Constant* target) { appendOffsetTask(con, target->value, offset(con)); emit(con, branch); } void -branch(Context* con, TernaryOperation op, Assembler::Constant* target) +branch(Context* con, lir::TernaryOperation op, lir::Constant* target) { conditional(con, branch(con, op), target); } void -branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, - Assembler::Operand* ah, Assembler::Operand* bl, - Assembler::Operand* bh, Assembler::Constant* target, +branchLong(Context* con, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, BinaryOperationType compareSigned, BinaryOperationType compareUnsigned) { @@ -1677,8 +1666,8 @@ branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, unsigned next = 0; switch (op) { - case JumpIfEqual: - case JumpIfFloatEqual: + case lir::JumpIfEqual: + case lir::JumpIfFloatEqual: next = con->code.length(); emit(con, bne(0)); @@ -1686,16 +1675,16 @@ branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, conditional(con, beq(0), target); break; - case JumpIfNotEqual: - case JumpIfFloatNotEqual: + case lir::JumpIfNotEqual: + case lir::JumpIfFloatNotEqual: conditional(con, bne(0), target); compareSigned(con, 4, al, 4, bl); conditional(con, bne(0), target); break; - case JumpIfLess: - case JumpIfFloatLess: + case lir::JumpIfLess: + case lir::JumpIfFloatLess: conditional(con, blt(0), target); next = con->code.length(); @@ -1705,8 +1694,8 @@ branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, conditional(con, blo(0), target); break; - case JumpIfGreater: - case JumpIfFloatGreater: + case lir::JumpIfGreater: + case lir::JumpIfFloatGreater: conditional(con, bgt(0), target); next = con->code.length(); @@ -1716,8 +1705,8 @@ branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, conditional(con, bhi(0), target); break; - case JumpIfLessOrEqual: - case JumpIfFloatLessOrEqual: + case lir::JumpIfLessOrEqual: + case lir::JumpIfFloatLessOrEqual: conditional(con, blt(0), target); next = con->code.length(); @@ -1727,8 +1716,8 @@ branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, conditional(con, bls(0), target); break; - case JumpIfGreaterOrEqual: - case JumpIfFloatGreaterOrEqual: + case lir::JumpIfGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: conditional(con, bgt(0), target); next = con->code.length(); @@ -1750,13 +1739,13 @@ branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, } void -branchRR(Context* con, TernaryOperation op, unsigned size, - Assembler::Register* a, Assembler::Register* b, - Assembler::Constant* target) +branchRR(Context* con, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target) { if (!isFpr(a) && size > TargetBytesPerWord) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); branchLong(con, op, a, &ah, b, &bh, target, CAST2(compareRR), CAST2(compareRR)); @@ -1767,9 +1756,9 @@ branchRR(Context* con, TernaryOperation op, unsigned size, } void -branchCR(Context* con, TernaryOperation op, unsigned size, - Assembler::Constant* a, Assembler::Register* b, - Assembler::Constant* target) +branchCR(Context* con, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target) { assert(con, !isFloatBranch(op)); @@ -1777,12 +1766,12 @@ branchCR(Context* con, TernaryOperation op, unsigned size, int64_t v = a->value->value(); ResolvedPromise low(v & ~static_cast(0)); - Assembler::Constant al(&low); + lir::Constant al(&low); ResolvedPromise high((v >> 32) & ~static_cast(0)); - Assembler::Constant ah(&high); + lir::Constant ah(&high); - Assembler::Register bh(b->high); + lir::Register bh(b->high); branchLong(con, op, &al, &ah, b, &bh, target, CAST2(compareCR), CAST2(compareCR)); @@ -1793,9 +1782,9 @@ branchCR(Context* con, TernaryOperation op, unsigned size, } void -branchRM(Context* con, TernaryOperation op, unsigned size, - Assembler::Register* a, Assembler::Memory* b, - Assembler::Constant* target) +branchRM(Context* con, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target) { assert(con, !isFloatBranch(op)); assert(con, size <= TargetBytesPerWord); @@ -1805,9 +1794,9 @@ branchRM(Context* con, TernaryOperation op, unsigned size, } void -branchCM(Context* con, TernaryOperation op, unsigned size, - Assembler::Constant* a, Assembler::Memory* b, - Assembler::Constant* target) +branchCM(Context* con, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target) { assert(con, !isFloatBranch(op)); assert(con, size <= TargetBytesPerWord); @@ -1823,17 +1812,17 @@ shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask) } void -moveCM(Context* con, unsigned srcSize, Assembler::Constant* src, - unsigned dstSize, Assembler::Memory* dst) +moveCM(Context* con, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Memory* dst) { switch (dstSize) { case 8: { - Assembler::Constant srcHigh + lir::Constant srcHigh (shiftMaskPromise(con, src->value, 32, 0xFFFFFFFF)); - Assembler::Constant srcLow + lir::Constant srcLow (shiftMaskPromise(con, src->value, 0, 0xFFFFFFFF)); - Assembler::Memory dstLow + lir::Memory dstLow (dst->base, dst->offset + 4, dst->index, dst->scale); moveCM(con, 4, &srcLow, 4, &dstLow); @@ -1841,7 +1830,7 @@ moveCM(Context* con, unsigned srcSize, Assembler::Constant* src, } break; default: - Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); moveCR(con, srcSize, src, dstSize, &tmp); moveRM(con, dstSize, &tmp, dstSize, dst); con->client->releaseTemporary(tmp.low); @@ -1849,8 +1838,8 @@ moveCM(Context* con, unsigned srcSize, Assembler::Constant* src, } void -negateRR(Context* con, unsigned srcSize, Assembler::Register* src, - unsigned dstSize UNUSED, Assembler::Register* dst) +negateRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Register* dst) { assert(con, srcSize == dstSize); @@ -1863,14 +1852,14 @@ negateRR(Context* con, unsigned srcSize, Assembler::Register* src, } void -callR(Context* con, unsigned size UNUSED, Assembler::Register* target) +callR(Context* con, unsigned size UNUSED, lir::Register* target) { assert(con, size == TargetBytesPerWord); emit(con, blx(target->low)); } void -callC(Context* con, unsigned size UNUSED, Assembler::Constant* target) +callC(Context* con, unsigned size UNUSED, lir::Constant* target) { assert(con, size == TargetBytesPerWord); @@ -1879,27 +1868,27 @@ callC(Context* con, unsigned size UNUSED, Assembler::Constant* target) } void -longCallC(Context* con, unsigned size UNUSED, Assembler::Constant* target) +longCallC(Context* con, unsigned size UNUSED, lir::Constant* target) { assert(con, size == TargetBytesPerWord); - Assembler::Register tmp(4); + lir::Register tmp(4); moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); callR(con, TargetBytesPerWord, &tmp); } void -longJumpC(Context* con, unsigned size UNUSED, Assembler::Constant* target) +longJumpC(Context* con, unsigned size UNUSED, lir::Constant* target) { assert(con, size == TargetBytesPerWord); - Assembler::Register tmp(4); // a non-arg reg that we don't mind clobbering + lir::Register tmp(4); // a non-arg reg that we don't mind clobbering moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); jumpR(con, TargetBytesPerWord, &tmp); } void -jumpC(Context* con, unsigned size UNUSED, Assembler::Constant* target) +jumpC(Context* con, unsigned size UNUSED, lir::Constant* target) { assert(con, size == TargetBytesPerWord); @@ -1991,10 +1980,10 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED, void populateTables(ArchitectureContext* con) { - const OperandType C = ConstantOperand; - const OperandType A = AddressOperand; - const OperandType R = RegisterOperand; - const OperandType M = MemoryOperand; + const lir::OperandType C = lir::ConstantOperand; + const lir::OperandType A = lir::AddressOperand; + const lir::OperandType R = lir::RegisterOperand; + const lir::OperandType M = lir::MemoryOperand; OperationType* zo = con->operations; UnaryOperationType* uo = con->unaryOperations; @@ -2002,78 +1991,78 @@ populateTables(ArchitectureContext* con) TernaryOperationType* to = con->ternaryOperations; BranchOperationType* bro = con->branchOperations; - zo[Return] = return_; - zo[LoadBarrier] = memoryBarrier; - zo[StoreStoreBarrier] = memoryBarrier; - zo[StoreLoadBarrier] = memoryBarrier; - zo[Trap] = trap; + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = memoryBarrier; + zo[lir::StoreStoreBarrier] = memoryBarrier; + zo[lir::StoreLoadBarrier] = memoryBarrier; + zo[lir::Trap] = trap; - uo[index(con, LongCall, C)] = CAST1(longCallC); + uo[index(con, lir::LongCall, C)] = CAST1(longCallC); - uo[index(con, AlignedLongCall, C)] = CAST1(longCallC); + uo[index(con, lir::AlignedLongCall, C)] = CAST1(longCallC); - uo[index(con, LongJump, C)] = CAST1(longJumpC); + uo[index(con, lir::LongJump, C)] = CAST1(longJumpC); - uo[index(con, AlignedLongJump, C)] = CAST1(longJumpC); + uo[index(con, lir::AlignedLongJump, C)] = CAST1(longJumpC); - uo[index(con, Jump, R)] = CAST1(jumpR); - uo[index(con, Jump, C)] = CAST1(jumpC); + uo[index(con, lir::Jump, R)] = CAST1(jumpR); + uo[index(con, lir::Jump, C)] = CAST1(jumpC); - uo[index(con, AlignedJump, R)] = CAST1(jumpR); - uo[index(con, AlignedJump, C)] = CAST1(jumpC); + uo[index(con, lir::AlignedJump, R)] = CAST1(jumpR); + uo[index(con, lir::AlignedJump, C)] = CAST1(jumpC); - uo[index(con, Call, C)] = CAST1(callC); - uo[index(con, Call, R)] = CAST1(callR); + uo[index(con, lir::Call, C)] = CAST1(callC); + uo[index(con, lir::Call, R)] = CAST1(callR); - uo[index(con, AlignedCall, C)] = CAST1(callC); - uo[index(con, AlignedCall, R)] = CAST1(callR); + uo[index(con, lir::AlignedCall, C)] = CAST1(callC); + uo[index(con, lir::AlignedCall, R)] = CAST1(callR); - bo[index(con, Move, R, R)] = CAST2(moveRR); - bo[index(con, Move, C, R)] = CAST2(moveCR); - bo[index(con, Move, C, M)] = CAST2(moveCM); - bo[index(con, Move, M, R)] = CAST2(moveMR); - bo[index(con, Move, R, M)] = CAST2(moveRM); - bo[index(con, Move, A, R)] = CAST2(moveAR); + bo[index(con, lir::Move, R, R)] = CAST2(moveRR); + bo[index(con, lir::Move, C, R)] = CAST2(moveCR); + bo[index(con, lir::Move, C, M)] = CAST2(moveCM); + bo[index(con, lir::Move, M, R)] = CAST2(moveMR); + bo[index(con, lir::Move, R, M)] = CAST2(moveRM); + bo[index(con, lir::Move, A, R)] = CAST2(moveAR); - bo[index(con, MoveZ, R, R)] = CAST2(moveZRR); - bo[index(con, MoveZ, M, R)] = CAST2(moveZMR); - bo[index(con, MoveZ, C, R)] = CAST2(moveCR); + bo[index(con, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(con, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(con, lir::MoveZ, C, R)] = CAST2(moveCR); - bo[index(con, Negate, R, R)] = CAST2(negateRR); + bo[index(con, lir::Negate, R, R)] = CAST2(negateRR); - bo[index(con, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); - bo[index(con, FloatNegate, R, R)] = CAST2(floatNegateRR); - bo[index(con, Float2Float, R, R)] = CAST2(float2FloatRR); - bo[index(con, Float2Int, R, R)] = CAST2(float2IntRR); - bo[index(con, Int2Float, R, R)] = CAST2(int2FloatRR); - bo[index(con, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + bo[index(con, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + bo[index(con, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); + bo[index(con, lir::Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(con, lir::Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(con, lir::Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(con, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); - to[index(con, Add, R)] = CAST3(addR); + to[index(con, lir::Add, R)] = CAST3(addR); - to[index(con, Subtract, R)] = CAST3(subR); + to[index(con, lir::Subtract, R)] = CAST3(subR); - to[index(con, Multiply, R)] = CAST3(multiplyR); + to[index(con, lir::Multiply, R)] = CAST3(multiplyR); - to[index(con, FloatAdd, R)] = CAST3(floatAddR); - to[index(con, FloatSubtract, R)] = CAST3(floatSubtractR); - to[index(con, FloatMultiply, R)] = CAST3(floatMultiplyR); - to[index(con, FloatDivide, R)] = CAST3(floatDivideR); + to[index(con, lir::FloatAdd, R)] = CAST3(floatAddR); + to[index(con, lir::FloatSubtract, R)] = CAST3(floatSubtractR); + to[index(con, lir::FloatMultiply, R)] = CAST3(floatMultiplyR); + to[index(con, lir::FloatDivide, R)] = CAST3(floatDivideR); - to[index(con, ShiftLeft, R)] = CAST3(shiftLeftR); - to[index(con, ShiftLeft, C)] = CAST3(shiftLeftC); + to[index(con, lir::ShiftLeft, R)] = CAST3(shiftLeftR); + to[index(con, lir::ShiftLeft, C)] = CAST3(shiftLeftC); - to[index(con, ShiftRight, R)] = CAST3(shiftRightR); - to[index(con, ShiftRight, C)] = CAST3(shiftRightC); + to[index(con, lir::ShiftRight, R)] = CAST3(shiftRightR); + to[index(con, lir::ShiftRight, C)] = CAST3(shiftRightC); - to[index(con, UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); - to[index(con, UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); + to[index(con, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); + to[index(con, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); - to[index(con, And, R)] = CAST3(andR); - to[index(con, And, C)] = CAST3(andC); + to[index(con, lir::And, R)] = CAST3(andR); + to[index(con, lir::And, C)] = CAST3(andC); - to[index(con, Or, R)] = CAST3(orR); + to[index(con, lir::Or, R)] = CAST3(orR); - to[index(con, Xor, R)] = CAST3(xorR); + to[index(con, lir::Xor, R)] = CAST3(xorR); bro[branchIndex(con, R, R)] = CAST_BRANCH(branchRR); bro[branchIndex(con, C, R)] = CAST_BRANCH(branchCR); @@ -2198,23 +2187,23 @@ class MyArchitecture: public Assembler::Architecture { - reinterpret_cast(instruction))); } - virtual void updateCall(UnaryOperation op UNUSED, + virtual void updateCall(lir::UnaryOperation op UNUSED, void* returnAddress, void* newTarget) { switch (op) { - case Call: - case Jump: - case AlignedCall: - case AlignedJump: { + case lir::Call: + case lir::Jump: + case lir::AlignedCall: + case lir::AlignedJump: { updateOffset(con.s, static_cast(returnAddress) - 4, reinterpret_cast(newTarget)); } break; - case LongCall: - case LongJump: - case AlignedLongCall: - case AlignedLongJump: { + case lir::LongCall: + case lir::LongJump: + case lir::AlignedLongCall: + case lir::AlignedLongJump: { uint32_t* p = static_cast(returnAddress) - 2; *reinterpret_cast(p + (((*p & PoolOffsetMask) + 8) / 4)) = newTarget; @@ -2270,34 +2259,34 @@ class MyArchitecture: public Assembler::Architecture { return 0; } - virtual BinaryOperation hasBinaryIntrinsic(Thread*, object) { - return NoBinaryOperation; + virtual lir::BinaryOperation hasBinaryIntrinsic(Thread*, object) { + return lir::NoBinaryOperation; } - virtual TernaryOperation hasTernaryIntrinsic(Thread*, object) { - return NoTernaryOperation; + virtual lir::TernaryOperation hasTernaryIntrinsic(Thread*, object) { + return lir::NoTernaryOperation; } - virtual bool alwaysCondensed(BinaryOperation) { + virtual bool alwaysCondensed(lir::BinaryOperation) { return false; } - virtual bool alwaysCondensed(TernaryOperation) { + virtual bool alwaysCondensed(lir::TernaryOperation) { return false; } virtual void plan - (UnaryOperation, + (lir::UnaryOperation, unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, bool* thunk) { - *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); *aRegisterMask = ~static_cast(0); *thunk = false; } virtual void planSource - (BinaryOperation op, + (lir::BinaryOperation op, unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned bSize, bool* thunk) { @@ -2306,43 +2295,43 @@ class MyArchitecture: public Assembler::Architecture { *aRegisterMask = GPR_MASK64; switch (op) { - case Negate: - *aTypeMask = (1 << RegisterOperand); + case lir::Negate: + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = GPR_MASK64; break; - case Absolute: + case lir::Absolute: *thunk = true; break; - case FloatAbsolute: - case FloatSquareRoot: - case FloatNegate: - case Float2Float: + case lir::FloatAbsolute: + case lir::FloatSquareRoot: + case lir::FloatNegate: + case lir::Float2Float: if (vfpSupported()) { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = FPR_MASK64; } else { *thunk = true; } break; - case Float2Int: + case lir::Float2Int: // todo: Java requires different semantics than SSE for // converting floats to integers, we we need to either use // thunks or produce inline machine code which handles edge // cases properly. if (false && vfpSupported() && bSize == 4) { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = FPR_MASK64; } else { *thunk = true; } break; - case Int2Float: + case lir::Int2Float: if (vfpSupported() && aSize == 4) { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = GPR_MASK64; } else { *thunk = true; @@ -2355,36 +2344,36 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (BinaryOperation op, + (lir::BinaryOperation op, unsigned, uint8_t aTypeMask, uint64_t, unsigned , uint8_t* bTypeMask, uint64_t* bRegisterMask) { - *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); *bRegisterMask = GPR_MASK64; switch (op) { - case Negate: - *bTypeMask = (1 << RegisterOperand); + case lir::Negate: + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = GPR_MASK64; break; - case FloatAbsolute: - case FloatSquareRoot: - case FloatNegate: - case Float2Float: - case Int2Float: - *bTypeMask = (1 << RegisterOperand); + case lir::FloatAbsolute: + case lir::FloatSquareRoot: + case lir::FloatNegate: + case lir::Float2Float: + case lir::Int2Float: + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = FPR_MASK64; break; - case Float2Int: - *bTypeMask = (1 << RegisterOperand); + case lir::Float2Int: + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = GPR_MASK64; break; - case Move: - if (!(aTypeMask & 1 << RegisterOperand)) { - *bTypeMask = 1 << RegisterOperand; + case lir::Move: + if (!(aTypeMask & 1 << lir::RegisterOperand)) { + *bTypeMask = 1 << lir::RegisterOperand; } break; @@ -2404,79 +2393,79 @@ class MyArchitecture: public Assembler::Architecture { *tmpTypeMask = 0; *tmpRegisterMask = 0; - if (dstTypeMask & (1 << MemoryOperand)) { + if (dstTypeMask & (1 << lir::MemoryOperand)) { // can't move directly from memory or constant to memory - *srcTypeMask = 1 << RegisterOperand; - *tmpTypeMask = 1 << RegisterOperand; + *srcTypeMask = 1 << lir::RegisterOperand; + *tmpTypeMask = 1 << lir::RegisterOperand; *tmpRegisterMask = GPR_MASK64; } else if (vfpSupported() && - dstTypeMask & 1 << RegisterOperand && + dstTypeMask & 1 << lir::RegisterOperand && dstRegisterMask & FPR_MASK) { - *srcTypeMask = *tmpTypeMask = 1 << RegisterOperand | - 1 << MemoryOperand; + *srcTypeMask = *tmpTypeMask = 1 << lir::RegisterOperand | + 1 << lir::MemoryOperand; *tmpRegisterMask = ~static_cast(0); } } virtual void planSource - (TernaryOperation op, + (lir::TernaryOperation op, unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask, unsigned, bool* thunk) { - *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); *aRegisterMask = GPR_MASK64; - *bTypeMask = (1 << RegisterOperand); + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = GPR_MASK64; *thunk = false; switch (op) { - case ShiftLeft: - case ShiftRight: - case UnsignedShiftRight: - if (bSize == 8) *aTypeMask = *bTypeMask = (1 << RegisterOperand); + case lir::ShiftLeft: + case lir::ShiftRight: + case lir::UnsignedShiftRight: + if (bSize == 8) *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); break; - case Add: - case Subtract: - case Or: - case Xor: - case Multiply: - *aTypeMask = *bTypeMask = (1 << RegisterOperand); + case lir::Add: + case lir::Subtract: + case lir::Or: + case lir::Xor: + case lir::Multiply: + *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); break; - case Divide: - case Remainder: - case FloatRemainder: + case lir::Divide: + case lir::Remainder: + case lir::FloatRemainder: *thunk = true; break; - case FloatAdd: - case FloatSubtract: - case FloatMultiply: - case FloatDivide: + case lir::FloatAdd: + case lir::FloatSubtract: + case lir::FloatMultiply: + case lir::FloatDivide: if (vfpSupported()) { - *aTypeMask = *bTypeMask = (1 << RegisterOperand); + *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = *bRegisterMask = FPR_MASK64; } else { *thunk = true; } break; - case JumpIfFloatEqual: - case JumpIfFloatNotEqual: - case JumpIfFloatLess: - case JumpIfFloatGreater: - case JumpIfFloatLessOrEqual: - case JumpIfFloatGreaterOrEqual: - case JumpIfFloatLessOrUnordered: - case JumpIfFloatGreaterOrUnordered: - case JumpIfFloatLessOrEqualOrUnordered: - case JumpIfFloatGreaterOrEqualOrUnordered: + case lir::JumpIfFloatEqual: + case lir::JumpIfFloatNotEqual: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatLessOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: if (vfpSupported()) { - *aTypeMask = *bTypeMask = (1 << RegisterOperand); + *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = *bRegisterMask = FPR_MASK64; } else { *thunk = true; @@ -2489,16 +2478,16 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (TernaryOperation op, + (lir::TernaryOperation op, unsigned, uint8_t, uint64_t, unsigned, uint8_t, const uint64_t bRegisterMask, unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask) { if (isBranch(op)) { - *cTypeMask = (1 << ConstantOperand); + *cTypeMask = (1 << lir::ConstantOperand); *cRegisterMask = 0; } else { - *cTypeMask = (1 << RegisterOperand); + *cTypeMask = (1 << lir::RegisterOperand); *cRegisterMask = bRegisterMask; } } @@ -2537,28 +2526,28 @@ class MyAssembler: public Assembler { virtual void checkStackOverflow(uintptr_t handler, unsigned stackLimitOffsetFromThread) { - Register stack(StackRegister); - Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); - Constant handlerConstant(new(con.zone) ResolvedPromise(handler)); - branchRM(&con, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, + lir::Register stack(StackRegister); + lir::Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); + lir::Constant handlerConstant(new(con.zone) ResolvedPromise(handler)); + branchRM(&con, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) { - Register link(LinkRegister); - Memory linkDst(ThreadRegister, ipOffset); + lir::Register link(LinkRegister); + lir::Memory linkDst(ThreadRegister, ipOffset); moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst); - Register stack(StackRegister); - Memory stackDst(ThreadRegister, stackOffset); + lir::Register stack(StackRegister); + lir::Memory stackDst(ThreadRegister, stackOffset); moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); } virtual void pushFrame(unsigned argumentCount, ...) { struct Argument { unsigned size; - OperandType type; - Operand* operand; + lir::OperandType type; + lir::Operand* operand; }; RUNTIME_ARRAY(Argument, arguments, argumentCount); @@ -2566,8 +2555,8 @@ class MyAssembler: public Assembler { unsigned footprint = 0; for (unsigned i = 0; i < argumentCount; ++i) { RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned); - RUNTIME_ARRAY_BODY(arguments)[i].type = static_cast(va_arg(a, int)); - RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, Operand*); + RUNTIME_ARRAY_BODY(arguments)[i].type = static_cast(va_arg(a, int)); + RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*); footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord); } va_end(a); @@ -2577,24 +2566,27 @@ class MyAssembler: public Assembler { unsigned offset = 0; for (unsigned i = 0; i < argumentCount; ++i) { if (i < arch_->argumentRegisterCount()) { - Register dst(arch_->argumentRegister(i)); + lir::Register dst(arch_->argumentRegister(i)); - apply(Move, - RUNTIME_ARRAY_BODY(arguments)[i].size, - RUNTIME_ARRAY_BODY(arguments)[i].type, - RUNTIME_ARRAY_BODY(arguments)[i].operand, - pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), RegisterOperand, - &dst); + apply(lir::Move, + OperandInfo( + RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo( + pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::RegisterOperand, &dst)); offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord); } else { - Memory dst(StackRegister, offset * TargetBytesPerWord); + lir::Memory dst(StackRegister, offset * TargetBytesPerWord); - apply(Move, - RUNTIME_ARRAY_BODY(arguments)[i].size, - RUNTIME_ARRAY_BODY(arguments)[i].type, - RUNTIME_ARRAY_BODY(arguments)[i].operand, - pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), MemoryOperand, &dst); + apply(lir::Move, + OperandInfo( + RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo( + pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::MemoryOperand, &dst)); offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord); } @@ -2609,37 +2601,37 @@ class MyAssembler: public Assembler { // how to handle them: assert(&con, footprint < 256); - Register stack(StackRegister); + lir::Register stack(StackRegister); ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); - Constant footprintConstant(&footprintPromise); + lir::Constant footprintConstant(&footprintPromise); subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); - Register returnAddress(LinkRegister); - Memory returnAddressDst + lir::Register returnAddress(LinkRegister); + lir::Memory returnAddressDst (StackRegister, (footprint - 1) * TargetBytesPerWord); moveRM(&con, TargetBytesPerWord, &returnAddress, TargetBytesPerWord, &returnAddressDst); } virtual void adjustFrame(unsigned difference) { - Register stack(StackRegister); + lir::Register stack(StackRegister); ResolvedPromise differencePromise(difference * TargetBytesPerWord); - Constant differenceConstant(&differencePromise); + lir::Constant differenceConstant(&differencePromise); subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack); } virtual void popFrame(unsigned footprint) { footprint += FrameHeaderSize; - Register returnAddress(LinkRegister); - Memory returnAddressSrc + lir::Register returnAddress(LinkRegister); + lir::Memory returnAddressSrc (StackRegister, (footprint - 1) * TargetBytesPerWord); moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &returnAddress); - Register stack(StackRegister); + lir::Register stack(StackRegister); ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); - Constant footprintConstant(&footprintPromise); + lir::Constant footprintConstant(&footprintPromise); addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); } @@ -2648,29 +2640,29 @@ class MyAssembler: public Assembler { int returnAddressSurrogate, int framePointerSurrogate UNUSED) { - assert(&con, framePointerSurrogate == NoRegister); + assert(&con, framePointerSurrogate == lir::NoRegister); if (TailCalls) { if (offset) { footprint += FrameHeaderSize; - Register link(LinkRegister); - Memory returnAddressSrc + lir::Register link(LinkRegister); + lir::Memory returnAddressSrc (StackRegister, (footprint - 1) * TargetBytesPerWord); moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &link); - Register stack(StackRegister); + lir::Register stack(StackRegister); ResolvedPromise footprintPromise ((footprint - offset) * TargetBytesPerWord); - Constant footprintConstant(&footprintPromise); + lir::Constant footprintConstant(&footprintPromise); addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); - if (returnAddressSurrogate != NoRegister) { + if (returnAddressSurrogate != lir::NoRegister) { assert(&con, offset > 0); - Register ras(returnAddressSurrogate); - Memory dst(StackRegister, (offset - 1) * TargetBytesPerWord); + lir::Register ras(returnAddressSurrogate); + lir::Memory dst(StackRegister, (offset - 1) * TargetBytesPerWord); moveRM(&con, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); } } else { @@ -2693,9 +2685,9 @@ class MyAssembler: public Assembler { if (TailCalls and argumentFootprint > StackAlignmentInWords) { offset = argumentFootprint - StackAlignmentInWords; - Register stack(StackRegister); + lir::Register stack(StackRegister); ResolvedPromise adjustmentPromise(offset * TargetBytesPerWord); - Constant adjustment(&adjustmentPromise); + lir::Constant adjustment(&adjustmentPromise); addC(&con, TargetBytesPerWord, &adjustment, &stack, &stack); } else { offset = 0; @@ -2709,53 +2701,45 @@ class MyAssembler: public Assembler { { popFrame(frameFootprint); - Register stack(StackRegister); - Memory newStackSrc(ThreadRegister, stackOffsetFromThread); + lir::Register stack(StackRegister); + lir::Memory newStackSrc(ThreadRegister, stackOffsetFromThread); moveMR(&con, TargetBytesPerWord, &newStackSrc, TargetBytesPerWord, &stack); return_(&con); } - virtual void apply(Operation op) { + virtual void apply(lir::Operation op) { arch_->con.operations[op](&con); } - virtual void apply(UnaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand) + virtual void apply(lir::UnaryOperation op, OperandInfo a) { - arch_->con.unaryOperations[index(&(arch_->con), op, aType)] - (&con, aSize, aOperand); + arch_->con.unaryOperations[index(&(arch_->con), op, a.type)] + (&con, a.size, a.operand); } - virtual void apply(BinaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand, - unsigned bSize, OperandType bType, Operand* bOperand) + virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) { - arch_->con.binaryOperations[index(&(arch_->con), op, aType, bType)] - (&con, aSize, aOperand, bSize, bOperand); + arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)] + (&con, a.size, a.operand, b.size, b.operand); } - virtual void apply(TernaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand, - unsigned bSize, OperandType bType UNUSED, - Operand* bOperand, - unsigned cSize UNUSED, OperandType cType UNUSED, - Operand* cOperand) + virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) { if (isBranch(op)) { - assert(&con, aSize == bSize); - assert(&con, cSize == TargetBytesPerWord); - assert(&con, cType == ConstantOperand); + assert(&con, a.size == b.size); + assert(&con, c.size == TargetBytesPerWord); + assert(&con, c.type == lir::ConstantOperand); - arch_->con.branchOperations[branchIndex(&(arch_->con), aType, bType)] - (&con, op, aSize, aOperand, bOperand, cOperand); + arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)] + (&con, op, a.size, a.operand, b.operand, c.operand); } else { - assert(&con, bSize == cSize); - assert(&con, bType == RegisterOperand); - assert(&con, cType == RegisterOperand); + assert(&con, b.size == c.size); + assert(&con, b.type == lir::RegisterOperand); + assert(&con, c.type == lir::RegisterOperand); - arch_->con.ternaryOperations[index(&(arch_->con), op, aType)] - (&con, bSize, aOperand, bOperand, cOperand); + arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)] + (&con, b.size, a.operand, b.operand, c.operand); } } diff --git a/src/codegen/assembler.h b/src/codegen/assembler.h index fbe03b70ac..d6ef7dd262 100644 --- a/src/codegen/assembler.h +++ b/src/codegen/assembler.h @@ -8,13 +8,30 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#ifndef ASSEMBLER_H -#define ASSEMBLER_H +#ifndef AVIAN_CODEGEN_ASSEMBLER_H +#define AVIAN_CODEGEN_ASSEMBLER_H #include "system.h" #include "zone.h" -namespace vm { +#include "codegen/lir.h" +#include "codegen/promise.h" + +namespace avian { +namespace codegen { + +class OperandInfo { +public: + const unsigned size; + const lir::OperandType type; + lir::Operand* const operand; + + inline OperandInfo(unsigned size, lir::OperandType type, lir::Operand* operand): + size(size), + type(type), + operand(operand) + { } +}; #ifdef AVIAN_TAILS const bool TailCalls = true; @@ -28,286 +45,8 @@ const bool UseFramePointer = true; const bool UseFramePointer = false; #endif -enum Operation { - Return, - LoadBarrier, - StoreStoreBarrier, - StoreLoadBarrier, - Trap -}; - -const unsigned OperationCount = Trap + 1; - -enum UnaryOperation { - Call, - LongCall, - AlignedLongCall, - AlignedCall, - Jump, - LongJump, - AlignedLongJump, - AlignedJump, - - NoUnaryOperation = -1 -}; - -const unsigned UnaryOperationCount = AlignedJump + 1; - -enum BinaryOperation { - Move, - MoveLow, - MoveHigh, - MoveZ, - Negate, - FloatNegate, - Float2Float, - Float2Int, - Int2Float, - FloatSquareRoot, - FloatAbsolute, - Absolute, - - NoBinaryOperation = -1 -}; - -const unsigned BinaryOperationCount = Absolute + 1; - -enum TernaryOperation { - Add, - Subtract, - Multiply, - Divide, - Remainder, - ShiftLeft, - ShiftRight, - UnsignedShiftRight, - And, - Or, - Xor, - FloatAdd, - FloatSubtract, - FloatMultiply, - FloatDivide, - FloatRemainder, - FloatMax, - FloatMin, - JumpIfLess, - JumpIfGreater, - JumpIfLessOrEqual, - JumpIfGreaterOrEqual, - JumpIfEqual, - JumpIfNotEqual, - JumpIfFloatEqual, - JumpIfFloatNotEqual, - JumpIfFloatLess, - JumpIfFloatGreater, - JumpIfFloatLessOrEqual, - JumpIfFloatGreaterOrEqual, - JumpIfFloatLessOrUnordered, - JumpIfFloatGreaterOrUnordered, - JumpIfFloatLessOrEqualOrUnordered, - JumpIfFloatGreaterOrEqualOrUnordered, - - NoTernaryOperation = -1 -}; - -const unsigned TernaryOperationCount -= JumpIfFloatGreaterOrEqualOrUnordered + 1; - -const unsigned NonBranchTernaryOperationCount = FloatMin + 1; -const unsigned BranchOperationCount -= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin; - -enum OperandType { - ConstantOperand, - AddressOperand, - RegisterOperand, - MemoryOperand -}; - -enum ValueType { - ValueGeneral, - ValueFloat -}; - -const unsigned OperandTypeCount = MemoryOperand + 1; - -const int NoRegister = -1; - -class Promise { - public: - class Listener { - public: - virtual bool resolve(int64_t value, void** location) = 0; - - Listener* next; - }; - - virtual int64_t value() = 0; - virtual bool resolved() = 0; - virtual Listener* listen(unsigned) { return 0; } -}; - -class ResolvedPromise: public Promise { - public: - ResolvedPromise(int64_t value): value_(value) { } - - virtual int64_t value() { - return value_; - } - - virtual bool resolved() { - return true; - } - - 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 OffsetPromise: public Promise { - public: - OffsetPromise(Promise* base, int64_t offset): - base(base), offset(offset) - { } - - virtual int64_t value() { - return base->value() + offset; - } - - virtual bool resolved() { - return base->resolved(); - } - - Promise* base; - int64_t offset; -}; - -class ListenPromise: public Promise { - public: - ListenPromise(System* s, Allocator* allocator): - s(s), allocator(allocator), listener(0) - { } - - virtual int64_t value() { - abort(s); - } - - virtual bool resolved() { - return false; - } - - virtual Listener* listen(unsigned sizeInBytes) { - Listener* l = static_cast(allocator->allocate(sizeInBytes)); - l->next = listener; - listener = l; - return l; - } - - System* s; - Allocator* allocator; - Listener* listener; - Promise* promise; -}; - -class DelayedPromise: public ListenPromise { - public: - DelayedPromise(System* s, Allocator* allocator, Promise* basis, - DelayedPromise* next): - ListenPromise(s, allocator), basis(basis), next(next) - { } - - virtual int64_t value() { - abort(s); - } - - virtual bool resolved() { - return false; - } - - virtual Listener* listen(unsigned sizeInBytes) { - Listener* l = static_cast(allocator->allocate(sizeInBytes)); - l->next = listener; - listener = l; - return l; - } - - Promise* basis; - DelayedPromise* next; -}; - class Assembler { public: - class Operand { }; - - class Constant: public Operand { - public: - Constant(Promise* value): value(value) { } - - Promise* value; - }; - - class Address: public Operand { - public: - Address(Promise* address): address(address) { } - - Promise* address; - }; - - class Register: public Operand { - public: - Register(int low, int high = NoRegister): low(low), high(high) { } - - int low; - int high; - }; - - class Memory: public Operand { - public: - Memory(int base, int offset, int index = NoRegister, unsigned scale = 1): - base(base), offset(offset), index(index), scale(scale) - { } - - int base; - int offset; - int index; - unsigned scale; - }; class Client { public: @@ -342,8 +81,8 @@ class Assembler { virtual uintptr_t maximumImmediateJump() = 0; - virtual bool alwaysCondensed(BinaryOperation op) = 0; - virtual bool alwaysCondensed(TernaryOperation op) = 0; + virtual bool alwaysCondensed(lir::BinaryOperation op) = 0; + virtual bool alwaysCondensed(lir::TernaryOperation op) = 0; virtual bool reserved(int register_) = 0; @@ -360,7 +99,7 @@ class Assembler { virtual bool matchCall(void* returnAddress, void* target) = 0; - virtual void updateCall(UnaryOperation op, void* returnAddress, + virtual void updateCall(lir::UnaryOperation op, void* returnAddress, void* newTarget) = 0; virtual void setConstant(void* dst, uint64_t constant) = 0; @@ -379,17 +118,17 @@ class Assembler { virtual int framePointerOffset() = 0; virtual void plan - (UnaryOperation op, + (lir::UnaryOperation op, unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, bool* thunk) = 0; virtual void planSource - (BinaryOperation op, + (lir::BinaryOperation op, unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned bSize, bool* thunk) = 0; virtual void planDestination - (BinaryOperation op, + (lir::BinaryOperation op, unsigned aSize, uint8_t aTypeMask, uint64_t aRegisterMask, unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask) = 0; @@ -399,18 +138,18 @@ class Assembler { uint8_t dstTypeMask, uint64_t dstRegisterMask) = 0; virtual void planSource - (TernaryOperation op, + (lir::TernaryOperation op, unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask, unsigned cSize, bool* thunk) = 0; virtual void planDestination - (TernaryOperation op, + (lir::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) = 0; - virtual Assembler* makeAssembler(Allocator*, Zone*) = 0; + virtual Assembler* makeAssembler(vm::Allocator*, vm::Zone*) = 0; virtual void acquire() = 0; virtual void release() = 0; @@ -437,19 +176,10 @@ class Assembler { unsigned stackOffsetFromThread) = 0; - virtual void apply(Operation op) = 0; - - virtual void apply(UnaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand) = 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 apply(lir::Operation op) = 0; + virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0; + virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0; + virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) = 0; virtual void setDestination(uint8_t* dst) = 0; @@ -468,6 +198,7 @@ class Assembler { virtual void dispose() = 0; }; -} // namespace vm +} // namespace codegen +} // namespace avian -#endif//ASSEMBLER_H +#endif // AVIAN_CODEGEN_ASSEMBLER_H diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 90efb622b8..ae8e6dd269 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -15,6 +15,7 @@ #include "util/runtime-array.h" using namespace vm; +using namespace avian::codegen; namespace { @@ -64,16 +65,16 @@ class Snapshot; void NO_RETURN abort(Context*); void -apply(Context* c, UnaryOperation op, +apply(Context* c, lir::UnaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High); void -apply(Context* c, BinaryOperation op, +apply(Context* c, lir::BinaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High, unsigned s2Size, Site* s2Low, Site* s2High); void -apply(Context* c, TernaryOperation op, +apply(Context* c, lir::TernaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); @@ -130,9 +131,9 @@ class Site { virtual bool frozen(Context*) { return false; } - virtual OperandType type(Context*) = 0; + virtual lir::OperandType type(Context*) = 0; - virtual void asAssemblerOperand(Context*, Site*, Assembler::Operand*) = 0; + virtual void asAssemblerOperand(Context*, Site*, lir::Operand*) = 0; virtual Site* copy(Context*) = 0; @@ -320,7 +321,7 @@ intersect(const SiteMask& a, const SiteMask& b) class Value: public Compiler::Operand { public: - Value(Site* site, Site* target, ValueType type): + Value(Site* site, Site* target, lir::ValueType type): reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this), nextWord(this), home(NoFrameIndex), type(type), wordIndex(0) { } @@ -333,7 +334,7 @@ class Value: public Compiler::Operand { Value* buddy; Value* nextWord; int16_t home; - ValueType type; + lir::ValueType type; uint8_t wordIndex; }; @@ -1279,16 +1280,16 @@ class Target { Target(): cost(Impossible) { } - Target(int index, OperandType type, unsigned cost): + Target(int index, lir::OperandType type, unsigned cost): index(index), type(type), cost(cost) { } int16_t index; - OperandType type; + lir::OperandType type; uint8_t cost; }; -ValueType +lir::ValueType valueType(Context* c, Compiler::OperandType type) { switch (type) { @@ -1296,9 +1297,9 @@ valueType(Context* c, Compiler::OperandType type) case Compiler::AddressType: case Compiler::IntegerType: case Compiler::VoidType: - return ValueGeneral; + return lir::ValueGeneral; case Compiler::FloatType: - return ValueFloat; + return lir::ValueFloat; default: abort(c); } @@ -1344,7 +1345,7 @@ pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, if ((1 << i) & mask) { RegisterResource* r = c->registerResources + i; unsigned myCost = resourceCost - (c, v, r, 1 << RegisterOperand, 1 << i, NoFrameIndex, costCalculator) + (c, v, r, 1 << lir::RegisterOperand, 1 << i, NoFrameIndex, costCalculator) + Target::MinimumRegisterCost; if ((static_cast(1) << i) == mask) { @@ -1362,7 +1363,7 @@ int pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, CostCalculator* costCalculator = 0) { - int target = NoRegister; + int target = lir::NoRegister; *cost = Target::Impossible; if (mask & c->arch->generalRegisterMask()) { @@ -1394,14 +1395,14 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, { unsigned cost; int number = pickRegisterTarget(c, v, mask, &cost, costCalculator); - return Target(number, RegisterOperand, cost); + return Target(number, lir::RegisterOperand, cost); } unsigned frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator) { return resourceCost - (c, v, c->frameResources + frameIndex, 1 << MemoryOperand, 0, frameIndex, + (c, v, c->frameResources + frameIndex, 1 << lir::MemoryOperand, 0, frameIndex, costCalculator) + Target::MinimumFrameCost; } @@ -1415,7 +1416,7 @@ pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) do { if (p->home >= 0) { Target mine - (p->home, MemoryOperand, frameCost(c, v, p->home, costCalculator)); + (p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator)); if (mine.cost == Target::MinimumFrameCost) { return mine; @@ -1436,7 +1437,7 @@ pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) unsigned count = totalFrameSize(c); for (unsigned i = 0; i < count; ++i) { - Target mine(i, MemoryOperand, frameCost(c, v, i, costCalculator)); + Target mine(i, lir::MemoryOperand, frameCost(c, v, i, costCalculator)); if (mine.cost == Target::MinimumFrameCost) { return mine; } else if (mine.cost < best.cost) { @@ -1452,7 +1453,7 @@ pickTarget(Context* c, Value* value, const SiteMask& mask, unsigned registerPenalty, Target best, CostCalculator* costCalculator) { - if (mask.typeMask & (1 << RegisterOperand)) { + if (mask.typeMask & (1 << lir::RegisterOperand)) { Target mine = pickRegisterTarget (c, value, mask.registerMask, costCalculator); @@ -1464,9 +1465,9 @@ pickTarget(Context* c, Value* value, const SiteMask& mask, } } - if (mask.typeMask & (1 << MemoryOperand)) { + if (mask.typeMask & (1 << lir::MemoryOperand)) { if (mask.frameIndex >= 0) { - Target mine(mask.frameIndex, MemoryOperand, + Target mine(mask.frameIndex, lir::MemoryOperand, frameCost(c, value, mask.frameIndex, costCalculator)); if (mine.cost == Target::MinimumFrameCost) { return mine; @@ -1497,12 +1498,12 @@ pickTarget(Context* c, Read* read, bool intersectRead, Value* value = read->value; uint32_t registerMask - = (value->type == ValueFloat ? ~0 : c->arch->generalRegisterMask()); + = (value->type == lir::ValueFloat ? ~0 : c->arch->generalRegisterMask()); SiteMask mask(~0, registerMask, AnyFrameIndex); read->intersect(&mask); - if (value->type == ValueFloat) { + if (value->type == lir::ValueFloat) { uint32_t floatMask = mask.registerMask & c->arch->floatRegisterMask(); if (floatMask) { mask.registerMask = floatMask; @@ -1616,7 +1617,7 @@ class ConstantSite: public Site { } virtual bool match(Context*, const SiteMask& mask) { - return mask.typeMask & (1 << ConstantOperand); + return mask.typeMask & (1 << lir::ConstantOperand); } virtual bool loneMatch(Context*, const SiteMask&) { @@ -1624,21 +1625,21 @@ class ConstantSite: public Site { } virtual bool matchNextWord(Context* c, Site* s, unsigned) { - return s->type(c) == ConstantOperand; + return s->type(c) == lir::ConstantOperand; } - virtual OperandType type(Context*) { - return ConstantOperand; + virtual lir::OperandType type(Context*) { + return lir::ConstantOperand; } virtual void asAssemblerOperand(Context* c, Site* high, - Assembler::Operand* result) + lir::Operand* result) { Promise* v = value; if (high != this) { v = combinedPromise(c, value, static_cast(high)->value); } - new (result) Assembler::Constant(v); + new (result) lir::Constant(v); } virtual Site* copy(Context* c) { @@ -1658,11 +1659,11 @@ class ConstantSite: public Site { } virtual SiteMask mask(Context*) { - return SiteMask(1 << ConstantOperand, 0, NoFrameIndex); + return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); } virtual SiteMask nextWordMask(Context*, unsigned) { - return SiteMask(1 << ConstantOperand, 0, NoFrameIndex); + return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); } Promise* value; @@ -1707,7 +1708,7 @@ class AddressSite: public Site { } virtual bool match(Context*, const SiteMask& mask) { - return mask.typeMask & (1 << AddressOperand); + return mask.typeMask & (1 << lir::AddressOperand); } virtual bool loneMatch(Context*, const SiteMask&) { @@ -1718,16 +1719,16 @@ class AddressSite: public Site { abort(c); } - virtual OperandType type(Context*) { - return AddressOperand; + virtual lir::OperandType type(Context*) { + return lir::AddressOperand; } virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, - Assembler::Operand* result) + lir::Operand* result) { assert(c, high == this); - new (result) Assembler::Address(address); + new (result) lir::Address(address); } virtual Site* copy(Context* c) { @@ -1747,7 +1748,7 @@ class AddressSite: public Site { } virtual SiteMask mask(Context*) { - return SiteMask(1 << AddressOperand, 0, NoFrameIndex); + return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex); } virtual SiteMask nextWordMask(Context* c, unsigned) { @@ -1773,7 +1774,7 @@ class RegisterSite: public Site { { } virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { - if (number != NoRegister) { + if (number != lir::NoRegister) { return vm::snprintf(buffer, bufferSize, "%p register %d", this, number); } else { return vm::snprintf(buffer, bufferSize, @@ -1782,11 +1783,11 @@ class RegisterSite: public Site { } virtual unsigned copyCost(Context* c, Site* s) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); if (s and (this == s or - (s->type(c) == RegisterOperand + (s->type(c) == lir::RegisterOperand and (static_cast(s)->mask_ & (1 << number))))) { return 0; @@ -1796,9 +1797,9 @@ class RegisterSite: public Site { } virtual bool match(Context* c UNUSED, const SiteMask& mask) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); - if ((mask.typeMask & (1 << RegisterOperand))) { + if ((mask.typeMask & (1 << lir::RegisterOperand))) { return ((static_cast(1) << number) & mask.registerMask); } else { return false; @@ -1806,9 +1807,9 @@ class RegisterSite: public Site { } virtual bool loneMatch(Context* c UNUSED, const SiteMask& mask) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); - if ((mask.typeMask & (1 << RegisterOperand))) { + if ((mask.typeMask & (1 << lir::RegisterOperand))) { return ((static_cast(1) << number) == mask.registerMask); } else { return false; @@ -1816,16 +1817,16 @@ class RegisterSite: public Site { } virtual bool matchNextWord(Context* c, Site* s, unsigned) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); - if (s->type(c) != RegisterOperand) { + if (s->type(c) != lir::RegisterOperand) { return false; } RegisterSite* rs = static_cast(s); unsigned size = rs->registerSize(c); if (size > TargetBytesPerWord) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); return number == rs->number; } else { uint32_t mask = c->arch->generalRegisterMask(); @@ -1835,8 +1836,8 @@ class RegisterSite: public Site { virtual void acquire(Context* c, Value* v) { Target target; - if (number != NoRegister) { - target = Target(number, RegisterOperand, 0); + if (number != lir::NoRegister) { + target = Target(number, lir::RegisterOperand, 0); } else { target = pickRegisterTarget(c, v, mask_); expect(c, target.cost < Target::Impossible); @@ -1849,53 +1850,53 @@ class RegisterSite: public Site { } virtual void release(Context* c, Value* v) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); local::release(c, c->registerResources + number, v, this); } virtual void freeze(Context* c, Value* v) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); c->registerResources[number].freeze(c, v); } virtual void thaw(Context* c, Value* v) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); c->registerResources[number].thaw(c, v); } virtual bool frozen(Context* c UNUSED) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); return c->registerResources[number].freezeCount != 0; } - virtual OperandType type(Context*) { - return RegisterOperand; + virtual lir::OperandType type(Context*) { + return lir::RegisterOperand; } virtual void asAssemblerOperand(Context* c UNUSED, Site* high, - Assembler::Operand* result) + lir::Operand* result) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); int highNumber; if (high != this) { highNumber = static_cast(high)->number; - assert(c, highNumber != NoRegister); + assert(c, highNumber != lir::NoRegister); } else { - highNumber = NoRegister; + highNumber = lir::NoRegister; } - new (result) Assembler::Register(number, highNumber); + new (result) lir::Register(number, highNumber); } virtual Site* copy(Context* c) { uint32_t mask; - if (number != NoRegister) { + if (number != lir::NoRegister) { mask = 1 << number; } else { mask = mask_; @@ -1913,30 +1914,30 @@ class RegisterSite: public Site { } virtual Site* makeNextWord(Context* c, unsigned) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); assert(c, ((1 << number) & c->arch->generalRegisterMask())); return freeRegisterSite(c, c->arch->generalRegisterMask()); } virtual SiteMask mask(Context* c UNUSED) { - return SiteMask(1 << RegisterOperand, mask_, NoFrameIndex); + return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex); } virtual SiteMask nextWordMask(Context* c, unsigned) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); if (registerSize(c) > TargetBytesPerWord) { return SiteMask - (1 << RegisterOperand, number, NoFrameIndex); + (1 << lir::RegisterOperand, number, NoFrameIndex); } else { return SiteMask - (1 << RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex); + (1 << lir::RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex); } } virtual unsigned registerSize(Context* c) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); if ((1 << number) & c->arch->floatRegisterMask()) { return c->arch->floatRegisterSize(); @@ -1946,7 +1947,7 @@ class RegisterSite: public Site { } virtual unsigned registerMask(Context* c UNUSED) { - assert(c, number != NoRegister); + assert(c, number != lir::NoRegister); return 1 << number; } @@ -1968,11 +1969,11 @@ registerSite(Context* c, int number) RegisterSite* freeRegisterSite(Context* c, uint32_t mask) { - return new(c->zone) RegisterSite(mask, NoRegister); + return new(c->zone) RegisterSite(mask, lir::NoRegister); } MemorySite* -memorySite(Context* c, int base, int offset = 0, int index = NoRegister, +memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1); class MemorySite: public Site { @@ -1995,7 +1996,7 @@ class MemorySite: public Site { if (s and (this == s or - (s->type(c) == MemoryOperand + (s->type(c) == lir::MemoryOperand and static_cast(s)->base == base and static_cast(s)->offset == offset and static_cast(s)->index == index @@ -2008,19 +2009,19 @@ class MemorySite: public Site { } bool conflicts(const SiteMask& mask) { - return (mask.typeMask & (1 << RegisterOperand)) != 0 + return (mask.typeMask & (1 << lir::RegisterOperand)) != 0 and (((1 << base) & mask.registerMask) == 0 - or (index != NoRegister + or (index != lir::NoRegister and ((1 << index) & mask.registerMask) == 0)); } virtual bool match(Context* c, const SiteMask& mask) { assert(c, acquired); - if (mask.typeMask & (1 << MemoryOperand)) { + if (mask.typeMask & (1 << lir::MemoryOperand)) { if (mask.frameIndex >= 0) { if (base == c->arch->stack()) { - assert(c, index == NoRegister); + assert(c, index == lir::NoRegister); return static_cast(frameIndexToOffset(c, mask.frameIndex)) == offset; } else { @@ -2037,9 +2038,9 @@ class MemorySite: public Site { virtual bool loneMatch(Context* c, const SiteMask& mask) { assert(c, acquired); - if (mask.typeMask & (1 << MemoryOperand)) { + if (mask.typeMask & (1 << lir::MemoryOperand)) { if (base == c->arch->stack()) { - assert(c, index == NoRegister); + assert(c, index == lir::NoRegister); if (mask.frameIndex == AnyFrameIndex) { return false; @@ -2052,7 +2053,7 @@ class MemorySite: public Site { } virtual bool matchNextWord(Context* c, Site* s, unsigned index) { - if (s->type(c) == MemoryOperand) { + if (s->type(c) == lir::MemoryOperand) { MemorySite* ms = static_cast(s); return ms->base == this->base and ((index == 1 and ms->offset == static_cast @@ -2068,12 +2069,12 @@ class MemorySite: public Site { virtual void acquire(Context* c, Value* v) { increment(c, c->registerResources + base); - if (index != NoRegister) { + if (index != lir::NoRegister) { increment(c, c->registerResources + index); } if (base == c->arch->stack()) { - assert(c, index == NoRegister); + assert(c, index == lir::NoRegister); assert (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); @@ -2086,7 +2087,7 @@ class MemorySite: public Site { virtual void release(Context* c, Value* v) { if (base == c->arch->stack()) { - assert(c, index == NoRegister); + assert(c, index == lir::NoRegister); assert (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); @@ -2095,7 +2096,7 @@ class MemorySite: public Site { } decrement(c, c->registerResources + base); - if (index != NoRegister) { + if (index != lir::NoRegister) { decrement(c, c->registerResources + index); } @@ -2107,7 +2108,7 @@ class MemorySite: public Site { c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v); } else { increment(c, c->registerResources + base); - if (index != NoRegister) { + if (index != lir::NoRegister) { increment(c, c->registerResources + index); } } @@ -2118,7 +2119,7 @@ class MemorySite: public Site { c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v); } else { decrement(c, c->registerResources + base); - if (index != NoRegister) { + if (index != lir::NoRegister) { decrement(c, c->registerResources + index); } } @@ -2129,12 +2130,12 @@ class MemorySite: public Site { and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0; } - virtual OperandType type(Context*) { - return MemoryOperand; + virtual lir::OperandType type(Context*) { + return lir::MemoryOperand; } virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, - Assembler::Operand* result) + lir::Operand* result) { // todo: endianness? assert(c, high == this @@ -2146,7 +2147,7 @@ class MemorySite: public Site { assert(c, acquired); - new (result) Assembler::Memory(base, offset, index, scale); + new (result) lir::Memory(base, offset, index, scale); } virtual Site* copy(Context* c) { @@ -2177,7 +2178,7 @@ class MemorySite: public Site { } virtual SiteMask mask(Context* c) { - return SiteMask(1 << MemoryOperand, 0, (base == c->arch->stack()) + return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack()) ? static_cast(offsetToFrameIndex(c, offset)) : NoFrameIndex); } @@ -2185,13 +2186,13 @@ class MemorySite: public Site { virtual SiteMask nextWordMask(Context* c, unsigned index) { int frameIndex; if (base == c->arch->stack()) { - assert(c, this->index == NoRegister); + assert(c, this->index == lir::NoRegister); frameIndex = static_cast(offsetToFrameIndex(c, offset)) + ((index == 1) xor c->arch->bigEndian() ? 1 : -1); } else { frameIndex = NoFrameIndex; } - return SiteMask(1 << MemoryOperand, 0, frameIndex); + return SiteMask(1 << lir::MemoryOperand, 0, frameIndex); } virtual bool isVolatile(Context* c) { @@ -2216,7 +2217,7 @@ frameSite(Context* c, int frameIndex) { assert(c, frameIndex >= 0); return memorySite - (c, c->arch->stack(), frameIndexToOffset(c, frameIndex), NoRegister, 0); + (c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0); } void @@ -2278,7 +2279,7 @@ pickTargetSite(Context* c, Read* read, bool intersectRead = false, expect(c, target.cost < Target::Impossible); - if (target.type == MemoryOperand) { + if (target.type == lir::MemoryOperand) { return frameSite(c, target.index); } else { return registerSite(c, target.index); @@ -2327,7 +2328,7 @@ class SingleRead: public Read { SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0) { - assert(c, (mask.typeMask != 1 << MemoryOperand) or mask.frameIndex >= 0); + assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0); return new(c->zone) SingleRead(mask, successor); } @@ -2630,21 +2631,21 @@ SiteMask generalRegisterMask(Context* c) { return SiteMask - (1 << RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex); + (1 << lir::RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex); } SiteMask generalRegisterOrConstantMask(Context* c) { return SiteMask - ((1 << RegisterOperand) | (1 << ConstantOperand), + ((1 << lir::RegisterOperand) | (1 << lir::ConstantOperand), c->arch->generalRegisterMask(), NoFrameIndex); } SiteMask fixedRegisterMask(int number) { - return SiteMask(1 << RegisterOperand, 1 << number, NoFrameIndex); + return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex); } class MultiRead: public Read { @@ -2884,10 +2885,10 @@ bool acceptForResolve(Context* c, Site* s, Read* read, const SiteMask& mask) { if (acceptMatch(c, s, read, mask) and (not s->frozen(c))) { - if (s->type(c) == RegisterOperand) { + if (s->type(c) == lir::RegisterOperand) { return c->availableGeneralRegisterCount > ResolveRegisterReserveCount; } else { - assert(c, s->match(c, SiteMask(1 << MemoryOperand, 0, AnyFrameIndex))); + assert(c, s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex))); return isHome(read->value, offsetToFrameIndex (c, static_cast(s)->offset)); @@ -2923,19 +2924,19 @@ move(Context* c, Value* value, Site* src, Site* dst) } if (srcSize == dstSize) { - apply(c, Move, srcSize, src, src, dstSize, dst, dst); + apply(c, lir::Move, srcSize, src, src, dstSize, dst, dst); } else if (srcSize > TargetBytesPerWord) { Site* low, *high, *other = pickSiteOrGrow(c, value, dst, &low, &high); other->freeze(c, value->nextWord); - apply(c, Move, srcSize, src, src, srcSize, low, high); + apply(c, lir::Move, srcSize, src, src, srcSize, low, high); other->thaw(c, value->nextWord); } else { Site* low, *high, *other = pickSiteOrMove(c, value, src, &low, &high); other->freeze(c, value->nextWord); - apply(c, Move, dstSize, low, high, dstSize, dst, dst); + apply(c, lir::Move, dstSize, low, high, dstSize, dst, dst); other->thaw(c, value->nextWord); } @@ -2946,12 +2947,12 @@ move(Context* c, Value* value, Site* src, Site* dst) void asAssemblerOperand(Context* c, Site* low, Site* high, - Assembler::Operand* result) + lir::Operand* result) { low->asAssemblerOperand(c, high, result); } -class OperandUnion: public Assembler::Operand { +class OperandUnion: public lir::Operand { // must be large enough and aligned properly to hold any operand // type (we'd use an actual union type here, except that classes // with constructors cannot be used in a union): @@ -2959,37 +2960,39 @@ class OperandUnion: public Assembler::Operand { }; void -apply(Context* c, UnaryOperation op, +apply(Context* c, lir::UnaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High) { assert(c, s1Low->type(c) == s1High->type(c)); - OperandType s1Type = s1Low->type(c); + lir::OperandType s1Type = s1Low->type(c); OperandUnion s1Union; asAssemblerOperand(c, s1Low, s1High, &s1Union); - c->assembler->apply(op, s1Size, s1Type, &s1Union); + c->assembler->apply(op, + OperandInfo(s1Size, s1Type, &s1Union)); } void -apply(Context* c, BinaryOperation op, +apply(Context* c, lir::BinaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High, unsigned s2Size, Site* s2Low, Site* s2High) { assert(c, s1Low->type(c) == s1High->type(c)); assert(c, s2Low->type(c) == s2High->type(c)); - OperandType s1Type = s1Low->type(c); + lir::OperandType s1Type = s1Low->type(c); OperandUnion s1Union; asAssemblerOperand(c, s1Low, s1High, &s1Union); - OperandType s2Type = s2Low->type(c); + lir::OperandType s2Type = s2Low->type(c); OperandUnion s2Union; asAssemblerOperand(c, s2Low, s2High, &s2Union); - c->assembler->apply(op, s1Size, s1Type, &s1Union, - s2Size, s2Type, &s2Union); + c->assembler->apply(op, + OperandInfo(s1Size, s1Type, &s1Union), + OperandInfo(s2Size, s2Type, &s2Union)); } void -apply(Context* c, TernaryOperation op, +apply(Context* c, lir::TernaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High) @@ -2998,18 +3001,19 @@ apply(Context* c, TernaryOperation op, assert(c, s2Low->type(c) == s2High->type(c)); assert(c, s3Low->type(c) == s3High->type(c)); - OperandType s1Type = s1Low->type(c); + lir::OperandType s1Type = s1Low->type(c); OperandUnion s1Union; asAssemblerOperand(c, s1Low, s1High, &s1Union); - OperandType s2Type = s2Low->type(c); + lir::OperandType s2Type = s2Low->type(c); OperandUnion s2Union; asAssemblerOperand(c, s2Low, s2High, &s2Union); - OperandType s3Type = s3Low->type(c); + lir::OperandType s3Type = s3Low->type(c); OperandUnion s3Union; asAssemblerOperand(c, s3Low, s3High, &s3Union); - c->assembler->apply(op, s1Size, s1Type, &s1Union, - s2Size, s2Type, &s2Union, - s3Size, s3Type, &s3Union); + c->assembler->apply(op, + OperandInfo(s1Size, s1Type, &s1Union), + OperandInfo(s2Size, s2Type, &s2Union), + OperandInfo(s3Size, s3Type, &s3Union)); } void @@ -3072,13 +3076,13 @@ clean(Context* c, Value* v, unsigned popIndex) { for (SiteIterator it(c, v); it.hasMore();) { Site* s = it.next(); - if (not (s->match(c, SiteMask(1 << MemoryOperand, 0, AnyFrameIndex)) + if (not (s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex)) and offsetToFrameIndex (c, static_cast(s)->offset) >= popIndex)) { if (false and - s->match(c, SiteMask(1 << MemoryOperand, 0, AnyFrameIndex))) + s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex))) { char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "remove %s from %p at %d pop offset 0x%x\n", @@ -3132,7 +3136,7 @@ saveLocals(Context* c, Event* e) } addRead(c, e, local->value, SiteMask - (1 << MemoryOperand, 0, local::frameIndex(c, li))); + (1 << lir::MemoryOperand, 0, local::frameIndex(c, li))); } } } @@ -3198,7 +3202,7 @@ class CallEvent: public Event { fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value); } - targetMask = SiteMask(1 << MemoryOperand, 0, frameIndex); + targetMask = SiteMask(1 << lir::MemoryOperand, 0, frameIndex); } addRead(c, this, s->value, targetMask); @@ -3221,7 +3225,7 @@ class CallEvent: public Event { uint8_t typeMask; uint64_t planRegisterMask; c->arch->plan - ((flags & Compiler::Aligned) ? AlignedCall : Call, TargetBytesPerWord, + ((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, TargetBytesPerWord, &typeMask, &planRegisterMask, &thunk); assert(c, not thunk); @@ -3290,7 +3294,7 @@ class CallEvent: public Event { framePointerSurrogate = v; addRead(c, this, v, generalRegisterMask(c)); } else { - addRead(c, this, v, SiteMask(1 << MemoryOperand, 0, frameIndex)); + addRead(c, this, v, SiteMask(1 << lir::MemoryOperand, 0, frameIndex)); } } } @@ -3321,7 +3325,7 @@ class CallEvent: public Event { } addRead(c, this, stack->value, SiteMask - (1 << MemoryOperand, 0, logicalIndex)); + (1 << lir::MemoryOperand, 0, logicalIndex)); } stack = stack->next; @@ -3336,25 +3340,25 @@ class CallEvent: public Event { } virtual void compile(Context* c) { - UnaryOperation op; + lir::UnaryOperation op; if (TailCalls and (flags & Compiler::TailJump)) { if (flags & Compiler::LongJumpOrCall) { if (flags & Compiler::Aligned) { - op = AlignedLongJump; + op = lir::AlignedLongJump; } else { - op = LongJump; + op = lir::LongJump; } } else if (flags & Compiler::Aligned) { - op = AlignedJump; + op = lir::AlignedJump; } else { - op = Jump; + op = lir::Jump; } assert(c, returnAddressSurrogate == 0 - or returnAddressSurrogate->source->type(c) == RegisterOperand); + or returnAddressSurrogate->source->type(c) == lir::RegisterOperand); assert(c, framePointerSurrogate == 0 - or framePointerSurrogate->source->type(c) == RegisterOperand); + or framePointerSurrogate->source->type(c) == lir::RegisterOperand); int ras; if (returnAddressSurrogate) { @@ -3363,7 +3367,7 @@ class CallEvent: public Event { ras = static_cast (returnAddressSurrogate->source)->number; } else { - ras = NoRegister; + ras = lir::NoRegister; } int fps; @@ -3373,7 +3377,7 @@ class CallEvent: public Event { fps = static_cast (framePointerSurrogate->source)->number; } else { - fps = NoRegister; + fps = lir::NoRegister; } int offset @@ -3383,14 +3387,14 @@ class CallEvent: public Event { c->assembler->popFrameForTailCall(c->alignedFrameSize, offset, ras, fps); } else if (flags & Compiler::LongJumpOrCall) { if (flags & Compiler::Aligned) { - op = AlignedLongCall; + op = lir::AlignedLongCall; } else { - op = LongCall; + op = lir::LongCall; } } else if (flags & Compiler::Aligned) { - op = AlignedCall; + op = lir::AlignedCall; } else { - op = Call; + op = lir::Call; } apply(c, op, TargetBytesPerWord, address->source, address->source); @@ -3504,7 +3508,7 @@ appendReturn(Context* c, unsigned size, Value* value) } void -maybeMove(Context* c, BinaryOperation type, unsigned srcSize, +maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, const SiteMask& dstMask) { @@ -3526,10 +3530,10 @@ maybeMove(Context* c, BinaryOperation type, unsigned srcSize, if (cost) { // todo: let c->arch->planMove decide this: - bool useTemporary = ((target->type(c) == MemoryOperand - and src->source->type(c) == MemoryOperand) + bool useTemporary = ((target->type(c) == lir::MemoryOperand + and src->source->type(c) == lir::MemoryOperand) or (srcSelectSize < dstSize - and target->type(c) != RegisterOperand)); + and target->type(c) != lir::RegisterOperand)); src->source->freeze(c, src); @@ -3539,7 +3543,7 @@ maybeMove(Context* c, BinaryOperation type, unsigned srcSize, bool addOffset = srcSize != srcSelectSize and c->arch->bigEndian() - and src->source->type(c) == MemoryOperand; + and src->source->type(c) == lir::MemoryOperand; if (addOffset) { static_cast(src->source)->offset @@ -3575,12 +3579,12 @@ maybeMove(Context* c, BinaryOperation type, unsigned srcSize, c->arch->planSource(type, dstSize, &srcTypeMask, &srcRegisterMask, dstSize, &thunk); - if (src->type == ValueGeneral) { + if (src->type == lir::ValueGeneral) { srcRegisterMask &= c->arch->generalRegisterMask(); } assert(c, thunk == 0); - assert(c, dstMask.typeMask & srcTypeMask & (1 << RegisterOperand)); + assert(c, dstMask.typeMask & srcTypeMask & (1 << lir::RegisterOperand)); Site* tmpTarget = freeRegisterSite (c, dstMask.registerMask & srcRegisterMask); @@ -3617,7 +3621,7 @@ maybeMove(Context* c, BinaryOperation type, unsigned srcSize, tmpTarget->freeze(c, dst); - apply(c, Move, dstSize, tmpTarget, tmpTarget, dstSize, target, target); + apply(c, lir::Move, dstSize, tmpTarget, tmpTarget, dstSize, target, target); tmpTarget->thaw(c, dst); @@ -3696,7 +3700,7 @@ pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, } Value* -value(Context* c, ValueType type, Site* site = 0, Site* target = 0) +value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0) { return new(c->zone) Value(site, target, type); } @@ -3735,7 +3739,7 @@ maybeSplit(Context* c, Value* v) class MoveEvent: public Event { public: - MoveEvent(Context* c, BinaryOperation type, unsigned srcSize, + MoveEvent(Context* c, lir::BinaryOperation type, unsigned srcSize, unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, const SiteMask& srcLowMask, const SiteMask& srcHighMask): Event(c), type(type), srcSize(srcSize), srcSelectSize(srcSelectSize), @@ -3786,7 +3790,7 @@ class MoveEvent: public Event { if (dst->target) { if (dstSize > TargetBytesPerWord) { if (src->source->registerSize(c) > TargetBytesPerWord) { - apply(c, Move, srcSelectSize, src->source, src->source, + apply(c, lir::Move, srcSelectSize, src->source, src->source, dstSize, dst->target, dst->target); if (live(c, dst) == 0) { @@ -3798,17 +3802,17 @@ class MoveEvent: public Event { } else { src->nextWord->source->freeze(c, src->nextWord); - maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, + maybeMove(c, lir::Move, TargetBytesPerWord, TargetBytesPerWord, src, TargetBytesPerWord, dst, dstLowMask); src->nextWord->source->thaw(c, src->nextWord); maybeMove - (c, Move, TargetBytesPerWord, TargetBytesPerWord, src->nextWord, + (c, lir::Move, TargetBytesPerWord, TargetBytesPerWord, src->nextWord, TargetBytesPerWord, dst->nextWord, dstHighMask); } } else { - maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, + maybeMove(c, lir::Move, TargetBytesPerWord, TargetBytesPerWord, src, TargetBytesPerWord, dst, dstLowMask); } } else { @@ -3827,7 +3831,7 @@ class MoveEvent: public Event { assert(c, srcSelectSize == TargetBytesPerWord); if (dst->nextWord->target or live(c, dst->nextWord)) { - assert(c, dstLowMask.typeMask & (1 << RegisterOperand)); + assert(c, dstLowMask.typeMask & (1 << lir::RegisterOperand)); Site* low = freeRegisterSite(c, dstLowMask.registerMask); @@ -3844,14 +3848,14 @@ class MoveEvent: public Event { srcb, dstb, src); } - apply(c, Move, TargetBytesPerWord, src->source, src->source, + apply(c, lir::Move, TargetBytesPerWord, src->source, src->source, TargetBytesPerWord, low, low); low->thaw(c, dst); src->source->thaw(c, src); - assert(c, dstHighMask.typeMask & (1 << RegisterOperand)); + assert(c, dstHighMask.typeMask & (1 << lir::RegisterOperand)); Site* high = freeRegisterSite(c, dstHighMask.registerMask); @@ -3868,7 +3872,7 @@ class MoveEvent: public Event { srcb, dstb, dst, dst->nextWord); } - apply(c, Move, TargetBytesPerWord, low, low, dstSize, low, high); + apply(c, lir::Move, TargetBytesPerWord, low, low, dstSize, low, high); high->thaw(c, dst->nextWord); @@ -3883,7 +3887,7 @@ class MoveEvent: public Event { } } - BinaryOperation type; + lir::BinaryOperation type; unsigned srcSize; unsigned srcSelectSize; Value* src; @@ -3892,7 +3896,7 @@ class MoveEvent: public Event { }; void -appendMove(Context* c, BinaryOperation type, unsigned srcSize, +appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst) { bool thunk; @@ -3916,7 +3920,7 @@ findConstantSite(Context* c, Value* v) { for (SiteIterator it(c, v); it.hasMore();) { Site* s = it.next(); - if (s->type(c) == ConstantOperand) { + if (s->type(c) == lir::ConstantOperand) { return static_cast(s); } } @@ -3985,7 +3989,7 @@ thawSource(Context* c, unsigned size, Value* v) class CombineEvent: public Event { public: - CombineEvent(Context* c, TernaryOperation type, + CombineEvent(Context* c, lir::TernaryOperation type, unsigned firstSize, Value* first, unsigned secondSize, Value* second, unsigned resultSize, Value* result, @@ -4084,7 +4088,7 @@ class CombineEvent: public Event { } } - TernaryOperation type; + lir::TernaryOperation type; unsigned firstSize; Value* first; unsigned secondSize; @@ -4390,14 +4394,14 @@ register_(Context* c, int number) | c->arch->floatRegisterMask())); Site* s = registerSite(c, number); - ValueType type = ((1 << number) & c->arch->floatRegisterMask()) - ? ValueFloat: ValueGeneral; + lir::ValueType type = ((1 << number) & c->arch->floatRegisterMask()) + ? lir::ValueFloat: lir::ValueGeneral; return value(c, type, s, s); } void -appendCombine(Context* c, TernaryOperation type, +appendCombine(Context* c, lir::TernaryOperation type, unsigned firstSize, Value* first, unsigned secondSize, Value* second, unsigned resultSize, Value* result) @@ -4435,7 +4439,7 @@ appendCombine(Context* c, TernaryOperation type, c->stack = oldStack; appendCall - (c, value(c, ValueGeneral, constantSite(c, handler)), 0, 0, result, + (c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, resultSize, argumentStack, stackSize, 0); } else { append @@ -4454,7 +4458,7 @@ appendCombine(Context* c, TernaryOperation type, class TranslateEvent: public Event { public: - TranslateEvent(Context* c, BinaryOperation type, unsigned valueSize, + TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize, Value* value, unsigned resultSize, Value* result, const SiteMask& valueLowMask, const SiteMask& valueHighMask): @@ -4521,7 +4525,7 @@ class TranslateEvent: public Event { } } - BinaryOperation type; + lir::BinaryOperation type; unsigned valueSize; unsigned resultSize; Value* value; @@ -4532,7 +4536,7 @@ class TranslateEvent: public Event { }; void -appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, +appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, Value* first, unsigned resultSize, Value* result) { bool thunk; @@ -4552,7 +4556,7 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, appendCall (c, value - (c, ValueGeneral, constantSite + (c, lir::ValueGeneral, constantSite (c, c->client->getThunk(type, firstSize, resultSize))), 0, 0, result, resultSize, argumentStack, ceilingDivide(firstSize, TargetBytesPerWord), 0); @@ -4567,7 +4571,7 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, class OperationEvent: public Event { public: - OperationEvent(Context* c, Operation op): + OperationEvent(Context* c, lir::Operation op): Event(c), op(op) { } @@ -4579,11 +4583,11 @@ class OperationEvent: public Event { c->assembler->apply(op); } - Operation op; + lir::Operation op; }; void -appendOperation(Context* c, Operation op) +appendOperation(Context* c, lir::Operation op) { append(c, new(c->zone) OperationEvent(c, op)); } @@ -4592,7 +4596,7 @@ void moveIfConflict(Context* c, Value* v, MemorySite* s) { if (v->reads) { - SiteMask mask(1 << RegisterOperand, ~0, AnyFrameIndex); + SiteMask mask(1 << lir::RegisterOperand, ~0, AnyFrameIndex); v->reads->intersect(&mask); if (s->conflicts(mask)) { maybeMove(c, v->reads, true, false); @@ -4626,23 +4630,23 @@ class MemoryEvent: public Event { ConstantSite* constant = findConstantSite(c, index); if (constant) { - indexRegister = NoRegister; + indexRegister = lir::NoRegister; displacement += (constant->value->value() * scale); scale = 1; } else { - assert(c, index->source->type(c) == RegisterOperand); + assert(c, index->source->type(c) == lir::RegisterOperand); indexRegister = static_cast(index->source)->number; } } else { - indexRegister = NoRegister; + indexRegister = lir::NoRegister; } - assert(c, base->source->type(c) == RegisterOperand); + assert(c, base->source->type(c) == lir::RegisterOperand); int baseRegister = static_cast(base->source)->number; popRead(c, this, base); if (index) { - if (TargetBytesPerWord == 8 and indexRegister != NoRegister) { - apply(c, Move, 4, index->source, index->source, + if (TargetBytesPerWord == 8 and indexRegister != lir::NoRegister) { + apply(c, lir::Move, 4, index->source, index->source, 8, index->source, index->source); } @@ -4701,59 +4705,59 @@ unordered(double a, double b) } bool -shouldJump(Context* c, TernaryOperation type, unsigned size, int64_t b, +shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b, int64_t a) { switch (type) { - case JumpIfEqual: + case lir::JumpIfEqual: return a == b; - case JumpIfNotEqual: + case lir::JumpIfNotEqual: return a != b; - case JumpIfLess: + case lir::JumpIfLess: return a < b; - case JumpIfGreater: + case lir::JumpIfGreater: return a > b; - case JumpIfLessOrEqual: + case lir::JumpIfLessOrEqual: return a <= b; - case JumpIfGreaterOrEqual: + case lir::JumpIfGreaterOrEqual: return a >= b; - case JumpIfFloatEqual: + case lir::JumpIfFloatEqual: return asFloat(size, a) == asFloat(size, b); - case JumpIfFloatNotEqual: + case lir::JumpIfFloatNotEqual: return asFloat(size, a) != asFloat(size, b); - case JumpIfFloatLess: + case lir::JumpIfFloatLess: return asFloat(size, a) < asFloat(size, b); - case JumpIfFloatGreater: + case lir::JumpIfFloatGreater: return asFloat(size, a) > asFloat(size, b); - case JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqual: return asFloat(size, a) <= asFloat(size, b); - case JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: return asFloat(size, a) >= asFloat(size, b); - case JumpIfFloatLessOrUnordered: + case lir::JumpIfFloatLessOrUnordered: return asFloat(size, a) < asFloat(size, b) or unordered(asFloat(size, a), asFloat(size, b)); - case JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: return asFloat(size, a) > asFloat(size, b) or unordered(asFloat(size, a), asFloat(size, b)); - case JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfFloatLessOrEqualOrUnordered: return asFloat(size, a) <= asFloat(size, b) or unordered(asFloat(size, a), asFloat(size, b)); - case JumpIfFloatGreaterOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: return asFloat(size, a) >= asFloat(size, b) or unordered(asFloat(size, a), asFloat(size, b)); @@ -4762,31 +4766,31 @@ shouldJump(Context* c, TernaryOperation type, unsigned size, int64_t b, } } -TernaryOperation -thunkBranch(Context* c, TernaryOperation type) +lir::TernaryOperation +thunkBranch(Context* c, lir::TernaryOperation type) { switch (type) { - case JumpIfFloatEqual: - return JumpIfEqual; + case lir::JumpIfFloatEqual: + return lir::JumpIfEqual; - case JumpIfFloatNotEqual: - return JumpIfNotEqual; + case lir::JumpIfFloatNotEqual: + return lir::JumpIfNotEqual; - case JumpIfFloatLess: - case JumpIfFloatLessOrUnordered: - return JumpIfLess; + case lir::JumpIfFloatLess: + case lir::JumpIfFloatLessOrUnordered: + return lir::JumpIfLess; - case JumpIfFloatGreater: - case JumpIfFloatGreaterOrUnordered: - return JumpIfGreater; + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatGreaterOrUnordered: + return lir::JumpIfGreater; - case JumpIfFloatLessOrEqual: - case JumpIfFloatLessOrEqualOrUnordered: - return JumpIfLessOrEqual; + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqualOrUnordered: + return lir::JumpIfLessOrEqual; - case JumpIfFloatGreaterOrEqual: - case JumpIfFloatGreaterOrEqualOrUnordered: - return JumpIfGreaterOrEqual; + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return lir::JumpIfGreaterOrEqual; default: abort(c); @@ -4795,7 +4799,7 @@ thunkBranch(Context* c, TernaryOperation type) class BranchEvent: public Event { public: - BranchEvent(Context* c, TernaryOperation type, unsigned size, + BranchEvent(Context* c, lir::TernaryOperation type, unsigned size, Value* first, Value* second, Value* address, const SiteMask& firstLowMask, const SiteMask& firstHighMask, @@ -4840,7 +4844,7 @@ class BranchEvent: public Event { } if (shouldJump(c, type, size, firstValue, secondValue)) { - apply(c, Jump, TargetBytesPerWord, address->source, address->source); + apply(c, lir::Jump, TargetBytesPerWord, address->source, address->source); } } else { freezeSource(c, size, first); @@ -4864,7 +4868,7 @@ class BranchEvent: public Event { virtual bool isBranch() { return true; } - TernaryOperation type; + lir::TernaryOperation type; unsigned size; Value* first; Value* second; @@ -4872,7 +4876,7 @@ class BranchEvent: public Event { }; void -appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, +appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first, Value* second, Value* address) { bool thunk; @@ -4900,14 +4904,14 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, Stack* argumentStack = c->stack; c->stack = oldStack; - Value* result = value(c, ValueGeneral); + Value* result = value(c, lir::ValueGeneral); appendCall (c, value - (c, ValueGeneral, constantSite(c, handler)), 0, 0, result, 4, + (c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4, argumentStack, ceilingDivide(size, TargetBytesPerWord) * 2, 0); appendBranch(c, thunkBranch(c, type), 4, value - (c, ValueGeneral, constantSite(c, static_cast(0))), + (c, lir::ValueGeneral, constantSite(c, static_cast(0))), result, address); } else { append @@ -4923,7 +4927,7 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, class JumpEvent: public Event { public: - JumpEvent(Context* c, UnaryOperation type, Value* address, bool exit, + JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit, bool cleanLocals): Event(c), type(type), address(address), exit(exit), cleanLocals(cleanLocals) @@ -4965,14 +4969,14 @@ class JumpEvent: public Event { return exit or unreachable(this); } - UnaryOperation type; + lir::UnaryOperation type; Value* address; bool exit; bool cleanLocals; }; void -appendJump(Context* c, UnaryOperation type, Value* address, bool exit = false, +appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false, bool cleanLocals = false) { append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); @@ -5001,22 +5005,25 @@ class BoundsCheckEvent: public Event { if (constant) { if (constant->value->value() < 0) { - Assembler::Constant handlerConstant(resolved(c, handler)); - a->apply(Call, TargetBytesPerWord, ConstantOperand, &handlerConstant); + lir::Constant handlerConstant(resolved(c, handler)); + a->apply(lir::Call, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); } } else { outOfBoundsPromise = codePromise(c, static_cast(0)); ConstantSite zero(resolved(c, 0)); ConstantSite oob(outOfBoundsPromise); - apply(c, JumpIfLess, 4, &zero, &zero, 4, index->source, index->source, - TargetBytesPerWord, &oob, &oob); + apply(c, lir::JumpIfLess, + 4, &zero, &zero, + 4, index->source, index->source, + TargetBytesPerWord, &oob, &oob); } if (constant == 0 or constant->value->value() >= 0) { - assert(c, object->source->type(c) == RegisterOperand); + assert(c, object->source->type(c) == lir::RegisterOperand); MemorySite length(static_cast(object->source)->number, - lengthOffset, NoRegister, 1); + lengthOffset, lir::NoRegister, 1); length.acquired = true; CodePromise* nextPromise = codePromise(c, static_cast(0)); @@ -5024,8 +5031,10 @@ class BoundsCheckEvent: public Event { freezeSource(c, TargetBytesPerWord, index); ConstantSite next(nextPromise); - apply(c, JumpIfGreater, 4, index->source, index->source, 4, &length, - &length, TargetBytesPerWord, &next, &next); + apply(c, lir::JumpIfGreater, + 4, index->source, + index->source, 4, &length, + &length, TargetBytesPerWord, &next, &next); thawSource(c, TargetBytesPerWord, index); @@ -5033,8 +5042,9 @@ class BoundsCheckEvent: public Event { outOfBoundsPromise->offset = a->offset(); } - Assembler::Constant handlerConstant(resolved(c, handler)); - a->apply(Call, TargetBytesPerWord, ConstantOperand, &handlerConstant); + lir::Constant handlerConstant(resolved(c, handler)); + a->apply(lir::Call, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); nextPromise->offset = a->offset(); } @@ -5400,7 +5410,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, buffer, v, el.localIndex, frameIndex(c, &el)); } - Value dummy(0, 0, ValueGeneral); + Value dummy(0, 0, lir::ValueGeneral); addSite(c, &dummy, s); removeSite(c, &dummy, s); freeze(c, frozen, s, 0); @@ -5420,7 +5430,7 @@ resolveSourceSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) Read* r = live(c, v); if (r and sites[el.localIndex] == 0) { - SiteMask mask((1 << RegisterOperand) | (1 << MemoryOperand), + SiteMask mask((1 << lir::RegisterOperand) | (1 << lir::MemoryOperand), c->arch->generalRegisterMask(), AnyFrameIndex); Site* s = pickSourceSite @@ -5454,7 +5464,7 @@ resolveTargetSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) Read* r = live(c, v); if (r and sites[el.localIndex] == 0) { - SiteMask mask((1 << RegisterOperand) | (1 << MemoryOperand), + SiteMask mask((1 << lir::RegisterOperand) | (1 << lir::MemoryOperand), c->arch->generalRegisterMask(), AnyFrameIndex); Site* s = pickSourceSite @@ -6057,7 +6067,7 @@ class MyCompiler: public Compiler { virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) { appendSaveLocals(&c); - appendJump(&c, Jump, static_cast(address), false, true); + appendJump(&c, lir::Jump, static_cast(address), false, true); static_cast(subroutine)->forkState = local::saveState(&c); } @@ -6216,17 +6226,17 @@ class MyCompiler: public Compiler { return p; } - virtual Operand* constant(int64_t value, OperandType type) { + virtual Operand* constant(int64_t value, Compiler::OperandType type) { return promiseConstant(resolved(&c, value), type); } - virtual Operand* promiseConstant(Promise* value, OperandType type) { + virtual Operand* promiseConstant(Promise* value, Compiler::OperandType type) { return local::value (&c, valueType(&c, type), local::constantSite(&c, value)); } virtual Operand* address(Promise* address) { - return value(&c, ValueGeneral, local::addressSite(&c, address)); + return value(&c, lir::ValueGeneral, local::addressSite(&c, address)); } virtual Operand* memory(Operand* base, @@ -6254,7 +6264,7 @@ class MyCompiler: public Compiler { virtual void push(unsigned footprint UNUSED) { assert(&c, footprint == 1); - Value* v = value(&c, ValueGeneral); + Value* v = value(&c, lir::ValueGeneral); Stack* s = local::stack(&c, v, c.stack); v->home = frameIndex(&c, s->index + c.localFootprint); @@ -6280,7 +6290,7 @@ class MyCompiler: public Compiler { } virtual void pushed() { - Value* v = value(&c, ValueGeneral); + Value* v = value(&c, lir::ValueGeneral); appendFrameSite (&c, v, frameIndex (&c, (c.stack ? c.stack->index : 0) + c.localFootprint)); @@ -6463,7 +6473,7 @@ class MyCompiler: public Compiler { Local* local = e->locals() + i; if (local->value) { initLocal - (1, i, local->value->type == ValueGeneral ? IntegerType : FloatType); + (1, i, local->value->type == lir::ValueGeneral ? IntegerType : FloatType); } } @@ -6492,7 +6502,7 @@ class MyCompiler: public Compiler { virtual void store(unsigned srcSize, Operand* src, unsigned dstSize, Operand* dst) { - appendMove(&c, Move, srcSize, srcSize, static_cast(src), + appendMove(&c, lir::Move, srcSize, srcSize, static_cast(src), dstSize, static_cast(dst)); } @@ -6502,7 +6512,7 @@ class MyCompiler: public Compiler { assert(&c, dstSize >= TargetBytesPerWord); Value* dst = value(&c, static_cast(src)->type); - appendMove(&c, Move, srcSize, srcSelectSize, static_cast(src), + appendMove(&c, lir::Move, srcSize, srcSelectSize, static_cast(src), dstSize, dst); return dst; } @@ -6513,7 +6523,7 @@ class MyCompiler: public Compiler { assert(&c, dstSize >= TargetBytesPerWord); Value* dst = value(&c, static_cast(src)->type); - appendMove(&c, MoveZ, srcSize, srcSelectSize, static_cast(src), + appendMove(&c, lir::MoveZ, srcSize, srcSelectSize, static_cast(src), dstSize, dst); return dst; } @@ -6521,140 +6531,140 @@ class MyCompiler: public Compiler { virtual void jumpIfEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); - appendBranch(&c, JumpIfEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfNotEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); - appendBranch(&c, JumpIfNotEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfNotEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfLess(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); - appendBranch(&c, JumpIfLess, size, static_cast(a), + appendBranch(&c, lir::JumpIfLess, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfGreater(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); - appendBranch(&c, JumpIfGreater, size, static_cast(a), + appendBranch(&c, lir::JumpIfGreater, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfLessOrEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); - appendBranch(&c, JumpIfLessOrEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfLessOrEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfGreaterOrEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); - appendBranch(&c, JumpIfGreaterOrEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfGreaterOrEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfFloatEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatNotEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatNotEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfFloatNotEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatLess(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatLess, size, static_cast(a), + appendBranch(&c, lir::JumpIfFloatLess, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatGreater(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatGreater, size, static_cast(a), + appendBranch(&c, lir::JumpIfFloatGreater, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatLessOrEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatLessOrEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfFloatLessOrEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatGreaterOrEqual(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatGreaterOrEqual, size, static_cast(a), + appendBranch(&c, lir::JumpIfFloatGreaterOrEqual, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatLessOrUnordered(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatLessOrUnordered, size, static_cast(a), + appendBranch(&c, lir::JumpIfFloatLessOrUnordered, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jumpIfFloatGreaterOrUnordered(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatGreaterOrUnordered, size, + appendBranch(&c, lir::JumpIfFloatGreaterOrUnordered, size, static_cast(a), static_cast(b), static_cast(address)); } @@ -6662,10 +6672,10 @@ class MyCompiler: public Compiler { virtual void jumpIfFloatLessOrEqualOrUnordered(unsigned size, Operand* a, Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatLessOrEqualOrUnordered, size, + appendBranch(&c, lir::JumpIfFloatLessOrEqualOrUnordered, size, static_cast(a), static_cast(b), static_cast(address)); } @@ -6674,240 +6684,239 @@ class MyCompiler: public Compiler { Operand* b, Operand* address) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); - appendBranch(&c, JumpIfFloatGreaterOrEqualOrUnordered, size, + appendBranch(&c, lir::JumpIfFloatGreaterOrEqualOrUnordered, size, static_cast(a), static_cast(b), static_cast(address)); } virtual void jmp(Operand* address) { - appendJump(&c, Jump, static_cast(address)); + appendJump(&c, lir::Jump, static_cast(address)); } virtual void exit(Operand* address) { - appendJump(&c, Jump, static_cast(address), true); + appendJump(&c, lir::Jump, static_cast(address), true); } virtual Operand* add(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, Add, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::Add, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* sub(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, Subtract, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::Subtract, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* mul(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, Multiply, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::Multiply, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* div(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, Divide, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::Divide, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* rem(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral - and static_cast(b)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, Remainder, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral + and static_cast(b)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::Remainder, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* fadd(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); - Value* result = value(&c, ValueFloat); - static_cast(a)->type = static_cast(b)->type = ValueFloat; - appendCombine(&c, FloatAdd, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); + static_cast(a)->type = static_cast(b)->type = lir::ValueFloat; + appendCombine(&c, lir::FloatAdd, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* fsub(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); - Value* result = value(&c, ValueFloat); - static_cast(a)->type = static_cast(b)->type = ValueFloat; - appendCombine(&c, FloatSubtract, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); + static_cast(a)->type = static_cast(b)->type = lir::ValueFloat; + appendCombine(&c, lir::FloatSubtract, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* fmul(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); - Value* result = value(&c, ValueFloat); - static_cast(a)->type = static_cast(b)->type = ValueFloat; - appendCombine(&c, FloatMultiply, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); + static_cast(a)->type = static_cast(b)->type = lir::ValueFloat; + appendCombine(&c, lir::FloatMultiply, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* fdiv(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); - Value* result = value(&c, ValueFloat); - appendCombine(&c, FloatDivide, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); + appendCombine(&c, lir::FloatDivide, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* frem(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueFloat - and static_cast(b)->type == ValueFloat); - Value* result = value(&c, ValueFloat); - appendCombine(&c, FloatRemainder, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueFloat + and static_cast(b)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); + appendCombine(&c, lir::FloatRemainder, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* shl(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, ShiftLeft, TargetBytesPerWord, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::ShiftLeft, TargetBytesPerWord, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* shr(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, ShiftRight, TargetBytesPerWord, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::ShiftRight, TargetBytesPerWord, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* ushr(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); appendCombine - (&c, UnsignedShiftRight, TargetBytesPerWord, static_cast(a), + (&c, lir::UnsignedShiftRight, TargetBytesPerWord, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* and_(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, And, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::And, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* or_(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, Or, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::Or, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* xor_(unsigned size, Operand* a, Operand* b) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, Xor, size, static_cast(a), + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendCombine(&c, lir::Xor, size, static_cast(a), size, static_cast(b), size, result); return result; } virtual Operand* neg(unsigned size, Operand* a) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendTranslate(&c, Negate, size, static_cast(a), size, result); + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendTranslate(&c, lir::Negate, size, static_cast(a), size, result); return result; } virtual Operand* fneg(unsigned size, Operand* a) { - assert(&c, static_cast(a)->type == ValueFloat); - Value* result = value(&c, ValueFloat); - appendTranslate - (&c, FloatNegate, size, static_cast(a), size, result); + assert(&c, static_cast(a)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); + appendTranslate(&c, lir::FloatNegate, size, static_cast(a), size, result); return result; } virtual Operand* abs(unsigned size, Operand* a) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendTranslate(&c, Absolute, size, static_cast(a), size, result); + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueGeneral); + appendTranslate(&c, lir::Absolute, size, static_cast(a), size, result); return result; } virtual Operand* fabs(unsigned size, Operand* a) { - assert(&c, static_cast(a)->type == ValueFloat); - Value* result = value(&c, ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); appendTranslate - (&c, FloatAbsolute, size, static_cast(a), size, result); + (&c, lir::FloatAbsolute, size, static_cast(a), size, result); return result; } virtual Operand* fsqrt(unsigned size, Operand* a) { - assert(&c, static_cast(a)->type == ValueFloat); - Value* result = value(&c, ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); appendTranslate - (&c, FloatSquareRoot, size, static_cast(a), size, result); + (&c, lir::FloatSquareRoot, size, static_cast(a), size, result); return result; } virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) { - assert(&c, static_cast(a)->type == ValueFloat); - Value* result = value(&c, ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueFloat); appendTranslate - (&c, Float2Float, aSize, static_cast(a), resSize, result); + (&c, lir::Float2Float, aSize, static_cast(a), resSize, result); return result; } virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) { - assert(&c, static_cast(a)->type == ValueFloat); - Value* result = value(&c, ValueGeneral); + assert(&c, static_cast(a)->type == lir::ValueFloat); + Value* result = value(&c, lir::ValueGeneral); appendTranslate - (&c, Float2Int, aSize, static_cast(a), resSize, result); + (&c, lir::Float2Int, aSize, static_cast(a), resSize, result); return result; } virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) { - assert(&c, static_cast(a)->type == ValueGeneral); - Value* result = value(&c, ValueFloat); + assert(&c, static_cast(a)->type == lir::ValueGeneral); + Value* result = value(&c, lir::ValueFloat); appendTranslate - (&c, Int2Float, aSize, static_cast(a), resSize, result); + (&c, lir::Int2Float, aSize, static_cast(a), resSize, result); return result; } virtual void trap() { - appendOperation(&c, Trap); + appendOperation(&c, lir::Trap); } virtual void loadBarrier() { - appendOperation(&c, LoadBarrier); + appendOperation(&c, lir::LoadBarrier); } virtual void storeStoreBarrier() { - appendOperation(&c, StoreStoreBarrier); + appendOperation(&c, lir::StoreStoreBarrier); } virtual void storeLoadBarrier() { - appendOperation(&c, StoreLoadBarrier); + appendOperation(&c, lir::StoreLoadBarrier); } virtual void compile(uintptr_t stackOverflowHandler, @@ -6982,7 +6991,8 @@ class MyCompiler: public Compiler { } // namespace -namespace vm { +namespace avian { +namespace codegen { Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, @@ -6991,4 +7001,5 @@ makeCompiler(System* system, Assembler* assembler, Zone* zone, return new(zone) local::MyCompiler(system, assembler, zone, client); } -} // namespace vm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler.h b/src/codegen/compiler.h index e66c69a67c..fbaad83791 100644 --- a/src/codegen/compiler.h +++ b/src/codegen/compiler.h @@ -15,7 +15,8 @@ #include "zone.h" #include "assembler.h" -namespace vm { +namespace avian { +namespace codegen { class TraceHandler { public: @@ -26,10 +27,10 @@ class Compiler { public: class Client { public: - virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0; - virtual intptr_t getThunk(BinaryOperation op, unsigned size, + virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0; + virtual intptr_t getThunk(lir::BinaryOperation op, unsigned size, unsigned resultSize) = 0; - virtual intptr_t getThunk(TernaryOperation op, unsigned size, + virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size, unsigned resultSize, bool* threadParameter) = 0; }; @@ -200,9 +201,10 @@ class Compiler { }; Compiler* -makeCompiler(System* system, Assembler* assembler, Zone* zone, +makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone, Compiler::Client* client); -} // namespace vm +} // namespace codegen +} // namespace avian #endif//COMPILER_H diff --git a/src/codegen/lir-ops.inc.cpp b/src/codegen/lir-ops.inc.cpp new file mode 100644 index 0000000000..cf038c6647 --- /dev/null +++ b/src/codegen/lir-ops.inc.cpp @@ -0,0 +1,62 @@ +LIR_OP_0(Return) +LIR_OP_0(LoadBarrier) +LIR_OP_0(StoreStoreBarrier) +LIR_OP_0(StoreLoadBarrier) +LIR_OP_0(Trap) + +LIR_OP_1(Call) +LIR_OP_1(LongCall) +LIR_OP_1(AlignedLongCall) +LIR_OP_1(AlignedCall) +LIR_OP_1(Jump) +LIR_OP_1(LongJump) +LIR_OP_1(AlignedLongJump) +LIR_OP_1(AlignedJump) + +LIR_OP_2(Move) +LIR_OP_2(MoveLow) +LIR_OP_2(MoveHigh) +LIR_OP_2(MoveZ) +LIR_OP_2(Negate) +LIR_OP_2(FloatNegate) +LIR_OP_2(Float2Float) +LIR_OP_2(Float2Int) +LIR_OP_2(Int2Float) +LIR_OP_2(FloatSquareRoot) +LIR_OP_2(FloatAbsolute) +LIR_OP_2(Absolute) + +LIR_OP_3(Add) +LIR_OP_3(Subtract) +LIR_OP_3(Multiply) +LIR_OP_3(Divide) +LIR_OP_3(Remainder) +LIR_OP_3(ShiftLeft) +LIR_OP_3(ShiftRight) +LIR_OP_3(UnsignedShiftRight) +LIR_OP_3(And) +LIR_OP_3(Or) +LIR_OP_3(Xor) +LIR_OP_3(FloatAdd) +LIR_OP_3(FloatSubtract) +LIR_OP_3(FloatMultiply) +LIR_OP_3(FloatDivide) +LIR_OP_3(FloatRemainder) +LIR_OP_3(FloatMax) +LIR_OP_3(FloatMin) +LIR_OP_3(JumpIfLess) +LIR_OP_3(JumpIfGreater) +LIR_OP_3(JumpIfLessOrEqual) +LIR_OP_3(JumpIfGreaterOrEqual) +LIR_OP_3(JumpIfEqual) +LIR_OP_3(JumpIfNotEqual) +LIR_OP_3(JumpIfFloatEqual) +LIR_OP_3(JumpIfFloatNotEqual) +LIR_OP_3(JumpIfFloatLess) +LIR_OP_3(JumpIfFloatGreater) +LIR_OP_3(JumpIfFloatLessOrEqual) +LIR_OP_3(JumpIfFloatGreaterOrEqual) +LIR_OP_3(JumpIfFloatLessOrUnordered) +LIR_OP_3(JumpIfFloatGreaterOrUnordered) +LIR_OP_3(JumpIfFloatLessOrEqualOrUnordered) +LIR_OP_3(JumpIfFloatGreaterOrEqualOrUnordered) diff --git a/src/codegen/lir.cpp b/src/codegen/lir.cpp new file mode 100644 index 0000000000..86c0839743 --- /dev/null +++ b/src/codegen/lir.cpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2012, 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 "lir.h" + +namespace { + +const char* lirOpcodeNames[] = { + #define LIR_OP_0(x) #x + #define LIR_OP_1(x) #x + #define LIR_OP_2(x) #x + #define LIR_OP_3(x) #x + #include "lir-ops.inc.cpp" + #undef LIR_OP_0 + #undef LIR_OP_1 + #undef LIR_OP_2 + #undef LIR_OP_3 +}; + +} + +namespace vm { + +const char* LirInstr::opcodeName(Opcode op) { + return lirOpcodeNames[op]; +} + +} \ No newline at end of file diff --git a/src/codegen/lir.h b/src/codegen/lir.h new file mode 100644 index 0000000000..b95e736f06 --- /dev/null +++ b/src/codegen/lir.h @@ -0,0 +1,174 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_LIR_H +#define AVIAN_CODEGEN_LIR_H + +namespace avian { +namespace codegen { +class Promise; + +namespace lir { +enum Operation { + #define LIR_OP_0(x) x, + #define LIR_OP_1(x) + #define LIR_OP_2(x) + #define LIR_OP_3(x) + #include "lir-ops.inc.cpp" + #undef LIR_OP_0 + #undef LIR_OP_1 + #undef LIR_OP_2 + #undef LIR_OP_3 +}; + +const unsigned OperationCount = Trap + 1; + +enum UnaryOperation { + #define LIR_OP_0(x) + #define LIR_OP_1(x) x, + #define LIR_OP_2(x) + #define LIR_OP_3(x) + #include "lir-ops.inc.cpp" + #undef LIR_OP_0 + #undef LIR_OP_1 + #undef LIR_OP_2 + #undef LIR_OP_3 + + NoUnaryOperation = -1 +}; + +const unsigned UnaryOperationCount = AlignedJump + 1; + +enum BinaryOperation { + #define LIR_OP_0(x) + #define LIR_OP_1(x) + #define LIR_OP_2(x) x, + #define LIR_OP_3(x) + #include "lir-ops.inc.cpp" + #undef LIR_OP_0 + #undef LIR_OP_1 + #undef LIR_OP_2 + #undef LIR_OP_3 + + NoBinaryOperation = -1 +}; + +const unsigned BinaryOperationCount = Absolute + 1; + +enum TernaryOperation { + #define LIR_OP_0(x) + #define LIR_OP_1(x) + #define LIR_OP_2(x) + #define LIR_OP_3(x) x, + #include "lir-ops.inc.cpp" + #undef LIR_OP_0 + #undef LIR_OP_1 + #undef LIR_OP_2 + #undef LIR_OP_3 + + NoTernaryOperation = -1 +}; + +const unsigned TernaryOperationCount += JumpIfFloatGreaterOrEqualOrUnordered + 1; + +const unsigned NonBranchTernaryOperationCount = FloatMin + 1; +const unsigned BranchOperationCount += JumpIfFloatGreaterOrEqualOrUnordered - FloatMin; + +enum OperandType { + ConstantOperand, + AddressOperand, + RegisterOperand, + MemoryOperand +}; + +enum ValueType { + ValueGeneral, + ValueFloat +}; + +const unsigned OperandTypeCount = MemoryOperand + 1; + +const int NoRegister = -1; + + +inline bool isBranch(lir::TernaryOperation op) { + return op > FloatMin; +} + +inline bool isFloatBranch(lir::TernaryOperation op) { + return op > JumpIfNotEqual; +} + +class Operand { }; + +class Constant: public Operand { + public: + Constant(Promise* value): value(value) { } + + Promise* value; +}; + +class Address: public Operand { + public: + Address(Promise* address): address(address) { } + + Promise* address; +}; + +class Register: public Operand { + public: + Register(int low, int high = NoRegister): low(low), high(high) { } + + int low; + int high; +}; + +class Memory: public Operand { + public: + Memory(int base, int offset, int index = NoRegister, unsigned scale = 1): + base(base), offset(offset), index(index), scale(scale) + { } + + int base; + int offset; + int index; + unsigned scale; +}; + +class Instr { +public: + + enum Opcode { + #define LIR_OP_0(x) OP_##x, + #define LIR_OP_1(x) OP_##x, + #define LIR_OP_2(x) OP_##x, + #define LIR_OP_3(x) OP_##x, + #include "lir-ops.inc.cpp" + #undef LIR_OP_0 + #undef LIR_OP_1 + #undef LIR_OP_2 + #undef LIR_OP_3 + }; + + static const char* opcodeName(Opcode op); + + static Opcode opcodeFromNullary(Operation op); + static Opcode opcodeFromUnary(UnaryOperation op); + static Opcode opcodeFromBinary(BinaryOperation op); + static Opcode opcodeFromTernary(TernaryOperation op); +}; + +} // namespace lir +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_LIR_H diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 6517e59264..ee263b25bc 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -17,6 +17,7 @@ #define CAST_BRANCH(x) reinterpret_cast(x) using namespace vm; +using namespace avian::codegen; namespace { @@ -263,33 +264,33 @@ class Task { typedef void (*OperationType)(Context*); -typedef void (*UnaryOperationType)(Context*, unsigned, Assembler::Operand*); +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); typedef void (*BinaryOperationType) -(Context*, unsigned, Assembler::Operand*, unsigned, Assembler::Operand*); +(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); typedef void (*TernaryOperationType) -(Context*, unsigned, Assembler::Operand*, Assembler::Operand*, - Assembler::Operand*); +(Context*, unsigned, lir::Operand*, lir::Operand*, + lir::Operand*); typedef void (*BranchOperationType) -(Context*, TernaryOperation, unsigned, Assembler::Operand*, - Assembler::Operand*, Assembler::Operand*); +(Context*, lir::TernaryOperation, unsigned, lir::Operand*, + lir::Operand*, lir::Operand*); class ArchitectureContext { public: ArchitectureContext(System* s): s(s) { } System* s; - OperationType operations[OperationCount]; - UnaryOperationType unaryOperations[UnaryOperationCount - * OperandTypeCount]; + OperationType operations[lir::OperationCount]; + UnaryOperationType unaryOperations[lir::UnaryOperationCount + * lir::OperandTypeCount]; BinaryOperationType binaryOperations - [BinaryOperationCount * OperandTypeCount * OperandTypeCount]; + [lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; TernaryOperationType ternaryOperations - [NonBranchTernaryOperationCount * OperandTypeCount]; + [lir::NonBranchTernaryOperationCount * lir::OperandTypeCount]; BranchOperationType branchOperations - [BranchOperationCount * OperandTypeCount * OperandTypeCount]; + [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; }; inline void NO_RETURN @@ -612,43 +613,37 @@ resolve(MyBlock* b) } inline unsigned -index(ArchitectureContext*, UnaryOperation operation, OperandType operand) +index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) { - return operation + (UnaryOperationCount * operand); + return operation + (lir::UnaryOperationCount * operand); } inline unsigned index(ArchitectureContext*, - BinaryOperation operation, - OperandType operand1, - OperandType operand2) + lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2) { return operation - + (BinaryOperationCount * operand1) - + (BinaryOperationCount * OperandTypeCount * operand2); -} - -bool -isBranch(TernaryOperation op) -{ - return op > FloatMin; + + (lir::BinaryOperationCount * operand1) + + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); } inline unsigned index(ArchitectureContext* c UNUSED, - TernaryOperation operation, - OperandType operand1) + lir::TernaryOperation operation, + lir::OperandType operand1) { assert(c, not isBranch(operation)); - return operation + (NonBranchTernaryOperationCount * operand1); + return operation + (lir::NonBranchTernaryOperationCount * operand1); } unsigned -branchIndex(ArchitectureContext* c UNUSED, OperandType operand1, - OperandType operand2) +branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, + lir::OperandType operand2) { - return operand1 + (OperandTypeCount * operand2); + return operand1 + (lir::OperandTypeCount * operand2); } // BEGIN OPERATION COMPILERS @@ -658,7 +653,7 @@ using namespace isa; inline void emit(Context* con, int code) { con->code.append4(targetV4(code)); } inline int newTemp(Context* con) { return con->client->acquireTemporary(); } inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } -inline int64_t getValue(Assembler::Constant* c) { return c->value->value(); } +inline int64_t getValue(lir::Constant* c) { return c->value->value(); } inline void write4(uint8_t* dst, uint32_t v) @@ -667,13 +662,13 @@ write4(uint8_t* dst, uint32_t v) } void -andC(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst); +andC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); -void shiftLeftR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) +void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if(size == 8) { - Assembler::Register Tmp(newTemp(con), newTemp(con)); Assembler::Register* tmp = &Tmp; + lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; emit(con, subfic(tmp->high, a->low, 32)); emit(con, slw(t->high, b->high, a->low)); emit(con, srw(tmp->low, b->low, tmp->high)); @@ -689,10 +684,10 @@ void shiftLeftR(Context* con, unsigned size, Assembler::Register* a, Assembler:: } void -moveRR(Context* c, unsigned srcSize, Assembler::Register* src, - unsigned dstSize, Assembler::Register* dst); +moveRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); -void shiftLeftC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) +void shiftLeftC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { int sh = getValue(a); if (size == 8) { @@ -714,10 +709,10 @@ void shiftLeftC(Context* con, unsigned size, Assembler::Constant* a, Assembler:: } } -void shiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) +void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if(size == 8) { - Assembler::Register Tmp(newTemp(con), newTemp(con)); Assembler::Register* tmp = &Tmp; + lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; emit(con, subfic(tmp->high, a->low, 32)); emit(con, srw(t->low, b->low, a->low)); emit(con, slw(tmp->low, b->high, tmp->high)); @@ -733,7 +728,7 @@ void shiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler: } } -void shiftRightC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) +void shiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { int sh = getValue(a); if(size == 8) { @@ -755,11 +750,11 @@ void shiftRightC(Context* con, unsigned size, Assembler::Constant* a, Assembler: } } -void unsignedShiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) +void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { emit(con, srw(t->low, b->low, a->low)); if(size == 8) { - Assembler::Register Tmp(newTemp(con), newTemp(con)); Assembler::Register* tmp = &Tmp; + lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; emit(con, subfic(tmp->high, a->low, 32)); emit(con, slw(tmp->low, b->high, tmp->high)); emit(con, or_(t->low, t->low, tmp->low)); @@ -771,13 +766,13 @@ void unsignedShiftRightR(Context* con, unsigned size, Assembler::Register* a, As } } -void unsignedShiftRightC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) +void unsignedShiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { int sh = getValue(a); if (size == 8) { if (sh & 0x3F) { if (sh == 32) { - Assembler::Register high(b->high); + lir::Register high(b->high); moveRR(con, 4, &high, 4, t); emit(con, li(t->high,0)); } else if (sh < 32) { @@ -909,7 +904,7 @@ appendConstantPoolEntry(Context* c, Promise* constant) } void -jumpR(Context* c, unsigned size UNUSED, Assembler::Register* target) +jumpR(Context* c, unsigned size UNUSED, lir::Register* target) { assert(c, size == TargetBytesPerWord); @@ -918,13 +913,13 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* target) } void -swapRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b) +swapRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == TargetBytesPerWord); assert(c, bSize == TargetBytesPerWord); - Assembler::Register tmp(c->client->acquireTemporary()); + lir::Register tmp(c->client->acquireTemporary()); moveRR(c, aSize, a, bSize, &tmp); moveRR(c, bSize, b, aSize, a); moveRR(c, bSize, &tmp, bSize, b); @@ -932,8 +927,8 @@ swapRR(Context* c, unsigned aSize, Assembler::Register* a, } void -moveRR(Context* c, unsigned srcSize, Assembler::Register* src, - unsigned dstSize, Assembler::Register* dst) +moveRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst) { switch (srcSize) { case 1: @@ -950,8 +945,8 @@ moveRR(Context* c, unsigned srcSize, Assembler::Register* src, moveRR(c, 4, src, 4, dst); emit(c, srawi(dst->high, src->low, 31)); } else if (srcSize == 8 and dstSize == 8) { - Assembler::Register srcHigh(src->high); - Assembler::Register dstHigh(dst->high); + lir::Register srcHigh(src->high); + lir::Register dstHigh(dst->high); if (src->high == dst->low) { if (src->low == dst->high) { @@ -974,8 +969,8 @@ moveRR(Context* c, unsigned srcSize, Assembler::Register* src, } void -moveZRR(Context* c, unsigned srcSize, Assembler::Register* src, - unsigned, Assembler::Register* dst) +moveZRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned, lir::Register* dst) { switch (srcSize) { case 2: @@ -987,8 +982,8 @@ moveZRR(Context* c, unsigned srcSize, Assembler::Register* src, } void -moveCR2(Context* c, unsigned, Assembler::Constant* src, - unsigned dstSize, Assembler::Register* dst, unsigned promiseOffset) +moveCR2(Context* c, unsigned, lir::Constant* src, + unsigned dstSize, lir::Register* dst, unsigned promiseOffset) { if (dstSize <= 4) { if (src->value->resolved()) { @@ -1011,13 +1006,13 @@ moveCR2(Context* c, unsigned, Assembler::Constant* src, } void -moveCR(Context* c, unsigned srcSize, Assembler::Constant* src, - unsigned dstSize, Assembler::Register* dst) +moveCR(Context* c, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Register* dst) { moveCR2(c, srcSize, src, dstSize, dst, 0); } -void addR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if(size == 8) { emit(con, addc(t->low, a->low, b->low)); emit(con, adde(t->high, a->high, b->high)); @@ -1026,7 +1021,7 @@ void addR(Context* con, unsigned size, Assembler::Register* a, Assembler::Regist } } -void addC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) { +void addC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { assert(con, size == TargetBytesPerWord); int32_t i = getValue(a); @@ -1039,7 +1034,7 @@ void addC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Regist } } -void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if(size == 8) { emit(con, subfc(t->low, a->low, b->low)); emit(con, subfe(t->high, a->high, b->high)); @@ -1048,15 +1043,15 @@ void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Regist } } -void subC(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) { +void subC(Context* c, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { assert(c, size == TargetBytesPerWord); ResolvedPromise promise(- a->value->value()); - Assembler::Constant constant(&promise); + lir::Constant constant(&promise); addC(c, size, &constant, b, t); } -void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { if(size == 8) { bool useTemporaries = b->low == t->low; int tmpLow; @@ -1085,14 +1080,14 @@ void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::R } } -void divideR(Context* con, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void divideR(Context* con, unsigned size UNUSED, lir::Register* a, lir::Register* b, lir::Register* t) { assert(con, size == 4); emit(con, divw(t->low, b->low, a->low)); } -void remainderR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { +void remainderR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { bool useTemporary = b->low == t->low; - Assembler::Register tmp(t->low); + lir::Register tmp(t->low); if (useTemporary) { tmp.low = con->client->acquireTemporary(); } @@ -1111,7 +1106,7 @@ normalize(Context* c, int offset, int index, unsigned scale, bool* preserveIndex, bool* release) { if (offset != 0 or scale != 1) { - Assembler::Register normalizedIndex + lir::Register normalizedIndex (*preserveIndex ? c->client->acquireTemporary() : index); if (*preserveIndex) { @@ -1124,10 +1119,10 @@ normalize(Context* c, int offset, int index, unsigned scale, int scaled; if (scale != 1) { - Assembler::Register unscaledIndex(index); + lir::Register unscaledIndex(index); ResolvedPromise scalePromise(log(scale)); - Assembler::Constant scaleConstant(&scalePromise); + lir::Constant scaleConstant(&scalePromise); shiftLeftC(c, TargetBytesPerWord, &scaleConstant, &unscaledIndex, &normalizedIndex); @@ -1138,10 +1133,10 @@ normalize(Context* c, int offset, int index, unsigned scale, } if (offset != 0) { - Assembler::Register untranslatedIndex(scaled); + lir::Register untranslatedIndex(scaled); ResolvedPromise offsetPromise(offset); - Assembler::Constant offsetConstant(&offsetPromise); + lir::Constant offsetConstant(&offsetPromise); addC(c, TargetBytesPerWord, &offsetConstant, &untranslatedIndex, &normalizedIndex); @@ -1155,10 +1150,10 @@ normalize(Context* c, int offset, int index, unsigned scale, } void -store(Context* c, unsigned size, Assembler::Register* src, +store(Context* c, unsigned size, lir::Register* src, int base, int offset, int index, unsigned scale, bool preserveIndex) { - if (index != NoRegister) { + if (index != lir::NoRegister) { bool release; int normalized = normalize (c, offset, index, scale, &preserveIndex, &release); @@ -1177,7 +1172,7 @@ store(Context* c, unsigned size, Assembler::Register* src, break; case 8: { - Assembler::Register srcHigh(src->high); + lir::Register srcHigh(src->high); store(c, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); store(c, 4, src, base, 4, normalized, 1, preserveIndex); } break; @@ -1201,9 +1196,9 @@ store(Context* c, unsigned size, Assembler::Register* src, break; case 8: { - Assembler::Register srcHigh(src->high); - store(c, 4, &srcHigh, base, offset, NoRegister, 1, false); - store(c, 4, src, base, offset + 4, NoRegister, 1, false); + lir::Register srcHigh(src->high); + store(c, 4, &srcHigh, base, offset, lir::NoRegister, 1, false); + store(c, 4, src, base, offset + 4, lir::NoRegister, 1, false); } break; default: abort(c); @@ -1212,8 +1207,8 @@ store(Context* c, unsigned size, Assembler::Register* src, } void -moveRM(Context* c, unsigned srcSize, Assembler::Register* src, - unsigned dstSize UNUSED, Assembler::Memory* dst) +moveRM(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst) { assert(c, srcSize == dstSize); @@ -1221,13 +1216,13 @@ moveRM(Context* c, unsigned srcSize, Assembler::Register* src, } void -moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src, - unsigned dstSize UNUSED, Assembler::Memory* dst) +moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst) { assert(c, srcSize == TargetBytesPerWord); assert(c, dstSize == TargetBytesPerWord); - if (dst->index == NoRegister) { + if (dst->index == lir::NoRegister) { emit(c, stwu(src->low, dst->base, dst->offset)); } else { assert(c, dst->offset == 0); @@ -1239,10 +1234,10 @@ moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src, void load(Context* c, unsigned srcSize, int base, int offset, int index, - unsigned scale, unsigned dstSize, Assembler::Register* dst, + unsigned scale, unsigned dstSize, lir::Register* dst, bool preserveIndex, bool signExtend) { - if (index != NoRegister) { + if (index != lir::NoRegister) { bool release; int normalized = normalize (c, offset, index, scale, &preserveIndex, &release); @@ -1269,7 +1264,7 @@ load(Context* c, unsigned srcSize, int base, int offset, int index, load(c, 4, base, 0, normalized, 1, 4, dst, preserveIndex, false); moveRR(c, 4, dst, 8, dst); } else if (srcSize == 8 and dstSize == 8) { - Assembler::Register dstHigh(dst->high); + lir::Register dstHigh(dst->high); load(c, 4, base, 0, normalized, 1, 4, &dstHigh, preserveIndex, false); load(c, 4, base, 4, normalized, 1, 4, dst, preserveIndex, false); } else { @@ -1304,9 +1299,9 @@ load(Context* c, unsigned srcSize, int base, int offset, int index, case 8: { if (dstSize == 8) { - Assembler::Register dstHigh(dst->high); - load(c, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, false); - load(c, 4, base, offset + 4, NoRegister, 1, 4, dst, false, false); + lir::Register dstHigh(dst->high); + load(c, 4, base, offset, lir::NoRegister, 1, 4, &dstHigh, false, false); + load(c, 4, base, offset + 4, lir::NoRegister, 1, 4, dst, false, false); } else { emit(c, lwzx(dst->low, base, offset)); } @@ -1318,29 +1313,29 @@ load(Context* c, unsigned srcSize, int base, int offset, int index, } void -moveMR(Context* c, unsigned srcSize, Assembler::Memory* src, - unsigned dstSize, Assembler::Register* dst) +moveMR(Context* c, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) { load(c, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, true); } void -moveZMR(Context* c, unsigned srcSize, Assembler::Memory* src, - unsigned dstSize, Assembler::Register* dst) +moveZMR(Context* c, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) { load(c, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, false); } void -andR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b, Assembler::Register* dst) +andR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { if (size == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); - Assembler::Register dh(dst->high); + lir::Register ah(a->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); andR(c, 4, a, b, dst); andR(c, 4, &ah, &bh, &dh); @@ -1350,20 +1345,20 @@ andR(Context* c, unsigned size, Assembler::Register* a, } void -andC(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst) +andC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { int64_t v = a->value->value(); if (size == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); - Assembler::Register dh(dst->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); andC(c, 4, &al, b, dst); andC(c, 4, &ah, &bh, &dh); @@ -1403,7 +1398,7 @@ andC(Context* c, unsigned size, Assembler::Constant* a, emit(c, andis(dst->low, b->low, v32 >> 16)); } else { bool useTemporary = b->low == dst->low; - Assembler::Register tmp(dst->low); + lir::Register tmp(dst->low); if (useTemporary) { tmp.low = c->client->acquireTemporary(); } @@ -1434,13 +1429,13 @@ andC(Context* c, unsigned size, Assembler::Constant* a, } void -orR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b, Assembler::Register* dst) +orR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { if (size == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); - Assembler::Register dh(dst->high); + lir::Register ah(a->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); orR(c, 4, a, b, dst); orR(c, 4, &ah, &bh, &dh); @@ -1450,20 +1445,20 @@ orR(Context* c, unsigned size, Assembler::Register* a, } void -orC(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst) +orC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { int64_t v = a->value->value(); if (size == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); - Assembler::Register dh(dst->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); orC(c, 4, &al, b, dst); orC(c, 4, &ah, &bh, &dh); @@ -1476,13 +1471,13 @@ orC(Context* c, unsigned size, Assembler::Constant* a, } void -xorR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b, Assembler::Register* dst) +xorR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { if (size == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); - Assembler::Register dh(dst->high); + lir::Register ah(a->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); xorR(c, 4, a, b, dst); xorR(c, 4, &ah, &bh, &dh); @@ -1492,20 +1487,20 @@ xorR(Context* c, unsigned size, Assembler::Register* a, } void -xorC(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b, Assembler::Register* dst) +xorC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { uint64_t v = a->value->value(); if (size == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); - Assembler::Register dh(dst->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); xorC(c, 4, &al, b, dst); xorC(c, 4, &ah, &bh, &dh); @@ -1520,12 +1515,12 @@ xorC(Context* c, unsigned size, Assembler::Constant* a, } void -moveAR2(Context* c, unsigned srcSize UNUSED, Assembler::Address* src, - unsigned dstSize, Assembler::Register* dst, unsigned promiseOffset) +moveAR2(Context* c, unsigned srcSize UNUSED, lir::Address* src, + unsigned dstSize, lir::Register* dst, unsigned promiseOffset) { assert(c, srcSize == 4 and dstSize == 4); - Assembler::Memory memory(dst->low, 0, -1, 0); + lir::Memory memory(dst->low, 0, -1, 0); appendImmediateTask (c, src->address, offset(c), TargetBytesPerWord, promiseOffset, true); @@ -1535,15 +1530,15 @@ moveAR2(Context* c, unsigned srcSize UNUSED, Assembler::Address* src, } void -moveAR(Context* c, unsigned srcSize, Assembler::Address* src, - unsigned dstSize, Assembler::Register* dst) +moveAR(Context* c, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst) { moveAR2(c, srcSize, src, dstSize, dst, 0); } void -compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +compareRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == 4 and bSize == 4); @@ -1551,15 +1546,15 @@ compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, } void -compareCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +compareCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == 4 and bSize == 4); if (a->value->resolved() and isInt16(a->value->value())) { emit(c, cmpwi(b->low, a->value->value())); } else { - Assembler::Register tmp(c->client->acquireTemporary()); + lir::Register tmp(c->client->acquireTemporary()); moveCR(c, aSize, a, bSize, &tmp); compareRR(c, bSize, &tmp, bSize, b); c->client->releaseTemporary(tmp.low); @@ -1567,32 +1562,32 @@ compareCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -compareCM(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Memory* b) +compareCM(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b) { assert(c, aSize == 4 and bSize == 4); - Assembler::Register tmp(c->client->acquireTemporary()); + lir::Register tmp(c->client->acquireTemporary()); moveMR(c, bSize, b, bSize, &tmp); compareCR(c, aSize, a, bSize, &tmp); c->client->releaseTemporary(tmp.low); } void -compareRM(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Memory* b) +compareRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Memory* b) { assert(c, aSize == 4 and bSize == 4); - Assembler::Register tmp(c->client->acquireTemporary()); + lir::Register tmp(c->client->acquireTemporary()); moveMR(c, bSize, b, bSize, &tmp); compareRR(c, aSize, a, bSize, &tmp); c->client->releaseTemporary(tmp.low); } void -compareUnsignedRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +compareUnsignedRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == 4 and bSize == 4); @@ -1600,15 +1595,15 @@ compareUnsignedRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, } void -compareUnsignedCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +compareUnsignedCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == 4 and bSize == 4); if (a->value->resolved() and (a->value->value() >> 16) == 0) { emit(c, cmplwi(b->low, a->value->value())); } else { - Assembler::Register tmp(c->client->acquireTemporary()); + lir::Register tmp(c->client->acquireTemporary()); moveCR(c, aSize, a, bSize, &tmp); compareUnsignedRR(c, bSize, &tmp, bSize, b); c->client->releaseTemporary(tmp.low); @@ -1616,25 +1611,25 @@ compareUnsignedCR(Context* c, unsigned aSize, Assembler::Constant* a, } int32_t -branch(Context* c, TernaryOperation op) +branch(Context* c, lir::TernaryOperation op) { switch (op) { - case JumpIfEqual: + case lir::JumpIfEqual: return beq(0); - case JumpIfNotEqual: + case lir::JumpIfNotEqual: return bne(0); - case JumpIfLess: + case lir::JumpIfLess: return blt(0); - case JumpIfGreater: + case lir::JumpIfGreater: return bgt(0); - case JumpIfLessOrEqual: + case lir::JumpIfLessOrEqual: return ble(0); - case JumpIfGreaterOrEqual: + case lir::JumpIfGreaterOrEqual: return bge(0); default: @@ -1643,22 +1638,22 @@ branch(Context* c, TernaryOperation op) } void -conditional(Context* c, int32_t branch, Assembler::Constant* target) +conditional(Context* c, int32_t branch, lir::Constant* target) { appendOffsetTask(c, target->value, offset(c), true); emit(c, branch); } void -branch(Context* c, TernaryOperation op, Assembler::Constant* target) +branch(Context* c, lir::TernaryOperation op, lir::Constant* target) { conditional(c, branch(c, op), target); } void -branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, - Assembler::Operand* ah, Assembler::Operand* bl, - Assembler::Operand* bh, Assembler::Constant* target, +branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, BinaryOperationType compareSigned, BinaryOperationType compareUnsigned) { @@ -1667,7 +1662,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, unsigned next = 0; switch (op) { - case JumpIfEqual: + case lir::JumpIfEqual: next = c->code.length(); emit(c, bne(0)); @@ -1675,14 +1670,14 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, beq(0), target); break; - case JumpIfNotEqual: + case lir::JumpIfNotEqual: conditional(c, bne(0), target); compareSigned(c, 4, al, 4, bl); conditional(c, bne(0), target); break; - case JumpIfLess: + case lir::JumpIfLess: conditional(c, blt(0), target); next = c->code.length(); @@ -1692,7 +1687,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, blt(0), target); break; - case JumpIfGreater: + case lir::JumpIfGreater: conditional(c, bgt(0), target); next = c->code.length(); @@ -1702,7 +1697,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, bgt(0), target); break; - case JumpIfLessOrEqual: + case lir::JumpIfLessOrEqual: conditional(c, blt(0), target); next = c->code.length(); @@ -1712,7 +1707,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, ble(0), target); break; - case JumpIfGreaterOrEqual: + case lir::JumpIfGreaterOrEqual: conditional(c, bgt(0), target); next = c->code.length(); @@ -1734,13 +1729,13 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, } void -branchRR(Context* c, TernaryOperation op, unsigned size, - Assembler::Register* a, Assembler::Register* b, - Assembler::Constant* target) +branchRR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target) { if (size > TargetBytesPerWord) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR), CAST2(compareUnsignedRR)); @@ -1751,20 +1746,20 @@ branchRR(Context* c, TernaryOperation op, unsigned size, } void -branchCR(Context* c, TernaryOperation op, unsigned size, - Assembler::Constant* a, Assembler::Register* b, - Assembler::Constant* target) +branchCR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target) { if (size > TargetBytesPerWord) { int64_t v = a->value->value(); ResolvedPromise low(v & ~static_cast(0)); - Assembler::Constant al(&low); + lir::Constant al(&low); ResolvedPromise high((v >> 32) & ~static_cast(0)); - Assembler::Constant ah(&high); + lir::Constant ah(&high); - Assembler::Register bh(b->high); + lir::Register bh(b->high); branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR), CAST2(compareUnsignedCR)); @@ -1775,9 +1770,9 @@ branchCR(Context* c, TernaryOperation op, unsigned size, } void -branchRM(Context* c, TernaryOperation op, unsigned size, - Assembler::Register* a, Assembler::Memory* b, - Assembler::Constant* target) +branchRM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target) { assert(c, size <= TargetBytesPerWord); @@ -1786,9 +1781,9 @@ branchRM(Context* c, TernaryOperation op, unsigned size, } void -branchCM(Context* c, TernaryOperation op, unsigned size, - Assembler::Constant* a, Assembler::Memory* b, - Assembler::Constant* target) +branchCM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target) { assert(c, size <= TargetBytesPerWord); @@ -1803,17 +1798,17 @@ shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) } void -moveCM(Context* c, unsigned srcSize, Assembler::Constant* src, - unsigned dstSize, Assembler::Memory* dst) +moveCM(Context* c, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Memory* dst) { switch (dstSize) { case 8: { - Assembler::Constant srcHigh + lir::Constant srcHigh (shiftMaskPromise(c, src->value, 32, 0xFFFFFFFF)); - Assembler::Constant srcLow + lir::Constant srcLow (shiftMaskPromise(c, src->value, 0, 0xFFFFFFFF)); - Assembler::Memory dstLow + lir::Memory dstLow (dst->base, dst->offset + 4, dst->index, dst->scale); moveCM(c, 4, &srcLow, 4, &dstLow); @@ -1821,7 +1816,7 @@ moveCM(Context* c, unsigned srcSize, Assembler::Constant* src, } break; default: - Assembler::Register tmp(c->client->acquireTemporary()); + lir::Register tmp(c->client->acquireTemporary()); moveCR(c, srcSize, src, dstSize, &tmp); moveRM(c, dstSize, &tmp, dstSize, dst); c->client->releaseTemporary(tmp.low); @@ -1829,13 +1824,13 @@ moveCM(Context* c, unsigned srcSize, Assembler::Constant* src, } void -negateRR(Context* c, unsigned srcSize, Assembler::Register* src, - unsigned dstSize UNUSED, Assembler::Register* dst) +negateRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Register* dst) { assert(c, srcSize == dstSize); if (srcSize == 8) { - Assembler::Register dstHigh(dst->high); + lir::Register dstHigh(dst->high); emit(c, subfic(dst->low, src->low, 0)); emit(c, subfze(dst->high, src->high)); @@ -1845,7 +1840,7 @@ negateRR(Context* c, unsigned srcSize, Assembler::Register* src, } void -callR(Context* c, unsigned size UNUSED, Assembler::Register* target) +callR(Context* c, unsigned size UNUSED, lir::Register* target) { assert(c, size == TargetBytesPerWord); @@ -1854,7 +1849,7 @@ callR(Context* c, unsigned size UNUSED, Assembler::Register* target) } void -callC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +callC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); @@ -1863,51 +1858,51 @@ callC(Context* c, unsigned size UNUSED, Assembler::Constant* target) } void -longCallC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +longCallC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); - Assembler::Register tmp(0); + lir::Register tmp(0); moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, 12); callR(c, TargetBytesPerWord, &tmp); } void -alignedLongCallC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +alignedLongCallC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); - Assembler::Register tmp(c->client->acquireTemporary()); - Assembler::Address address(appendConstantPoolEntry(c, target->value)); + lir::Register tmp(c->client->acquireTemporary()); + lir::Address address(appendConstantPoolEntry(c, target->value)); moveAR2(c, TargetBytesPerWord, &address, TargetBytesPerWord, &tmp, 12); callR(c, TargetBytesPerWord, &tmp); c->client->releaseTemporary(tmp.low); } void -longJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +longJumpC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); - Assembler::Register tmp(0); + lir::Register tmp(0); moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, 12); jumpR(c, TargetBytesPerWord, &tmp); } void -alignedLongJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +alignedLongJumpC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); - Assembler::Register tmp(c->client->acquireTemporary()); - Assembler::Address address(appendConstantPoolEntry(c, target->value)); + lir::Register tmp(c->client->acquireTemporary()); + lir::Address address(appendConstantPoolEntry(c, target->value)); moveAR2(c, TargetBytesPerWord, &address, TargetBytesPerWord, &tmp, 12); jumpR(c, TargetBytesPerWord, &tmp); c->client->releaseTemporary(tmp.low); } void -jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +jumpC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); @@ -1993,10 +1988,10 @@ nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size, void populateTables(ArchitectureContext* c) { - const OperandType C = ConstantOperand; - const OperandType A = AddressOperand; - const OperandType R = RegisterOperand; - const OperandType M = MemoryOperand; + const lir::OperandType C = lir::ConstantOperand; + const lir::OperandType A = lir::AddressOperand; + const lir::OperandType R = lir::RegisterOperand; + const lir::OperandType M = lir::MemoryOperand; OperationType* zo = c->operations; UnaryOperationType* uo = c->unaryOperations; @@ -2004,74 +1999,74 @@ populateTables(ArchitectureContext* c) TernaryOperationType* to = c->ternaryOperations; BranchOperationType* bro = c->branchOperations; - zo[Return] = return_; - zo[LoadBarrier] = memoryBarrier; - zo[StoreStoreBarrier] = memoryBarrier; - zo[StoreLoadBarrier] = memoryBarrier; - zo[Trap] = trap; + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = memoryBarrier; + zo[lir::StoreStoreBarrier] = memoryBarrier; + zo[lir::StoreLoadBarrier] = memoryBarrier; + zo[lir::Trap] = trap; - uo[index(c, LongCall, C)] = CAST1(longCallC); + uo[index(c, lir::LongCall, C)] = CAST1(longCallC); - uo[index(c, AlignedLongCall, C)] = CAST1(alignedLongCallC); + uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); - uo[index(c, LongJump, C)] = CAST1(longJumpC); + uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); - uo[index(c, AlignedLongJump, C)] = CAST1(alignedLongJumpC); + uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); - uo[index(c, Jump, R)] = CAST1(jumpR); - uo[index(c, Jump, C)] = CAST1(jumpC); + uo[index(c, lir::Jump, R)] = CAST1(jumpR); + uo[index(c, lir::Jump, C)] = CAST1(jumpC); - uo[index(c, AlignedJump, R)] = CAST1(jumpR); - uo[index(c, AlignedJump, C)] = CAST1(jumpC); + uo[index(c, lir::AlignedJump, R)] = CAST1(jumpR); + uo[index(c, lir::AlignedJump, C)] = CAST1(jumpC); - uo[index(c, Call, C)] = CAST1(callC); - uo[index(c, Call, R)] = CAST1(callR); + uo[index(c, lir::Call, C)] = CAST1(callC); + uo[index(c, lir::Call, R)] = CAST1(callR); - uo[index(c, AlignedCall, C)] = CAST1(callC); - uo[index(c, AlignedCall, R)] = CAST1(callR); + uo[index(c, lir::AlignedCall, C)] = CAST1(callC); + uo[index(c, lir::AlignedCall, R)] = CAST1(callR); - bo[index(c, Move, R, R)] = CAST2(moveRR); - bo[index(c, Move, C, R)] = CAST2(moveCR); - bo[index(c, Move, C, M)] = CAST2(moveCM); - bo[index(c, Move, M, R)] = CAST2(moveMR); - bo[index(c, Move, R, M)] = CAST2(moveRM); - bo[index(c, Move, A, R)] = CAST2(moveAR); + bo[index(c, lir::Move, R, R)] = CAST2(moveRR); + bo[index(c, lir::Move, C, R)] = CAST2(moveCR); + bo[index(c, lir::Move, C, M)] = CAST2(moveCM); + bo[index(c, lir::Move, M, R)] = CAST2(moveMR); + bo[index(c, lir::Move, R, M)] = CAST2(moveRM); + bo[index(c, lir::Move, A, R)] = CAST2(moveAR); - bo[index(c, MoveZ, R, R)] = CAST2(moveZRR); - bo[index(c, MoveZ, M, R)] = CAST2(moveZMR); - bo[index(c, MoveZ, C, R)] = CAST2(moveCR); + bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR); - bo[index(c, Negate, R, R)] = CAST2(negateRR); + bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); - to[index(c, Add, R)] = CAST3(addR); - to[index(c, Add, C)] = CAST3(addC); + to[index(c, lir::Add, R)] = CAST3(addR); + to[index(c, lir::Add, C)] = CAST3(addC); - to[index(c, Subtract, R)] = CAST3(subR); - to[index(c, Subtract, C)] = CAST3(subC); + to[index(c, lir::Subtract, R)] = CAST3(subR); + to[index(c, lir::Subtract, C)] = CAST3(subC); - to[index(c, Multiply, R)] = CAST3(multiplyR); + to[index(c, lir::Multiply, R)] = CAST3(multiplyR); - to[index(c, Divide, R)] = CAST3(divideR); + to[index(c, lir::Divide, R)] = CAST3(divideR); - to[index(c, Remainder, R)] = CAST3(remainderR); + to[index(c, lir::Remainder, R)] = CAST3(remainderR); - to[index(c, ShiftLeft, R)] = CAST3(shiftLeftR); - to[index(c, ShiftLeft, C)] = CAST3(shiftLeftC); + to[index(c, lir::ShiftLeft, R)] = CAST3(shiftLeftR); + to[index(c, lir::ShiftLeft, C)] = CAST3(shiftLeftC); - to[index(c, ShiftRight, R)] = CAST3(shiftRightR); - to[index(c, ShiftRight, C)] = CAST3(shiftRightC); + to[index(c, lir::ShiftRight, R)] = CAST3(shiftRightR); + to[index(c, lir::ShiftRight, C)] = CAST3(shiftRightC); - to[index(c, UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); - to[index(c, UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); + to[index(c, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); + to[index(c, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); - to[index(c, And, C)] = CAST3(andC); - to[index(c, And, R)] = CAST3(andR); + to[index(c, lir::And, C)] = CAST3(andC); + to[index(c, lir::And, R)] = CAST3(andR); - to[index(c, Or, C)] = CAST3(orC); - to[index(c, Or, R)] = CAST3(orR); + to[index(c, lir::Or, C)] = CAST3(orC); + to[index(c, lir::Or, R)] = CAST3(orR); - to[index(c, Xor, C)] = CAST3(xorC); - to[index(c, Xor, R)] = CAST3(xorR); + to[index(c, lir::Xor, C)] = CAST3(xorC); + to[index(c, lir::Xor, R)] = CAST3(xorR); bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); @@ -2114,7 +2109,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual int returnHigh() { - return (TargetBytesPerWord == 4 ? 3 : NoRegister); + return (TargetBytesPerWord == 4 ? 3 : lir::NoRegister); } virtual int virtualCallTarget() { @@ -2191,28 +2186,28 @@ class MyArchitecture: public Assembler::Architecture { - reinterpret_cast(instruction))); } - virtual void updateCall(UnaryOperation op UNUSED, + virtual void updateCall(lir::UnaryOperation op UNUSED, void* returnAddress, void* newTarget) { switch (op) { - case Call: - case Jump: - case AlignedCall: - case AlignedJump: { + case lir::Call: + case lir::Jump: + case lir::AlignedCall: + case lir::AlignedJump: { updateOffset(c.s, static_cast(returnAddress) - 4, false, reinterpret_cast(newTarget), 0); } break; - case LongCall: - case LongJump: { + case lir::LongCall: + case lir::LongJump: { updateImmediate (c.s, static_cast(returnAddress) - 12, reinterpret_cast(newTarget), TargetBytesPerWord, false); } break; - case AlignedLongCall: - case AlignedLongJump: { + case lir::AlignedLongCall: + case lir::AlignedLongJump: { uint32_t* p = static_cast(returnAddress) - 4; *reinterpret_cast(unha16(p[0] & 0xFFFF, p[1] & 0xFFFF)) = newTarget; @@ -2268,34 +2263,34 @@ class MyArchitecture: public Assembler::Architecture { return 0; } - virtual BinaryOperation hasBinaryIntrinsic(Thread*, object) { - return NoBinaryOperation; + virtual lir::BinaryOperation hasBinaryIntrinsic(Thread*, object) { + return lir::NoBinaryOperation; } - virtual TernaryOperation hasTernaryIntrinsic(Thread*, object) { - return NoTernaryOperation; + virtual lir::TernaryOperation hasTernaryIntrinsic(Thread*, object) { + return lir::NoTernaryOperation; } - virtual bool alwaysCondensed(BinaryOperation) { + virtual bool alwaysCondensed(lir::BinaryOperation) { return false; } - virtual bool alwaysCondensed(TernaryOperation) { + virtual bool alwaysCondensed(lir::TernaryOperation) { return false; } virtual void plan - (UnaryOperation, + (lir::UnaryOperation, unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, bool* thunk) { - *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); *aRegisterMask = ~static_cast(0); *thunk = false; } virtual void planSource - (BinaryOperation op, + (lir::BinaryOperation op, unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned, bool* thunk) { @@ -2305,17 +2300,17 @@ class MyArchitecture: public Assembler::Architecture { *thunk = false; switch (op) { - case Negate: - *aTypeMask = (1 << RegisterOperand); + case lir::Negate: + *aTypeMask = (1 << lir::RegisterOperand); break; - case Absolute: - case FloatAbsolute: - case FloatSquareRoot: - case FloatNegate: - case Float2Float: - case Float2Int: - case Int2Float: + case lir::Absolute: + case lir::FloatAbsolute: + case lir::FloatSquareRoot: + case lir::FloatNegate: + case lir::Float2Float: + case lir::Float2Int: + case lir::Int2Float: *thunk = true; break; @@ -2325,16 +2320,16 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (BinaryOperation op, + (lir::BinaryOperation op, unsigned, uint8_t, uint64_t, unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask) { - *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); *bRegisterMask = ~static_cast(0); switch (op) { - case Negate: - *bTypeMask = (1 << RegisterOperand); + case lir::Negate: + *bTypeMask = (1 << lir::RegisterOperand); break; default: @@ -2353,42 +2348,42 @@ class MyArchitecture: public Assembler::Architecture { *tmpTypeMask = 0; *tmpRegisterMask = 0; - if (dstTypeMask & (1 << MemoryOperand)) { + if (dstTypeMask & (1 << lir::MemoryOperand)) { // can't move directly from memory or constant to memory - *srcTypeMask = 1 << RegisterOperand; - *tmpTypeMask = 1 << RegisterOperand; + *srcTypeMask = 1 << lir::RegisterOperand; + *tmpTypeMask = 1 << lir::RegisterOperand; *tmpRegisterMask = ~static_cast(0); } } virtual void planSource - (TernaryOperation op, + (lir::TernaryOperation op, unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask, unsigned, bool* thunk) { - *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); *aRegisterMask = ~static_cast(0); - *bTypeMask = (1 << RegisterOperand); + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = ~static_cast(0); *thunk = false; switch (op) { - case Add: - case Subtract: + case lir::Add: + case lir::Subtract: if (aSize == 8) { - *aTypeMask = *bTypeMask = (1 << RegisterOperand); + *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); } break; - case Multiply: - *aTypeMask = *bTypeMask = (1 << RegisterOperand); + case lir::Multiply: + *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); break; - case Divide: - case Remainder: + case lir::Divide: + case lir::Remainder: // todo: we shouldn't need to defer to thunks for integers which // are smaller than or equal to tne native word size, but // PowerPC doesn't generate traps for divide by zero, so we'd @@ -2398,25 +2393,25 @@ class MyArchitecture: public Assembler::Architecture { if (true) {//if (TargetBytesPerWord == 4 and aSize == 8) { *thunk = true; } else { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); } break; - case FloatAdd: - case FloatSubtract: - case FloatMultiply: - case FloatDivide: - case FloatRemainder: - case JumpIfFloatEqual: - case JumpIfFloatNotEqual: - case JumpIfFloatLess: - case JumpIfFloatGreater: - case JumpIfFloatLessOrEqual: - case JumpIfFloatGreaterOrEqual: - case JumpIfFloatLessOrUnordered: - case JumpIfFloatGreaterOrUnordered: - case JumpIfFloatLessOrEqualOrUnordered: - case JumpIfFloatGreaterOrEqualOrUnordered: + case lir::FloatAdd: + case lir::FloatSubtract: + case lir::FloatMultiply: + case lir::FloatDivide: + case lir::FloatRemainder: + case lir::JumpIfFloatEqual: + case lir::JumpIfFloatNotEqual: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatLessOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: *thunk = true; break; @@ -2426,16 +2421,16 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (TernaryOperation op, + (lir::TernaryOperation op, unsigned, uint8_t, uint64_t, unsigned, uint8_t, const uint64_t, unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask) { if (isBranch(op)) { - *cTypeMask = (1 << ConstantOperand); + *cTypeMask = (1 << lir::ConstantOperand); *cRegisterMask = 0; } else { - *cTypeMask = (1 << RegisterOperand); + *cTypeMask = (1 << lir::RegisterOperand); *cRegisterMask = ~static_cast(0); } } @@ -2474,41 +2469,41 @@ class MyAssembler: public Assembler { virtual void checkStackOverflow(uintptr_t handler, unsigned stackLimitOffsetFromThread) { - Register stack(StackRegister); - Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); - Constant handlerConstant + lir::Register stack(StackRegister); + lir::Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); + lir::Constant handlerConstant (new(c.zone) ResolvedPromise(handler)); - branchRM(&c, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, + branchRM(&c, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } virtual void saveFrame(unsigned stackOffset, unsigned) { - Register returnAddress(0); + lir::Register returnAddress(0); emit(&c, mflr(returnAddress.low)); - Memory returnAddressDst + lir::Memory returnAddressDst (StackRegister, ReturnAddressOffset * TargetBytesPerWord); moveRM(&c, TargetBytesPerWord, &returnAddress, TargetBytesPerWord, &returnAddressDst); - Register stack(StackRegister); - Memory stackDst(ThreadRegister, stackOffset); + lir::Register stack(StackRegister); + lir::Memory stackDst(ThreadRegister, stackOffset); moveRM(&c, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); } virtual void pushFrame(unsigned argumentCount, ...) { struct { unsigned size; - OperandType type; - Operand* operand; + lir::OperandType type; + lir::Operand* operand; } arguments[argumentCount]; va_list a; va_start(a, argumentCount); unsigned footprint = 0; for (unsigned i = 0; i < argumentCount; ++i) { arguments[i].size = va_arg(a, unsigned); - arguments[i].type = static_cast(va_arg(a, int)); - arguments[i].operand = va_arg(a, Operand*); + arguments[i].type = static_cast(va_arg(a, int)); + arguments[i].operand = va_arg(a, lir::Operand*); footprint += ceilingDivide(arguments[i].size, TargetBytesPerWord); } va_end(a); @@ -2518,21 +2513,21 @@ class MyAssembler: public Assembler { unsigned offset = 0; for (unsigned i = 0; i < argumentCount; ++i) { if (i < arch_->argumentRegisterCount()) { - Register dst(arch_->argumentRegister(i)); + lir::Register dst(arch_->argumentRegister(i)); - apply(Move, - arguments[i].size, arguments[i].type, arguments[i].operand, - pad(arguments[i].size, TargetBytesPerWord), RegisterOperand, - &dst); + apply(lir::Move, + OperandInfo(arguments[i].size, arguments[i].type, arguments[i].operand), + OperandInfo(pad(arguments[i].size, TargetBytesPerWord), lir::RegisterOperand, + &dst)); offset += ceilingDivide(arguments[i].size, TargetBytesPerWord); } else { - Memory dst + lir::Memory dst (ThreadRegister, (offset + FrameFooterSize) * TargetBytesPerWord); - apply(Move, - arguments[i].size, arguments[i].type, arguments[i].operand, - pad(arguments[i].size, TargetBytesPerWord), MemoryOperand, &dst); + apply(lir::Move, + OperandInfo(arguments[i].size, arguments[i].type, arguments[i].operand), + OperandInfo(pad(arguments[i].size, TargetBytesPerWord), lir::MemoryOperand, &dst)); offset += ceilingDivide(arguments[i].size, TargetBytesPerWord); } @@ -2540,37 +2535,37 @@ class MyAssembler: public Assembler { } virtual void allocateFrame(unsigned footprint) { - Register returnAddress(0); + lir::Register returnAddress(0); emit(&c, mflr(returnAddress.low)); - Memory returnAddressDst + lir::Memory returnAddressDst (StackRegister, ReturnAddressOffset * TargetBytesPerWord); moveRM(&c, TargetBytesPerWord, &returnAddress, TargetBytesPerWord, &returnAddressDst); - Register stack(StackRegister); - Memory stackDst(StackRegister, -footprint * TargetBytesPerWord); + lir::Register stack(StackRegister); + lir::Memory stackDst(StackRegister, -footprint * TargetBytesPerWord); moveAndUpdateRM (&c, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); } virtual void adjustFrame(unsigned difference) { - Register nextStack(0); - Memory stackSrc(StackRegister, 0); + lir::Register nextStack(0); + lir::Memory stackSrc(StackRegister, 0); moveMR(&c, TargetBytesPerWord, &stackSrc, TargetBytesPerWord, &nextStack); - Memory stackDst(StackRegister, -difference * TargetBytesPerWord); + lir::Memory stackDst(StackRegister, -difference * TargetBytesPerWord); moveAndUpdateRM (&c, TargetBytesPerWord, &nextStack, TargetBytesPerWord, &stackDst); } virtual void popFrame(unsigned) { - Register stack(StackRegister); - Memory stackSrc(StackRegister, 0); + lir::Register stack(StackRegister); + lir::Memory stackSrc(StackRegister, 0); moveMR(&c, TargetBytesPerWord, &stackSrc, TargetBytesPerWord, &stack); - Register returnAddress(0); - Memory returnAddressSrc + lir::Register returnAddress(0); + lir::Memory returnAddressSrc (StackRegister, ReturnAddressOffset * TargetBytesPerWord); moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &returnAddress); @@ -2585,8 +2580,8 @@ class MyAssembler: public Assembler { { if (TailCalls) { if (offset) { - Register tmp(0); - Memory returnAddressSrc + lir::Register tmp(0); + lir::Memory returnAddressSrc (StackRegister, (ReturnAddressOffset + footprint) * TargetBytesPerWord); moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, @@ -2594,29 +2589,29 @@ class MyAssembler: public Assembler { emit(&c, mtlr(tmp.low)); - Memory stackSrc(StackRegister, footprint * TargetBytesPerWord); + lir::Memory stackSrc(StackRegister, footprint * TargetBytesPerWord); moveMR(&c, TargetBytesPerWord, &stackSrc, TargetBytesPerWord, &tmp); - Memory stackDst + lir::Memory stackDst (StackRegister, (footprint - offset) * TargetBytesPerWord); moveAndUpdateRM (&c, TargetBytesPerWord, &tmp, TargetBytesPerWord, &stackDst); - if (returnAddressSurrogate != NoRegister) { + if (returnAddressSurrogate != lir::NoRegister) { assert(&c, offset > 0); - Register ras(returnAddressSurrogate); - Memory dst + lir::Register ras(returnAddressSurrogate); + lir::Memory dst (StackRegister, (ReturnAddressOffset + offset) * TargetBytesPerWord); moveRM(&c, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); } - if (framePointerSurrogate != NoRegister) { + if (framePointerSurrogate != lir::NoRegister) { assert(&c, offset > 0); - Register fps(framePointerSurrogate); - Memory dst(StackRegister, offset * TargetBytesPerWord); + lir::Register fps(framePointerSurrogate); + lir::Memory dst(StackRegister, offset * TargetBytesPerWord); moveRM(&c, TargetBytesPerWord, &fps, TargetBytesPerWord, &dst); } } else { @@ -2636,11 +2631,11 @@ class MyAssembler: public Assembler { assert(&c, (argumentFootprint % StackAlignmentInWords) == 0); if (TailCalls and argumentFootprint > StackAlignmentInWords) { - Register tmp(0); - Memory stackSrc(StackRegister, 0); + lir::Register tmp(0); + lir::Memory stackSrc(StackRegister, 0); moveMR(&c, TargetBytesPerWord, &stackSrc, TargetBytesPerWord, &tmp); - Memory stackDst(StackRegister, + lir::Memory stackDst(StackRegister, (argumentFootprint - StackAlignmentInWords) * TargetBytesPerWord); moveAndUpdateRM @@ -2655,64 +2650,56 @@ class MyAssembler: public Assembler { { popFrame(frameFootprint); - Register tmp1(0); - Memory stackSrc(StackRegister, 0); + lir::Register tmp1(0); + lir::Memory stackSrc(StackRegister, 0); moveMR(&c, TargetBytesPerWord, &stackSrc, TargetBytesPerWord, &tmp1); - Register tmp2(5); - Memory newStackSrc(ThreadRegister, stackOffsetFromThread); + lir::Register tmp2(5); + lir::Memory newStackSrc(ThreadRegister, stackOffsetFromThread); moveMR(&c, TargetBytesPerWord, &newStackSrc, TargetBytesPerWord, &tmp2); - Register stack(StackRegister); + lir::Register stack(StackRegister); subR(&c, TargetBytesPerWord, &stack, &tmp2, &tmp2); - Memory stackDst(StackRegister, 0, tmp2.low); + lir::Memory stackDst(StackRegister, 0, tmp2.low); moveAndUpdateRM (&c, TargetBytesPerWord, &tmp1, TargetBytesPerWord, &stackDst); return_(&c); } - virtual void apply(Operation op) { + virtual void apply(lir::Operation op) { arch_->c.operations[op](&c); } - virtual void apply(UnaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand) + virtual void apply(lir::UnaryOperation op, OperandInfo a) { - arch_->c.unaryOperations[index(&(arch_->c), op, aType)] - (&c, aSize, aOperand); + arch_->c.unaryOperations[index(&(arch_->c), op, a.type)] + (&c, a.size, a.operand); } - virtual void apply(BinaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand, - unsigned bSize, OperandType bType, Operand* bOperand) + virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) { - arch_->c.binaryOperations[index(&(arch_->c), op, aType, bType)] - (&c, aSize, aOperand, bSize, bOperand); + arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)] + (&c, a.size, a.operand, b.size, b.operand); } - virtual void apply(TernaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand, - unsigned bSize, OperandType bType UNUSED, - Operand* bOperand, - unsigned cSize UNUSED, OperandType cType UNUSED, - Operand* cOperand) + virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) { if (isBranch(op)) { - assert(&c, aSize == bSize); - assert(&c, cSize == TargetBytesPerWord); - assert(&c, cType == ConstantOperand); + assert(&this->c, a.size == b.size); + assert(&this->c, c.size == TargetBytesPerWord); + assert(&this->c, c.type == lir::ConstantOperand); - arch_->c.branchOperations[branchIndex(&(arch_->c), aType, bType)] - (&c, op, aSize, aOperand, bOperand, cOperand); + arch_->c.branchOperations[branchIndex(&(arch_->c), a.type, b.type)] + (&this->c, op, a.size, a.operand, b.operand, c.operand); } else { - assert(&c, bSize == cSize); - assert(&c, bType == RegisterOperand); - assert(&c, cType == RegisterOperand); + assert(&this->c, b.size == c.size); + assert(&this->c, b.type == lir::RegisterOperand); + assert(&this->c, c.type == lir::RegisterOperand); - arch_->c.ternaryOperations[index(&(arch_->c), op, aType)] - (&c, bSize, aOperand, bOperand, cOperand); + arch_->c.ternaryOperations[index(&(arch_->c), op, a.type)] + (&this->c, b.size, a.operand, b.operand, c.operand); } } diff --git a/src/codegen/promise.h b/src/codegen/promise.h new file mode 100644 index 0000000000..1e21943999 --- /dev/null +++ b/src/codegen/promise.h @@ -0,0 +1,159 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_PROMISE_H +#define AVIAN_CODEGEN_PROMISE_H + +#include "allocator.h" + +namespace avian { +namespace codegen { + +class Promise { + public: + class Listener { + public: + virtual bool resolve(int64_t value, void** location) = 0; + + Listener* next; + }; + + virtual int64_t value() = 0; + virtual bool resolved() = 0; + virtual Listener* listen(unsigned) { return 0; } +}; + +class ResolvedPromise: public Promise { + public: + ResolvedPromise(int64_t value): value_(value) { } + + virtual int64_t value() { + return value_; + } + + virtual bool resolved() { + return true; + } + + 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 OffsetPromise: public Promise { + public: + OffsetPromise(Promise* base, int64_t offset): + base(base), offset(offset) + { } + + virtual int64_t value() { + return base->value() + offset; + } + + virtual bool resolved() { + return base->resolved(); + } + + Promise* base; + int64_t offset; +}; + +class ListenPromise: public Promise { + public: + ListenPromise(vm::System* s, vm::Allocator* allocator): + s(s), allocator(allocator), listener(0) + { } + + virtual int64_t value() { + abort(s); + } + + virtual bool resolved() { + return false; + } + + virtual Listener* listen(unsigned sizeInBytes) { + Listener* l = static_cast(allocator->allocate(sizeInBytes)); + l->next = listener; + listener = l; + return l; + } + + vm::System* s; + vm::Allocator* allocator; + Listener* listener; + Promise* promise; +}; + +class DelayedPromise: public ListenPromise { + public: + DelayedPromise(vm::System* s, vm::Allocator* allocator, Promise* basis, + DelayedPromise* next): + ListenPromise(s, allocator), basis(basis), next(next) + { } + + virtual int64_t value() { + abort(s); + } + + virtual bool resolved() { + return false; + } + + virtual Listener* listen(unsigned sizeInBytes) { + Listener* l = static_cast(allocator->allocate(sizeInBytes)); + l->next = listener; + listener = l; + return l; + } + + Promise* basis; + DelayedPromise* next; +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_PROMISE_H \ No newline at end of file diff --git a/src/codegen/targets.cpp b/src/codegen/targets.cpp index 64b5a0f630..2df6636120 100644 --- a/src/codegen/targets.cpp +++ b/src/codegen/targets.cpp @@ -14,7 +14,7 @@ namespace avian { namespace codegen { -vm::Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures UNUSED) { +Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures UNUSED) { #ifndef AVIAN_TARGET_ARCH #error "Must specify native target!" #endif diff --git a/src/codegen/targets.h b/src/codegen/targets.h index c4070b4641..1d146e4b4d 100644 --- a/src/codegen/targets.h +++ b/src/codegen/targets.h @@ -16,11 +16,11 @@ namespace avian { namespace codegen { -vm::Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures); +Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures); -vm::Assembler::Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures); -vm::Assembler::Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures); -vm::Assembler::Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures); +Assembler::Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures); +Assembler::Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures); +Assembler::Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures); } // namespace codegen } // namespace avian diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index e1f107dc32..02836f40a3 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -21,6 +21,7 @@ #define CAST_BRANCH(x) reinterpret_cast(x) using namespace vm; +using namespace avian::codegen; namespace { @@ -126,14 +127,14 @@ class MyBlock: public Assembler::Block { typedef void (*OperationType)(Context*); -typedef void (*UnaryOperationType)(Context*, unsigned, Assembler::Operand*); +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); typedef void (*BinaryOperationType) -(Context*, unsigned, Assembler::Operand*, unsigned, Assembler::Operand*); +(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); typedef void (*BranchOperationType) -(Context*, TernaryOperation, unsigned, Assembler::Operand*, - Assembler::Operand*, Assembler::Operand*); +(Context*, lir::TernaryOperation, unsigned, lir::Operand*, + lir::Operand*, lir::Operand*); class ArchitectureContext { public: @@ -143,17 +144,17 @@ class ArchitectureContext { System* s; bool useNativeFeatures; - OperationType operations[OperationCount]; - UnaryOperationType unaryOperations[UnaryOperationCount - * OperandTypeCount]; + OperationType operations[lir::OperationCount]; + UnaryOperationType unaryOperations[lir::UnaryOperationCount + * lir::OperandTypeCount]; BinaryOperationType binaryOperations - [(BinaryOperationCount + NonBranchTernaryOperationCount) - * OperandTypeCount - * OperandTypeCount]; + [(lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::OperandTypeCount + * lir::OperandTypeCount]; BranchOperationType branchOperations - [(BranchOperationCount) - * OperandTypeCount - * OperandTypeCount]; + [lir::BranchOperationCount + * lir::OperandTypeCount + * lir::OperandTypeCount]; }; class Context { @@ -482,44 +483,44 @@ void maybeRex(Context* c, unsigned size, int a, int index, int base, } else { byte = REX_NONE; } - if (a != NoRegister and (a & 8)) byte |= REX_R; - if (index != NoRegister and (index & 8)) byte |= REX_X; - if (base != NoRegister and (base & 8)) byte |= REX_B; + if (a != lir::NoRegister and (a & 8)) byte |= REX_R; + if (index != lir::NoRegister and (index & 8)) byte |= REX_X; + if (base != lir::NoRegister and (base & 8)) byte |= REX_B; if (always or byte != REX_NONE) c->code.append(byte); } } void -maybeRex(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) +maybeRex(Context* c, unsigned size, lir::Register* a, + lir::Register* b) { - maybeRex(c, size, a->low, NoRegister, b->low, false); + maybeRex(c, size, a->low, lir::NoRegister, b->low, false); } void -alwaysRex(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) +alwaysRex(Context* c, unsigned size, lir::Register* a, + lir::Register* b) { - maybeRex(c, size, a->low, NoRegister, b->low, true); + maybeRex(c, size, a->low, lir::NoRegister, b->low, true); } void -maybeRex(Context* c, unsigned size, Assembler::Register* a) +maybeRex(Context* c, unsigned size, lir::Register* a) { - maybeRex(c, size, NoRegister, NoRegister, a->low, false); + maybeRex(c, size, lir::NoRegister, lir::NoRegister, a->low, false); } void -maybeRex(Context* c, unsigned size, Assembler::Register* a, - Assembler::Memory* b) +maybeRex(Context* c, unsigned size, lir::Register* a, + lir::Memory* b) { maybeRex(c, size, a->low, b->index, b->base, size == 1 and (a->low & 4)); } void -maybeRex(Context* c, unsigned size, Assembler::Memory* a) +maybeRex(Context* c, unsigned size, lir::Memory* a) { - maybeRex(c, size, NoRegister, a->index, a->base, false); + maybeRex(c, size, lir::NoRegister, a->index, a->base, false); } int @@ -529,7 +530,7 @@ regCode(int a) } int -regCode(Assembler::Register* a) +regCode(lir::Register* a) { return regCode(a->low); } @@ -541,7 +542,7 @@ modrm(Context* c, uint8_t mod, int a, int b) } void -modrm(Context* c, uint8_t mod, Assembler::Register* a, Assembler::Register* b) +modrm(Context* c, uint8_t mod, lir::Register* a, lir::Register* b) { modrm(c, mod, a->low, b->low); } @@ -555,7 +556,7 @@ sib(Context* c, unsigned scale, int index, int base) void modrmSib(Context* c, int width, int a, int scale, int index, int base) { - if (index == NoRegister) { + if (index == lir::NoRegister) { modrm(c, width, base, a); if (regCode(base) == rsp) { sib(c, 0x00, rsp, rsp); @@ -582,7 +583,7 @@ modrmSibImm(Context* c, int a, int scale, int index, int base, int offset) void -modrmSibImm(Context* c, Assembler::Register* a, Assembler::Memory* b) +modrmSibImm(Context* c, lir::Register* a, lir::Memory* b) { modrmSibImm(c, a->low, b->scale, b->index, b->base, b->offset); } @@ -638,7 +639,7 @@ storeLoadBarrier(Context* c) } void -unconditional(Context* c, unsigned jump, Assembler::Constant* a) +unconditional(Context* c, unsigned jump, lir::Constant* a) { appendOffsetTask(c, a->value, offset(c), 5); @@ -647,7 +648,7 @@ unconditional(Context* c, unsigned jump, Assembler::Constant* a) } void -conditional(Context* c, unsigned condition, Assembler::Constant* a) +conditional(Context* c, unsigned condition, lir::Constant* a) { appendOffsetTask(c, a->value, offset(c), 6); @@ -656,66 +657,54 @@ conditional(Context* c, unsigned condition, Assembler::Constant* a) } unsigned -index(ArchitectureContext*, UnaryOperation operation, OperandType operand) +index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) { - return operation + (UnaryOperationCount * operand); + return operation + (lir::UnaryOperationCount * operand); } unsigned -index(ArchitectureContext*, BinaryOperation operation, - OperandType operand1, - OperandType operand2) +index(ArchitectureContext*, lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2) { return operation - + ((BinaryOperationCount + NonBranchTernaryOperationCount) * operand1) - + ((BinaryOperationCount + NonBranchTernaryOperationCount) - * OperandTypeCount * operand2); -} - -bool -isBranch(TernaryOperation op) -{ - return op > FloatMin; -} - -bool -isFloatBranch(TernaryOperation op) -{ - return op > JumpIfNotEqual; + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::OperandTypeCount * operand2); } unsigned -index(ArchitectureContext* c UNUSED, TernaryOperation operation, - OperandType operand1, OperandType operand2) +index(ArchitectureContext* c UNUSED, lir::TernaryOperation operation, + lir::OperandType operand1, lir::OperandType operand2) { assert(c, not isBranch(operation)); - return BinaryOperationCount + operation - + ((BinaryOperationCount + NonBranchTernaryOperationCount) * operand1) - + ((BinaryOperationCount + NonBranchTernaryOperationCount) - * OperandTypeCount * operand2); + return lir::BinaryOperationCount + operation + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::OperandTypeCount * operand2); } unsigned -branchIndex(ArchitectureContext* c UNUSED, OperandType operand1, - OperandType operand2) +branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, + lir::OperandType operand2) { - return operand1 + (OperandTypeCount * operand2); + return operand1 + (lir::OperandTypeCount * operand2); } void -moveCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b); +moveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); void -moveCR2(Context*, unsigned, Assembler::Constant*, unsigned, - Assembler::Register*, unsigned); +moveCR2(Context*, unsigned, lir::Constant*, unsigned, + lir::Register*, unsigned); void -callR(Context*, unsigned, Assembler::Register*); +callR(Context*, unsigned, lir::Register*); void -callC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +callC(Context* c, unsigned size UNUSED, lir::Constant* a) { assert(c, size == TargetBytesPerWord); @@ -723,12 +712,12 @@ callC(Context* c, unsigned size UNUSED, Assembler::Constant* a) } void -longCallC(Context* c, unsigned size, Assembler::Constant* a) +longCallC(Context* c, unsigned size, lir::Constant* a) { assert(c, size == TargetBytesPerWord); if (TargetBytesPerWord == 8) { - Assembler::Register r(LongJumpRegister); + lir::Register r(LongJumpRegister); moveCR2(c, size, a, size, &r, 11); callR(c, size, &r); } else { @@ -737,7 +726,7 @@ longCallC(Context* c, unsigned size, Assembler::Constant* a) } void -jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) +jumpR(Context* c, unsigned size UNUSED, lir::Register* a) { assert(c, size == TargetBytesPerWord); @@ -746,7 +735,7 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) } void -jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +jumpC(Context* c, unsigned size UNUSED, lir::Constant* a) { assert(c, size == TargetBytesPerWord); @@ -754,7 +743,7 @@ jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a) } void -jumpM(Context* c, unsigned size UNUSED, Assembler::Memory* a) +jumpM(Context* c, unsigned size UNUSED, lir::Memory* a) { assert(c, size == TargetBytesPerWord); @@ -764,12 +753,12 @@ jumpM(Context* c, unsigned size UNUSED, Assembler::Memory* a) } void -longJumpC(Context* c, unsigned size, Assembler::Constant* a) +longJumpC(Context* c, unsigned size, lir::Constant* a) { assert(c, size == TargetBytesPerWord); if (TargetBytesPerWord == 8) { - Assembler::Register r(LongJumpRegister); + lir::Register r(LongJumpRegister); moveCR2(c, size, a, size, &r, 11); jumpR(c, size, &r); } else { @@ -778,7 +767,7 @@ longJumpC(Context* c, unsigned size, Assembler::Constant* a) } void -callR(Context* c, unsigned size UNUSED, Assembler::Register* a) +callR(Context* c, unsigned size UNUSED, lir::Register* a) { assert(c, size == TargetBytesPerWord); @@ -788,7 +777,7 @@ callR(Context* c, unsigned size UNUSED, Assembler::Register* a) } void -callM(Context* c, unsigned size UNUSED, Assembler::Memory* a) +callM(Context* c, unsigned size UNUSED, lir::Memory* a) { assert(c, size == TargetBytesPerWord); @@ -798,14 +787,14 @@ callM(Context* c, unsigned size UNUSED, Assembler::Memory* a) } void -alignedCallC(Context* c, unsigned size, Assembler::Constant* a) +alignedCallC(Context* c, unsigned size, lir::Constant* a) { new(c->zone) AlignmentPadding(c, 1, 4); callC(c, size, a); } void -alignedLongCallC(Context* c, unsigned size, Assembler::Constant* a) +alignedLongCallC(Context* c, unsigned size, lir::Constant* a) { assert(c, size == TargetBytesPerWord); @@ -818,14 +807,14 @@ alignedLongCallC(Context* c, unsigned size, Assembler::Constant* a) } void -alignedJumpC(Context* c, unsigned size, Assembler::Constant* a) +alignedJumpC(Context* c, unsigned size, lir::Constant* a) { new (c->zone) AlignmentPadding(c, 1, 4); jumpC(c, size, a); } void -alignedLongJumpC(Context* c, unsigned size, Assembler::Constant* a) +alignedLongJumpC(Context* c, unsigned size, lir::Constant* a) { assert(c, size == TargetBytesPerWord); @@ -838,10 +827,10 @@ alignedLongJumpC(Context* c, unsigned size, Assembler::Constant* a) } void -pushR(Context* c, unsigned size, Assembler::Register* a) +pushR(Context* c, unsigned size, lir::Register* a) { if (TargetBytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); + lir::Register ah(a->high); pushR(c, 4, &ah); pushR(c, 4, a); @@ -852,14 +841,14 @@ pushR(Context* c, unsigned size, Assembler::Register* a) } void -moveRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b); +moveRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); void -popR(Context* c, unsigned size, Assembler::Register* a) +popR(Context* c, unsigned size, lir::Register* a) { if (TargetBytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); + lir::Register ah(a->high); popR(c, 4, a); popR(c, 4, &ah); @@ -873,19 +862,19 @@ popR(Context* c, unsigned size, Assembler::Register* a) } void -addCarryCR(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b); +addCarryCR(Context* c, unsigned size, lir::Constant* a, + lir::Register* b); void -negateR(Context* c, unsigned size, Assembler::Register* a) +negateR(Context* c, unsigned size, lir::Register* a) { if (TargetBytesPerWord == 4 and size == 8) { assert(c, a->low == rax and a->high == rdx); ResolvedPromise zeroPromise(0); - Assembler::Constant zero(&zeroPromise); + lir::Constant zero(&zeroPromise); - Assembler::Register ah(a->high); + lir::Register ah(a->high); negateR(c, 4, a); addCarryCR(c, 4, &zero, &ah); @@ -897,8 +886,8 @@ negateR(Context* c, unsigned size, Assembler::Register* a) } void -negateRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b UNUSED) +negateRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED) { assert(c, aSize == bSize); @@ -906,19 +895,19 @@ negateRR(Context* c, unsigned aSize, Assembler::Register* a, } void -moveCR2(Context* c, UNUSED unsigned aSize, Assembler::Constant* a, - UNUSED unsigned bSize, Assembler::Register* b, unsigned promiseOffset) +moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, + UNUSED unsigned bSize, lir::Register* b, unsigned promiseOffset) { if (TargetBytesPerWord == 4 and bSize == 8) { int64_t v = a->value->value(); ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); + lir::Register bh(b->high); moveCR(c, 4, &al, 4, b); moveCR(c, 4, &ah, 4, &bh); @@ -936,14 +925,14 @@ moveCR2(Context* c, UNUSED unsigned aSize, Assembler::Constant* a, } bool -floatReg(Assembler::Register* a) +floatReg(lir::Register* a) { return a->low >= xmm0; } void -sseMoveRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +sseMoveRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize >= 4); assert(c, aSize == bSize); @@ -974,19 +963,19 @@ sseMoveRR(Context* c, unsigned aSize, Assembler::Register* a, } void -sseMoveCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +sseMoveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize <= TargetBytesPerWord); - Assembler::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); + lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); moveCR2(c, aSize, a, aSize, &tmp, 0); sseMoveRR(c, aSize, &tmp, bSize, b); c->client->releaseTemporary(tmp.low); } void -moveCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +moveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { if (floatReg(b)) { sseMoveCR(c, aSize, a, bSize, b); @@ -996,8 +985,8 @@ moveCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -swapRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +swapRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); assert(c, aSize == TargetBytesPerWord); @@ -1008,8 +997,8 @@ swapRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, } void -moveRR(Context* c, unsigned aSize, Assembler::Register* a, - UNUSED unsigned bSize, Assembler::Register* b) +moveRR(Context* c, unsigned aSize, lir::Register* a, + UNUSED unsigned bSize, lir::Register* b) { if (floatReg(a) or floatReg(b)) { sseMoveRR(c, aSize, a, bSize, b); @@ -1017,8 +1006,8 @@ moveRR(Context* c, unsigned aSize, Assembler::Register* a, } if (TargetBytesPerWord == 4 and aSize == 8 and bSize == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); if (a->high == b->low) { if (a->low == b->high) { @@ -1089,8 +1078,8 @@ moveRR(Context* c, unsigned aSize, Assembler::Register* a, } void -sseMoveMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +sseMoveMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize >= 4); @@ -1107,8 +1096,8 @@ sseMoveMR(Context* c, unsigned aSize, Assembler::Memory* a, } void -moveMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize, Assembler::Register* b) +moveMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b) { if (floatReg(b)) { sseMoveMR(c, aSize, a, bSize, b); @@ -1149,8 +1138,8 @@ moveMR(Context* c, unsigned aSize, Assembler::Memory* a, case 8: if (TargetBytesPerWord == 4 and bSize == 8) { - Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); - Assembler::Register bh(b->high); + lir::Memory ah(a->base, a->offset + 4, a->index, a->scale); + lir::Register bh(b->high); moveMR(c, 4, a, 4, b); moveMR(c, 4, &ah, 4, &bh); @@ -1166,8 +1155,8 @@ moveMR(Context* c, unsigned aSize, Assembler::Memory* a, } void -sseMoveRM(Context* c, unsigned aSize, Assembler::Register* a, - UNUSED unsigned bSize, Assembler::Memory* b) +sseMoveRM(Context* c, unsigned aSize, lir::Register* a, + UNUSED unsigned bSize, lir::Memory* b) { assert(c, aSize >= 4); assert(c, aSize == bSize); @@ -1185,8 +1174,8 @@ sseMoveRM(Context* c, unsigned aSize, Assembler::Register* a, } void -moveRM(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Memory* b) +moveRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Memory* b) { assert(c, aSize == bSize); @@ -1227,8 +1216,8 @@ moveRM(Context* c, unsigned aSize, Assembler::Register* a, opcode(c, 0x89); modrmSibImm(c, a, b); } else { - Assembler::Register ah(a->high); - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); + lir::Register ah(a->high); + lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); moveRM(c, 4, a, 4, b); moveRM(c, 4, &ah, 4, &bh); @@ -1240,13 +1229,13 @@ moveRM(Context* c, unsigned aSize, Assembler::Register* a, } void -moveAR(Context* c, unsigned aSize, Assembler::Address* a, - unsigned bSize, Assembler::Register* b) +moveAR(Context* c, unsigned aSize, lir::Address* a, + unsigned bSize, lir::Register* b) { assert(c, TargetBytesPerWord == 8 or (aSize == 4 and bSize == 4)); - Assembler::Constant constant(a->address); - Assembler::Memory memory(b->low, 0, -1, 0); + lir::Constant constant(a->address); + lir::Memory memory(b->low, 0, -1, 0); moveCR(c, aSize, &constant, bSize, b); moveMR(c, bSize, &memory, bSize, b); @@ -1259,8 +1248,8 @@ shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) } void -moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a, - unsigned bSize, Assembler::Memory* b) +moveCM(Context* c, unsigned aSize UNUSED, lir::Constant* a, + unsigned bSize, lir::Memory* b) { switch (bSize) { case 1: @@ -1298,17 +1287,17 @@ moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a, modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); c->code.append4(a->value->value()); } else { - Assembler::Register tmp + lir::Register tmp (c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, 8, a, 8, &tmp); moveRM(c, 8, &tmp, 8, b); c->client->releaseTemporary(tmp.low); } } else { - Assembler::Constant ah(shiftMaskPromise(c, a->value, 32, 0xFFFFFFFF)); - Assembler::Constant al(shiftMaskPromise(c, a->value, 0, 0xFFFFFFFF)); + lir::Constant ah(shiftMaskPromise(c, a->value, 32, 0xFFFFFFFF)); + lir::Constant al(shiftMaskPromise(c, a->value, 0, 0xFFFFFFFF)); - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); + lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); moveCM(c, 4, &al, 4, b); moveCM(c, 4, &ah, 4, &bh); @@ -1320,8 +1309,8 @@ moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a, } void -moveZRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +moveZRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { switch (aSize) { case 2: @@ -1335,8 +1324,8 @@ moveZRR(Context* c, unsigned aSize, Assembler::Register* a, } void -moveZMR(Context* c, unsigned aSize UNUSED, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +moveZMR(Context* c, unsigned aSize UNUSED, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, bSize == TargetBytesPerWord); assert(c, aSize == 2); @@ -1347,8 +1336,8 @@ moveZMR(Context* c, unsigned aSize UNUSED, Assembler::Memory* a, } void -addCarryRR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) +addCarryRR(Context* c, unsigned size, lir::Register* a, + lir::Register* b) { assert(c, TargetBytesPerWord == 8 or size == 4); @@ -1358,14 +1347,14 @@ addCarryRR(Context* c, unsigned size, Assembler::Register* a, } void -addRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +addRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); if (TargetBytesPerWord == 4 and aSize == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); addRR(c, 4, a, 4, b); addCarryRR(c, 4, &ah, &bh); @@ -1377,8 +1366,8 @@ addRR(Context* c, unsigned aSize, Assembler::Register* a, } void -addCarryCR(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b) +addCarryCR(Context* c, unsigned size, lir::Constant* a, + lir::Register* b) { int64_t v = a->value->value(); @@ -1393,8 +1382,8 @@ addCarryCR(Context* c, unsigned size, Assembler::Constant* a, } void -addCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +addCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == bSize); @@ -1402,12 +1391,12 @@ addCR(Context* c, unsigned aSize, Assembler::Constant* a, if (v) { if (TargetBytesPerWord == 4 and bSize == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); + lir::Register bh(b->high); addCR(c, 4, &al, 4, b); addCarryCR(c, 4, &ah, &bh); @@ -1422,7 +1411,7 @@ addCR(Context* c, unsigned aSize, Assembler::Constant* a, c->code.append4(v); } } else { - Assembler::Register tmp + lir::Register tmp (c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, aSize, &tmp); addRR(c, aSize, &tmp, bSize, b); @@ -1433,8 +1422,8 @@ addCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, - Assembler::Register* b) +subtractBorrowCR(Context* c, unsigned size UNUSED, lir::Constant* a, + lir::Register* b) { assert(c, TargetBytesPerWord == 8 or size == 4); @@ -1449,12 +1438,12 @@ subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } void -subtractRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b); +subtractRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); void -subtractCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +subtractCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == bSize); @@ -1462,12 +1451,12 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a, if (v) { if (TargetBytesPerWord == 4 and bSize == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); + lir::Register bh(b->high); subtractCR(c, 4, &al, 4, b); subtractBorrowCR(c, 4, &ah, &bh); @@ -1482,7 +1471,7 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a, c->code.append4(v); } } else { - Assembler::Register tmp + lir::Register tmp (c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, aSize, &tmp); subtractRR(c, aSize, &tmp, bSize, b); @@ -1493,8 +1482,8 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -subtractBorrowRR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) +subtractBorrowRR(Context* c, unsigned size, lir::Register* a, + lir::Register* b) { assert(c, TargetBytesPerWord == 8 or size == 4); @@ -1504,14 +1493,14 @@ subtractBorrowRR(Context* c, unsigned size, Assembler::Register* a, } void -subtractRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +subtractRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); if (TargetBytesPerWord == 4 and aSize == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); subtractRR(c, 4, a, 4, b); subtractBorrowRR(c, 4, &ah, &bh); @@ -1523,15 +1512,15 @@ subtractRR(Context* c, unsigned aSize, Assembler::Register* a, } void -andRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +andRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); if (TargetBytesPerWord == 4 and aSize == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); andRR(c, 4, a, 4, b); andRR(c, 4, &ah, 4, &bh); @@ -1543,8 +1532,8 @@ andRR(Context* c, unsigned aSize, Assembler::Register* a, } void -andCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +andCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == bSize); @@ -1552,12 +1541,12 @@ andCR(Context* c, unsigned aSize, Assembler::Constant* a, if (TargetBytesPerWord == 4 and bSize == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); + lir::Register bh(b->high); andCR(c, 4, &al, 4, b); andCR(c, 4, &ah, 4, &bh); @@ -1572,7 +1561,7 @@ andCR(Context* c, unsigned aSize, Assembler::Constant* a, c->code.append4(v); } } else { - Assembler::Register tmp + lir::Register tmp (c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, aSize, &tmp); andRR(c, aSize, &tmp, bSize, b); @@ -1582,14 +1571,14 @@ andCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -orRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +orRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); if (TargetBytesPerWord == 4 and aSize == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); orRR(c, 4, a, 4, b); orRR(c, 4, &ah, 4, &bh); @@ -1601,8 +1590,8 @@ orRR(Context* c, unsigned aSize, Assembler::Register* a, } void -orCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +orCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == bSize); @@ -1610,12 +1599,12 @@ orCR(Context* c, unsigned aSize, Assembler::Constant* a, if (v) { if (TargetBytesPerWord == 4 and bSize == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); + lir::Register bh(b->high); orCR(c, 4, &al, 4, b); orCR(c, 4, &ah, 4, &bh); @@ -1630,7 +1619,7 @@ orCR(Context* c, unsigned aSize, Assembler::Constant* a, c->code.append4(v); } } else { - Assembler::Register tmp + lir::Register tmp (c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, aSize, &tmp); orRR(c, aSize, &tmp, bSize, b); @@ -1641,12 +1630,12 @@ orCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -xorRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +xorRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { if (TargetBytesPerWord == 4 and aSize == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); xorRR(c, 4, a, 4, b); xorRR(c, 4, &ah, 4, &bh); @@ -1658,8 +1647,8 @@ xorRR(Context* c, unsigned aSize, Assembler::Register* a, } void -xorCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +xorCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == bSize); @@ -1667,12 +1656,12 @@ xorCR(Context* c, unsigned aSize, Assembler::Constant* a, if (v) { if (TargetBytesPerWord == 4 and bSize == 8) { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); + lir::Constant ah(&high); ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + lir::Constant al(&low); - Assembler::Register bh(b->high); + lir::Register bh(b->high); xorCR(c, 4, &al, 4, b); xorCR(c, 4, &ah, 4, &bh); @@ -1687,7 +1676,7 @@ xorCR(Context* c, unsigned aSize, Assembler::Constant* a, c->code.append4(v); } } else { - Assembler::Register tmp + lir::Register tmp (c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, aSize, &tmp); xorRR(c, aSize, &tmp, bSize, b); @@ -1698,8 +1687,8 @@ xorCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -multiplyRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +multiplyRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); @@ -1712,12 +1701,12 @@ multiplyRR(Context* c, unsigned aSize, Assembler::Register* a, c->client->save(rax); - Assembler::Register axdx(rax, rdx); - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register axdx(rax, rdx); + lir::Register ah(a->high); + lir::Register bh(b->high); - Assembler::Register tmp(-1); - Assembler::Register* scratch; + lir::Register tmp(-1); + lir::Register* scratch; if (a->low == b->low) { tmp.low = c->client->acquireTemporary (GeneralRegisterMask & ~(1 << rax)); @@ -1749,30 +1738,30 @@ multiplyRR(Context* c, unsigned aSize, Assembler::Register* a, } void -branch(Context* c, TernaryOperation op, Assembler::Constant* target) +branch(Context* c, lir::TernaryOperation op, lir::Constant* target) { switch (op) { - case JumpIfEqual: + case lir::JumpIfEqual: conditional(c, 0x84, target); break; - case JumpIfNotEqual: + case lir::JumpIfNotEqual: conditional(c, 0x85, target); break; - case JumpIfLess: + case lir::JumpIfLess: conditional(c, 0x8c, target); break; - case JumpIfGreater: + case lir::JumpIfGreater: conditional(c, 0x8f, target); break; - case JumpIfLessOrEqual: + case lir::JumpIfLessOrEqual: conditional(c, 0x8e, target); break; - case JumpIfGreaterOrEqual: + case lir::JumpIfGreaterOrEqual: conditional(c, 0x8d, target); break; @@ -1782,49 +1771,49 @@ branch(Context* c, TernaryOperation op, Assembler::Constant* target) } void -branchFloat(Context* c, TernaryOperation op, Assembler::Constant* target) +branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) { switch (op) { - case JumpIfFloatEqual: + case lir::JumpIfFloatEqual: conditional(c, 0x84, target); break; - case JumpIfFloatNotEqual: + case lir::JumpIfFloatNotEqual: conditional(c, 0x85, target); break; - case JumpIfFloatLess: + case lir::JumpIfFloatLess: conditional(c, 0x82, target); break; - case JumpIfFloatGreater: + case lir::JumpIfFloatGreater: conditional(c, 0x87, target); break; - case JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqual: conditional(c, 0x86, target); break; - case JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: conditional(c, 0x83, target); break; - case JumpIfFloatLessOrUnordered: + case lir::JumpIfFloatLessOrUnordered: conditional(c, 0x82, target); conditional(c, 0x8a, target); break; - case JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: conditional(c, 0x87, target); conditional(c, 0x8a, target); break; - case JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfFloatLessOrEqualOrUnordered: conditional(c, 0x86, target); conditional(c, 0x8a, target); break; - case JumpIfFloatGreaterOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: conditional(c, 0x83, target); conditional(c, 0x8a, target); break; @@ -1835,8 +1824,8 @@ branchFloat(Context* c, TernaryOperation op, Assembler::Constant* target) } void -compareRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +compareRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); assert(c, aSize <= TargetBytesPerWord); @@ -1847,8 +1836,8 @@ compareRR(Context* c, unsigned aSize, Assembler::Register* a, } void -compareCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +compareCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == bSize); assert(c, TargetBytesPerWord == 8 or aSize == 4); @@ -1864,7 +1853,7 @@ compareCR(Context* c, unsigned aSize, Assembler::Constant* a, c->code.append4(v); } } else { - Assembler::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); + lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, aSize, &tmp); compareRR(c, aSize, &tmp, bSize, b); c->client->releaseTemporary(tmp.low); @@ -1872,8 +1861,8 @@ compareCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -compareRM(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Memory* b) +compareRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Memory* b) { assert(c, aSize == bSize); assert(c, TargetBytesPerWord == 8 or aSize == 4); @@ -1887,8 +1876,8 @@ compareRM(Context* c, unsigned aSize, Assembler::Register* a, } void -compareCM(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Memory* b) +compareCM(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b) { assert(c, aSize == bSize); assert(c, TargetBytesPerWord == 8 or aSize == 4); @@ -1907,7 +1896,7 @@ compareCM(Context* c, unsigned aSize, Assembler::Constant* a, abort(c); } } else { - Assembler::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); + lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, bSize, &tmp); compareRM(c, bSize, &tmp, bSize, b); c->client->releaseTemporary(tmp.low); @@ -1915,8 +1904,8 @@ compareCM(Context* c, unsigned aSize, Assembler::Constant* a, } void -compareFloatRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +compareFloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); @@ -1929,9 +1918,9 @@ compareFloatRR(Context* c, unsigned aSize, Assembler::Register* a, } void -branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, - Assembler::Operand* ah, Assembler::Operand* bl, - Assembler::Operand* bh, Assembler::Constant* target, +branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, BinaryOperationType compare) { compare(c, 4, ah, 4, bh); @@ -1939,7 +1928,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, unsigned next = 0; switch (op) { - case JumpIfEqual: + case lir::JumpIfEqual: opcode(c, 0x75); // jne next = c->code.length(); c->code.append(0); @@ -1948,14 +1937,14 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, 0x84, target); // je break; - case JumpIfNotEqual: + case lir::JumpIfNotEqual: conditional(c, 0x85, target); // jne compare(c, 4, al, 4, bl); conditional(c, 0x85, target); // jne break; - case JumpIfLess: + case lir::JumpIfLess: conditional(c, 0x8c, target); // jl opcode(c, 0x7f); // jg @@ -1966,7 +1955,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, 0x82, target); // jb break; - case JumpIfGreater: + case lir::JumpIfGreater: conditional(c, 0x8f, target); // jg opcode(c, 0x7c); // jl @@ -1977,7 +1966,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, 0x87, target); // ja break; - case JumpIfLessOrEqual: + case lir::JumpIfLessOrEqual: conditional(c, 0x8c, target); // jl opcode(c, 0x7f); // jg @@ -1988,7 +1977,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, conditional(c, 0x86, target); // jbe break; - case JumpIfGreaterOrEqual: + case lir::JumpIfGreaterOrEqual: conditional(c, 0x8f, target); // jg opcode(c, 0x7c); // jl @@ -2010,16 +1999,16 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, } void -branchRR(Context* c, TernaryOperation op, unsigned size, - Assembler::Register* a, Assembler::Register* b, - Assembler::Constant* target) +branchRR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target) { if (isFloatBranch(op)) { compareFloatRR(c, size, a, size, b); branchFloat(c, op, target); } else if (size > TargetBytesPerWord) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + lir::Register ah(a->high); + lir::Register bh(b->high); branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR)); } else { @@ -2029,9 +2018,9 @@ branchRR(Context* c, TernaryOperation op, unsigned size, } void -branchCR(Context* c, TernaryOperation op, unsigned size, - Assembler::Constant* a, Assembler::Register* b, - Assembler::Constant* target) +branchCR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target) { assert(c, not isFloatBranch(op)); @@ -2039,12 +2028,12 @@ branchCR(Context* c, TernaryOperation op, unsigned size, int64_t v = a->value->value(); ResolvedPromise low(v & ~static_cast(0)); - Assembler::Constant al(&low); + lir::Constant al(&low); ResolvedPromise high((v >> 32) & ~static_cast(0)); - Assembler::Constant ah(&high); + lir::Constant ah(&high); - Assembler::Register bh(b->high); + lir::Register bh(b->high); branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR)); } else { @@ -2054,9 +2043,9 @@ branchCR(Context* c, TernaryOperation op, unsigned size, } void -branchRM(Context* c, TernaryOperation op, unsigned size, - Assembler::Register* a, Assembler::Memory* b, - Assembler::Constant* target) +branchRM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target) { assert(c, not isFloatBranch(op)); assert(c, size <= TargetBytesPerWord); @@ -2066,9 +2055,9 @@ branchRM(Context* c, TernaryOperation op, unsigned size, } void -branchCM(Context* c, TernaryOperation op, unsigned size, - Assembler::Constant* a, Assembler::Memory* b, - Assembler::Constant* target) +branchCM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target) { assert(c, not isFloatBranch(op)); assert(c, size <= TargetBytesPerWord); @@ -2078,14 +2067,14 @@ branchCM(Context* c, TernaryOperation op, unsigned size, } void -multiplyCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +multiplyCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { assert(c, aSize == bSize); if (TargetBytesPerWord == 4 and aSize == 8) { const uint32_t mask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); - Assembler::Register tmp(c->client->acquireTemporary(mask), + lir::Register tmp(c->client->acquireTemporary(mask), c->client->acquireTemporary(mask)); moveCR(c, aSize, a, aSize, &tmp); @@ -2107,7 +2096,7 @@ multiplyCR(Context* c, unsigned aSize, Assembler::Constant* a, c->code.append4(v); } } else { - Assembler::Register tmp + lir::Register tmp (c->client->acquireTemporary(GeneralRegisterMask)); moveCR(c, aSize, a, aSize, &tmp); multiplyRR(c, aSize, &tmp, bSize, b); @@ -2118,8 +2107,8 @@ multiplyCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -divideRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b UNUSED) +divideRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED) { assert(c, aSize == bSize); @@ -2135,8 +2124,8 @@ divideRR(Context* c, unsigned aSize, Assembler::Register* a, } void -remainderRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +remainderRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, aSize == bSize); @@ -2150,25 +2139,25 @@ remainderRR(Context* c, unsigned aSize, Assembler::Register* a, maybeRex(c, aSize, b, a); opcode(c, 0xf7, 0xf8 + regCode(a)); - Assembler::Register dx(rdx); + lir::Register dx(rdx); moveRR(c, TargetBytesPerWord, &dx, TargetBytesPerWord, b); } void doShift(Context* c, UNUSED void (*shift) - (Context*, unsigned, Assembler::Register*, unsigned, - Assembler::Register*), - int type, UNUSED unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) + (Context*, unsigned, lir::Register*, unsigned, + lir::Register*), + int type, UNUSED unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { int64_t v = a->value->value(); if (TargetBytesPerWord == 4 and bSize == 8) { c->client->save(rcx); - Assembler::Register cx(rcx); + lir::Register cx(rcx); ResolvedPromise promise(v & 0x3F); - Assembler::Constant masked(&promise); + lir::Constant masked(&promise); moveCR(c, 4, &masked, 4, &cx); shift(c, aSize, &cx, bSize, b); } else { @@ -2185,15 +2174,15 @@ doShift(Context* c, UNUSED void (*shift) } void -shiftLeftRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b) +shiftLeftRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { if (TargetBytesPerWord == 4 and bSize == 8) { - Assembler::Register cx(rcx); + lir::Register cx(rcx); if (a->low != rcx) { c->client->save(rcx); ResolvedPromise promise(0x3F); - Assembler::Constant mask(&promise); + lir::Constant mask(&promise); moveRR(c, 4, a, 4, &cx); andCR(c, 4, &mask, 4, &cx); } @@ -2206,13 +2195,13 @@ shiftLeftRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, opcode(c, 0xd3, 0xe0 + b->low); ResolvedPromise promise(32); - Assembler::Constant constant(&promise); + lir::Constant constant(&promise); compareCR(c, aSize, &constant, aSize, &cx); opcode(c, 0x7c); //jl c->code.append(2 + 2); - Assembler::Register bh(b->high); + lir::Register bh(b->high); moveRR(c, 4, b, 4, &bh); // 2 bytes xorRR(c, 4, b, 4, b); // 2 bytes } else { @@ -2224,22 +2213,22 @@ shiftLeftRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, } void -shiftLeftCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +shiftLeftCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { doShift(c, shiftLeftRR, 0xe0, aSize, a, bSize, b); } void -shiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b) +shiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { if (TargetBytesPerWord == 4 and bSize == 8) { - Assembler::Register cx(rcx); + lir::Register cx(rcx); if (a->low != rcx) { c->client->save(rcx); ResolvedPromise promise(0x3F); - Assembler::Constant mask(&promise); + lir::Constant mask(&promise); moveRR(c, 4, a, 4, &cx); andCR(c, 4, &mask, 4, &cx); } @@ -2252,13 +2241,13 @@ shiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, opcode(c, 0xd3, 0xf8 + b->high); ResolvedPromise promise(32); - Assembler::Constant constant(&promise); + lir::Constant constant(&promise); compareCR(c, aSize, &constant, aSize, &cx); opcode(c, 0x7c); //jl c->code.append(2 + 3); - Assembler::Register bh(b->high); + lir::Register bh(b->high); moveRR(c, 4, &bh, 4, b); // 2 bytes // sar 31,high @@ -2273,22 +2262,22 @@ shiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, } void -shiftRightCR(Context* c, unsigned aSize, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +shiftRightCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { doShift(c, shiftRightRR, 0xf8, aSize, a, bSize, b); } void -unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b) +unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { if (TargetBytesPerWord == 4 and bSize == 8) { - Assembler::Register cx(rcx); + lir::Register cx(rcx); if (a->low != rcx) { c->client->save(rcx); ResolvedPromise promise(0x3F); - Assembler::Constant mask(&promise); + lir::Constant mask(&promise); moveRR(c, 4, a, 4, &cx); andCR(c, 4, &mask, 4, &cx); } @@ -2301,13 +2290,13 @@ unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, opcode(c, 0xd3, 0xe8 + b->high); ResolvedPromise promise(32); - Assembler::Constant constant(&promise); + lir::Constant constant(&promise); compareCR(c, aSize, &constant, aSize, &cx); opcode(c, 0x7c); //jl c->code.append(2 + 2); - Assembler::Register bh(b->high); + lir::Register bh(b->high); moveRR(c, 4, &bh, 4, b); // 2 bytes xorRR(c, 4, &bh, 4, &bh); // 2 bytes } else { @@ -2319,15 +2308,15 @@ unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, Assembler::Register* a, } void -unsignedShiftRightCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a, - unsigned bSize, Assembler::Register* b) +unsignedShiftRightCR(Context* c, unsigned aSize UNUSED, lir::Constant* a, + unsigned bSize, lir::Register* b) { doShift(c, unsignedShiftRightRR, 0xe8, aSize, a, bSize, b); } void -floatRegOp(Context* c, unsigned aSize, Assembler::Register* a, unsigned bSize, - Assembler::Register* b, uint8_t op, uint8_t mod = 0xc0) +floatRegOp(Context* c, unsigned aSize, lir::Register* a, unsigned bSize, + lir::Register* b, uint8_t op, uint8_t mod = 0xc0) { if (aSize == 4) { opcode(c, 0xf3); @@ -2340,8 +2329,8 @@ floatRegOp(Context* c, unsigned aSize, Assembler::Register* a, unsigned bSize, } void -floatMemOp(Context* c, unsigned aSize, Assembler::Memory* a, unsigned bSize, - Assembler::Register* b, uint8_t op) +floatMemOp(Context* c, unsigned aSize, lir::Memory* a, unsigned bSize, + lir::Register* b, uint8_t op) { if (aSize == 4) { opcode(c, 0xf3); @@ -2354,130 +2343,130 @@ floatMemOp(Context* c, unsigned aSize, Assembler::Memory* a, unsigned bSize, } void -floatSqrtRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatSqrtRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { floatRegOp(c, aSize, a, 4, b, 0x51); } void -floatSqrtMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatSqrtMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { floatMemOp(c, aSize, a, 4, b, 0x51); } void -floatAddRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatAddRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { floatRegOp(c, aSize, a, 4, b, 0x58); } void -floatAddMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatAddMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { floatMemOp(c, aSize, a, 4, b, 0x58); } void -floatSubtractRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatSubtractRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { floatRegOp(c, aSize, a, 4, b, 0x5c); } void -floatSubtractMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatSubtractMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { floatMemOp(c, aSize, a, 4, b, 0x5c); } void -floatMultiplyRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatMultiplyRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { floatRegOp(c, aSize, a, 4, b, 0x59); } void -floatMultiplyMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatMultiplyMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { floatMemOp(c, aSize, a, 4, b, 0x59); } void -floatDivideRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatDivideRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { floatRegOp(c, aSize, a, 4, b, 0x5e); } void -floatDivideMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatDivideMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { floatMemOp(c, aSize, a, 4, b, 0x5e); } void -float2FloatRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +float2FloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { floatRegOp(c, aSize, a, 4, b, 0x5a); } void -float2FloatMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize UNUSED, Assembler::Register* b) +float2FloatMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) { floatMemOp(c, aSize, a, 4, b, 0x5a); } void -float2IntRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b) +float2IntRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { assert(c, not floatReg(b)); floatRegOp(c, aSize, a, bSize, b, 0x2c); } void -float2IntMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize, Assembler::Register* b) +float2IntMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b) { floatMemOp(c, aSize, a, bSize, b, 0x2c); } void -int2FloatRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize, Assembler::Register* b) +int2FloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { floatRegOp(c, bSize, a, aSize, b, 0x2a); } void -int2FloatMR(Context* c, unsigned aSize, Assembler::Memory* a, - unsigned bSize, Assembler::Register* b) +int2FloatMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b) { floatMemOp(c, bSize, a, aSize, b, 0x2a); } void -floatNegateRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatNegateRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, floatReg(a) and floatReg(b)); // unlike most of the other floating point code, this does NOT // support doubles: assert(c, aSize == 4); ResolvedPromise pcon(0x80000000); - Assembler::Constant con(&pcon); + lir::Constant con(&pcon); if (a->low == b->low) { - Assembler::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); + lir::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); moveCR(c, 4, &con, 4, &tmp); maybeRex(c, 4, a, &tmp); opcode(c, 0x0f, 0x57); @@ -2493,17 +2482,17 @@ floatNegateRR(Context* c, unsigned aSize, Assembler::Register* a, } void -floatAbsoluteRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +floatAbsoluteRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { assert(c, floatReg(a) and floatReg(b)); // unlike most of the other floating point code, this does NOT // support doubles: assert(c, aSize == 4); ResolvedPromise pcon(0x7fffffff); - Assembler::Constant con(&pcon); + lir::Constant con(&pcon); if (a->low == b->low) { - Assembler::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); + lir::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); moveCR(c, 4, &con, 4, &tmp); maybeRex(c, 4, a, &tmp); opcode(c, 0x0f, 0x54); @@ -2518,11 +2507,11 @@ floatAbsoluteRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, } void -absoluteRR(Context* c, unsigned aSize, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b UNUSED) +absoluteRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED) { assert(c, aSize == bSize and a->low == rax and b->low == rax); - Assembler::Register d + lir::Register d (c->client->acquireTemporary(static_cast(1) << rdx)); maybeRex(c, aSize, a, b); opcode(c, 0x99); @@ -2624,114 +2613,114 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, void populateTables(ArchitectureContext* c) { - const OperandType C = ConstantOperand; - const OperandType A = AddressOperand; - const OperandType R = RegisterOperand; - const OperandType M = MemoryOperand; + const lir::OperandType C = lir::ConstantOperand; + const lir::OperandType A = lir::AddressOperand; + const lir::OperandType R = lir::RegisterOperand; + const lir::OperandType M = lir::MemoryOperand; OperationType* zo = c->operations; UnaryOperationType* uo = c->unaryOperations; BinaryOperationType* bo = c->binaryOperations; BranchOperationType* bro = c->branchOperations; - zo[Return] = return_; - zo[LoadBarrier] = ignore; - zo[StoreStoreBarrier] = ignore; - zo[StoreLoadBarrier] = storeLoadBarrier; - zo[Trap] = trap; + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = ignore; + zo[lir::StoreStoreBarrier] = ignore; + zo[lir::StoreLoadBarrier] = storeLoadBarrier; + zo[lir::Trap] = trap; - uo[index(c, Call, C)] = CAST1(callC); - uo[index(c, Call, R)] = CAST1(callR); - uo[index(c, Call, M)] = CAST1(callM); + uo[index(c, lir::Call, C)] = CAST1(callC); + uo[index(c, lir::Call, R)] = CAST1(callR); + uo[index(c, lir::Call, M)] = CAST1(callM); - uo[index(c, AlignedCall, C)] = CAST1(alignedCallC); + uo[index(c, lir::AlignedCall, C)] = CAST1(alignedCallC); - uo[index(c, LongCall, C)] = CAST1(longCallC); + uo[index(c, lir::LongCall, C)] = CAST1(longCallC); - uo[index(c, AlignedLongCall, C)] = CAST1(alignedLongCallC); + uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); - uo[index(c, Jump, R)] = CAST1(jumpR); - uo[index(c, Jump, C)] = CAST1(jumpC); - uo[index(c, Jump, M)] = CAST1(jumpM); + uo[index(c, lir::Jump, R)] = CAST1(jumpR); + uo[index(c, lir::Jump, C)] = CAST1(jumpC); + uo[index(c, lir::Jump, M)] = CAST1(jumpM); - uo[index(c, AlignedJump, C)] = CAST1(alignedJumpC); + uo[index(c, lir::AlignedJump, C)] = CAST1(alignedJumpC); - uo[index(c, LongJump, C)] = CAST1(longJumpC); + uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); - uo[index(c, AlignedLongJump, C)] = CAST1(alignedLongJumpC); + uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); - bo[index(c, Negate, R, R)] = CAST2(negateRR); + bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); - bo[index(c, FloatNegate, R, R)] = CAST2(floatNegateRR); + bo[index(c, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); - bo[index(c, Move, R, R)] = CAST2(moveRR); - bo[index(c, Move, C, R)] = CAST2(moveCR); - bo[index(c, Move, M, R)] = CAST2(moveMR); - bo[index(c, Move, R, M)] = CAST2(moveRM); - bo[index(c, Move, C, M)] = CAST2(moveCM); - bo[index(c, Move, A, R)] = CAST2(moveAR); + bo[index(c, lir::Move, R, R)] = CAST2(moveRR); + bo[index(c, lir::Move, C, R)] = CAST2(moveCR); + bo[index(c, lir::Move, M, R)] = CAST2(moveMR); + bo[index(c, lir::Move, R, M)] = CAST2(moveRM); + bo[index(c, lir::Move, C, M)] = CAST2(moveCM); + bo[index(c, lir::Move, A, R)] = CAST2(moveAR); - bo[index(c, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); - bo[index(c, FloatSquareRoot, M, R)] = CAST2(floatSqrtMR); + bo[index(c, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + bo[index(c, lir::FloatSquareRoot, M, R)] = CAST2(floatSqrtMR); - bo[index(c, MoveZ, R, R)] = CAST2(moveZRR); - bo[index(c, MoveZ, M, R)] = CAST2(moveZMR); - bo[index(c, MoveZ, C, R)] = CAST2(moveCR); + bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR); - bo[index(c, Add, R, R)] = CAST2(addRR); - bo[index(c, Add, C, R)] = CAST2(addCR); + bo[index(c, lir::Add, R, R)] = CAST2(addRR); + bo[index(c, lir::Add, C, R)] = CAST2(addCR); - bo[index(c, Subtract, C, R)] = CAST2(subtractCR); - bo[index(c, Subtract, R, R)] = CAST2(subtractRR); + bo[index(c, lir::Subtract, C, R)] = CAST2(subtractCR); + bo[index(c, lir::Subtract, R, R)] = CAST2(subtractRR); - bo[index(c, FloatAdd, R, R)] = CAST2(floatAddRR); - bo[index(c, FloatAdd, M, R)] = CAST2(floatAddMR); + bo[index(c, lir::FloatAdd, R, R)] = CAST2(floatAddRR); + bo[index(c, lir::FloatAdd, M, R)] = CAST2(floatAddMR); - bo[index(c, FloatSubtract, R, R)] = CAST2(floatSubtractRR); - bo[index(c, FloatSubtract, M, R)] = CAST2(floatSubtractMR); + bo[index(c, lir::FloatSubtract, R, R)] = CAST2(floatSubtractRR); + bo[index(c, lir::FloatSubtract, M, R)] = CAST2(floatSubtractMR); - bo[index(c, And, R, R)] = CAST2(andRR); - bo[index(c, And, C, R)] = CAST2(andCR); + bo[index(c, lir::And, R, R)] = CAST2(andRR); + bo[index(c, lir::And, C, R)] = CAST2(andCR); - bo[index(c, Or, R, R)] = CAST2(orRR); - bo[index(c, Or, C, R)] = CAST2(orCR); + bo[index(c, lir::Or, R, R)] = CAST2(orRR); + bo[index(c, lir::Or, C, R)] = CAST2(orCR); - bo[index(c, Xor, R, R)] = CAST2(xorRR); - bo[index(c, Xor, C, R)] = CAST2(xorCR); + bo[index(c, lir::Xor, R, R)] = CAST2(xorRR); + bo[index(c, lir::Xor, C, R)] = CAST2(xorCR); - bo[index(c, Multiply, R, R)] = CAST2(multiplyRR); - bo[index(c, Multiply, C, R)] = CAST2(multiplyCR); + bo[index(c, lir::Multiply, R, R)] = CAST2(multiplyRR); + bo[index(c, lir::Multiply, C, R)] = CAST2(multiplyCR); - bo[index(c, Divide, R, R)] = CAST2(divideRR); + bo[index(c, lir::Divide, R, R)] = CAST2(divideRR); - bo[index(c, FloatMultiply, R, R)] = CAST2(floatMultiplyRR); - bo[index(c, FloatMultiply, M, R)] = CAST2(floatMultiplyMR); + bo[index(c, lir::FloatMultiply, R, R)] = CAST2(floatMultiplyRR); + bo[index(c, lir::FloatMultiply, M, R)] = CAST2(floatMultiplyMR); - bo[index(c, FloatDivide, R, R)] = CAST2(floatDivideRR); - bo[index(c, FloatDivide, M, R)] = CAST2(floatDivideMR); + bo[index(c, lir::FloatDivide, R, R)] = CAST2(floatDivideRR); + bo[index(c, lir::FloatDivide, M, R)] = CAST2(floatDivideMR); - bo[index(c, Remainder, R, R)] = CAST2(remainderRR); + bo[index(c, lir::Remainder, R, R)] = CAST2(remainderRR); - bo[index(c, ShiftLeft, R, R)] = CAST2(shiftLeftRR); - bo[index(c, ShiftLeft, C, R)] = CAST2(shiftLeftCR); + bo[index(c, lir::ShiftLeft, R, R)] = CAST2(shiftLeftRR); + bo[index(c, lir::ShiftLeft, C, R)] = CAST2(shiftLeftCR); - bo[index(c, ShiftRight, R, R)] = CAST2(shiftRightRR); - bo[index(c, ShiftRight, C, R)] = CAST2(shiftRightCR); + bo[index(c, lir::ShiftRight, R, R)] = CAST2(shiftRightRR); + bo[index(c, lir::ShiftRight, C, R)] = CAST2(shiftRightCR); - bo[index(c, UnsignedShiftRight, R, R)] = CAST2(unsignedShiftRightRR); - bo[index(c, UnsignedShiftRight, C, R)] = CAST2(unsignedShiftRightCR); + bo[index(c, lir::UnsignedShiftRight, R, R)] = CAST2(unsignedShiftRightRR); + bo[index(c, lir::UnsignedShiftRight, C, R)] = CAST2(unsignedShiftRightCR); - bo[index(c, Float2Float, R, R)] = CAST2(float2FloatRR); - bo[index(c, Float2Float, M, R)] = CAST2(float2FloatMR); + bo[index(c, lir::Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(c, lir::Float2Float, M, R)] = CAST2(float2FloatMR); - bo[index(c, Float2Int, R, R)] = CAST2(float2IntRR); - bo[index(c, Float2Int, M, R)] = CAST2(float2IntMR); + bo[index(c, lir::Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(c, lir::Float2Int, M, R)] = CAST2(float2IntMR); - bo[index(c, Int2Float, R, R)] = CAST2(int2FloatRR); - bo[index(c, Int2Float, M, R)] = CAST2(int2FloatMR); + bo[index(c, lir::Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(c, lir::Int2Float, M, R)] = CAST2(int2FloatMR); - bo[index(c, Absolute, R, R)] = CAST2(absoluteRR); - bo[index(c, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + bo[index(c, lir::Absolute, R, R)] = CAST2(absoluteRR); + bo[index(c, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); @@ -2780,7 +2769,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual int returnHigh() { - return (TargetBytesPerWord == 4 ? rdx : NoRegister); + return (TargetBytesPerWord == 4 ? rdx : lir::NoRegister); } virtual int virtualCallTarget() { @@ -2891,28 +2880,28 @@ class MyArchitecture: public Assembler::Architecture { return *instruction == 0xE8 and actualTarget == target; } - virtual void updateCall(UnaryOperation op, void* returnAddress, + virtual void updateCall(lir::UnaryOperation op, void* returnAddress, void* newTarget) { bool assertAlignment UNUSED; switch (op) { - case AlignedCall: - op = Call; + case lir::AlignedCall: + op = lir::Call; assertAlignment = true; break; - case AlignedJump: - op = Jump; + case lir::AlignedJump: + op = lir::Jump; assertAlignment = true; break; - case AlignedLongCall: - op = LongCall; + case lir::AlignedLongCall: + op = lir::LongCall; assertAlignment = true; break; - case AlignedLongJump: - op = LongJump; + case lir::AlignedLongJump: + op = lir::LongJump; assertAlignment = true; break; @@ -2920,11 +2909,11 @@ class MyArchitecture: public Assembler::Architecture { assertAlignment = false; } - if (TargetBytesPerWord == 4 or op == Call or op == Jump) { + if (TargetBytesPerWord == 4 or op == lir::Call or op == lir::Jump) { uint8_t* instruction = static_cast(returnAddress) - 5; - assert(&c, ((op == Call or op == LongCall) and *instruction == 0xE8) - or ((op == Jump or op == LongJump) and *instruction == 0xE9)); + assert(&c, ((op == lir::Call or op == lir::LongCall) and *instruction == 0xE8) + or ((op == lir::Jump or op == lir::LongJump) and *instruction == 0xE9)); assert(&c, (not assertAlignment) or reinterpret_cast(instruction + 1) % 4 == 0); @@ -2942,8 +2931,8 @@ class MyArchitecture: public Assembler::Architecture { assert(&c, instruction[0] == 0x49 and instruction[1] == 0xBA); assert(&c, instruction[10] == 0x41 and instruction[11] == 0xFF); - assert(&c, (op == LongCall and instruction[12] == 0xD2) - or (op == LongJump and instruction[12] == 0xE2)); + assert(&c, (op == lir::LongCall and instruction[12] == 0xD2) + or (op == lir::LongJump and instruction[12] == 0xE2)); assert(&c, (not assertAlignment) or reinterpret_cast(instruction + 2) % 8 == 0); @@ -2987,18 +2976,18 @@ class MyArchitecture: public Assembler::Architecture { return 0; } - virtual bool alwaysCondensed(BinaryOperation op) { + virtual bool alwaysCondensed(lir::BinaryOperation op) { switch(op) { - case Float2Float: - case Float2Int: - case Int2Float: - case FloatAbsolute: - case FloatNegate: - case FloatSquareRoot: + case lir::Float2Float: + case lir::Float2Int: + case lir::Int2Float: + case lir::FloatAbsolute: + case lir::FloatNegate: + case lir::FloatSquareRoot: return false; - case Negate: - case Absolute: + case lir::Negate: + case lir::Absolute: return true; default: @@ -3006,7 +2995,7 @@ class MyArchitecture: public Assembler::Architecture { } } - virtual bool alwaysCondensed(TernaryOperation) { + virtual bool alwaysCondensed(lir::TernaryOperation) { return true; } @@ -3019,18 +3008,18 @@ class MyArchitecture: public Assembler::Architecture { } virtual void plan - (UnaryOperation, + (lir::UnaryOperation, unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, bool* thunk) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand) - | (1 << ConstantOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand) + | (1 << lir::ConstantOperand); *aRegisterMask = ~static_cast(0); *thunk = false; } virtual void planSource - (BinaryOperation op, + (lir::BinaryOperation op, unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned bSize, bool* thunk) { @@ -3041,24 +3030,24 @@ class MyArchitecture: public Assembler::Architecture { *thunk = false; switch (op) { - case Negate: - *aTypeMask = (1 << RegisterOperand); + case lir::Negate: + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = (static_cast(1) << (rdx + 32)) | (static_cast(1) << rax); break; - case Absolute: + case lir::Absolute: if (aSize <= TargetBytesPerWord) { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = (static_cast(1) << rax); } else { *thunk = true; } break; - case FloatAbsolute: + case lir::FloatAbsolute: if (useSSE(&c)) { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { @@ -3066,19 +3055,19 @@ class MyArchitecture: public Assembler::Architecture { } break; - case FloatNegate: + case lir::FloatNegate: // floatNegateRR does not support doubles if (useSSE(&c) and aSize == 4 and bSize == 4) { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = FloatRegisterMask; } else { *thunk = true; } break; - case FloatSquareRoot: + case lir::FloatSquareRoot: if (useSSE(&c)) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); *aRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { @@ -3086,9 +3075,9 @@ class MyArchitecture: public Assembler::Architecture { } break; - case Float2Float: + case lir::Float2Float: if (useSSE(&c)) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); *aRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { @@ -3096,13 +3085,13 @@ class MyArchitecture: public Assembler::Architecture { } break; - case Float2Int: + case lir::Float2Int: // todo: Java requires different semantics than SSE for // converting floats to integers, we we need to either use // thunks or produce inline machine code which handles edge // cases properly. if (false and useSSE(&c) and bSize <= TargetBytesPerWord) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); *aRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { @@ -3110,9 +3099,9 @@ class MyArchitecture: public Assembler::Architecture { } break; - case Int2Float: + case lir::Int2Float: if (useSSE(&c) and aSize <= TargetBytesPerWord) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); *aRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); } else { @@ -3120,18 +3109,18 @@ class MyArchitecture: public Assembler::Architecture { } break; - case Move: + case lir::Move: *aTypeMask = ~0; *aRegisterMask = ~static_cast(0); if (TargetBytesPerWord == 4) { if (aSize == 4 and bSize == 8) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); const uint32_t mask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); *aRegisterMask = (static_cast(mask) << 32) | mask; } else if (aSize == 1 or bSize == 1) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); const uint32_t mask = (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx); *aRegisterMask = (static_cast(mask) << 32) | mask; @@ -3145,7 +3134,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (BinaryOperation op, unsigned aSize, uint8_t aTypeMask, + (lir::BinaryOperation op, unsigned aSize, uint8_t aTypeMask, uint64_t aRegisterMask, unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask) { @@ -3154,42 +3143,42 @@ class MyArchitecture: public Assembler::Architecture { | (static_cast(GeneralRegisterMask) << 32); switch (op) { - case Absolute: - *bTypeMask = (1 << RegisterOperand); + case lir::Absolute: + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = (static_cast(1) << rax); break; - case FloatAbsolute: - *bTypeMask = (1 << RegisterOperand); + case lir::FloatAbsolute: + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = aRegisterMask; break; - case Negate: - *bTypeMask = (1 << RegisterOperand); + case lir::Negate: + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = aRegisterMask; break; - case FloatNegate: - case FloatSquareRoot: - case Float2Float: - case Int2Float: - *bTypeMask = (1 << RegisterOperand); + case lir::FloatNegate: + case lir::FloatSquareRoot: + case lir::Float2Float: + case lir::Int2Float: + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; break; - case Float2Int: - *bTypeMask = (1 << RegisterOperand); + case lir::Float2Int: + *bTypeMask = (1 << lir::RegisterOperand); break; - case Move: - if (aTypeMask & ((1 << MemoryOperand) | 1 << AddressOperand)) { - *bTypeMask = (1 << RegisterOperand); + case lir::Move: + if (aTypeMask & ((1 << lir::MemoryOperand) | 1 << lir::AddressOperand)) { + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32) | FloatRegisterMask; - } else if (aTypeMask & (1 << RegisterOperand)) { - *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + } else if (aTypeMask & (1 << lir::RegisterOperand)) { + *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); if (aRegisterMask & FloatRegisterMask) { *bRegisterMask = FloatRegisterMask; } else { @@ -3197,7 +3186,7 @@ class MyArchitecture: public Assembler::Architecture { | (static_cast(GeneralRegisterMask) << 32); } } else { - *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); } if (TargetBytesPerWord == 4) { @@ -3228,33 +3217,33 @@ class MyArchitecture: public Assembler::Architecture { *tmpTypeMask = 0; *tmpRegisterMask = 0; - if (dstTypeMask & (1 << MemoryOperand)) { + if (dstTypeMask & (1 << lir::MemoryOperand)) { // can't move directly from memory to memory - *srcTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); - *tmpTypeMask = 1 << RegisterOperand; + *srcTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); + *tmpTypeMask = 1 << lir::RegisterOperand; *tmpRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); - } else if (dstTypeMask & (1 << RegisterOperand)) { + } else if (dstTypeMask & (1 << lir::RegisterOperand)) { if (size > TargetBytesPerWord) { // can't move directly from FPR to GPR or vice-versa for // values larger than the GPR size if (dstRegisterMask & FloatRegisterMask) { *srcRegisterMask = FloatRegisterMask | (static_cast(FloatRegisterMask) << 32); - *tmpTypeMask = 1 << MemoryOperand; + *tmpTypeMask = 1 << lir::MemoryOperand; } else if (dstRegisterMask & GeneralRegisterMask) { *srcRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); - *tmpTypeMask = 1 << MemoryOperand; + *tmpTypeMask = 1 << lir::MemoryOperand; } } if (dstRegisterMask & FloatRegisterMask) { // can't move directly from constant to FPR - *srcTypeMask &= ~(1 << ConstantOperand); + *srcTypeMask &= ~(1 << lir::ConstantOperand); if (size > TargetBytesPerWord) { - *tmpTypeMask = 1 << MemoryOperand; + *tmpTypeMask = 1 << lir::MemoryOperand; } else { - *tmpTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *tmpTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); *tmpRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); } @@ -3263,29 +3252,29 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planSource - (TernaryOperation op, + (lir::TernaryOperation op, unsigned aSize, uint8_t *aTypeMask, uint64_t *aRegisterMask, unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask, unsigned, bool* thunk) { - *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); *aRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); - *bTypeMask = (1 << RegisterOperand); + *bTypeMask = (1 << lir::RegisterOperand); *bRegisterMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); *thunk = false; switch (op) { - case FloatAdd: - case FloatSubtract: - case FloatMultiply: - case FloatDivide: + case lir::FloatAdd: + case lir::FloatSubtract: + case lir::FloatMultiply: + case lir::FloatDivide: if (useSSE(&c)) { - *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); - *bTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + *bTypeMask = (1 << lir::RegisterOperand); const uint64_t mask = (static_cast(FloatRegisterMask) << 32) @@ -3297,11 +3286,11 @@ class MyArchitecture: public Assembler::Architecture { } break; - case FloatRemainder: + case lir::FloatRemainder: *thunk = true; break; - case Multiply: + case lir::Multiply: if (TargetBytesPerWord == 4 and aSize == 8) { const uint32_t mask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); *aRegisterMask = (static_cast(mask) << 32) | mask; @@ -3312,29 +3301,29 @@ class MyArchitecture: public Assembler::Architecture { } break; - case Divide: + case lir::Divide: if (TargetBytesPerWord == 4 and aSize == 8) { *thunk = true; } else { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); *bRegisterMask = 1 << rax; } break; - case Remainder: + case lir::Remainder: if (TargetBytesPerWord == 4 and aSize == 8) { *thunk = true; } else { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); *bRegisterMask = 1 << rax; } break; - case ShiftLeft: - case ShiftRight: - case UnsignedShiftRight: { + case lir::ShiftLeft: + case lir::ShiftRight: + case lir::UnsignedShiftRight: { if (TargetBytesPerWord == 4 and bSize == 8) { const uint32_t mask = GeneralRegisterMask & ~(1 << rcx); *aRegisterMask = (static_cast(mask) << 32) | mask; @@ -3347,18 +3336,18 @@ class MyArchitecture: public Assembler::Architecture { } } break; - case JumpIfFloatEqual: - case JumpIfFloatNotEqual: - case JumpIfFloatLess: - case JumpIfFloatGreater: - case JumpIfFloatLessOrEqual: - case JumpIfFloatGreaterOrEqual: - case JumpIfFloatLessOrUnordered: - case JumpIfFloatGreaterOrUnordered: - case JumpIfFloatLessOrEqualOrUnordered: - case JumpIfFloatGreaterOrEqualOrUnordered: + case lir::JumpIfFloatEqual: + case lir::JumpIfFloatNotEqual: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatLessOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: if (useSSE(&c)) { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << lir::RegisterOperand); *aRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; *bTypeMask = *aTypeMask; @@ -3374,15 +3363,15 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (TernaryOperation op, unsigned, uint8_t, uint64_t, unsigned, uint8_t, + (lir::TernaryOperation op, unsigned, uint8_t, uint64_t, unsigned, uint8_t, uint64_t bRegisterMask, unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask) { if (isBranch(op)) { - *cTypeMask = (1 << ConstantOperand); + *cTypeMask = (1 << lir::ConstantOperand); *cRegisterMask = 0; } else { - *cTypeMask = (1 << RegisterOperand); + *cTypeMask = (1 << lir::RegisterOperand); *cRegisterMask = bRegisterMask; } } @@ -3421,25 +3410,27 @@ class MyAssembler: public Assembler { virtual void checkStackOverflow(uintptr_t handler, unsigned stackLimitOffsetFromThread) { - Register stack(rsp); - Memory stackLimit(rbx, stackLimitOffsetFromThread); - Constant handlerConstant(resolved(&c, handler)); - branchRM(&c, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, + lir::Register stack(rsp); + lir::Memory stackLimit(rbx, stackLimitOffsetFromThread); + lir::Constant handlerConstant(resolved(&c, handler)); + branchRM(&c, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } virtual void saveFrame(unsigned stackOffset, unsigned) { - Register stack(rsp); - Memory stackDst(rbx, stackOffset); - apply(Move, TargetBytesPerWord, RegisterOperand, &stack, - TargetBytesPerWord, MemoryOperand, &stackDst); + lir::Register stack(rsp); + lir::Memory stackDst(rbx, stackOffset); + apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), + OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &stackDst)); } virtual void pushFrame(unsigned argumentCount, ...) { + // TODO: Argument should be replaced by OperandInfo... struct Argument { unsigned size; - OperandType type; - Operand* operand; + lir::OperandType type; + lir::Operand* operand; }; RUNTIME_ARRAY(Argument, arguments, argumentCount); va_list a; va_start(a, argumentCount); @@ -3447,8 +3438,8 @@ class MyAssembler: public Assembler { for (unsigned i = 0; i < argumentCount; ++i) { RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned); RUNTIME_ARRAY_BODY(arguments)[i].type - = static_cast(va_arg(a, int)); - RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, Operand*); + = static_cast(va_arg(a, int)); + RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*); footprint += ceilingDivide (RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord); } @@ -3459,23 +3450,27 @@ class MyAssembler: public Assembler { unsigned offset = 0; for (unsigned i = 0; i < argumentCount; ++i) { if (i < arch_->argumentRegisterCount()) { - Register dst(arch_->argumentRegister(i)); - apply(Move, - RUNTIME_ARRAY_BODY(arguments)[i].size, - RUNTIME_ARRAY_BODY(arguments)[i].type, - RUNTIME_ARRAY_BODY(arguments)[i].operand, - pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), - RegisterOperand, - &dst); + lir::Register dst(arch_->argumentRegister(i)); + apply(lir::Move, + OperandInfo( + RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo( + pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), + lir::RegisterOperand, + &dst)); } else { - Memory dst(rsp, offset * TargetBytesPerWord); - apply(Move, - RUNTIME_ARRAY_BODY(arguments)[i].size, - RUNTIME_ARRAY_BODY(arguments)[i].type, - RUNTIME_ARRAY_BODY(arguments)[i].operand, - pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), - MemoryOperand, - &dst); + lir::Memory dst(rsp, offset * TargetBytesPerWord); + apply(lir::Move, + OperandInfo( + RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo( + pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), + lir::MemoryOperand, + &dst)); offset += ceilingDivide (RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord); } @@ -3483,44 +3478,49 @@ class MyAssembler: public Assembler { } virtual void allocateFrame(unsigned footprint) { - Register stack(rsp); + lir::Register stack(rsp); if (UseFramePointer) { - Register base(rbp); + lir::Register base(rbp); pushR(&c, TargetBytesPerWord, &base); - apply(Move, TargetBytesPerWord, RegisterOperand, &stack, - TargetBytesPerWord, RegisterOperand, &base); + apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &base)); } - Constant footprintConstant(resolved(&c, footprint * TargetBytesPerWord)); - apply(Subtract, TargetBytesPerWord, ConstantOperand, &footprintConstant, - TargetBytesPerWord, RegisterOperand, &stack, - TargetBytesPerWord, RegisterOperand, &stack); + lir::Constant footprintConstant(resolved(&c, footprint * TargetBytesPerWord)); + apply(lir::Subtract, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &footprintConstant), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack)); } virtual void adjustFrame(unsigned difference) { - Register stack(rsp); - Constant differenceConstant(resolved(&c, difference * TargetBytesPerWord)); - apply(Subtract, TargetBytesPerWord, ConstantOperand, &differenceConstant, - TargetBytesPerWord, RegisterOperand, &stack, - TargetBytesPerWord, RegisterOperand, &stack); + lir::Register stack(rsp); + lir::Constant differenceConstant(resolved(&c, difference * TargetBytesPerWord)); + apply(lir::Subtract, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &differenceConstant), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack)); } virtual void popFrame(unsigned frameFootprint) { if (UseFramePointer) { - Register base(rbp); - Register stack(rsp); - apply(Move, TargetBytesPerWord, RegisterOperand, &base, - TargetBytesPerWord, RegisterOperand, &stack); + lir::Register base(rbp); + lir::Register stack(rsp); + apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &base), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack)); popR(&c, TargetBytesPerWord, &base); } else { - Register stack(rsp); - Constant footprint(resolved(&c, frameFootprint * TargetBytesPerWord)); - apply(Add, TargetBytesPerWord, ConstantOperand, &footprint, - TargetBytesPerWord, RegisterOperand, &stack, - TargetBytesPerWord, RegisterOperand, &stack); + lir::Register stack(rsp); + lir::Constant footprint(resolved(&c, frameFootprint * TargetBytesPerWord)); + apply(lir::Add, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &footprint), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack)); } } @@ -3531,16 +3531,16 @@ class MyAssembler: public Assembler { { if (TailCalls) { if (offset) { - Register tmp(c.client->acquireTemporary()); + lir::Register tmp(c.client->acquireTemporary()); unsigned baseSize = UseFramePointer ? 1 : 0; - Memory returnAddressSrc + lir::Memory returnAddressSrc (rsp, (frameFootprint + baseSize) * TargetBytesPerWord); moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &tmp); - Memory returnAddressDst + lir::Memory returnAddressDst (rsp, (frameFootprint - offset + baseSize) * TargetBytesPerWord); moveRM(&c, TargetBytesPerWord, &tmp, TargetBytesPerWord, &returnAddressDst); @@ -3548,31 +3548,31 @@ class MyAssembler: public Assembler { c.client->releaseTemporary(tmp.low); if (UseFramePointer) { - Memory baseSrc(rsp, frameFootprint * TargetBytesPerWord); - Register base(rbp); + lir::Memory baseSrc(rsp, frameFootprint * TargetBytesPerWord); + lir::Register base(rbp); moveMR(&c, TargetBytesPerWord, &baseSrc, TargetBytesPerWord, &base); } - Register stack(rsp); - Constant footprint + lir::Register stack(rsp); + lir::Constant footprint (resolved (&c, (frameFootprint - offset + baseSize) * TargetBytesPerWord)); addCR(&c, TargetBytesPerWord, &footprint, TargetBytesPerWord, &stack); - if (returnAddressSurrogate != NoRegister) { + if (returnAddressSurrogate != lir::NoRegister) { assert(&c, offset > 0); - Register ras(returnAddressSurrogate); - Memory dst(rsp, offset * TargetBytesPerWord); + lir::Register ras(returnAddressSurrogate); + lir::Memory dst(rsp, offset * TargetBytesPerWord); moveRM(&c, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); } - if (framePointerSurrogate != NoRegister) { + if (framePointerSurrogate != lir::NoRegister) { assert(&c, offset > 0); - Register fps(framePointerSurrogate); - Memory dst(rsp, (offset - 1) * TargetBytesPerWord); + lir::Register fps(framePointerSurrogate); + lir::Memory dst(rsp, (offset - 1) * TargetBytesPerWord); moveRM(&c, TargetBytesPerWord, &fps, TargetBytesPerWord, &dst); } } else { @@ -3592,11 +3592,11 @@ class MyAssembler: public Assembler { assert(&c, (argumentFootprint % StackAlignmentInWords) == 0); if (TailCalls and argumentFootprint > StackAlignmentInWords) { - Register returnAddress(rcx); + lir::Register returnAddress(rcx); popR(&c, TargetBytesPerWord, &returnAddress); - Register stack(rsp); - Constant adjustment + lir::Register stack(rsp); + lir::Constant adjustment (resolved(&c, (argumentFootprint - StackAlignmentInWords) * TargetBytesPerWord)); addCR(&c, TargetBytesPerWord, &adjustment, TargetBytesPerWord, &stack); @@ -3612,54 +3612,47 @@ class MyAssembler: public Assembler { { popFrame(frameFootprint); - Register returnAddress(rcx); + lir::Register returnAddress(rcx); popR(&c, TargetBytesPerWord, &returnAddress); - Register stack(rsp); - Memory stackSrc(rbx, stackOffsetFromThread); + lir::Register stack(rsp); + lir::Memory stackSrc(rbx, stackOffsetFromThread); moveMR(&c, TargetBytesPerWord, &stackSrc, TargetBytesPerWord, &stack); jumpR(&c, TargetBytesPerWord, &returnAddress); } - virtual void apply(Operation op) { + virtual void apply(lir::Operation op) { arch_->c.operations[op](&c); } - virtual void apply(UnaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand) + virtual void apply(lir::UnaryOperation op, OperandInfo a) { - arch_->c.unaryOperations[index(&(arch_->c), op, aType)] - (&c, aSize, aOperand); + arch_->c.unaryOperations[index(&(arch_->c), op, a.type)] + (&c, a.size, a.operand); } - virtual void apply(BinaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand, - unsigned bSize, OperandType bType, Operand* bOperand) + virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) { - arch_->c.binaryOperations[index(&(arch_->c), op, aType, bType)] - (&c, aSize, aOperand, bSize, bOperand); + arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)] + (&c, a.size, a.operand, b.size, b.operand); } - virtual void apply(TernaryOperation op, - unsigned aSize, OperandType aType, Operand* aOperand, - unsigned bSize, OperandType bType, Operand* bOperand, - unsigned cSize UNUSED, OperandType cType UNUSED, - Operand* cOperand) + virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) { if (isBranch(op)) { - assert(&c, aSize == bSize); - assert(&c, cSize == TargetBytesPerWord); - assert(&c, cType == ConstantOperand); + assert(&this->c, a.size == b.size); + assert(&this->c, c.size == TargetBytesPerWord); + assert(&this->c, c.type == lir::ConstantOperand); - arch_->c.branchOperations[branchIndex(&(arch_->c), aType, bType)] - (&c, op, aSize, aOperand, bOperand, cOperand); + arch_->c.branchOperations[branchIndex(&(arch_->c), a.type, b.type)] + (&this->c, op, a.size, a.operand, b.operand, c.operand); } else { - assert(&c, bSize == cSize); - assert(&c, bType == cType); + assert(&this->c, b.size == c.size); + assert(&this->c, b.type == c.type); - arch_->c.binaryOperations[index(&(arch_->c), op, aType, bType)] - (&c, aSize, aOperand, bSize, bOperand); + arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)] + (&this->c, a.size, a.operand, b.size, b.operand); } } diff --git a/src/compile.cpp b/src/compile.cpp index b01e56bee6..5b9245df15 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -37,6 +37,8 @@ vmJumpAndInvoke(void* thread, void* function, void* stack, unsigned argumentFootprint, uintptr_t* arguments, unsigned frameSize); +using avian::codegen::Compiler; + namespace { namespace local { @@ -291,7 +293,7 @@ class MyThread: public Thread { void** thunkTable; CallTrace* trace; Reference* reference; - Assembler::Architecture* arch; + avian::codegen::Assembler::Architecture* arch; Context* transition; TraceContext* traceContext; uintptr_t stackLimit; @@ -737,7 +739,7 @@ stackForFrame(MyThread* t, void* frame, object method) return static_cast(frame) - stackOffsetFromFrame(t, method); } -class PoolElement: public Promise { +class PoolElement: public avian::codegen::Promise { public: PoolElement(Thread* t, object target, PoolElement* next): t(t), target(target), address(0), next(next) @@ -793,7 +795,7 @@ class SubroutinePath; class SubroutineCall { public: - SubroutineCall(Subroutine* subroutine, Promise* returnAddress): + SubroutineCall(Subroutine* subroutine, avian::codegen::Promise* returnAddress): subroutine(subroutine), returnAddress(returnAddress), paths(0), @@ -804,7 +806,7 @@ class SubroutineCall { } Subroutine* subroutine; - Promise* returnAddress; + avian::codegen::Promise* returnAddress; SubroutinePath* paths; SubroutineCall* next; }; @@ -863,7 +865,7 @@ class SubroutineTrace { uintptr_t map[0]; }; -class TraceElement: public TraceHandler { +class TraceElement: public avian::codegen::TraceHandler { public: static const unsigned VirtualCall = 1 << 0; static const unsigned TailCall = 1 << 1; @@ -885,7 +887,7 @@ class TraceElement: public TraceHandler { memset(map, 0xFF, mapSize * BytesPerWord); } - virtual void handleTrace(Promise* address, unsigned argumentIndex) { + virtual void handleTrace(avian::codegen::Promise* address, unsigned argumentIndex) { if (this->address == 0) { this->address = address; this->argumentIndex = argumentIndex; @@ -893,7 +895,7 @@ class TraceElement: public TraceHandler { } Context* context; - Promise* address; + avian::codegen::Promise* address; TraceElement* next; SubroutineTrace* subroutineTrace; object target; @@ -905,7 +907,7 @@ class TraceElement: public TraceHandler { uintptr_t map[0]; }; -class TraceElementPromise: public Promise { +class TraceElementPromise: public avian::codegen::Promise { public: TraceElementPromise(System* s, TraceElement* trace): s(s), trace(trace) { } @@ -994,7 +996,7 @@ class BootContext { }; BootContext(Thread* t, object constants, object calls, - DelayedPromise* addresses, Zone* zone, OffsetResolver* resolver): + avian::codegen::DelayedPromise* addresses, Zone* zone, OffsetResolver* resolver): protector(t, this), constants(constants), calls(calls), addresses(addresses), addressSentinal(addresses), zone(zone), resolver(resolver) @@ -1003,8 +1005,8 @@ class BootContext { MyProtector protector; object constants; object calls; - DelayedPromise* addresses; - DelayedPromise* addressSentinal; + avian::codegen::DelayedPromise* addresses; + avian::codegen::DelayedPromise* addressSentinal; Zone* zone; OffsetResolver* resolver; }; @@ -1045,32 +1047,32 @@ class Context { public: MyClient(MyThread* t): t(t) { } - virtual intptr_t getThunk(UnaryOperation, unsigned) { + virtual intptr_t getThunk(avian::codegen::lir::UnaryOperation, unsigned) { abort(t); } - virtual intptr_t getThunk(BinaryOperation op, unsigned size, + virtual intptr_t getThunk(avian::codegen::lir::BinaryOperation op, unsigned size, unsigned resultSize) { if (size == 8) { switch(op) { - case Absolute: + case avian::codegen::lir::Absolute: assert(t, resultSize == 8); return local::getThunk(t, absoluteLongThunk); - case FloatNegate: + case avian::codegen::lir::FloatNegate: assert(t, resultSize == 8); return local::getThunk(t, negateDoubleThunk); - case FloatSquareRoot: + case avian::codegen::lir::FloatSquareRoot: assert(t, resultSize == 8); return local::getThunk(t, squareRootDoubleThunk); - case Float2Float: + case avian::codegen::lir::Float2Float: assert(t, resultSize == 4); return local::getThunk(t, doubleToFloatThunk); - case Float2Int: + case avian::codegen::lir::Float2Int: if (resultSize == 8) { return local::getThunk(t, doubleToLongThunk); } else { @@ -1078,7 +1080,7 @@ class Context { return local::getThunk(t, doubleToIntThunk); } - case Int2Float: + case avian::codegen::lir::Int2Float: if (resultSize == 8) { return local::getThunk(t, longToDoubleThunk); } else { @@ -1092,23 +1094,23 @@ class Context { assert(t, size == 4); switch(op) { - case Absolute: + case avian::codegen::lir::Absolute: assert(t, resultSize == 4); return local::getThunk(t, absoluteIntThunk); - case FloatNegate: + case avian::codegen::lir::FloatNegate: assert(t, resultSize == 4); return local::getThunk(t, negateFloatThunk); - case FloatAbsolute: + case avian::codegen::lir::FloatAbsolute: assert(t, resultSize == 4); return local::getThunk(t, absoluteFloatThunk); - case Float2Float: + case avian::codegen::lir::Float2Float: assert(t, resultSize == 8); return local::getThunk(t, floatToDoubleThunk); - case Float2Int: + case avian::codegen::lir::Float2Int: if (resultSize == 4) { return local::getThunk(t, floatToIntThunk); } else { @@ -1116,7 +1118,7 @@ class Context { return local::getThunk(t, floatToLongThunk); } - case Int2Float: + case avian::codegen::lir::Int2Float: if (resultSize == 4) { return local::getThunk(t, intToFloatThunk); } else { @@ -1129,48 +1131,48 @@ class Context { } } - virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned, + virtual intptr_t getThunk(avian::codegen::lir::TernaryOperation op, unsigned size, unsigned, bool* threadParameter) { *threadParameter = false; if (size == 8) { switch (op) { - case Divide: + case avian::codegen::lir::Divide: *threadParameter = true; return local::getThunk(t, divideLongThunk); - case Remainder: + case avian::codegen::lir::Remainder: *threadParameter = true; return local::getThunk(t, moduloLongThunk); - case FloatAdd: + case avian::codegen::lir::FloatAdd: return local::getThunk(t, addDoubleThunk); - case FloatSubtract: + case avian::codegen::lir::FloatSubtract: return local::getThunk(t, subtractDoubleThunk); - case FloatMultiply: + case avian::codegen::lir::FloatMultiply: return local::getThunk(t, multiplyDoubleThunk); - case FloatDivide: + case avian::codegen::lir::FloatDivide: return local::getThunk(t, divideDoubleThunk); - case FloatRemainder: + case avian::codegen::lir::FloatRemainder: return local::getThunk(t, moduloDoubleThunk); - case JumpIfFloatEqual: - case JumpIfFloatNotEqual: - case JumpIfFloatLess: - case JumpIfFloatGreater: - case JumpIfFloatLessOrEqual: - case JumpIfFloatGreaterOrUnordered: - case JumpIfFloatGreaterOrEqualOrUnordered: + case avian::codegen::lir::JumpIfFloatEqual: + case avian::codegen::lir::JumpIfFloatNotEqual: + case avian::codegen::lir::JumpIfFloatLess: + case avian::codegen::lir::JumpIfFloatGreater: + case avian::codegen::lir::JumpIfFloatLessOrEqual: + case avian::codegen::lir::JumpIfFloatGreaterOrUnordered: + case avian::codegen::lir::JumpIfFloatGreaterOrEqualOrUnordered: return local::getThunk(t, compareDoublesGThunk); - case JumpIfFloatGreaterOrEqual: - case JumpIfFloatLessOrUnordered: - case JumpIfFloatLessOrEqualOrUnordered: + case avian::codegen::lir::JumpIfFloatGreaterOrEqual: + case avian::codegen::lir::JumpIfFloatLessOrUnordered: + case avian::codegen::lir::JumpIfFloatLessOrEqualOrUnordered: return local::getThunk(t, compareDoublesLThunk); default: abort(t); @@ -1178,41 +1180,41 @@ class Context { } else { assert(t, size == 4); switch (op) { - case Divide: + case avian::codegen::lir::Divide: *threadParameter = true; return local::getThunk(t, divideIntThunk); - case Remainder: + case avian::codegen::lir::Remainder: *threadParameter = true; return local::getThunk(t, moduloIntThunk); - case FloatAdd: + case avian::codegen::lir::FloatAdd: return local::getThunk(t, addFloatThunk); - case FloatSubtract: + case avian::codegen::lir::FloatSubtract: return local::getThunk(t, subtractFloatThunk); - case FloatMultiply: + case avian::codegen::lir::FloatMultiply: return local::getThunk(t, multiplyFloatThunk); - case FloatDivide: + case avian::codegen::lir::FloatDivide: return local::getThunk(t, divideFloatThunk); - case FloatRemainder: + case avian::codegen::lir::FloatRemainder: return local::getThunk(t, moduloFloatThunk); - case JumpIfFloatEqual: - case JumpIfFloatNotEqual: - case JumpIfFloatLess: - case JumpIfFloatGreater: - case JumpIfFloatLessOrEqual: - case JumpIfFloatGreaterOrUnordered: - case JumpIfFloatGreaterOrEqualOrUnordered: + case avian::codegen::lir::JumpIfFloatEqual: + case avian::codegen::lir::JumpIfFloatNotEqual: + case avian::codegen::lir::JumpIfFloatLess: + case avian::codegen::lir::JumpIfFloatGreater: + case avian::codegen::lir::JumpIfFloatLessOrEqual: + case avian::codegen::lir::JumpIfFloatGreaterOrUnordered: + case avian::codegen::lir::JumpIfFloatGreaterOrEqualOrUnordered: return local::getThunk(t, compareFloatsGThunk); - case JumpIfFloatGreaterOrEqual: - case JumpIfFloatLessOrUnordered: - case JumpIfFloatLessOrEqualOrUnordered: + case avian::codegen::lir::JumpIfFloatGreaterOrEqual: + case avian::codegen::lir::JumpIfFloatLessOrUnordered: + case avian::codegen::lir::JumpIfFloatLessOrEqualOrUnordered: return local::getThunk(t, compareFloatsLThunk); default: abort(t); @@ -1297,9 +1299,9 @@ class Context { MyThread* thread; Zone zone; - Assembler* assembler; + avian::codegen::Assembler* assembler; MyClient client; - Compiler* compiler; + avian::codegen::Compiler* compiler; object method; BootContext* bootContext; PoolElement* objectPool; @@ -1359,6 +1361,8 @@ class Frame { Object }; + typedef Compiler::Operand* Value; + Frame(Context* context, uint8_t* stackMap): context(context), t(context->thread), @@ -1400,10 +1404,10 @@ class Frame { } } - Compiler::Operand* append(object o) { + Value append(object o) { BootContext* bc = context->bootContext; if (bc) { - Promise* p = new (bc->zone) ListenPromise(t->m->system, bc->zone); + avian::codegen::Promise* p = new (bc->zone) avian::codegen::ListenPromise(t->m->system, bc->zone); PROTECT(t, o); object pointer = makePointer(t, p); @@ -1623,34 +1627,34 @@ class Frame { set(sp - 2, saved); } - Promise* addressPromise(Promise* p) { + avian::codegen::Promise* addressPromise(avian::codegen::Promise* p) { BootContext* bc = context->bootContext; if (bc) { - bc->addresses = new(bc->zone) DelayedPromise(t->m->system, bc->zone, p, bc->addresses); + bc->addresses = new(bc->zone) avian::codegen::DelayedPromise(t->m->system, bc->zone, p, bc->addresses); return bc->addresses; } else { return p; } } - Compiler::Operand* addressOperand(Promise* p) { + Value addressOperand(avian::codegen::Promise* p) { return c->promiseConstant(p, Compiler::AddressType); } - Compiler::Operand* absoluteAddressOperand(Promise* p) { + Value absoluteAddressOperand(avian::codegen::Promise* p) { return context->bootContext ? c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, TARGET_THREAD_CODEIMAGE), c->promiseConstant (new(&context->zone) - OffsetPromise + avian::codegen::OffsetPromise (p, - reinterpret_cast(codeAllocator(t)->base)), Compiler::AddressType)) : addressOperand(p); } - Compiler::Operand* machineIp(unsigned logicalIp) { + Value machineIp(unsigned logicalIp) { return c->promiseConstant(c->machineIp(logicalIp), Compiler::AddressType); } @@ -1674,35 +1678,33 @@ class Frame { this->ip = ip; } - void pushQuiet(unsigned footprint, Compiler::Operand* o) { + void pushQuiet(unsigned footprint, Value o) { c->push(footprint, o); } - void pushLongQuiet(Compiler::Operand* o) { + void pushLongQuiet(Value o) { pushQuiet(2, o); } - Compiler::Operand* popQuiet(unsigned footprint) { + Value popQuiet(unsigned footprint) { return c->pop(footprint); } - Compiler::Operand* popLongQuiet() { - Compiler::Operand* r = popQuiet(2); - - return r; + Value popLongQuiet() { + return popQuiet(2); } - void pushInt(Compiler::Operand* o) { + void pushInt(Value o) { pushQuiet(1, o); pushedInt(); } - void pushAddress(Compiler::Operand* o) { + void pushAddress(Value o) { pushQuiet(1, o); pushedInt(); } - void pushObject(Compiler::Operand* o) { + void pushObject(Value o) { pushQuiet(1, o); pushedObject(); } @@ -1713,7 +1715,7 @@ class Frame { pushedObject(); } - void pushLong(Compiler::Operand* o) { + void pushLong(Value o) { pushLongQuiet(o); pushedLong(); } @@ -1723,17 +1725,17 @@ class Frame { c->popped(count); } - Compiler::Operand* popInt() { + Value popInt() { poppedInt(); return popQuiet(1); } - Compiler::Operand* popLong() { + Value popLong() { poppedLong(); return popLongQuiet(); } - Compiler::Operand* popObject() { + Value popObject() { poppedObject(); return popQuiet(1); } @@ -1789,8 +1791,8 @@ class Frame { } void dupX1() { - Compiler::Operand* s0 = popQuiet(1); - Compiler::Operand* s1 = popQuiet(1); + Value s0 = popQuiet(1); + Value s1 = popQuiet(1); pushQuiet(1, s0); pushQuiet(1, s1); @@ -1800,17 +1802,17 @@ class Frame { } void dupX2() { - Compiler::Operand* s0 = popQuiet(1); + Value s0 = popQuiet(1); if (get(sp - 2) == Long) { - Compiler::Operand* s1 = popLongQuiet(); + Value s1 = popLongQuiet(); pushQuiet(1, s0); pushLongQuiet(s1); pushQuiet(1, s0); } else { - Compiler::Operand* s1 = popQuiet(1); - Compiler::Operand* s2 = popQuiet(1); + Value s1 = popQuiet(1); + Value s2 = popQuiet(1); pushQuiet(1, s0); pushQuiet(1, s2); @@ -1825,8 +1827,8 @@ class Frame { if (get(sp - 1) == Long) { pushLongQuiet(c->peek(2, 0)); } else { - Compiler::Operand* s0 = popQuiet(1); - Compiler::Operand* s1 = popQuiet(1); + Value s0 = popQuiet(1); + Value s1 = popQuiet(1); pushQuiet(1, s1); pushQuiet(1, s0); @@ -1839,16 +1841,16 @@ class Frame { void dup2X1() { if (get(sp - 1) == Long) { - Compiler::Operand* s0 = popLongQuiet(); - Compiler::Operand* s1 = popQuiet(1); + Value s0 = popLongQuiet(); + Value s1 = popQuiet(1); pushLongQuiet(s0); pushQuiet(1, s1); pushLongQuiet(s0); } else { - Compiler::Operand* s0 = popQuiet(1); - Compiler::Operand* s1 = popQuiet(1); - Compiler::Operand* s2 = popQuiet(1); + Value s0 = popQuiet(1); + Value s1 = popQuiet(1); + Value s2 = popQuiet(1); pushQuiet(1, s1); pushQuiet(1, s0); @@ -1862,17 +1864,17 @@ class Frame { void dup2X2() { if (get(sp - 1) == Long) { - Compiler::Operand* s0 = popLongQuiet(); + Value s0 = popLongQuiet(); if (get(sp - 3) == Long) { - Compiler::Operand* s1 = popLongQuiet(); + Value s1 = popLongQuiet(); pushLongQuiet(s0); pushLongQuiet(s1); pushLongQuiet(s0); } else { - Compiler::Operand* s1 = popQuiet(1); - Compiler::Operand* s2 = popQuiet(1); + Value s1 = popQuiet(1); + Value s2 = popQuiet(1); pushLongQuiet(s0); pushQuiet(1, s2); @@ -1880,10 +1882,10 @@ class Frame { pushLongQuiet(s0); } } else { - Compiler::Operand* s0 = popQuiet(1); - Compiler::Operand* s1 = popQuiet(1); - Compiler::Operand* s2 = popQuiet(1); - Compiler::Operand* s3 = popQuiet(1); + Value s0 = popQuiet(1); + Value s1 = popQuiet(1); + Value s2 = popQuiet(1); + Value s3 = popQuiet(1); pushQuiet(1, s1); pushQuiet(1, s0); @@ -1897,8 +1899,8 @@ class Frame { } void swap() { - Compiler::Operand* s0 = popQuiet(1); - Compiler::Operand* s1 = popQuiet(1); + Value s0 = popQuiet(1); + Value s1 = popQuiet(1); pushQuiet(1, s0); pushQuiet(1, s1); @@ -1921,7 +1923,7 @@ class Frame { return e; } - unsigned startSubroutine(unsigned ip, Promise* returnAddress) { + unsigned startSubroutine(unsigned ip, avian::codegen::Promise* returnAddress) { pushAddress(absoluteAddressOperand(returnAddress)); Subroutine* subroutine = 0; @@ -1989,7 +1991,7 @@ class Frame { Context* context; MyThread* t; - Compiler* c; + avian::codegen::Compiler* c; Subroutine* subroutine; uint8_t* stackMap; unsigned ip; @@ -2194,7 +2196,7 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) unsigned argumentFootprint = t->arch->argumentFootprint(methodParameterFootprint(t, target)); unsigned alignment = t->arch->stackAlignmentInWords(); - if (TailCalls and argumentFootprint > alignment) { + if (avian::codegen::TailCalls and argumentFootprint > alignment) { top += argumentFootprint - alignment; } @@ -3379,11 +3381,11 @@ useLongJump(MyThread* t, uintptr_t target) Compiler::Operand* compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall, - bool useThunk, unsigned rSize, Promise* addressPromise) + bool useThunk, unsigned rSize, avian::codegen::Promise* addressPromise) { - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; - unsigned flags = (TailCalls and tailCall ? Compiler::TailJump : 0); + unsigned flags = (avian::codegen::TailCalls and tailCall ? Compiler::TailJump : 0); unsigned traceFlags; if (addressPromise == 0 and useLongJump(t, methodAddress(t, target))) { @@ -3394,18 +3396,18 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall, } if (useThunk - or (TailCalls and tailCall and (methodFlags(t, target) & ACC_NATIVE))) + or (avian::codegen::TailCalls and tailCall and (methodFlags(t, target) & ACC_NATIVE))) { if (frame->context->bootContext == 0) { flags |= Compiler::Aligned; } - if (TailCalls and tailCall) { + if (avian::codegen::TailCalls and tailCall) { traceFlags |= TraceElement::TailCall; TraceElement* trace = frame->trace(target, traceFlags); - Promise* returnAddressPromise = new + avian::codegen::Promise* returnAddressPromise = new (frame->context->zone.allocate(sizeof(TraceElementPromise))) TraceElementPromise(t->m->system, trace); @@ -3471,10 +3473,10 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall) if (bc) { if ((methodClass(t, target) == methodClass(t, frame->context->method) or (not classNeedsInit(t, methodClass(t, target)))) - and (not (TailCalls and tailCall + and (not (avian::codegen::TailCalls and tailCall and (methodFlags(t, target) & ACC_NATIVE)))) { - Promise* p = new(bc->zone) ListenPromise(t->m->system, bc->zone); + avian::codegen::Promise* p = new(bc->zone) avian::codegen::ListenPromise(t->m->system, bc->zone); PROTECT(t, target); object pointer = makePointer(t, p); @@ -3557,7 +3559,7 @@ void compileDirectReferenceInvoke(MyThread* t, Frame* frame, Thunk thunk, object reference, bool isStatic, bool tailCall) { - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; PROTECT(t, reference); @@ -3603,7 +3605,7 @@ void compileDirectAbstractInvoke(MyThread* t, Frame* frame, Thunk thunk, object target, bool tailCall) { - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; compileAbstractInvoke (t, frame, c->call @@ -3619,7 +3621,7 @@ compileDirectAbstractInvoke(MyThread* t, Frame* frame, Thunk thunk, void handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) { - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; object method = frame->context->method; if (methodFlags(t, method) & ACC_SYNCHRONIZED) { @@ -3728,7 +3730,7 @@ bool isTailCall(MyThread* t, object code, unsigned ip, object caller, int calleeReturnCode) { - return TailCalls + return avian::codegen::TailCalls and ((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0) and (not inTryBlock(t, code, ip - 1)) and (not needsReturnBarrier(t, caller)) @@ -3760,7 +3762,7 @@ integerBranch(MyThread* t, Frame* frame, object code, unsigned& ip, return false; } - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; unsigned instruction = codeBody(t, code, ip++); uint32_t offset = codeReadInt16(t, code, ip); uint32_t newIp = (ip - 3) + offset; @@ -3811,7 +3813,7 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, return false; } - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; unsigned instruction = codeBody(t, code, ip++); uint32_t offset = codeReadInt16(t, code, ip); uint32_t newIp = (ip - 3) + offset; @@ -3886,7 +3888,7 @@ intrinsic(MyThread* t, Frame* frame, object target) object className = vm::className(t, methodClass(t, target)); if (UNLIKELY(MATCH(className, "java/lang/Math"))) { - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; if (MATCH(methodName(t, target), "sqrt") and MATCH(methodSpec(t, target), "(D)D")) { @@ -3905,7 +3907,7 @@ intrinsic(MyThread* t, Frame* frame, object target) } } } else if (UNLIKELY(MATCH(className, "sun/misc/Unsafe"))) { - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; if (MATCH(methodName(t, target), "getByte") and MATCH(methodSpec(t, target), "(J)B")) { @@ -4099,7 +4101,7 @@ class SwitchState { unsigned count, unsigned defaultIp, Compiler::Operand* key, - Promise* start, + avian::codegen::Promise* start, int bottom, int top): state(state), @@ -4126,7 +4128,7 @@ class SwitchState { unsigned count; unsigned defaultIp; Compiler::Operand* key; - Promise* start; + avian::codegen::Promise* start; int bottom; int top; unsigned index; @@ -4146,7 +4148,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, }; Frame* frame = initialFrame; - Compiler* c = frame->c; + avian::codegen::Compiler* c = frame->c; Context* context = frame->context; unsigned stackSize = codeMaxStack(t, methodCode(t, context->method)); Stack stack(t); @@ -5673,7 +5675,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, Compiler::Operand* default_ = frame->addressOperand (frame->addressPromise(c->machineIp(defaultIp))); - Promise* start = 0; + avian::codegen::Promise* start = 0; uint32_t* ipTable = static_cast (stack.push(sizeof(uint32_t) * pairCount)); for (int32_t i = 0; i < pairCount; ++i) { @@ -5684,7 +5686,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, ipTable[i] = newIp; - Promise* p = c->poolAppend(key); + avian::codegen::Promise* p = c->poolAppend(key); if (i == 0) { start = p; } @@ -6199,7 +6201,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, int32_t bottom = codeReadInt32(t, code, ip); int32_t top = codeReadInt32(t, code, ip); - Promise* start = 0; + avian::codegen::Promise* start = 0; unsigned count = top - bottom + 1; uint32_t* ipTable = static_cast (stack.push(sizeof(uint32_t) * count)); @@ -6210,7 +6212,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, ipTable[i] = newIp; - Promise* p = c->poolAppendPromise + avian::codegen::Promise* p = c->poolAppendPromise (frame->addressPromise(c->machineIp(newIp))); if (i == 0) { start = p; @@ -6489,7 +6491,7 @@ truncateLineNumberTable(Thread* t, object table, unsigned length) object translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start) { - Compiler* c = context->compiler; + avian::codegen::Compiler* c = context->compiler; object oldTable = codeExceptionHandlerTable (t, methodCode(t, context->method)); @@ -6935,7 +6937,7 @@ simpleFrameMapTableSize(MyThread* t, object method, object map) } uint8_t* -finish(MyThread* t, FixedAllocator* allocator, Assembler* a, const char* name, +finish(MyThread* t, FixedAllocator* allocator, avian::codegen::Assembler* a, const char* name, unsigned length) { uint8_t* start = static_cast @@ -7214,7 +7216,7 @@ makeSimpleFrameMapTable(MyThread* t, Context* context, uint8_t* start, void finish(MyThread* t, FixedAllocator* allocator, Context* context) { - Compiler* c = context->compiler; + avian::codegen::Compiler* c = context->compiler; if (false) { logCompile @@ -7291,11 +7293,11 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) BootContext* bc = context->bootContext; if (bc) { - for (DelayedPromise* p = bc->addresses; + for (avian::codegen::DelayedPromise* p = bc->addresses; p != bc->addressSentinal; p = p->next) { - p->basis = new(bc->zone) ResolvedPromise(p->basis->value()); + p->basis = new(bc->zone) avian::codegen::ResolvedPromise(p->basis->value()); } } @@ -7400,7 +7402,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) void compile(MyThread* t, Context* context) { - Compiler* c = context->compiler; + avian::codegen::Compiler* c = context->compiler; // fprintf(stderr, "compiling %s.%s%s\n", // &byteArrayBody(t, className(t, methodClass(t, context->method)), 0), @@ -7534,7 +7536,7 @@ compile(MyThread* t, Context* context) } void -updateCall(MyThread* t, UnaryOperation op, void* returnAddress, void* target) +updateCall(MyThread* t, avian::codegen::lir::UnaryOperation op, void* returnAddress, void* target) { t->arch->updateCall(op, returnAddress, target); } @@ -7827,7 +7829,7 @@ invokeNative(MyThread* t) uintptr_t* stack = static_cast(t->stack); - if (TailCalls + if (avian::codegen::TailCalls and t->arch->argumentFootprint(parameterFootprint) > t->arch->stackAlignmentInWords()) { @@ -9264,7 +9266,7 @@ class MyProcessor: public Processor { } virtual void compileMethod(Thread* vmt, Zone* zone, object* constants, - object* calls, DelayedPromise** addresses, + object* calls, avian::codegen::DelayedPromise** addresses, object method, OffsetResolver* resolver) { MyThread* t = static_cast(vmt); @@ -9505,17 +9507,17 @@ compileMethod2(MyThread* t, void* ip) } if (updateCaller) { - UnaryOperation op; + avian::codegen::lir::UnaryOperation op; if (callNodeFlags(t, node) & TraceElement::LongCall) { if (callNodeFlags(t, node) & TraceElement::TailCall) { - op = AlignedLongJump; + op = avian::codegen::lir::AlignedLongJump; } else { - op = AlignedLongCall; + op = avian::codegen::lir::AlignedLongCall; } } else if (callNodeFlags(t, node) & TraceElement::TailCall) { - op = AlignedJump; + op = avian::codegen::lir::AlignedJump; } else { - op = AlignedCall; + op = avian::codegen::lir::AlignedCall; } updateCall(t, op, updateIp, reinterpret_cast(address)); @@ -10045,27 +10047,34 @@ thunkToThunk(const MyProcessor::Thunk& thunk, uint8_t* base) (thunk.start - base, thunk.frameSavedOffset, thunk.length); } +using avian::codegen::OperandInfo; +namespace lir = avian::codegen::lir; + void compileCall(MyThread* t, Context* c, ThunkIndex index, bool call = true) { - Assembler* a = c->assembler; + avian::codegen::Assembler* a = c->assembler; if (processor(t)->bootImage) { - Assembler::Memory table(t->arch->thread(), TARGET_THREAD_THUNKTABLE); - Assembler::Register scratch(t->arch->scratch()); - a->apply(Move, TargetBytesPerWord, MemoryOperand, &table, - TargetBytesPerWord, RegisterOperand, &scratch); - Assembler::Memory proc(scratch.low, index * TargetBytesPerWord); - a->apply(Move, TargetBytesPerWord, MemoryOperand, &proc, - TargetBytesPerWord, RegisterOperand, &scratch); + lir::Memory table(t->arch->thread(), TARGET_THREAD_THUNKTABLE); + lir::Register scratch(t->arch->scratch()); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &table), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &scratch)); + lir::Memory proc(scratch.low, index * TargetBytesPerWord); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &proc), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &scratch)); a->apply - (call ? Call : Jump, TargetBytesPerWord, RegisterOperand, &scratch); + (call ? lir::Call : lir::Jump, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &scratch)); } else { - Assembler::Constant proc - (new(&c->zone) ResolvedPromise(reinterpret_cast(t->thunkTable[index]))); + lir::Constant proc + (new(&c->zone) avian::codegen::ResolvedPromise(reinterpret_cast(t->thunkTable[index]))); a->apply - (call ? LongCall : LongJump, TargetBytesPerWord, ConstantOperand, &proc); + (call ? lir::LongCall : lir::LongJump, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &proc)); } } @@ -10075,21 +10084,22 @@ compileThunks(MyThread* t, FixedAllocator* allocator) MyProcessor* p = processor(t); { Context context(t); - Assembler* a = context.assembler; + avian::codegen::Assembler* a = context.assembler; a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.default_.frameSavedOffset = a->length(); - Assembler::Register thread(t->arch->thread()); - a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread); + lir::Register thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::RegisterOperand, &thread); compileCall(t, &context, compileMethodIndex); a->popFrame(t->arch->alignFrameSize(1)); - Assembler::Register result(t->arch->returnLow()); - a->apply(Jump, TargetBytesPerWord, RegisterOperand, &result); + lir::Register result(t->arch->returnLow()); + a->apply(lir::Jump, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &result)); p->thunks.default_.length = a->endBlock(false)->resolve(0, 0); @@ -10098,43 +10108,47 @@ compileThunks(MyThread* t, FixedAllocator* allocator) } { Context context(t); - Assembler* a = context.assembler; + avian::codegen::Assembler* a = context.assembler; - Assembler::Register class_(t->arch->virtualCallTarget()); - Assembler::Memory virtualCallTargetSrc + lir::Register class_(t->arch->virtualCallTarget()); + lir::Memory virtualCallTargetSrc (t->arch->stack(), (t->arch->frameFooterSize() + t->arch->frameReturnAddressSize()) * TargetBytesPerWord); - a->apply(Move, TargetBytesPerWord, MemoryOperand, &virtualCallTargetSrc, - TargetBytesPerWord, RegisterOperand, &class_); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &virtualCallTargetSrc), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &class_)); - Assembler::Memory virtualCallTargetDst + lir::Memory virtualCallTargetDst (t->arch->thread(), TARGET_THREAD_VIRTUALCALLTARGET); - a->apply(Move, TargetBytesPerWord, RegisterOperand, &class_, - TargetBytesPerWord, MemoryOperand, &virtualCallTargetDst); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &class_), + OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &virtualCallTargetDst)); - Assembler::Register index(t->arch->virtualCallIndex()); - Assembler::Memory virtualCallIndex + lir::Register index(t->arch->virtualCallIndex()); + lir::Memory virtualCallIndex (t->arch->thread(), TARGET_THREAD_VIRTUALCALLINDEX); - a->apply(Move, TargetBytesPerWord, RegisterOperand, &index, - TargetBytesPerWord, MemoryOperand, &virtualCallIndex); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &index), + OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &virtualCallIndex)); a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.defaultVirtual.frameSavedOffset = a->length(); - Assembler::Register thread(t->arch->thread()); - a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread); + lir::Register thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::RegisterOperand, &thread); compileCall(t, &context, compileVirtualMethodIndex); a->popFrame(t->arch->alignFrameSize(1)); - Assembler::Register result(t->arch->returnLow()); - a->apply(Jump, TargetBytesPerWord, RegisterOperand, &result); + lir::Register result(t->arch->returnLow()); + a->apply(lir::Jump, + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &result)); p->thunks.defaultVirtual.length = a->endBlock(false)->resolve(0, 0); @@ -10143,14 +10157,14 @@ compileThunks(MyThread* t, FixedAllocator* allocator) } { Context context(t); - Assembler* a = context.assembler; + avian::codegen::Assembler* a = context.assembler; a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.native.frameSavedOffset = a->length(); - Assembler::Register thread(t->arch->thread()); - a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread); + lir::Register thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::RegisterOperand, &thread); compileCall(t, &context, invokeNativeIndex); @@ -10164,14 +10178,14 @@ compileThunks(MyThread* t, FixedAllocator* allocator) } { Context context(t); - Assembler* a = context.assembler; + avian::codegen::Assembler* a = context.assembler; a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.aioob.frameSavedOffset = a->length(); - Assembler::Register thread(t->arch->thread()); - a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread); + lir::Register thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::RegisterOperand, &thread); compileCall(t, &context, throwArrayIndexOutOfBoundsIndex); @@ -10182,14 +10196,14 @@ compileThunks(MyThread* t, FixedAllocator* allocator) } { Context context(t); - Assembler* a = context.assembler; + avian::codegen::Assembler* a = context.assembler; a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.stackOverflow.frameSavedOffset = a->length(); - Assembler::Register thread(t->arch->thread()); - a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread); + lir::Register thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::RegisterOperand, &thread); compileCall(t, &context, throwStackOverflowIndex); @@ -10200,7 +10214,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) } { { Context context(t); - Assembler* a = context.assembler; + avian::codegen::Assembler* a = context.assembler; a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); @@ -10219,7 +10233,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) #define THUNK(s) { \ Context context(t); \ - Assembler* a = context.assembler; \ + avian::codegen::Assembler* a = context.assembler; \ \ a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); \ \ @@ -10317,17 +10331,19 @@ uintptr_t compileVirtualThunk(MyThread* t, unsigned index, unsigned* size) { Context context(t); - Assembler* a = context.assembler; + avian::codegen::Assembler* a = context.assembler; - ResolvedPromise indexPromise(index); - Assembler::Constant indexConstant(&indexPromise); - Assembler::Register indexRegister(t->arch->virtualCallIndex()); - a->apply(Move, TargetBytesPerWord, ConstantOperand, &indexConstant, - TargetBytesPerWord, RegisterOperand, &indexRegister); + avian::codegen::ResolvedPromise indexPromise(index); + lir::Constant indexConstant(&indexPromise); + lir::Register indexRegister(t->arch->virtualCallIndex()); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &indexConstant), + OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &indexRegister)); - ResolvedPromise defaultVirtualThunkPromise(defaultVirtualThunk(t)); - Assembler::Constant thunk(&defaultVirtualThunkPromise); - a->apply(Jump, TargetBytesPerWord, ConstantOperand, &thunk); + avian::codegen::ResolvedPromise defaultVirtualThunkPromise(defaultVirtualThunk(t)); + lir::Constant thunk(&defaultVirtualThunkPromise); + a->apply(lir::Jump, + OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &thunk)); *size = a->endBlock(false)->resolve(0, 0); diff --git a/src/processor.h b/src/processor.h index ab9d68e1aa..1c1de3e577 100644 --- a/src/processor.h +++ b/src/processor.h @@ -18,9 +18,13 @@ #include "heapwalk.h" #include "zone.h" -namespace vm { - +namespace avian { +namespace codegen { class DelayedPromise; +} +} + +namespace vm { class Processor { public: @@ -143,7 +147,7 @@ class Processor { virtual void compileMethod(Thread* t, Zone* zone, object* constants, object* calls, - DelayedPromise** addresses, object method, + avian::codegen::DelayedPromise** addresses, object method, OffsetResolver* resolver) = 0; virtual void From 6d39de064ce5283658ba67a4e5ee1614f2d8280d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Feb 2013 08:48:32 -0700 Subject: [PATCH 211/378] update bootimage.cpp and heapwalk.cpp to reflect function renames --- src/bootimage.cpp | 6 +++--- src/heapwalk.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 5a57a40e1c..111d850f97 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -14,7 +14,7 @@ #include "machine.h" #include "util.h" #include "stream.h" -#include "assembler.h" +#include "codegen/assembler.h" #include "target.h" #include "binaryToObject/tools.h" #include "lzma.h" @@ -31,7 +31,7 @@ namespace { const unsigned HeapCapacity = 512 * 1024 * 1024; const unsigned TargetFixieSizeInBytes = 8 + (TargetBytesPerWord * 2); -const unsigned TargetFixieSizeInWords = ceiling +const unsigned TargetFixieSizeInWords = ceilingDivide (TargetFixieSizeInBytes, TargetBytesPerWord); const unsigned TargetFixieAge = 0; const unsigned TargetFixieFlags = 2; @@ -787,7 +787,7 @@ targetSize(Thread* t, object typeMaps, object referer, unsigned refererOffset, { return (TargetBytesPerWord * 2) + pad - (ceiling + (ceilingDivide (objectMaskCount (classTypeMap(t, typeMaps, referer)), 32) * 4, TargetBytesPerWord); } else { diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index 69840abf16..8732d28497 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -228,7 +228,8 @@ inline object get(object o, unsigned offsetInWords) { return static_cast - (mask(fieldAtOffset(o, offsetInWords * BytesPerWord))); + (maskAlignedPointer + (fieldAtOffset(o, offsetInWords * BytesPerWord))); } unsigned @@ -297,7 +298,8 @@ class MyHeapWalker: public HeapWalker { Visitor(Context* c, HeapVisitor* v): c(c), v(v) { } virtual void visit(void* p) { - walk(c, v, static_cast(mask(*static_cast(p)))); + walk(c, v, static_cast + (maskAlignedPointer(*static_cast(p)))); } Context* c; From 144fdb8f4979a93253425010a84cf3393f18f9ac Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Feb 2013 09:04:04 -0700 Subject: [PATCH 212/378] include util/runtime-array.h in windows.cpp to fix build --- src/windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/windows.cpp b/src/windows.cpp index 02ebfc72b5..5c85eb906e 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -25,6 +25,7 @@ #include "arch.h" #include "system.h" +#include "util/runtime-array.h" #if defined(WINAPI_FAMILY) From fd47c6f406b9664d3f8e95c7c2f0ebc845df79f0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Feb 2013 09:09:30 -0700 Subject: [PATCH 213/378] switch clean target back to deleting all generated files --- makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/makefile b/makefile index f62fcb2346..5b793c169a 100755 --- a/makefile +++ b/makefile @@ -1268,11 +1268,6 @@ clean-current: .PHONY: clean clean: - @echo "removing $(build)" - rm -rf $(build) - -.PHONY: clean-all -clean-all: @echo "removing build" rm -rf build From 34471e5d607f2b6485d273984732f01323b823f3 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 11 Feb 2013 18:51:39 -0700 Subject: [PATCH 214/378] factor out assert / abort / expect implementations --- src/codegen/arm/assembler.cpp | 33 ++++--------------------- src/codegen/compiler.cpp | 28 +++++---------------- src/codegen/powerpc/assembler.cpp | 33 ++++--------------------- src/codegen/x86/assembler.cpp | 27 ++++---------------- src/heap.cpp | 19 +++----------- src/machine.cpp | 6 ++--- src/machine.h | 20 ++------------- src/system.h | 39 +++++++++++------------------ src/util/abort.h | 41 +++++++++++++++++++++++++++++++ src/util/runtime-array.h | 6 ++--- 10 files changed, 88 insertions(+), 164 deletions(-) create mode 100644 src/util/abort.h diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index ecaad31007..d92648aa2b 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -9,6 +9,7 @@ details. */ #include "alloc-vector.h" +#include "util/abort.h" #include "codegen/assembler.h" @@ -340,36 +341,12 @@ class ArchitectureContext { [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; }; -inline void NO_RETURN -abort(Context* con) -{ - abort(con->s); +inline Aborter* getAborter(Context* con) { + return con->s; } -inline void NO_RETURN -abort(ArchitectureContext* con) -{ - abort(con->s); -} - -#ifndef NDEBUG -inline void -assert(Context* con, bool v) -{ - assert(con->s, v); -} - -inline void -assert(ArchitectureContext* con, bool v) -{ - assert(con->s, v); -} -#endif // not NDEBUG - -inline void -expect(Context* con, bool v) -{ - expect(con->s, v); +inline Aborter* getAborter(ArchitectureContext* con) { + return con->s; } class Offset: public Promise { diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index ae8e6dd269..14777717ae 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -62,8 +62,6 @@ class StubRead; class Block; class Snapshot; -void NO_RETURN abort(Context*); - void apply(Context* c, lir::UnaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High); @@ -79,6 +77,8 @@ apply(Context* c, lir::TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); +inline Aborter* getAborter(Context* c); + class Cell { public: Cell(Cell* next, void* value): next(next), value(value) { } @@ -453,6 +453,10 @@ class Context { unsigned availableGeneralRegisterCount; }; +inline Aborter* getAborter(Context* c) { + return c->system; +} + unsigned RegisterResource::index(Context* c) { @@ -545,26 +549,6 @@ class IpPromise: public Promise { int logicalIp; }; -inline void NO_RETURN -abort(Context* c) -{ - abort(c->system); -} - -#ifndef NDEBUG -inline void -assert(Context* c, bool v) -{ - assert(c->system, v); -} -#endif // not NDEBUG - -inline void -expect(Context* c, bool v) -{ - expect(c->system, v); -} - unsigned count(Cell* c) { diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index ee263b25bc..87060c3b9b 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -10,6 +10,7 @@ #include "codegen/assembler.h" #include "alloc-vector.h" +#include "util/abort.h" #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) @@ -293,36 +294,12 @@ class ArchitectureContext { [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; }; -inline void NO_RETURN -abort(Context* c) -{ - abort(c->s); +inline Aborter* getAborter(Context* con) { + return con->s; } -inline void NO_RETURN -abort(ArchitectureContext* c) -{ - abort(c->s); -} - -#ifndef NDEBUG -inline void -assert(Context* c, bool v) -{ - assert(c->s, v); -} - -inline void -assert(ArchitectureContext* c, bool v) -{ - assert(c->s, v); -} -#endif // not NDEBUG - -inline void -expect(Context* c, bool v) -{ - expect(c->s, v); +inline Aborter* getAborter(ArchitectureContext* con) { + return con->s; } class Offset: public Promise { diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 02836f40a3..633dd49486 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -15,6 +15,7 @@ #include "codegen/assembler.h" #include "util/runtime-array.h" +#include "util/abort.h" #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) @@ -176,32 +177,14 @@ class Context { ArchitectureContext* ac; }; -void NO_RETURN -abort(Context* c) -{ - abort(c->s); +Aborter* getAborter(Context* c) { + return c->s; } -void NO_RETURN -abort(ArchitectureContext* c) -{ - abort(c->s); +Aborter* getAborter(ArchitectureContext* c) { + return c->s; } -#ifndef NDEBUG -void -assert(Context* c, bool v) -{ - assert(c->s, v); -} - -void -assert(ArchitectureContext* c, bool v) -{ - assert(c->s, v); -} -#endif // not NDEBUG - ResolvedPromise* resolved(Context* c, int64_t value) { diff --git a/src/heap.cpp b/src/heap.cpp index f706bca253..eadb13ef78 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -55,10 +55,7 @@ class MutexLock { class Context; -void NO_RETURN abort(Context*); -#ifndef NDEBUG -void assert(Context*, bool); -#endif +Aborter* getAborter(Context* c); void* tryAllocate(Context* c, unsigned size); void* allocate(Context* c, unsigned size); @@ -745,20 +742,10 @@ segment(Context* c, void* p) } } -inline void NO_RETURN -abort(Context* c) -{ - abort(c->system); +inline Aborter* getAborter(Context* c) { + return c->system; } -#ifndef NDEBUG -inline void -assert(Context* c, bool v) -{ - assert(c->system, v); -} -#endif - inline unsigned minimumNextGen1Capacity(Context* c) { diff --git a/src/machine.cpp b/src/machine.cpp index 677a7f9b92..395413e660 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3966,7 +3966,7 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size, Client(Thread* t): t(t) { } virtual void NO_RETURN handleError() { - vm::abort(t); + abort(t); } private: @@ -4853,11 +4853,11 @@ makeTrace(Thread* t, Processor::StackWalker* walker) virtual bool visit(Processor::StackWalker* walker) { if (trace == 0) { trace = makeObjectArray(t, walker->count()); - vm_assert(t, trace); + assert(t, trace); } object e = makeTraceElement(t, walker->method(), walker->ip()); - vm_assert(t, index < objectArrayLength(t, trace)); + assert(t, index < objectArrayLength(t, trace)); set(t, trace, ArrayBody + (index * BytesPerWord), e); ++ index; return true; diff --git a/src/machine.h b/src/machine.h index 909b647c01..d31b4bf7b1 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1761,24 +1761,8 @@ class RawMonitorResource: public Thread::Resource { System::Monitor* m; }; -inline void NO_RETURN -abort(Thread* t) -{ - abort(t->m->system); -} - -#ifndef NDEBUG -inline void -assert(Thread* t, bool v) -{ - assert(t->m->system, v); -} -#endif // not NDEBUG - -inline void -expect(Thread* t, bool v) -{ - expect(t->m->system, v); +inline Aborter* getAborter(Thread* t) { + return t->m->system; } class FixedAllocator: public Allocator { diff --git a/src/system.h b/src/system.h index ef69317f0b..1a95980da3 100644 --- a/src/system.h +++ b/src/system.h @@ -13,10 +13,11 @@ #include "common.h" #include "allocator.h" +#include "util/abort.h" namespace vm { -class System { +class System : public Aborter { public: typedef intptr_t Status; @@ -150,7 +151,6 @@ class System { virtual int64_t now() = 0; virtual void yield() = 0; virtual void exit(int code) = 0; - virtual void abort() = 0; virtual void dispose() = 0; }; @@ -165,11 +165,8 @@ allocate(System* s, unsigned size) #define ACQUIRE_MONITOR(t, m) \ System::MonitorResource MAKE_NAME(monitorResource_) (t, m) -inline void NO_RETURN -abort(System* s) -{ - s->abort(); // this should not return - ::abort(); +inline Aborter* getAborter(System* s) { + return s; } inline void NO_RETURN @@ -178,28 +175,22 @@ sysAbort(System* s) abort(s); } -inline void -expect(System* s, bool v) -{ - if (UNLIKELY(not v)) abort(s); -} +// #ifdef NDEBUG -#ifdef NDEBUG +// # define assert(a, b) +// # define vm_assert(a, b) -# define assert(a, b) -# define vm_assert(a, b) +// #else // not NDEBUG -#else // not NDEBUG +// inline void +// assert(System* s, bool v) +// { +// expect(s, v); +// } -inline void -assert(System* s, bool v) -{ - expect(s, v); -} +// # define vm_assert(a, b) vm::assert(a, b) -# define vm_assert(a, b) vm::assert(a, b) - -#endif // not NDEBUG +// #endif // not NDEBUG JNIEXPORT System* makeSystem(const char* crashDumpDirectory); diff --git a/src/util/abort.h b/src/util/abort.h new file mode 100644 index 0000000000..7624ea5b8f --- /dev/null +++ b/src/util/abort.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_ABORT_H +#define AVIAN_UTIL_ABORT_H + +class Aborter { +public: + virtual void NO_RETURN abort() = 0; +}; + +template +inline void NO_RETURN abort(T t) { + getAborter(t)->abort(); + ::abort(); +} + +template +inline void expect(T t, bool v) { + if(UNLIKELY(!v)) { + abort(t); + } +} + +#ifdef NDEBUG +#define assert(t, v) +#else +template +inline void assert(T t, bool v) { + expect(t, v); +} +#endif + +#endif // AVIAN_UTIL_ABORT_H \ No newline at end of file diff --git a/src/util/runtime-array.h b/src/util/runtime-array.h index 378718708d..ffd8e3348b 100644 --- a/src/util/runtime-array.h +++ b/src/util/runtime-array.h @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#ifndef UTIL_RUNTIME_ARRAY_H -#define UTIL_RUNTIME_ARRAY_H +#ifndef AVIAN_UTIL_RUNTIME_ARRAY_H +#define AVIAN_UTIL_RUNTIME_ARRAY_H #ifdef _MSC_VER @@ -37,4 +37,4 @@ class RuntimeArray { #endif -#endif \ No newline at end of file +#endif // AVIAN_UTIL_RUNTIME_ARRAY_H \ No newline at end of file From ef5e534e1ef5b32c7f062016f67c2faef9b21ed4 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 11 Feb 2013 21:31:19 -0700 Subject: [PATCH 215/378] begin moving register allocator out of compiler.cpp --- makefile | 2 + src/codegen/arm/assembler.cpp | 16 ++-- src/codegen/assembler.h | 5 +- src/codegen/compiler.cpp | 130 +++++++++++------------------- src/codegen/compiler.h | 6 +- src/codegen/powerpc/assembler.cpp | 12 +-- src/codegen/regalloc.cpp | 24 ++++++ src/codegen/regalloc.h | 37 +++++++++ src/codegen/registers.cpp | 35 ++++++++ src/codegen/registers.h | 51 ++++++++++++ src/codegen/x86/assembler.cpp | 16 ++-- 11 files changed, 225 insertions(+), 109 deletions(-) create mode 100644 src/codegen/regalloc.cpp create mode 100644 src/codegen/regalloc.h create mode 100644 src/codegen/registers.cpp create mode 100644 src/codegen/registers.h diff --git a/makefile b/makefile index f62fcb2346..4ff3aef558 100755 --- a/makefile +++ b/makefile @@ -953,6 +953,8 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) ifeq ($(process),compile) vm-sources += \ $(src)/codegen/compiler.cpp \ + $(src)/codegen/regalloc.cpp \ + $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp ifeq ($(codegen-targets),native) diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index d92648aa2b..c15007835f 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -8,11 +8,12 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include "codegen/assembler.h" +#include "codegen/registers.h" + #include "alloc-vector.h" #include "util/abort.h" -#include "codegen/assembler.h" - #include "util/runtime-array.h" #define CAST1(x) reinterpret_cast(x) @@ -210,6 +211,9 @@ const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32; // making the following const somehow breaks debug symbol output in GDB /* const */ uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32; +const RegisterFile MyRegisterFileWithoutFloats(GPR_MASK, 0); +const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK); + inline bool isFpr(lir::Register* reg) { return reg->low >= N_GPRS; } @@ -2057,12 +2061,8 @@ class MyArchitecture: public Assembler::Architecture { return vfpSupported() ? 8 : 0; } - virtual uint32_t generalRegisterMask() { - return GPR_MASK; - } - - virtual uint32_t floatRegisterMask() { - return vfpSupported() ? FPR_MASK : 0; + virtual const RegisterFile* registerFile() { + return vfpSupported() ? &MyRegisterFileWithFloats : &MyRegisterFileWithoutFloats; } virtual int scratch() { diff --git a/src/codegen/assembler.h b/src/codegen/assembler.h index d6ef7dd262..21301fd71f 100644 --- a/src/codegen/assembler.h +++ b/src/codegen/assembler.h @@ -20,6 +20,8 @@ namespace avian { namespace codegen { +class RegisterFile; + class OperandInfo { public: const unsigned size; @@ -66,8 +68,7 @@ class Assembler { public: virtual unsigned floatRegisterSize() = 0; - virtual uint32_t generalRegisterMask() = 0; - virtual uint32_t floatRegisterMask() = 0; + virtual const RegisterFile* registerFile() = 0; virtual int scratch() = 0; virtual int stack() = 0; diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 14777717ae..768b91748d 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -8,12 +8,14 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "compiler.h" -#include "assembler.h" #include "target.h" #include "util/runtime-array.h" +#include "codegen/compiler.h" +#include "codegen/assembler.h" +#include "codegen/regalloc.h" + using namespace vm; using namespace avian::codegen; @@ -338,30 +340,6 @@ class Value: public Compiler::Operand { uint8_t wordIndex; }; -uint32_t -registerMask(Assembler::Architecture* arch) -{ - return arch->generalRegisterMask() | arch->floatRegisterMask(); -} - -unsigned -maskStart(uint32_t mask) -{ - for (int i = 0; i <= 31; ++i) { - if (mask & (1 << i)) return i; - } - return 32; -} - -unsigned -maskLimit(uint32_t mask) -{ - for (int i = 31; i >= 0; --i) { - if (mask & (1 << i)) return i + 1; - } - return 0; -} - class Context { public: Context(System* system, Assembler* assembler, Zone* zone, @@ -376,15 +354,11 @@ class Context { saved(0), predecessor(0), logicalCode(0), - registerStart(maskStart(registerMask(arch))), - registerLimit(maskLimit(registerMask(arch))), - generalRegisterStart(maskStart(arch->generalRegisterMask())), - generalRegisterLimit(maskLimit(arch->generalRegisterMask())), - floatRegisterStart(maskStart(arch->floatRegisterMask())), - floatRegisterLimit(maskLimit(arch->floatRegisterMask())), + regFile(arch->registerFile()), + regAlloc(system, arch->registerFile()), registerResources (static_cast - (zone->allocate(sizeof(RegisterResource) * registerLimit))), + (zone->allocate(sizeof(RegisterResource) * regFile->allRegisters.limit))), frameResources(0), acquiredResources(0), firstConstant(0), @@ -402,16 +376,16 @@ class Context { localFootprint(0), machineCodeSize(0), alignedFrameSize(0), - availableGeneralRegisterCount(generalRegisterLimit - generalRegisterStart) + availableGeneralRegisterCount(regFile->generalRegisters.limit - regFile->generalRegisters.start) { - for (unsigned i = generalRegisterStart; i < generalRegisterLimit; ++i) { + for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) { new (registerResources + i) RegisterResource(arch->reserved(i)); if (registerResources[i].reserved) { -- availableGeneralRegisterCount; } } - for (unsigned i = floatRegisterStart; i < floatRegisterLimit; ++i) { + for (unsigned i = regFile->floatRegisters.start; i < regFile->floatRegisters.limit; ++i) { new (registerResources + i) RegisterResource(arch->reserved(i)); } } @@ -426,12 +400,8 @@ class Context { Cell* saved; Event* predecessor; LogicalInstruction** logicalCode; - uint8_t registerStart; - uint8_t registerLimit; - uint8_t generalRegisterStart; - uint8_t generalRegisterLimit; - uint8_t floatRegisterStart; - uint8_t floatRegisterLimit; + const RegisterFile* regFile; + regalloc::RegisterAllocator regAlloc; RegisterResource* registerResources; FrameResource* frameResources; Resource* acquiredResources; @@ -1158,7 +1128,7 @@ increment(Context* c, RegisterResource* r) ++ r->referenceCount; if (r->referenceCount == 1 - and ((1 << r->index(c)) & c->arch->generalRegisterMask())) + and ((1 << r->index(c)) & c->regFile->generalRegisters.mask)) { decrementAvailableGeneralRegisterCount(c); } @@ -1179,7 +1149,7 @@ decrement(Context* c, RegisterResource* r) -- r->referenceCount; if (r->referenceCount == 0 - and ((1 << r->index(c)) & c->arch->generalRegisterMask())) + and ((1 << r->index(c)) & c->regFile->generalRegisters.mask)) { incrementAvailableGeneralRegisterCount(c); } @@ -1204,7 +1174,7 @@ RegisterResource::freeze(Context* c, Value* v) freezeResource(c, this, v); if (freezeCount == 1 - and ((1 << index(c)) & c->arch->generalRegisterMask())) + and ((1 << index(c)) & c->regFile->generalRegisters.mask)) { decrementAvailableGeneralRegisterCount(c); } @@ -1239,7 +1209,7 @@ RegisterResource::thaw(Context* c, Value* v) thawResource(c, this, v); if (freezeCount == 0 - and ((1 << index(c)) & c->arch->generalRegisterMask())) + and ((1 << index(c)) & c->regFile->generalRegisters.mask)) { incrementAvailableGeneralRegisterCount(c); } @@ -1291,20 +1261,18 @@ valueType(Context* c, Compiler::OperandType type) class CostCalculator { public: - virtual unsigned cost(Context* c, uint8_t typeMask, uint32_t registerMask, - int frameIndex) = 0; + virtual unsigned cost(Context* c, SiteMask mask) = 0; }; unsigned -resourceCost(Context* c, Value* v, Resource* r, uint8_t typeMask, - uint32_t registerMask, int frameIndex, +resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, CostCalculator* costCalculator) { if (r->reserved or r->freezeCount or r->referenceCount) { return Target::Impossible; } else { - unsigned baseCost = costCalculator ? costCalculator->cost - (c, typeMask, registerMask, frameIndex) : 0; + unsigned baseCost = + costCalculator ? costCalculator->cost(c, mask) : 0; if (r->value) { assert(c, findSite(c, r->value, r->site)); @@ -1329,7 +1297,7 @@ pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, if ((1 << i) & mask) { RegisterResource* r = c->registerResources + i; unsigned myCost = resourceCost - (c, v, r, 1 << lir::RegisterOperand, 1 << i, NoFrameIndex, costCalculator) + (c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator) + Target::MinimumRegisterCost; if ((static_cast(1) << i) == mask) { @@ -1350,9 +1318,9 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, int target = lir::NoRegister; *cost = Target::Impossible; - if (mask & c->arch->generalRegisterMask()) { - for (int i = c->generalRegisterLimit - 1; - i >= c->generalRegisterStart; --i) + if (mask & c->regFile->generalRegisters.mask) { + for (int i = c->regFile->generalRegisters.limit - 1; + i >= c->regFile->generalRegisters.start; --i) { if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { return i; @@ -1360,9 +1328,9 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, } } - if (mask & c->arch->floatRegisterMask()) { - for (int i = c->floatRegisterStart; - i < static_cast(c->floatRegisterLimit); ++i) + if (mask & c->regFile->floatRegisters.mask) { + for (int i = c->regFile->floatRegisters.start; + i < static_cast(c->regFile->floatRegisters.limit); ++i) { if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { return i; @@ -1386,7 +1354,7 @@ unsigned frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator) { return resourceCost - (c, v, c->frameResources + frameIndex, 1 << lir::MemoryOperand, 0, frameIndex, + (c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex), costCalculator) + Target::MinimumFrameCost; } @@ -1482,13 +1450,13 @@ pickTarget(Context* c, Read* read, bool intersectRead, Value* value = read->value; uint32_t registerMask - = (value->type == lir::ValueFloat ? ~0 : c->arch->generalRegisterMask()); + = (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask); SiteMask mask(~0, registerMask, AnyFrameIndex); read->intersect(&mask); if (value->type == lir::ValueFloat) { - uint32_t floatMask = mask.registerMask & c->arch->floatRegisterMask(); + uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask; if (floatMask) { mask.registerMask = floatMask; } @@ -1813,7 +1781,7 @@ class RegisterSite: public Site { assert(c, number != lir::NoRegister); return number == rs->number; } else { - uint32_t mask = c->arch->generalRegisterMask(); + uint32_t mask = c->regFile->generalRegisters.mask; return ((1 << number) & mask) and ((1 << rs->number) & mask); } } @@ -1899,9 +1867,9 @@ class RegisterSite: public Site { virtual Site* makeNextWord(Context* c, unsigned) { assert(c, number != lir::NoRegister); - assert(c, ((1 << number) & c->arch->generalRegisterMask())); + assert(c, ((1 << number) & c->regFile->generalRegisters.mask)); - return freeRegisterSite(c, c->arch->generalRegisterMask()); + return freeRegisterSite(c, c->regFile->generalRegisters.mask); } virtual SiteMask mask(Context* c UNUSED) { @@ -1916,14 +1884,14 @@ class RegisterSite: public Site { (1 << lir::RegisterOperand, number, NoFrameIndex); } else { return SiteMask - (1 << lir::RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex); + (1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex); } } virtual unsigned registerSize(Context* c) { assert(c, number != lir::NoRegister); - if ((1 << number) & c->arch->floatRegisterMask()) { + if ((1 << number) & c->regFile->floatRegisters.mask) { return c->arch->floatRegisterSize(); } else { return TargetBytesPerWord; @@ -1944,8 +1912,8 @@ RegisterSite* registerSite(Context* c, int number) { assert(c, number >= 0); - assert(c, (1 << number) & (c->arch->generalRegisterMask() - | c->arch->floatRegisterMask())); + assert(c, (1 << number) & (c->regFile->generalRegisters.mask + | c->regFile->floatRegisters.mask)); return new(c->zone) RegisterSite(1 << number, number); } @@ -2382,8 +2350,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, includeNextWord(includeNextWord) { } - virtual unsigned cost(Context* c, uint8_t typeMask, uint32_t registerMask, - int frameIndex) + virtual unsigned cost(Context* c, SiteMask dstMask) { uint8_t srcTypeMask; uint64_t srcRegisterMask; @@ -2392,10 +2359,9 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, c->arch->planMove (size, &srcTypeMask, &srcRegisterMask, &tmpTypeMask, &tmpRegisterMask, - typeMask, registerMask); + dstMask.typeMask, dstMask.registerMask); SiteMask srcMask(srcTypeMask, srcRegisterMask, AnyFrameIndex); - SiteMask dstMask(typeMask, registerMask, frameIndex); for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) { Site* s = it.next(); if (s->match(c, srcMask) or s->match(c, dstMask)) { @@ -2615,7 +2581,7 @@ SiteMask generalRegisterMask(Context* c) { return SiteMask - (1 << lir::RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex); + (1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex); } SiteMask @@ -2623,7 +2589,7 @@ generalRegisterOrConstantMask(Context* c) { return SiteMask ((1 << lir::RegisterOperand) | (1 << lir::ConstantOperand), - c->arch->generalRegisterMask(), NoFrameIndex); + c->regFile->generalRegisters.mask, NoFrameIndex); } SiteMask @@ -3143,7 +3109,7 @@ class CallEvent: public Event { resultSize(resultSize), stackArgumentFootprint(stackArgumentFootprint) { - uint32_t registerMask = c->arch->generalRegisterMask(); + uint32_t registerMask = c->regFile->generalRegisters.mask; if (argumentCount) { assert(c, (flags & Compiler::TailJump) == 0); @@ -3564,7 +3530,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, dstSize, &thunk); if (src->type == lir::ValueGeneral) { - srcRegisterMask &= c->arch->generalRegisterMask(); + srcRegisterMask &= c->regFile->generalRegisters.mask; } assert(c, thunk == 0); @@ -4374,11 +4340,11 @@ loadLocal(Context* c, unsigned footprint, unsigned index) Value* register_(Context* c, int number) { - assert(c, (1 << number) & (c->arch->generalRegisterMask() - | c->arch->floatRegisterMask())); + assert(c, (1 << number) & (c->regFile->generalRegisters.mask + | c->regFile->floatRegisters.mask)); Site* s = registerSite(c, number); - lir::ValueType type = ((1 << number) & c->arch->floatRegisterMask()) + lir::ValueType type = ((1 << number) & c->regFile->floatRegisters.mask) ? lir::ValueFloat: lir::ValueGeneral; return value(c, type, s, s); @@ -5415,7 +5381,7 @@ resolveSourceSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) if (r and sites[el.localIndex] == 0) { SiteMask mask((1 << lir::RegisterOperand) | (1 << lir::MemoryOperand), - c->arch->generalRegisterMask(), AnyFrameIndex); + c->regFile->generalRegisters.mask, AnyFrameIndex); Site* s = pickSourceSite (c, r, 0, 0, &mask, true, false, true, acceptForResolve); @@ -5449,7 +5415,7 @@ resolveTargetSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) if (r and sites[el.localIndex] == 0) { SiteMask mask((1 << lir::RegisterOperand) | (1 << lir::MemoryOperand), - c->arch->generalRegisterMask(), AnyFrameIndex); + c->regFile->generalRegisters.mask, AnyFrameIndex); Site* s = pickSourceSite (c, r, 0, 0, &mask, false, true, true, acceptForResolve); diff --git a/src/codegen/compiler.h b/src/codegen/compiler.h index fbaad83791..b7aeeed2dc 100644 --- a/src/codegen/compiler.h +++ b/src/codegen/compiler.h @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#ifndef COMPILER_H -#define COMPILER_H +#ifndef AVIAN_CODEGEN_COMPILER_H +#define AVIAN_CODEGEN_COMPILER_H #include "system.h" #include "zone.h" @@ -207,4 +207,4 @@ makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone, } // namespace codegen } // namespace avian -#endif//COMPILER_H +#endif // AVIAN_CODEGEN_COMPILER_H diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 87060c3b9b..426891d475 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -9,6 +9,8 @@ details. */ #include "codegen/assembler.h" +#include "codegen/registers.h" + #include "alloc-vector.h" #include "util/abort.h" @@ -153,6 +155,8 @@ inline int unha16(int32_t high, int32_t low) { return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; } +const RegisterFile MyRegisterFile(0xFFFFFFFF, 0); + inline bool isInt16(target_intptr_t v) { @@ -2061,12 +2065,8 @@ class MyArchitecture: public Assembler::Architecture { return 0; } - virtual uint32_t generalRegisterMask() { - return 0xFFFFFFFF; - } - - virtual uint32_t floatRegisterMask() { - return 0; + virtual const RegisterFile* registerFile() { + return &MyRegisterFile; } virtual int scratch() { diff --git a/src/codegen/regalloc.cpp b/src/codegen/regalloc.cpp new file mode 100644 index 0000000000..bc8abf926b --- /dev/null +++ b/src/codegen/regalloc.cpp @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2012, 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 "codegen/regalloc.h" + +namespace avian { +namespace codegen { +namespace regalloc { + +RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile): + a(a), + registerFile(registerFile) +{ } + +} // namespace regalloc +} // namespace codegen +} // namespace avian \ No newline at end of file diff --git a/src/codegen/regalloc.h b/src/codegen/regalloc.h new file mode 100644 index 0000000000..83fbd878f3 --- /dev/null +++ b/src/codegen/regalloc.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_REGALLOC_H +#define AVIAN_CODEGEN_REGALLOC_H + +#include "common.h" + +#include "codegen/registers.h" + +class Aborter; + +namespace avian { +namespace codegen { +namespace regalloc { + +class RegisterAllocator { +public: + Aborter* a; + const RegisterFile* registerFile; + + RegisterAllocator(Aborter* a, const RegisterFile* registerFile); + +}; + +} // namespace regalloc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_REGALLOC_H \ No newline at end of file diff --git a/src/codegen/registers.cpp b/src/codegen/registers.cpp new file mode 100644 index 0000000000..6e8dea822a --- /dev/null +++ b/src/codegen/registers.cpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2012, 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 "codegen/registers.h" + +namespace avian { +namespace codegen { + +unsigned +RegisterMask::maskStart(uint32_t mask) +{ + for (int i = 0; i <= 31; ++i) { + if (mask & (1 << i)) return i; + } + return 32; +} + +unsigned +RegisterMask::maskLimit(uint32_t mask) +{ + for (int i = 31; i >= 0; --i) { + if (mask & (1 << i)) return i + 1; + } + return 0; +} + +} // namespace codegen +} // namespace avian diff --git a/src/codegen/registers.h b/src/codegen/registers.h new file mode 100644 index 0000000000..317bb2215a --- /dev/null +++ b/src/codegen/registers.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_REGISTERS_H +#define AVIAN_CODEGEN_REGISTERS_H + +#include "common.h" + +namespace avian { +namespace codegen { + +class RegisterMask { +public: + uint32_t mask; + uint8_t start; + uint8_t limit; + + static unsigned maskStart(uint32_t mask); + static unsigned maskLimit(uint32_t mask); + + inline RegisterMask(uint32_t mask): + mask(mask), + start(maskStart(mask)), + limit(maskLimit(mask)) + { } +}; + +class RegisterFile { +public: + RegisterMask allRegisters; + RegisterMask generalRegisters; + RegisterMask floatRegisters; + + inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask): + allRegisters(generalRegisterMask | floatRegisterMask), + generalRegisters(generalRegisterMask), + floatRegisters(floatRegisterMask) + { } +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_REGISTERS_H \ No newline at end of file diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 633dd49486..5e3fa6aa3c 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -13,6 +13,7 @@ #include "alloc-vector.h" #include "codegen/assembler.h" +#include "codegen/registers.h" #include "util/runtime-array.h" #include "util/abort.h" @@ -72,6 +73,8 @@ const unsigned GeneralRegisterMask const unsigned FloatRegisterMask = TargetBytesPerWord == 4 ? 0x00ff0000 : 0xffff0000; +const RegisterFile MyRegisterFile(GeneralRegisterMask, FloatRegisterMask); + const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1); const int LongJumpRegister = r10; @@ -2714,7 +2717,8 @@ populateTables(ArchitectureContext* c) class MyArchitecture: public Assembler::Architecture { public: MyArchitecture(System* system, bool useNativeFeatures): - c(system, useNativeFeatures), referenceCount(0) + c(system, useNativeFeatures), + referenceCount(0) { populateTables(&c); } @@ -2726,13 +2730,9 @@ class MyArchitecture: public Assembler::Architecture { return 0; } } - - virtual uint32_t generalRegisterMask() { - return GeneralRegisterMask; - } - - virtual uint32_t floatRegisterMask() { - return useSSE(&c) ? FloatRegisterMask : 0; + + virtual const RegisterFile* registerFile() { + return &MyRegisterFile; } virtual int scratch() { From 740886d58e5dcac8cd2d2787eaed17fde00a0dda Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 12:11:47 -0700 Subject: [PATCH 216/378] begin splitting up compiler.cpp --- makefile | 4 +- src/codegen/compiler.cpp | 412 ++++-------------------------- src/codegen/compiler/context.cpp | 68 +++++ src/codegen/compiler/context.h | 84 ++++++ src/codegen/compiler/resource.cpp | 152 +++++++++++ src/codegen/compiler/resource.h | 79 ++++++ src/codegen/compiler/value.h | 49 ++++ 7 files changed, 487 insertions(+), 361 deletions(-) create mode 100644 src/codegen/compiler/context.cpp create mode 100644 src/codegen/compiler/context.h create mode 100644 src/codegen/compiler/resource.cpp create mode 100644 src/codegen/compiler/resource.h create mode 100644 src/codegen/compiler/value.h diff --git a/makefile b/makefile index 4ff3aef558..e84d022f57 100755 --- a/makefile +++ b/makefile @@ -923,7 +923,7 @@ generated-code = \ $(build)/type-name-initializations.cpp \ $(build)/type-maps.cpp -vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) +vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) $(wildcard $(src)/codegen/compiler/*.h) vm-sources = \ $(src)/$(system).cpp \ @@ -954,6 +954,8 @@ ifeq ($(process),compile) vm-sources += \ $(src)/codegen/compiler.cpp \ $(src)/codegen/regalloc.cpp \ + $(src)/codegen/compiler/context.cpp \ + $(src)/codegen/compiler/resource.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 768b91748d..1f27b5749e 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -16,12 +16,15 @@ #include "codegen/assembler.h" #include "codegen/regalloc.h" +#include "codegen/compiler/context.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/value.h" + using namespace vm; -using namespace avian::codegen; -namespace { - -namespace local { +namespace avian { +namespace codegen { +namespace compiler { const bool DebugAppend = false; const bool DebugCompile = false; @@ -33,9 +36,6 @@ const bool DebugSites = false; const bool DebugMoves = false; const bool DebugBuddies = false; -const int AnyFrameIndex = -2; -const int NoFrameIndex = -1; - const unsigned StealRegisterReserveCount = 2; // this should be equal to the largest number of registers used by a @@ -48,8 +48,6 @@ const unsigned ConstantCopyCost = 3; const unsigned MemoryCopyCost = 4; const unsigned CopyPenalty = 10; -class Context; -class Value; class Stack; class Site; class ConstantSite; @@ -79,8 +77,6 @@ apply(Context* c, lir::TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); -inline Aborter* getAborter(Context* c); - class Cell { public: Cell(Cell* next, void* value): next(next), value(value) { } @@ -221,58 +217,6 @@ class LogicalInstruction { int index; }; -class Resource { - public: - Resource(bool reserved = false): - value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0), - referenceCount(0), reserved(reserved) - { } - - virtual void freeze(Context*, Value*) = 0; - - virtual void thaw(Context*, Value*) = 0; - - virtual unsigned toString(Context*, char*, unsigned) = 0; - - Value* value; - Site* site; - Resource* previousAcquired; - Resource* nextAcquired; - uint8_t freezeCount; - uint8_t referenceCount; - bool reserved; -}; - -class RegisterResource: public Resource { - public: - RegisterResource(bool reserved): - Resource(reserved) - { } - - virtual void freeze(Context*, Value*); - - virtual void thaw(Context*, Value*); - - virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize) { - return vm::snprintf(buffer, bufferSize, "register %d", index(c)); - } - - virtual unsigned index(Context*); -}; - -class FrameResource: public Resource { - public: - virtual void freeze(Context*, Value*); - - virtual void thaw(Context*, Value*); - - virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize) { - return vm::snprintf(buffer, bufferSize, "frame %d", index(c)); - } - - virtual unsigned index(Context*); -}; - class ConstantPoolNode { public: ConstantPoolNode(Promise* promise): promise(promise), next(0) { } @@ -321,124 +265,6 @@ intersect(const SiteMask& a, const SiteMask& b) intersectFrameIndexes(a.frameIndex, b.frameIndex)); } -class Value: public Compiler::Operand { - public: - Value(Site* site, Site* target, lir::ValueType type): - reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this), - nextWord(this), home(NoFrameIndex), type(type), wordIndex(0) - { } - - Read* reads; - Read* lastRead; - Site* sites; - Site* source; - Site* target; - Value* buddy; - Value* nextWord; - int16_t home; - lir::ValueType type; - uint8_t wordIndex; -}; - -class Context { - public: - Context(System* system, Assembler* assembler, Zone* zone, - Compiler::Client* client): - system(system), - assembler(assembler), - arch(assembler->arch()), - zone(zone), - client(client), - stack(0), - locals(0), - saved(0), - predecessor(0), - logicalCode(0), - regFile(arch->registerFile()), - regAlloc(system, arch->registerFile()), - registerResources - (static_cast - (zone->allocate(sizeof(RegisterResource) * regFile->allRegisters.limit))), - frameResources(0), - acquiredResources(0), - firstConstant(0), - lastConstant(0), - machineCode(0), - firstEvent(0), - lastEvent(0), - forkState(0), - subroutine(0), - firstBlock(0), - logicalIp(-1), - constantCount(0), - logicalCodeLength(0), - parameterFootprint(0), - localFootprint(0), - machineCodeSize(0), - alignedFrameSize(0), - availableGeneralRegisterCount(regFile->generalRegisters.limit - regFile->generalRegisters.start) - { - for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) { - new (registerResources + i) RegisterResource(arch->reserved(i)); - - if (registerResources[i].reserved) { - -- availableGeneralRegisterCount; - } - } - for (unsigned i = regFile->floatRegisters.start; i < regFile->floatRegisters.limit; ++i) { - new (registerResources + i) RegisterResource(arch->reserved(i)); - } - } - - System* system; - Assembler* assembler; - Assembler::Architecture* arch; - Zone* zone; - Compiler::Client* client; - Stack* stack; - Local* locals; - Cell* saved; - Event* predecessor; - LogicalInstruction** logicalCode; - const RegisterFile* regFile; - regalloc::RegisterAllocator regAlloc; - RegisterResource* registerResources; - FrameResource* frameResources; - Resource* acquiredResources; - ConstantPoolNode* firstConstant; - ConstantPoolNode* lastConstant; - uint8_t* machineCode; - Event* firstEvent; - Event* lastEvent; - ForkState* forkState; - MySubroutine* subroutine; - Block* firstBlock; - int logicalIp; - unsigned constantCount; - unsigned logicalCodeLength; - unsigned parameterFootprint; - unsigned localFootprint; - unsigned machineCodeSize; - unsigned alignedFrameSize; - unsigned availableGeneralRegisterCount; -}; - -inline Aborter* getAborter(Context* c) { - return c->system; -} - -unsigned -RegisterResource::index(Context* c) -{ - return this - c->registerResources; -} - -unsigned -FrameResource::index(Context* c) -{ - return this - c->frameResources; -} - class PoolPromise: public Promise { public: PoolPromise(Context* c, int key): c(c), key(key) { } @@ -1093,135 +919,6 @@ addBuddy(Value* original, Value* buddy) } } -void -decrementAvailableGeneralRegisterCount(Context* c) -{ - assert(c, c->availableGeneralRegisterCount); - -- c->availableGeneralRegisterCount; - - if (DebugResources) { - fprintf(stderr, "%d registers available\n", - c->availableGeneralRegisterCount); - } -} - -void -incrementAvailableGeneralRegisterCount(Context* c) -{ - ++ c->availableGeneralRegisterCount; - - if (DebugResources) { - fprintf(stderr, "%d registers available\n", - c->availableGeneralRegisterCount); - } -} - -void -increment(Context* c, RegisterResource* r) -{ - if (not r->reserved) { - if (DebugResources) { - char buffer[256]; r->toString(c, buffer, 256); - fprintf(stderr, "increment %s to %d\n", buffer, r->referenceCount + 1); - } - - ++ r->referenceCount; - - if (r->referenceCount == 1 - and ((1 << r->index(c)) & c->regFile->generalRegisters.mask)) - { - decrementAvailableGeneralRegisterCount(c); - } - } -} - -void -decrement(Context* c, RegisterResource* r) -{ - if (not r->reserved) { - if (DebugResources) { - char buffer[256]; r->toString(c, buffer, 256); - fprintf(stderr, "decrement %s to %d\n", buffer, r->referenceCount - 1); - } - - assert(c, r->referenceCount > 0); - - -- r->referenceCount; - - if (r->referenceCount == 0 - and ((1 << r->index(c)) & c->regFile->generalRegisters.mask)) - { - incrementAvailableGeneralRegisterCount(c); - } - } -} - -void -freezeResource(Context* c, Resource* r, Value* v) -{ - if (DebugResources) { - char buffer[256]; r->toString(c, buffer, 256); - fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1); - } - - ++ r->freezeCount; -} - -void -RegisterResource::freeze(Context* c, Value* v) -{ - if (not reserved) { - freezeResource(c, this, v); - - if (freezeCount == 1 - and ((1 << index(c)) & c->regFile->generalRegisters.mask)) - { - decrementAvailableGeneralRegisterCount(c); - } - } -} - -void -FrameResource::freeze(Context* c, Value* v) -{ - freezeResource(c, this, v); -} - -void -thawResource(Context* c, Resource* r, Value* v) -{ - if (not r->reserved) { - if (DebugResources) { - char buffer[256]; r->toString(c, buffer, 256); - fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1); - } - - assert(c, r->freezeCount); - - -- r->freezeCount; - } -} - -void -RegisterResource::thaw(Context* c, Value* v) -{ - if (not reserved) { - thawResource(c, this, v); - - if (freezeCount == 0 - and ((1 << index(c)) & c->regFile->generalRegisters.mask)) - { - incrementAvailableGeneralRegisterCount(c); - } - } -} - -void -FrameResource::thaw(Context* c, Value* v) -{ - thawResource(c, this, v); -} - class Target { public: static const unsigned MinimumRegisterCost = 0; @@ -1796,7 +1493,7 @@ class RegisterSite: public Site { } RegisterResource* resource = c->registerResources + target.index; - local::acquire(c, resource, v, this); + compiler::acquire(c, resource, v, this); number = target.index; } @@ -1804,7 +1501,7 @@ class RegisterSite: public Site { virtual void release(Context* c, Value* v) { assert(c, number != lir::NoRegister); - local::release(c, c->registerResources + number, v, this); + compiler::release(c, c->registerResources + number, v, this); } virtual void freeze(Context* c, Value* v) { @@ -2020,9 +1717,9 @@ class MemorySite: public Site { } virtual void acquire(Context* c, Value* v) { - increment(c, c->registerResources + base); + c->registerResources[base].increment(c); if (index != lir::NoRegister) { - increment(c, c->registerResources + index); + c->registerResources[index].increment(c); } if (base == c->arch->stack()) { @@ -2030,7 +1727,7 @@ class MemorySite: public Site { assert (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); - local::acquire + compiler::acquire (c, c->frameResources + offsetToFrameIndex(c, offset), v, this); } @@ -2043,13 +1740,13 @@ class MemorySite: public Site { assert (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); - local::release + compiler::release (c, c->frameResources + offsetToFrameIndex(c, offset), v, this); } - decrement(c, c->registerResources + base); + c->registerResources[base].decrement(c); if (index != lir::NoRegister) { - decrement(c, c->registerResources + index); + c->registerResources[index].decrement(c); } acquired = false; @@ -2059,9 +1756,9 @@ class MemorySite: public Site { if (base == c->arch->stack()) { c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v); } else { - increment(c, c->registerResources + base); + c->registerResources[base].increment(c); if (index != lir::NoRegister) { - increment(c, c->registerResources + index); + c->registerResources[index].increment(c); } } } @@ -2070,9 +1767,9 @@ class MemorySite: public Site { if (base == c->arch->stack()) { c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v); } else { - decrement(c, c->registerResources + base); + c->registerResources[base].decrement(c); if (index != lir::NoRegister) { - decrement(c, c->registerResources + index); + c->registerResources[index].decrement(c); } } } @@ -2245,7 +1942,7 @@ class SingleRead: public Read { { } virtual bool intersect(SiteMask* mask, unsigned) { - *mask = local::intersect(*mask, this->mask); + *mask = compiler::intersect(*mask, this->mask); return true; } @@ -3082,11 +2779,11 @@ saveLocals(Context* c, Event* e) if (local->value) { if (DebugReads) { fprintf(stderr, "local save read %p at %d of %d\n", - local->value, local::frameIndex(c, li), totalFrameSize(c)); + local->value, compiler::frameIndex(c, li), totalFrameSize(c)); } addRead(c, e, local->value, SiteMask - (1 << lir::MemoryOperand, 0, local::frameIndex(c, li))); + (1 << lir::MemoryOperand, 0, compiler::frameIndex(c, li))); } } } @@ -3266,7 +2963,7 @@ class CallEvent: public Event { while (stack) { if (stack->value) { - unsigned logicalIndex = local::frameIndex + unsigned logicalIndex = compiler::frameIndex (c, stack->index + c->localFootprint); if (DebugReads) { @@ -4376,13 +4073,13 @@ appendCombine(Context* c, lir::TernaryOperation type, unsigned stackSize = ceilingDivide(secondSize, TargetBytesPerWord) + ceilingDivide(firstSize, TargetBytesPerWord); - local::push(c, ceilingDivide(secondSize, TargetBytesPerWord), second); - local::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); + compiler::push(c, ceilingDivide(secondSize, TargetBytesPerWord), second); + compiler::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); if (threadParameter) { ++ stackSize; - local::push(c, 1, register_(c, c->arch->thread())); + compiler::push(c, 1, register_(c, c->arch->thread())); } Stack* argumentStack = c->stack; @@ -4499,7 +4196,7 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, if (thunk) { Stack* oldStack = c->stack; - local::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); + compiler::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -4848,8 +4545,8 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first assert(c, not threadParameter); - local::push(c, ceilingDivide(size, TargetBytesPerWord), second); - local::push(c, ceilingDivide(size, TargetBytesPerWord), first); + compiler::push(c, ceilingDivide(size, TargetBytesPerWord), second); + compiler::push(c, ceilingDivide(size, TargetBytesPerWord), first); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -5209,7 +4906,7 @@ append(Context* c, Event* e) e->logicalInstruction->index); } - Link* link = local::link + Link* link = compiler::link (c, p, e->predecessors, e, p->successors, c->forkState); e->predecessors = link; p->successors = link; @@ -5840,7 +5537,7 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) block->assemblerBlock = a->endBlock(e->next != 0); if (e->next) { - block = local::block(c, e->next); + block = compiler::block(c, e->next); } } } @@ -5969,12 +5666,12 @@ class Client: public Assembler::Client { int r = pickRegisterTarget(c, 0, mask, &cost); expect(c, cost < Target::Impossible); save(r); - increment(c, c->registerResources + r); + c->registerResources[r].increment(c); return r; } virtual void releaseTemporary(int r) { - decrement(c, c->registerResources + r); + c->registerResources[r].decrement(c); } virtual void save(int r) { @@ -6002,13 +5699,13 @@ class MyCompiler: public Compiler { } virtual State* saveState() { - State* s = local::saveState(&c); + State* s = compiler::saveState(&c); restoreState(s); return s; } virtual void restoreState(State* state) { - local::restoreState(&c, static_cast(state)); + compiler::restoreState(&c, static_cast(state)); } virtual Subroutine* startSubroutine() { @@ -6018,7 +5715,7 @@ class MyCompiler: public Compiler { virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) { appendSaveLocals(&c); appendJump(&c, lir::Jump, static_cast(address), false, true); - static_cast(subroutine)->forkState = local::saveState(&c); + static_cast(subroutine)->forkState = compiler::saveState(&c); } virtual void linkSubroutine(Subroutine* subroutine) { @@ -6085,7 +5782,7 @@ class MyCompiler: public Compiler { p->stackAfter = c.stack; p->localsAfter = c.locals; - Link* link = local::link + Link* link = compiler::link (&c, p, e->predecessors, e, p->successors, c.forkState); e->predecessors = link; p->successors = link; @@ -6181,12 +5878,12 @@ class MyCompiler: public Compiler { } virtual Operand* promiseConstant(Promise* value, Compiler::OperandType type) { - return local::value - (&c, valueType(&c, type), local::constantSite(&c, value)); + return compiler::value + (&c, valueType(&c, type), compiler::constantSite(&c, value)); } virtual Operand* address(Promise* address) { - return value(&c, lir::ValueGeneral, local::addressSite(&c, address)); + return value(&c, lir::ValueGeneral, compiler::addressSite(&c, address)); } virtual Operand* memory(Operand* base, @@ -6204,7 +5901,7 @@ class MyCompiler: public Compiler { } virtual Operand* register_(int number) { - return local::register_(&c, number); + return compiler::register_(&c, number); } Promise* machineIp() { @@ -6215,14 +5912,14 @@ class MyCompiler: public Compiler { assert(&c, footprint == 1); Value* v = value(&c, lir::ValueGeneral); - Stack* s = local::stack(&c, v, c.stack); + Stack* s = compiler::stack(&c, v, c.stack); v->home = frameIndex(&c, s->index + c.localFootprint); c.stack = s; } virtual void push(unsigned footprint, Operand* value) { - local::push(&c, footprint, static_cast(value)); + compiler::push(&c, footprint, static_cast(value)); } virtual void save(unsigned footprint, Operand* value) { @@ -6236,7 +5933,7 @@ class MyCompiler: public Compiler { } virtual Operand* pop(unsigned footprint) { - return local::pop(&c, footprint); + return compiler::pop(&c, footprint); } virtual void pushed() { @@ -6245,7 +5942,7 @@ class MyCompiler: public Compiler { (&c, v, frameIndex (&c, (c.stack ? c.stack->index : 0) + c.localFootprint)); - Stack* s = local::stack(&c, v, c.stack); + Stack* s = compiler::stack(&c, v, c.stack); v->home = frameIndex(&c, s->index + c.localFootprint); c.stack = s; } @@ -6340,7 +6037,7 @@ class MyCompiler: public Compiler { Stack* argumentStack = c.stack; for (int i = index - 1; i >= 0; --i) { - argumentStack = local::stack + argumentStack = compiler::stack (&c, RUNTIME_ARRAY_BODY(arguments)[i], argumentStack); } @@ -6431,11 +6128,11 @@ class MyCompiler: public Compiler { } virtual void storeLocal(unsigned footprint, Operand* src, unsigned index) { - local::storeLocal(&c, footprint, static_cast(src), index, true); + compiler::storeLocal(&c, footprint, static_cast(src), index, true); } virtual Operand* loadLocal(unsigned footprint, unsigned index) { - return local::loadLocal(&c, footprint, index); + return compiler::loadLocal(&c, footprint, index); } virtual void saveLocals() { @@ -6872,7 +6569,7 @@ class MyCompiler: public Compiler { virtual void compile(uintptr_t stackOverflowHandler, unsigned stackLimitOffset) { - local::compile(&c, stackOverflowHandler, stackLimitOffset); + compiler::compile(&c, stackOverflowHandler, stackLimitOffset); } virtual unsigned resolve(uint8_t* dst) { @@ -6934,21 +6631,16 @@ class MyCompiler: public Compiler { } Context c; - local::Client client; + compiler::Client client; }; -} // namespace local - -} // namespace - -namespace avian { -namespace codegen { +} // namespace compiler Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, Compiler::Client* client) { - return new(zone) local::MyCompiler(system, assembler, zone, client); + return new(zone) compiler::MyCompiler(system, assembler, zone, client); } } // namespace codegen diff --git a/src/codegen/compiler/context.cpp b/src/codegen/compiler/context.cpp new file mode 100644 index 0000000000..dd1f129bad --- /dev/null +++ b/src/codegen/compiler/context.cpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2008-2012, 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 "codegen/compiler/context.h" +#include "codegen/compiler/resource.h" + +namespace avian { +namespace codegen { +namespace compiler { + +Context::Context(vm::System* system, Assembler* assembler, vm::Zone* zone, + Compiler::Client* client): + system(system), + assembler(assembler), + arch(assembler->arch()), + zone(zone), + client(client), + stack(0), + locals(0), + saved(0), + predecessor(0), + logicalCode(0), + regFile(arch->registerFile()), + regAlloc(system, arch->registerFile()), + registerResources + (static_cast + (zone->allocate(sizeof(RegisterResource) * regFile->allRegisters.limit))), + frameResources(0), + acquiredResources(0), + firstConstant(0), + lastConstant(0), + machineCode(0), + firstEvent(0), + lastEvent(0), + forkState(0), + subroutine(0), + firstBlock(0), + logicalIp(-1), + constantCount(0), + logicalCodeLength(0), + parameterFootprint(0), + localFootprint(0), + machineCodeSize(0), + alignedFrameSize(0), + availableGeneralRegisterCount(regFile->generalRegisters.limit - regFile->generalRegisters.start) +{ + for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) { + new (registerResources + i) RegisterResource(arch->reserved(i)); + + if (registerResources[i].reserved) { + -- availableGeneralRegisterCount; + } + } + for (unsigned i = regFile->floatRegisters.start; i < regFile->floatRegisters.limit; ++i) { + new (registerResources + i) RegisterResource(arch->reserved(i)); + } +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h new file mode 100644 index 0000000000..df6382e68f --- /dev/null +++ b/src/codegen/compiler/context.h @@ -0,0 +1,84 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_CONTEXT_H +#define AVIAN_CODEGEN_COMPILER_CONTEXT_H + +#include "codegen/assembler.h" +#include "codegen/regalloc.h" +#include "codegen/compiler.h" + +namespace avian { +namespace codegen { +namespace compiler { + +class Stack; +class Local; +class Cell; +class Event; +class LogicalInstruction; + +class Resource; +class RegisterResource; +class FrameResource; + +class ConstantPoolNode; + +class ForkState; +class MySubroutine; +class Block; + +class Context { + public: + Context(vm::System* system, Assembler* assembler, vm::Zone* zone, + Compiler::Client* client); + + vm::System* system; + Assembler* assembler; + Assembler::Architecture* arch; + vm::Zone* zone; + Compiler::Client* client; + Stack* stack; + Local* locals; + Cell* saved; + Event* predecessor; + LogicalInstruction** logicalCode; + const RegisterFile* regFile; + regalloc::RegisterAllocator regAlloc; + RegisterResource* registerResources; + FrameResource* frameResources; + Resource* acquiredResources; + ConstantPoolNode* firstConstant; + ConstantPoolNode* lastConstant; + uint8_t* machineCode; + Event* firstEvent; + Event* lastEvent; + ForkState* forkState; + MySubroutine* subroutine; + Block* firstBlock; + int logicalIp; + unsigned constantCount; + unsigned logicalCodeLength; + unsigned parameterFootprint; + unsigned localFootprint; + unsigned machineCodeSize; + unsigned alignedFrameSize; + unsigned availableGeneralRegisterCount; +}; + +inline Aborter* getAborter(Context* c) { + return c->system; +} + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_CONTEXT_H diff --git a/src/codegen/compiler/resource.cpp b/src/codegen/compiler/resource.cpp new file mode 100644 index 0000000000..0480c6e3d7 --- /dev/null +++ b/src/codegen/compiler/resource.cpp @@ -0,0 +1,152 @@ +/* Copyright (c) 2008-2012, 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 "codegen/compiler/context.h" +#include "codegen/compiler/resource.h" + +namespace avian { +namespace codegen { +namespace compiler { + +const bool DebugResources = false; + +void decrementAvailableGeneralRegisterCount(Context* c) { + assert(c, c->availableGeneralRegisterCount); + -- c->availableGeneralRegisterCount; + + if (DebugResources) { + fprintf(stderr, "%d registers available\n", + c->availableGeneralRegisterCount); + } +} + +void incrementAvailableGeneralRegisterCount(Context* c) { + ++ c->availableGeneralRegisterCount; + + if (DebugResources) { + fprintf(stderr, "%d registers available\n", + c->availableGeneralRegisterCount); + } +} + +void freezeResource(Context* c, Resource* r, Value* v) { + if (DebugResources) { + char buffer[256]; r->toString(c, buffer, 256); + fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1); + } + + ++ r->freezeCount; +} + +void thawResource(Context* c, Resource* r, Value* v) { + if (not r->reserved) { + if (DebugResources) { + char buffer[256]; r->toString(c, buffer, 256); + fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1); + } + + assert(c, r->freezeCount); + + -- r->freezeCount; + } +} + + + +void RegisterResource::freeze(Context* c, Value* v) { + if (not reserved) { + freezeResource(c, this, v); + + if (freezeCount == 1 + and ((1 << index(c)) & c->regFile->generalRegisters.mask)) + { + decrementAvailableGeneralRegisterCount(c); + } + } +} + +void RegisterResource::thaw(Context* c, Value* v) { + if (not reserved) { + thawResource(c, this, v); + + if (freezeCount == 0 + and ((1 << index(c)) & c->regFile->generalRegisters.mask)) + { + incrementAvailableGeneralRegisterCount(c); + } + } +} + +unsigned RegisterResource::toString(Context* c, char* buffer, unsigned bufferSize) { + return vm::snprintf(buffer, bufferSize, "register %d", index(c)); +} + +unsigned RegisterResource::index(Context* c) { + return this - c->registerResources; +} + +void RegisterResource::increment(Context* c) { + if (not this->reserved) { + if (DebugResources) { + char buffer[256]; this->toString(c, buffer, 256); + fprintf(stderr, "increment %s to %d\n", buffer, this->referenceCount + 1); + } + + ++ this->referenceCount; + + if (this->referenceCount == 1 + and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) + { + decrementAvailableGeneralRegisterCount(c); + } + } +} + +void RegisterResource::decrement(Context* c) { + if (not this->reserved) { + if (DebugResources) { + char buffer[256]; this->toString(c, buffer, 256); + fprintf(stderr, "decrement %s to %d\n", buffer, this->referenceCount - 1); + } + + assert(c, this->referenceCount > 0); + + -- this->referenceCount; + + if (this->referenceCount == 0 + and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) + { + incrementAvailableGeneralRegisterCount(c); + } + } +} + + + +void FrameResource::freeze(Context* c, Value* v) { + freezeResource(c, this, v); +} + +void FrameResource::thaw(Context* c, Value* v) { + thawResource(c, this, v); +} + +unsigned FrameResource::toString(Context* c, char* buffer, unsigned bufferSize) { + return vm::snprintf(buffer, bufferSize, "frame %d", index(c)); +} + +unsigned FrameResource::index(Context* c) { + return this - c->frameResources; +} + + +} // namespace compiler +} // namespace codegen +} // namespace avian \ No newline at end of file diff --git a/src/codegen/compiler/resource.h b/src/codegen/compiler/resource.h new file mode 100644 index 0000000000..b9d469bbf3 --- /dev/null +++ b/src/codegen/compiler/resource.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_RESOURCE_H +#define AVIAN_CODEGEN_COMPILER_RESOURCE_H + +#include "codegen/compiler/context.h" + +namespace avian { +namespace codegen { +namespace compiler { + +class Value; +class Site; + +class Resource { + public: + Resource(bool reserved = false): + value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0), + referenceCount(0), reserved(reserved) + { } + + virtual void freeze(Context*, Value*) = 0; + + virtual void thaw(Context*, Value*) = 0; + + virtual unsigned toString(Context*, char*, unsigned) = 0; + + Value* value; + Site* site; + Resource* previousAcquired; + Resource* nextAcquired; + uint8_t freezeCount; + uint8_t referenceCount; + bool reserved; +}; + +class RegisterResource: public Resource { + public: + RegisterResource(bool reserved): + Resource(reserved) + { } + + virtual void freeze(Context*, Value*); + + virtual void thaw(Context*, Value*); + + virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize); + + virtual unsigned index(Context*); + + void increment(Context*); + + void decrement(Context*); +}; + +class FrameResource: public Resource { + public: + virtual void freeze(Context*, Value*); + + virtual void thaw(Context*, Value*); + + virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize); + + virtual unsigned index(Context*); +}; + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_RESOURCE_H diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h new file mode 100644 index 0000000000..a2e8040db6 --- /dev/null +++ b/src/codegen/compiler/value.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_VALUE_H +#define AVIAN_CODEGEN_COMPILER_VALUE_H + +#include "codegen/lir.h" + +namespace avian { +namespace codegen { +namespace compiler { + +class Read; +class Site; + +const int AnyFrameIndex = -2; +const int NoFrameIndex = -1; + +class Value: public Compiler::Operand { + public: + Value(Site* site, Site* target, lir::ValueType type): + reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this), + nextWord(this), home(NoFrameIndex), type(type), wordIndex(0) + { } + + Read* reads; + Read* lastRead; + Site* sites; + Site* source; + Site* target; + Value* buddy; + Value* nextWord; + int16_t home; + lir::ValueType type; + uint8_t wordIndex; +}; + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_VALUE_H \ No newline at end of file From 952cad2360d9b7e5e6e65c1c41067b7ffd9e85f5 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 12:56:56 -0700 Subject: [PATCH 217/378] move site out of compiler.cpp --- makefile | 1 + src/codegen/compiler.cpp | 244 +----------------------------- src/codegen/compiler/resource.cpp | 8 + src/codegen/compiler/resource.h | 12 +- src/codegen/compiler/site.cpp | 102 +++++++++++++ src/codegen/compiler/site.h | 190 +++++++++++++++++++++++ 6 files changed, 308 insertions(+), 249 deletions(-) create mode 100644 src/codegen/compiler/site.cpp create mode 100644 src/codegen/compiler/site.h diff --git a/makefile b/makefile index e84d022f57..a408804b29 100755 --- a/makefile +++ b/makefile @@ -956,6 +956,7 @@ ifeq ($(process),compile) $(src)/codegen/regalloc.cpp \ $(src)/codegen/compiler/context.cpp \ $(src)/codegen/compiler/resource.cpp \ + $(src)/codegen/compiler/site.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 1f27b5749e..d07caa4e7d 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -19,6 +19,7 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/resource.h" #include "codegen/compiler/value.h" +#include "codegen/compiler/site.h" using namespace vm; @@ -42,12 +43,6 @@ const unsigned StealRegisterReserveCount = 2; // compare instruction: const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4); -const unsigned RegisterCopyCost = 1; -const unsigned AddressCopyCost = 2; -const unsigned ConstantCopyCost = 3; -const unsigned MemoryCopyCost = 4; -const unsigned CopyPenalty = 10; - class Stack; class Site; class ConstantSite; @@ -90,70 +85,6 @@ class Local { Value* value; }; -class SiteMask { - public: - SiteMask(): typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) { } - - SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex): - typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex) - { } - - uint8_t typeMask; - uint32_t registerMask; - int frameIndex; -}; - -class Site { - public: - Site(): next(0) { } - - virtual Site* readTarget(Context*, Read*) { return this; } - - virtual unsigned toString(Context*, char*, unsigned) = 0; - - virtual unsigned copyCost(Context*, Site*) = 0; - - virtual bool match(Context*, const SiteMask&) = 0; - - virtual bool loneMatch(Context*, const SiteMask&) = 0; - - virtual bool matchNextWord(Context*, Site*, unsigned) = 0; - - virtual void acquire(Context*, Value*) { } - - virtual void release(Context*, Value*) { } - - virtual void freeze(Context*, Value*) { } - - virtual void thaw(Context*, Value*) { } - - virtual bool frozen(Context*) { return false; } - - virtual lir::OperandType type(Context*) = 0; - - virtual void asAssemblerOperand(Context*, Site*, lir::Operand*) = 0; - - virtual Site* copy(Context*) = 0; - - virtual Site* copyLow(Context*) = 0; - - virtual Site* copyHigh(Context*) = 0; - - virtual Site* makeNextWord(Context*, unsigned) = 0; - - virtual SiteMask mask(Context*) = 0; - - virtual SiteMask nextWordMask(Context*, unsigned) = 0; - - virtual unsigned registerSize(Context*) { return TargetBytesPerWord; } - - virtual unsigned registerMask(Context*) { return 0; } - - virtual bool isVolatile(Context*) { return false; } - - Site* next; -}; - class Stack { public: Stack(unsigned index, Value* value, Stack* next): @@ -586,84 +517,6 @@ frameIndex(Context* c, FrameIterator::Element* element) return frameIndex(c, element->localIndex); } -class SiteIterator { - public: - SiteIterator(Context* c, Value* v, bool includeBuddies = true, - bool includeNextWord = true): - c(c), - originalValue(v), - currentValue(v), - includeBuddies(includeBuddies), - includeNextWord(includeNextWord), - pass(0), - next_(findNext(&(v->sites))), - previous(0) - { } - - Site** findNext(Site** p) { - while (true) { - if (*p) { - if (pass == 0 or (*p)->registerSize(c) > TargetBytesPerWord) { - return p; - } else { - p = &((*p)->next); - } - } else { - if (includeBuddies) { - Value* v = currentValue->buddy; - if (v != originalValue) { - currentValue = v; - p = &(v->sites); - continue; - } - } - - if (includeNextWord and pass == 0) { - Value* v = originalValue->nextWord; - if (v != originalValue) { - pass = 1; - originalValue = v; - currentValue = v; - p = &(v->sites); - continue; - } - } - - return 0; - } - } - } - - bool hasMore() { - if (previous) { - next_ = findNext(&((*previous)->next)); - previous = 0; - } - return next_ != 0; - } - - Site* next() { - previous = next_; - return *previous; - } - - void remove(Context* c) { - (*previous)->release(c, originalValue); - *previous = (*previous)->next; - next_ = findNext(previous); - previous = 0; - } - - Context* c; - Value* originalValue; - Value* currentValue; - bool includeBuddies; - bool includeNextWord; - uint8_t pass; - Site** next_; - Site** previous; -}; - bool hasSite(Context* c, Value* v) { @@ -1233,109 +1086,20 @@ acquire(Context* c, Resource* resource, Value* value, Site* site); void release(Context* c, Resource* resource, Value* value, Site* site); -ConstantSite* -constantSite(Context* c, Promise* value); - -ShiftMaskPromise* -shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) -{ +Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { return new(c->zone) ShiftMaskPromise(base, shift, mask); } -CombinedPromise* -combinedPromise(Context* c, Promise* low, Promise* high) -{ +Promise* combinedPromise(Context* c, Promise* low, Promise* high) { return new(c->zone) CombinedPromise(low, high); } -class ConstantSite: public Site { - public: - ConstantSite(Promise* value): value(value) { } - - virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { - if (value->resolved()) { - return vm::snprintf - (buffer, bufferSize, "constant %" LLD, value->value()); - } else { - return vm::snprintf(buffer, bufferSize, "constant unresolved"); - } - } - - virtual unsigned copyCost(Context*, Site* s) { - return (s == this ? 0 : ConstantCopyCost); - } - - virtual bool match(Context*, const SiteMask& mask) { - return mask.typeMask & (1 << lir::ConstantOperand); - } - - virtual bool loneMatch(Context*, const SiteMask&) { - return true; - } - - virtual bool matchNextWord(Context* c, Site* s, unsigned) { - return s->type(c) == lir::ConstantOperand; - } - - virtual lir::OperandType type(Context*) { - return lir::ConstantOperand; - } - - virtual void asAssemblerOperand(Context* c, Site* high, - lir::Operand* result) - { - Promise* v = value; - if (high != this) { - v = combinedPromise(c, value, static_cast(high)->value); - } - new (result) lir::Constant(v); - } - - virtual Site* copy(Context* c) { - return constantSite(c, value); - } - - virtual Site* copyLow(Context* c) { - return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF)); - } - - virtual Site* copyHigh(Context* c) { - return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF)); - } - - virtual Site* makeNextWord(Context* c, unsigned) { - abort(c); - } - - virtual SiteMask mask(Context*) { - return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); - } - - virtual SiteMask nextWordMask(Context*, unsigned) { - return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); - } - - Promise* value; -}; - -ConstantSite* -constantSite(Context* c, Promise* value) -{ - return new(c->zone) ConstantSite(value); -} - -ResolvedPromise* +Promise* resolved(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } -ConstantSite* -constantSite(Context* c, int64_t value) -{ - return constantSite(c, resolved(c, value)); -} - AddressSite* addressSite(Context* c, Promise* address); diff --git a/src/codegen/compiler/resource.cpp b/src/codegen/compiler/resource.cpp index 0480c6e3d7..1b549e0197 100644 --- a/src/codegen/compiler/resource.cpp +++ b/src/codegen/compiler/resource.cpp @@ -59,6 +59,14 @@ void thawResource(Context* c, Resource* r, Value* v) { } +Resource::Resource(bool reserved): + value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0), + referenceCount(0), reserved(reserved) +{ } + +RegisterResource::RegisterResource(bool reserved): + Resource(reserved) +{ } void RegisterResource::freeze(Context* c, Value* v) { if (not reserved) { diff --git a/src/codegen/compiler/resource.h b/src/codegen/compiler/resource.h index b9d469bbf3..004cbc34cc 100644 --- a/src/codegen/compiler/resource.h +++ b/src/codegen/compiler/resource.h @@ -11,21 +11,17 @@ #ifndef AVIAN_CODEGEN_COMPILER_RESOURCE_H #define AVIAN_CODEGEN_COMPILER_RESOURCE_H -#include "codegen/compiler/context.h" - namespace avian { namespace codegen { namespace compiler { +class Context; class Value; class Site; class Resource { public: - Resource(bool reserved = false): - value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0), - referenceCount(0), reserved(reserved) - { } + Resource(bool reserved = false); virtual void freeze(Context*, Value*) = 0; @@ -44,9 +40,7 @@ class Resource { class RegisterResource: public Resource { public: - RegisterResource(bool reserved): - Resource(reserved) - { } + RegisterResource(bool reserved); virtual void freeze(Context*, Value*); diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp new file mode 100644 index 0000000000..1e3dcff448 --- /dev/null +++ b/src/codegen/compiler/site.cpp @@ -0,0 +1,102 @@ +/* Copyright (c) 2008-2012, 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 "target.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/value.h" +#include "codegen/compiler/site.h" + +namespace avian { +namespace codegen { +namespace compiler { + + +ResolvedPromise* resolved(Context* c, int64_t value); + +SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies, + bool includeNextWord): + c(c), + originalValue(v), + currentValue(v), + includeBuddies(includeBuddies), + includeNextWord(includeNextWord), + pass(0), + next_(findNext(&(v->sites))), + previous(0) +{ } + +Site** SiteIterator::findNext(Site** p) { + while (true) { + if (*p) { + if (pass == 0 or (*p)->registerSize(c) > vm::TargetBytesPerWord) { + return p; + } else { + p = &((*p)->next); + } + } else { + if (includeBuddies) { + Value* v = currentValue->buddy; + if (v != originalValue) { + currentValue = v; + p = &(v->sites); + continue; + } + } + + if (includeNextWord and pass == 0) { + Value* v = originalValue->nextWord; + if (v != originalValue) { + pass = 1; + originalValue = v; + currentValue = v; + p = &(v->sites); + continue; + } + } + + return 0; + } + } +} + +bool SiteIterator::hasMore() { + if (previous) { + next_ = findNext(&((*previous)->next)); + previous = 0; + } + return next_ != 0; +} + +Site* SiteIterator::next() { + previous = next_; + return *previous; +} + +void SiteIterator::remove(Context* c) { + (*previous)->release(c, originalValue); + *previous = (*previous)->next; + next_ = findNext(previous); + previous = 0; +} + + + +Site* constantSite(Context* c, Promise* value) { + return new(c->zone) ConstantSite(value); +} + +Site* constantSite(Context* c, int64_t value) { + return constantSite(c, resolved(c, value)); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian \ No newline at end of file diff --git a/src/codegen/compiler/site.h b/src/codegen/compiler/site.h new file mode 100644 index 0000000000..aa66243b70 --- /dev/null +++ b/src/codegen/compiler/site.h @@ -0,0 +1,190 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_SITE_H +#define AVIAN_CODEGEN_COMPILER_SITE_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; + +const unsigned RegisterCopyCost = 1; +const unsigned AddressCopyCost = 2; +const unsigned ConstantCopyCost = 3; +const unsigned MemoryCopyCost = 4; +const unsigned CopyPenalty = 10; + +class SiteMask { + public: + SiteMask(): typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) { } + + SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex): + typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex) + { } + + uint8_t typeMask; + uint32_t registerMask; + int frameIndex; +}; + +class Site { + public: + Site(): next(0) { } + + virtual Site* readTarget(Context*, Read*) { return this; } + + virtual unsigned toString(Context*, char*, unsigned) = 0; + + virtual unsigned copyCost(Context*, Site*) = 0; + + virtual bool match(Context*, const SiteMask&) = 0; + + virtual bool loneMatch(Context*, const SiteMask&) = 0; + + virtual bool matchNextWord(Context*, Site*, unsigned) = 0; + + virtual void acquire(Context*, Value*) { } + + virtual void release(Context*, Value*) { } + + virtual void freeze(Context*, Value*) { } + + virtual void thaw(Context*, Value*) { } + + virtual bool frozen(Context*) { return false; } + + virtual lir::OperandType type(Context*) = 0; + + virtual void asAssemblerOperand(Context*, Site*, lir::Operand*) = 0; + + virtual Site* copy(Context*) = 0; + + virtual Site* copyLow(Context*) = 0; + + virtual Site* copyHigh(Context*) = 0; + + virtual Site* makeNextWord(Context*, unsigned) = 0; + + virtual SiteMask mask(Context*) = 0; + + virtual SiteMask nextWordMask(Context*, unsigned) = 0; + + virtual unsigned registerSize(Context*) { return vm::TargetBytesPerWord; } + + virtual unsigned registerMask(Context*) { return 0; } + + virtual bool isVolatile(Context*) { return false; } + + Site* next; +}; + +class SiteIterator { + public: + SiteIterator(Context* c, Value* v, bool includeBuddies = true, + bool includeNextWord = true); + + Site** findNext(Site** p); + bool hasMore(); + Site* next(); + void remove(Context* c); + + Context* c; + Value* originalValue; + Value* currentValue; + bool includeBuddies; + bool includeNextWord; + uint8_t pass; + Site** next_; + Site** previous; +}; + +Site* constantSite(Context* c, Promise* value); +Site* constantSite(Context* c, int64_t value); + +Promise* combinedPromise(Context* c, Promise* low, Promise* high); +Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask); + +class ConstantSite: public Site { + public: + ConstantSite(Promise* value): value(value) { } + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { + if (value->resolved()) { + return vm::snprintf + (buffer, bufferSize, "constant %" LLD, value->value()); + } else { + return vm::snprintf(buffer, bufferSize, "constant unresolved"); + } + } + + virtual unsigned copyCost(Context*, Site* s) { + return (s == this ? 0 : ConstantCopyCost); + } + + virtual bool match(Context*, const SiteMask& mask) { + return mask.typeMask & (1 << lir::ConstantOperand); + } + + virtual bool loneMatch(Context*, const SiteMask&) { + return true; + } + + virtual bool matchNextWord(Context* c, Site* s, unsigned) { + return s->type(c) == lir::ConstantOperand; + } + + virtual lir::OperandType type(Context*) { + return lir::ConstantOperand; + } + + virtual void asAssemblerOperand(Context* c, Site* high, + lir::Operand* result) + { + Promise* v = value; + if (high != this) { + v = combinedPromise(c, value, static_cast(high)->value); + } + new (result) lir::Constant(v); + } + + virtual Site* copy(Context* c) { + return constantSite(c, value); + } + + virtual Site* copyLow(Context* c) { + return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF)); + } + + virtual Site* copyHigh(Context* c) { + return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF)); + } + + virtual Site* makeNextWord(Context* c, unsigned) { + abort(c); + } + + virtual SiteMask mask(Context*) { + return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); + } + + virtual SiteMask nextWordMask(Context*, unsigned) { + return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); + } + + Promise* value; +}; + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_SITE_H From b0abc4e1e50b7c68768e68673e8f9634d314880a Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 16:49:46 -0700 Subject: [PATCH 218/378] further split up compiler.cpp --- makefile | 3 +- src/codegen/compiler.cpp | 705 +----------------------------- src/codegen/compiler/context.h | 5 +- src/codegen/compiler/read.h | 46 ++ src/codegen/compiler/regalloc.cpp | 301 +++++++++++++ src/codegen/compiler/regalloc.h | 106 +++++ src/codegen/compiler/resource.cpp | 66 +++ src/codegen/compiler/resource.h | 4 + src/codegen/compiler/site.cpp | 273 ++++++++++++ src/codegen/compiler/site.h | 57 +++ src/codegen/compiler/value.cpp | 43 ++ src/codegen/compiler/value.h | 13 +- src/codegen/regalloc.cpp | 24 - src/codegen/regalloc.h | 37 -- 14 files changed, 916 insertions(+), 767 deletions(-) create mode 100644 src/codegen/compiler/read.h create mode 100644 src/codegen/compiler/regalloc.cpp create mode 100644 src/codegen/compiler/regalloc.h create mode 100644 src/codegen/compiler/value.cpp delete mode 100644 src/codegen/regalloc.cpp delete mode 100644 src/codegen/regalloc.h diff --git a/makefile b/makefile index a408804b29..9f57682239 100755 --- a/makefile +++ b/makefile @@ -953,10 +953,11 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) ifeq ($(process),compile) vm-sources += \ $(src)/codegen/compiler.cpp \ - $(src)/codegen/regalloc.cpp \ $(src)/codegen/compiler/context.cpp \ $(src)/codegen/compiler/resource.cpp \ $(src)/codegen/compiler/site.cpp \ + $(src)/codegen/compiler/regalloc.cpp \ + $(src)/codegen/compiler/value.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index d07caa4e7d..7b63548c42 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -14,12 +14,13 @@ #include "codegen/compiler.h" #include "codegen/assembler.h" -#include "codegen/regalloc.h" +#include "codegen/compiler/regalloc.h" #include "codegen/compiler/context.h" #include "codegen/compiler/resource.h" #include "codegen/compiler/value.h" #include "codegen/compiler/site.h" +#include "codegen/compiler/read.h" using namespace vm; @@ -156,29 +157,6 @@ class ConstantPoolNode { ConstantPoolNode* next; }; -class Read { - public: - Read(): - value(0), event(0), eventNext(0) - { } - - virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0; - - virtual Value* high(Context* c) { abort(c); } - - virtual Value* successor() = 0; - - virtual bool valid() = 0; - - virtual void append(Context* c, Read* r) = 0; - - virtual Read* next(Context* c) = 0; - - Value* value; - Event* event; - Read* eventNext; -}; - int intersectFrameIndexes(int a, int b) { @@ -524,15 +502,6 @@ hasSite(Context* c, Value* v) return it.hasMore(); } -bool -findSite(Context*, Value* v, Site* site) -{ - for (Site* s = v->sites; s; s = s->next) { - if (s == site) return true; - } - return false; -} - bool uniqueSite(Context* c, Value* v, Site* s) { @@ -561,7 +530,7 @@ uniqueSite(Context* c, Value* v, Site* s) void addSite(Context* c, Value* v, Site* s) { - if (not findSite(c, v, s)) { + if (not v->findSite(s)) { if (DebugSites) { char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "add site %s to %p\n", buffer, v); @@ -588,7 +557,7 @@ removeSite(Context* c, Value* v, Site* s) if (DebugSites) { fprintf(stderr, "%p has more: %d\n", v, hasSite(c, v)); } - assert(c, not findSite(c, v, s)); + assert(c, not v->findSite(s)); } void @@ -745,16 +714,6 @@ popRead(Context* c, Event* e UNUSED, Value* v) } } -bool -buddies(Value* a, Value* b) -{ - if (a == b) return true; - for (Value* p = a->buddy; p != a; p = p->buddy) { - if (p == b) return true; - } - return false; -} - void addBuddy(Value* original, Value* buddy) { @@ -772,27 +731,6 @@ addBuddy(Value* original, Value* buddy) } } -class Target { - public: - static const unsigned MinimumRegisterCost = 0; - static const unsigned MinimumFrameCost = 1; - static const unsigned StealPenalty = 2; - static const unsigned StealUniquePenalty = 4; - static const unsigned IndirectMovePenalty = 4; - static const unsigned LowRegisterPenalty = 10; - static const unsigned Impossible = 20; - - Target(): cost(Impossible) { } - - Target(int index, lir::OperandType type, unsigned cost): - index(index), type(type), cost(cost) - { } - - int16_t index; - lir::OperandType type; - uint8_t cost; -}; - lir::ValueType valueType(Context* c, Compiler::OperandType type) { @@ -809,283 +747,6 @@ valueType(Context* c, Compiler::OperandType type) } } -class CostCalculator { - public: - virtual unsigned cost(Context* c, SiteMask mask) = 0; -}; - -unsigned -resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, - CostCalculator* costCalculator) -{ - if (r->reserved or r->freezeCount or r->referenceCount) { - return Target::Impossible; - } else { - unsigned baseCost = - costCalculator ? costCalculator->cost(c, mask) : 0; - - if (r->value) { - assert(c, findSite(c, r->value, r->site)); - - if (v and buddies(r->value, v)) { - return baseCost; - } else if (uniqueSite(c, r->value, r->site)) { - return baseCost + Target::StealUniquePenalty; - } else { - return baseCost = Target::StealPenalty; - } - } else { - return baseCost; - } - } -} - -bool -pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, - unsigned* cost, CostCalculator* costCalculator = 0) -{ - if ((1 << i) & mask) { - RegisterResource* r = c->registerResources + i; - unsigned myCost = resourceCost - (c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator) - + Target::MinimumRegisterCost; - - if ((static_cast(1) << i) == mask) { - *cost = myCost; - return true; - } else if (myCost < *cost) { - *cost = myCost; - *target = i; - } - } - return false; -} - -int -pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, - CostCalculator* costCalculator = 0) -{ - int target = lir::NoRegister; - *cost = Target::Impossible; - - if (mask & c->regFile->generalRegisters.mask) { - for (int i = c->regFile->generalRegisters.limit - 1; - i >= c->regFile->generalRegisters.start; --i) - { - if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { - return i; - } - } - } - - if (mask & c->regFile->floatRegisters.mask) { - for (int i = c->regFile->floatRegisters.start; - i < static_cast(c->regFile->floatRegisters.limit); ++i) - { - if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { - return i; - } - } - } - - return target; -} - -Target -pickRegisterTarget(Context* c, Value* v, uint32_t mask, - CostCalculator* costCalculator = 0) -{ - unsigned cost; - int number = pickRegisterTarget(c, v, mask, &cost, costCalculator); - return Target(number, lir::RegisterOperand, cost); -} - -unsigned -frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator) -{ - return resourceCost - (c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex), - costCalculator) - + Target::MinimumFrameCost; -} - -Target -pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) -{ - Target best; - - Value* p = v; - do { - if (p->home >= 0) { - Target mine - (p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator)); - - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - p = p->buddy; - } while (p != v); - - return best; -} - -Target -pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) -{ - Target best; - - unsigned count = totalFrameSize(c); - for (unsigned i = 0; i < count; ++i) { - Target mine(i, lir::MemoryOperand, frameCost(c, v, i, costCalculator)); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - return best; -} - -Target -pickTarget(Context* c, Value* value, const SiteMask& mask, - unsigned registerPenalty, Target best, - CostCalculator* costCalculator) -{ - if (mask.typeMask & (1 << lir::RegisterOperand)) { - Target mine = pickRegisterTarget - (c, value, mask.registerMask, costCalculator); - - mine.cost += registerPenalty; - if (mine.cost == Target::MinimumRegisterCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - if (mask.typeMask & (1 << lir::MemoryOperand)) { - if (mask.frameIndex >= 0) { - Target mine(mask.frameIndex, lir::MemoryOperand, - frameCost(c, value, mask.frameIndex, costCalculator)); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } else if (mask.frameIndex == AnyFrameIndex) { - Target mine = pickFrameTarget(c, value, costCalculator); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - } - - return best; -} - -Target -pickTarget(Context* c, Read* read, bool intersectRead, - unsigned registerReserveCount, CostCalculator* costCalculator) -{ - unsigned registerPenalty - = (c->availableGeneralRegisterCount > registerReserveCount - ? 0 : Target::LowRegisterPenalty); - - Value* value = read->value; - - uint32_t registerMask - = (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask); - - SiteMask mask(~0, registerMask, AnyFrameIndex); - read->intersect(&mask); - - if (value->type == lir::ValueFloat) { - uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask; - if (floatMask) { - mask.registerMask = floatMask; - } - } - - Target best; - - Value* successor = read->successor(); - if (successor) { - Read* r = live(c, successor); - if (r) { - SiteMask intersection = mask; - if (r->intersect(&intersection)) { - best = pickTarget - (c, value, intersection, registerPenalty, best, costCalculator); - - if (best.cost <= Target::MinimumFrameCost) { - return best; - } - } - } - } - - best = pickTarget(c, value, mask, registerPenalty, best, costCalculator); - if (best.cost <= Target::MinimumFrameCost) { - return best; - } - - if (intersectRead) { - if (best.cost == Target::Impossible) { - fprintf(stderr, "mask type %d reg %d frame %d\n", - mask.typeMask, mask.registerMask, mask.frameIndex); - abort(c); - } - return best; - } - - { Target mine = pickRegisterTarget(c, value, registerMask, costCalculator); - - mine.cost += registerPenalty; - - if (mine.cost == Target::MinimumRegisterCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - { Target mine = pickFrameTarget(c, value, costCalculator); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - if (best.cost >= Target::StealUniquePenalty - and c->availableGeneralRegisterCount == 0) - { - // there are no free registers left, so moving from memory to - // memory isn't an option - try harder to find an available frame - // site: - best = pickAnyFrameTarget(c, value, costCalculator); - assert(c, best.cost <= 3); - } - - if (best.cost == Target::Impossible) { - abort(c); - } - - return best; -} - -void -acquire(Context* c, Resource* resource, Value* value, Site* site); - -void -release(Context* c, Resource* resource, Value* value, Site* site); - Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { return new(c->zone) ShiftMaskPromise(base, shift, mask); } @@ -1094,297 +755,10 @@ Promise* combinedPromise(Context* c, Promise* low, Promise* high) { return new(c->zone) CombinedPromise(low, high); } -Promise* -resolved(Context* c, int64_t value) -{ +Promise* resolved(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } -AddressSite* -addressSite(Context* c, Promise* address); - -class AddressSite: public Site { - public: - AddressSite(Promise* address): address(address) { } - - virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { - if (address->resolved()) { - return vm::snprintf - (buffer, bufferSize, "address %" LLD, address->value()); - } else { - return vm::snprintf(buffer, bufferSize, "address unresolved"); - } - } - - virtual unsigned copyCost(Context*, Site* s) { - return (s == this ? 0 : AddressCopyCost); - } - - virtual bool match(Context*, const SiteMask& mask) { - return mask.typeMask & (1 << lir::AddressOperand); - } - - virtual bool loneMatch(Context*, const SiteMask&) { - return false; - } - - virtual bool matchNextWord(Context* c, Site*, unsigned) { - abort(c); - } - - virtual lir::OperandType type(Context*) { - return lir::AddressOperand; - } - - virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, - lir::Operand* result) - { - assert(c, high == this); - - new (result) lir::Address(address); - } - - virtual Site* copy(Context* c) { - return addressSite(c, address); - } - - virtual Site* copyLow(Context* c) { - abort(c); - } - - virtual Site* copyHigh(Context* c) { - abort(c); - } - - virtual Site* makeNextWord(Context* c, unsigned) { - abort(c); - } - - virtual SiteMask mask(Context*) { - return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex); - } - - virtual SiteMask nextWordMask(Context* c, unsigned) { - abort(c); - } - - Promise* address; -}; - -AddressSite* -addressSite(Context* c, Promise* address) -{ - return new(c->zone) AddressSite(address); -} - -RegisterSite* -freeRegisterSite(Context* c, uint32_t mask); - -class RegisterSite: public Site { - public: - RegisterSite(uint32_t mask, int number): - mask_(mask), number(number) - { } - - virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { - if (number != lir::NoRegister) { - return vm::snprintf(buffer, bufferSize, "%p register %d", this, number); - } else { - return vm::snprintf(buffer, bufferSize, - "%p register unacquired (mask %d)", this, mask_); - } - } - - virtual unsigned copyCost(Context* c, Site* s) { - assert(c, number != lir::NoRegister); - - if (s and - (this == s or - (s->type(c) == lir::RegisterOperand - and (static_cast(s)->mask_ & (1 << number))))) - { - return 0; - } else { - return RegisterCopyCost; - } - } - - virtual bool match(Context* c UNUSED, const SiteMask& mask) { - assert(c, number != lir::NoRegister); - - if ((mask.typeMask & (1 << lir::RegisterOperand))) { - return ((static_cast(1) << number) & mask.registerMask); - } else { - return false; - } - } - - virtual bool loneMatch(Context* c UNUSED, const SiteMask& mask) { - assert(c, number != lir::NoRegister); - - if ((mask.typeMask & (1 << lir::RegisterOperand))) { - return ((static_cast(1) << number) == mask.registerMask); - } else { - return false; - } - } - - virtual bool matchNextWord(Context* c, Site* s, unsigned) { - assert(c, number != lir::NoRegister); - - if (s->type(c) != lir::RegisterOperand) { - return false; - } - - RegisterSite* rs = static_cast(s); - unsigned size = rs->registerSize(c); - if (size > TargetBytesPerWord) { - assert(c, number != lir::NoRegister); - return number == rs->number; - } else { - uint32_t mask = c->regFile->generalRegisters.mask; - return ((1 << number) & mask) and ((1 << rs->number) & mask); - } - } - - virtual void acquire(Context* c, Value* v) { - Target target; - if (number != lir::NoRegister) { - target = Target(number, lir::RegisterOperand, 0); - } else { - target = pickRegisterTarget(c, v, mask_); - expect(c, target.cost < Target::Impossible); - } - - RegisterResource* resource = c->registerResources + target.index; - compiler::acquire(c, resource, v, this); - - number = target.index; - } - - virtual void release(Context* c, Value* v) { - assert(c, number != lir::NoRegister); - - compiler::release(c, c->registerResources + number, v, this); - } - - virtual void freeze(Context* c, Value* v) { - assert(c, number != lir::NoRegister); - - c->registerResources[number].freeze(c, v); - } - - virtual void thaw(Context* c, Value* v) { - assert(c, number != lir::NoRegister); - - c->registerResources[number].thaw(c, v); - } - - virtual bool frozen(Context* c UNUSED) { - assert(c, number != lir::NoRegister); - - return c->registerResources[number].freezeCount != 0; - } - - virtual lir::OperandType type(Context*) { - return lir::RegisterOperand; - } - - virtual void asAssemblerOperand(Context* c UNUSED, Site* high, - lir::Operand* result) - { - assert(c, number != lir::NoRegister); - - int highNumber; - if (high != this) { - highNumber = static_cast(high)->number; - assert(c, highNumber != lir::NoRegister); - } else { - highNumber = lir::NoRegister; - } - - new (result) lir::Register(number, highNumber); - } - - virtual Site* copy(Context* c) { - uint32_t mask; - - if (number != lir::NoRegister) { - mask = 1 << number; - } else { - mask = mask_; - } - - return freeRegisterSite(c, mask); - } - - virtual Site* copyLow(Context* c) { - abort(c); - } - - virtual Site* copyHigh(Context* c) { - abort(c); - } - - virtual Site* makeNextWord(Context* c, unsigned) { - assert(c, number != lir::NoRegister); - assert(c, ((1 << number) & c->regFile->generalRegisters.mask)); - - return freeRegisterSite(c, c->regFile->generalRegisters.mask); - } - - virtual SiteMask mask(Context* c UNUSED) { - return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex); - } - - virtual SiteMask nextWordMask(Context* c, unsigned) { - assert(c, number != lir::NoRegister); - - if (registerSize(c) > TargetBytesPerWord) { - return SiteMask - (1 << lir::RegisterOperand, number, NoFrameIndex); - } else { - return SiteMask - (1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex); - } - } - - virtual unsigned registerSize(Context* c) { - assert(c, number != lir::NoRegister); - - if ((1 << number) & c->regFile->floatRegisters.mask) { - return c->arch->floatRegisterSize(); - } else { - return TargetBytesPerWord; - } - } - - virtual unsigned registerMask(Context* c UNUSED) { - assert(c, number != lir::NoRegister); - - return 1 << number; - } - - uint32_t mask_; - int number; -}; - -RegisterSite* -registerSite(Context* c, int number) -{ - assert(c, number >= 0); - assert(c, (1 << number) & (c->regFile->generalRegisters.mask - | c->regFile->floatRegisters.mask)); - - return new(c->zone) RegisterSite(1 << number, number); -} - -RegisterSite* -freeRegisterSite(Context* c, uint32_t mask) -{ - return new(c->zone) RegisterSite(mask, lir::NoRegister); -} - MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1); @@ -1960,7 +1334,7 @@ steal(Context* c, Resource* r, Value* thief) thief, resourceBuffer, r->value, siteBuffer); } - if ((not (thief and buddies(thief, r->value)) + if ((not (thief and thief->isBuddyOf(r->value)) and uniqueSite(c, r->value, r->site))) { r->site->freeze(c, r->value); @@ -1973,71 +1347,6 @@ steal(Context* c, Resource* r, Value* thief) removeSite(c, r->value, r->site); } -void -acquire(Context* c, Resource* resource, Value* value, Site* site) -{ - assert(c, value); - assert(c, site); - - if (not resource->reserved) { - if (DebugResources) { - char buffer[256]; resource->toString(c, buffer, 256); - fprintf(stderr, "%p acquire %s\n", value, buffer); - } - - if (resource->value) { - assert(c, findSite(c, resource->value, resource->site)); - assert(c, not findSite(c, value, resource->site)); - - steal(c, resource, value); - } - - if (c->acquiredResources) { - c->acquiredResources->previousAcquired = resource; - resource->nextAcquired = c->acquiredResources; - } - c->acquiredResources = resource; - - resource->value = value; - resource->site = site; - } -} - -void -release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) -{ - if (not resource->reserved) { - if (DebugResources) { - char buffer[256]; resource->toString(c, buffer, 256); - fprintf(stderr, "%p release %s\n", resource->value, buffer); - } - - assert(c, resource->value); - assert(c, resource->site); - - assert(c, buddies(resource->value, value)); - assert(c, site == resource->site); - - Resource* next = resource->nextAcquired; - if (next) { - next->previousAcquired = resource->previousAcquired; - resource->nextAcquired = 0; - } - - Resource* previous = resource->previousAcquired; - if (previous) { - previous->nextAcquired = next; - resource->previousAcquired = 0; - } else { - assert(c, c->acquiredResources == resource); - c->acquiredResources = next; - } - - resource->value = 0; - resource->site = 0; - } -} - SiteMask generalRegisterMask(Context* c) { @@ -2319,7 +1628,7 @@ move(Context* c, Value* value, Site* src, Site* dst) srcb, dstb, value, value); } - assert(c, findSite(c, value, dst)); + assert(c, value->findSite(dst)); src->freeze(c, value); dst->freeze(c, value); diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index df6382e68f..2605aaf64d 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -12,9 +12,10 @@ #define AVIAN_CODEGEN_COMPILER_CONTEXT_H #include "codegen/assembler.h" -#include "codegen/regalloc.h" #include "codegen/compiler.h" +#include "codegen/compiler/regalloc.h" + namespace avian { namespace codegen { namespace compiler { @@ -51,7 +52,7 @@ class Context { Event* predecessor; LogicalInstruction** logicalCode; const RegisterFile* regFile; - regalloc::RegisterAllocator regAlloc; + RegisterAllocator regAlloc; RegisterResource* registerResources; FrameResource* frameResources; Resource* acquiredResources; diff --git a/src/codegen/compiler/read.h b/src/codegen/compiler/read.h new file mode 100644 index 0000000000..a0c1d5a763 --- /dev/null +++ b/src/codegen/compiler/read.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_READ_H +#define AVIAN_CODEGEN_COMPILER_READ_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Read { + public: + Read(): + value(0), event(0), eventNext(0) + { } + + virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0; + + virtual Value* high(Context* c) { abort(c); } + + virtual Value* successor() = 0; + + virtual bool valid() = 0; + + virtual void append(Context* c, Read* r) = 0; + + virtual Read* next(Context* c) = 0; + + Value* value; + Event* event; + Read* eventNext; +}; + + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_READ_H diff --git a/src/codegen/compiler/regalloc.cpp b/src/codegen/compiler/regalloc.cpp new file mode 100644 index 0000000000..2727b569c4 --- /dev/null +++ b/src/codegen/compiler/regalloc.cpp @@ -0,0 +1,301 @@ +/* Copyright (c) 2008-2012, 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 "target.h" + +#include "codegen/compiler/regalloc.h" +#include "codegen/compiler/context.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/read.h" + +namespace avian { +namespace codegen { +namespace compiler { + +RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile): + a(a), + registerFile(registerFile) +{ } + + +bool uniqueSite(Context* c, Value* v, Site* s); +unsigned totalFrameSize(Context* c); +Read* live(Context* c UNUSED, Value* v); + +unsigned +resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, + CostCalculator* costCalculator) +{ + if (r->reserved or r->freezeCount or r->referenceCount) { + return Target::Impossible; + } else { + unsigned baseCost = + costCalculator ? costCalculator->cost(c, mask) : 0; + + if (r->value) { + assert(c, r->value->findSite(r->site)); + + if (v and r->value->isBuddyOf(v)) { + return baseCost; + } else if (uniqueSite(c, r->value, r->site)) { + return baseCost + Target::StealUniquePenalty; + } else { + return baseCost = Target::StealPenalty; + } + } else { + return baseCost; + } + } +} + +bool +pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, + unsigned* cost, CostCalculator* costCalculator) +{ + if ((1 << i) & mask) { + RegisterResource* r = c->registerResources + i; + unsigned myCost = resourceCost + (c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator) + + Target::MinimumRegisterCost; + + if ((static_cast(1) << i) == mask) { + *cost = myCost; + return true; + } else if (myCost < *cost) { + *cost = myCost; + *target = i; + } + } + return false; +} + +int +pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, + CostCalculator* costCalculator) +{ + int target = lir::NoRegister; + *cost = Target::Impossible; + + if (mask & c->regFile->generalRegisters.mask) { + for (int i = c->regFile->generalRegisters.limit - 1; + i >= c->regFile->generalRegisters.start; --i) + { + if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { + return i; + } + } + } + + if (mask & c->regFile->floatRegisters.mask) { + for (int i = c->regFile->floatRegisters.start; + i < static_cast(c->regFile->floatRegisters.limit); ++i) + { + if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { + return i; + } + } + } + + return target; +} + +Target +pickRegisterTarget(Context* c, Value* v, uint32_t mask, + CostCalculator* costCalculator) +{ + unsigned cost; + int number = pickRegisterTarget(c, v, mask, &cost, costCalculator); + return Target(number, lir::RegisterOperand, cost); +} + +unsigned +frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator) +{ + return resourceCost + (c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex), + costCalculator) + + Target::MinimumFrameCost; +} + +Target +pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) +{ + Target best; + + Value* p = v; + do { + if (p->home >= 0) { + Target mine + (p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator)); + + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + p = p->buddy; + } while (p != v); + + return best; +} + +Target +pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) +{ + Target best; + + unsigned count = totalFrameSize(c); + for (unsigned i = 0; i < count; ++i) { + Target mine(i, lir::MemoryOperand, frameCost(c, v, i, costCalculator)); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + return best; +} + +Target +pickTarget(Context* c, Value* value, const SiteMask& mask, + unsigned registerPenalty, Target best, + CostCalculator* costCalculator) +{ + if (mask.typeMask & (1 << lir::RegisterOperand)) { + Target mine = pickRegisterTarget + (c, value, mask.registerMask, costCalculator); + + mine.cost += registerPenalty; + if (mine.cost == Target::MinimumRegisterCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + if (mask.typeMask & (1 << lir::MemoryOperand)) { + if (mask.frameIndex >= 0) { + Target mine(mask.frameIndex, lir::MemoryOperand, + frameCost(c, value, mask.frameIndex, costCalculator)); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } else if (mask.frameIndex == AnyFrameIndex) { + Target mine = pickFrameTarget(c, value, costCalculator); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + } + + return best; +} + +Target +pickTarget(Context* c, Read* read, bool intersectRead, + unsigned registerReserveCount, CostCalculator* costCalculator) +{ + unsigned registerPenalty + = (c->availableGeneralRegisterCount > registerReserveCount + ? 0 : Target::LowRegisterPenalty); + + Value* value = read->value; + + uint32_t registerMask + = (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask); + + SiteMask mask(~0, registerMask, AnyFrameIndex); + read->intersect(&mask); + + if (value->type == lir::ValueFloat) { + uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask; + if (floatMask) { + mask.registerMask = floatMask; + } + } + + Target best; + + Value* successor = read->successor(); + if (successor) { + Read* r = live(c, successor); + if (r) { + SiteMask intersection = mask; + if (r->intersect(&intersection)) { + best = pickTarget + (c, value, intersection, registerPenalty, best, costCalculator); + + if (best.cost <= Target::MinimumFrameCost) { + return best; + } + } + } + } + + best = pickTarget(c, value, mask, registerPenalty, best, costCalculator); + if (best.cost <= Target::MinimumFrameCost) { + return best; + } + + if (intersectRead) { + if (best.cost == Target::Impossible) { + fprintf(stderr, "mask type %d reg %d frame %d\n", + mask.typeMask, mask.registerMask, mask.frameIndex); + abort(c); + } + return best; + } + + { Target mine = pickRegisterTarget(c, value, registerMask, costCalculator); + + mine.cost += registerPenalty; + + if (mine.cost == Target::MinimumRegisterCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + { Target mine = pickFrameTarget(c, value, costCalculator); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + if (best.cost >= Target::StealUniquePenalty + and c->availableGeneralRegisterCount == 0) + { + // there are no free registers left, so moving from memory to + // memory isn't an option - try harder to find an available frame + // site: + best = pickAnyFrameTarget(c, value, costCalculator); + assert(c, best.cost <= 3); + } + + if (best.cost == Target::Impossible) { + abort(c); + } + + return best; +} + +} // namespace regalloc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/regalloc.h b/src/codegen/compiler/regalloc.h new file mode 100644 index 0000000000..cfbf154f1f --- /dev/null +++ b/src/codegen/compiler/regalloc.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_REGALLOC_H +#define AVIAN_CODEGEN_COMPILER_REGALLOC_H + +#include "common.h" + +#include "codegen/lir.h" +#include "codegen/registers.h" + +class Aborter; + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; +class Value; +class SiteMask; +class Resource; +class Read; + + +class RegisterAllocator { +public: + Aborter* a; + const RegisterFile* registerFile; + + RegisterAllocator(Aborter* a, const RegisterFile* registerFile); + +}; + +class Target { + public: + static const unsigned MinimumRegisterCost = 0; + static const unsigned MinimumFrameCost = 1; + static const unsigned StealPenalty = 2; + static const unsigned StealUniquePenalty = 4; + static const unsigned IndirectMovePenalty = 4; + static const unsigned LowRegisterPenalty = 10; + static const unsigned Impossible = 20; + + Target(): cost(Impossible) { } + + Target(int index, lir::OperandType type, unsigned cost): + index(index), type(type), cost(cost) + { } + + int16_t index; + lir::OperandType type; + uint8_t cost; +}; + +class CostCalculator { + public: + virtual unsigned cost(Context* c, SiteMask mask) = 0; +}; + +unsigned +resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, + CostCalculator* costCalculator); + + +bool +pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, + unsigned* cost, CostCalculator* costCalculator = 0); + +int +pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, + CostCalculator* costCalculator = 0); + +Target +pickRegisterTarget(Context* c, Value* v, uint32_t mask, + CostCalculator* costCalculator = 0); + +unsigned +frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator); + +Target +pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator); + +Target +pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator); + +Target +pickTarget(Context* c, Value* value, const SiteMask& mask, + unsigned registerPenalty, Target best, + CostCalculator* costCalculator); + +Target +pickTarget(Context* c, Read* read, bool intersectRead, + unsigned registerReserveCount, CostCalculator* costCalculator); + +} // namespace regalloc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H \ No newline at end of file diff --git a/src/codegen/compiler/resource.cpp b/src/codegen/compiler/resource.cpp index 1b549e0197..af5e917762 100644 --- a/src/codegen/compiler/resource.cpp +++ b/src/codegen/compiler/resource.cpp @@ -10,6 +10,7 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/resource.h" +#include "codegen/compiler/value.h" namespace avian { namespace codegen { @@ -17,6 +18,9 @@ namespace compiler { const bool DebugResources = false; + +void steal(Context* c, Resource* r, Value* thief); + void decrementAvailableGeneralRegisterCount(Context* c) { assert(c, c->availableGeneralRegisterCount); -- c->availableGeneralRegisterCount; @@ -155,6 +159,68 @@ unsigned FrameResource::index(Context* c) { } +void acquire(Context* c, Resource* resource, Value* value, Site* site) { + assert(c, value); + assert(c, site); + + if (not resource->reserved) { + if (DebugResources) { + char buffer[256]; resource->toString(c, buffer, 256); + fprintf(stderr, "%p acquire %s\n", value, buffer); + } + + if (resource->value) { + assert(c, resource->value->findSite(resource->site)); + assert(c, not value->findSite(resource->site)); + + steal(c, resource, value); + } + + if (c->acquiredResources) { + c->acquiredResources->previousAcquired = resource; + resource->nextAcquired = c->acquiredResources; + } + c->acquiredResources = resource; + + resource->value = value; + resource->site = site; + } +} + +void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) { + if (not resource->reserved) { + if (DebugResources) { + char buffer[256]; resource->toString(c, buffer, 256); + fprintf(stderr, "%p release %s\n", resource->value, buffer); + } + + assert(c, resource->value); + assert(c, resource->site); + + assert(c, resource->value->isBuddyOf(value)); + assert(c, site == resource->site); + + Resource* next = resource->nextAcquired; + if (next) { + next->previousAcquired = resource->previousAcquired; + resource->nextAcquired = 0; + } + + Resource* previous = resource->previousAcquired; + if (previous) { + previous->nextAcquired = next; + resource->previousAcquired = 0; + } else { + assert(c, c->acquiredResources == resource); + c->acquiredResources = next; + } + + resource->value = 0; + resource->site = 0; + } +} + + } // namespace compiler } // namespace codegen } // namespace avian \ No newline at end of file diff --git a/src/codegen/compiler/resource.h b/src/codegen/compiler/resource.h index 004cbc34cc..1cc35e3445 100644 --- a/src/codegen/compiler/resource.h +++ b/src/codegen/compiler/resource.h @@ -66,6 +66,10 @@ class FrameResource: public Resource { virtual unsigned index(Context*); }; +void acquire(Context* c, Resource* resource, Value* value, Site* site); + +void release(Context* c, Resource* resource, Value* value, Site* site); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp index 1e3dcff448..1534356674 100644 --- a/src/codegen/compiler/site.cpp +++ b/src/codegen/compiler/site.cpp @@ -13,6 +13,7 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/value.h" #include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" namespace avian { namespace codegen { @@ -97,6 +98,278 @@ Site* constantSite(Context* c, int64_t value) { return constantSite(c, resolved(c, value)); } + + +class AddressSite: public Site { + public: + AddressSite(Promise* address): address(address) { } + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { + if (address->resolved()) { + return vm::snprintf + (buffer, bufferSize, "address %" LLD, address->value()); + } else { + return vm::snprintf(buffer, bufferSize, "address unresolved"); + } + } + + virtual unsigned copyCost(Context*, Site* s) { + return (s == this ? 0 : AddressCopyCost); + } + + virtual bool match(Context*, const SiteMask& mask) { + return mask.typeMask & (1 << lir::AddressOperand); + } + + virtual bool loneMatch(Context*, const SiteMask&) { + return false; + } + + virtual bool matchNextWord(Context* c, Site*, unsigned) { + abort(c); + } + + virtual lir::OperandType type(Context*) { + return lir::AddressOperand; + } + + virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, + lir::Operand* result) + { + assert(c, high == this); + + new (result) lir::Address(address); + } + + virtual Site* copy(Context* c) { + return addressSite(c, address); + } + + virtual Site* copyLow(Context* c) { + abort(c); + } + + virtual Site* copyHigh(Context* c) { + abort(c); + } + + virtual Site* makeNextWord(Context* c, unsigned) { + abort(c); + } + + virtual SiteMask mask(Context*) { + return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex); + } + + virtual SiteMask nextWordMask(Context* c, unsigned) { + abort(c); + } + + Promise* address; +}; + +Site* addressSite(Context* c, Promise* address) { + return new(c->zone) AddressSite(address); +} + + +RegisterSite::RegisterSite(uint32_t mask, int number): + mask_(mask), number(number) +{ } + +unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize) { + if (number != lir::NoRegister) { + return vm::snprintf(buffer, bufferSize, "%p register %d", this, number); + } else { + return vm::snprintf(buffer, bufferSize, + "%p register unacquired (mask %d)", this, mask_); + } +} + +unsigned RegisterSite::copyCost(Context* c, Site* s) { + assert(c, number != lir::NoRegister); + + if (s and + (this == s or + (s->type(c) == lir::RegisterOperand + and (static_cast(s)->mask_ & (1 << number))))) + { + return 0; + } else { + return RegisterCopyCost; + } +} + +bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) { + assert(c, number != lir::NoRegister); + + if ((mask.typeMask & (1 << lir::RegisterOperand))) { + return ((static_cast(1) << number) & mask.registerMask); + } else { + return false; + } +} + +bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) { + assert(c, number != lir::NoRegister); + + if ((mask.typeMask & (1 << lir::RegisterOperand))) { + return ((static_cast(1) << number) == mask.registerMask); + } else { + return false; + } +} + +bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) { + assert(c, number != lir::NoRegister); + + if (s->type(c) != lir::RegisterOperand) { + return false; + } + + RegisterSite* rs = static_cast(s); + unsigned size = rs->registerSize(c); + if (size > vm::TargetBytesPerWord) { + assert(c, number != lir::NoRegister); + return number == rs->number; + } else { + uint32_t mask = c->regFile->generalRegisters.mask; + return ((1 << number) & mask) and ((1 << rs->number) & mask); + } +} + +void RegisterSite::acquire(Context* c, Value* v) { + Target target; + if (number != lir::NoRegister) { + target = Target(number, lir::RegisterOperand, 0); + } else { + target = pickRegisterTarget(c, v, mask_); + expect(c, target.cost < Target::Impossible); + } + + RegisterResource* resource = c->registerResources + target.index; + compiler::acquire(c, resource, v, this); + + number = target.index; +} + +void RegisterSite::release(Context* c, Value* v) { + assert(c, number != lir::NoRegister); + + compiler::release(c, c->registerResources + number, v, this); +} + +void RegisterSite::freeze(Context* c, Value* v) { + assert(c, number != lir::NoRegister); + + c->registerResources[number].freeze(c, v); +} + +void RegisterSite::thaw(Context* c, Value* v) { + assert(c, number != lir::NoRegister); + + c->registerResources[number].thaw(c, v); +} + +bool RegisterSite::frozen(Context* c UNUSED) { + assert(c, number != lir::NoRegister); + + return c->registerResources[number].freezeCount != 0; +} + +lir::OperandType RegisterSite::type(Context*) { + return lir::RegisterOperand; +} + +void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high, + lir::Operand* result) +{ + assert(c, number != lir::NoRegister); + + int highNumber; + if (high != this) { + highNumber = static_cast(high)->number; + assert(c, highNumber != lir::NoRegister); + } else { + highNumber = lir::NoRegister; + } + + new (result) lir::Register(number, highNumber); +} + +Site* RegisterSite::copy(Context* c) { + uint32_t mask; + + if (number != lir::NoRegister) { + mask = 1 << number; + } else { + mask = mask_; + } + + return freeRegisterSite(c, mask); +} + +Site* RegisterSite::copyLow(Context* c) { + abort(c); +} + +Site* RegisterSite::copyHigh(Context* c) { + abort(c); +} + +Site* RegisterSite::makeNextWord(Context* c, unsigned) { + assert(c, number != lir::NoRegister); + assert(c, ((1 << number) & c->regFile->generalRegisters.mask)); + + return freeRegisterSite(c, c->regFile->generalRegisters.mask); +} + +SiteMask RegisterSite::mask(Context* c UNUSED) { + return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex); +} + +SiteMask RegisterSite::nextWordMask(Context* c, unsigned) { + assert(c, number != lir::NoRegister); + + if (registerSize(c) > vm::TargetBytesPerWord) { + return SiteMask + (1 << lir::RegisterOperand, number, NoFrameIndex); + } else { + return SiteMask + (1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex); + } +} + +unsigned RegisterSite::registerSize(Context* c) { + assert(c, number != lir::NoRegister); + + if ((1 << number) & c->regFile->floatRegisters.mask) { + return c->arch->floatRegisterSize(); + } else { + return vm::TargetBytesPerWord; + } +} + +unsigned RegisterSite::registerMask(Context* c UNUSED) { + assert(c, number != lir::NoRegister); + + return 1 << number; +} + + + +Site* registerSite(Context* c, int number) { + assert(c, number >= 0); + assert(c, (1 << number) & (c->regFile->generalRegisters.mask + | c->regFile->floatRegisters.mask)); + + return new(c->zone) RegisterSite(1 << number, number); +} + +Site* freeRegisterSite(Context* c, uint32_t mask) { + return new(c->zone) RegisterSite(mask, lir::NoRegister); +} + } // namespace compiler } // namespace codegen } // namespace avian \ No newline at end of file diff --git a/src/codegen/compiler/site.h b/src/codegen/compiler/site.h index aa66243b70..0d32b263a2 100644 --- a/src/codegen/compiler/site.h +++ b/src/codegen/compiler/site.h @@ -11,6 +11,9 @@ #ifndef AVIAN_CODEGEN_COMPILER_SITE_H #define AVIAN_CODEGEN_COMPILER_SITE_H +#include "codegen/compiler/value.h" +#include "codegen/compiler/context.h" + namespace avian { namespace codegen { namespace compiler { @@ -183,6 +186,60 @@ class ConstantSite: public Site { Promise* value; }; +Site* addressSite(Context* c, Promise* address); + +class RegisterSite: public Site { + public: + RegisterSite(uint32_t mask, int number); + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize); + + virtual unsigned copyCost(Context* c, Site* s); + + virtual bool match(Context* c UNUSED, const SiteMask& mask); + + virtual bool loneMatch(Context* c UNUSED, const SiteMask& mask); + + virtual bool matchNextWord(Context* c, Site* s, unsigned); + + virtual void acquire(Context* c, Value* v); + + virtual void release(Context* c, Value* v); + + virtual void freeze(Context* c, Value* v); + + virtual void thaw(Context* c, Value* v); + + virtual bool frozen(Context* c UNUSED); + + virtual lir::OperandType type(Context*); + + virtual void asAssemblerOperand(Context* c UNUSED, Site* high, + lir::Operand* result); + + virtual Site* copy(Context* c); + + virtual Site* copyLow(Context* c); + + virtual Site* copyHigh(Context* c); + + virtual Site* makeNextWord(Context* c, unsigned); + + virtual SiteMask mask(Context* c UNUSED); + + virtual SiteMask nextWordMask(Context* c, unsigned); + + virtual unsigned registerSize(Context* c); + + virtual unsigned registerMask(Context* c UNUSED); + + uint32_t mask_; + int number; +}; + +Site* registerSite(Context* c, int number); +Site* freeRegisterSite(Context* c, uint32_t mask); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp new file mode 100644 index 0000000000..a8f88acbca --- /dev/null +++ b/src/codegen/compiler/value.cpp @@ -0,0 +1,43 @@ +/* Copyright (c) 2008-2012, 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 "target.h" + +#include "codegen/compiler/regalloc.h" +#include "codegen/compiler/site.h" + +namespace avian { +namespace codegen { +namespace compiler { + +Value::Value(Site* site, Site* target, lir::ValueType type): + reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this), + nextWord(this), home(NoFrameIndex), type(type), wordIndex(0) +{ } + +bool Value::findSite(Site* site) { + for (Site* s = this->sites; s; s = s->next) { + if (s == site) return true; + } + return false; +} + +bool Value::isBuddyOf(Value* b) { + Value* a = this; + if (a == b) return true; + for (Value* p = a->buddy; p != a; p = p->buddy) { + if (p == b) return true; + } + return false; +} + +} // namespace regalloc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index a2e8040db6..f913d89363 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -13,6 +13,8 @@ #include "codegen/lir.h" +#include "codegen/compiler.h" + namespace avian { namespace codegen { namespace compiler { @@ -25,11 +27,6 @@ const int NoFrameIndex = -1; class Value: public Compiler::Operand { public: - Value(Site* site, Site* target, lir::ValueType type): - reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this), - nextWord(this), home(NoFrameIndex), type(type), wordIndex(0) - { } - Read* reads; Read* lastRead; Site* sites; @@ -40,6 +37,12 @@ class Value: public Compiler::Operand { int16_t home; lir::ValueType type; uint8_t wordIndex; + + Value(Site* site, Site* target, lir::ValueType type); + + bool findSite(Site* site); + + bool isBuddyOf(Value* b); }; } // namespace compiler diff --git a/src/codegen/regalloc.cpp b/src/codegen/regalloc.cpp deleted file mode 100644 index bc8abf926b..0000000000 --- a/src/codegen/regalloc.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (c) 2008-2012, 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 "codegen/regalloc.h" - -namespace avian { -namespace codegen { -namespace regalloc { - -RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile): - a(a), - registerFile(registerFile) -{ } - -} // namespace regalloc -} // namespace codegen -} // namespace avian \ No newline at end of file diff --git a/src/codegen/regalloc.h b/src/codegen/regalloc.h deleted file mode 100644 index 83fbd878f3..0000000000 --- a/src/codegen/regalloc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2008-2012, Avian Contributors - - Permission to use, copy, modify, and/or distribute this software - for any purpose with or without fee is hereby granted, provided - that the above copyright notice and this permission notice appear - in all copies. - - There is NO WARRANTY for this software. See license.txt for - details. */ - -#ifndef AVIAN_CODEGEN_REGALLOC_H -#define AVIAN_CODEGEN_REGALLOC_H - -#include "common.h" - -#include "codegen/registers.h" - -class Aborter; - -namespace avian { -namespace codegen { -namespace regalloc { - -class RegisterAllocator { -public: - Aborter* a; - const RegisterFile* registerFile; - - RegisterAllocator(Aborter* a, const RegisterFile* registerFile); - -}; - -} // namespace regalloc -} // namespace codegen -} // namespace avian - -#endif // AVIAN_CODEGEN_REGALLOC_H \ No newline at end of file From 6d265374ec9338fad7db5677e920cb3e736e5f36 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 18:18:51 -0700 Subject: [PATCH 219/378] move Reads out of compile.cpp --- makefile | 1 + src/codegen/compiler.cpp | 508 +-------------------------------- src/codegen/compiler/context.h | 27 +- src/codegen/compiler/read.cpp | 183 ++++++++++++ src/codegen/compiler/read.h | 73 +++++ src/codegen/compiler/site.cpp | 253 +++++++++++++++- src/codegen/compiler/site.h | 60 ++++ 7 files changed, 609 insertions(+), 496 deletions(-) create mode 100644 src/codegen/compiler/read.cpp diff --git a/makefile b/makefile index 9f57682239..f094576f32 100755 --- a/makefile +++ b/makefile @@ -958,6 +958,7 @@ ifeq ($(process),compile) $(src)/codegen/compiler/site.cpp \ $(src)/codegen/compiler/regalloc.cpp \ $(src)/codegen/compiler/value.cpp \ + $(src)/codegen/compiler/read.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 7b63548c42..5e7a06b927 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -45,11 +45,6 @@ const unsigned StealRegisterReserveCount = 2; const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4); class Stack; -class Site; -class ConstantSite; -class AddressSite; -class RegisterSite; -class MemorySite; class Event; class PushEvent; class Read; @@ -73,14 +68,6 @@ apply(Context* c, lir::TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); -class Cell { - public: - Cell(Cell* next, void* value): next(next), value(value) { } - - Cell* next; - void* value; -}; - class Local { public: Value* value; @@ -106,7 +93,7 @@ class ForkElement { class ForkState: public Compiler::State { public: - ForkState(Stack* stack, Local* locals, Cell* saved, Event* predecessor, + ForkState(Stack* stack, Local* locals, Cell* saved, Event* predecessor, unsigned logicalIp): stack(stack), locals(locals), @@ -118,7 +105,7 @@ class ForkState: public Compiler::State { Stack* stack; Local* locals; - Cell* saved; + Cell* saved; Event* predecessor; unsigned logicalIp; unsigned readCount; @@ -157,23 +144,6 @@ class ConstantPoolNode { ConstantPoolNode* next; }; -int -intersectFrameIndexes(int a, int b) -{ - if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex; - if (a == AnyFrameIndex) return b; - if (b == AnyFrameIndex) return a; - if (a == b) return a; - return NoFrameIndex; -} - -SiteMask -intersect(const SiteMask& a, const SiteMask& b) -{ - return SiteMask(a.typeMask & b.typeMask, a.registerMask & b.registerMask, - intersectFrameIndexes(a.frameIndex, b.frameIndex)); -} - class PoolPromise: public Promise { public: PoolPromise(Context* c, int key): c(c), key(key) { } @@ -254,29 +224,11 @@ class IpPromise: public Promise { int logicalIp; }; -unsigned -count(Cell* c) -{ - unsigned count = 0; - while (c) { - ++ count; - c = c->next; - } - return count; -} - -Cell* -cons(Context* c, void* value, Cell* next) -{ - return new (c->zone) Cell(next, value); -} - -Cell* -reverseDestroy(Cell* cell) -{ - Cell* previous = 0; +template +Cell* reverseDestroy(Cell* cell) { + Cell* previous = 0; while (cell) { - Cell* next = cell->next; + Cell* next = cell->next; cell->next = previous; previous = cell; cell = next; @@ -377,7 +329,7 @@ class Event { Snapshot* snapshots; Link* predecessors; Link* successors; - Cell* visitLinks; + Cell* visitLinks; Block* block; LogicalInstruction* logicalInstruction; unsigned readCount; @@ -759,254 +711,6 @@ Promise* resolved(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } -MemorySite* -memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, - unsigned scale = 1); - -class MemorySite: public Site { - public: - MemorySite(int base, int offset, int index, unsigned scale): - acquired(false), base(base), offset(offset), index(index), scale(scale) - { } - - virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { - if (acquired) { - return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d", - base, offset, index, scale); - } else { - return vm::snprintf(buffer, bufferSize, "memory unacquired"); - } - } - - virtual unsigned copyCost(Context* c, Site* s) { - assert(c, acquired); - - if (s and - (this == s or - (s->type(c) == lir::MemoryOperand - and static_cast(s)->base == base - and static_cast(s)->offset == offset - and static_cast(s)->index == index - and static_cast(s)->scale == scale))) - { - return 0; - } else { - return MemoryCopyCost; - } - } - - bool conflicts(const SiteMask& mask) { - return (mask.typeMask & (1 << lir::RegisterOperand)) != 0 - and (((1 << base) & mask.registerMask) == 0 - or (index != lir::NoRegister - and ((1 << index) & mask.registerMask) == 0)); - } - - virtual bool match(Context* c, const SiteMask& mask) { - assert(c, acquired); - - if (mask.typeMask & (1 << lir::MemoryOperand)) { - if (mask.frameIndex >= 0) { - if (base == c->arch->stack()) { - assert(c, index == lir::NoRegister); - return static_cast(frameIndexToOffset(c, mask.frameIndex)) - == offset; - } else { - return false; - } - } else { - return true; - } - } else { - return false; - } - } - - virtual bool loneMatch(Context* c, const SiteMask& mask) { - assert(c, acquired); - - if (mask.typeMask & (1 << lir::MemoryOperand)) { - if (base == c->arch->stack()) { - assert(c, index == lir::NoRegister); - - if (mask.frameIndex == AnyFrameIndex) { - return false; - } else { - return true; - } - } - } - return false; - } - - virtual bool matchNextWord(Context* c, Site* s, unsigned index) { - if (s->type(c) == lir::MemoryOperand) { - MemorySite* ms = static_cast(s); - return ms->base == this->base - and ((index == 1 and ms->offset == static_cast - (this->offset + TargetBytesPerWord)) - or (index == 0 and this->offset == static_cast - (ms->offset + TargetBytesPerWord))) - and ms->index == this->index - and ms->scale == this->scale; - } else { - return false; - } - } - - virtual void acquire(Context* c, Value* v) { - c->registerResources[base].increment(c); - if (index != lir::NoRegister) { - c->registerResources[index].increment(c); - } - - if (base == c->arch->stack()) { - assert(c, index == lir::NoRegister); - assert - (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); - - compiler::acquire - (c, c->frameResources + offsetToFrameIndex(c, offset), v, this); - } - - acquired = true; - } - - virtual void release(Context* c, Value* v) { - if (base == c->arch->stack()) { - assert(c, index == lir::NoRegister); - assert - (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); - - compiler::release - (c, c->frameResources + offsetToFrameIndex(c, offset), v, this); - } - - c->registerResources[base].decrement(c); - if (index != lir::NoRegister) { - c->registerResources[index].decrement(c); - } - - acquired = false; - } - - virtual void freeze(Context* c, Value* v) { - if (base == c->arch->stack()) { - c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v); - } else { - c->registerResources[base].increment(c); - if (index != lir::NoRegister) { - c->registerResources[index].increment(c); - } - } - } - - virtual void thaw(Context* c, Value* v) { - if (base == c->arch->stack()) { - c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v); - } else { - c->registerResources[base].decrement(c); - if (index != lir::NoRegister) { - c->registerResources[index].decrement(c); - } - } - } - - virtual bool frozen(Context* c) { - return base == c->arch->stack() - and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0; - } - - virtual lir::OperandType type(Context*) { - return lir::MemoryOperand; - } - - virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, - lir::Operand* result) - { - // todo: endianness? - assert(c, high == this - or (static_cast(high)->base == base - and static_cast(high)->offset - == static_cast(offset + TargetBytesPerWord) - and static_cast(high)->index == index - and static_cast(high)->scale == scale)); - - assert(c, acquired); - - new (result) lir::Memory(base, offset, index, scale); - } - - virtual Site* copy(Context* c) { - return memorySite(c, base, offset, index, scale); - } - - Site* copyHalf(Context* c, bool add) { - if (add) { - return memorySite(c, base, offset + TargetBytesPerWord, index, scale); - } else { - return copy(c); - } - } - - virtual Site* copyLow(Context* c) { - return copyHalf(c, c->arch->bigEndian()); - } - - virtual Site* copyHigh(Context* c) { - return copyHalf(c, not c->arch->bigEndian()); - } - - virtual Site* makeNextWord(Context* c, unsigned index) { - return memorySite - (c, base, offset + ((index == 1) xor c->arch->bigEndian() - ? TargetBytesPerWord : -TargetBytesPerWord), - this->index, scale); - } - - virtual SiteMask mask(Context* c) { - return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack()) - ? static_cast(offsetToFrameIndex(c, offset)) - : NoFrameIndex); - } - - virtual SiteMask nextWordMask(Context* c, unsigned index) { - int frameIndex; - if (base == c->arch->stack()) { - assert(c, this->index == lir::NoRegister); - frameIndex = static_cast(offsetToFrameIndex(c, offset)) - + ((index == 1) xor c->arch->bigEndian() ? 1 : -1); - } else { - frameIndex = NoFrameIndex; - } - return SiteMask(1 << lir::MemoryOperand, 0, frameIndex); - } - - virtual bool isVolatile(Context* c) { - return base != c->arch->stack(); - } - - bool acquired; - int base; - int offset; - int index; - unsigned scale; -}; - -MemorySite* -memorySite(Context* c, int base, int offset, int index, unsigned scale) -{ - return new(c->zone) MemorySite(base, offset, index, scale); -} - -MemorySite* -frameSite(Context* c, int frameIndex) -{ - assert(c, frameIndex >= 0); - return memorySite - (c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0); -} - void move(Context* c, Value* value, Site* src, Site* dst); @@ -1073,45 +777,6 @@ pickTargetSite(Context* c, Read* read, bool intersectRead = false, } } -class SingleRead: public Read { - public: - SingleRead(const SiteMask& mask, Value* successor): - next_(0), mask(mask), high_(0), successor_(successor) - { } - - virtual bool intersect(SiteMask* mask, unsigned) { - *mask = compiler::intersect(*mask, this->mask); - - return true; - } - - virtual Value* high(Context*) { - return high_; - } - - virtual Value* successor() { - return successor_; - } - - virtual bool valid() { - return true; - } - - virtual void append(Context* c UNUSED, Read* r) { - assert(c, next_ == 0); - next_ = r; - } - - virtual Read* next(Context*) { - return next_; - } - - Read* next_; - SiteMask mask; - Value* high_; - Value* successor_; -}; - SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0) { @@ -1137,7 +802,7 @@ pickSourceSite(Context* c, Read* read, Site* target = 0, SiteMask mask; if (extraMask) { - mask = intersect(mask, *extraMask); + mask = mask.intersectionWith(*extraMask); } if (intersectRead) { @@ -1368,104 +1033,6 @@ fixedRegisterMask(int number) return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex); } -class MultiRead: public Read { - public: - MultiRead(): - reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false) - { } - - virtual bool intersect(SiteMask* mask, unsigned depth) { - if (depth > 0) { - // short-circuit recursion to avoid poor performance in - // deeply-nested branches - return reads != 0; - } - - bool result = false; - if (not visited) { - visited = true; - for (Cell** cell = &reads; *cell;) { - Read* r = static_cast((*cell)->value); - bool valid = r->intersect(mask, depth + 1); - if (valid) { - result = true; - cell = &((*cell)->next); - } else { - *cell = (*cell)->next; - } - } - visited = false; - } - return result; - } - - virtual Value* successor() { - return 0; - } - - virtual bool valid() { - bool result = false; - if (not visited) { - visited = true; - for (Cell** cell = &reads; *cell;) { - Read* r = static_cast((*cell)->value); - if (r->valid()) { - result = true; - cell = &((*cell)->next); - } else { - *cell = (*cell)->next; - } - } - visited = false; - } - return result; - } - - virtual void append(Context* c, Read* r) { - Cell* cell = cons(c, r, 0); - if (lastRead == 0) { - reads = cell; - } else { - lastRead->next = cell; - } - lastRead = cell; - -// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this); - - lastTarget->value = r; - } - - virtual Read* next(Context* c) { - abort(c); - } - - void allocateTarget(Context* c) { - Cell* cell = cons(c, 0, 0); - -// fprintf(stderr, "allocate target for %p: %p\n", this, cell); - - if (lastTarget) { - lastTarget->next = cell; - } else { - firstTarget = cell; - } - lastTarget = cell; - } - - Read* nextTarget() { - // fprintf(stderr, "next target for %p: %p\n", this, firstTarget); - - Read* r = static_cast(firstTarget->value); - firstTarget = firstTarget->next; - return r; - } - - Cell* reads; - Cell* lastRead; - Cell* firstTarget; - Cell* lastTarget; - bool visited; -}; MultiRead* multiRead(Context* c) @@ -1473,49 +1040,6 @@ multiRead(Context* c) return new(c->zone) MultiRead; } -class StubRead: public Read { - public: - StubRead(): - next_(0), read(0), visited(false), valid_(true) - { } - - virtual bool intersect(SiteMask* mask, unsigned depth) { - if (not visited) { - visited = true; - if (read) { - bool valid = read->intersect(mask, depth); - if (not valid) { - read = 0; - } - } - visited = false; - } - return valid_; - } - - virtual Value* successor() { - return 0; - } - - virtual bool valid() { - return valid_; - } - - virtual void append(Context* c UNUSED, Read* r) { - assert(c, next_ == 0); - next_ = r; - } - - virtual Read* next(Context*) { - return next_; - } - - Read* next_; - Read* read; - bool visited; - bool valid_; -}; - StubRead* stubRead(Context* c) { @@ -2385,7 +1909,7 @@ pickMatchOrMove(Context* c, Read* r, Site* nextWord, unsigned index, } return pickSiteOrMove - (c, r->value, intersect(mask, nextWord->nextWordMask(c, index)), + (c, r->value, mask.intersectionWith(nextWord->nextWordMask(c, index)), true, true); } @@ -4257,9 +3781,8 @@ captureBranchSnapshots(Context* c, Event* e) e->snapshots = makeSnapshots(c, el.value, e->snapshots); } - for (Cell* sv = e->successors->forkState->saved; sv; sv = sv->next) { - e->snapshots = makeSnapshots - (c, static_cast(sv->value), e->snapshots); + for (Cell* sv = e->successors->forkState->saved; sv; sv = sv->next) { + e->snapshots = makeSnapshots(c, sv->value, e->snapshots); } if (DebugControl) { @@ -4577,9 +4100,8 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) } if (e->visitLinks) { - for (Cell* cell = reverseDestroy(e->visitLinks); cell; cell = cell->next) - { - visit(c, static_cast(cell->value)); + for (Cell* cell = reverseDestroy(e->visitLinks); cell; cell = cell->next) { + visit(c, cell->value); } e->visitLinks = 0; } @@ -4666,8 +4188,8 @@ saveState(Context* c) addForkElement(c, e.value, state, count++); } - for (Cell* sv = c->saved; sv; sv = sv->next) { - addForkElement(c, static_cast(sv->value), state, count++); + for (Cell* sv = c->saved; sv; sv = sv->next) { + addForkElement(c, sv->value, state, count++); } state->readCount = count; diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index 2605aaf64d..8508086978 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -22,7 +22,6 @@ namespace compiler { class Stack; class Local; -class Cell; class Event; class LogicalInstruction; @@ -36,6 +35,25 @@ class ForkState; class MySubroutine; class Block; +template +class Cell { + public: + Cell(Cell* next, T* value): next(next), value(value) { } + + Cell* next; + T* value; +}; + +template +unsigned count(Cell* c) { + unsigned count = 0; + while (c) { + ++ count; + c = c->next; + } + return count; +} + class Context { public: Context(vm::System* system, Assembler* assembler, vm::Zone* zone, @@ -48,7 +66,7 @@ class Context { Compiler::Client* client; Stack* stack; Local* locals; - Cell* saved; + Cell* saved; Event* predecessor; LogicalInstruction** logicalCode; const RegisterFile* regFile; @@ -78,6 +96,11 @@ inline Aborter* getAborter(Context* c) { return c->system; } +template +Cell* cons(Context* c, T* value, Cell* next) { + return new (c->zone) Cell(next, value); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/read.cpp b/src/codegen/compiler/read.cpp new file mode 100644 index 0000000000..08308cfa52 --- /dev/null +++ b/src/codegen/compiler/read.cpp @@ -0,0 +1,183 @@ +/* Copyright (c) 2008-2012, 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 "target.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/value.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/read.h" + +namespace avian { +namespace codegen { +namespace compiler { + + +SingleRead::SingleRead(const SiteMask& mask, Value* successor): + next_(0), mask(mask), high_(0), successor_(successor) +{ } + +bool SingleRead::intersect(SiteMask* mask, unsigned) { + *mask = mask->intersectionWith(this->mask); + + return true; +} + +Value* SingleRead::high(Context*) { + return high_; +} + +Value* SingleRead::successor() { + return successor_; +} + +bool SingleRead::valid() { + return true; +} + +void SingleRead::append(Context* c UNUSED, Read* r) { + assert(c, next_ == 0); + next_ = r; +} + +Read* SingleRead::next(Context*) { + return next_; +} + +MultiRead::MultiRead(): + reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false) +{ } + +bool MultiRead::intersect(SiteMask* mask, unsigned depth) { + if (depth > 0) { + // short-circuit recursion to avoid poor performance in + // deeply-nested branches + return reads != 0; + } + + bool result = false; + if (not visited) { + visited = true; + for (Cell** cell = &reads; *cell;) { + Read* r = (*cell)->value; + bool valid = r->intersect(mask, depth + 1); + if (valid) { + result = true; + cell = &((*cell)->next); + } else { + *cell = (*cell)->next; + } + } + visited = false; + } + return result; +} + +Value* MultiRead::successor() { + return 0; +} + +bool MultiRead::valid() { + bool result = false; + if (not visited) { + visited = true; + for (Cell** cell = &reads; *cell;) { + Read* r = (*cell)->value; + if (r->valid()) { + result = true; + cell = &((*cell)->next); + } else { + *cell = (*cell)->next; + } + } + visited = false; + } + return result; +} + +void MultiRead::append(Context* c, Read* r) { + Cell* cell = cons(c, r, 0); + if (lastRead == 0) { + reads = cell; + } else { + lastRead->next = cell; + } + lastRead = cell; + +// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this); + + lastTarget->value = r; +} + +Read* MultiRead::next(Context* c) { + abort(c); +} + +void MultiRead::allocateTarget(Context* c) { + Cell* cell = cons(c, 0, 0); + +// fprintf(stderr, "allocate target for %p: %p\n", this, cell); + + if (lastTarget) { + lastTarget->next = cell; + } else { + firstTarget = cell; + } + lastTarget = cell; +} + +Read* MultiRead::nextTarget() { + // fprintf(stderr, "next target for %p: %p\n", this, firstTarget); + + Read* r = firstTarget->value; + firstTarget = firstTarget->next; + return r; +} + + +StubRead::StubRead(): + next_(0), read(0), visited(false), valid_(true) +{ } + +bool StubRead::intersect(SiteMask* mask, unsigned depth) { + if (not visited) { + visited = true; + if (read) { + bool valid = read->intersect(mask, depth); + if (not valid) { + read = 0; + } + } + visited = false; + } + return valid_; +} + +Value* StubRead::successor() { + return 0; +} + +bool StubRead::valid() { + return valid_; +} + +void StubRead::append(Context* c UNUSED, Read* r) { + assert(c, next_ == 0); + next_ = r; +} + +Read* StubRead::next(Context*) { + return next_; +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/read.h b/src/codegen/compiler/read.h index a0c1d5a763..4e942ba75a 100644 --- a/src/codegen/compiler/read.h +++ b/src/codegen/compiler/read.h @@ -15,6 +15,11 @@ namespace avian { namespace codegen { namespace compiler { +class Context; +class SiteMask; +class Value; +class Event; + class Read { public: Read(): @@ -38,6 +43,74 @@ class Read { Read* eventNext; }; +class SingleRead: public Read { + public: + SingleRead(const SiteMask& mask, Value* successor); + + virtual bool intersect(SiteMask* mask, unsigned); + + virtual Value* high(Context*); + + virtual Value* successor(); + + virtual bool valid(); + + virtual void append(Context* c UNUSED, Read* r); + + virtual Read* next(Context*); + + Read* next_; + SiteMask mask; + Value* high_; + Value* successor_; +}; + + +class MultiRead: public Read { + public: + MultiRead(); + + virtual bool intersect(SiteMask* mask, unsigned depth); + + virtual Value* successor(); + + virtual bool valid(); + + virtual void append(Context* c, Read* r); + + virtual Read* next(Context* c); + + void allocateTarget(Context* c); + + Read* nextTarget(); + + Cell* reads; + Cell* lastRead; + Cell* firstTarget; + Cell* lastTarget; + bool visited; +}; + +class StubRead: public Read { + public: + StubRead(); + + virtual bool intersect(SiteMask* mask, unsigned depth); + + virtual Value* successor(); + + virtual bool valid(); + + virtual void append(Context* c UNUSED, Read* r); + + virtual Read* next(Context*); + + Read* next_; + Read* read; + bool visited; + bool valid_; +}; + } // namespace compiler } // namespace codegen diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp index 1534356674..43eb211112 100644 --- a/src/codegen/compiler/site.cpp +++ b/src/codegen/compiler/site.cpp @@ -20,8 +20,27 @@ namespace codegen { namespace compiler { +unsigned frameIndexToOffset(Context* c, unsigned frameIndex); + +unsigned offsetToFrameIndex(Context* c, unsigned offset); + ResolvedPromise* resolved(Context* c, int64_t value); + +int intersectFrameIndexes(int a, int b) { + if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex; + if (a == AnyFrameIndex) return b; + if (b == AnyFrameIndex) return a; + if (a == b) return a; + return NoFrameIndex; +} + + +SiteMask SiteMask::intersectionWith(const SiteMask& b) { + return SiteMask(typeMask & b.typeMask, registerMask & b.registerMask, + intersectFrameIndexes(frameIndex, b.frameIndex)); +} + SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies, bool includeNextWord): c(c), @@ -370,6 +389,238 @@ Site* freeRegisterSite(Context* c, uint32_t mask) { return new(c->zone) RegisterSite(mask, lir::NoRegister); } +MemorySite::MemorySite(int base, int offset, int index, unsigned scale): + acquired(false), base(base), offset(offset), index(index), scale(scale) +{ } + +unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize) { + if (acquired) { + return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d", + base, offset, index, scale); + } else { + return vm::snprintf(buffer, bufferSize, "memory unacquired"); + } +} + +unsigned MemorySite::copyCost(Context* c, Site* s) { + assert(c, acquired); + + if (s and + (this == s or + (s->type(c) == lir::MemoryOperand + and static_cast(s)->base == base + and static_cast(s)->offset == offset + and static_cast(s)->index == index + and static_cast(s)->scale == scale))) + { + return 0; + } else { + return MemoryCopyCost; + } +} + +bool MemorySite::conflicts(const SiteMask& mask) { + return (mask.typeMask & (1 << lir::RegisterOperand)) != 0 + and (((1 << base) & mask.registerMask) == 0 + or (index != lir::NoRegister + and ((1 << index) & mask.registerMask) == 0)); +} + +bool MemorySite::match(Context* c, const SiteMask& mask) { + assert(c, acquired); + + if (mask.typeMask & (1 << lir::MemoryOperand)) { + if (mask.frameIndex >= 0) { + if (base == c->arch->stack()) { + assert(c, index == lir::NoRegister); + return static_cast(frameIndexToOffset(c, mask.frameIndex)) + == offset; + } else { + return false; + } + } else { + return true; + } + } else { + return false; + } +} + +bool MemorySite::loneMatch(Context* c, const SiteMask& mask) { + assert(c, acquired); + + if (mask.typeMask & (1 << lir::MemoryOperand)) { + if (base == c->arch->stack()) { + assert(c, index == lir::NoRegister); + + if (mask.frameIndex == AnyFrameIndex) { + return false; + } else { + return true; + } + } + } + return false; +} + +bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) { + if (s->type(c) == lir::MemoryOperand) { + MemorySite* ms = static_cast(s); + return ms->base == this->base + and ((index == 1 and ms->offset == static_cast + (this->offset + vm::TargetBytesPerWord)) + or (index == 0 and this->offset == static_cast + (ms->offset + vm::TargetBytesPerWord))) + and ms->index == this->index + and ms->scale == this->scale; + } else { + return false; + } +} + +void MemorySite::acquire(Context* c, Value* v) { + c->registerResources[base].increment(c); + if (index != lir::NoRegister) { + c->registerResources[index].increment(c); + } + + if (base == c->arch->stack()) { + assert(c, index == lir::NoRegister); + assert + (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); + + compiler::acquire + (c, c->frameResources + offsetToFrameIndex(c, offset), v, this); + } + + acquired = true; +} + +void MemorySite::release(Context* c, Value* v) { + if (base == c->arch->stack()) { + assert(c, index == lir::NoRegister); + assert + (c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); + + compiler::release + (c, c->frameResources + offsetToFrameIndex(c, offset), v, this); + } + + c->registerResources[base].decrement(c); + if (index != lir::NoRegister) { + c->registerResources[index].decrement(c); + } + + acquired = false; +} + +void MemorySite::freeze(Context* c, Value* v) { + if (base == c->arch->stack()) { + c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v); + } else { + c->registerResources[base].increment(c); + if (index != lir::NoRegister) { + c->registerResources[index].increment(c); + } + } +} + +void MemorySite::thaw(Context* c, Value* v) { + if (base == c->arch->stack()) { + c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v); + } else { + c->registerResources[base].decrement(c); + if (index != lir::NoRegister) { + c->registerResources[index].decrement(c); + } + } +} + +bool MemorySite::frozen(Context* c) { + return base == c->arch->stack() + and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0; +} + +lir::OperandType MemorySite::type(Context*) { + return lir::MemoryOperand; +} + +void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, + lir::Operand* result) +{ + // todo: endianness? + assert(c, high == this + or (static_cast(high)->base == base + and static_cast(high)->offset + == static_cast(offset + vm::TargetBytesPerWord) + and static_cast(high)->index == index + and static_cast(high)->scale == scale)); + + assert(c, acquired); + + new (result) lir::Memory(base, offset, index, scale); +} + +Site* MemorySite::copy(Context* c) { + return memorySite(c, base, offset, index, scale); +} + +Site* MemorySite::copyHalf(Context* c, bool add) { + if (add) { + return memorySite(c, base, offset + vm::TargetBytesPerWord, index, scale); + } else { + return copy(c); + } +} + +Site* MemorySite::copyLow(Context* c) { + return copyHalf(c, c->arch->bigEndian()); +} + +Site* MemorySite::copyHigh(Context* c) { + return copyHalf(c, not c->arch->bigEndian()); +} + +Site* MemorySite::makeNextWord(Context* c, unsigned index) { + return memorySite + (c, base, offset + ((index == 1) xor c->arch->bigEndian() + ? vm::TargetBytesPerWord : -vm::TargetBytesPerWord), + this->index, scale); +} + +SiteMask MemorySite::mask(Context* c) { + return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack()) + ? static_cast(offsetToFrameIndex(c, offset)) + : NoFrameIndex); +} + +SiteMask MemorySite::nextWordMask(Context* c, unsigned index) { + int frameIndex; + if (base == c->arch->stack()) { + assert(c, this->index == lir::NoRegister); + frameIndex = static_cast(offsetToFrameIndex(c, offset)) + + ((index == 1) xor c->arch->bigEndian() ? 1 : -1); + } else { + frameIndex = NoFrameIndex; + } + return SiteMask(1 << lir::MemoryOperand, 0, frameIndex); +} + +bool MemorySite::isVolatile(Context* c) { + return base != c->arch->stack(); +} + + +MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) { + return new(c->zone) MemorySite(base, offset, index, scale); +} + +MemorySite* frameSite(Context* c, int frameIndex) { + assert(c, frameIndex >= 0); + return memorySite + (c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0); +} + } // namespace compiler } // namespace codegen -} // namespace avian \ No newline at end of file +} // namespace avian diff --git a/src/codegen/compiler/site.h b/src/codegen/compiler/site.h index 0d32b263a2..6f5508be91 100644 --- a/src/codegen/compiler/site.h +++ b/src/codegen/compiler/site.h @@ -34,6 +34,8 @@ class SiteMask { typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex) { } + SiteMask intersectionWith(const SiteMask& b); + uint8_t typeMask; uint32_t registerMask; int frameIndex; @@ -240,6 +242,64 @@ class RegisterSite: public Site { Site* registerSite(Context* c, int number); Site* freeRegisterSite(Context* c, uint32_t mask); + +class MemorySite: public Site { + public: + MemorySite(int base, int offset, int index, unsigned scale); + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize); + + virtual unsigned copyCost(Context* c, Site* s); + + bool conflicts(const SiteMask& mask); + + virtual bool match(Context* c, const SiteMask& mask); + + virtual bool loneMatch(Context* c, const SiteMask& mask); + + virtual bool matchNextWord(Context* c, Site* s, unsigned index); + + virtual void acquire(Context* c, Value* v); + + virtual void release(Context* c, Value* v); + + virtual void freeze(Context* c, Value* v); + + virtual void thaw(Context* c, Value* v); + + virtual bool frozen(Context* c); + + virtual lir::OperandType type(Context*); + + virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, + lir::Operand* result); + + virtual Site* copy(Context* c); + + Site* copyHalf(Context* c, bool add); + + virtual Site* copyLow(Context* c); + + virtual Site* copyHigh(Context* c); + + virtual Site* makeNextWord(Context* c, unsigned index); + + virtual SiteMask mask(Context* c); + + virtual SiteMask nextWordMask(Context* c, unsigned index); + + virtual bool isVolatile(Context* c); + + bool acquired; + int base; + int offset; + int index; + unsigned scale; +}; + +MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1); +MemorySite* frameSite(Context* c, int frameIndex); + } // namespace compiler } // namespace codegen } // namespace avian From 0f6e098b6929e1701bcba80a585e73aef7e0bcb6 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 19:33:40 -0700 Subject: [PATCH 220/378] move CallEvent out of compiler.cpp --- makefile | 2 + src/codegen/compiler.cpp | 587 +++---------------------------- src/codegen/compiler/event.cpp | 446 +++++++++++++++++++++++ src/codegen/compiler/event.h | 85 +++++ src/codegen/compiler/promise.cpp | 26 ++ src/codegen/compiler/promise.h | 52 +++ src/codegen/compiler/read.cpp | 8 + src/codegen/compiler/read.h | 2 + src/codegen/compiler/site.cpp | 6 + src/codegen/compiler/site.h | 6 +- src/codegen/compiler/stack.h | 35 ++ src/codegen/compiler/value.cpp | 12 + src/codegen/compiler/value.h | 4 + 13 files changed, 732 insertions(+), 539 deletions(-) create mode 100644 src/codegen/compiler/event.cpp create mode 100644 src/codegen/compiler/event.h create mode 100644 src/codegen/compiler/promise.cpp create mode 100644 src/codegen/compiler/promise.h create mode 100644 src/codegen/compiler/stack.h diff --git a/makefile b/makefile index f094576f32..5e14ad1d7e 100755 --- a/makefile +++ b/makefile @@ -959,6 +959,8 @@ ifeq ($(process),compile) $(src)/codegen/compiler/regalloc.cpp \ $(src)/codegen/compiler/value.cpp \ $(src)/codegen/compiler/read.cpp \ + $(src)/codegen/compiler/event.cpp \ + $(src)/codegen/compiler/promise.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 5e7a06b927..ca6ee5ba23 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -21,6 +21,9 @@ #include "codegen/compiler/value.h" #include "codegen/compiler/site.h" #include "codegen/compiler/read.h" +#include "codegen/compiler/event.h" +#include "codegen/compiler/stack.h" +#include "codegen/compiler/promise.h" using namespace vm; @@ -33,8 +36,6 @@ const bool DebugCompile = false; const bool DebugResources = false; const bool DebugFrame = false; const bool DebugControl = false; -const bool DebugReads = false; -const bool DebugSites = false; const bool DebugMoves = false; const bool DebugBuddies = false; @@ -45,7 +46,6 @@ const unsigned StealRegisterReserveCount = 2; const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4); class Stack; -class Event; class PushEvent; class Read; class MultiRead; @@ -73,17 +73,6 @@ class Local { Value* value; }; -class Stack { - public: - Stack(unsigned index, Value* value, Stack* next): - index(index), value(value), next(next) - { } - - unsigned index; - Value* value; - Stack* next; -}; - class ForkElement { public: Value* value; @@ -166,33 +155,6 @@ class PoolPromise: public Promise { int key; }; -class CodePromise: public Promise { - public: - CodePromise(Context* c, CodePromise* next): - c(c), offset(0), next(next) - { } - - CodePromise(Context* c, Promise* offset): - c(c), offset(offset), next(0) - { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast(c->machineCode + offset->value()); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0 and offset and offset->resolved(); - } - - Context* c; - Promise* offset; - CodePromise* next; -}; - unsigned machineOffset(Context* c, int logicalIp) { @@ -298,43 +260,6 @@ countSuccessors(Link* link) return c; } -class Event { - public: - Event(Context* c): - next(0), stackBefore(c->stack), localsBefore(c->locals), - stackAfter(0), localsAfter(0), promises(0), reads(0), - junctionSites(0), snapshots(0), predecessors(0), successors(0), - visitLinks(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]), - readCount(0) - { } - - virtual const char* name() = 0; - - virtual void compile(Context* c) = 0; - - virtual bool isBranch() { return false; } - - virtual bool allExits() { return false; } - - virtual Local* locals() { return localsBefore; } - - Event* next; - Stack* stackBefore; - Local* localsBefore; - Stack* stackAfter; - Local* localsAfter; - CodePromise* promises; - Read* reads; - Site** junctionSites; - Snapshot* snapshots; - Link* predecessors; - Link* successors; - Cell* visitLinks; - Block* block; - LogicalInstruction* logicalInstruction; - unsigned readCount; -}; - unsigned totalFrameSize(Context* c) { @@ -479,20 +404,6 @@ uniqueSite(Context* c, Value* v, Site* s) } } -void -addSite(Context* c, Value* v, Site* s) -{ - if (not v->findSite(s)) { - if (DebugSites) { - char buffer[256]; s->toString(c, buffer, 256); - fprintf(stderr, "add site %s to %p\n", buffer, v); - } - s->acquire(c, v); - s->next = v->sites; - v->sites = s; - } -} - void removeSite(Context* c, Value* v, Site* s) { @@ -598,7 +509,7 @@ deadWord(Context* c, Value* v) if (s->registerSize(c) > TargetBytesPerWord) { it.remove(c); - addSite(c, nextWord, s); + nextWord->addSite(c, s); } } } @@ -631,7 +542,7 @@ deadBuddy(Context* c, Value* v, Read* r UNUSED) Site* s = it.next(); it.remove(c); - addSite(c, next, s); + next->addSite(c, s); } } @@ -777,14 +688,6 @@ pickTargetSite(Context* c, Read* read, bool intersectRead = false, } } -SingleRead* -read(Context* c, const SiteMask& mask, Value* successor = 0) -{ - assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0); - - return new(c->zone) SingleRead(mask, successor); -} - bool acceptMatch(Context* c, Site* s, Read*, const SiteMask& mask) { @@ -919,7 +822,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, src->freeze(c, value); - addSite(c, value, dst); + value->addSite(c, dst); src->thaw(c, value); @@ -934,7 +837,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, Site* tmp = pickTargetSite(c, &tmpRead, true); - addSite(c, value, tmp); + value->addSite(c, tmp); move(c, value, src, tmp); @@ -1027,13 +930,6 @@ generalRegisterOrConstantMask(Context* c) c->regFile->generalRegisters.mask, NoFrameIndex); } -SiteMask -fixedRegisterMask(int number) -{ - return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex); -} - - MultiRead* multiRead(Context* c) { @@ -1093,7 +989,7 @@ pickSiteOrGrow(Context* c, Value* v, Site* s, unsigned index) } n = s->makeNextWord(c, index); - addSite(c, v, n); + v->addSite(c, n); return n; } @@ -1260,61 +1156,6 @@ apply(Context* c, lir::TernaryOperation op, OperandInfo(s3Size, s3Type, &s3Union)); } -void -addRead(Context* c, Event* e, Value* v, Read* r) -{ - if (DebugReads) { - fprintf(stderr, "add read %p to %p last %p event %p (%s)\n", - r, v, v->lastRead, e, (e ? e->name() : 0)); - } - - r->value = v; - if (e) { - r->event = e; - r->eventNext = e->reads; - e->reads = r; - ++ e->readCount; - } - - if (v->lastRead) { - // if (DebugReads) { - // fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v); - // } - - v->lastRead->append(c, r); - } else { - v->reads = r; - } - v->lastRead = r; -} - -void -addRead(Context* c, Event* e, Value* v, const SiteMask& mask, - Value* successor = 0) -{ - addRead(c, e, v, read(c, mask, successor)); -} - -void -addReads(Context* c, Event* e, Value* v, unsigned size, - const SiteMask& lowMask, Value* lowSuccessor, - const SiteMask& highMask, Value* highSuccessor) -{ - SingleRead* r = read(c, lowMask, lowSuccessor); - addRead(c, e, v, r); - if (size > TargetBytesPerWord) { - r->high_ = v->nextWord; - addRead(c, e, v->nextWord, highMask, highSuccessor); - } -} - -void -addReads(Context* c, Event* e, Value* v, unsigned size, - const SiteMask& lowMask, const SiteMask& highMask) -{ - addReads(c, e, v, size, lowMask, 0, highMask, 0); -} - void clean(Context* c, Value* v, unsigned popIndex) { @@ -1353,18 +1194,6 @@ clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, } } -CodePromise* -codePromise(Context* c, Event* e) -{ - return e->promises = new(c->zone) CodePromise(c, e->promises); -} - -CodePromise* -codePromise(Context* c, Promise* offset) -{ - return new (c->zone) CodePromise(c, offset); -} - void append(Context* c, Event* e); @@ -1379,333 +1208,12 @@ saveLocals(Context* c, Event* e) local->value, compiler::frameIndex(c, li), totalFrameSize(c)); } - addRead(c, e, local->value, SiteMask + e->addRead(c, local->value, SiteMask (1 << lir::MemoryOperand, 0, compiler::frameIndex(c, li))); } } } -class CallEvent: public Event { - public: - CallEvent(Context* c, Value* address, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned resultSize, - Stack* argumentStack, unsigned argumentCount, - unsigned stackArgumentFootprint): - Event(c), - address(address), - traceHandler(traceHandler), - result(result), - returnAddressSurrogate(0), - framePointerSurrogate(0), - popIndex(0), - stackArgumentIndex(0), - flags(flags), - resultSize(resultSize), - stackArgumentFootprint(stackArgumentFootprint) - { - uint32_t registerMask = c->regFile->generalRegisters.mask; - - if (argumentCount) { - assert(c, (flags & Compiler::TailJump) == 0); - assert(c, stackArgumentFootprint == 0); - - Stack* s = argumentStack; - unsigned index = 0; - unsigned argumentIndex = 0; - - while (true) { - unsigned footprint - = (argumentIndex + 1 < argumentCount - and s->value->nextWord == s->next->value) - ? 2 : 1; - - if (index % (c->arch->argumentAlignment() ? footprint : 1)) { - ++ index; - } - - SiteMask targetMask; - if (index + (c->arch->argumentRegisterAlignment() ? footprint : 1) - <= c->arch->argumentRegisterCount()) - { - int number = c->arch->argumentRegister(index); - - if (DebugReads) { - fprintf(stderr, "reg %d arg read %p\n", number, s->value); - } - - targetMask = fixedRegisterMask(number); - registerMask &= ~(1 << number); - } else { - if (index < c->arch->argumentRegisterCount()) { - index = c->arch->argumentRegisterCount(); - } - - unsigned frameIndex = index - c->arch->argumentRegisterCount(); - - if (DebugReads) { - fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value); - } - - targetMask = SiteMask(1 << lir::MemoryOperand, 0, frameIndex); - } - - addRead(c, this, s->value, targetMask); - - ++ index; - - if ((++ argumentIndex) < argumentCount) { - s = s->next; - } else { - break; - } - } - } - - if (DebugReads) { - fprintf(stderr, "address read %p\n", address); - } - - { bool thunk; - uint8_t typeMask; - uint64_t planRegisterMask; - c->arch->plan - ((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, TargetBytesPerWord, - &typeMask, &planRegisterMask, &thunk); - - assert(c, not thunk); - - addRead(c, this, address, SiteMask - (typeMask, registerMask & planRegisterMask, AnyFrameIndex)); - } - - Stack* stack = stackBefore; - - if (stackArgumentFootprint) { - RUNTIME_ARRAY(Value*, arguments, stackArgumentFootprint); - for (int i = stackArgumentFootprint - 1; i >= 0; --i) { - Value* v = stack->value; - stack = stack->next; - - if ((TargetBytesPerWord == 8 - and (v == 0 or (i >= 1 and stack->value == 0))) - or (TargetBytesPerWord == 4 and v->nextWord != v)) - { - assert(c, TargetBytesPerWord == 8 or v->nextWord == stack->value); - - RUNTIME_ARRAY_BODY(arguments)[i--] = stack->value; - stack = stack->next; - } - RUNTIME_ARRAY_BODY(arguments)[i] = v; - } - - int returnAddressIndex; - int framePointerIndex; - int frameOffset; - - if (TailCalls and (flags & Compiler::TailJump)) { - assert(c, argumentCount == 0); - - int base = frameBase(c); - returnAddressIndex = base + c->arch->returnAddressOffset(); - if (UseFramePointer) { - framePointerIndex = base + c->arch->framePointerOffset(); - } else { - framePointerIndex = -1; - } - - frameOffset = totalFrameSize(c) - - c->arch->argumentFootprint(stackArgumentFootprint); - } else { - returnAddressIndex = -1; - framePointerIndex = -1; - frameOffset = 0; - } - - for (unsigned i = 0; i < stackArgumentFootprint; ++i) { - Value* v = RUNTIME_ARRAY_BODY(arguments)[i]; - if (v) { - int frameIndex = i + frameOffset; - - if (DebugReads) { - fprintf(stderr, "stack arg read %p at %d of %d\n", - v, frameIndex, totalFrameSize(c)); - } - - if (static_cast(frameIndex) == returnAddressIndex) { - returnAddressSurrogate = v; - addRead(c, this, v, generalRegisterMask(c)); - } else if (static_cast(frameIndex) == framePointerIndex) { - framePointerSurrogate = v; - addRead(c, this, v, generalRegisterMask(c)); - } else { - addRead(c, this, v, SiteMask(1 << lir::MemoryOperand, 0, frameIndex)); - } - } - } - } - - if ((not TailCalls) or (flags & Compiler::TailJump) == 0) { - stackArgumentIndex = c->localFootprint; - if (stackBefore) { - stackArgumentIndex += stackBefore->index + 1 - stackArgumentFootprint; - } - - popIndex - = c->alignedFrameSize - + c->parameterFootprint - - c->arch->frameFooterSize() - - stackArgumentIndex; - - assert(c, static_cast(popIndex) >= 0); - - while (stack) { - if (stack->value) { - unsigned logicalIndex = compiler::frameIndex - (c, stack->index + c->localFootprint); - - if (DebugReads) { - fprintf(stderr, "stack save read %p at %d of %d\n", - stack->value, logicalIndex, totalFrameSize(c)); - } - - addRead(c, this, stack->value, SiteMask - (1 << lir::MemoryOperand, 0, logicalIndex)); - } - - stack = stack->next; - } - - saveLocals(c, this); - } - } - - virtual const char* name() { - return "CallEvent"; - } - - virtual void compile(Context* c) { - lir::UnaryOperation op; - - if (TailCalls and (flags & Compiler::TailJump)) { - if (flags & Compiler::LongJumpOrCall) { - if (flags & Compiler::Aligned) { - op = lir::AlignedLongJump; - } else { - op = lir::LongJump; - } - } else if (flags & Compiler::Aligned) { - op = lir::AlignedJump; - } else { - op = lir::Jump; - } - - assert(c, returnAddressSurrogate == 0 - or returnAddressSurrogate->source->type(c) == lir::RegisterOperand); - assert(c, framePointerSurrogate == 0 - or framePointerSurrogate->source->type(c) == lir::RegisterOperand); - - int ras; - if (returnAddressSurrogate) { - returnAddressSurrogate->source->freeze(c, returnAddressSurrogate); - - ras = static_cast - (returnAddressSurrogate->source)->number; - } else { - ras = lir::NoRegister; - } - - int fps; - if (framePointerSurrogate) { - framePointerSurrogate->source->freeze(c, framePointerSurrogate); - - fps = static_cast - (framePointerSurrogate->source)->number; - } else { - fps = lir::NoRegister; - } - - int offset - = static_cast(c->arch->argumentFootprint(stackArgumentFootprint)) - - static_cast(c->arch->argumentFootprint(c->parameterFootprint)); - - c->assembler->popFrameForTailCall(c->alignedFrameSize, offset, ras, fps); - } else if (flags & Compiler::LongJumpOrCall) { - if (flags & Compiler::Aligned) { - op = lir::AlignedLongCall; - } else { - op = lir::LongCall; - } - } else if (flags & Compiler::Aligned) { - op = lir::AlignedCall; - } else { - op = lir::Call; - } - - apply(c, op, TargetBytesPerWord, address->source, address->source); - - if (traceHandler) { - traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)), - stackArgumentIndex); - } - - if (TailCalls) { - if (flags & Compiler::TailJump) { - if (returnAddressSurrogate) { - returnAddressSurrogate->source->thaw(c, returnAddressSurrogate); - } - - if (framePointerSurrogate) { - framePointerSurrogate->source->thaw(c, framePointerSurrogate); - } - } else { - unsigned footprint = c->arch->argumentFootprint - (stackArgumentFootprint); - - if (footprint > c->arch->stackAlignmentInWords()) { - c->assembler->adjustFrame - (footprint - c->arch->stackAlignmentInWords()); - } - } - } - - clean(c, this, stackBefore, localsBefore, reads, popIndex); - - if (resultSize and live(c, result)) { - addSite(c, result, registerSite(c, c->arch->returnLow())); - if (resultSize > TargetBytesPerWord and live(c, result->nextWord)) { - addSite(c, result->nextWord, registerSite(c, c->arch->returnHigh())); - } - } - } - - virtual bool allExits() { - return (flags & Compiler::TailJump) != 0; - } - - Value* address; - TraceHandler* traceHandler; - Value* result; - Value* returnAddressSurrogate; - Value* framePointerSurrogate; - unsigned popIndex; - unsigned stackArgumentIndex; - unsigned flags; - unsigned resultSize; - unsigned stackArgumentFootprint; -}; - -void -appendCall(Context* c, Value* address, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned resultSize, - Stack* argumentStack, unsigned argumentCount, - unsigned stackArgumentFootprint) -{ - append(c, new(c->zone) - CallEvent(c, address, flags, traceHandler, result, - resultSize, argumentStack, argumentCount, - stackArgumentFootprint)); -} - bool unreachable(Event* event) { @@ -1721,8 +1229,9 @@ class ReturnEvent: public Event { Event(c), value(value) { if (value) { - addReads(c, this, value, size, fixedRegisterMask(c->arch->returnLow()), - fixedRegisterMask(c->arch->returnHigh())); + this->addReads(c, value, size, + SiteMask::fixedRegisterMask(c->arch->returnLow()), + SiteMask::fixedRegisterMask(c->arch->returnHigh())); } } @@ -1781,7 +1290,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, src->source->freeze(c, src); - addSite(c, dst, target); + dst->addSite(c, target); src->source->thaw(c, src); @@ -1835,7 +1344,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, src->source->freeze(c, src); - addSite(c, dst, tmpTarget); + dst->addSite(c, tmpTarget); tmpTarget->freeze(c, dst); @@ -1861,7 +1370,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, srcb, dstb, src, dst); } - addSite(c, dst, target); + dst->addSite(c, target); tmpTarget->freeze(c, dst); @@ -1968,8 +1477,8 @@ split(Context* c, Value* v) Site* s = it.next(); removeSite(c, v, s); - addSite(c, v, s->copyLow(c)); - addSite(c, v->nextWord, s->copyHigh(c)); + v->addSite(c, s->copyLow(c)); + v->nextWord->addSite(c, s->copyHigh(c)); } } @@ -2001,7 +1510,7 @@ class MoveEvent: public Event { maybeSplit(c, src); } - addReads(c, this, src, srcSelectSize, srcLowMask, noop ? dst : 0, + this->addReads(c, src, srcSelectSize, srcLowMask, noop ? dst : 0, srcHighMask, noop and dstSize > TargetBytesPerWord ? dst->nextWord : 0); } @@ -2081,7 +1590,7 @@ class MoveEvent: public Event { src->source->freeze(c, src); - addSite(c, dst, low); + dst->addSite(c, low); low->freeze(c, dst); @@ -2105,7 +1614,7 @@ class MoveEvent: public Event { low->freeze(c, dst); - addSite(c, dst->nextWord, high); + dst->nextWord->addSite(c, high); high->freeze(c, dst->nextWord); @@ -2203,7 +1712,7 @@ getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask) r.successor_ = result; s = pickTargetSite(c, &r, true); v = result; - addSite(c, result, s); + result->addSite(c, s); } removeSite(c, v, s); @@ -2245,7 +1754,7 @@ class CombineEvent: public Event { secondSize(secondSize), second(second), resultSize(resultSize), result(result) { - addReads(c, this, first, firstSize, firstLowMask, firstHighMask); + this->addReads(c, first, firstSize, firstLowMask, firstHighMask); if (resultSize > TargetBytesPerWord) { grow(c, result); @@ -2253,7 +1762,7 @@ class CombineEvent: public Event { bool condensed = c->arch->alwaysCondensed(type); - addReads(c, this, second, secondSize, + this->addReads(c, second, secondSize, secondLowMask, condensed ? result : 0, secondHighMask, condensed ? result->nextWord : 0); } @@ -2325,9 +1834,9 @@ class CombineEvent: public Event { } if (live(c, result)) { - addSite(c, result, low); + result->addSite(c, low); if (resultSize > lowSize and live(c, result->nextWord)) { - addSite(c, result->nextWord, high); + result->nextWord->addSite(c, high); } } } @@ -2715,7 +2224,7 @@ class TranslateEvent: public Event { grow(c, result); } - addReads(c, this, value, valueSize, valueLowMask, condensed ? result : 0, + this->addReads(c, value, valueSize, valueLowMask, condensed ? result : 0, valueHighMask, condensed ? result->nextWord : 0); } @@ -2762,9 +2271,9 @@ class TranslateEvent: public Event { } if (live(c, result)) { - addSite(c, result, low); + result->addSite(c, low); if (resultSize > lowSize and live(c, result->nextWord)) { - addSite(c, result->nextWord, high); + result->nextWord->addSite(c, high); } } } @@ -2856,9 +2365,9 @@ class MemoryEvent: public Event { Event(c), base(base), displacement(displacement), index(index), scale(scale), result(result) { - addRead(c, this, base, generalRegisterMask(c)); + this->addRead(c, base, generalRegisterMask(c)); if (index) { - addRead(c, this, index, generalRegisterOrConstantMask(c)); + this->addRead(c, index, generalRegisterOrConstantMask(c)); } } @@ -2906,14 +2415,14 @@ class MemoryEvent: public Event { low = static_cast(site->copyLow(c)); result->nextWord->target = high; - addSite(c, result->nextWord, high); + result->nextWord->addSite(c, high); moveIfConflict(c, result->nextWord, high); } else { low = site; } result->target = low; - addSite(c, result, low); + result->addSite(c, low); moveIfConflict(c, result, low); } @@ -3052,15 +2561,15 @@ class BranchEvent: public Event { Event(c), type(type), size(size), first(first), second(second), address(address) { - addReads(c, this, first, size, firstLowMask, firstHighMask); - addReads(c, this, second, size, secondLowMask, secondHighMask); + this->addReads(c, first, size, firstLowMask, firstHighMask); + this->addReads(c, second, size, secondLowMask, secondHighMask); uint8_t typeMask; uint64_t registerMask; c->arch->planDestination(type, size, 0, 0, size, 0, 0, TargetBytesPerWord, &typeMask, ®isterMask); - addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); } virtual const char* name() { @@ -3183,7 +2692,7 @@ class JumpEvent: public Event { assert(c, not thunk); - addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); } virtual const char* name() { @@ -3233,8 +2742,8 @@ class BoundsCheckEvent: public Event { Event(c), object(object), lengthOffset(lengthOffset), index(index), handler(handler) { - addRead(c, this, object, generalRegisterMask(c)); - addRead(c, this, index, generalRegisterOrConstantMask(c)); + this->addRead(c, object, generalRegisterMask(c)); + this->addRead(c, index, generalRegisterOrConstantMask(c)); } virtual const char* name() { @@ -3254,7 +2763,7 @@ class BoundsCheckEvent: public Event { OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); } } else { - outOfBoundsPromise = codePromise(c, static_cast(0)); + outOfBoundsPromise = compiler::codePromise(c, static_cast(0)); ConstantSite zero(resolved(c, 0)); ConstantSite oob(outOfBoundsPromise); @@ -3270,7 +2779,7 @@ class BoundsCheckEvent: public Event { lengthOffset, lir::NoRegister, 1); length.acquired = true; - CodePromise* nextPromise = codePromise(c, static_cast(0)); + CodePromise* nextPromise = compiler::codePromise(c, static_cast(0)); freezeSource(c, TargetBytesPerWord, index); @@ -3322,7 +2831,7 @@ class FrameSiteEvent: public Event { virtual void compile(Context* c) { if (live(c, value)) { - addSite(c, value, frameSite(c, index)); + value->addSite(c, frameSite(c, index)); } } @@ -3382,7 +2891,7 @@ class BuddyEvent: public Event { BuddyEvent(Context* c, Value* original, Value* buddy): Event(c), original(original), buddy(buddy) { - addRead(c, this, original, SiteMask(~0, ~0, AnyFrameIndex), buddy); + this->addRead(c, original, SiteMask(~0, ~0, AnyFrameIndex), buddy); } virtual const char* name() { @@ -3655,7 +3164,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, } Value dummy(0, 0, lir::ValueGeneral); - addSite(c, &dummy, s); + dummy.addSite(c, s); removeSite(c, &dummy, s); freeze(c, frozen, s, 0); } @@ -3806,7 +3315,7 @@ setSites(Context* c, Value* v, Site* s) assert(c, live(c, v)); for (; s; s = s->next) { - addSite(c, v, s->copy(c)); + v->addSite(c, s->copy(c)); } if (DebugControl) { @@ -3924,7 +3433,8 @@ setStubRead(Context* c, StubReadPair* p, Value* v) if (DebugReads) { fprintf(stderr, "add stub read %p to %p\n", r, v); } - addRead(c, 0, v, r); + // TODO: this is rather icky looking... but despite how it looks, it will not cause an NPE + ((Event*)0)->addRead(c, v, r); p->value = v; p->read = r; @@ -4157,7 +3667,8 @@ addForkElement(Context* c, Value* v, ForkState* state, unsigned index) if (DebugReads) { fprintf(stderr, "add multi read %p to %p\n", r, v); } - addRead(c, 0, v, r); + // TODO: this is rather icky looking... but despite how it looks, it will not cause an NPE + ((Event*)0)->addRead(c, v, r); ForkElement* p = state->elements + index; p->value = v; @@ -4500,7 +4011,7 @@ class MyCompiler: public Compiler { } Promise* machineIp() { - return codePromise(&c, c.logicalCode[c.logicalIp]->lastEvent); + return c.logicalCode[c.logicalIp]->lastEvent->makeCodePromise(&c); } virtual void push(unsigned footprint UNUSED) { diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp new file mode 100644 index 0000000000..9b4fee04e1 --- /dev/null +++ b/src/codegen/compiler/event.cpp @@ -0,0 +1,446 @@ +/* Copyright (c) 2008-2012, 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 "target.h" +#include "util/runtime-array.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/event.h" +#include "codegen/compiler/stack.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/read.h" +#include "codegen/compiler/value.h" +#include "codegen/compiler/promise.h" + +namespace avian { +namespace codegen { +namespace compiler { + + +unsigned frameBase(Context* c); +unsigned totalFrameSize(Context* c); +int frameIndex(Context* c, int localIndex); + +SiteMask generalRegisterMask(Context* c); +SiteMask generalRegisterOrConstantMask(Context* c); + +CodePromise* codePromise(Context* c, Promise* offset); + +void saveLocals(Context* c, Event* e); + +void +apply(Context* c, lir::UnaryOperation op, + unsigned s1Size, Site* s1Low, Site* s1High); + +void +apply(Context* c, lir::BinaryOperation op, + unsigned s1Size, Site* s1Low, Site* s1High, + unsigned s2Size, Site* s2Low, Site* s2High); + +void +apply(Context* c, lir::TernaryOperation op, + unsigned s1Size, Site* s1Low, Site* s1High, + unsigned s2Size, Site* s2Low, Site* s2High, + unsigned s3Size, Site* s3Low, Site* s3High); + + +void append(Context* c, Event* e); + + +void clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, + unsigned popIndex); + +Read* live(Context* c UNUSED, Value* v); + +Event::Event(Context* c): + next(0), stackBefore(c->stack), localsBefore(c->locals), + stackAfter(0), localsAfter(0), promises(0), reads(0), + junctionSites(0), snapshots(0), predecessors(0), successors(0), + visitLinks(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]), + readCount(0) +{ } + +void Event::addRead(Context* c, Value* v, Read* r) { + if (DebugReads) { + fprintf(stderr, "add read %p to %p last %p event %p (%s)\n", + r, v, v->lastRead, this, (this ? this->name() : 0)); + } + + r->value = v; + if (this) { + r->event = this; + r->eventNext = this->reads; + this->reads = r; + ++ this->readCount; + } + + if (v->lastRead) { + // if (DebugReads) { + // fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v); + // } + + v->lastRead->append(c, r); + } else { + v->reads = r; + } + v->lastRead = r; +} + +void Event::addRead(Context* c, Value* v, const SiteMask& mask, Value* successor) { + this->addRead(c, v, read(c, mask, successor)); +} + +void Event::addReads(Context* c, Value* v, unsigned size, + const SiteMask& lowMask, Value* lowSuccessor, + const SiteMask& highMask, Value* highSuccessor) +{ + SingleRead* r = read(c, lowMask, lowSuccessor); + this->addRead(c, v, r); + if (size > vm::TargetBytesPerWord) { + r->high_ = v->nextWord; + this->addRead(c, v->nextWord, highMask, highSuccessor); + } +} + +void Event::addReads(Context* c, Value* v, unsigned size, + const SiteMask& lowMask, const SiteMask& highMask) +{ + this->addReads(c, v, size, lowMask, 0, highMask, 0); +} + +CodePromise* Event::makeCodePromise(Context* c) { + return this->promises = new(c->zone) CodePromise(c, this->promises); +} + + +class CallEvent: public Event { + public: + CallEvent(Context* c, Value* address, unsigned flags, + TraceHandler* traceHandler, Value* result, unsigned resultSize, + Stack* argumentStack, unsigned argumentCount, + unsigned stackArgumentFootprint): + Event(c), + address(address), + traceHandler(traceHandler), + result(result), + returnAddressSurrogate(0), + framePointerSurrogate(0), + popIndex(0), + stackArgumentIndex(0), + flags(flags), + resultSize(resultSize), + stackArgumentFootprint(stackArgumentFootprint) + { + uint32_t registerMask = c->regFile->generalRegisters.mask; + + if (argumentCount) { + assert(c, (flags & Compiler::TailJump) == 0); + assert(c, stackArgumentFootprint == 0); + + Stack* s = argumentStack; + unsigned index = 0; + unsigned argumentIndex = 0; + + while (true) { + unsigned footprint + = (argumentIndex + 1 < argumentCount + and s->value->nextWord == s->next->value) + ? 2 : 1; + + if (index % (c->arch->argumentAlignment() ? footprint : 1)) { + ++ index; + } + + SiteMask targetMask; + if (index + (c->arch->argumentRegisterAlignment() ? footprint : 1) + <= c->arch->argumentRegisterCount()) + { + int number = c->arch->argumentRegister(index); + + if (DebugReads) { + fprintf(stderr, "reg %d arg read %p\n", number, s->value); + } + + targetMask = SiteMask::fixedRegisterMask(number); + registerMask &= ~(1 << number); + } else { + if (index < c->arch->argumentRegisterCount()) { + index = c->arch->argumentRegisterCount(); + } + + unsigned frameIndex = index - c->arch->argumentRegisterCount(); + + if (DebugReads) { + fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value); + } + + targetMask = SiteMask(1 << lir::MemoryOperand, 0, frameIndex); + } + + this->addRead(c, s->value, targetMask); + + ++ index; + + if ((++ argumentIndex) < argumentCount) { + s = s->next; + } else { + break; + } + } + } + + if (DebugReads) { + fprintf(stderr, "address read %p\n", address); + } + + { bool thunk; + uint8_t typeMask; + uint64_t planRegisterMask; + c->arch->plan + ((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, vm::TargetBytesPerWord, + &typeMask, &planRegisterMask, &thunk); + + assert(c, not thunk); + + this->addRead(c, address, SiteMask + (typeMask, registerMask & planRegisterMask, AnyFrameIndex)); + } + + Stack* stack = stackBefore; + + if (stackArgumentFootprint) { + RUNTIME_ARRAY(Value*, arguments, stackArgumentFootprint); + for (int i = stackArgumentFootprint - 1; i >= 0; --i) { + Value* v = stack->value; + stack = stack->next; + + if ((vm::TargetBytesPerWord == 8 + and (v == 0 or (i >= 1 and stack->value == 0))) + or (vm::TargetBytesPerWord == 4 and v->nextWord != v)) + { + assert(c, vm::TargetBytesPerWord == 8 or v->nextWord == stack->value); + + RUNTIME_ARRAY_BODY(arguments)[i--] = stack->value; + stack = stack->next; + } + RUNTIME_ARRAY_BODY(arguments)[i] = v; + } + + int returnAddressIndex; + int framePointerIndex; + int frameOffset; + + if (TailCalls and (flags & Compiler::TailJump)) { + assert(c, argumentCount == 0); + + int base = frameBase(c); + returnAddressIndex = base + c->arch->returnAddressOffset(); + if (UseFramePointer) { + framePointerIndex = base + c->arch->framePointerOffset(); + } else { + framePointerIndex = -1; + } + + frameOffset = totalFrameSize(c) + - c->arch->argumentFootprint(stackArgumentFootprint); + } else { + returnAddressIndex = -1; + framePointerIndex = -1; + frameOffset = 0; + } + + for (unsigned i = 0; i < stackArgumentFootprint; ++i) { + Value* v = RUNTIME_ARRAY_BODY(arguments)[i]; + if (v) { + int frameIndex = i + frameOffset; + + if (DebugReads) { + fprintf(stderr, "stack arg read %p at %d of %d\n", + v, frameIndex, totalFrameSize(c)); + } + + if (static_cast(frameIndex) == returnAddressIndex) { + returnAddressSurrogate = v; + this->addRead(c, v, generalRegisterMask(c)); + } else if (static_cast(frameIndex) == framePointerIndex) { + framePointerSurrogate = v; + this->addRead(c, v, generalRegisterMask(c)); + } else { + this->addRead(c, v, SiteMask(1 << lir::MemoryOperand, 0, frameIndex)); + } + } + } + } + + if ((not TailCalls) or (flags & Compiler::TailJump) == 0) { + stackArgumentIndex = c->localFootprint; + if (stackBefore) { + stackArgumentIndex += stackBefore->index + 1 - stackArgumentFootprint; + } + + popIndex + = c->alignedFrameSize + + c->parameterFootprint + - c->arch->frameFooterSize() + - stackArgumentIndex; + + assert(c, static_cast(popIndex) >= 0); + + while (stack) { + if (stack->value) { + unsigned logicalIndex = compiler::frameIndex + (c, stack->index + c->localFootprint); + + if (DebugReads) { + fprintf(stderr, "stack save read %p at %d of %d\n", + stack->value, logicalIndex, totalFrameSize(c)); + } + + this->addRead(c, stack->value, SiteMask + (1 << lir::MemoryOperand, 0, logicalIndex)); + } + + stack = stack->next; + } + + saveLocals(c, this); + } + } + + virtual const char* name() { + return "CallEvent"; + } + + virtual void compile(Context* c) { + lir::UnaryOperation op; + + if (TailCalls and (flags & Compiler::TailJump)) { + if (flags & Compiler::LongJumpOrCall) { + if (flags & Compiler::Aligned) { + op = lir::AlignedLongJump; + } else { + op = lir::LongJump; + } + } else if (flags & Compiler::Aligned) { + op = lir::AlignedJump; + } else { + op = lir::Jump; + } + + assert(c, returnAddressSurrogate == 0 + or returnAddressSurrogate->source->type(c) == lir::RegisterOperand); + assert(c, framePointerSurrogate == 0 + or framePointerSurrogate->source->type(c) == lir::RegisterOperand); + + int ras; + if (returnAddressSurrogate) { + returnAddressSurrogate->source->freeze(c, returnAddressSurrogate); + + ras = static_cast + (returnAddressSurrogate->source)->number; + } else { + ras = lir::NoRegister; + } + + int fps; + if (framePointerSurrogate) { + framePointerSurrogate->source->freeze(c, framePointerSurrogate); + + fps = static_cast + (framePointerSurrogate->source)->number; + } else { + fps = lir::NoRegister; + } + + int offset + = static_cast(c->arch->argumentFootprint(stackArgumentFootprint)) + - static_cast(c->arch->argumentFootprint(c->parameterFootprint)); + + c->assembler->popFrameForTailCall(c->alignedFrameSize, offset, ras, fps); + } else if (flags & Compiler::LongJumpOrCall) { + if (flags & Compiler::Aligned) { + op = lir::AlignedLongCall; + } else { + op = lir::LongCall; + } + } else if (flags & Compiler::Aligned) { + op = lir::AlignedCall; + } else { + op = lir::Call; + } + + apply(c, op, vm::TargetBytesPerWord, address->source, address->source); + + if (traceHandler) { + traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)), + stackArgumentIndex); + } + + if (TailCalls) { + if (flags & Compiler::TailJump) { + if (returnAddressSurrogate) { + returnAddressSurrogate->source->thaw(c, returnAddressSurrogate); + } + + if (framePointerSurrogate) { + framePointerSurrogate->source->thaw(c, framePointerSurrogate); + } + } else { + unsigned footprint = c->arch->argumentFootprint + (stackArgumentFootprint); + + if (footprint > c->arch->stackAlignmentInWords()) { + c->assembler->adjustFrame + (footprint - c->arch->stackAlignmentInWords()); + } + } + } + + clean(c, this, stackBefore, localsBefore, reads, popIndex); + + if (resultSize and live(c, result)) { + result->addSite(c, registerSite(c, c->arch->returnLow())); + if (resultSize > vm::TargetBytesPerWord and live(c, result->nextWord)) { + result->nextWord->addSite(c, registerSite(c, c->arch->returnHigh())); + } + } + } + + virtual bool allExits() { + return (flags & Compiler::TailJump) != 0; + } + + Value* address; + TraceHandler* traceHandler; + Value* result; + Value* returnAddressSurrogate; + Value* framePointerSurrogate; + unsigned popIndex; + unsigned stackArgumentIndex; + unsigned flags; + unsigned resultSize; + unsigned stackArgumentFootprint; +}; + +void +appendCall(Context* c, Value* address, unsigned flags, + TraceHandler* traceHandler, Value* result, unsigned resultSize, + Stack* argumentStack, unsigned argumentCount, + unsigned stackArgumentFootprint) +{ + append(c, new(c->zone) + CallEvent(c, address, flags, traceHandler, result, + resultSize, argumentStack, argumentCount, + stackArgumentFootprint)); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h new file mode 100644 index 0000000000..3308ede12a --- /dev/null +++ b/src/codegen/compiler/event.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_EVENT_H +#define AVIAN_CODEGEN_COMPILER_EVENT_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; +class CodePromise; +class Snapshot; +class Link; +class Site; + +const bool DebugReads = false; + +class Event { + public: + Event(Context* c); + + virtual const char* name() = 0; + + virtual void compile(Context* c) = 0; + + virtual bool isBranch() { return false; } + + virtual bool allExits() { return false; } + + virtual Local* locals() { return localsBefore; } + + + + void addRead(Context* c, Value* v, Read* r); + + void addRead(Context* c, Value* v, const SiteMask& mask, + Value* successor = 0); + + void addReads(Context* c, Value* v, unsigned size, + const SiteMask& lowMask, Value* lowSuccessor, + const SiteMask& highMask, Value* highSuccessor); + + void addReads(Context* c, Value* v, unsigned size, + const SiteMask& lowMask, const SiteMask& highMask); + + + + CodePromise* makeCodePromise(Context* c); + + Event* next; + Stack* stackBefore; + Local* localsBefore; + Stack* stackAfter; + Local* localsAfter; + CodePromise* promises; + Read* reads; + Site** junctionSites; + Snapshot* snapshots; + Link* predecessors; + Link* successors; + Cell* visitLinks; + Block* block; + LogicalInstruction* logicalInstruction; + unsigned readCount; +}; + +void +appendCall(Context* c, Value* address, unsigned flags, + TraceHandler* traceHandler, Value* result, unsigned resultSize, + Stack* argumentStack, unsigned argumentCount, + unsigned stackArgumentFootprint); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_EVENT_H diff --git a/src/codegen/compiler/promise.cpp b/src/codegen/compiler/promise.cpp new file mode 100644 index 0000000000..ceb25d89e7 --- /dev/null +++ b/src/codegen/compiler/promise.cpp @@ -0,0 +1,26 @@ +/* Copyright (c) 2008-2012, 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 "codegen/compiler/context.h" +#include "codegen/compiler/promise.h" + +namespace avian { +namespace codegen { +namespace compiler { + +CodePromise* +codePromise(Context* c, Promise* offset) +{ + return new (c->zone) CodePromise(c, offset); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/promise.h b/src/codegen/compiler/promise.h new file mode 100644 index 0000000000..2afcd49304 --- /dev/null +++ b/src/codegen/compiler/promise.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_PROMISE_H +#define AVIAN_CODEGEN_COMPILER_PROMISE_H + +namespace avian { +namespace codegen { +namespace compiler { + + +class CodePromise: public Promise { + public: + CodePromise(Context* c, CodePromise* next): + c(c), offset(0), next(next) + { } + + CodePromise(Context* c, Promise* offset): + c(c), offset(offset), next(0) + { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast(c->machineCode + offset->value()); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0 and offset and offset->resolved(); + } + + Context* c; + Promise* offset; + CodePromise* next; +}; + +CodePromise* codePromise(Context* c, Promise* offset); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_PROMISE_H diff --git a/src/codegen/compiler/read.cpp b/src/codegen/compiler/read.cpp index 08308cfa52..1b90878c1e 100644 --- a/src/codegen/compiler/read.cpp +++ b/src/codegen/compiler/read.cpp @@ -178,6 +178,14 @@ Read* StubRead::next(Context*) { return next_; } + + +SingleRead* read(Context* c, const SiteMask& mask, Value* successor) { + assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0); + + return new(c->zone) SingleRead(mask, successor); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/read.h b/src/codegen/compiler/read.h index 4e942ba75a..52db19b0e8 100644 --- a/src/codegen/compiler/read.h +++ b/src/codegen/compiler/read.h @@ -111,6 +111,8 @@ class StubRead: public Read { bool valid_; }; +SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0); + } // namespace compiler } // namespace codegen diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp index 43eb211112..d05a09cd64 100644 --- a/src/codegen/compiler/site.cpp +++ b/src/codegen/compiler/site.cpp @@ -109,6 +109,12 @@ void SiteIterator::remove(Context* c) { +unsigned Site::registerSize(Context*) { + return vm::TargetBytesPerWord; +} + + + Site* constantSite(Context* c, Promise* value) { return new(c->zone) ConstantSite(value); } diff --git a/src/codegen/compiler/site.h b/src/codegen/compiler/site.h index 6f5508be91..1360e8959f 100644 --- a/src/codegen/compiler/site.h +++ b/src/codegen/compiler/site.h @@ -36,6 +36,10 @@ class SiteMask { SiteMask intersectionWith(const SiteMask& b); + static SiteMask fixedRegisterMask(int number) { + return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex); + } + uint8_t typeMask; uint32_t registerMask; int frameIndex; @@ -83,7 +87,7 @@ class Site { virtual SiteMask nextWordMask(Context*, unsigned) = 0; - virtual unsigned registerSize(Context*) { return vm::TargetBytesPerWord; } + virtual unsigned registerSize(Context*); virtual unsigned registerMask(Context*) { return 0; } diff --git a/src/codegen/compiler/stack.h b/src/codegen/compiler/stack.h new file mode 100644 index 0000000000..7ae8c4f7c1 --- /dev/null +++ b/src/codegen/compiler/stack.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_STACK_H +#define AVIAN_CODEGEN_COMPILER_STACK_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Value; + +class Stack { + public: + Stack(unsigned index, Value* value, Stack* next): + index(index), value(value), next(next) + { } + + unsigned index; + Value* value; + Stack* next; +}; + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_STACK_H diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp index a8f88acbca..90a4f3c100 100644 --- a/src/codegen/compiler/value.cpp +++ b/src/codegen/compiler/value.cpp @@ -38,6 +38,18 @@ bool Value::isBuddyOf(Value* b) { return false; } +void Value::addSite(Context* c, Site* s) { + if (not this->findSite(s)) { + if (DebugSites) { + char buffer[256]; s->toString(c, buffer, 256); + fprintf(stderr, "add site %s to %p\n", buffer, this); + } + s->acquire(c, this); + s->next = this->sites; + this->sites = s; + } +} + } // namespace regalloc } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index f913d89363..f21bcbc062 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -25,6 +25,8 @@ class Site; const int AnyFrameIndex = -2; const int NoFrameIndex = -1; +const bool DebugSites = false; + class Value: public Compiler::Operand { public: Read* reads; @@ -43,6 +45,8 @@ class Value: public Compiler::Operand { bool findSite(Site* site); bool isBuddyOf(Value* b); + + void addSite(Context* c, Site* s); }; } // namespace compiler From 165c77d7729fe12a8be241db5a094644741f1438 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 19:43:19 -0700 Subject: [PATCH 221/378] move ReturnEvent out of compiler.cpp --- src/codegen/compiler.cpp | 91 ++-------------------------------- src/codegen/compiler/event.cpp | 52 +++++++++++++++++++ src/codegen/compiler/event.h | 43 +++++++++++++++- 3 files changed, 96 insertions(+), 90 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index ca6ee5ba23..5ab7eaea50 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -198,45 +198,6 @@ Cell* reverseDestroy(Cell* cell) { return previous; } -class StubReadPair { - public: - Value* value; - StubRead* read; -}; - -class JunctionState { - public: - JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { } - - unsigned frameFootprint; - StubReadPair reads[0]; -}; - -class Link { - public: - Link(Event* predecessor, Link* nextPredecessor, Event* successor, - Link* nextSuccessor, ForkState* forkState): - predecessor(predecessor), nextPredecessor(nextPredecessor), - successor(successor), nextSuccessor(nextSuccessor), forkState(forkState), - junctionState(0) - { } - - Event* predecessor; - Link* nextPredecessor; - Event* successor; - Link* nextSuccessor; - ForkState* forkState; - JunctionState* junctionState; -}; - -Link* -link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, - Link* nextSuccessor, ForkState* forkState) -{ - return new(c->zone) Link - (predecessor, nextPredecessor, successor, nextSuccessor, forkState); -} - unsigned countPredecessors(Link* link) { @@ -1214,52 +1175,6 @@ saveLocals(Context* c, Event* e) } } -bool -unreachable(Event* event) -{ - for (Link* p = event->predecessors; p; p = p->nextPredecessor) { - if (not p->predecessor->allExits()) return false; - } - return event->predecessors != 0; -} - -class ReturnEvent: public Event { - public: - ReturnEvent(Context* c, unsigned size, Value* value): - Event(c), value(value) - { - if (value) { - this->addReads(c, value, size, - SiteMask::fixedRegisterMask(c->arch->returnLow()), - SiteMask::fixedRegisterMask(c->arch->returnHigh())); - } - } - - virtual const char* name() { - return "ReturnEvent"; - } - - virtual void compile(Context* c) { - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - - if (not unreachable(this)) { - c->assembler->popFrameAndPopArgumentsAndReturn - (c->alignedFrameSize, - c->arch->argumentFootprint(c->parameterFootprint)); - } - } - - Value* value; -}; - -void -appendReturn(Context* c, unsigned size, Value* value) -{ - append(c, new(c->zone) ReturnEvent(c, size, value)); -} - void maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, @@ -2580,7 +2495,7 @@ class BranchEvent: public Event { ConstantSite* firstConstant = findConstantSite(c, first); ConstantSite* secondConstant = findConstantSite(c, second); - if (not unreachable(this)) { + if (not this->isUnreachable()) { if (firstConstant and secondConstant and firstConstant->value->resolved() @@ -2700,7 +2615,7 @@ class JumpEvent: public Event { } virtual void compile(Context* c) { - if (not unreachable(this)) { + if (not this->isUnreachable()) { apply(c, type, TargetBytesPerWord, address->source, address->source); } @@ -2719,7 +2634,7 @@ class JumpEvent: public Event { virtual bool isBranch() { return true; } virtual bool allExits() { - return exit or unreachable(this); + return exit or this->isUnreachable(); } lir::UnaryOperation type; diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 9b4fee04e1..2ac259cf94 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -59,6 +59,8 @@ void clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, Read* live(Context* c UNUSED, Value* v); +void popRead(Context* c, Event* e UNUSED, Value* v); + Event::Event(Context* c): next(0), stackBefore(c->stack), localsBefore(c->locals), stackAfter(0), localsAfter(0), promises(0), reads(0), @@ -119,6 +121,20 @@ CodePromise* Event::makeCodePromise(Context* c) { return this->promises = new(c->zone) CodePromise(c, this->promises); } +bool Event::isUnreachable() { + for (Link* p = this->predecessors; p; p = p->nextPredecessor) { + if (not p->predecessor->allExits()) return false; + } + return this->predecessors != 0; +} + +Link* link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, + Link* nextSuccessor, ForkState* forkState) +{ + return new(c->zone) Link + (predecessor, nextPredecessor, successor, nextSuccessor, forkState); +} + class CallEvent: public Event { public: @@ -441,6 +457,42 @@ appendCall(Context* c, Value* address, unsigned flags, stackArgumentFootprint)); } + +class ReturnEvent: public Event { + public: + ReturnEvent(Context* c, unsigned size, Value* value): + Event(c), value(value) + { + if (value) { + this->addReads(c, value, size, + SiteMask::fixedRegisterMask(c->arch->returnLow()), + SiteMask::fixedRegisterMask(c->arch->returnHigh())); + } + } + + virtual const char* name() { + return "ReturnEvent"; + } + + virtual void compile(Context* c) { + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + if (not this->isUnreachable()) { + c->assembler->popFrameAndPopArgumentsAndReturn + (c->alignedFrameSize, + c->arch->argumentFootprint(c->parameterFootprint)); + } + } + + Value* value; +}; + +void appendReturn(Context* c, unsigned size, Value* value) { + append(c, new(c->zone) ReturnEvent(c, size, value)); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 3308ede12a..91b441353b 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -20,6 +20,7 @@ class CodePromise; class Snapshot; class Link; class Site; +class StubRead; const bool DebugReads = false; @@ -51,10 +52,10 @@ class Event { void addReads(Context* c, Value* v, unsigned size, const SiteMask& lowMask, const SiteMask& highMask); - - CodePromise* makeCodePromise(Context* c); + bool isUnreachable(); + Event* next; Stack* stackBefore; Local* localsBefore; @@ -72,12 +73,50 @@ class Event { unsigned readCount; }; +class StubReadPair { + public: + Value* value; + StubRead* read; +}; + +class JunctionState { + public: + JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { } + + unsigned frameFootprint; + StubReadPair reads[0]; +}; + +class Link { + public: + Link(Event* predecessor, Link* nextPredecessor, Event* successor, + Link* nextSuccessor, ForkState* forkState): + predecessor(predecessor), nextPredecessor(nextPredecessor), + successor(successor), nextSuccessor(nextSuccessor), forkState(forkState), + junctionState(0) + { } + + Event* predecessor; + Link* nextPredecessor; + Event* successor; + Link* nextSuccessor; + ForkState* forkState; + JunctionState* junctionState; +}; + +Link* +link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, + Link* nextSuccessor, ForkState* forkState); + void appendCall(Context* c, Value* address, unsigned flags, TraceHandler* traceHandler, Value* result, unsigned resultSize, Stack* argumentStack, unsigned argumentCount, unsigned stackArgumentFootprint); +void +appendReturn(Context* c, unsigned size, Value* value); + } // namespace compiler } // namespace codegen } // namespace avian From 5ad0eb86d344fb331f859142ad0fae2c26fb628c Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 20:03:37 -0700 Subject: [PATCH 222/378] move MoveEvent out of compiler.cpp --- src/codegen/compiler.cpp | 269 ++------------------------------- src/codegen/compiler/event.cpp | 186 +++++++++++++++++++++++ src/codegen/compiler/event.h | 5 + src/codegen/compiler/value.cpp | 55 +++++++ src/codegen/compiler/value.h | 13 ++ 5 files changed, 272 insertions(+), 256 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 5ab7eaea50..019204da74 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -36,7 +36,6 @@ const bool DebugCompile = false; const bool DebugResources = false; const bool DebugFrame = false; const bool DebugControl = false; -const bool DebugMoves = false; const bool DebugBuddies = false; const unsigned StealRegisterReserveCount = 2; @@ -333,13 +332,6 @@ frameIndex(Context* c, FrameIterator::Element* element) return frameIndex(c, element->localIndex); } -bool -hasSite(Context* c, Value* v) -{ - SiteIterator it(c, v); - return it.hasMore(); -} - bool uniqueSite(Context* c, Value* v, Site* s) { @@ -365,25 +357,6 @@ uniqueSite(Context* c, Value* v, Site* s) } } -void -removeSite(Context* c, Value* v, Site* s) -{ - for (SiteIterator it(c, v); it.hasMore();) { - if (s == it.next()) { - if (DebugSites) { - char buffer[256]; s->toString(c, buffer, 256); - fprintf(stderr, "remove site %s from %p\n", buffer, v); - } - it.remove(c); - break; - } - } - if (DebugSites) { - fprintf(stderr, "%p has more: %d\n", v, hasSite(c, v)); - } - assert(c, not v->findSite(s)); -} - void clearSites(Context* c, Value* v) { @@ -873,7 +846,7 @@ steal(Context* c, Resource* r, Value* thief) r->site->thaw(c, r->value); } - removeSite(c, r->value, r->site); + r->value->removeSite(c, r->site); } SiteMask @@ -1238,7 +1211,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, // pick a temporary register which is valid as both a // destination and a source for the moves we need to perform: - removeSite(c, dst, target); + dst->removeSite(c, target); bool thunk; uint8_t srcTypeMask; @@ -1294,7 +1267,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, tmpTarget->thaw(c, dst); if (isStore) { - removeSite(c, dst, tmpTarget); + dst->removeSite(c, tmpTarget); } } } @@ -1315,7 +1288,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, } if (isStore) { - removeSite(c, dst, target); + dst->removeSite(c, target); } } @@ -1358,7 +1331,7 @@ pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, addBuddy(src, dst); if (src->source->isVolatile(c)) { - removeSite(c, src, src->source); + src->removeSite(c, src->source); } return s; @@ -1367,222 +1340,6 @@ pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, } } -Value* -value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0) -{ - return new(c->zone) Value(site, target, type); -} - -void -grow(Context* c, Value* v) -{ - assert(c, v->nextWord == v); - - Value* next = value(c, v->type); - v->nextWord = next; - next->nextWord = v; - next->wordIndex = 1; -} - -void -split(Context* c, Value* v) -{ - grow(c, v); - for (SiteIterator it(c, v); it.hasMore();) { - Site* s = it.next(); - removeSite(c, v, s); - - v->addSite(c, s->copyLow(c)); - v->nextWord->addSite(c, s->copyHigh(c)); - } -} - -void -maybeSplit(Context* c, Value* v) -{ - if (v->nextWord == v) { - split(c, v); - } -} - -class MoveEvent: public Event { - public: - MoveEvent(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, - const SiteMask& srcLowMask, const SiteMask& srcHighMask): - Event(c), type(type), srcSize(srcSize), srcSelectSize(srcSelectSize), - src(src), dstSize(dstSize), dst(dst) - { - assert(c, srcSelectSize <= srcSize); - - bool noop = srcSelectSize >= dstSize; - - if (dstSize > TargetBytesPerWord) { - grow(c, dst); - } - - if (srcSelectSize > TargetBytesPerWord) { - maybeSplit(c, src); - } - - this->addReads(c, src, srcSelectSize, srcLowMask, noop ? dst : 0, - srcHighMask, - noop and dstSize > TargetBytesPerWord ? dst->nextWord : 0); - } - - virtual const char* name() { - return "MoveEvent"; - } - - virtual void compile(Context* c) { - uint8_t dstTypeMask; - uint64_t dstRegisterMask; - - c->arch->planDestination - (type, - srcSelectSize, - 1 << src->source->type(c), - (static_cast(src->nextWord->source->registerMask(c)) << 32) - | static_cast(src->source->registerMask(c)), - dstSize, - &dstTypeMask, - &dstRegisterMask); - - SiteMask dstLowMask(dstTypeMask, dstRegisterMask, AnyFrameIndex); - SiteMask dstHighMask(dstTypeMask, dstRegisterMask >> 32, AnyFrameIndex); - - if (srcSelectSize >= TargetBytesPerWord - and dstSize >= TargetBytesPerWord - and srcSelectSize >= dstSize) - { - if (dst->target) { - if (dstSize > TargetBytesPerWord) { - if (src->source->registerSize(c) > TargetBytesPerWord) { - apply(c, lir::Move, srcSelectSize, src->source, src->source, - dstSize, dst->target, dst->target); - - if (live(c, dst) == 0) { - removeSite(c, dst, dst->target); - if (dstSize > TargetBytesPerWord) { - removeSite(c, dst->nextWord, dst->nextWord->target); - } - } - } else { - src->nextWord->source->freeze(c, src->nextWord); - - maybeMove(c, lir::Move, TargetBytesPerWord, TargetBytesPerWord, src, - TargetBytesPerWord, dst, dstLowMask); - - src->nextWord->source->thaw(c, src->nextWord); - - maybeMove - (c, lir::Move, TargetBytesPerWord, TargetBytesPerWord, src->nextWord, - TargetBytesPerWord, dst->nextWord, dstHighMask); - } - } else { - maybeMove(c, lir::Move, TargetBytesPerWord, TargetBytesPerWord, src, - TargetBytesPerWord, dst, dstLowMask); - } - } else { - Site* low = pickSiteOrMove(c, src, dst, 0, 0); - if (dstSize > TargetBytesPerWord) { - pickSiteOrMove(c, src->nextWord, dst->nextWord, low, 1); - } - } - } else if (srcSelectSize <= TargetBytesPerWord - and dstSize <= TargetBytesPerWord) - { - maybeMove(c, type, srcSize, srcSelectSize, src, dstSize, dst, - dstLowMask); - } else { - assert(c, srcSize == TargetBytesPerWord); - assert(c, srcSelectSize == TargetBytesPerWord); - - if (dst->nextWord->target or live(c, dst->nextWord)) { - assert(c, dstLowMask.typeMask & (1 << lir::RegisterOperand)); - - Site* low = freeRegisterSite(c, dstLowMask.registerMask); - - src->source->freeze(c, src); - - dst->addSite(c, low); - - low->freeze(c, dst); - - if (DebugMoves) { - char srcb[256]; src->source->toString(c, srcb, 256); - char dstb[256]; low->toString(c, dstb, 256); - fprintf(stderr, "move %s to %s for %p\n", - srcb, dstb, src); - } - - apply(c, lir::Move, TargetBytesPerWord, src->source, src->source, - TargetBytesPerWord, low, low); - - low->thaw(c, dst); - - src->source->thaw(c, src); - - assert(c, dstHighMask.typeMask & (1 << lir::RegisterOperand)); - - Site* high = freeRegisterSite(c, dstHighMask.registerMask); - - low->freeze(c, dst); - - dst->nextWord->addSite(c, high); - - high->freeze(c, dst->nextWord); - - if (DebugMoves) { - char srcb[256]; low->toString(c, srcb, 256); - char dstb[256]; high->toString(c, dstb, 256); - fprintf(stderr, "extend %s to %s for %p %p\n", - srcb, dstb, dst, dst->nextWord); - } - - apply(c, lir::Move, TargetBytesPerWord, low, low, dstSize, low, high); - - high->thaw(c, dst->nextWord); - - low->thaw(c, dst); - } else { - pickSiteOrMove(c, src, dst, 0, 0); - } - } - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - } - - lir::BinaryOperation type; - unsigned srcSize; - unsigned srcSelectSize; - Value* src; - unsigned dstSize; - Value* dst; -}; - -void -appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst) -{ - bool thunk; - uint8_t srcTypeMask; - uint64_t srcRegisterMask; - - c->arch->planSource - (type, srcSelectSize, &srcTypeMask, &srcRegisterMask, dstSize, &thunk); - - assert(c, not thunk); - - append(c, new(c->zone) - MoveEvent - (c, type, srcSize, srcSelectSize, src, dstSize, dst, - SiteMask(srcTypeMask, srcRegisterMask, AnyFrameIndex), - SiteMask(srcTypeMask, srcRegisterMask >> 32, AnyFrameIndex))); -} - ConstantSite* findConstantSite(Context* c, Value* v) { @@ -1630,7 +1387,7 @@ getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask) result->addSite(c, s); } - removeSite(c, v, s); + v->removeSite(c, s); s->freeze(c, v); @@ -1672,7 +1429,7 @@ class CombineEvent: public Event { this->addReads(c, first, firstSize, firstLowMask, firstHighMask); if (resultSize > TargetBytesPerWord) { - grow(c, result); + result->grow(c); } bool condensed = c->arch->alwaysCondensed(type); @@ -1896,7 +1653,7 @@ push(Context* c, unsigned footprint, Value* v) assert(c, footprint == 2); if (TargetBytesPerWord == 4) { - maybeSplit(c, low); + low->maybeSplit(c); high = pushWord(c, low->nextWord); } else { high = pushWord(c, 0); @@ -2136,7 +1893,7 @@ class TranslateEvent: public Event { bool condensed = c->arch->alwaysCondensed(type); if (resultSize > TargetBytesPerWord) { - grow(c, result); + result->grow(c); } this->addReads(c, value, valueSize, valueLowMask, condensed ? result : 0, @@ -2268,7 +2025,7 @@ moveIfConflict(Context* c, Value* v, MemorySite* s) v->reads->intersect(&mask); if (s->conflicts(mask)) { maybeMove(c, v->reads, true, false); - removeSite(c, v, s); + v->removeSite(c, s); } } } @@ -2818,7 +2575,7 @@ class BuddyEvent: public Event { fprintf(stderr, "original %p buddy %p\n", original, buddy); } - assert(c, hasSite(c, original)); + assert(c, original->hasSite(c)); assert(c, original); assert(c, buddy); @@ -2952,7 +2709,7 @@ readSource(Context* c, Read* r) fprintf(stderr, "read source for %p from %s\n", v, buffer); } - if (not hasSite(c, v)) { + if (not v->hasSite(c)) { if (DebugReads) { fprintf(stderr, "no sites found for %p\n", v); } @@ -3080,7 +2837,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, Value dummy(0, 0, lir::ValueGeneral); dummy.addSite(c, s); - removeSite(c, &dummy, s); + dummy.removeSite(c, s); freeze(c, frozen, s, 0); } } diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 2ac259cf94..e96a7c8d08 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -61,6 +61,14 @@ Read* live(Context* c UNUSED, Value* v); void popRead(Context* c, Event* e UNUSED, Value* v); +void +maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, + unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, + const SiteMask& dstMask); +Site* +pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, + unsigned index); + Event::Event(Context* c): next(0), stackBefore(c->stack), localsBefore(c->locals), stackAfter(0), localsAfter(0), promises(0), reads(0), @@ -493,6 +501,184 @@ void appendReturn(Context* c, unsigned size, Value* value) { append(c, new(c->zone) ReturnEvent(c, size, value)); } +class MoveEvent: public Event { + public: + MoveEvent(Context* c, lir::BinaryOperation type, unsigned srcSize, + unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, + const SiteMask& srcLowMask, const SiteMask& srcHighMask): + Event(c), type(type), srcSize(srcSize), srcSelectSize(srcSelectSize), + src(src), dstSize(dstSize), dst(dst) + { + assert(c, srcSelectSize <= srcSize); + + bool noop = srcSelectSize >= dstSize; + + if (dstSize > vm::TargetBytesPerWord) { + dst->grow(c); + } + + if (srcSelectSize > vm::TargetBytesPerWord) { + src->maybeSplit(c); + } + + this->addReads(c, src, srcSelectSize, srcLowMask, noop ? dst : 0, + srcHighMask, + noop and dstSize > vm::TargetBytesPerWord ? dst->nextWord : 0); + } + + virtual const char* name() { + return "MoveEvent"; + } + + virtual void compile(Context* c) { + uint8_t dstTypeMask; + uint64_t dstRegisterMask; + + c->arch->planDestination + (type, + srcSelectSize, + 1 << src->source->type(c), + (static_cast(src->nextWord->source->registerMask(c)) << 32) + | static_cast(src->source->registerMask(c)), + dstSize, + &dstTypeMask, + &dstRegisterMask); + + SiteMask dstLowMask(dstTypeMask, dstRegisterMask, AnyFrameIndex); + SiteMask dstHighMask(dstTypeMask, dstRegisterMask >> 32, AnyFrameIndex); + + if (srcSelectSize >= vm::TargetBytesPerWord + and dstSize >= vm::TargetBytesPerWord + and srcSelectSize >= dstSize) + { + if (dst->target) { + if (dstSize > vm::TargetBytesPerWord) { + if (src->source->registerSize(c) > vm::TargetBytesPerWord) { + apply(c, lir::Move, srcSelectSize, src->source, src->source, + dstSize, dst->target, dst->target); + + if (live(c, dst) == 0) { + dst->removeSite(c, dst->target); + if (dstSize > vm::TargetBytesPerWord) { + dst->nextWord->removeSite(c, dst->nextWord->target); + } + } + } else { + src->nextWord->source->freeze(c, src->nextWord); + + maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, src, + vm::TargetBytesPerWord, dst, dstLowMask); + + src->nextWord->source->thaw(c, src->nextWord); + + maybeMove + (c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, src->nextWord, + vm::TargetBytesPerWord, dst->nextWord, dstHighMask); + } + } else { + maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, src, + vm::TargetBytesPerWord, dst, dstLowMask); + } + } else { + Site* low = pickSiteOrMove(c, src, dst, 0, 0); + if (dstSize > vm::TargetBytesPerWord) { + pickSiteOrMove(c, src->nextWord, dst->nextWord, low, 1); + } + } + } else if (srcSelectSize <= vm::TargetBytesPerWord + and dstSize <= vm::TargetBytesPerWord) + { + maybeMove(c, type, srcSize, srcSelectSize, src, dstSize, dst, + dstLowMask); + } else { + assert(c, srcSize == vm::TargetBytesPerWord); + assert(c, srcSelectSize == vm::TargetBytesPerWord); + + if (dst->nextWord->target or live(c, dst->nextWord)) { + assert(c, dstLowMask.typeMask & (1 << lir::RegisterOperand)); + + Site* low = freeRegisterSite(c, dstLowMask.registerMask); + + src->source->freeze(c, src); + + dst->addSite(c, low); + + low->freeze(c, dst); + + if (DebugMoves) { + char srcb[256]; src->source->toString(c, srcb, 256); + char dstb[256]; low->toString(c, dstb, 256); + fprintf(stderr, "move %s to %s for %p\n", + srcb, dstb, src); + } + + apply(c, lir::Move, vm::TargetBytesPerWord, src->source, src->source, + vm::TargetBytesPerWord, low, low); + + low->thaw(c, dst); + + src->source->thaw(c, src); + + assert(c, dstHighMask.typeMask & (1 << lir::RegisterOperand)); + + Site* high = freeRegisterSite(c, dstHighMask.registerMask); + + low->freeze(c, dst); + + dst->nextWord->addSite(c, high); + + high->freeze(c, dst->nextWord); + + if (DebugMoves) { + char srcb[256]; low->toString(c, srcb, 256); + char dstb[256]; high->toString(c, dstb, 256); + fprintf(stderr, "extend %s to %s for %p %p\n", + srcb, dstb, dst, dst->nextWord); + } + + apply(c, lir::Move, vm::TargetBytesPerWord, low, low, dstSize, low, high); + + high->thaw(c, dst->nextWord); + + low->thaw(c, dst); + } else { + pickSiteOrMove(c, src, dst, 0, 0); + } + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + } + + lir::BinaryOperation type; + unsigned srcSize; + unsigned srcSelectSize; + Value* src; + unsigned dstSize; + Value* dst; +}; + +void +appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, + unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst) +{ + bool thunk; + uint8_t srcTypeMask; + uint64_t srcRegisterMask; + + c->arch->planSource + (type, srcSelectSize, &srcTypeMask, &srcRegisterMask, dstSize, &thunk); + + assert(c, not thunk); + + append(c, new(c->zone) + MoveEvent + (c, type, srcSize, srcSelectSize, src, dstSize, dst, + SiteMask(srcTypeMask, srcRegisterMask, AnyFrameIndex), + SiteMask(srcTypeMask, srcRegisterMask >> 32, AnyFrameIndex))); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 91b441353b..6dbbd018d4 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -23,6 +23,7 @@ class Site; class StubRead; const bool DebugReads = false; +const bool DebugMoves = false; class Event { public: @@ -117,6 +118,10 @@ appendCall(Context* c, Value* address, unsigned flags, void appendReturn(Context* c, unsigned size, Value* value); +void +appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, + unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp index 90a4f3c100..62fe9c86a5 100644 --- a/src/codegen/compiler/value.cpp +++ b/src/codegen/compiler/value.cpp @@ -50,6 +50,61 @@ void Value::addSite(Context* c, Site* s) { } } + +void Value::grow(Context* c) { + assert(c, this->nextWord == this); + + Value* next = value(c, this->type); + this->nextWord = next; + next->nextWord = this; + next->wordIndex = 1; +} + + +void Value::maybeSplit(Context* c) { + if (this->nextWord == this) { + this->split(c); + } +} + +void Value::split(Context* c) { + this->grow(c); + for (SiteIterator it(c, this); it.hasMore();) { + Site* s = it.next(); + this->removeSite(c, s); + + this->addSite(c, s->copyLow(c)); + this->nextWord->addSite(c, s->copyHigh(c)); + } +} + +void Value::removeSite(Context* c, Site* s) { + for (SiteIterator it(c, this); it.hasMore();) { + if (s == it.next()) { + if (DebugSites) { + char buffer[256]; s->toString(c, buffer, 256); + fprintf(stderr, "remove site %s from %p\n", buffer, this); + } + it.remove(c); + break; + } + } + if (DebugSites) { + fprintf(stderr, "%p has more: %d\n", this, this->hasSite(c)); + } + assert(c, not this->findSite(s)); +} + +bool Value::hasSite(Context* c) { + SiteIterator it(c, this); + return it.hasMore(); +} + + +Value* value(Context* c, lir::ValueType type, Site* site, Site* target) { + return new(c->zone) Value(site, target, type); +} + } // namespace regalloc } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index f21bcbc062..0543ec3c74 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -47,8 +47,21 @@ class Value: public Compiler::Operand { bool isBuddyOf(Value* b); void addSite(Context* c, Site* s); + + void grow(Context* c); + + void maybeSplit(Context* c); + + void split(Context* c); + + void removeSite(Context* c, Site* s); + + bool hasSite(Context* c); }; + +Value* value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0); + } // namespace compiler } // namespace codegen } // namespace avian From 8a61b38a0196acbde01df5b590d1552be71e7201 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 20:28:29 -0700 Subject: [PATCH 223/378] move CombineEvent out of compiler.cpp --- src/codegen/compiler.cpp | 296 +----------------------------- src/codegen/compiler/event.cpp | 253 +++++++++++++++++++++++++ src/codegen/compiler/event.h | 6 + src/codegen/compiler/read.h | 4 + src/codegen/compiler/regalloc.cpp | 3 +- src/codegen/compiler/value.cpp | 44 +++++ src/codegen/compiler/value.h | 8 + 7 files changed, 321 insertions(+), 293 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 019204da74..9af7e73e97 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -332,31 +332,6 @@ frameIndex(Context* c, FrameIterator::Element* element) return frameIndex(c, element->localIndex); } -bool -uniqueSite(Context* c, Value* v, Site* s) -{ - SiteIterator it(c, v); - Site* p UNUSED = it.next(); - if (it.hasMore()) { - // the site is not this word's only site, but if the site is - // shared with the next word, it may be that word's only site - if (v->nextWord != v and s->registerSize(c) > TargetBytesPerWord) { - SiteIterator nit(c, v->nextWord); - Site* p = nit.next(); - if (nit.hasMore()) { - return false; - } else { - return p == s; - } - } else { - return false; - } - } else { - assert(c, p == s); - return true; - } -} - void clearSites(Context* c, Value* v) { @@ -369,39 +344,10 @@ clearSites(Context* c, Value* v) } } -bool -valid(Read* r) -{ - return r and r->valid(); -} - -#ifndef NDEBUG - -bool -hasBuddy(Context* c, Value* a, Value* b) -{ - if (a == b) { - return true; - } - - int i = 0; - for (Value* p = a->buddy; p != a; p = p->buddy) { - if (p == b) { - return true; - } - if (++i > 1000) { - abort(c); - } - } - return false; -} - -#endif // not NDEBUG - Read* live(Context* c UNUSED, Value* v) { - assert(c, hasBuddy(c, v->buddy, v)); + assert(c, v->buddy->hasBuddy(c, v)); Value* p = v; do { @@ -414,21 +360,6 @@ live(Context* c UNUSED, Value* v) return 0; } -Read* -liveNext(Context* c, Value* v) -{ - assert(c, hasBuddy(c, v->buddy, v)); - - Read* r = v->reads->next(c); - if (valid(r)) return r; - - for (Value* p = v->buddy; p != v; p = p->buddy) { - if (valid(p->reads)) return p->reads; - } - - return 0; -} - unsigned sitesToString(Context* c, Value* v, char* buffer, unsigned size); @@ -837,7 +768,7 @@ steal(Context* c, Resource* r, Value* thief) } if ((not (thief and thief->isBuddyOf(r->value)) - and uniqueSite(c, r->value, r->site))) + and r->value->uniqueSite(c, r->site))) { r->site->freeze(c, r->value); @@ -1352,175 +1283,14 @@ findConstantSite(Context* c, Value* v) return 0; } -void -preserve(Context* c, Value* v, Read* r, Site* s) -{ - s->freeze(c, v); - - maybeMove(c, r, false, true, 0); - - s->thaw(c, v); -} - Site* -getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask) -{ - Site* s; - Value* v; - Read* r = liveNext(c, value); - if (value->source->match - (c, static_cast(resultMask)) - and (r == 0 or value->source->loneMatch - (c, static_cast(resultMask)))) - { - s = value->source; - v = value; - if (r and uniqueSite(c, v, s)) { - preserve(c, v, r, s); - } - } else { - SingleRead r(resultMask, 0); - r.value = result; - r.successor_ = result; - s = pickTargetSite(c, &r, true); - v = result; - result->addSite(c, s); - } - - v->removeSite(c, s); - - s->freeze(c, v); - - return s; -} +getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask); void -freezeSource(Context* c, unsigned size, Value* v) -{ - v->source->freeze(c, v); - if (size > TargetBytesPerWord) { - v->nextWord->source->freeze(c, v->nextWord); - } -} +freezeSource(Context* c, unsigned size, Value* v); void -thawSource(Context* c, unsigned size, Value* v) -{ - v->source->thaw(c, v); - if (size > TargetBytesPerWord) { - v->nextWord->source->thaw(c, v->nextWord); - } -} - -class CombineEvent: public Event { - public: - CombineEvent(Context* c, lir::TernaryOperation type, - unsigned firstSize, Value* first, - unsigned secondSize, Value* second, - unsigned resultSize, Value* result, - const SiteMask& firstLowMask, - const SiteMask& firstHighMask, - const SiteMask& secondLowMask, - const SiteMask& secondHighMask): - Event(c), type(type), firstSize(firstSize), first(first), - secondSize(secondSize), second(second), resultSize(resultSize), - result(result) - { - this->addReads(c, first, firstSize, firstLowMask, firstHighMask); - - if (resultSize > TargetBytesPerWord) { - result->grow(c); - } - - bool condensed = c->arch->alwaysCondensed(type); - - this->addReads(c, second, secondSize, - secondLowMask, condensed ? result : 0, - secondHighMask, condensed ? result->nextWord : 0); - } - - virtual const char* name() { - return "CombineEvent"; - } - - virtual void compile(Context* c) { - assert(c, first->source->type(c) == first->nextWord->source->type(c)); - - // if (second->source->type(c) != second->nextWord->source->type(c)) { - // fprintf(stderr, "%p %p %d : %p %p %d\n", - // second, second->source, second->source->type(c), - // second->nextWord, second->nextWord->source, - // second->nextWord->source->type(c)); - // } - - assert(c, second->source->type(c) == second->nextWord->source->type(c)); - - freezeSource(c, firstSize, first); - - uint8_t cTypeMask; - uint64_t cRegisterMask; - - c->arch->planDestination - (type, - firstSize, - 1 << first->source->type(c), - (static_cast(first->nextWord->source->registerMask(c)) << 32) - | static_cast(first->source->registerMask(c)), - secondSize, - 1 << second->source->type(c), - (static_cast(second->nextWord->source->registerMask(c)) << 32) - | static_cast(second->source->registerMask(c)), - resultSize, - &cTypeMask, - &cRegisterMask); - - SiteMask resultLowMask(cTypeMask, cRegisterMask, AnyFrameIndex); - SiteMask resultHighMask(cTypeMask, cRegisterMask >> 32, AnyFrameIndex); - - Site* low = getTarget(c, second, result, resultLowMask); - unsigned lowSize = low->registerSize(c); - Site* high - = (resultSize > lowSize - ? getTarget(c, second->nextWord, result->nextWord, resultHighMask) - : low); - -// fprintf(stderr, "combine %p:%p and %p:%p into %p:%p\n", -// first, first->nextWord, -// second, second->nextWord, -// result, result->nextWord); - - apply(c, type, - firstSize, first->source, first->nextWord->source, - secondSize, second->source, second->nextWord->source, - resultSize, low, high); - - thawSource(c, firstSize, first); - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - - low->thaw(c, second); - if (resultSize > lowSize) { - high->thaw(c, second->nextWord); - } - - if (live(c, result)) { - result->addSite(c, low); - if (resultSize > lowSize and live(c, result->nextWord)) { - result->nextWord->addSite(c, high); - } - } - } - - lir::TernaryOperation type; - unsigned firstSize; - Value* first; - unsigned secondSize; - Value* second; - unsigned resultSize; - Value* result; -}; +thawSource(Context* c, unsigned size, Value* v); void removeBuddy(Context* c, Value* v) @@ -1825,62 +1595,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -void -appendCombine(Context* c, lir::TernaryOperation type, - unsigned firstSize, Value* first, - unsigned secondSize, Value* second, - unsigned resultSize, Value* result) -{ - bool thunk; - uint8_t firstTypeMask; - uint64_t firstRegisterMask; - uint8_t secondTypeMask; - uint64_t secondRegisterMask; - - c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask, - secondSize, &secondTypeMask, &secondRegisterMask, - resultSize, &thunk); - - if (thunk) { - Stack* oldStack = c->stack; - - bool threadParameter; - intptr_t handler = c->client->getThunk - (type, firstSize, resultSize, &threadParameter); - - unsigned stackSize = ceilingDivide(secondSize, TargetBytesPerWord) - + ceilingDivide(firstSize, TargetBytesPerWord); - - compiler::push(c, ceilingDivide(secondSize, TargetBytesPerWord), second); - compiler::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); - - if (threadParameter) { - ++ stackSize; - - compiler::push(c, 1, register_(c, c->arch->thread())); - } - - Stack* argumentStack = c->stack; - c->stack = oldStack; - - appendCall - (c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, - resultSize, argumentStack, stackSize, 0); - } else { - append - (c, new(c->zone) - CombineEvent - (c, type, - firstSize, first, - secondSize, second, - resultSize, result, - SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), - SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex))); - } -} - class TranslateEvent: public Event { public: TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize, diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index e96a7c8d08..d238f54bd8 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -65,10 +65,27 @@ void maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, const SiteMask& dstMask); + +Site* +maybeMove(Context* c, Value* v, const SiteMask& mask, bool intersectMask, + bool includeNextWord, unsigned registerReserveCount = 0); + +Site* +maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, + unsigned registerReserveCount = 0); Site* pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, unsigned index); +void push(Context* c, unsigned footprint, Value* v); + +Site* +pickTargetSite(Context* c, Read* read, bool intersectRead = false, + unsigned registerReserveCount = 0, + CostCalculator* costCalculator = 0); +Value* +register_(Context* c, int number); + Event::Event(Context* c): next(0), stackBefore(c->stack), localsBefore(c->locals), stackAfter(0), localsAfter(0), promises(0), reads(0), @@ -679,6 +696,242 @@ appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, SiteMask(srcTypeMask, srcRegisterMask >> 32, AnyFrameIndex))); } + +void +freezeSource(Context* c, unsigned size, Value* v) +{ + v->source->freeze(c, v); + if (size > vm::TargetBytesPerWord) { + v->nextWord->source->freeze(c, v->nextWord); + } +} + +void +thawSource(Context* c, unsigned size, Value* v) +{ + v->source->thaw(c, v); + if (size > vm::TargetBytesPerWord) { + v->nextWord->source->thaw(c, v->nextWord); + } +} + +Read* liveNext(Context* c, Value* v) { + assert(c, v->buddy->hasBuddy(c, v)); + + Read* r = v->reads->next(c); + if (valid(r)) return r; + + for (Value* p = v->buddy; p != v; p = p->buddy) { + if (valid(p->reads)) return p->reads; + } + + return 0; +} + +void preserve(Context* c, Value* v, Read* r, Site* s) { + s->freeze(c, v); + + maybeMove(c, r, false, true, 0); + + s->thaw(c, v); +} + +Site* getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask) { + Site* s; + Value* v; + Read* r = liveNext(c, value); + if (value->source->match + (c, static_cast(resultMask)) + and (r == 0 or value->source->loneMatch + (c, static_cast(resultMask)))) + { + s = value->source; + v = value; + if (r and v->uniqueSite(c, s)) { + preserve(c, v, r, s); + } + } else { + SingleRead r(resultMask, 0); + r.value = result; + r.successor_ = result; + s = pickTargetSite(c, &r, true); + v = result; + result->addSite(c, s); + } + + v->removeSite(c, s); + + s->freeze(c, v); + + return s; +} + +class CombineEvent: public Event { + public: + CombineEvent(Context* c, lir::TernaryOperation type, + unsigned firstSize, Value* first, + unsigned secondSize, Value* second, + unsigned resultSize, Value* result, + const SiteMask& firstLowMask, + const SiteMask& firstHighMask, + const SiteMask& secondLowMask, + const SiteMask& secondHighMask): + Event(c), type(type), firstSize(firstSize), first(first), + secondSize(secondSize), second(second), resultSize(resultSize), + result(result) + { + this->addReads(c, first, firstSize, firstLowMask, firstHighMask); + + if (resultSize > vm::TargetBytesPerWord) { + result->grow(c); + } + + bool condensed = c->arch->alwaysCondensed(type); + + this->addReads(c, second, secondSize, + secondLowMask, condensed ? result : 0, + secondHighMask, condensed ? result->nextWord : 0); + } + + virtual const char* name() { + return "CombineEvent"; + } + + virtual void compile(Context* c) { + assert(c, first->source->type(c) == first->nextWord->source->type(c)); + + // if (second->source->type(c) != second->nextWord->source->type(c)) { + // fprintf(stderr, "%p %p %d : %p %p %d\n", + // second, second->source, second->source->type(c), + // second->nextWord, second->nextWord->source, + // second->nextWord->source->type(c)); + // } + + assert(c, second->source->type(c) == second->nextWord->source->type(c)); + + freezeSource(c, firstSize, first); + + uint8_t cTypeMask; + uint64_t cRegisterMask; + + c->arch->planDestination + (type, + firstSize, + 1 << first->source->type(c), + (static_cast(first->nextWord->source->registerMask(c)) << 32) + | static_cast(first->source->registerMask(c)), + secondSize, + 1 << second->source->type(c), + (static_cast(second->nextWord->source->registerMask(c)) << 32) + | static_cast(second->source->registerMask(c)), + resultSize, + &cTypeMask, + &cRegisterMask); + + SiteMask resultLowMask(cTypeMask, cRegisterMask, AnyFrameIndex); + SiteMask resultHighMask(cTypeMask, cRegisterMask >> 32, AnyFrameIndex); + + Site* low = getTarget(c, second, result, resultLowMask); + unsigned lowSize = low->registerSize(c); + Site* high + = (resultSize > lowSize + ? getTarget(c, second->nextWord, result->nextWord, resultHighMask) + : low); + +// fprintf(stderr, "combine %p:%p and %p:%p into %p:%p\n", +// first, first->nextWord, +// second, second->nextWord, +// result, result->nextWord); + + apply(c, type, + firstSize, first->source, first->nextWord->source, + secondSize, second->source, second->nextWord->source, + resultSize, low, high); + + thawSource(c, firstSize, first); + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + low->thaw(c, second); + if (resultSize > lowSize) { + high->thaw(c, second->nextWord); + } + + if (live(c, result)) { + result->addSite(c, low); + if (resultSize > lowSize and live(c, result->nextWord)) { + result->nextWord->addSite(c, high); + } + } + } + + lir::TernaryOperation type; + unsigned firstSize; + Value* first; + unsigned secondSize; + Value* second; + unsigned resultSize; + Value* result; +}; + +void +appendCombine(Context* c, lir::TernaryOperation type, + unsigned firstSize, Value* first, + unsigned secondSize, Value* second, + unsigned resultSize, Value* result) +{ + bool thunk; + uint8_t firstTypeMask; + uint64_t firstRegisterMask; + uint8_t secondTypeMask; + uint64_t secondRegisterMask; + + c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask, + secondSize, &secondTypeMask, &secondRegisterMask, + resultSize, &thunk); + + if (thunk) { + Stack* oldStack = c->stack; + + bool threadParameter; + intptr_t handler = c->client->getThunk + (type, firstSize, resultSize, &threadParameter); + + unsigned stackSize = vm::ceilingDivide(secondSize, vm::TargetBytesPerWord) + + vm::ceilingDivide(firstSize, vm::TargetBytesPerWord); + + compiler::push(c, vm::ceilingDivide(secondSize, vm::TargetBytesPerWord), second); + compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), first); + + if (threadParameter) { + ++ stackSize; + + compiler::push(c, 1, register_(c, c->arch->thread())); + } + + Stack* argumentStack = c->stack; + c->stack = oldStack; + + appendCall + (c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, + resultSize, argumentStack, stackSize, 0); + } else { + append + (c, new(c->zone) + CombineEvent + (c, type, + firstSize, first, + secondSize, second, + resultSize, result, + SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), + SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex), + SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex), + SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex))); + } +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 6dbbd018d4..08de6e26c9 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -122,6 +122,12 @@ void appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst); +void +appendCombine(Context* c, lir::TernaryOperation type, + unsigned firstSize, Value* first, + unsigned secondSize, Value* second, + unsigned resultSize, Value* result); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/read.h b/src/codegen/compiler/read.h index 52db19b0e8..e221dfb4bb 100644 --- a/src/codegen/compiler/read.h +++ b/src/codegen/compiler/read.h @@ -43,6 +43,10 @@ class Read { Read* eventNext; }; +inline bool valid(Read* r) { + return r and r->valid(); +} + class SingleRead: public Read { public: SingleRead(const SiteMask& mask, Value* successor); diff --git a/src/codegen/compiler/regalloc.cpp b/src/codegen/compiler/regalloc.cpp index 2727b569c4..60fb2c7100 100644 --- a/src/codegen/compiler/regalloc.cpp +++ b/src/codegen/compiler/regalloc.cpp @@ -26,7 +26,6 @@ RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFil { } -bool uniqueSite(Context* c, Value* v, Site* s); unsigned totalFrameSize(Context* c); Read* live(Context* c UNUSED, Value* v); @@ -45,7 +44,7 @@ resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, if (v and r->value->isBuddyOf(v)) { return baseCost; - } else if (uniqueSite(c, r->value, r->site)) { + } else if (r->value->uniqueSite(c, r->site)) { return baseCost + Target::StealUniquePenalty; } else { return baseCost = Target::StealPenalty; diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp index 62fe9c86a5..cc3ac08092 100644 --- a/src/codegen/compiler/value.cpp +++ b/src/codegen/compiler/value.cpp @@ -100,6 +100,50 @@ bool Value::hasSite(Context* c) { return it.hasMore(); } +bool Value::uniqueSite(Context* c, Site* s) { + SiteIterator it(c, this); + Site* p UNUSED = it.next(); + if (it.hasMore()) { + // the site is not this word's only site, but if the site is + // shared with the next word, it may be that word's only site + if (this->nextWord != this and s->registerSize(c) > vm::TargetBytesPerWord) { + SiteIterator nit(c, this->nextWord); + Site* p = nit.next(); + if (nit.hasMore()) { + return false; + } else { + return p == s; + } + } else { + return false; + } + } else { + assert(c, p == s); + return true; + } +} + + +#ifndef NDEBUG +bool Value::hasBuddy(Context* c, Value* b) { + Value* a = this; + if (a == b) { + return true; + } + + int i = 0; + for (Value* p = a->buddy; p != a; p = p->buddy) { + if (p == b) { + return true; + } + if (++i > 1000) { + abort(c); + } + } + return false; +} +#endif // not NDEBUG + Value* value(Context* c, lir::ValueType type, Site* site, Site* target) { return new(c->zone) Value(site, target, type); diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index 0543ec3c74..f567c86cd5 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -57,6 +57,14 @@ class Value: public Compiler::Operand { void removeSite(Context* c, Site* s); bool hasSite(Context* c); + + bool uniqueSite(Context* c, Site* s); + + +#ifndef NDEBUG + bool hasBuddy(Context* c, Value* b); +#endif // not NDEBUG + }; From 70f9209a6ed7b55915cdd76ae305be14f52d5d68 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 20:31:28 -0700 Subject: [PATCH 224/378] move TranslateEvent out of compiler.cpp --- src/codegen/compiler.cpp | 113 --------------------------------- src/codegen/compiler/event.cpp | 113 +++++++++++++++++++++++++++++++++ src/codegen/compiler/event.h | 4 ++ 3 files changed, 117 insertions(+), 113 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 9af7e73e97..e747e5668a 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -1595,119 +1595,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -class TranslateEvent: public Event { - public: - TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize, - Value* value, unsigned resultSize, Value* result, - const SiteMask& valueLowMask, - const SiteMask& valueHighMask): - Event(c), type(type), valueSize(valueSize), resultSize(resultSize), - value(value), result(result) - { - bool condensed = c->arch->alwaysCondensed(type); - - if (resultSize > TargetBytesPerWord) { - result->grow(c); - } - - this->addReads(c, value, valueSize, valueLowMask, condensed ? result : 0, - valueHighMask, condensed ? result->nextWord : 0); - } - - virtual const char* name() { - return "TranslateEvent"; - } - - virtual void compile(Context* c) { - assert(c, value->source->type(c) == value->nextWord->source->type(c)); - - uint8_t bTypeMask; - uint64_t bRegisterMask; - - c->arch->planDestination - (type, - valueSize, - 1 << value->source->type(c), - (static_cast(value->nextWord->source->registerMask(c)) << 32) - | static_cast(value->source->registerMask(c)), - resultSize, - &bTypeMask, - &bRegisterMask); - - SiteMask resultLowMask(bTypeMask, bRegisterMask, AnyFrameIndex); - SiteMask resultHighMask(bTypeMask, bRegisterMask >> 32, AnyFrameIndex); - - Site* low = getTarget(c, value, result, resultLowMask); - unsigned lowSize = low->registerSize(c); - Site* high - = (resultSize > lowSize - ? getTarget(c, value->nextWord, result->nextWord, resultHighMask) - : low); - - apply(c, type, valueSize, value->source, value->nextWord->source, - resultSize, low, high); - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - - low->thaw(c, value); - if (resultSize > lowSize) { - high->thaw(c, value->nextWord); - } - - if (live(c, result)) { - result->addSite(c, low); - if (resultSize > lowSize and live(c, result->nextWord)) { - result->nextWord->addSite(c, high); - } - } - } - - lir::BinaryOperation type; - unsigned valueSize; - unsigned resultSize; - Value* value; - Value* result; - Read* resultRead; - SiteMask resultLowMask; - SiteMask resultHighMask; -}; - -void -appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, - Value* first, unsigned resultSize, Value* result) -{ - bool thunk; - uint8_t firstTypeMask; - uint64_t firstRegisterMask; - - c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask, - resultSize, &thunk); - - if (thunk) { - Stack* oldStack = c->stack; - - compiler::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first); - - Stack* argumentStack = c->stack; - c->stack = oldStack; - - appendCall - (c, value - (c, lir::ValueGeneral, constantSite - (c, c->client->getThunk(type, firstSize, resultSize))), - 0, 0, result, resultSize, argumentStack, - ceilingDivide(firstSize, TargetBytesPerWord), 0); - } else { - append(c, new(c->zone) - TranslateEvent - (c, type, firstSize, first, resultSize, result, - SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), - SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex))); - } -} - class OperationEvent: public Event { public: OperationEvent(Context* c, lir::Operation op): diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index d238f54bd8..c98cbacbf3 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -932,6 +932,119 @@ appendCombine(Context* c, lir::TernaryOperation type, } } +class TranslateEvent: public Event { + public: + TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize, + Value* value, unsigned resultSize, Value* result, + const SiteMask& valueLowMask, + const SiteMask& valueHighMask): + Event(c), type(type), valueSize(valueSize), resultSize(resultSize), + value(value), result(result) + { + bool condensed = c->arch->alwaysCondensed(type); + + if (resultSize > vm::TargetBytesPerWord) { + result->grow(c); + } + + this->addReads(c, value, valueSize, valueLowMask, condensed ? result : 0, + valueHighMask, condensed ? result->nextWord : 0); + } + + virtual const char* name() { + return "TranslateEvent"; + } + + virtual void compile(Context* c) { + assert(c, value->source->type(c) == value->nextWord->source->type(c)); + + uint8_t bTypeMask; + uint64_t bRegisterMask; + + c->arch->planDestination + (type, + valueSize, + 1 << value->source->type(c), + (static_cast(value->nextWord->source->registerMask(c)) << 32) + | static_cast(value->source->registerMask(c)), + resultSize, + &bTypeMask, + &bRegisterMask); + + SiteMask resultLowMask(bTypeMask, bRegisterMask, AnyFrameIndex); + SiteMask resultHighMask(bTypeMask, bRegisterMask >> 32, AnyFrameIndex); + + Site* low = getTarget(c, value, result, resultLowMask); + unsigned lowSize = low->registerSize(c); + Site* high + = (resultSize > lowSize + ? getTarget(c, value->nextWord, result->nextWord, resultHighMask) + : low); + + apply(c, type, valueSize, value->source, value->nextWord->source, + resultSize, low, high); + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + low->thaw(c, value); + if (resultSize > lowSize) { + high->thaw(c, value->nextWord); + } + + if (live(c, result)) { + result->addSite(c, low); + if (resultSize > lowSize and live(c, result->nextWord)) { + result->nextWord->addSite(c, high); + } + } + } + + lir::BinaryOperation type; + unsigned valueSize; + unsigned resultSize; + Value* value; + Value* result; + Read* resultRead; + SiteMask resultLowMask; + SiteMask resultHighMask; +}; + +void +appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, + Value* first, unsigned resultSize, Value* result) +{ + bool thunk; + uint8_t firstTypeMask; + uint64_t firstRegisterMask; + + c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask, + resultSize, &thunk); + + if (thunk) { + Stack* oldStack = c->stack; + + compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), first); + + Stack* argumentStack = c->stack; + c->stack = oldStack; + + appendCall + (c, value + (c, lir::ValueGeneral, constantSite + (c, c->client->getThunk(type, firstSize, resultSize))), + 0, 0, result, resultSize, argumentStack, + vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), 0); + } else { + append(c, new(c->zone) + TranslateEvent + (c, type, firstSize, first, resultSize, result, + SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), + SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex))); + } +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 08de6e26c9..a87619e0a7 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -128,6 +128,10 @@ appendCombine(Context* c, lir::TernaryOperation type, unsigned secondSize, Value* second, unsigned resultSize, Value* result); +void +appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, + Value* first, unsigned resultSize, Value* result); + } // namespace compiler } // namespace codegen } // namespace avian From 9c102bc1a861a19c5efd7189725d8c9f299df221 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 20:33:33 -0700 Subject: [PATCH 225/378] move OperationEvent out of compiler.cpp --- src/codegen/compiler.cpp | 23 ----------------------- src/codegen/compiler/event.cpp | 23 +++++++++++++++++++++++ src/codegen/compiler/event.h | 3 +++ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index e747e5668a..8265fc3a58 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -1595,29 +1595,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -class OperationEvent: public Event { - public: - OperationEvent(Context* c, lir::Operation op): - Event(c), op(op) - { } - - virtual const char* name() { - return "OperationEvent"; - } - - virtual void compile(Context* c) { - c->assembler->apply(op); - } - - lir::Operation op; -}; - -void -appendOperation(Context* c, lir::Operation op) -{ - append(c, new(c->zone) OperationEvent(c, op)); -} - void moveIfConflict(Context* c, Value* v, MemorySite* s) { diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index c98cbacbf3..b0ccd3a48e 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -1045,6 +1045,29 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, } } +class OperationEvent: public Event { + public: + OperationEvent(Context* c, lir::Operation op): + Event(c), op(op) + { } + + virtual const char* name() { + return "OperationEvent"; + } + + virtual void compile(Context* c) { + c->assembler->apply(op); + } + + lir::Operation op; +}; + +void +appendOperation(Context* c, lir::Operation op) +{ + append(c, new(c->zone) OperationEvent(c, op)); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index a87619e0a7..22a812657b 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -132,6 +132,9 @@ void appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, Value* first, unsigned resultSize, Value* result); +void +appendOperation(Context* c, lir::Operation op); + } // namespace compiler } // namespace codegen } // namespace avian From 18e6f28ff4e53513b22aa378bc0dbf3bf1351552 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 20:36:37 -0700 Subject: [PATCH 226/378] move MemoryEvent out of compiler.cpp --- src/codegen/compiler.cpp | 107 +-------------------------------- src/codegen/compiler/event.cpp | 106 ++++++++++++++++++++++++++++++++ src/codegen/compiler/event.h | 4 ++ 3 files changed, 111 insertions(+), 106 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 8265fc3a58..ab16fb5446 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -1272,16 +1272,7 @@ pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, } ConstantSite* -findConstantSite(Context* c, Value* v) -{ - for (SiteIterator it(c, v); it.hasMore();) { - Site* s = it.next(); - if (s->type(c) == lir::ConstantOperand) { - return static_cast(s); - } - } - return 0; -} +findConstantSite(Context* c, Value* v); Site* getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask); @@ -1595,102 +1586,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -void -moveIfConflict(Context* c, Value* v, MemorySite* s) -{ - if (v->reads) { - SiteMask mask(1 << lir::RegisterOperand, ~0, AnyFrameIndex); - v->reads->intersect(&mask); - if (s->conflicts(mask)) { - maybeMove(c, v->reads, true, false); - v->removeSite(c, s); - } - } -} - -class MemoryEvent: public Event { - public: - MemoryEvent(Context* c, Value* base, int displacement, Value* index, - unsigned scale, Value* result): - Event(c), base(base), displacement(displacement), index(index), - scale(scale), result(result) - { - this->addRead(c, base, generalRegisterMask(c)); - if (index) { - this->addRead(c, index, generalRegisterOrConstantMask(c)); - } - } - - virtual const char* name() { - return "MemoryEvent"; - } - - virtual void compile(Context* c) { - int indexRegister; - int displacement = this->displacement; - unsigned scale = this->scale; - if (index) { - ConstantSite* constant = findConstantSite(c, index); - - if (constant) { - indexRegister = lir::NoRegister; - displacement += (constant->value->value() * scale); - scale = 1; - } else { - assert(c, index->source->type(c) == lir::RegisterOperand); - indexRegister = static_cast(index->source)->number; - } - } else { - indexRegister = lir::NoRegister; - } - assert(c, base->source->type(c) == lir::RegisterOperand); - int baseRegister = static_cast(base->source)->number; - - popRead(c, this, base); - if (index) { - if (TargetBytesPerWord == 8 and indexRegister != lir::NoRegister) { - apply(c, lir::Move, 4, index->source, index->source, - 8, index->source, index->source); - } - - popRead(c, this, index); - } - - MemorySite* site = memorySite - (c, baseRegister, displacement, indexRegister, scale); - - MemorySite* low; - if (result->nextWord != result) { - MemorySite* high = static_cast(site->copyHigh(c)); - low = static_cast(site->copyLow(c)); - - result->nextWord->target = high; - result->nextWord->addSite(c, high); - moveIfConflict(c, result->nextWord, high); - } else { - low = site; - } - - result->target = low; - result->addSite(c, low); - moveIfConflict(c, result, low); - } - - Value* base; - int displacement; - Value* index; - unsigned scale; - Value* result; -}; - -void -appendMemory(Context* c, Value* base, int displacement, Value* index, - unsigned scale, Value* result) -{ - append(c, new(c->zone) - MemoryEvent(c, base, displacement, index, scale, result)); -} - double asFloat(unsigned size, int64_t v) { diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index b0ccd3a48e..4073bcad69 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -1068,6 +1068,112 @@ appendOperation(Context* c, lir::Operation op) append(c, new(c->zone) OperationEvent(c, op)); } +ConstantSite* findConstantSite(Context* c, Value* v) { + for (SiteIterator it(c, v); it.hasMore();) { + Site* s = it.next(); + if (s->type(c) == lir::ConstantOperand) { + return static_cast(s); + } + } + return 0; +} + +void +moveIfConflict(Context* c, Value* v, MemorySite* s) +{ + if (v->reads) { + SiteMask mask(1 << lir::RegisterOperand, ~0, AnyFrameIndex); + v->reads->intersect(&mask); + if (s->conflicts(mask)) { + maybeMove(c, v->reads, true, false); + v->removeSite(c, s); + } + } +} + +class MemoryEvent: public Event { + public: + MemoryEvent(Context* c, Value* base, int displacement, Value* index, + unsigned scale, Value* result): + Event(c), base(base), displacement(displacement), index(index), + scale(scale), result(result) + { + this->addRead(c, base, generalRegisterMask(c)); + if (index) { + this->addRead(c, index, generalRegisterOrConstantMask(c)); + } + } + + virtual const char* name() { + return "MemoryEvent"; + } + + virtual void compile(Context* c) { + int indexRegister; + int displacement = this->displacement; + unsigned scale = this->scale; + if (index) { + ConstantSite* constant = findConstantSite(c, index); + + if (constant) { + indexRegister = lir::NoRegister; + displacement += (constant->value->value() * scale); + scale = 1; + } else { + assert(c, index->source->type(c) == lir::RegisterOperand); + indexRegister = static_cast(index->source)->number; + } + } else { + indexRegister = lir::NoRegister; + } + assert(c, base->source->type(c) == lir::RegisterOperand); + int baseRegister = static_cast(base->source)->number; + + popRead(c, this, base); + if (index) { + if (vm::TargetBytesPerWord == 8 and indexRegister != lir::NoRegister) { + apply(c, lir::Move, 4, index->source, index->source, + 8, index->source, index->source); + } + + popRead(c, this, index); + } + + MemorySite* site = memorySite + (c, baseRegister, displacement, indexRegister, scale); + + MemorySite* low; + if (result->nextWord != result) { + MemorySite* high = static_cast(site->copyHigh(c)); + low = static_cast(site->copyLow(c)); + + result->nextWord->target = high; + result->nextWord->addSite(c, high); + moveIfConflict(c, result->nextWord, high); + } else { + low = site; + } + + result->target = low; + result->addSite(c, low); + moveIfConflict(c, result, low); + } + + Value* base; + int displacement; + Value* index; + unsigned scale; + Value* result; +}; + +void +appendMemory(Context* c, Value* base, int displacement, Value* index, + unsigned scale, Value* result) +{ + append(c, new(c->zone) + MemoryEvent(c, base, displacement, index, scale, result)); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 22a812657b..89188a245b 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -135,6 +135,10 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, void appendOperation(Context* c, lir::Operation op); +void +appendMemory(Context* c, Value* base, int displacement, Value* index, + unsigned scale, Value* result); + } // namespace compiler } // namespace codegen } // namespace avian From 65b7cf047c9c5534a32b4d32ce4c3e7987d30a8e Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 20:43:42 -0700 Subject: [PATCH 227/378] move BranchEvent out of compiler.cpp --- src/codegen/compiler.cpp | 237 --------------------------------- src/codegen/compiler/event.cpp | 235 ++++++++++++++++++++++++++++++++ src/codegen/compiler/event.h | 4 + 3 files changed, 239 insertions(+), 237 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index ab16fb5446..d44426b46f 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -1586,243 +1586,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -double -asFloat(unsigned size, int64_t v) -{ - if (size == 4) { - return bitsToFloat(v); - } else { - return bitsToDouble(v); - } -} - -bool -unordered(double a, double b) -{ - return not (a >= b or a < b); -} - -bool -shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b, - int64_t a) -{ - switch (type) { - case lir::JumpIfEqual: - return a == b; - - case lir::JumpIfNotEqual: - return a != b; - - case lir::JumpIfLess: - return a < b; - - case lir::JumpIfGreater: - return a > b; - - case lir::JumpIfLessOrEqual: - return a <= b; - - case lir::JumpIfGreaterOrEqual: - return a >= b; - - case lir::JumpIfFloatEqual: - return asFloat(size, a) == asFloat(size, b); - - case lir::JumpIfFloatNotEqual: - return asFloat(size, a) != asFloat(size, b); - - case lir::JumpIfFloatLess: - return asFloat(size, a) < asFloat(size, b); - - case lir::JumpIfFloatGreater: - return asFloat(size, a) > asFloat(size, b); - - case lir::JumpIfFloatLessOrEqual: - return asFloat(size, a) <= asFloat(size, b); - - case lir::JumpIfFloatGreaterOrEqual: - return asFloat(size, a) >= asFloat(size, b); - - case lir::JumpIfFloatLessOrUnordered: - return asFloat(size, a) < asFloat(size, b) - or unordered(asFloat(size, a), asFloat(size, b)); - - case lir::JumpIfFloatGreaterOrUnordered: - return asFloat(size, a) > asFloat(size, b) - or unordered(asFloat(size, a), asFloat(size, b)); - - case lir::JumpIfFloatLessOrEqualOrUnordered: - return asFloat(size, a) <= asFloat(size, b) - or unordered(asFloat(size, a), asFloat(size, b)); - - case lir::JumpIfFloatGreaterOrEqualOrUnordered: - return asFloat(size, a) >= asFloat(size, b) - or unordered(asFloat(size, a), asFloat(size, b)); - - default: - abort(c); - } -} - -lir::TernaryOperation -thunkBranch(Context* c, lir::TernaryOperation type) -{ - switch (type) { - case lir::JumpIfFloatEqual: - return lir::JumpIfEqual; - - case lir::JumpIfFloatNotEqual: - return lir::JumpIfNotEqual; - - case lir::JumpIfFloatLess: - case lir::JumpIfFloatLessOrUnordered: - return lir::JumpIfLess; - - case lir::JumpIfFloatGreater: - case lir::JumpIfFloatGreaterOrUnordered: - return lir::JumpIfGreater; - - case lir::JumpIfFloatLessOrEqual: - case lir::JumpIfFloatLessOrEqualOrUnordered: - return lir::JumpIfLessOrEqual; - - case lir::JumpIfFloatGreaterOrEqual: - case lir::JumpIfFloatGreaterOrEqualOrUnordered: - return lir::JumpIfGreaterOrEqual; - - default: - abort(c); - } -} - -class BranchEvent: public Event { - public: - BranchEvent(Context* c, lir::TernaryOperation type, unsigned size, - Value* first, Value* second, Value* address, - const SiteMask& firstLowMask, - const SiteMask& firstHighMask, - const SiteMask& secondLowMask, - const SiteMask& secondHighMask): - Event(c), type(type), size(size), first(first), second(second), - address(address) - { - this->addReads(c, first, size, firstLowMask, firstHighMask); - this->addReads(c, second, size, secondLowMask, secondHighMask); - - uint8_t typeMask; - uint64_t registerMask; - c->arch->planDestination(type, size, 0, 0, size, 0, 0, TargetBytesPerWord, - &typeMask, ®isterMask); - - this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); - } - - virtual const char* name() { - return "BranchEvent"; - } - - virtual void compile(Context* c) { - ConstantSite* firstConstant = findConstantSite(c, first); - ConstantSite* secondConstant = findConstantSite(c, second); - - if (not this->isUnreachable()) { - if (firstConstant - and secondConstant - and firstConstant->value->resolved() - and secondConstant->value->resolved()) - { - int64_t firstValue = firstConstant->value->value(); - int64_t secondValue = secondConstant->value->value(); - - if (size > TargetBytesPerWord) { - firstValue |= findConstantSite - (c, first->nextWord)->value->value() << 32; - secondValue |= findConstantSite - (c, second->nextWord)->value->value() << 32; - } - - if (shouldJump(c, type, size, firstValue, secondValue)) { - apply(c, lir::Jump, TargetBytesPerWord, address->source, address->source); - } - } else { - freezeSource(c, size, first); - freezeSource(c, size, second); - freezeSource(c, TargetBytesPerWord, address); - - apply(c, type, size, first->source, first->nextWord->source, - size, second->source, second->nextWord->source, - TargetBytesPerWord, address->source, address->source); - - thawSource(c, TargetBytesPerWord, address); - thawSource(c, size, second); - thawSource(c, size, first); - } - } - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - } - - virtual bool isBranch() { return true; } - - lir::TernaryOperation type; - unsigned size; - Value* first; - Value* second; - Value* address; -}; - -void -appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first, - Value* second, Value* address) -{ - bool thunk; - uint8_t firstTypeMask; - uint64_t firstRegisterMask; - uint8_t secondTypeMask; - uint64_t secondRegisterMask; - - c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask, - size, &secondTypeMask, &secondRegisterMask, - TargetBytesPerWord, &thunk); - - if (thunk) { - Stack* oldStack = c->stack; - - bool threadParameter; - intptr_t handler = c->client->getThunk - (type, size, size, &threadParameter); - - assert(c, not threadParameter); - - compiler::push(c, ceilingDivide(size, TargetBytesPerWord), second); - compiler::push(c, ceilingDivide(size, TargetBytesPerWord), first); - - Stack* argumentStack = c->stack; - c->stack = oldStack; - - Value* result = value(c, lir::ValueGeneral); - appendCall - (c, value - (c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4, - argumentStack, ceilingDivide(size, TargetBytesPerWord) * 2, 0); - - appendBranch(c, thunkBranch(c, type), 4, value - (c, lir::ValueGeneral, constantSite(c, static_cast(0))), - result, address); - } else { - append - (c, new(c->zone) - BranchEvent - (c, type, size, first, second, address, - SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), - SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex))); - } -} - class JumpEvent: public Event { public: JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit, diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 4073bcad69..1722714df4 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -1174,6 +1174,241 @@ appendMemory(Context* c, Value* base, int displacement, Value* index, MemoryEvent(c, base, displacement, index, scale, result)); } +double asFloat(unsigned size, int64_t v) { + if (size == 4) { + return vm::bitsToFloat(v); + } else { + return vm::bitsToDouble(v); + } +} + +bool +unordered(double a, double b) +{ + return not (a >= b or a < b); +} + +bool +shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b, + int64_t a) +{ + switch (type) { + case lir::JumpIfEqual: + return a == b; + + case lir::JumpIfNotEqual: + return a != b; + + case lir::JumpIfLess: + return a < b; + + case lir::JumpIfGreater: + return a > b; + + case lir::JumpIfLessOrEqual: + return a <= b; + + case lir::JumpIfGreaterOrEqual: + return a >= b; + + case lir::JumpIfFloatEqual: + return asFloat(size, a) == asFloat(size, b); + + case lir::JumpIfFloatNotEqual: + return asFloat(size, a) != asFloat(size, b); + + case lir::JumpIfFloatLess: + return asFloat(size, a) < asFloat(size, b); + + case lir::JumpIfFloatGreater: + return asFloat(size, a) > asFloat(size, b); + + case lir::JumpIfFloatLessOrEqual: + return asFloat(size, a) <= asFloat(size, b); + + case lir::JumpIfFloatGreaterOrEqual: + return asFloat(size, a) >= asFloat(size, b); + + case lir::JumpIfFloatLessOrUnordered: + return asFloat(size, a) < asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case lir::JumpIfFloatGreaterOrUnordered: + return asFloat(size, a) > asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case lir::JumpIfFloatLessOrEqualOrUnordered: + return asFloat(size, a) <= asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return asFloat(size, a) >= asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + default: + abort(c); + } +} + +lir::TernaryOperation +thunkBranch(Context* c, lir::TernaryOperation type) +{ + switch (type) { + case lir::JumpIfFloatEqual: + return lir::JumpIfEqual; + + case lir::JumpIfFloatNotEqual: + return lir::JumpIfNotEqual; + + case lir::JumpIfFloatLess: + case lir::JumpIfFloatLessOrUnordered: + return lir::JumpIfLess; + + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatGreaterOrUnordered: + return lir::JumpIfGreater; + + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqualOrUnordered: + return lir::JumpIfLessOrEqual; + + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return lir::JumpIfGreaterOrEqual; + + default: + abort(c); + } +} + +class BranchEvent: public Event { + public: + BranchEvent(Context* c, lir::TernaryOperation type, unsigned size, + Value* first, Value* second, Value* address, + const SiteMask& firstLowMask, + const SiteMask& firstHighMask, + const SiteMask& secondLowMask, + const SiteMask& secondHighMask): + Event(c), type(type), size(size), first(first), second(second), + address(address) + { + this->addReads(c, first, size, firstLowMask, firstHighMask); + this->addReads(c, second, size, secondLowMask, secondHighMask); + + uint8_t typeMask; + uint64_t registerMask; + c->arch->planDestination(type, size, 0, 0, size, 0, 0, vm::TargetBytesPerWord, + &typeMask, ®isterMask); + + this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + } + + virtual const char* name() { + return "BranchEvent"; + } + + virtual void compile(Context* c) { + ConstantSite* firstConstant = findConstantSite(c, first); + ConstantSite* secondConstant = findConstantSite(c, second); + + if (not this->isUnreachable()) { + if (firstConstant + and secondConstant + and firstConstant->value->resolved() + and secondConstant->value->resolved()) + { + int64_t firstValue = firstConstant->value->value(); + int64_t secondValue = secondConstant->value->value(); + + if (size > vm::TargetBytesPerWord) { + firstValue |= findConstantSite + (c, first->nextWord)->value->value() << 32; + secondValue |= findConstantSite + (c, second->nextWord)->value->value() << 32; + } + + if (shouldJump(c, type, size, firstValue, secondValue)) { + apply(c, lir::Jump, vm::TargetBytesPerWord, address->source, address->source); + } + } else { + freezeSource(c, size, first); + freezeSource(c, size, second); + freezeSource(c, vm::TargetBytesPerWord, address); + + apply(c, type, size, first->source, first->nextWord->source, + size, second->source, second->nextWord->source, + vm::TargetBytesPerWord, address->source, address->source); + + thawSource(c, vm::TargetBytesPerWord, address); + thawSource(c, size, second); + thawSource(c, size, first); + } + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + } + + virtual bool isBranch() { return true; } + + lir::TernaryOperation type; + unsigned size; + Value* first; + Value* second; + Value* address; +}; + +void +appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first, + Value* second, Value* address) +{ + bool thunk; + uint8_t firstTypeMask; + uint64_t firstRegisterMask; + uint8_t secondTypeMask; + uint64_t secondRegisterMask; + + c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask, + size, &secondTypeMask, &secondRegisterMask, + vm::TargetBytesPerWord, &thunk); + + if (thunk) { + Stack* oldStack = c->stack; + + bool threadParameter; + intptr_t handler = c->client->getThunk + (type, size, size, &threadParameter); + + assert(c, not threadParameter); + + compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), second); + compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), first); + + Stack* argumentStack = c->stack; + c->stack = oldStack; + + Value* result = value(c, lir::ValueGeneral); + appendCall + (c, value + (c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4, + argumentStack, vm::ceilingDivide(size, vm::TargetBytesPerWord) * 2, 0); + + appendBranch(c, thunkBranch(c, type), 4, value + (c, lir::ValueGeneral, constantSite(c, static_cast(0))), + result, address); + } else { + append + (c, new(c->zone) + BranchEvent + (c, type, size, first, second, address, + SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), + SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex), + SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex), + SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex))); + } +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 89188a245b..97686c22cf 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -139,6 +139,10 @@ void appendMemory(Context* c, Value* base, int displacement, Value* index, unsigned scale, Value* result); +void +appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first, + Value* second, Value* address); + } // namespace compiler } // namespace codegen } // namespace avian From d00950458f3705993e7e0beaeb630e6973fb518f Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 21:34:59 -0700 Subject: [PATCH 228/378] move JumpEvent out of compiler.cpp --- makefile | 1 + src/codegen/compiler.cpp | 232 +-------------------------------- src/codegen/compiler/event.cpp | 97 +++++++++++++- src/codegen/compiler/event.h | 4 + src/codegen/compiler/frame.cpp | 119 +++++++++++++++++ src/codegen/compiler/frame.h | 75 +++++++++++ src/codegen/compiler/stack.h | 35 ----- 7 files changed, 297 insertions(+), 266 deletions(-) create mode 100644 src/codegen/compiler/frame.cpp create mode 100644 src/codegen/compiler/frame.h delete mode 100644 src/codegen/compiler/stack.h diff --git a/makefile b/makefile index 5e14ad1d7e..1dd25da9a6 100755 --- a/makefile +++ b/makefile @@ -961,6 +961,7 @@ ifeq ($(process),compile) $(src)/codegen/compiler/read.cpp \ $(src)/codegen/compiler/event.cpp \ $(src)/codegen/compiler/promise.cpp \ + $(src)/codegen/compiler/frame.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index d44426b46f..e8bba8e44f 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -22,8 +22,8 @@ #include "codegen/compiler/site.h" #include "codegen/compiler/read.h" #include "codegen/compiler/event.h" -#include "codegen/compiler/stack.h" #include "codegen/compiler/promise.h" +#include "codegen/compiler/frame.h" using namespace vm; @@ -67,11 +67,6 @@ apply(Context* c, lir::TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); -class Local { - public: - Value* value; -}; - class ForkElement { public: Value* value; @@ -220,118 +215,6 @@ countSuccessors(Link* link) return c; } -unsigned -totalFrameSize(Context* c) -{ - return c->alignedFrameSize - + c->arch->frameHeaderSize() - + c->arch->argumentFootprint(c->parameterFootprint); -} - -int -frameIndex(Context* c, int localIndex) -{ - assert(c, localIndex >= 0); - - int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1; - - if (localIndex < static_cast(c->parameterFootprint)) { - index += c->arch->frameHeaderSize(); - } else { - index -= c->arch->frameFooterSize(); - } - - assert(c, index >= 0); - assert(c, static_cast(index) < totalFrameSize(c)); - - return index; -} - -unsigned -frameIndexToOffset(Context* c, unsigned frameIndex) -{ - assert(c, frameIndex < totalFrameSize(c)); - - return (frameIndex + c->arch->frameFooterSize()) * TargetBytesPerWord; -} - -unsigned -offsetToFrameIndex(Context* c, unsigned offset) -{ - assert(c, static_cast - ((offset / TargetBytesPerWord) - c->arch->frameFooterSize()) >= 0); - assert(c, ((offset / TargetBytesPerWord) - c->arch->frameFooterSize()) - < totalFrameSize(c)); - - return (offset / TargetBytesPerWord) - c->arch->frameFooterSize(); -} - -unsigned -frameBase(Context* c) -{ - return c->alignedFrameSize - - c->arch->frameReturnAddressSize() - - c->arch->frameFooterSize() - + c->arch->frameHeaderSize(); -} - -class FrameIterator { - public: - class Element { - public: - Element(Value* value, unsigned localIndex): - value(value), localIndex(localIndex) - { } - - Value* const value; - const unsigned localIndex; - }; - - FrameIterator(Context* c, Stack* stack, Local* locals, - bool includeEmpty = false): - stack(stack), locals(locals), localIndex(c->localFootprint - 1), - includeEmpty(includeEmpty) - { } - - bool hasMore() { - if (not includeEmpty) { - while (stack and stack->value == 0) stack = stack->next; - - while (localIndex >= 0 and locals[localIndex].value == 0) -- localIndex; - } - - return stack != 0 or localIndex >= 0; - } - - Element next(Context* c) { - Value* v; - unsigned li; - if (stack) { - Stack* s = stack; - v = s->value; - li = s->index + c->localFootprint; - stack = stack->next; - } else { - Local* l = locals + localIndex; - v = l->value; - li = localIndex; - -- localIndex; - } - return Element(v, li); - } - - Stack* stack; - Local* locals; - int localIndex; - bool includeEmpty; -}; - -int -frameIndex(Context* c, FrameIterator::Element* element) -{ - return frameIndex(c, element->localIndex); -} - void clearSites(Context* c, Value* v) { @@ -1021,44 +904,6 @@ apply(Context* c, lir::TernaryOperation op, OperandInfo(s3Size, s3Type, &s3Union)); } -void -clean(Context* c, Value* v, unsigned popIndex) -{ - for (SiteIterator it(c, v); it.hasMore();) { - Site* s = it.next(); - if (not (s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex)) - and offsetToFrameIndex - (c, static_cast(s)->offset) - >= popIndex)) - { - if (false and - s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex))) - { - char buffer[256]; s->toString(c, buffer, 256); - fprintf(stderr, "remove %s from %p at %d pop offset 0x%x\n", - buffer, v, offsetToFrameIndex - (c, static_cast(s)->offset), - frameIndexToOffset(c, popIndex)); - } - it.remove(c); - } - } -} - -void -clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, - unsigned popIndex) -{ - for (FrameIterator it(c, stack, locals); it.hasMore();) { - FrameIterator::Element e = it.next(c); - clean(c, e.value, popIndex); - } - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, e, r->value); - } -} - void append(Context* c, Event* e); @@ -1366,12 +1211,6 @@ makeSnapshots(Context* c, Value* value, Snapshot* next) return next; } -Stack* -stack(Context* c, Value* value, Stack* next) -{ - return new(c->zone) Stack(next ? next->index + 1 : 0, value, next); -} - Value* maybeBuddy(Context* c, Value* v); @@ -1586,63 +1425,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -class JumpEvent: public Event { - public: - JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit, - bool cleanLocals): - Event(c), type(type), address(address), exit(exit), - cleanLocals(cleanLocals) - { - bool thunk; - uint8_t typeMask; - uint64_t registerMask; - c->arch->plan(type, TargetBytesPerWord, &typeMask, ®isterMask, &thunk); - - assert(c, not thunk); - - this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); - } - - virtual const char* name() { - return "JumpEvent"; - } - - virtual void compile(Context* c) { - if (not this->isUnreachable()) { - apply(c, type, TargetBytesPerWord, address->source, address->source); - } - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - - if (cleanLocals) { - for (FrameIterator it(c, 0, c->locals); it.hasMore();) { - FrameIterator::Element e = it.next(c); - clean(c, e.value, 0); - } - } - } - - virtual bool isBranch() { return true; } - - virtual bool allExits() { - return exit or this->isUnreachable(); - } - - lir::UnaryOperation type; - Value* address; - bool exit; - bool cleanLocals; -}; - -void -appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false, - bool cleanLocals = false) -{ - append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); -} - class BoundsCheckEvent: public Event { public: BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset, @@ -2053,7 +1835,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "resolve original %s for %p local %d frame %d\n", - buffer, v, el.localIndex, frameIndex(c, &el)); + buffer, v, el.localIndex, el.frameIndex(c)); } Site* target = pickSiteOrMove @@ -2068,7 +1850,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "freeze original %s for %p local %d frame %d\n", - buffer, v, el.localIndex, frameIndex(c, &el)); + buffer, v, el.localIndex, el.frameIndex(c)); } Value dummy(0, 0, lir::ValueGeneral); @@ -2101,7 +1883,7 @@ resolveSourceSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) if (DebugControl) { char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "resolve source %s from %p local %d frame %d\n", - buffer, v, el.localIndex, frameIndex(c, &el)); + buffer, v, el.localIndex, el.frameIndex(c)); } freeze(c, frozen, s, v); @@ -2142,7 +1924,7 @@ resolveTargetSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) if (DebugControl) { char buffer[256]; sites[el.localIndex]->toString(c, buffer, 256); fprintf(stderr, "resolve target %s for %p local %d frame %d\n", - buffer, el.value, el.localIndex, frameIndex(c, &el)); + buffer, el.value, el.localIndex, el.frameIndex(c)); } } } @@ -2258,11 +2040,11 @@ setSites(Context* c, Event* e, Site** sites) } else if (DebugControl) { char buffer[256]; sitesToString(c, sites[el.localIndex], buffer, 256); fprintf(stderr, "skip sites %s for %p local %d frame %d\n", - buffer, el.value, el.localIndex, frameIndex(c, &el)); + buffer, el.value, el.localIndex, el.frameIndex(c)); } } else if (DebugControl) { fprintf(stderr, "no sites for %p local %d frame %d\n", - el.value, el.localIndex, frameIndex(c, &el)); + el.value, el.localIndex, el.frameIndex(c)); } } } diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 1722714df4..93f12c62b1 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -13,21 +13,16 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/event.h" -#include "codegen/compiler/stack.h" #include "codegen/compiler/site.h" #include "codegen/compiler/read.h" #include "codegen/compiler/value.h" #include "codegen/compiler/promise.h" +#include "codegen/compiler/frame.h" namespace avian { namespace codegen { namespace compiler { - -unsigned frameBase(Context* c); -unsigned totalFrameSize(Context* c); -int frameIndex(Context* c, int localIndex); - SiteMask generalRegisterMask(Context* c); SiteMask generalRegisterOrConstantMask(Context* c); @@ -1409,6 +1404,96 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first } } +void clean(Context* c, Value* v, unsigned popIndex) { + for (SiteIterator it(c, v); it.hasMore();) { + Site* s = it.next(); + if (not (s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex)) + and offsetToFrameIndex + (c, static_cast(s)->offset) + >= popIndex)) + { + if (false and + s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex))) + { + char buffer[256]; s->toString(c, buffer, 256); + fprintf(stderr, "remove %s from %p at %d pop offset 0x%x\n", + buffer, v, offsetToFrameIndex + (c, static_cast(s)->offset), + frameIndexToOffset(c, popIndex)); + } + it.remove(c); + } + } +} + +void +clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, + unsigned popIndex) +{ + for (FrameIterator it(c, stack, locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + clean(c, e.value, popIndex); + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, e, r->value); + } +} + +class JumpEvent: public Event { + public: + JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit, + bool cleanLocals): + Event(c), type(type), address(address), exit(exit), + cleanLocals(cleanLocals) + { + bool thunk; + uint8_t typeMask; + uint64_t registerMask; + c->arch->plan(type, vm::TargetBytesPerWord, &typeMask, ®isterMask, &thunk); + + assert(c, not thunk); + + this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + } + + virtual const char* name() { + return "JumpEvent"; + } + + virtual void compile(Context* c) { + if (not this->isUnreachable()) { + apply(c, type, vm::TargetBytesPerWord, address->source, address->source); + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + if (cleanLocals) { + for (FrameIterator it(c, 0, c->locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + clean(c, e.value, 0); + } + } + } + + virtual bool isBranch() { return true; } + + virtual bool allExits() { + return exit or this->isUnreachable(); + } + + lir::UnaryOperation type; + Value* address; + bool exit; + bool cleanLocals; +}; + +void appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit, bool cleanLocals) { + append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 97686c22cf..d3a171baee 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -143,6 +143,10 @@ void appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first, Value* second, Value* address); +void +appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false, + bool cleanLocals = false); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/frame.cpp b/src/codegen/compiler/frame.cpp new file mode 100644 index 0000000000..e879238b79 --- /dev/null +++ b/src/codegen/compiler/frame.cpp @@ -0,0 +1,119 @@ +/* Copyright (c) 2008-2012, 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 "target.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/frame.h" + +namespace avian { +namespace codegen { +namespace compiler { + +unsigned totalFrameSize(Context* c) { + return c->alignedFrameSize + + c->arch->frameHeaderSize() + + c->arch->argumentFootprint(c->parameterFootprint); +} + +int frameIndex(Context* c, int localIndex) { + assert(c, localIndex >= 0); + + int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1; + + if (localIndex < static_cast(c->parameterFootprint)) { + index += c->arch->frameHeaderSize(); + } else { + index -= c->arch->frameFooterSize(); + } + + assert(c, index >= 0); + assert(c, static_cast(index) < totalFrameSize(c)); + + return index; +} + +unsigned frameIndexToOffset(Context* c, unsigned frameIndex) { + assert(c, frameIndex < totalFrameSize(c)); + + return (frameIndex + c->arch->frameFooterSize()) * vm::TargetBytesPerWord; +} + +unsigned offsetToFrameIndex(Context* c, unsigned offset) { + assert(c, static_cast + ((offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize()) >= 0); + assert(c, ((offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize()) + < totalFrameSize(c)); + + return (offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize(); +} + +unsigned frameBase(Context* c) { + return c->alignedFrameSize + - c->arch->frameReturnAddressSize() + - c->arch->frameFooterSize() + + c->arch->frameHeaderSize(); +} + +FrameIterator::Element::Element(Value* value, unsigned localIndex): + value(value), localIndex(localIndex) +{ } + + +int FrameIterator::Element::frameIndex(Context* c) { + return compiler::frameIndex(c, this->localIndex); +} + +FrameIterator::FrameIterator(Context* c, Stack* stack, Local* locals, + bool includeEmpty): + stack(stack), locals(locals), localIndex(c->localFootprint - 1), + includeEmpty(includeEmpty) +{ } + +bool FrameIterator::hasMore() { + if (not includeEmpty) { + while (stack and stack->value == 0) { + stack = stack->next; + } + + while (localIndex >= 0 and locals[localIndex].value == 0) { + -- localIndex; + } + } + + return stack != 0 or localIndex >= 0; +} + +FrameIterator::Element FrameIterator::next(Context* c) { + Value* v; + unsigned li; + if (stack) { + Stack* s = stack; + v = s->value; + li = s->index + c->localFootprint; + stack = stack->next; + } else { + Local* l = locals + localIndex; + v = l->value; + li = localIndex; + -- localIndex; + } + return Element(v, li); +} + +Stack* stack(Context* c, Value* value, Stack* next) { + return new(c->zone) Stack(next ? next->index + 1 : 0, value, next); +} + + + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/frame.h b/src/codegen/compiler/frame.h new file mode 100644 index 0000000000..3ae47dfae9 --- /dev/null +++ b/src/codegen/compiler/frame.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_FRAME_H +#define AVIAN_CODEGEN_COMPILER_FRAME_H + +namespace avian { +namespace codegen { +namespace compiler { + +unsigned totalFrameSize(Context* c); + +int frameIndex(Context* c, int localIndex); + +unsigned frameIndexToOffset(Context* c, unsigned frameIndex); + +unsigned offsetToFrameIndex(Context* c, unsigned offset); + +unsigned frameBase(Context* c); + +class FrameIterator { + public: + class Element { + public: + Element(Value* value, unsigned localIndex); + + int frameIndex(Context* c); + + Value* const value; + const unsigned localIndex; + }; + + FrameIterator(Context* c, Stack* stack, Local* locals, + bool includeEmpty = false); + + bool hasMore(); + + Element next(Context* c); + + Stack* stack; + Local* locals; + int localIndex; + bool includeEmpty; +}; + +class Local { + public: + Value* value; +}; + +class Stack { + public: + Stack(unsigned index, Value* value, Stack* next): + index(index), value(value), next(next) + { } + + unsigned index; + Value* value; + Stack* next; +}; + +Stack* stack(Context* c, Value* value, Stack* next); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_FRAME_H diff --git a/src/codegen/compiler/stack.h b/src/codegen/compiler/stack.h deleted file mode 100644 index 7ae8c4f7c1..0000000000 --- a/src/codegen/compiler/stack.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2008-2012, Avian Contributors - - Permission to use, copy, modify, and/or distribute this software - for any purpose with or without fee is hereby granted, provided - that the above copyright notice and this permission notice appear - in all copies. - - There is NO WARRANTY for this software. See license.txt for - details. */ - -#ifndef AVIAN_CODEGEN_COMPILER_STACK_H -#define AVIAN_CODEGEN_COMPILER_STACK_H - -namespace avian { -namespace codegen { -namespace compiler { - -class Value; - -class Stack { - public: - Stack(unsigned index, Value* value, Stack* next): - index(index), value(value), next(next) - { } - - unsigned index; - Value* value; - Stack* next; -}; - -} // namespace compiler -} // namespace codegen -} // namespace avian - -#endif // AVIAN_CODEGEN_COMPILER_STACK_H From be86d26512407b788c52c9a8422fcf534c189643 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 21:49:37 -0700 Subject: [PATCH 229/378] move BoundsCheckEvent out of compiler.cpp --- src/codegen/compiler.cpp | 101 +------------------------------ src/codegen/compiler/event.cpp | 84 +++++++++++++++++++++++++ src/codegen/compiler/event.h | 4 ++ src/codegen/compiler/promise.cpp | 36 ++++++++++- src/codegen/compiler/promise.h | 26 +++----- src/codegen/compiler/site.cpp | 10 +-- 6 files changed, 137 insertions(+), 124 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index e8bba8e44f..ee79e97a8f 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -14,6 +14,7 @@ #include "codegen/compiler.h" #include "codegen/assembler.h" +#include "codegen/promise.h" #include "codegen/compiler/regalloc.h" #include "codegen/compiler/context.h" @@ -358,18 +359,6 @@ valueType(Context* c, Compiler::OperandType type) } } -Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new(c->zone) ShiftMaskPromise(base, shift, mask); -} - -Promise* combinedPromise(Context* c, Promise* low, Promise* high) { - return new(c->zone) CombinedPromise(low, high); -} - -Promise* resolved(Context* c, int64_t value) { - return new(c->zone) ResolvedPromise(value); -} - void move(Context* c, Value* value, Site* src, Site* dst); @@ -1425,90 +1414,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -class BoundsCheckEvent: public Event { - public: - BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset, - Value* index, intptr_t handler): - Event(c), object(object), lengthOffset(lengthOffset), index(index), - handler(handler) - { - this->addRead(c, object, generalRegisterMask(c)); - this->addRead(c, index, generalRegisterOrConstantMask(c)); - } - - virtual const char* name() { - return "BoundsCheckEvent"; - } - - virtual void compile(Context* c) { - Assembler* a = c->assembler; - - ConstantSite* constant = findConstantSite(c, index); - CodePromise* outOfBoundsPromise = 0; - - if (constant) { - if (constant->value->value() < 0) { - lir::Constant handlerConstant(resolved(c, handler)); - a->apply(lir::Call, - OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); - } - } else { - outOfBoundsPromise = compiler::codePromise(c, static_cast(0)); - - ConstantSite zero(resolved(c, 0)); - ConstantSite oob(outOfBoundsPromise); - apply(c, lir::JumpIfLess, - 4, &zero, &zero, - 4, index->source, index->source, - TargetBytesPerWord, &oob, &oob); - } - - if (constant == 0 or constant->value->value() >= 0) { - assert(c, object->source->type(c) == lir::RegisterOperand); - MemorySite length(static_cast(object->source)->number, - lengthOffset, lir::NoRegister, 1); - length.acquired = true; - - CodePromise* nextPromise = compiler::codePromise(c, static_cast(0)); - - freezeSource(c, TargetBytesPerWord, index); - - ConstantSite next(nextPromise); - apply(c, lir::JumpIfGreater, - 4, index->source, - index->source, 4, &length, - &length, TargetBytesPerWord, &next, &next); - - thawSource(c, TargetBytesPerWord, index); - - if (constant == 0) { - outOfBoundsPromise->offset = a->offset(); - } - - lir::Constant handlerConstant(resolved(c, handler)); - a->apply(lir::Call, - OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); - - nextPromise->offset = a->offset(); - } - - popRead(c, this, object); - popRead(c, this, index); - } - - Value* object; - unsigned lengthOffset; - Value* index; - intptr_t handler; -}; - -void -appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, - Value* index, intptr_t handler) -{ - append(c, new(c->zone) BoundsCheckEvent(c, object, lengthOffset, index, handler)); -} - class FrameSiteEvent: public Event { public: FrameSiteEvent(Context* c, Value* value, int index): @@ -2650,7 +2555,7 @@ class MyCompiler: public Compiler { } virtual Promise* poolAppend(intptr_t value) { - return poolAppendPromise(resolved(&c, value)); + return poolAppendPromise(resolvedPromise(&c, value)); } virtual Promise* poolAppendPromise(Promise* value) { @@ -2670,7 +2575,7 @@ class MyCompiler: public Compiler { } virtual Operand* constant(int64_t value, Compiler::OperandType type) { - return promiseConstant(resolved(&c, value), type); + return promiseConstant(resolvedPromise(&c, value), type); } virtual Operand* promiseConstant(Promise* value, Compiler::OperandType type) { diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 93f12c62b1..abb170bb1b 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -1494,6 +1494,90 @@ void appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit, append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); } +class BoundsCheckEvent: public Event { + public: + BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset, + Value* index, intptr_t handler): + Event(c), object(object), lengthOffset(lengthOffset), index(index), + handler(handler) + { + this->addRead(c, object, generalRegisterMask(c)); + this->addRead(c, index, generalRegisterOrConstantMask(c)); + } + + virtual const char* name() { + return "BoundsCheckEvent"; + } + + virtual void compile(Context* c) { + Assembler* a = c->assembler; + + ConstantSite* constant = findConstantSite(c, index); + CodePromise* outOfBoundsPromise = 0; + + if (constant) { + if (constant->value->value() < 0) { + lir::Constant handlerConstant(resolvedPromise(c, handler)); + a->apply(lir::Call, + OperandInfo(vm::TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); + } + } else { + outOfBoundsPromise = compiler::codePromise(c, static_cast(0)); + + ConstantSite zero(resolvedPromise(c, 0)); + ConstantSite oob(outOfBoundsPromise); + apply(c, lir::JumpIfLess, + 4, &zero, &zero, + 4, index->source, index->source, + vm::TargetBytesPerWord, &oob, &oob); + } + + if (constant == 0 or constant->value->value() >= 0) { + assert(c, object->source->type(c) == lir::RegisterOperand); + MemorySite length(static_cast(object->source)->number, + lengthOffset, lir::NoRegister, 1); + length.acquired = true; + + CodePromise* nextPromise = compiler::codePromise(c, static_cast(0)); + + freezeSource(c, vm::TargetBytesPerWord, index); + + ConstantSite next(nextPromise); + apply(c, lir::JumpIfGreater, + 4, index->source, + index->source, 4, &length, + &length, vm::TargetBytesPerWord, &next, &next); + + thawSource(c, vm::TargetBytesPerWord, index); + + if (constant == 0) { + outOfBoundsPromise->offset = a->offset(); + } + + lir::Constant handlerConstant(resolvedPromise(c, handler)); + a->apply(lir::Call, + OperandInfo(vm::TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); + + nextPromise->offset = a->offset(); + } + + popRead(c, this, object); + popRead(c, this, index); + } + + Value* object; + unsigned lengthOffset; + Value* index; + intptr_t handler; +}; + +void +appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, + Value* index, intptr_t handler) +{ + append(c, new(c->zone) BoundsCheckEvent(c, object, lengthOffset, index, handler)); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index d3a171baee..ecefcf85d6 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -147,6 +147,10 @@ void appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false, bool cleanLocals = false); +void +appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, + Value* index, intptr_t handler); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/promise.cpp b/src/codegen/compiler/promise.cpp index ceb25d89e7..e4e55edbc9 100644 --- a/src/codegen/compiler/promise.cpp +++ b/src/codegen/compiler/promise.cpp @@ -15,12 +15,42 @@ namespace avian { namespace codegen { namespace compiler { -CodePromise* -codePromise(Context* c, Promise* offset) -{ +CodePromise::CodePromise(Context* c, CodePromise* next): + c(c), offset(0), next(next) +{ } + +CodePromise::CodePromise(Context* c, Promise* offset): + c(c), offset(offset), next(0) +{ } + +int64_t CodePromise::value() { + if (resolved()) { + return reinterpret_cast(c->machineCode + offset->value()); + } + + abort(c); +} + +bool CodePromise::resolved() { + return c->machineCode != 0 and offset and offset->resolved(); +} + +CodePromise* codePromise(Context* c, Promise* offset) { return new (c->zone) CodePromise(c, offset); } +Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { + return new (c->zone) ShiftMaskPromise(base, shift, mask); +} + +Promise* combinedPromise(Context* c, Promise* low, Promise* high) { + return new (c->zone) CombinedPromise(low, high); +} + +Promise* resolvedPromise(Context* c, int64_t value) { + return new (c->zone) ResolvedPromise(value); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/promise.h b/src/codegen/compiler/promise.h index 2afcd49304..d7262b3724 100644 --- a/src/codegen/compiler/promise.h +++ b/src/codegen/compiler/promise.h @@ -18,25 +18,13 @@ namespace compiler { class CodePromise: public Promise { public: - CodePromise(Context* c, CodePromise* next): - c(c), offset(0), next(next) - { } + CodePromise(Context* c, CodePromise* next); - CodePromise(Context* c, Promise* offset): - c(c), offset(offset), next(0) - { } + CodePromise(Context* c, Promise* offset); - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast(c->machineCode + offset->value()); - } - - abort(c); - } + virtual int64_t value(); - virtual bool resolved() { - return c->machineCode != 0 and offset and offset->resolved(); - } + virtual bool resolved(); Context* c; Promise* offset; @@ -45,6 +33,12 @@ class CodePromise: public Promise { CodePromise* codePromise(Context* c, Promise* offset); +Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask); + +Promise* combinedPromise(Context* c, Promise* low, Promise* high); + +Promise* resolvedPromise(Context* c, int64_t value); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp index d05a09cd64..dc877b9e1e 100644 --- a/src/codegen/compiler/site.cpp +++ b/src/codegen/compiler/site.cpp @@ -14,18 +14,14 @@ #include "codegen/compiler/value.h" #include "codegen/compiler/site.h" #include "codegen/compiler/resource.h" +#include "codegen/compiler/frame.h" +#include "codegen/compiler/promise.h" namespace avian { namespace codegen { namespace compiler { -unsigned frameIndexToOffset(Context* c, unsigned frameIndex); - -unsigned offsetToFrameIndex(Context* c, unsigned offset); - -ResolvedPromise* resolved(Context* c, int64_t value); - int intersectFrameIndexes(int a, int b) { if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex; @@ -120,7 +116,7 @@ Site* constantSite(Context* c, Promise* value) { } Site* constantSite(Context* c, int64_t value) { - return constantSite(c, resolved(c, value)); + return constantSite(c, resolvedPromise(c, value)); } From 94ddb62b5fccca6a2ce9ecf060e10aadd7fdbefa Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 21:52:07 -0700 Subject: [PATCH 230/378] move FrameSiteEvent out of compiler.cpp --- src/codegen/compiler.cpp | 26 -------------------------- src/codegen/compiler/event.cpp | 27 +++++++++++++++++++++++++++ src/codegen/compiler/event.h | 3 +++ 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index ee79e97a8f..5f1f9ab431 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -1414,32 +1414,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -class FrameSiteEvent: public Event { - public: - FrameSiteEvent(Context* c, Value* value, int index): - Event(c), value(value), index(index) - { } - - virtual const char* name() { - return "FrameSiteEvent"; - } - - virtual void compile(Context* c) { - if (live(c, value)) { - value->addSite(c, frameSite(c, index)); - } - } - - Value* value; - int index; -}; - -void -appendFrameSite(Context* c, Value* value, int index) -{ - append(c, new(c->zone) FrameSiteEvent(c, value, index)); -} - unsigned frameFootprint(Context* c, Stack* s) { diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index abb170bb1b..68d3bccfd6 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -1578,6 +1578,33 @@ appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, append(c, new(c->zone) BoundsCheckEvent(c, object, lengthOffset, index, handler)); } + +class FrameSiteEvent: public Event { + public: + FrameSiteEvent(Context* c, Value* value, int index): + Event(c), value(value), index(index) + { } + + virtual const char* name() { + return "FrameSiteEvent"; + } + + virtual void compile(Context* c) { + if (live(c, value)) { + value->addSite(c, frameSite(c, index)); + } + } + + Value* value; + int index; +}; + +void +appendFrameSite(Context* c, Value* value, int index) +{ + append(c, new(c->zone) FrameSiteEvent(c, value, index)); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index ecefcf85d6..c28fa6230b 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -151,6 +151,9 @@ void appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, Value* index, intptr_t handler); +void +appendFrameSite(Context* c, Value* value, int index); + } // namespace compiler } // namespace codegen } // namespace avian From 64d58bdb290ecc4fdf55d46029903f6c11b5e1fb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Feb 2013 08:48:32 -0700 Subject: [PATCH 231/378] update bootimage.cpp and heapwalk.cpp to reflect function renames --- src/bootimage.cpp | 6 +++--- src/heapwalk.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 5a57a40e1c..111d850f97 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -14,7 +14,7 @@ #include "machine.h" #include "util.h" #include "stream.h" -#include "assembler.h" +#include "codegen/assembler.h" #include "target.h" #include "binaryToObject/tools.h" #include "lzma.h" @@ -31,7 +31,7 @@ namespace { const unsigned HeapCapacity = 512 * 1024 * 1024; const unsigned TargetFixieSizeInBytes = 8 + (TargetBytesPerWord * 2); -const unsigned TargetFixieSizeInWords = ceiling +const unsigned TargetFixieSizeInWords = ceilingDivide (TargetFixieSizeInBytes, TargetBytesPerWord); const unsigned TargetFixieAge = 0; const unsigned TargetFixieFlags = 2; @@ -787,7 +787,7 @@ targetSize(Thread* t, object typeMaps, object referer, unsigned refererOffset, { return (TargetBytesPerWord * 2) + pad - (ceiling + (ceilingDivide (objectMaskCount (classTypeMap(t, typeMaps, referer)), 32) * 4, TargetBytesPerWord); } else { diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index 69840abf16..8732d28497 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -228,7 +228,8 @@ inline object get(object o, unsigned offsetInWords) { return static_cast - (mask(fieldAtOffset(o, offsetInWords * BytesPerWord))); + (maskAlignedPointer + (fieldAtOffset(o, offsetInWords * BytesPerWord))); } unsigned @@ -297,7 +298,8 @@ class MyHeapWalker: public HeapWalker { Visitor(Context* c, HeapVisitor* v): c(c), v(v) { } virtual void visit(void* p) { - walk(c, v, static_cast(mask(*static_cast(p)))); + walk(c, v, static_cast + (maskAlignedPointer(*static_cast(p)))); } Context* c; From b8fd040ac15be98c74b93a6ca287db827d73bf1b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Feb 2013 09:04:04 -0700 Subject: [PATCH 232/378] include util/runtime-array.h in windows.cpp to fix build --- src/windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/windows.cpp b/src/windows.cpp index 02ebfc72b5..5c85eb906e 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -25,6 +25,7 @@ #include "arch.h" #include "system.h" +#include "util/runtime-array.h" #if defined(WINAPI_FAMILY) From a7ab59f1f6caa2c765edc86439e51f5d4d905788 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Feb 2013 09:09:30 -0700 Subject: [PATCH 233/378] switch clean target back to deleting all generated files --- makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/makefile b/makefile index 1dd25da9a6..8a3b4a7e81 100755 --- a/makefile +++ b/makefile @@ -1278,11 +1278,6 @@ clean-current: .PHONY: clean clean: - @echo "removing $(build)" - rm -rf $(build) - -.PHONY: clean-all -clean-all: @echo "removing build" rm -rf build From 2db0303e2f21a6331c6d33269d65c78e27499709 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 23:23:07 -0700 Subject: [PATCH 234/378] further compiler cleanup / organization --- makefile | 1 + src/codegen/compiler.cpp | 282 ++----------------------------- src/codegen/compiler/context.h | 12 ++ src/codegen/compiler/event.cpp | 88 ++++++++++ src/codegen/compiler/event.h | 10 ++ src/codegen/compiler/ir.cpp | 48 ++++++ src/codegen/compiler/ir.h | 90 ++++++++++ src/codegen/compiler/promise.cpp | 60 +++++++ src/codegen/compiler/promise.h | 4 + src/codegen/compiler/value.cpp | 10 ++ src/codegen/compiler/value.h | 1 + 11 files changed, 339 insertions(+), 267 deletions(-) create mode 100644 src/codegen/compiler/ir.cpp create mode 100644 src/codegen/compiler/ir.h diff --git a/makefile b/makefile index 8a3b4a7e81..b83d2d45a7 100755 --- a/makefile +++ b/makefile @@ -962,6 +962,7 @@ ifeq ($(process),compile) $(src)/codegen/compiler/event.cpp \ $(src)/codegen/compiler/promise.cpp \ $(src)/codegen/compiler/frame.cpp \ + $(src)/codegen/compiler/ir.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 5f1f9ab431..23c62a8b5e 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -25,6 +25,7 @@ #include "codegen/compiler/event.h" #include "codegen/compiler/promise.h" #include "codegen/compiler/frame.h" +#include "codegen/compiler/ir.h" using namespace vm; @@ -45,14 +46,6 @@ const unsigned StealRegisterReserveCount = 2; // compare instruction: const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4); -class Stack; -class PushEvent; -class Read; -class MultiRead; -class StubRead; -class Block; -class Snapshot; - void apply(Context* c, lir::UnaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High); @@ -68,57 +61,6 @@ apply(Context* c, lir::TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); -class ForkElement { - public: - Value* value; - MultiRead* read; - bool local; -}; - -class ForkState: public Compiler::State { - public: - ForkState(Stack* stack, Local* locals, Cell* saved, Event* predecessor, - unsigned logicalIp): - stack(stack), - locals(locals), - saved(saved), - predecessor(predecessor), - logicalIp(logicalIp), - readCount(0) - { } - - Stack* stack; - Local* locals; - Cell* saved; - Event* predecessor; - unsigned logicalIp; - unsigned readCount; - ForkElement elements[0]; -}; - -class MySubroutine: public Compiler::Subroutine { - public: - MySubroutine(): forkState(0) { } - - ForkState* forkState; -}; - -class LogicalInstruction { - public: - LogicalInstruction(int index, Stack* stack, Local* locals): - firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack), - locals(locals), machineOffset(0), subroutine(0), index(index) - { } - - Event* firstEvent; - Event* lastEvent; - LogicalInstruction* immediatePredecessor; - Stack* stack; - Local* locals; - Promise* machineOffset; - MySubroutine* subroutine; - int index; -}; class ConstantPoolNode { public: @@ -128,106 +70,6 @@ class ConstantPoolNode { ConstantPoolNode* next; }; -class PoolPromise: public Promise { - public: - PoolPromise(Context* c, int key): c(c), key(key) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast - (c->machineCode + pad(c->machineCodeSize, TargetBytesPerWord) - + (key * TargetBytesPerWord)); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0; - } - - Context* c; - int key; -}; - -unsigned -machineOffset(Context* c, int logicalIp) -{ - return c->logicalCode[logicalIp]->machineOffset->value(); -} - -class IpPromise: public Promise { - public: - IpPromise(Context* c, int logicalIp): - c(c), - logicalIp(logicalIp) - { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast - (c->machineCode + machineOffset(c, logicalIp)); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0 - and c->logicalCode[logicalIp]->machineOffset->resolved(); - } - - Context* c; - int logicalIp; -}; - -template -Cell* reverseDestroy(Cell* cell) { - Cell* previous = 0; - while (cell) { - Cell* next = cell->next; - cell->next = previous; - previous = cell; - cell = next; - } - return previous; -} - -unsigned -countPredecessors(Link* link) -{ - unsigned c = 0; - for (; link; link = link->nextPredecessor) ++ c; - return c; -} - -Link* -lastPredecessor(Link* link) -{ - while (link->nextPredecessor) link = link->nextPredecessor; - return link; -} - -unsigned -countSuccessors(Link* link) -{ - unsigned c = 0; - for (; link; link = link->nextSuccessor) ++ c; - return c; -} - -void -clearSites(Context* c, Value* v) -{ - if (DebugSites) { - fprintf(stderr, "clear sites for %p\n", v); - } - for (SiteIterator it(c, v); it.hasMore();) { - it.next(); - it.remove(c); - } -} - Read* live(Context* c UNUSED, Value* v) { @@ -321,7 +163,7 @@ popRead(Context* c, Event* e UNUSED, Value* v) if (r) { deadBuddy(c, v, r); } else { - clearSites(c, v); + v->clearSites(c); } } } @@ -1140,11 +982,11 @@ removeBuddy(Context* c, Value* v) assert(c, p->buddy); if (not live(c, next)) { - clearSites(c, next); + next->clearSites(c); } if (not live(c, v)) { - clearSites(c, v); + v->clearSites(c); } } } @@ -1437,7 +1279,7 @@ visit(Context* c, Link* link) v->reads = p->read->nextTarget(); // fprintf(stderr, "next read %p for %p from %p\n", v->reads, v, p->read); if (not live(c, v)) { - clearSites(c, v); + v->clearSites(c); } } } @@ -1492,67 +1334,6 @@ appendBuddy(Context* c, Value* original, Value* buddy) append(c, new(c->zone) BuddyEvent(c, original, buddy)); } -class SaveLocalsEvent: public Event { - public: - SaveLocalsEvent(Context* c): - Event(c) - { - saveLocals(c, this); - } - - virtual const char* name() { - return "SaveLocalsEvent"; - } - - virtual void compile(Context* c) { - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - } -}; - -void -appendSaveLocals(Context* c) -{ - append(c, new(c->zone) SaveLocalsEvent(c)); -} - -class DummyEvent: public Event { - public: - DummyEvent(Context* c, Local* locals): - Event(c), - locals_(locals) - { } - - virtual const char* name() { - return "DummyEvent"; - } - - virtual void compile(Context*) { } - - virtual Local* locals() { - return locals_; - } - - Local* locals_; -}; - -void -appendDummy(Context* c) -{ - Stack* stack = c->stack; - Local* locals = c->locals; - LogicalInstruction* i = c->logicalCode[c->logicalIp]; - - c->stack = i->stack; - c->locals = i->locals; - - append(c, new(c->zone) DummyEvent(c, locals)); - - c->stack = stack; - c->locals = locals; -} - void append(Context* c, Event* e) { @@ -1898,11 +1679,11 @@ resetFrame(Context* c, Event* e) { for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) { FrameIterator::Element el = it.next(c); - clearSites(c, el.value); + el.value->clearSites(c); } while (c->acquiredResources) { - clearSites(c, c->acquiredResources->value); + c->acquiredResources->value->clearSites(c); } } @@ -2058,35 +1839,6 @@ updateJunctionReads(Context* c, JunctionState* state) } } -LogicalInstruction* -next(Context* c, LogicalInstruction* i) -{ - for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) { - i = c->logicalCode[n]; - if (i) return i; - } - return 0; -} - -class Block { - public: - Block(Event* head): - head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0) - { } - - Event* head; - Block* nextBlock; - LogicalInstruction* nextInstruction; - Assembler::Block* assemblerBlock; - unsigned start; -}; - -Block* -block(Context* c, Event* head) -{ - return new(c->zone) Block(head); -} - void compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) { @@ -2110,8 +1862,8 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) fprintf(stderr, " -- compile %s at %d with %d preds %d succs %d stack\n", e->name(), e->logicalInstruction->index, - countPredecessors(e->predecessors), - countSuccessors(e->successors), + e->predecessors->countPredecessors(), + e->successors->countSuccessors(), e->stackBefore ? e->stackBefore->index + 1 : 0); } @@ -2125,7 +1877,7 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) } if (e->predecessors) { - visit(c, lastPredecessor(e->predecessors)); + visit(c, e->predecessors->lastPredecessor()); Event* first = e->predecessors->predecessor; if (e->predecessors->nextPredecessor) { @@ -2191,7 +1943,7 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) a->endEvent(); - LogicalInstruction* nextInstruction = next(c, e->logicalInstruction); + LogicalInstruction* nextInstruction = e->logicalInstruction->next(c); if (e->next == 0 or (e->next->logicalInstruction != e->logicalInstruction and (e->next->logicalInstruction != nextInstruction @@ -2433,9 +2185,7 @@ class MyCompiler: public Compiler { memset(c.locals, 0, sizeof(Local) * localFootprint); - c.logicalCode[-1] = new - (c.zone->allocate(sizeof(LogicalInstruction))) - LogicalInstruction(-1, c.stack, c.locals); + c.logicalCode[-1] = new(c.zone) LogicalInstruction(-1, c.stack, c.locals); } virtual void visitLogicalIp(unsigned logicalIp) { @@ -2494,9 +2244,7 @@ class MyCompiler: public Compiler { p->localsAfter = c.locals; } - c.logicalCode[logicalIp] = new - (c.zone->allocate(sizeof(LogicalInstruction))) - LogicalInstruction(logicalIp, c.stack, c.locals); + c.logicalCode[logicalIp] = new(c.zone) LogicalInstruction(logicalIp, c.stack, c.locals); bool startSubroutine = c.subroutine != 0; if (startSubroutine) { @@ -2525,7 +2273,7 @@ class MyCompiler: public Compiler { } virtual Promise* machineIp(unsigned logicalIp) { - return new(c.zone) IpPromise(&c, logicalIp); + return ipPromise(&c, logicalIp); } virtual Promise* poolAppend(intptr_t value) { @@ -2533,7 +2281,7 @@ class MyCompiler: public Compiler { } virtual Promise* poolAppendPromise(Promise* value) { - Promise* p = new(c.zone) PoolPromise(&c, c.constantCount); + Promise* p = poolPromise(&c, c.constantCount); ConstantPoolNode* constant = new (c.zone) ConstantPoolNode(value); diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index 8508086978..974de8e17a 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -54,6 +54,18 @@ unsigned count(Cell* c) { return count; } +template +Cell* reverseDestroy(Cell* cell) { + Cell* previous = 0; + while (cell) { + Cell* next = cell->next; + cell->next = previous; + previous = cell; + cell = next; + } + return previous; +} + class Context { public: Context(vm::System* system, Assembler* assembler, vm::Zone* zone, diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 68d3bccfd6..ba8c0c222a 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -18,6 +18,7 @@ #include "codegen/compiler/value.h" #include "codegen/compiler/promise.h" #include "codegen/compiler/frame.h" +#include "codegen/compiler/ir.h" namespace avian { namespace codegen { @@ -148,6 +149,32 @@ bool Event::isUnreachable() { return this->predecessors != 0; } +unsigned Link::countPredecessors() { + Link* link = this; + unsigned c = 0; + for (; link; link = link->nextPredecessor) { + ++ c; + } + return c; +} + +Link* Link::lastPredecessor() { + Link* link = this; + while (link->nextPredecessor) { + link = link->nextPredecessor; + } + return link; +} + +unsigned Link::countSuccessors() { + Link* link = this; + unsigned c = 0; + for (; link; link = link->nextSuccessor) { + ++ c; + } + return c; +} + Link* link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, Link* nextSuccessor, ForkState* forkState) { @@ -1605,6 +1632,67 @@ appendFrameSite(Context* c, Value* value, int index) append(c, new(c->zone) FrameSiteEvent(c, value, index)); } +class SaveLocalsEvent: public Event { + public: + SaveLocalsEvent(Context* c): + Event(c) + { + saveLocals(c, this); + } + + virtual const char* name() { + return "SaveLocalsEvent"; + } + + virtual void compile(Context* c) { + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + } +}; + +void +appendSaveLocals(Context* c) +{ + append(c, new(c->zone) SaveLocalsEvent(c)); +} + +class DummyEvent: public Event { + public: + DummyEvent(Context* c, Local* locals): + Event(c), + locals_(locals) + { } + + virtual const char* name() { + return "DummyEvent"; + } + + virtual void compile(Context*) { } + + virtual Local* locals() { + return locals_; + } + + Local* locals_; +}; + +void +appendDummy(Context* c) +{ + Stack* stack = c->stack; + Local* locals = c->locals; + LogicalInstruction* i = c->logicalCode[c->logicalIp]; + + c->stack = i->stack; + c->locals = i->locals; + + append(c, new(c->zone) DummyEvent(c, locals)); + + c->stack = stack; + c->locals = locals; +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index c28fa6230b..504da33bae 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -97,6 +97,10 @@ class Link { junctionState(0) { } + unsigned countPredecessors(); + Link* lastPredecessor(); + unsigned countSuccessors(); + Event* predecessor; Link* nextPredecessor; Event* successor; @@ -154,6 +158,12 @@ appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, void appendFrameSite(Context* c, Value* value, int index); +void +appendSaveLocals(Context* c); + +void +appendDummy(Context* c); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/ir.cpp b/src/codegen/compiler/ir.cpp new file mode 100644 index 0000000000..671fd86df8 --- /dev/null +++ b/src/codegen/compiler/ir.cpp @@ -0,0 +1,48 @@ +/* Copyright (c) 2008-2012, 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 "codegen/compiler/context.h" +#include "codegen/compiler/ir.h" + +namespace avian { +namespace codegen { +namespace compiler { + +LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals): + firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack), + locals(locals), machineOffset(0), subroutine(0), index(index) +{ } + +LogicalInstruction* LogicalInstruction::next(Context* c) { + LogicalInstruction* i = this; + for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) { + i = c->logicalCode[n]; + if (i) return i; + } + return 0; +} + +unsigned +machineOffset(Context* c, int logicalIp) +{ + return c->logicalCode[logicalIp]->machineOffset->value(); +} + +Block::Block(Event* head): + head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0) +{ } + +Block* block(Context* c, Event* head) { + return new(c->zone) Block(head); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/ir.h b/src/codegen/compiler/ir.h new file mode 100644 index 0000000000..56a0283367 --- /dev/null +++ b/src/codegen/compiler/ir.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_IR_H +#define AVIAN_CODEGEN_COMPILER_IR_H + +namespace avian { +namespace codegen { +namespace compiler { + +class MultiRead; + +class ForkElement { + public: + Value* value; + MultiRead* read; + bool local; +}; + +class ForkState: public Compiler::State { + public: + ForkState(Stack* stack, Local* locals, Cell* saved, Event* predecessor, + unsigned logicalIp): + stack(stack), + locals(locals), + saved(saved), + predecessor(predecessor), + logicalIp(logicalIp), + readCount(0) + { } + + Stack* stack; + Local* locals; + Cell* saved; + Event* predecessor; + unsigned logicalIp; + unsigned readCount; + ForkElement elements[0]; +}; + +class LogicalInstruction { + public: + LogicalInstruction(int index, Stack* stack, Local* locals); + + LogicalInstruction* next(Context* c); + + Event* firstEvent; + Event* lastEvent; + LogicalInstruction* immediatePredecessor; + Stack* stack; + Local* locals; + Promise* machineOffset; + MySubroutine* subroutine; + int index; +}; + +class MySubroutine: public Compiler::Subroutine { + public: + MySubroutine(): forkState(0) { } + + ForkState* forkState; +}; + +class Block { + public: + Block(Event* head); + + Event* head; + Block* nextBlock; + LogicalInstruction* nextInstruction; + Assembler::Block* assemblerBlock; + unsigned start; +}; + +Block* block(Context* c, Event* head); + +unsigned machineOffset(Context* c, int logicalIp); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_IR_H diff --git a/src/codegen/compiler/promise.cpp b/src/codegen/compiler/promise.cpp index e4e55edbc9..fc5a69da63 100644 --- a/src/codegen/compiler/promise.cpp +++ b/src/codegen/compiler/promise.cpp @@ -8,8 +8,11 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include "target.h" + #include "codegen/compiler/context.h" #include "codegen/compiler/promise.h" +#include "codegen/compiler/ir.h" namespace avian { namespace codegen { @@ -51,6 +54,63 @@ Promise* resolvedPromise(Context* c, int64_t value) { return new (c->zone) ResolvedPromise(value); } +class IpPromise: public Promise { + public: + IpPromise(Context* c, int logicalIp): + c(c), + logicalIp(logicalIp) + { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast + (c->machineCode + machineOffset(c, logicalIp)); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0 + and c->logicalCode[logicalIp]->machineOffset->resolved(); + } + + Context* c; + int logicalIp; +}; + +Promise* ipPromise(Context* c, int logicalIp) { + return new (c->zone) IpPromise(c, logicalIp); +} + + +class PoolPromise: public Promise { + public: + PoolPromise(Context* c, int key): c(c), key(key) { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast + (c->machineCode + vm::pad(c->machineCodeSize, vm::TargetBytesPerWord) + + (key * vm::TargetBytesPerWord)); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0; + } + + Context* c; + int key; +}; + +Promise* poolPromise(Context* c, int key) { + return new(c->zone) PoolPromise(c, key); +} + + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/promise.h b/src/codegen/compiler/promise.h index d7262b3724..516782e0cd 100644 --- a/src/codegen/compiler/promise.h +++ b/src/codegen/compiler/promise.h @@ -39,6 +39,10 @@ Promise* combinedPromise(Context* c, Promise* low, Promise* high); Promise* resolvedPromise(Context* c, int64_t value); +Promise* ipPromise(Context* c, int logicalIp); + +Promise* poolPromise(Context* c, int key); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp index cc3ac08092..58c3f341ae 100644 --- a/src/codegen/compiler/value.cpp +++ b/src/codegen/compiler/value.cpp @@ -123,6 +123,16 @@ bool Value::uniqueSite(Context* c, Site* s) { } } +void Value::clearSites(Context* c) { + if (DebugSites) { + fprintf(stderr, "clear sites for %p\n", this); + } + for (SiteIterator it(c, this); it.hasMore();) { + it.next(); + it.remove(c); + } +} + #ifndef NDEBUG bool Value::hasBuddy(Context* c, Value* b) { diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index f567c86cd5..9cdac0bba3 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -60,6 +60,7 @@ class Value: public Compiler::Operand { bool uniqueSite(Context* c, Site* s); + void clearSites(Context* c); #ifndef NDEBUG bool hasBuddy(Context* c, Value* b); From 4568ece4afb07ababbba580478dbbb808e03965a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 14 Feb 2013 08:36:45 -0700 Subject: [PATCH 235/378] add note about using an absolute path for the openjdk option --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1e35318627..52bf9c844e 100644 --- a/README.md +++ b/README.md @@ -249,9 +249,11 @@ where OpenJDK is installed, e.g.: This will build Avian as a conventional JVM (e.g. libjvm.so) which loads its boot class library and native libraries (e.g. libjava.so) -from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. In this configuration, -OpenJDK needs to remain installed for Avian to work, and you can run -applications like this: +from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. Note that you must +use an absolute path here, or else the result will not work when run +from other directories. In this configuration, OpenJDK needs to +remain installed for Avian to work, and you can run applications like +this: $ build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ com.example.MyApplication From b4a73a2e0b4dceb5c1f7682fde4d7799c52b5cfa Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 14 Feb 2013 11:43:21 -0700 Subject: [PATCH 236/378] include runtime-array.h to fix arm build --- src/arm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arm.h b/src/arm.h index 5593c86f92..5d2835de14 100644 --- a/src/arm.h +++ b/src/arm.h @@ -13,6 +13,7 @@ #include "types.h" #include "common.h" +#include "util/runtime-array.h" #ifdef __APPLE__ # include "libkern/OSAtomic.h" From 1258b23ea1882fc73c762ab1bac6a7cf13ceafa1 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 14 Feb 2013 17:21:57 -0700 Subject: [PATCH 237/378] add remote-test capability To execute tests on a remote host (for instance, because you're cross-compiling), simply do: make remote-test=true remote-test-host= test You can set several variables to control the functionality of remote-test. See them below, along with their default values: remote-test-host = localhost # host to ssh to remote-test-port = 22 remote-test-user = ${USER} # user to execute tests as remote-test-dir = /tmp/avian-test-${USER} # dir to rsync build output to --- makefile | 30 ++++++++++++++++++++++++------ test/test.sh | 5 ++++- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/makefile b/makefile index b83d2d45a7..5ee56d857b 100755 --- a/makefile +++ b/makefile @@ -266,9 +266,14 @@ asm-output = -o $(1) asm-input = -c $(1) asm-format = S as = $(cc) -ld = $(cxx) +ld = $(cc) build-ld = $(build-cc) +remote-test-host = localhost +remote-test-port = 22 +remote-test-user = ${USER} +remote-test-dir = /tmp/avian-test-${USER} + static = -static shared = -shared @@ -1251,11 +1256,14 @@ vg: build $(library-path) $(vg) $(test-executable) $(test-args) .PHONY: test -test: build - $(library-path) /bin/sh $(test)/test.sh 2>/dev/null \ - $(test-executable) $(mode) "$(test-flags)" \ - $(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \ - $(continuation-tests) $(tail-tests) +test: build $(build)/run-tests.sh $(build)/test.sh +ifneq ($(remote-test),true) + /bin/sh $(build)/run-tests.sh +else + @echo "testing remotely..." $(arch) $(target-arch) + rsync $(build) -rav --exclude '*.o' --rsh="ssh -p$(remote-test-port)" $(remote-test-user)@$(remote-test-host):$(remote-test-dir) + ssh -p$(remote-test-port) $(remote-test-user)@$(remote-test-host) sh "$(remote-test-dir)/$(platform)-$(arch)$(options)/run-tests.sh" +endif .PHONY: tarball tarball: @@ -1286,6 +1294,16 @@ ifeq ($(continuations),true) $(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) endif +$(build)/run-tests.sh: $(test-classes) makefile + echo 'cd $$(dirname $$0)' > $(@) + echo "sh ./test.sh 2>/dev/null \\" >> $(@) + echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)${exe-suffix} $(mode) \"-Djava.library.path=$$(pwd) -cp test\" log.txt \\" >> $(@) + echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@) + echo "$(continuation-tests) $(tail-tests)" >> $(@) + +$(build)/test.sh: $(test)/test.sh + cp $(<) $(@) + gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) @echo "generating $(@)" diff --git a/test/test.sh b/test/test.sh index defd6af06a..2dc26b4ef3 100644 --- a/test/test.sh +++ b/test/test.sh @@ -1,14 +1,17 @@ #!/bin/sh -log=build/log.txt vg="nice valgrind --leak-check=full --num-callers=32 \ --freelist-vol=100000000 --error-exitcode=1" +ld_path=${1}; shift vm=${1}; shift mode=${1}; shift flags=${1}; shift +log=${1}; shift tests=${@} +export ${ld_path} + echo -n "" >${log} echo From 33d245d0f7687bcab13747ffd5548b89fd8c8796 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 14 Feb 2013 20:54:20 -0700 Subject: [PATCH 238/378] add unittest framework --- makefile | 48 +++++++++++++++++++++-- test/test.sh | 13 ++++++- unittest/codegen/assembler-test.cpp | 37 ++++++++++++++++++ unittest/test-harness.cpp | 53 +++++++++++++++++++++++++ unittest/test-harness.h | 60 +++++++++++++++++++++++++++++ 5 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 unittest/codegen/assembler-test.cpp create mode 100644 unittest/test-harness.cpp create mode 100644 unittest/test-harness.h diff --git a/makefile b/makefile index 5ee56d857b..2f766eb2b2 100755 --- a/makefile +++ b/makefile @@ -64,6 +64,7 @@ test-build = $(build)/test src = src classpath-src = classpath test = test +unittest = unittest win32 ?= $(root)/win32 win64 ?= $(root)/win64 winrt ?= $(root)/winrt @@ -997,6 +998,8 @@ heapwalk-sources = $(src)/heapwalk.cpp heapwalk-objects = \ $(call cpp-objects,$(heapwalk-sources),$(src),$(build)) +unittest-objects = $(call cpp-objects,$(unittest-sources),$(unittest),$(build)/unittest/) + ifeq ($(heapdump),true) vm-sources += $(src)/heapdump.cpp vm-heapwalk-objects = $(heapwalk-objects) @@ -1124,6 +1127,8 @@ executable = $(build)/$(name)${exe-suffix} dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) executable-dynamic = $(build)/$(name)-dynamic$(exe-suffix) +unittest-executable = $(build)/$(name)-unittest${exe-suffix} + ifneq ($(classpath),avian) # Assembler, ConstantPool, and Stream are not technically needed for a # working build, but we include them since our Subroutine test uses @@ -1181,6 +1186,13 @@ test-extra-classes = \ $(call java-classes,$(test-extra-sources),$(test),$(test-build)) test-extra-dep = $(test-build)-extra.dep +unittest-sources = \ + $(wildcard $(unittest)/*.cpp) \ + $(wildcard $(unittest)/codegen/*.cpp) + +unittest-depends = \ + $(wildcard $(unittest)/*.h) + ifeq ($(continuations),true) continuation-tests = \ extra.Continuations \ @@ -1256,11 +1268,11 @@ vg: build $(library-path) $(vg) $(test-executable) $(test-args) .PHONY: test -test: build $(build)/run-tests.sh $(build)/test.sh +test: build $(build)/run-tests.sh $(build)/test.sh $(unittest-executable) ifneq ($(remote-test),true) /bin/sh $(build)/run-tests.sh else - @echo "testing remotely..." $(arch) $(target-arch) + @echo "testing remotely..." rsync $(build) -rav --exclude '*.o' --rsh="ssh -p$(remote-test-port)" $(remote-test-user)@$(remote-test-host):$(remote-test-dir) ssh -p$(remote-test-port) $(remote-test-user)@$(remote-test-host) sh "$(remote-test-dir)/$(platform)-$(arch)$(options)/run-tests.sh" endif @@ -1297,7 +1309,7 @@ endif $(build)/run-tests.sh: $(test-classes) makefile echo 'cd $$(dirname $$0)' > $(@) echo "sh ./test.sh 2>/dev/null \\" >> $(@) - echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)${exe-suffix} $(mode) \"-Djava.library.path=$$(pwd) -cp test\" log.txt \\" >> $(@) + echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(name)${exe-suffix} $(mode) \"-Djava.library.path=$$(pwd) -cp test\" \\" >> $(@) echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@) echo "$(continuation-tests) $(tail-tests)" >> $(@) @@ -1356,9 +1368,18 @@ define compile-asm-object $(as) $(asmflags) $(call asm-output,$(@)) $(call asm-input,$(<)) endef +define compile-unittest-object + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -c $$($(windows-path) -I$(unittest) $(<)) $(call output,$(@)) +endef + $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(compile-object) +$(unittest-objects): $(build)/unittest/%.o: $(unittest)/%.cpp $(vm-depends) $(unittest-depends) + $(compile-unittest-object) + $(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) $(compile-object) @@ -1531,6 +1552,8 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) +unittest-executable-objects = $(unittest-objects) $(vm-objects) + $(executable): $(executable-objects) @echo "linking $(@)" ifeq ($(platform),windows) @@ -1550,6 +1573,25 @@ else endif $(strip) $(strip-all) $(@) + +$(unittest-executable): $(unittest-executable-objects) + @echo "linking $(@)" +ifeq ($(platform),windows) +ifdef ms_cl_compiler + $(ld) $(lflags) $(unittest-executable-objects) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif +else + $(dlltool) -z $(@).def $(unittest-executable-objects) + $(dlltool) -d $(@).def -e $(@).exp + $(ld) $(@).exp $(unittest-executable-objects) $(lflags) -o $(@) +endif +else + $(ld) $(unittest-executable-objects) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@) +endif + $(bootimage-generator): $(bootimage-generator-objects) echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform) $(MAKE) mode=$(mode) \ diff --git a/test/test.sh b/test/test.sh index 2dc26b4ef3..e30e90c1cb 100644 --- a/test/test.sh +++ b/test/test.sh @@ -4,20 +4,29 @@ vg="nice valgrind --leak-check=full --num-callers=32 \ --freelist-vol=100000000 --error-exitcode=1" ld_path=${1}; shift +unit_tester=${1}; shift vm=${1}; shift mode=${1}; shift flags=${1}; shift -log=${1}; shift tests=${@} +log=log.txt + export ${ld_path} echo -n "" >${log} +printf "%12s------- Unit tests -------\n" "" +${unit_tester} 2>>${log} +if [ "${?}" != "0" ]; then + trouble=1 +fi + echo +printf "%12s------- Java tests -------\n" "" for test in ${tests}; do - printf "%24s" "${test}: " + printf "%24s: " "${test}" case ${mode} in debug|debug-fast|fast|small ) diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp new file mode 100644 index 0000000000..d7d09a72d3 --- /dev/null +++ b/unittest/codegen/assembler-test.cpp @@ -0,0 +1,37 @@ +/* Copyright (c) 2008-2011, 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 + +#include "common.h" +#include "codegen/assembler.h" +#include "codegen/targets.h" + +#include "test-harness.h" + +#include "system.h" + + +using namespace avian::codegen; +using namespace vm; + +class BasicAssemblerTest : public Test { +public: + BasicAssemblerTest(): + Test("BasicAssemblerTest") + {} + + virtual void run() { + System* s = makeSystem(0); + Assembler::Architecture* arch = makeArchitectureNative(s, true); + arch->release(); + s->dispose(); + } +} basicAssemblerTest; diff --git a/unittest/test-harness.cpp b/unittest/test-harness.cpp new file mode 100644 index 0000000000..30472298ba --- /dev/null +++ b/unittest/test-harness.cpp @@ -0,0 +1,53 @@ +/* Copyright (c) 2008-2011, 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 + +#include "common.h" +#include "test-harness.h" + +// since we aren't linking against libstdc++, we must implement this +// ourselves: +extern "C" void __cxa_pure_virtual(void) { abort(); } + +Test* Test::first = 0; +Test** Test::last = &first; + +Test::Test(const char* name): + next(0), + failures(0), + runs(0), + name(name) +{ + *last = this; + last = &next; +} + +bool Test::runAll() { + int failures = 0; + for(Test* t = Test::first; t; t = t->next) { + printf("%24s: ", t->name); + t->run(); + failures += t->failures; + if(t->failures > 0) { + printf("failure\n"); + } else { + printf("success\n"); + } + } + return failures == 0; +} + +int main(int argc UNUSED, char** argv UNUSED) { + if(Test::runAll()) { + return 0; + } + return 1; +} \ No newline at end of file diff --git a/unittest/test-harness.h b/unittest/test-harness.h new file mode 100644 index 0000000000..e977c95c02 --- /dev/null +++ b/unittest/test-harness.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2008-2011, 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 + +class Test { +private: + Test* next; + static Test* first; + static Test** last; + + friend int main(int argc, char** argv); + + void print(uintptr_t value) { + fprintf(stderr, "%p", reinterpret_cast(value)); + } + + void print(bool value) { + fprintf(stderr, "%s", value ? "true" : "false"); + } + + int failures; + int runs; + +protected: + template + void assertEquals(T expected, T actual) { + if(expected != actual) { + fprintf(stderr, "assertion failure, expected: "); + print(expected); + fprintf(stderr, ", actual: "); + print(actual); + fprintf(stderr, "\n"); + failures++; + } + runs++; + } + + void assertTrue(bool value) { + assertEquals(true, value); + } + +public: + const char* const name; + Test(const char* name); + + virtual void run() = 0; + + static bool runAll(); +}; + +#endif \ No newline at end of file From a3fb540ec31ffdba920fdbc6d416db523c8fae72 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 07:35:17 -0700 Subject: [PATCH 239/378] add ArchitecturePlanTest --- makefile | 2 +- src/bootimage.cpp | 2 +- src/{ => heap}/heap.cpp | 2 +- src/{ => heap}/heap.h | 0 src/machine.h | 2 +- src/processor.h | 2 +- unittest/codegen/assembler-test.cpp | 77 +++++++++++++++++++++++++---- unittest/test-harness.h | 29 ++++++++++- 8 files changed, 100 insertions(+), 16 deletions(-) rename src/{ => heap}/heap.cpp (99%) rename src/{ => heap}/heap.h (100%) diff --git a/makefile b/makefile index 2f766eb2b2..f760e2a223 100755 --- a/makefile +++ b/makefile @@ -936,7 +936,7 @@ vm-sources = \ $(src)/finder.cpp \ $(src)/machine.cpp \ $(src)/util.cpp \ - $(src)/heap.cpp \ + $(src)/heap/heap.cpp \ $(src)/$(process).cpp \ $(src)/classpath-$(classpath).cpp \ $(src)/builtin.cpp \ diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 111d850f97..c2879403a2 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "heap.h" +#include "heap/heap.h" #include "heapwalk.h" #include "common.h" #include "machine.h" diff --git a/src/heap.cpp b/src/heap/heap.cpp similarity index 99% rename from src/heap.cpp rename to src/heap/heap.cpp index eadb13ef78..119a250572 100644 --- a/src/heap.cpp +++ b/src/heap/heap.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "heap.h" +#include "heap/heap.h" #include "system.h" #include "common.h" #include "arch.h" diff --git a/src/heap.h b/src/heap/heap.h similarity index 100% rename from src/heap.h rename to src/heap/heap.h diff --git a/src/machine.h b/src/machine.h index d31b4bf7b1..1d29cbc88a 100644 --- a/src/machine.h +++ b/src/machine.h @@ -13,7 +13,7 @@ #include "common.h" #include "system.h" -#include "heap.h" +#include "heap/heap.h" #include "finder.h" #include "processor.h" #include "constants.h" diff --git a/src/processor.h b/src/processor.h index 1c1de3e577..47e8d3c02d 100644 --- a/src/processor.h +++ b/src/processor.h @@ -13,7 +13,7 @@ #include "common.h" #include "system.h" -#include "heap.h" +#include "heap/heap.h" #include "bootimage.h" #include "heapwalk.h" #include "zone.h" diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp index d7d09a72d3..3fe8a07427 100644 --- a/unittest/codegen/assembler-test.cpp +++ b/unittest/codegen/assembler-test.cpp @@ -11,27 +11,86 @@ #include #include "common.h" +#include "heap/heap.h" +#include "system.h" +#include "target.h" + #include "codegen/assembler.h" #include "codegen/targets.h" +#include "codegen/lir.h" #include "test-harness.h" -#include "system.h" - using namespace avian::codegen; using namespace vm; -class BasicAssemblerTest : public Test { +class BasicEnv { public: - BasicAssemblerTest(): - Test("BasicAssemblerTest") - {} + System* s; + Heap* heap; + Assembler::Architecture* arch; - virtual void run() { - System* s = makeSystem(0); - Assembler::Architecture* arch = makeArchitectureNative(s, true); + BasicEnv(): + s(makeSystem(0)), + heap(makeHeap(s, 32 * 1024)), + arch(makeArchitectureNative(s, true)) + { + arch->acquire(); + } + + ~BasicEnv() { arch->release(); s->dispose(); } +}; + +class Asm { +public: + Zone zone; + Assembler* a; + + Asm(BasicEnv& env): + zone(env.s, env.heap, 8192), + a(env.arch->makeAssembler(env.heap, &zone)) + { } + + ~Asm() { + a->dispose(); + } +}; + + +class BasicAssemblerTest : public Test { +public: + BasicAssemblerTest(): + Test("BasicAssembler") + {} + + virtual void run() { + BasicEnv env; + Asm a(env); + } } basicAssemblerTest; + +class ArchitecturePlanTest : public Test { +public: + ArchitecturePlanTest(): + Test("ArchitecturePlan") + {} + + virtual void run() { + BasicEnv env; + + for(int op = (int)lir::Call; op < (int)lir::AlignedJump; op++) { + bool thunk; + uint8_t typeMask; + uint64_t registerMask; + env.arch->plan((lir::UnaryOperation)op, vm::TargetBytesPerWord, &typeMask, ®isterMask, &thunk); + assertFalse(thunk); + assertNotEqual(static_cast(0), typeMask); + assertNotEqual(static_cast(0), registerMask); + } + + } +} architecturePlanTest; diff --git a/unittest/test-harness.h b/unittest/test-harness.h index e977c95c02..0b6b5e0fba 100644 --- a/unittest/test-harness.h +++ b/unittest/test-harness.h @@ -27,12 +27,20 @@ private: fprintf(stderr, "%s", value ? "true" : "false"); } + void print(uint8_t value) { + fprintf(stderr, "0x%02x", value); + } + + void print(uint64_t value) { + fprintf(stderr, "0x%" LLD, value); + } + int failures; int runs; protected: template - void assertEquals(T expected, T actual) { + void assertEqual(T expected, T actual) { if(expected != actual) { fprintf(stderr, "assertion failure, expected: "); print(expected); @@ -43,9 +51,26 @@ protected: } runs++; } + + template + void assertNotEqual(T expected, T actual) { + if(expected == actual) { + fprintf(stderr, "assertion failure, expected: not "); + print(expected); + fprintf(stderr, ", actual: "); + print(actual); + fprintf(stderr, "\n"); + failures++; + } + runs++; + } void assertTrue(bool value) { - assertEquals(true, value); + assertEqual(true, value); + } + + void assertFalse(bool value) { + assertEqual(false, value); } public: From 71765bb26f0b00926c45aac674bb475bf9aa09d7 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 09:53:02 -0700 Subject: [PATCH 240/378] fix cross-compile windows build --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index 395413e660..8555878c41 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -21,7 +21,7 @@ #if defined(PLATFORM_WINDOWS) # define WIN32_LEAN_AND_MEAN -# include +# include #endif using namespace vm; From d4494aef9a2031e8e1fbef2bc68e484104977756 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 09:54:05 -0700 Subject: [PATCH 241/378] fix test-harness for 32-bit platforms --- unittest/test-harness.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/unittest/test-harness.h b/unittest/test-harness.h index 0b6b5e0fba..717cfc317f 100644 --- a/unittest/test-harness.h +++ b/unittest/test-harness.h @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#ifndef ARCH_H -#define ARCH_H +#ifndef TEST_HARNESS_H +#define TEST_HARNESS_H class Test { private: @@ -19,22 +19,24 @@ private: friend int main(int argc, char** argv); - void print(uintptr_t value) { + + void print(uint64_t value) { fprintf(stderr, "%p", reinterpret_cast(value)); } + void print(uint32_t value) { + fprintf(stderr, "%p", reinterpret_cast(value)); + } + + + void print(uint8_t value) { + print(static_cast(value)); + } + void print(bool value) { fprintf(stderr, "%s", value ? "true" : "false"); } - void print(uint8_t value) { - fprintf(stderr, "0x%02x", value); - } - - void print(uint64_t value) { - fprintf(stderr, "0x%" LLD, value); - } - int failures; int runs; @@ -82,4 +84,4 @@ public: static bool runAll(); }; -#endif \ No newline at end of file +#endif // TEST_HARNESS_H From 9a91c1dd2d4b05779fea5c8cc78daf6cc7416338 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 17:43:21 -0700 Subject: [PATCH 242/378] set remote-test variable based on the presence of remote-test-host or remote-test-port The new way to run a remote test is: make arch= remote-test-host= test --- makefile | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index f760e2a223..d075355c60 100755 --- a/makefile +++ b/makefile @@ -270,8 +270,18 @@ as = $(cc) ld = $(cc) build-ld = $(build-cc) -remote-test-host = localhost -remote-test-port = 22 +default-remote-test-host = localhost +default-remote-test-port = 22 +ifeq ($(remote-test-host),) + remote-test-host = $(default-remote-test-host) +else + remote-test = true +endif +ifeq ($(remote-test-port),) + remote-test-port = $(default-remote-test-port) +else + remote-test = true +endif remote-test-user = ${USER} remote-test-dir = /tmp/avian-test-${USER} @@ -1272,7 +1282,7 @@ test: build $(build)/run-tests.sh $(build)/test.sh $(unittest-executable) ifneq ($(remote-test),true) /bin/sh $(build)/run-tests.sh else - @echo "testing remotely..." + @echo "running tests on $(remote-test-user)@$(remote-test-host):$(remote-test-port), in $(remote-test-dir)" rsync $(build) -rav --exclude '*.o' --rsh="ssh -p$(remote-test-port)" $(remote-test-user)@$(remote-test-host):$(remote-test-dir) ssh -p$(remote-test-port) $(remote-test-user)@$(remote-test-host) sh "$(remote-test-dir)/$(platform)-$(arch)$(options)/run-tests.sh" endif From a5869c854f1501aa190c8d6b5764c4b34dab941d Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 20:28:39 -0700 Subject: [PATCH 243/378] fix interpret.cpp build --- src/interpret.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/interpret.cpp b/src/interpret.cpp index 9ef5a9d613..8b9f4e12d9 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -16,6 +16,8 @@ #include "process.h" #include "arch.h" +#include "util/runtime-array.h" + using namespace vm; namespace local { @@ -3191,7 +3193,7 @@ class MyProcessor: public Processor { } virtual void compileMethod(vm::Thread*, Zone*, object*, object*, - DelayedPromise**, object, OffsetResolver*) + avian::codegen::DelayedPromise**, object, OffsetResolver*) { abort(s); } From 5a5b9248e62ccb9d0352b48ccbb23e22acb9fa1a Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 20:44:55 -0700 Subject: [PATCH 244/378] fix unittests for process=interpret build --- makefile | 60 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/makefile b/makefile index d075355c60..1e29f0ca91 100755 --- a/makefile +++ b/makefile @@ -966,31 +966,41 @@ embed-loader-objects = $(call cpp-objects,$(embed-loader-sources),$(src),$(build embed-sources = $(src)/embed.cpp embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) +compiler-sources = \ + $(src)/codegen/compiler.cpp \ + $(src)/codegen/compiler/context.cpp \ + $(src)/codegen/compiler/resource.cpp \ + $(src)/codegen/compiler/site.cpp \ + $(src)/codegen/compiler/regalloc.cpp \ + $(src)/codegen/compiler/value.cpp \ + $(src)/codegen/compiler/read.cpp \ + $(src)/codegen/compiler/event.cpp \ + $(src)/codegen/compiler/promise.cpp \ + $(src)/codegen/compiler/frame.cpp \ + $(src)/codegen/compiler/ir.cpp \ + $(src)/codegen/registers.cpp \ + $(src)/codegen/targets.cpp + +all-assembler-sources = \ + $(src)/codegen/x86/assembler.cpp \ + $(src)/codegen/arm/assembler.cpp \ + $(src)/codegen/powerpc/assembler.cpp + +native-assembler-sources = \ + $(src)/codegen/$(target-asm)/assembler.cpp + +all-codegen-target-sources = \ + $(compiler-sources) \ + $(native-assembler-sources) + ifeq ($(process),compile) - vm-sources += \ - $(src)/codegen/compiler.cpp \ - $(src)/codegen/compiler/context.cpp \ - $(src)/codegen/compiler/resource.cpp \ - $(src)/codegen/compiler/site.cpp \ - $(src)/codegen/compiler/regalloc.cpp \ - $(src)/codegen/compiler/value.cpp \ - $(src)/codegen/compiler/read.cpp \ - $(src)/codegen/compiler/event.cpp \ - $(src)/codegen/compiler/promise.cpp \ - $(src)/codegen/compiler/frame.cpp \ - $(src)/codegen/compiler/ir.cpp \ - $(src)/codegen/registers.cpp \ - $(src)/codegen/targets.cpp + vm-sources += $(compiler-sources) ifeq ($(codegen-targets),native) - vm-sources += \ - $(src)/codegen/$(target-asm)/assembler.cpp + vm-sources += $(native-assembler-sources) endif ifeq ($(codegen-targets),all) - vm-sources += \ - $(src)/codegen/x86/assembler.cpp \ - $(src)/codegen/arm/assembler.cpp \ - $(src)/codegen/powerpc/assembler.cpp + vm-sources += $(all-assembler-sources) endif vm-asm-sources += $(src)/compile-$(asm).$(asm-format) @@ -1001,6 +1011,7 @@ ifeq ($(aot-only),true) endif vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(build)) +all-codegen-target-objects = $(call cpp-objects,$(all-codegen-target-sources),$(src),$(build)) vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build)) vm-objects = $(vm-cpp-objects) $(vm-asm-objects) @@ -1387,6 +1398,11 @@ endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(compile-object) +ifeq ($(process),interpret) +$(all-codegen-target-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) + $(compile-object) +endif + $(unittest-objects): $(build)/unittest/%.o: $(unittest)/%.cpp $(vm-depends) $(unittest-depends) $(compile-unittest-object) @@ -1564,6 +1580,10 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ unittest-executable-objects = $(unittest-objects) $(vm-objects) +ifeq ($(process),interpret) + unittest-executable-objects += $(all-codegen-target-objects) +endif + $(executable): $(executable-objects) @echo "linking $(@)" ifeq ($(platform),windows) From fbbd718fe1870a6acee7b9a07d84e21022d47017 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 16 Feb 2013 08:36:29 -0700 Subject: [PATCH 245/378] fix bootimage build --- src/bootimage.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index c2879403a2..0dba4af877 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -15,6 +15,7 @@ #include "util.h" #include "stream.h" #include "codegen/assembler.h" +#include "codegen/promise.h" #include "target.h" #include "binaryToObject/tools.h" #include "lzma.h" @@ -25,6 +26,7 @@ extern "C" void __cxa_pure_virtual(void) { abort(); } using namespace vm; using namespace avian::tools; +using namespace avian::codegen; namespace { @@ -326,7 +328,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, Client(Thread* t): t(t) { } virtual void NO_RETURN handleError() { - vm::abort(t); + abort(t); } private: From fd0b2b844bf3d31cfe45b3d9112e2f555a7057d9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 16 Feb 2013 08:36:41 -0700 Subject: [PATCH 246/378] test various configurations besides the default in Travis CI --- .travis.yml | 2 +- test/ci.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 test/ci.sh diff --git a/.travis.yml b/.travis.yml index e2d152d5f2..18dcccd6af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,2 @@ language: cpp -script: "make test" +script: ./test/ci.sh diff --git a/test/ci.sh b/test/ci.sh new file mode 100755 index 0000000000..555ce4687e --- /dev/null +++ b/test/ci.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +make mode=debug test +make test +make process=interpret test +make bootimage=true test +make tails=true continuations=true test From 4462b87f1045454e60eacd3987c29bdb4b732a23 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 20:04:30 -0700 Subject: [PATCH 247/378] group typeMask and registerMask into OperandMask, for Architecture::plan --- src/codegen/arm/assembler.cpp | 120 ++++---- src/codegen/assembler.h | 40 ++- src/codegen/compiler.cpp | 156 +++++------ src/codegen/compiler/event.cpp | 419 ++++++++++++++-------------- src/codegen/compiler/site.h | 8 + src/codegen/powerpc/assembler.cpp | 78 +++--- src/codegen/x86/assembler.cpp | 222 ++++++++------- unittest/codegen/assembler-test.cpp | 9 +- 8 files changed, 529 insertions(+), 523 deletions(-) diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index c15007835f..85a7a0e933 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -2254,27 +2254,27 @@ class MyArchitecture: public Assembler::Architecture { virtual void plan (lir::UnaryOperation, - unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned, OperandMask& aMask, bool* thunk) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); - *aRegisterMask = ~static_cast(0); + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); + aMask.registerMask = ~static_cast(0); *thunk = false; } virtual void planSource (lir::BinaryOperation op, - unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned aSize, OperandMask& aMask, unsigned bSize, bool* thunk) { *thunk = false; - *aTypeMask = ~0; - *aRegisterMask = GPR_MASK64; + aMask.typeMask = ~0; + aMask.registerMask = GPR_MASK64; switch (op) { case lir::Negate: - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = GPR_MASK64; + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = GPR_MASK64; break; case lir::Absolute: @@ -2286,8 +2286,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::FloatNegate: case lir::Float2Float: if (vfpSupported()) { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = FPR_MASK64; + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = FPR_MASK64; } else { *thunk = true; } @@ -2299,8 +2299,8 @@ class MyArchitecture: public Assembler::Architecture { // thunks or produce inline machine code which handles edge // cases properly. if (false && vfpSupported() && bSize == 4) { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = FPR_MASK64; + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = FPR_MASK64; } else { *thunk = true; } @@ -2308,8 +2308,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::Int2Float: if (vfpSupported() && aSize == 4) { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = GPR_MASK64; + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = GPR_MASK64; } else { *thunk = true; } @@ -2322,16 +2322,16 @@ class MyArchitecture: public Assembler::Architecture { virtual void planDestination (lir::BinaryOperation op, - unsigned, uint8_t aTypeMask, uint64_t, - unsigned , uint8_t* bTypeMask, uint64_t* bRegisterMask) + unsigned, const OperandMask& aMask, + unsigned, OperandMask& bMask) { - *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *bRegisterMask = GPR_MASK64; + bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + bMask.registerMask = GPR_MASK64; switch (op) { case lir::Negate: - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = GPR_MASK64; + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = GPR_MASK64; break; case lir::FloatAbsolute: @@ -2339,18 +2339,18 @@ class MyArchitecture: public Assembler::Architecture { case lir::FloatNegate: case lir::Float2Float: case lir::Int2Float: - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = FPR_MASK64; + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = FPR_MASK64; break; case lir::Float2Int: - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = GPR_MASK64; + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = GPR_MASK64; break; case lir::Move: - if (!(aTypeMask & 1 << lir::RegisterOperand)) { - *bTypeMask = 1 << lir::RegisterOperand; + if (!(aMask.typeMask & 1 << lir::RegisterOperand)) { + bMask.typeMask = 1 << lir::RegisterOperand; } break; @@ -2360,41 +2360,41 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planMove - (unsigned, uint8_t* srcTypeMask, uint64_t* srcRegisterMask, - uint8_t* tmpTypeMask, uint64_t* tmpRegisterMask, - uint8_t dstTypeMask, uint64_t dstRegisterMask) + (unsigned, OperandMask& srcMask, + OperandMask& tmpMask, + const OperandMask& dstMask) { - *srcTypeMask = ~0; - *srcRegisterMask = ~static_cast(0); + srcMask.typeMask = ~0; + srcMask.registerMask = ~static_cast(0); - *tmpTypeMask = 0; - *tmpRegisterMask = 0; + tmpMask.typeMask = 0; + tmpMask.registerMask = 0; - if (dstTypeMask & (1 << lir::MemoryOperand)) { + if (dstMask.typeMask & (1 << lir::MemoryOperand)) { // can't move directly from memory or constant to memory - *srcTypeMask = 1 << lir::RegisterOperand; - *tmpTypeMask = 1 << lir::RegisterOperand; - *tmpRegisterMask = GPR_MASK64; + srcMask.typeMask = 1 << lir::RegisterOperand; + tmpMask.typeMask = 1 << lir::RegisterOperand; + tmpMask.registerMask = GPR_MASK64; } else if (vfpSupported() && - dstTypeMask & 1 << lir::RegisterOperand && - dstRegisterMask & FPR_MASK) { - *srcTypeMask = *tmpTypeMask = 1 << lir::RegisterOperand | + dstMask.typeMask & 1 << lir::RegisterOperand && + dstMask.registerMask & FPR_MASK) { + srcMask.typeMask = tmpMask.typeMask = 1 << lir::RegisterOperand | 1 << lir::MemoryOperand; - *tmpRegisterMask = ~static_cast(0); + tmpMask.registerMask = ~static_cast(0); } } virtual void planSource (lir::TernaryOperation op, - unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, - unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask, + unsigned, OperandMask& aMask, + unsigned bSize, OperandMask& bMask, unsigned, bool* thunk) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); - *aRegisterMask = GPR_MASK64; + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); + aMask.registerMask = GPR_MASK64; - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = GPR_MASK64; + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = GPR_MASK64; *thunk = false; @@ -2402,7 +2402,7 @@ class MyArchitecture: public Assembler::Architecture { case lir::ShiftLeft: case lir::ShiftRight: case lir::UnsignedShiftRight: - if (bSize == 8) *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); + if (bSize == 8) aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand); break; case lir::Add: @@ -2410,7 +2410,7 @@ class MyArchitecture: public Assembler::Architecture { case lir::Or: case lir::Xor: case lir::Multiply: - *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); + aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand); break; case lir::Divide: @@ -2424,8 +2424,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::FloatMultiply: case lir::FloatDivide: if (vfpSupported()) { - *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = *bRegisterMask = FPR_MASK64; + aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = bMask.registerMask = FPR_MASK64; } else { *thunk = true; } @@ -2442,8 +2442,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::JumpIfFloatLessOrEqualOrUnordered: case lir::JumpIfFloatGreaterOrEqualOrUnordered: if (vfpSupported()) { - *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = *bRegisterMask = FPR_MASK64; + aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = bMask.registerMask = FPR_MASK64; } else { *thunk = true; } @@ -2456,16 +2456,16 @@ class MyArchitecture: public Assembler::Architecture { virtual void planDestination (lir::TernaryOperation op, - unsigned, uint8_t, uint64_t, - unsigned, uint8_t, const uint64_t bRegisterMask, - unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask) + unsigned, const OperandMask& aMask UNUSED, + unsigned, const OperandMask& bMask, + unsigned, OperandMask& cMask) { if (isBranch(op)) { - *cTypeMask = (1 << lir::ConstantOperand); - *cRegisterMask = 0; + cMask.typeMask = (1 << lir::ConstantOperand); + cMask.registerMask = 0; } else { - *cTypeMask = (1 << lir::RegisterOperand); - *cRegisterMask = bRegisterMask; + cMask.typeMask = (1 << lir::RegisterOperand); + cMask.registerMask = bMask.registerMask; } } diff --git a/src/codegen/assembler.h b/src/codegen/assembler.h index 21301fd71f..8322ef8128 100644 --- a/src/codegen/assembler.h +++ b/src/codegen/assembler.h @@ -35,6 +35,22 @@ public: { } }; +class OperandMask { +public: + uint8_t typeMask; + uint64_t registerMask; + + OperandMask(uint8_t typeMask, uint64_t registerMask): + typeMask(typeMask), + registerMask(registerMask) + { } + + OperandMask(): + typeMask(~0), + registerMask(~static_cast(0)) + { } +}; + #ifdef AVIAN_TAILS const bool TailCalls = true; #else @@ -120,35 +136,35 @@ class Assembler { virtual void plan (lir::UnaryOperation op, - unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned aSize, OperandMask& aMask, bool* thunk) = 0; virtual void planSource (lir::BinaryOperation op, - unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned aSize, OperandMask& aMask, unsigned bSize, bool* thunk) = 0; virtual void planDestination (lir::BinaryOperation op, - unsigned aSize, uint8_t aTypeMask, uint64_t aRegisterMask, - unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask) = 0; + unsigned aSize, const OperandMask& aMask, + unsigned bSize, OperandMask& bMask) = 0; virtual void planMove - (unsigned size, uint8_t* srcTypeMask, uint64_t* srcRegisterMask, - uint8_t* tmpTypeMask, uint64_t* tmpRegisterMask, - uint8_t dstTypeMask, uint64_t dstRegisterMask) = 0; + (unsigned size, OperandMask& src, + OperandMask& tmp, + const OperandMask& dst) = 0; virtual void planSource (lir::TernaryOperation op, - unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, - unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask, + unsigned aSize, OperandMask& aMask, + unsigned bSize, OperandMask& bMask, unsigned cSize, bool* thunk) = 0; virtual void planDestination (lir::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) = 0; + unsigned aSize, const OperandMask& aMask, + unsigned bSize, const OperandMask& bMask, + unsigned cSize, OperandMask& cMask) = 0; virtual Assembler* makeAssembler(vm::Allocator*, vm::Zone*) = 0; diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 23c62a8b5e..de46f1c639 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -334,16 +334,13 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, virtual unsigned cost(Context* c, SiteMask dstMask) { - uint8_t srcTypeMask; - uint64_t srcRegisterMask; - uint8_t tmpTypeMask; - uint64_t tmpRegisterMask; + OperandMask src; + OperandMask tmp; c->arch->planMove - (size, &srcTypeMask, &srcRegisterMask, - &tmpTypeMask, &tmpRegisterMask, - dstMask.typeMask, dstMask.registerMask); + (size, src, tmp, + OperandMask(dstMask.typeMask, dstMask.registerMask)); - SiteMask srcMask(srcTypeMask, srcRegisterMask, AnyFrameIndex); + SiteMask srcMask(src.typeMask, src.registerMask, AnyFrameIndex); for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) { Site* s = it.next(); if (s->match(c, srcMask) or s->match(c, dstMask)) { @@ -359,26 +356,23 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, bool includeNextWord; } costCalculator(value, size, includeNextWord); - Site* dst = pickTargetSite + Site* dstSite = pickTargetSite (c, read, intersectRead, registerReserveCount, &costCalculator); - uint8_t srcTypeMask; - uint64_t srcRegisterMask; - uint8_t tmpTypeMask; - uint64_t tmpRegisterMask; + OperandMask src; + OperandMask tmp; c->arch->planMove - (size, &srcTypeMask, &srcRegisterMask, - &tmpTypeMask, &tmpRegisterMask, - 1 << dst->type(c), dst->registerMask(c)); + (size, src, tmp, + OperandMask(1 << dstSite->type(c), dstSite->registerMask(c))); - SiteMask srcMask(srcTypeMask, srcRegisterMask, AnyFrameIndex); + SiteMask srcMask(src.typeMask, src.registerMask, AnyFrameIndex); unsigned cost = 0xFFFFFFFF; - Site* src = 0; + Site* srcSite = 0; for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) { Site* s = it.next(); - unsigned v = s->copyCost(c, dst); + unsigned v = s->copyCost(c, dstSite); if (v == 0) { - src = s; + srcSite = s; cost = 0; break; } @@ -386,50 +380,50 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, v += CopyPenalty; } if (v < cost) { - src = s; + srcSite = s; cost = v; } } if (cost) { if (DebugMoves) { - char srcb[256]; src->toString(c, srcb, 256); - char dstb[256]; dst->toString(c, dstb, 256); + char srcb[256]; srcSite->toString(c, srcb, 256); + char dstb[256]; dstSite->toString(c, dstb, 256); fprintf(stderr, "maybe move %s to %s for %p to %p\n", srcb, dstb, value, value); } - src->freeze(c, value); + srcSite->freeze(c, value); - value->addSite(c, dst); + value->addSite(c, dstSite); - src->thaw(c, value); + srcSite->thaw(c, value); - if (not src->match(c, srcMask)) { - src->freeze(c, value); - dst->freeze(c, value); + if (not srcSite->match(c, srcMask)) { + srcSite->freeze(c, value); + dstSite->freeze(c, value); - SiteMask tmpMask(tmpTypeMask, tmpRegisterMask, AnyFrameIndex); + SiteMask tmpMask(tmp.typeMask, tmp.registerMask, AnyFrameIndex); SingleRead tmpRead(tmpMask, 0); tmpRead.value = value; tmpRead.successor_ = value; - Site* tmp = pickTargetSite(c, &tmpRead, true); + Site* tmpSite = pickTargetSite(c, &tmpRead, true); - value->addSite(c, tmp); + value->addSite(c, tmpSite); - move(c, value, src, tmp); + move(c, value, srcSite, tmpSite); - dst->thaw(c, value); - src->thaw(c, value); + dstSite->thaw(c, value); + srcSite->thaw(c, value); - src = tmp; + srcSite = tmpSite; } - move(c, value, src, dst); + move(c, value, srcSite, dstSite); } - return dst; + return dstSite; } Site* @@ -757,145 +751,143 @@ saveLocals(Context* c, Event* e) void maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, + unsigned srcSelectSize, Value* srcValue, unsigned dstSize, Value* dstValue, const SiteMask& dstMask) { - Read* read = live(c, dst); + Read* read = live(c, dstValue); bool isStore = read == 0; Site* target; - if (dst->target) { - target = dst->target; + if (dstValue->target) { + target = dstValue->target; } else if (isStore) { return; } else { target = pickTargetSite(c, read); } - unsigned cost = src->source->copyCost(c, target); + unsigned cost = srcValue->source->copyCost(c, target); if (srcSelectSize < dstSize) cost = 1; if (cost) { // todo: let c->arch->planMove decide this: bool useTemporary = ((target->type(c) == lir::MemoryOperand - and src->source->type(c) == lir::MemoryOperand) + and srcValue->source->type(c) == lir::MemoryOperand) or (srcSelectSize < dstSize and target->type(c) != lir::RegisterOperand)); - src->source->freeze(c, src); + srcValue->source->freeze(c, srcValue); - dst->addSite(c, target); + dstValue->addSite(c, target); - src->source->thaw(c, src); + srcValue->source->thaw(c, srcValue); bool addOffset = srcSize != srcSelectSize and c->arch->bigEndian() - and src->source->type(c) == lir::MemoryOperand; + and srcValue->source->type(c) == lir::MemoryOperand; if (addOffset) { - static_cast(src->source)->offset + static_cast(srcValue->source)->offset += (srcSize - srcSelectSize); } - target->freeze(c, dst); + target->freeze(c, dstValue); if (target->match(c, dstMask) and not useTemporary) { if (DebugMoves) { - char srcb[256]; src->source->toString(c, srcb, 256); + char srcb[256]; srcValue->source->toString(c, srcb, 256); char dstb[256]; target->toString(c, dstb, 256); fprintf(stderr, "move %s to %s for %p to %p\n", - srcb, dstb, src, dst); + srcb, dstb, srcValue, dstValue); } - src->source->freeze(c, src); + srcValue->source->freeze(c, srcValue); - apply(c, type, min(srcSelectSize, dstSize), src->source, src->source, + apply(c, type, min(srcSelectSize, dstSize), srcValue->source, srcValue->source, dstSize, target, target); - src->source->thaw(c, src); + srcValue->source->thaw(c, srcValue); } else { // pick a temporary register which is valid as both a // destination and a source for the moves we need to perform: - dst->removeSite(c, target); + dstValue->removeSite(c, target); bool thunk; - uint8_t srcTypeMask; - uint64_t srcRegisterMask; + OperandMask src; - c->arch->planSource(type, dstSize, &srcTypeMask, &srcRegisterMask, - dstSize, &thunk); + c->arch->planSource(type, dstSize, src, dstSize, &thunk); - if (src->type == lir::ValueGeneral) { - srcRegisterMask &= c->regFile->generalRegisters.mask; + if (srcValue->type == lir::ValueGeneral) { + src.registerMask &= c->regFile->generalRegisters.mask; } assert(c, thunk == 0); - assert(c, dstMask.typeMask & srcTypeMask & (1 << lir::RegisterOperand)); + assert(c, dstMask.typeMask & src.typeMask & (1 << lir::RegisterOperand)); Site* tmpTarget = freeRegisterSite - (c, dstMask.registerMask & srcRegisterMask); + (c, dstMask.registerMask & src.registerMask); - src->source->freeze(c, src); + srcValue->source->freeze(c, srcValue); - dst->addSite(c, tmpTarget); + dstValue->addSite(c, tmpTarget); - tmpTarget->freeze(c, dst); + tmpTarget->freeze(c, dstValue); if (DebugMoves) { - char srcb[256]; src->source->toString(c, srcb, 256); + char srcb[256]; srcValue->source->toString(c, srcb, 256); char dstb[256]; tmpTarget->toString(c, dstb, 256); fprintf(stderr, "move %s to %s for %p to %p\n", - srcb, dstb, src, dst); + srcb, dstb, srcValue, dstValue); } - apply(c, type, srcSelectSize, src->source, src->source, + apply(c, type, srcSelectSize, srcValue->source, srcValue->source, dstSize, tmpTarget, tmpTarget); - tmpTarget->thaw(c, dst); + tmpTarget->thaw(c, dstValue); - src->source->thaw(c, src); + srcValue->source->thaw(c, srcValue); if (useTemporary or isStore) { if (DebugMoves) { char srcb[256]; tmpTarget->toString(c, srcb, 256); char dstb[256]; target->toString(c, dstb, 256); fprintf(stderr, "move %s to %s for %p to %p\n", - srcb, dstb, src, dst); + srcb, dstb, srcValue, dstValue); } - dst->addSite(c, target); + dstValue->addSite(c, target); - tmpTarget->freeze(c, dst); + tmpTarget->freeze(c, dstValue); apply(c, lir::Move, dstSize, tmpTarget, tmpTarget, dstSize, target, target); - tmpTarget->thaw(c, dst); + tmpTarget->thaw(c, dstValue); if (isStore) { - dst->removeSite(c, tmpTarget); + dstValue->removeSite(c, tmpTarget); } } } - target->thaw(c, dst); + target->thaw(c, dstValue); if (addOffset) { - static_cast(src->source)->offset + static_cast(srcValue->source)->offset -= (srcSize - srcSelectSize); } } else { - target = src->source; + target = srcValue->source; if (DebugMoves) { char dstb[256]; target->toString(c, dstb, 256); - fprintf(stderr, "null move in %s for %p to %p\n", dstb, src, dst); + fprintf(stderr, "null move in %s for %p to %p\n", dstb, srcValue, dstValue); } } if (isStore) { - dst->removeSite(c, target); + dstValue->removeSite(c, target); } } diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index ba8c0c222a..a785001de9 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -264,16 +264,15 @@ class CallEvent: public Event { } { bool thunk; - uint8_t typeMask; - uint64_t planRegisterMask; + OperandMask op; c->arch->plan ((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, vm::TargetBytesPerWord, - &typeMask, &planRegisterMask, &thunk); + op, &thunk); assert(c, not thunk); this->addRead(c, address, SiteMask - (typeMask, registerMask & planRegisterMask, AnyFrameIndex)); + (op.typeMask, registerMask & op.registerMask, AnyFrameIndex)); } Stack* stack = stackBefore; @@ -543,26 +542,26 @@ void appendReturn(Context* c, unsigned size, Value* value) { class MoveEvent: public Event { public: MoveEvent(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, + unsigned srcSelectSize, Value* srcValue, unsigned dstSize, Value* dstValue, const SiteMask& srcLowMask, const SiteMask& srcHighMask): Event(c), type(type), srcSize(srcSize), srcSelectSize(srcSelectSize), - src(src), dstSize(dstSize), dst(dst) + srcValue(srcValue), dstSize(dstSize), dstValue(dstValue) { assert(c, srcSelectSize <= srcSize); bool noop = srcSelectSize >= dstSize; if (dstSize > vm::TargetBytesPerWord) { - dst->grow(c); + dstValue->grow(c); } if (srcSelectSize > vm::TargetBytesPerWord) { - src->maybeSplit(c); + srcValue->maybeSplit(c); } - this->addReads(c, src, srcSelectSize, srcLowMask, noop ? dst : 0, + this->addReads(c, srcValue, srcSelectSize, srcLowMask, noop ? dstValue : 0, srcHighMask, - noop and dstSize > vm::TargetBytesPerWord ? dst->nextWord : 0); + noop and dstSize > vm::TargetBytesPerWord ? dstValue->nextWord : 0); } virtual const char* name() { @@ -570,118 +569,116 @@ class MoveEvent: public Event { } virtual void compile(Context* c) { - uint8_t dstTypeMask; - uint64_t dstRegisterMask; + OperandMask dst; c->arch->planDestination (type, srcSelectSize, - 1 << src->source->type(c), - (static_cast(src->nextWord->source->registerMask(c)) << 32) - | static_cast(src->source->registerMask(c)), - dstSize, - &dstTypeMask, - &dstRegisterMask); + OperandMask( + 1 << srcValue->source->type(c), + (static_cast(srcValue->nextWord->source->registerMask(c)) << 32) + | static_cast(srcValue->source->registerMask(c))), + dstSize, dst); - SiteMask dstLowMask(dstTypeMask, dstRegisterMask, AnyFrameIndex); - SiteMask dstHighMask(dstTypeMask, dstRegisterMask >> 32, AnyFrameIndex); + SiteMask dstLowMask(dst.typeMask, dst.registerMask, AnyFrameIndex); + SiteMask dstHighMask(dst.typeMask, dst.registerMask >> 32, AnyFrameIndex); if (srcSelectSize >= vm::TargetBytesPerWord and dstSize >= vm::TargetBytesPerWord and srcSelectSize >= dstSize) { - if (dst->target) { + if (dstValue->target) { if (dstSize > vm::TargetBytesPerWord) { - if (src->source->registerSize(c) > vm::TargetBytesPerWord) { - apply(c, lir::Move, srcSelectSize, src->source, src->source, - dstSize, dst->target, dst->target); + if (srcValue->source->registerSize(c) > vm::TargetBytesPerWord) { + apply(c, lir::Move, srcSelectSize, srcValue->source, srcValue->source, + dstSize, dstValue->target, dstValue->target); - if (live(c, dst) == 0) { - dst->removeSite(c, dst->target); + if (live(c, dstValue) == 0) { + dstValue->removeSite(c, dstValue->target); if (dstSize > vm::TargetBytesPerWord) { - dst->nextWord->removeSite(c, dst->nextWord->target); + dstValue->nextWord->removeSite(c, dstValue->nextWord->target); } } } else { - src->nextWord->source->freeze(c, src->nextWord); + srcValue->nextWord->source->freeze(c, srcValue->nextWord); - maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, src, - vm::TargetBytesPerWord, dst, dstLowMask); + maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, srcValue, + vm::TargetBytesPerWord, dstValue, dstLowMask); - src->nextWord->source->thaw(c, src->nextWord); + srcValue->nextWord->source->thaw(c, srcValue->nextWord); maybeMove - (c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, src->nextWord, - vm::TargetBytesPerWord, dst->nextWord, dstHighMask); + (c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, srcValue->nextWord, + vm::TargetBytesPerWord, dstValue->nextWord, dstHighMask); } } else { - maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, src, - vm::TargetBytesPerWord, dst, dstLowMask); + maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, srcValue, + vm::TargetBytesPerWord, dstValue, dstLowMask); } } else { - Site* low = pickSiteOrMove(c, src, dst, 0, 0); + Site* low = pickSiteOrMove(c, srcValue, dstValue, 0, 0); if (dstSize > vm::TargetBytesPerWord) { - pickSiteOrMove(c, src->nextWord, dst->nextWord, low, 1); + pickSiteOrMove(c, srcValue->nextWord, dstValue->nextWord, low, 1); } } } else if (srcSelectSize <= vm::TargetBytesPerWord and dstSize <= vm::TargetBytesPerWord) { - maybeMove(c, type, srcSize, srcSelectSize, src, dstSize, dst, + maybeMove(c, type, srcSize, srcSelectSize, srcValue, dstSize, dstValue, dstLowMask); } else { assert(c, srcSize == vm::TargetBytesPerWord); assert(c, srcSelectSize == vm::TargetBytesPerWord); - if (dst->nextWord->target or live(c, dst->nextWord)) { + if (dstValue->nextWord->target or live(c, dstValue->nextWord)) { assert(c, dstLowMask.typeMask & (1 << lir::RegisterOperand)); Site* low = freeRegisterSite(c, dstLowMask.registerMask); - src->source->freeze(c, src); + srcValue->source->freeze(c, srcValue); - dst->addSite(c, low); + dstValue->addSite(c, low); - low->freeze(c, dst); + low->freeze(c, dstValue); if (DebugMoves) { - char srcb[256]; src->source->toString(c, srcb, 256); + char srcb[256]; srcValue->source->toString(c, srcb, 256); char dstb[256]; low->toString(c, dstb, 256); fprintf(stderr, "move %s to %s for %p\n", - srcb, dstb, src); + srcb, dstb, srcValue); } - apply(c, lir::Move, vm::TargetBytesPerWord, src->source, src->source, + apply(c, lir::Move, vm::TargetBytesPerWord, srcValue->source, srcValue->source, vm::TargetBytesPerWord, low, low); - low->thaw(c, dst); + low->thaw(c, dstValue); - src->source->thaw(c, src); + srcValue->source->thaw(c, srcValue); assert(c, dstHighMask.typeMask & (1 << lir::RegisterOperand)); Site* high = freeRegisterSite(c, dstHighMask.registerMask); - low->freeze(c, dst); + low->freeze(c, dstValue); - dst->nextWord->addSite(c, high); + dstValue->nextWord->addSite(c, high); - high->freeze(c, dst->nextWord); + high->freeze(c, dstValue->nextWord); if (DebugMoves) { char srcb[256]; low->toString(c, srcb, 256); char dstb[256]; high->toString(c, dstb, 256); fprintf(stderr, "extend %s to %s for %p %p\n", - srcb, dstb, dst, dst->nextWord); + srcb, dstb, dstValue, dstValue->nextWord); } apply(c, lir::Move, vm::TargetBytesPerWord, low, low, dstSize, low, high); - high->thaw(c, dst->nextWord); + high->thaw(c, dstValue->nextWord); - low->thaw(c, dst); + low->thaw(c, dstValue); } else { - pickSiteOrMove(c, src, dst, 0, 0); + pickSiteOrMove(c, srcValue, dstValue, 0, 0); } } @@ -693,29 +690,28 @@ class MoveEvent: public Event { lir::BinaryOperation type; unsigned srcSize; unsigned srcSelectSize; - Value* src; + Value* srcValue; unsigned dstSize; - Value* dst; + Value* dstValue; }; void appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst) + unsigned srcSelectSize, Value* srcValue, unsigned dstSize, Value* dstValue) { bool thunk; - uint8_t srcTypeMask; - uint64_t srcRegisterMask; + OperandMask src; c->arch->planSource - (type, srcSelectSize, &srcTypeMask, &srcRegisterMask, dstSize, &thunk); + (type, srcSelectSize, src, dstSize, &thunk); assert(c, not thunk); append(c, new(c->zone) MoveEvent - (c, type, srcSize, srcSelectSize, src, dstSize, dst, - SiteMask(srcTypeMask, srcRegisterMask, AnyFrameIndex), - SiteMask(srcTypeMask, srcRegisterMask >> 32, AnyFrameIndex))); + (c, type, srcSize, srcSelectSize, srcValue, dstSize, dstValue, + SiteMask(src.typeMask, src.registerMask, AnyFrameIndex), + SiteMask(src.typeMask, src.registerMask >> 32, AnyFrameIndex))); } @@ -791,28 +787,28 @@ Site* getTarget(Context* c, Value* value, Value* result, const SiteMask& resultM class CombineEvent: public Event { public: CombineEvent(Context* c, lir::TernaryOperation type, - unsigned firstSize, Value* first, - unsigned secondSize, Value* second, - unsigned resultSize, Value* result, + unsigned firstSize, Value* firstValue, + unsigned secondSize, Value* secondValue, + unsigned resultSize, Value* resultValue, const SiteMask& firstLowMask, const SiteMask& firstHighMask, const SiteMask& secondLowMask, const SiteMask& secondHighMask): - Event(c), type(type), firstSize(firstSize), first(first), - secondSize(secondSize), second(second), resultSize(resultSize), - result(result) + Event(c), type(type), firstSize(firstSize), firstValue(firstValue), + secondSize(secondSize), secondValue(secondValue), resultSize(resultSize), + resultValue(resultValue) { - this->addReads(c, first, firstSize, firstLowMask, firstHighMask); + this->addReads(c, firstValue, firstSize, firstLowMask, firstHighMask); if (resultSize > vm::TargetBytesPerWord) { - result->grow(c); + resultValue->grow(c); } bool condensed = c->arch->alwaysCondensed(type); - this->addReads(c, second, secondSize, - secondLowMask, condensed ? result : 0, - secondHighMask, condensed ? result->nextWord : 0); + this->addReads(c, secondValue, secondSize, + secondLowMask, condensed ? resultValue : 0, + secondHighMask, condensed ? resultValue->nextWord : 0); } virtual const char* name() { @@ -820,99 +816,99 @@ class CombineEvent: public Event { } virtual void compile(Context* c) { - assert(c, first->source->type(c) == first->nextWord->source->type(c)); + assert(c, firstValue->source->type(c) == firstValue->nextWord->source->type(c)); - // if (second->source->type(c) != second->nextWord->source->type(c)) { + // if (secondValue->source->type(c) != secondValue->nextWord->source->type(c)) { // fprintf(stderr, "%p %p %d : %p %p %d\n", - // second, second->source, second->source->type(c), - // second->nextWord, second->nextWord->source, - // second->nextWord->source->type(c)); + // secondValue, secondValue->source, secondValue->source->type(c), + // secondValue->nextWord, secondValue->nextWord->source, + // secondValue->nextWord->source->type(c)); // } - assert(c, second->source->type(c) == second->nextWord->source->type(c)); + assert(c, secondValue->source->type(c) == secondValue->nextWord->source->type(c)); - freezeSource(c, firstSize, first); + freezeSource(c, firstSize, firstValue); - uint8_t cTypeMask; - uint64_t cRegisterMask; + OperandMask cMask; c->arch->planDestination (type, firstSize, - 1 << first->source->type(c), - (static_cast(first->nextWord->source->registerMask(c)) << 32) - | static_cast(first->source->registerMask(c)), + OperandMask( + 1 << firstValue->source->type(c), + (static_cast(firstValue->nextWord->source->registerMask(c)) << 32) + | static_cast(firstValue->source->registerMask(c))), secondSize, - 1 << second->source->type(c), - (static_cast(second->nextWord->source->registerMask(c)) << 32) - | static_cast(second->source->registerMask(c)), + OperandMask( + 1 << secondValue->source->type(c), + (static_cast(secondValue->nextWord->source->registerMask(c)) << 32) + | static_cast(secondValue->source->registerMask(c))), resultSize, - &cTypeMask, - &cRegisterMask); + cMask); - SiteMask resultLowMask(cTypeMask, cRegisterMask, AnyFrameIndex); - SiteMask resultHighMask(cTypeMask, cRegisterMask >> 32, AnyFrameIndex); + SiteMask resultLowMask(cMask.typeMask, cMask.registerMask, AnyFrameIndex); + SiteMask resultHighMask(cMask.typeMask, cMask.registerMask >> 32, AnyFrameIndex); - Site* low = getTarget(c, second, result, resultLowMask); + Site* low = getTarget(c, secondValue, resultValue, resultLowMask); unsigned lowSize = low->registerSize(c); Site* high = (resultSize > lowSize - ? getTarget(c, second->nextWord, result->nextWord, resultHighMask) + ? getTarget(c, secondValue->nextWord, resultValue->nextWord, resultHighMask) : low); // fprintf(stderr, "combine %p:%p and %p:%p into %p:%p\n", -// first, first->nextWord, -// second, second->nextWord, -// result, result->nextWord); +// firstValue, firstValue->nextWord, +// secondValue, secondValue->nextWord, +// resultValue, resultValue->nextWord); apply(c, type, - firstSize, first->source, first->nextWord->source, - secondSize, second->source, second->nextWord->source, + firstSize, firstValue->source, firstValue->nextWord->source, + secondSize, secondValue->source, secondValue->nextWord->source, resultSize, low, high); - thawSource(c, firstSize, first); + thawSource(c, firstSize, firstValue); for (Read* r = reads; r; r = r->eventNext) { popRead(c, this, r->value); } - low->thaw(c, second); + low->thaw(c, secondValue); if (resultSize > lowSize) { - high->thaw(c, second->nextWord); + high->thaw(c, secondValue->nextWord); } - if (live(c, result)) { - result->addSite(c, low); - if (resultSize > lowSize and live(c, result->nextWord)) { - result->nextWord->addSite(c, high); + if (live(c, resultValue)) { + resultValue->addSite(c, low); + if (resultSize > lowSize and live(c, resultValue->nextWord)) { + resultValue->nextWord->addSite(c, high); } } } lir::TernaryOperation type; unsigned firstSize; - Value* first; + Value* firstValue; unsigned secondSize; - Value* second; + Value* secondValue; unsigned resultSize; - Value* result; + Value* resultValue; }; void appendCombine(Context* c, lir::TernaryOperation type, - unsigned firstSize, Value* first, - unsigned secondSize, Value* second, - unsigned resultSize, Value* result) + unsigned firstSize, Value* firstValue, + unsigned secondSize, Value* secondValue, + unsigned resultSize, Value* resultValue) { bool thunk; - uint8_t firstTypeMask; - uint64_t firstRegisterMask; - uint8_t secondTypeMask; - uint64_t secondRegisterMask; + OperandMask firstMask; + OperandMask secondMask; - c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask, - secondSize, &secondTypeMask, &secondRegisterMask, - resultSize, &thunk); + c->arch->planSource(type, + firstSize, firstMask, + secondSize, secondMask, + resultSize, + &thunk); if (thunk) { Stack* oldStack = c->stack; @@ -924,8 +920,8 @@ appendCombine(Context* c, lir::TernaryOperation type, unsigned stackSize = vm::ceilingDivide(secondSize, vm::TargetBytesPerWord) + vm::ceilingDivide(firstSize, vm::TargetBytesPerWord); - compiler::push(c, vm::ceilingDivide(secondSize, vm::TargetBytesPerWord), second); - compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), first); + compiler::push(c, vm::ceilingDivide(secondSize, vm::TargetBytesPerWord), secondValue); + compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue); if (threadParameter) { ++ stackSize; @@ -937,40 +933,40 @@ appendCombine(Context* c, lir::TernaryOperation type, c->stack = oldStack; appendCall - (c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, + (c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, resultValue, resultSize, argumentStack, stackSize, 0); } else { append (c, new(c->zone) CombineEvent (c, type, - firstSize, first, - secondSize, second, - resultSize, result, - SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), - SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex))); + firstSize, firstValue, + secondSize, secondValue, + resultSize, resultValue, + SiteMask(firstMask.typeMask, firstMask.registerMask, AnyFrameIndex), + SiteMask(firstMask.typeMask, firstMask.registerMask >> 32, AnyFrameIndex), + SiteMask(secondMask.typeMask, secondMask.registerMask, AnyFrameIndex), + SiteMask(secondMask.typeMask, secondMask.registerMask >> 32, AnyFrameIndex))); } } class TranslateEvent: public Event { public: TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize, - Value* value, unsigned resultSize, Value* result, + Value* value, unsigned resultSize, Value* resultValue, const SiteMask& valueLowMask, const SiteMask& valueHighMask): Event(c), type(type), valueSize(valueSize), resultSize(resultSize), - value(value), result(result) + value(value), resultValue(resultValue) { bool condensed = c->arch->alwaysCondensed(type); if (resultSize > vm::TargetBytesPerWord) { - result->grow(c); + resultValue->grow(c); } - this->addReads(c, value, valueSize, valueLowMask, condensed ? result : 0, - valueHighMask, condensed ? result->nextWord : 0); + this->addReads(c, value, valueSize, valueLowMask, condensed ? resultValue : 0, + valueHighMask, condensed ? resultValue->nextWord : 0); } virtual const char* name() { @@ -980,27 +976,26 @@ class TranslateEvent: public Event { virtual void compile(Context* c) { assert(c, value->source->type(c) == value->nextWord->source->type(c)); - uint8_t bTypeMask; - uint64_t bRegisterMask; + OperandMask bMask; c->arch->planDestination (type, valueSize, - 1 << value->source->type(c), - (static_cast(value->nextWord->source->registerMask(c)) << 32) - | static_cast(value->source->registerMask(c)), + OperandMask( + 1 << value->source->type(c), + (static_cast(value->nextWord->source->registerMask(c)) << 32) + | static_cast(value->source->registerMask(c))), resultSize, - &bTypeMask, - &bRegisterMask); + bMask); - SiteMask resultLowMask(bTypeMask, bRegisterMask, AnyFrameIndex); - SiteMask resultHighMask(bTypeMask, bRegisterMask >> 32, AnyFrameIndex); + SiteMask resultLowMask(bMask.typeMask, bMask.registerMask, AnyFrameIndex); + SiteMask resultHighMask(bMask.typeMask, bMask.registerMask >> 32, AnyFrameIndex); - Site* low = getTarget(c, value, result, resultLowMask); + Site* low = getTarget(c, value, resultValue, resultLowMask); unsigned lowSize = low->registerSize(c); Site* high = (resultSize > lowSize - ? getTarget(c, value->nextWord, result->nextWord, resultHighMask) + ? getTarget(c, value->nextWord, resultValue->nextWord, resultHighMask) : low); apply(c, type, valueSize, value->source, value->nextWord->source, @@ -1015,10 +1010,10 @@ class TranslateEvent: public Event { high->thaw(c, value->nextWord); } - if (live(c, result)) { - result->addSite(c, low); - if (resultSize > lowSize and live(c, result->nextWord)) { - result->nextWord->addSite(c, high); + if (live(c, resultValue)) { + resultValue->addSite(c, low); + if (resultSize > lowSize and live(c, resultValue->nextWord)) { + resultValue->nextWord->addSite(c, high); } } } @@ -1027,7 +1022,7 @@ class TranslateEvent: public Event { unsigned valueSize; unsigned resultSize; Value* value; - Value* result; + Value* resultValue; Read* resultRead; SiteMask resultLowMask; SiteMask resultHighMask; @@ -1035,19 +1030,18 @@ class TranslateEvent: public Event { void appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, - Value* first, unsigned resultSize, Value* result) + Value* firstValue, unsigned resultSize, Value* resultValue) { bool thunk; - uint8_t firstTypeMask; - uint64_t firstRegisterMask; + OperandMask first; - c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask, + c->arch->planSource(type, firstSize, first, resultSize, &thunk); if (thunk) { Stack* oldStack = c->stack; - compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), first); + compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -1056,14 +1050,14 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, (c, value (c, lir::ValueGeneral, constantSite (c, c->client->getThunk(type, firstSize, resultSize))), - 0, 0, result, resultSize, argumentStack, + 0, 0, resultValue, resultSize, argumentStack, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), 0); } else { append(c, new(c->zone) TranslateEvent - (c, type, firstSize, first, resultSize, result, - SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), - SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex))); + (c, type, firstSize, firstValue, resultSize, resultValue, + SiteMask(first.typeMask, first.registerMask, AnyFrameIndex), + SiteMask(first.typeMask, first.registerMask >> 32, AnyFrameIndex))); } } @@ -1306,23 +1300,24 @@ thunkBranch(Context* c, lir::TernaryOperation type) class BranchEvent: public Event { public: BranchEvent(Context* c, lir::TernaryOperation type, unsigned size, - Value* first, Value* second, Value* address, + Value* firstValue, Value* secondValue, Value* addressValue, const SiteMask& firstLowMask, const SiteMask& firstHighMask, const SiteMask& secondLowMask, const SiteMask& secondHighMask): - Event(c), type(type), size(size), first(first), second(second), - address(address) + Event(c), type(type), size(size), firstValue(firstValue), secondValue(secondValue), + addressValue(addressValue) { - this->addReads(c, first, size, firstLowMask, firstHighMask); - this->addReads(c, second, size, secondLowMask, secondHighMask); + this->addReads(c, firstValue, size, firstLowMask, firstHighMask); + this->addReads(c, secondValue, size, secondLowMask, secondHighMask); - uint8_t typeMask; - uint64_t registerMask; - c->arch->planDestination(type, size, 0, 0, size, 0, 0, vm::TargetBytesPerWord, - &typeMask, ®isterMask); + OperandMask dstMask; + c->arch->planDestination(type, + size, OperandMask(0, 0), + size, OperandMask(0, 0), + vm::TargetBytesPerWord, dstMask); - this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + this->addRead(c, addressValue, SiteMask(dstMask.typeMask, dstMask.registerMask, AnyFrameIndex)); } virtual const char* name() { @@ -1330,8 +1325,8 @@ class BranchEvent: public Event { } virtual void compile(Context* c) { - ConstantSite* firstConstant = findConstantSite(c, first); - ConstantSite* secondConstant = findConstantSite(c, second); + ConstantSite* firstConstant = findConstantSite(c, firstValue); + ConstantSite* secondConstant = findConstantSite(c, secondValue); if (not this->isUnreachable()) { if (firstConstant @@ -1339,31 +1334,31 @@ class BranchEvent: public Event { and firstConstant->value->resolved() and secondConstant->value->resolved()) { - int64_t firstValue = firstConstant->value->value(); - int64_t secondValue = secondConstant->value->value(); + int64_t firstConstVal = firstConstant->value->value(); + int64_t secondConstVal = secondConstant->value->value(); if (size > vm::TargetBytesPerWord) { - firstValue |= findConstantSite - (c, first->nextWord)->value->value() << 32; - secondValue |= findConstantSite - (c, second->nextWord)->value->value() << 32; + firstConstVal |= findConstantSite + (c, firstValue->nextWord)->value->value() << 32; + secondConstVal |= findConstantSite + (c, secondValue->nextWord)->value->value() << 32; } - if (shouldJump(c, type, size, firstValue, secondValue)) { - apply(c, lir::Jump, vm::TargetBytesPerWord, address->source, address->source); + if (shouldJump(c, type, size, firstConstVal, secondConstVal)) { + apply(c, lir::Jump, vm::TargetBytesPerWord, addressValue->source, addressValue->source); } } else { - freezeSource(c, size, first); - freezeSource(c, size, second); - freezeSource(c, vm::TargetBytesPerWord, address); + freezeSource(c, size, firstValue); + freezeSource(c, size, secondValue); + freezeSource(c, vm::TargetBytesPerWord, addressValue); - apply(c, type, size, first->source, first->nextWord->source, - size, second->source, second->nextWord->source, - vm::TargetBytesPerWord, address->source, address->source); + apply(c, type, size, firstValue->source, firstValue->nextWord->source, + size, secondValue->source, secondValue->nextWord->source, + vm::TargetBytesPerWord, addressValue->source, addressValue->source); - thawSource(c, vm::TargetBytesPerWord, address); - thawSource(c, size, second); - thawSource(c, size, first); + thawSource(c, vm::TargetBytesPerWord, addressValue); + thawSource(c, size, secondValue); + thawSource(c, size, firstValue); } } @@ -1376,24 +1371,23 @@ class BranchEvent: public Event { lir::TernaryOperation type; unsigned size; - Value* first; - Value* second; - Value* address; + Value* firstValue; + Value* secondValue; + Value* addressValue; }; void -appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first, - Value* second, Value* address) +appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* firstValue, + Value* secondValue, Value* addressValue) { bool thunk; - uint8_t firstTypeMask; - uint64_t firstRegisterMask; - uint8_t secondTypeMask; - uint64_t secondRegisterMask; + OperandMask firstMask; + OperandMask secondMask; - c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask, - size, &secondTypeMask, &secondRegisterMask, - vm::TargetBytesPerWord, &thunk); + c->arch->planSource(type, + size, firstMask, + size, secondMask, + vm::TargetBytesPerWord, &thunk); if (thunk) { Stack* oldStack = c->stack; @@ -1404,8 +1398,8 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first assert(c, not threadParameter); - compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), second); - compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), first); + compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), secondValue); + compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), firstValue); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -1418,16 +1412,16 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first appendBranch(c, thunkBranch(c, type), 4, value (c, lir::ValueGeneral, constantSite(c, static_cast(0))), - result, address); + result, addressValue); } else { append (c, new(c->zone) BranchEvent - (c, type, size, first, second, address, - SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), - SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex))); + (c, type, size, firstValue, secondValue, addressValue, + SiteMask(firstMask.typeMask, firstMask.registerMask, AnyFrameIndex), + SiteMask(firstMask.typeMask, firstMask.registerMask >> 32, AnyFrameIndex), + SiteMask(secondMask.typeMask, secondMask.registerMask, AnyFrameIndex), + SiteMask(secondMask.typeMask, secondMask.registerMask >> 32, AnyFrameIndex))); } } @@ -1475,13 +1469,12 @@ class JumpEvent: public Event { cleanLocals(cleanLocals) { bool thunk; - uint8_t typeMask; - uint64_t registerMask; - c->arch->plan(type, vm::TargetBytesPerWord, &typeMask, ®isterMask, &thunk); + OperandMask mask; + c->arch->plan(type, vm::TargetBytesPerWord, mask, &thunk); assert(c, not thunk); - this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + this->addRead(c, address, SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex)); } virtual const char* name() { diff --git a/src/codegen/compiler/site.h b/src/codegen/compiler/site.h index 1360e8959f..bf2cef34b6 100644 --- a/src/codegen/compiler/site.h +++ b/src/codegen/compiler/site.h @@ -40,6 +40,14 @@ class SiteMask { return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex); } + static SiteMask lowPart(const OperandMask& mask) { + return SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex); + } + + static SiteMask highPart(const OperandMask& mask) { + return SiteMask(mask.typeMask, mask.registerMask >> 32, AnyFrameIndex); + } + uint8_t typeMask; uint32_t registerMask; int frameIndex; diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 426891d475..97e5cec19d 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -2258,27 +2258,27 @@ class MyArchitecture: public Assembler::Architecture { virtual void plan (lir::UnaryOperation, - unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned, OperandMask& aMask, bool* thunk) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); - *aRegisterMask = ~static_cast(0); + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); + aMask.registerMask = ~static_cast(0); *thunk = false; } virtual void planSource (lir::BinaryOperation op, - unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned, OperandMask& aMask, unsigned, bool* thunk) { - *aTypeMask = ~0; - *aRegisterMask = ~static_cast(0); + aMask.typeMask = ~0; + aMask.registerMask = ~static_cast(0); *thunk = false; switch (op) { case lir::Negate: - *aTypeMask = (1 << lir::RegisterOperand); + aMask.typeMask = (1 << lir::RegisterOperand); break; case lir::Absolute: @@ -2298,15 +2298,15 @@ class MyArchitecture: public Assembler::Architecture { virtual void planDestination (lir::BinaryOperation op, - unsigned, uint8_t, uint64_t, - unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask) + unsigned, const OperandMask& aMask UNUSED, + unsigned, OperandMask& bMask) { - *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *bRegisterMask = ~static_cast(0); + bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + bMask.registerMask = ~static_cast(0); switch (op) { case lir::Negate: - *bTypeMask = (1 << lir::RegisterOperand); + bMask.typeMask = (1 << lir::RegisterOperand); break; default: @@ -2315,35 +2315,35 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planMove - (unsigned, uint8_t* srcTypeMask, uint64_t* srcRegisterMask, - uint8_t* tmpTypeMask, uint64_t* tmpRegisterMask, - uint8_t dstTypeMask, uint64_t) + (unsigned, OperandMask& srcMask, + OperandMask& tmpMask, + const OperandMask& dstMask) { - *srcTypeMask = ~0; - *srcRegisterMask = ~static_cast(0); + srcMask.typeMask = ~0; + srcMask.registerMask = ~static_cast(0); - *tmpTypeMask = 0; - *tmpRegisterMask = 0; + tmpMask.typeMask = 0; + tmpMask.registerMask = 0; - if (dstTypeMask & (1 << lir::MemoryOperand)) { + if (dstMask.typeMask & (1 << lir::MemoryOperand)) { // can't move directly from memory or constant to memory - *srcTypeMask = 1 << lir::RegisterOperand; - *tmpTypeMask = 1 << lir::RegisterOperand; - *tmpRegisterMask = ~static_cast(0); + srcMask.typeMask = 1 << lir::RegisterOperand; + tmpMask.typeMask = 1 << lir::RegisterOperand; + tmpMask.registerMask = ~static_cast(0); } } virtual void planSource (lir::TernaryOperation op, - unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, - unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask, + unsigned aSize, OperandMask& aMask, + unsigned, OperandMask& bMask, unsigned, bool* thunk) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); - *aRegisterMask = ~static_cast(0); + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); + aMask.registerMask = ~static_cast(0); - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = ~static_cast(0); + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = ~static_cast(0); *thunk = false; @@ -2351,12 +2351,12 @@ class MyArchitecture: public Assembler::Architecture { case lir::Add: case lir::Subtract: if (aSize == 8) { - *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); + aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand); } break; case lir::Multiply: - *aTypeMask = *bTypeMask = (1 << lir::RegisterOperand); + aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand); break; case lir::Divide: @@ -2370,7 +2370,7 @@ class MyArchitecture: public Assembler::Architecture { if (true) {//if (TargetBytesPerWord == 4 and aSize == 8) { *thunk = true; } else { - *aTypeMask = (1 << lir::RegisterOperand); + aMask.typeMask = (1 << lir::RegisterOperand); } break; @@ -2399,16 +2399,16 @@ class MyArchitecture: public Assembler::Architecture { virtual void planDestination (lir::TernaryOperation op, - unsigned, uint8_t, uint64_t, - unsigned, uint8_t, const uint64_t, - unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask) + unsigned, const OperandMask& aMask UNUSED, + unsigned, const OperandMask& bMask UNUSED, + unsigned, OperandMask& cMask) { if (isBranch(op)) { - *cTypeMask = (1 << lir::ConstantOperand); - *cRegisterMask = 0; + cMask.typeMask = (1 << lir::ConstantOperand); + cMask.registerMask = 0; } else { - *cTypeMask = (1 << lir::RegisterOperand); - *cRegisterMask = ~static_cast(0); + cMask.typeMask = (1 << lir::RegisterOperand); + cMask.registerMask = ~static_cast(0); } } diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 5e3fa6aa3c..33b7ce168d 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -2992,37 +2992,34 @@ class MyArchitecture: public Assembler::Architecture { virtual void plan (lir::UnaryOperation, - unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned, OperandMask& aMask, bool* thunk) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand) - | (1 << lir::ConstantOperand); - *aRegisterMask = ~static_cast(0); + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand) | (1 << lir::ConstantOperand); *thunk = false; } virtual void planSource (lir::BinaryOperation op, - unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned aSize, OperandMask& aMask, unsigned bSize, bool* thunk) { - *aTypeMask = ~0; - *aRegisterMask = GeneralRegisterMask | + aMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); *thunk = false; switch (op) { case lir::Negate: - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = (static_cast(1) << (rdx + 32)) + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = (static_cast(1) << (rdx + 32)) | (static_cast(1) << rax); break; case lir::Absolute: if (aSize <= TargetBytesPerWord) { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = (static_cast(1) << rax); + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = (static_cast(1) << rax); } else { *thunk = true; } @@ -3030,8 +3027,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::FloatAbsolute: if (useSSE(&c)) { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = (static_cast(FloatRegisterMask) << 32) + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { *thunk = true; @@ -3041,8 +3038,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::FloatNegate: // floatNegateRR does not support doubles if (useSSE(&c) and aSize == 4 and bSize == 4) { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = FloatRegisterMask; + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = FloatRegisterMask; } else { *thunk = true; } @@ -3050,8 +3047,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::FloatSquareRoot: if (useSSE(&c)) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *aRegisterMask = (static_cast(FloatRegisterMask) << 32) + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + aMask.registerMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { *thunk = true; @@ -3060,8 +3057,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::Float2Float: if (useSSE(&c)) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *aRegisterMask = (static_cast(FloatRegisterMask) << 32) + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + aMask.registerMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { *thunk = true; @@ -3074,8 +3071,8 @@ class MyArchitecture: public Assembler::Architecture { // thunks or produce inline machine code which handles edge // cases properly. if (false and useSSE(&c) and bSize <= TargetBytesPerWord) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *aRegisterMask = (static_cast(FloatRegisterMask) << 32) + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + aMask.registerMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; } else { *thunk = true; @@ -3084,8 +3081,8 @@ class MyArchitecture: public Assembler::Architecture { case lir::Int2Float: if (useSSE(&c) and aSize <= TargetBytesPerWord) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *aRegisterMask = GeneralRegisterMask + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + aMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); } else { *thunk = true; @@ -3093,20 +3090,20 @@ class MyArchitecture: public Assembler::Architecture { break; case lir::Move: - *aTypeMask = ~0; - *aRegisterMask = ~static_cast(0); + aMask.typeMask = ~0; + aMask.registerMask = ~static_cast(0); if (TargetBytesPerWord == 4) { if (aSize == 4 and bSize == 8) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); const uint32_t mask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); - *aRegisterMask = (static_cast(mask) << 32) | mask; + aMask.registerMask = (static_cast(mask) << 32) | mask; } else if (aSize == 1 or bSize == 1) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); const uint32_t mask = (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx); - *aRegisterMask = (static_cast(mask) << 32) | mask; + aMask.registerMask = (static_cast(mask) << 32) | mask; } } break; @@ -3117,69 +3114,69 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (lir::BinaryOperation op, unsigned aSize, uint8_t aTypeMask, - uint64_t aRegisterMask, unsigned bSize, uint8_t* bTypeMask, - uint64_t* bRegisterMask) + (lir::BinaryOperation op, + unsigned aSize, const OperandMask& aMask, + unsigned bSize, OperandMask& bMask) { - *bTypeMask = ~0; - *bRegisterMask = GeneralRegisterMask + bMask.typeMask = ~0; + bMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); switch (op) { case lir::Absolute: - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = (static_cast(1) << rax); + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = (static_cast(1) << rax); break; case lir::FloatAbsolute: - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = aRegisterMask; + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = aMask.registerMask; break; case lir::Negate: - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = aRegisterMask; + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = aMask.registerMask; break; case lir::FloatNegate: case lir::FloatSquareRoot: case lir::Float2Float: case lir::Int2Float: - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = (static_cast(FloatRegisterMask) << 32) + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; break; case lir::Float2Int: - *bTypeMask = (1 << lir::RegisterOperand); + bMask.typeMask = (1 << lir::RegisterOperand); break; case lir::Move: - if (aTypeMask & ((1 << lir::MemoryOperand) | 1 << lir::AddressOperand)) { - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = GeneralRegisterMask + if (aMask.typeMask & ((1 << lir::MemoryOperand) | 1 << lir::AddressOperand)) { + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32) | FloatRegisterMask; - } else if (aTypeMask & (1 << lir::RegisterOperand)) { - *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - if (aRegisterMask & FloatRegisterMask) { - *bRegisterMask = FloatRegisterMask; + } else if (aMask.typeMask & (1 << lir::RegisterOperand)) { + bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + if (aMask.registerMask & FloatRegisterMask) { + bMask.registerMask = FloatRegisterMask; } else { - *bRegisterMask = GeneralRegisterMask + bMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); } } else { - *bTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); } if (TargetBytesPerWord == 4) { if (aSize == 4 and bSize == 8) { - *bRegisterMask = (static_cast(1) << (rdx + 32)) + bMask.registerMask = (static_cast(1) << (rdx + 32)) | (static_cast(1) << rax); } else if (aSize == 1 or bSize == 1) { const uint32_t mask = (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx); - *bRegisterMask = (static_cast(mask) << 32) | mask; + bMask.registerMask = (static_cast(mask) << 32) | mask; } } break; @@ -3190,44 +3187,44 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planMove - (unsigned size, uint8_t* srcTypeMask, uint64_t* srcRegisterMask, - uint8_t* tmpTypeMask, uint64_t* tmpRegisterMask, - uint8_t dstTypeMask, uint64_t dstRegisterMask) + (unsigned size, OperandMask& srcMask, + OperandMask& tmpMask, + const OperandMask& dstMask) { - *srcTypeMask = ~0; - *srcRegisterMask = ~static_cast(0); + srcMask.typeMask = ~0; + srcMask.registerMask = ~static_cast(0); - *tmpTypeMask = 0; - *tmpRegisterMask = 0; + tmpMask.typeMask = 0; + tmpMask.registerMask = 0; - if (dstTypeMask & (1 << lir::MemoryOperand)) { + if (dstMask.typeMask & (1 << lir::MemoryOperand)) { // can't move directly from memory to memory - *srcTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); - *tmpTypeMask = 1 << lir::RegisterOperand; - *tmpRegisterMask = GeneralRegisterMask + srcMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); + tmpMask.typeMask = 1 << lir::RegisterOperand; + tmpMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); - } else if (dstTypeMask & (1 << lir::RegisterOperand)) { + } else if (dstMask.typeMask & (1 << lir::RegisterOperand)) { if (size > TargetBytesPerWord) { // can't move directly from FPR to GPR or vice-versa for // values larger than the GPR size - if (dstRegisterMask & FloatRegisterMask) { - *srcRegisterMask = FloatRegisterMask + if (dstMask.registerMask & FloatRegisterMask) { + srcMask.registerMask = FloatRegisterMask | (static_cast(FloatRegisterMask) << 32); - *tmpTypeMask = 1 << lir::MemoryOperand; - } else if (dstRegisterMask & GeneralRegisterMask) { - *srcRegisterMask = GeneralRegisterMask + tmpMask.typeMask = 1 << lir::MemoryOperand; + } else if (dstMask.registerMask & GeneralRegisterMask) { + srcMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); - *tmpTypeMask = 1 << lir::MemoryOperand; + tmpMask.typeMask = 1 << lir::MemoryOperand; } } - if (dstRegisterMask & FloatRegisterMask) { + if (dstMask.registerMask & FloatRegisterMask) { // can't move directly from constant to FPR - *srcTypeMask &= ~(1 << lir::ConstantOperand); + srcMask.typeMask &= ~(1 << lir::ConstantOperand); if (size > TargetBytesPerWord) { - *tmpTypeMask = 1 << lir::MemoryOperand; + tmpMask.typeMask = 1 << lir::MemoryOperand; } else { - *tmpTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *tmpRegisterMask = GeneralRegisterMask + tmpMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + tmpMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); } } @@ -3236,16 +3233,16 @@ class MyArchitecture: public Assembler::Architecture { virtual void planSource (lir::TernaryOperation op, - unsigned aSize, uint8_t *aTypeMask, uint64_t *aRegisterMask, - unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask, + unsigned aSize, OperandMask& aMask, + unsigned bSize, OperandMask& bMask, unsigned, bool* thunk) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); - *aRegisterMask = GeneralRegisterMask + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand); + aMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); - *bTypeMask = (1 << lir::RegisterOperand); - *bRegisterMask = GeneralRegisterMask + bMask.typeMask = (1 << lir::RegisterOperand); + bMask.registerMask = GeneralRegisterMask | (static_cast(GeneralRegisterMask) << 32); *thunk = false; @@ -3256,14 +3253,14 @@ class MyArchitecture: public Assembler::Architecture { case lir::FloatMultiply: case lir::FloatDivide: if (useSSE(&c)) { - *aTypeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); - *bTypeMask = (1 << lir::RegisterOperand); + aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand); + bMask.typeMask = (1 << lir::RegisterOperand); const uint64_t mask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; - *aRegisterMask = mask; - *bRegisterMask = mask; + aMask.registerMask = mask; + bMask.registerMask = mask; } else { *thunk = true; } @@ -3276,11 +3273,11 @@ class MyArchitecture: public Assembler::Architecture { case lir::Multiply: if (TargetBytesPerWord == 4 and aSize == 8) { const uint32_t mask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); - *aRegisterMask = (static_cast(mask) << 32) | mask; - *bRegisterMask = (static_cast(1) << (rdx + 32)) | mask; + aMask.registerMask = (static_cast(mask) << 32) | mask; + bMask.registerMask = (static_cast(1) << (rdx + 32)) | mask; } else { - *aRegisterMask = GeneralRegisterMask; - *bRegisterMask = GeneralRegisterMask; + aMask.registerMask = GeneralRegisterMask; + bMask.registerMask = GeneralRegisterMask; } break; @@ -3288,9 +3285,9 @@ class MyArchitecture: public Assembler::Architecture { if (TargetBytesPerWord == 4 and aSize == 8) { *thunk = true; } else { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); - *bRegisterMask = 1 << rax; + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); + bMask.registerMask = 1 << rax; } break; @@ -3298,9 +3295,9 @@ class MyArchitecture: public Assembler::Architecture { if (TargetBytesPerWord == 4 and aSize == 8) { *thunk = true; } else { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); - *bRegisterMask = 1 << rax; + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); + bMask.registerMask = 1 << rax; } break; @@ -3309,13 +3306,13 @@ class MyArchitecture: public Assembler::Architecture { case lir::UnsignedShiftRight: { if (TargetBytesPerWord == 4 and bSize == 8) { const uint32_t mask = GeneralRegisterMask & ~(1 << rcx); - *aRegisterMask = (static_cast(mask) << 32) | mask; - *bRegisterMask = (static_cast(mask) << 32) | mask; + aMask.registerMask = (static_cast(mask) << 32) | mask; + bMask.registerMask = (static_cast(mask) << 32) | mask; } else { - *aRegisterMask = (static_cast(GeneralRegisterMask) << 32) + aMask.registerMask = (static_cast(GeneralRegisterMask) << 32) | (static_cast(1) << rcx); const uint32_t mask = GeneralRegisterMask & ~(1 << rcx); - *bRegisterMask = (static_cast(mask) << 32) | mask; + bMask.registerMask = (static_cast(mask) << 32) | mask; } } break; @@ -3330,11 +3327,11 @@ class MyArchitecture: public Assembler::Architecture { case lir::JumpIfFloatLessOrEqualOrUnordered: case lir::JumpIfFloatGreaterOrEqualOrUnordered: if (useSSE(&c)) { - *aTypeMask = (1 << lir::RegisterOperand); - *aRegisterMask = (static_cast(FloatRegisterMask) << 32) + aMask.typeMask = (1 << lir::RegisterOperand); + aMask.registerMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; - *bTypeMask = *aTypeMask; - *bRegisterMask = *aRegisterMask; + bMask.typeMask = aMask.typeMask; + bMask.registerMask = aMask.registerMask; } else { *thunk = true; } @@ -3346,16 +3343,17 @@ class MyArchitecture: public Assembler::Architecture { } virtual void planDestination - (lir::TernaryOperation op, unsigned, uint8_t, uint64_t, unsigned, uint8_t, - uint64_t bRegisterMask, unsigned, uint8_t* cTypeMask, - uint64_t* cRegisterMask) + (lir::TernaryOperation op, + unsigned, const OperandMask&, + unsigned, const OperandMask& bMask, + unsigned, OperandMask& cMask) { if (isBranch(op)) { - *cTypeMask = (1 << lir::ConstantOperand); - *cRegisterMask = 0; + cMask.typeMask = (1 << lir::ConstantOperand); + cMask.registerMask = 0; } else { - *cTypeMask = (1 << lir::RegisterOperand); - *cRegisterMask = bRegisterMask; + cMask.typeMask = (1 << lir::RegisterOperand); + cMask.registerMask = bMask.registerMask; } } diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp index 3fe8a07427..78317c19c8 100644 --- a/unittest/codegen/assembler-test.cpp +++ b/unittest/codegen/assembler-test.cpp @@ -84,12 +84,11 @@ public: for(int op = (int)lir::Call; op < (int)lir::AlignedJump; op++) { bool thunk; - uint8_t typeMask; - uint64_t registerMask; - env.arch->plan((lir::UnaryOperation)op, vm::TargetBytesPerWord, &typeMask, ®isterMask, &thunk); + OperandMask mask; + env.arch->plan((lir::UnaryOperation)op, vm::TargetBytesPerWord, mask, &thunk); assertFalse(thunk); - assertNotEqual(static_cast(0), typeMask); - assertNotEqual(static_cast(0), registerMask); + assertNotEqual(static_cast(0), mask.typeMask); + assertNotEqual(static_cast(0), mask.registerMask); } } From 49bfda3932bc4e4f7af128ea3a1c8042bf42914a Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 15 Feb 2013 22:04:32 -0700 Subject: [PATCH 248/378] construct SiteMasks based on OperationMasks --- src/codegen/compiler.cpp | 6 ++--- src/codegen/compiler/event.cpp | 40 +++++++++++++++++----------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index de46f1c639..bd67d8bdc1 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -340,7 +340,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, (size, src, tmp, OperandMask(dstMask.typeMask, dstMask.registerMask)); - SiteMask srcMask(src.typeMask, src.registerMask, AnyFrameIndex); + SiteMask srcMask = SiteMask::lowPart(src); for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) { Site* s = it.next(); if (s->match(c, srcMask) or s->match(c, dstMask)) { @@ -365,7 +365,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, (size, src, tmp, OperandMask(1 << dstSite->type(c), dstSite->registerMask(c))); - SiteMask srcMask(src.typeMask, src.registerMask, AnyFrameIndex); + SiteMask srcMask = SiteMask::lowPart(src); unsigned cost = 0xFFFFFFFF; Site* srcSite = 0; for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) { @@ -403,7 +403,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord, srcSite->freeze(c, value); dstSite->freeze(c, value); - SiteMask tmpMask(tmp.typeMask, tmp.registerMask, AnyFrameIndex); + SiteMask tmpMask = SiteMask::lowPart(tmp); SingleRead tmpRead(tmpMask, 0); tmpRead.value = value; tmpRead.successor_ = value; diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index a785001de9..3cb37b821c 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -580,8 +580,8 @@ class MoveEvent: public Event { | static_cast(srcValue->source->registerMask(c))), dstSize, dst); - SiteMask dstLowMask(dst.typeMask, dst.registerMask, AnyFrameIndex); - SiteMask dstHighMask(dst.typeMask, dst.registerMask >> 32, AnyFrameIndex); + SiteMask dstLowMask = SiteMask::lowPart(dst); + SiteMask dstHighMask = SiteMask::highPart(dst); if (srcSelectSize >= vm::TargetBytesPerWord and dstSize >= vm::TargetBytesPerWord @@ -710,8 +710,8 @@ appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, append(c, new(c->zone) MoveEvent (c, type, srcSize, srcSelectSize, srcValue, dstSize, dstValue, - SiteMask(src.typeMask, src.registerMask, AnyFrameIndex), - SiteMask(src.typeMask, src.registerMask >> 32, AnyFrameIndex))); + SiteMask::lowPart(src), + SiteMask::highPart(src))); } @@ -846,8 +846,8 @@ class CombineEvent: public Event { resultSize, cMask); - SiteMask resultLowMask(cMask.typeMask, cMask.registerMask, AnyFrameIndex); - SiteMask resultHighMask(cMask.typeMask, cMask.registerMask >> 32, AnyFrameIndex); + SiteMask resultLowMask = SiteMask::lowPart(cMask); + SiteMask resultHighMask = SiteMask::highPart(cMask); Site* low = getTarget(c, secondValue, resultValue, resultLowMask); unsigned lowSize = low->registerSize(c); @@ -943,10 +943,10 @@ appendCombine(Context* c, lir::TernaryOperation type, firstSize, firstValue, secondSize, secondValue, resultSize, resultValue, - SiteMask(firstMask.typeMask, firstMask.registerMask, AnyFrameIndex), - SiteMask(firstMask.typeMask, firstMask.registerMask >> 32, AnyFrameIndex), - SiteMask(secondMask.typeMask, secondMask.registerMask, AnyFrameIndex), - SiteMask(secondMask.typeMask, secondMask.registerMask >> 32, AnyFrameIndex))); + SiteMask::lowPart(firstMask), + SiteMask::highPart(firstMask), + SiteMask::lowPart(secondMask), + SiteMask::highPart(secondMask))); } } @@ -988,8 +988,8 @@ class TranslateEvent: public Event { resultSize, bMask); - SiteMask resultLowMask(bMask.typeMask, bMask.registerMask, AnyFrameIndex); - SiteMask resultHighMask(bMask.typeMask, bMask.registerMask >> 32, AnyFrameIndex); + SiteMask resultLowMask = SiteMask::lowPart(bMask); + SiteMask resultHighMask = SiteMask::highPart(bMask); Site* low = getTarget(c, value, resultValue, resultLowMask); unsigned lowSize = low->registerSize(c); @@ -1056,8 +1056,8 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, append(c, new(c->zone) TranslateEvent (c, type, firstSize, firstValue, resultSize, resultValue, - SiteMask(first.typeMask, first.registerMask, AnyFrameIndex), - SiteMask(first.typeMask, first.registerMask >> 32, AnyFrameIndex))); + SiteMask::lowPart(first), + SiteMask::highPart(first))); } } @@ -1317,7 +1317,7 @@ class BranchEvent: public Event { size, OperandMask(0, 0), vm::TargetBytesPerWord, dstMask); - this->addRead(c, addressValue, SiteMask(dstMask.typeMask, dstMask.registerMask, AnyFrameIndex)); + this->addRead(c, addressValue, SiteMask::lowPart(dstMask)); } virtual const char* name() { @@ -1418,10 +1418,10 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first (c, new(c->zone) BranchEvent (c, type, size, firstValue, secondValue, addressValue, - SiteMask(firstMask.typeMask, firstMask.registerMask, AnyFrameIndex), - SiteMask(firstMask.typeMask, firstMask.registerMask >> 32, AnyFrameIndex), - SiteMask(secondMask.typeMask, secondMask.registerMask, AnyFrameIndex), - SiteMask(secondMask.typeMask, secondMask.registerMask >> 32, AnyFrameIndex))); + SiteMask::lowPart(firstMask), + SiteMask::highPart(firstMask), + SiteMask::lowPart(secondMask), + SiteMask::highPart(secondMask))); } } @@ -1474,7 +1474,7 @@ class JumpEvent: public Event { assert(c, not thunk); - this->addRead(c, address, SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex)); + this->addRead(c, address, SiteMask::lowPart(mask)); } virtual const char* name() { From 61f03643e0db111863469efc5c329c99055545ce Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sat, 16 Feb 2013 19:50:34 -0700 Subject: [PATCH 249/378] begin splitting up x86 assembler --- makefile | 37 ++-- src/codegen/x86/assembler.cpp | 368 +++++----------------------------- src/codegen/x86/block.cpp | 39 ++++ src/codegen/x86/block.h | 40 ++++ src/codegen/x86/context.cpp | 34 ++++ src/codegen/x86/context.h | 91 +++++++++ src/codegen/x86/fixup.cpp | 106 ++++++++++ src/codegen/x86/fixup.h | 87 ++++++++ src/codegen/x86/padding.cpp | 68 +++++++ src/codegen/x86/padding.h | 38 ++++ src/common.h | 12 ++ 11 files changed, 583 insertions(+), 337 deletions(-) create mode 100644 src/codegen/x86/block.cpp create mode 100644 src/codegen/x86/block.h create mode 100644 src/codegen/x86/context.cpp create mode 100644 src/codegen/x86/context.h create mode 100644 src/codegen/x86/fixup.cpp create mode 100644 src/codegen/x86/fixup.h create mode 100644 src/codegen/x86/padding.cpp create mode 100644 src/codegen/x86/padding.h diff --git a/makefile b/makefile index 1e29f0ca91..d0d451c9ae 100755 --- a/makefile +++ b/makefile @@ -939,7 +939,7 @@ generated-code = \ $(build)/type-name-initializations.cpp \ $(build)/type-maps.cpp -vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) $(wildcard $(src)/codegen/compiler/*.h) +vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) vm-sources = \ $(src)/$(system).cpp \ @@ -968,26 +968,31 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) compiler-sources = \ $(src)/codegen/compiler.cpp \ - $(src)/codegen/compiler/context.cpp \ - $(src)/codegen/compiler/resource.cpp \ - $(src)/codegen/compiler/site.cpp \ - $(src)/codegen/compiler/regalloc.cpp \ - $(src)/codegen/compiler/value.cpp \ - $(src)/codegen/compiler/read.cpp \ - $(src)/codegen/compiler/event.cpp \ - $(src)/codegen/compiler/promise.cpp \ - $(src)/codegen/compiler/frame.cpp \ - $(src)/codegen/compiler/ir.cpp \ + $(wildcard $(src)/codegen/compiler/*.cpp) \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp +compiler-objects = $(call cpp-objects,$(compiler-sources),$(src),$(build)) +$(compiler-objects): $(wildcard $(src)/codegen/compiler/*.h) $(vm-depends) + +x86-assembler-sources = $(wildcard $(src)/codegen/x86/*.cpp) +x86-assembler-objects = $(call cpp-objects,$(x86-assembler-sources),$(src),$(build)) +$(x86-assembler-objects): $(wildcard $(src)/codegen/x86/*.h) $(vm-depends) + +arm-assembler-sources = $(wildcard $(src)/codegen/arm/*.cpp) +arm-assembler-objects = $(call cpp-objects,$(arm-assembler-sources),$(src),$(build)) +$(arm-assembler-objects): $(wildcard $(src)/codegen/arm/*.h) $(vm-depends) + +powerpc-assembler-sources = $(wildcard $(src)/codegen/powerpc/*.cpp) +powerpc-assembler-objects = $(call cpp-objects,$(powerpc-assembler-sources),$(src),$(build)) +$(powerpc-assembler-objects): $(wildcard $(src)/codegen/powerpc/*.h) $(vm-depends) all-assembler-sources = \ - $(src)/codegen/x86/assembler.cpp \ - $(src)/codegen/arm/assembler.cpp \ - $(src)/codegen/powerpc/assembler.cpp + $(x86-assembler-sources) \ + $(arm-assembler-sources) \ + $(powerpc-assembler-sources) -native-assembler-sources = \ - $(src)/codegen/$(target-asm)/assembler.cpp +native-assembler-sources = $($(target-asm)-assembler-sources) +native-assembler-objects = $($(target-asm)-assembler-objects) all-codegen-target-sources = \ $(compiler-sources) \ diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 33b7ce168d..c455f3e963 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -15,6 +15,11 @@ #include "codegen/assembler.h" #include "codegen/registers.h" +#include "codegen/x86/context.h" +#include "codegen/x86/block.h" +#include "codegen/x86/fixup.h" +#include "codegen/x86/padding.h" + #include "util/runtime-array.h" #include "util/abort.h" @@ -23,11 +28,10 @@ #define CAST_BRANCH(x) reinterpret_cast(x) using namespace vm; -using namespace avian::codegen; -namespace { - -namespace local { +namespace avian { +namespace codegen { +namespace x86 { enum { rax = 0, @@ -82,18 +86,6 @@ const int LongJumpRegister = r10; const unsigned StackAlignmentInBytes = 16; const unsigned StackAlignmentInWords = StackAlignmentInBytes / TargetBytesPerWord; -bool -isInt8(target_intptr_t v) -{ - return v == static_cast(v); -} - -bool -isInt32(target_intptr_t v) -{ - return v == static_cast(v); -} - class Task; class AlignmentPadding; @@ -101,213 +93,6 @@ unsigned padding(AlignmentPadding* p, unsigned index, unsigned offset, AlignmentPadding* limit); -class Context; -class MyBlock; - -ResolvedPromise* -resolved(Context* c, int64_t value); - -class MyBlock: public Assembler::Block { - public: - MyBlock(unsigned offset): - next(0), firstPadding(0), lastPadding(0), offset(offset), start(~0), - size(0) - { } - - virtual unsigned resolve(unsigned start, Assembler::Block* next) { - this->start = start; - this->next = static_cast(next); - - return start + size + padding(firstPadding, start, offset, lastPadding); - } - - MyBlock* next; - AlignmentPadding* firstPadding; - AlignmentPadding* lastPadding; - unsigned offset; - unsigned start; - unsigned size; -}; - -typedef void (*OperationType)(Context*); - -typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); - -typedef void (*BinaryOperationType) -(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); - -typedef void (*BranchOperationType) -(Context*, lir::TernaryOperation, unsigned, lir::Operand*, - lir::Operand*, lir::Operand*); - -class ArchitectureContext { - public: - ArchitectureContext(System* s, bool useNativeFeatures): - s(s), useNativeFeatures(useNativeFeatures) - { } - - System* s; - bool useNativeFeatures; - OperationType operations[lir::OperationCount]; - UnaryOperationType unaryOperations[lir::UnaryOperationCount - * lir::OperandTypeCount]; - BinaryOperationType binaryOperations - [(lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) - * lir::OperandTypeCount - * lir::OperandTypeCount]; - BranchOperationType branchOperations - [lir::BranchOperationCount - * lir::OperandTypeCount - * lir::OperandTypeCount]; -}; - -class Context { - public: - Context(System* s, Allocator* a, Zone* zone, ArchitectureContext* ac): - s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new(zone) MyBlock(0)), - lastBlock(firstBlock), ac(ac) - { } - - System* s; - Zone* zone; - Assembler::Client* client; - Vector code; - Task* tasks; - uint8_t* result; - MyBlock* firstBlock; - MyBlock* lastBlock; - ArchitectureContext* ac; -}; - -Aborter* getAborter(Context* c) { - return c->s; -} - -Aborter* getAborter(ArchitectureContext* c) { - return c->s; -} - -ResolvedPromise* -resolved(Context* c, int64_t value) -{ - return new(c->zone) ResolvedPromise(value); -} - -class Offset: public Promise { - public: - Offset(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit): - c(c), block(block), offset(offset), limit(limit), value_(-1) - { } - - virtual bool resolved() { - return block->start != static_cast(~0); - } - - virtual int64_t value() { - assert(c, resolved()); - - if (value_ == -1) { - value_ = block->start + (offset - block->offset) - + padding(block->firstPadding, block->start, block->offset, limit); - } - - return value_; - } - - Context* c; - MyBlock* block; - unsigned offset; - AlignmentPadding* limit; - int value_; -}; - -Promise* -offset(Context* c) -{ - return new(c->zone) Offset(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); -} - -class Task { - public: - Task(Task* next): next(next) { } - - virtual void run(Context* c) = 0; - - Task* next; -}; - -void* -resolveOffset(System* s, uint8_t* instruction, unsigned instructionSize, - int64_t value) -{ - intptr_t v = reinterpret_cast(value) - - instruction - instructionSize; - - expect(s, isInt32(v)); - - int32_t v4 = v; - memcpy(instruction + instructionSize - 4, &v4, 4); - return instruction + instructionSize; -} - -class OffsetListener: public Promise::Listener { - public: - OffsetListener(System* s, uint8_t* instruction, - unsigned instructionSize): - s(s), - instruction(instruction), - instructionSize(instructionSize) - { } - - virtual bool resolve(int64_t value, void** location) { - void* p = resolveOffset(s, instruction, instructionSize, value); - if (location) *location = p; - return false; - } - - System* s; - uint8_t* instruction; - unsigned instructionSize; -}; - -class OffsetTask: public Task { - public: - OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, - unsigned instructionSize): - Task(next), - promise(promise), - instructionOffset(instructionOffset), - instructionSize(instructionSize) - { } - - virtual void run(Context* c) { - if (promise->resolved()) { - resolveOffset - (c->s, c->result + instructionOffset->value(), instructionSize, - promise->value()); - } else { - new (promise->listen(sizeof(OffsetListener))) - OffsetListener(c->s, c->result + instructionOffset->value(), - instructionSize); - } - } - - Promise* promise; - Promise* instructionOffset; - unsigned instructionSize; -}; - -void -appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, - unsigned instructionSize) -{ - OffsetTask* task = - new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, instructionSize); - - c->tasks = task; -} - void copy(System* s, void* dst, int64_t src, unsigned size) { @@ -378,60 +163,6 @@ appendImmediateTask(Context* c, Promise* promise, Promise* offset, (c->tasks, promise, offset, size, promiseOffset); } -class AlignmentPadding { - public: - AlignmentPadding(Context* c, unsigned instructionOffset, unsigned alignment): - offset(c->code.length()), - instructionOffset(instructionOffset), - alignment(alignment), - next(0), - padding(-1) - { - if (c->lastBlock->firstPadding) { - c->lastBlock->lastPadding->next = this; - } else { - c->lastBlock->firstPadding = this; - } - c->lastBlock->lastPadding = this; - } - - unsigned offset; - unsigned instructionOffset; - unsigned alignment; - AlignmentPadding* next; - int padding; -}; - -unsigned -padding(AlignmentPadding* p, unsigned start, unsigned offset, - AlignmentPadding* limit) -{ - unsigned padding = 0; - if (limit) { - if (limit->padding == -1) { - for (; p; p = p->next) { - if (p->padding == -1) { - unsigned index = p->offset - offset; - while ((start + index + padding + p->instructionOffset) - % p->alignment) - { - ++ padding; - } - - p->padding = padding; - - if (p == limit) break; - } else { - padding = p->padding; - } - } - } else { - padding = limit->padding; - } - } - return padding; -} - extern "C" bool detectFeature(unsigned ecx, unsigned edx); @@ -558,7 +289,7 @@ modrmSibImm(Context* c, int a, int scale, int index, int base, int offset) { if (offset == 0 and regCode(base) != rbp) { modrmSib(c, 0x00, a, scale, index, base); - } else if (isInt8(offset)) { + } else if (vm::fitsInInt8(offset)) { modrmSib(c, 0x40, a, scale, index, base); c->code.append(offset); } else { @@ -627,7 +358,7 @@ storeLoadBarrier(Context* c) void unconditional(Context* c, unsigned jump, lir::Constant* a) { - appendOffsetTask(c, a->value, offset(c), 5); + appendOffsetTask(c, a->value, offsetPromise(c), 5); opcode(c, jump); c->code.append4(0); @@ -636,7 +367,7 @@ unconditional(Context* c, unsigned jump, lir::Constant* a) void conditional(Context* c, unsigned condition, lir::Constant* a) { - appendOffsetTask(c, a->value, offset(c), 6); + appendOffsetTask(c, a->value, offsetPromise(c), 6); opcode(c, 0x0f, condition); c->code.append4(0); @@ -904,7 +635,7 @@ moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, c->code.appendTargetAddress(a->value->value()); } else { appendImmediateTask - (c, a->value, offset(c), TargetBytesPerWord, promiseOffset); + (c, a->value, offsetPromise(c), TargetBytesPerWord, promiseOffset); c->code.appendTargetAddress(static_cast(0)); } } @@ -1260,14 +991,14 @@ moveCM(Context* c, unsigned aSize UNUSED, lir::Constant* a, if (a->value->resolved()) { c->code.append4(a->value->value()); } else { - appendImmediateTask(c, a->value, offset(c), 4); + appendImmediateTask(c, a->value, offsetPromise(c), 4); c->code.append4(0); } break; case 8: { if (TargetBytesPerWord == 8) { - if (a->value->resolved() and isInt32(a->value->value())) { + if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { maybeRex(c, bSize, b); opcode(c, 0xc7); modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); @@ -1358,7 +1089,7 @@ addCarryCR(Context* c, unsigned size, lir::Constant* a, int64_t v = a->value->value(); maybeRex(c, size, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xd0 + regCode(b)); c->code.append(v); } else { @@ -1387,9 +1118,9 @@ addCR(Context* c, unsigned aSize, lir::Constant* a, addCR(c, 4, &al, 4, b); addCarryCR(c, 4, &ah, &bh); } else { - if (isInt32(v)) { + if (vm::fitsInInt32(v)) { maybeRex(c, aSize, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xc0 + regCode(b)); c->code.append(v); } else { @@ -1414,7 +1145,7 @@ subtractBorrowCR(Context* c, unsigned size UNUSED, lir::Constant* a, assert(c, TargetBytesPerWord == 8 or size == 4); int64_t v = a->value->value(); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xd8 + regCode(b)); c->code.append(v); } else { @@ -1447,9 +1178,9 @@ subtractCR(Context* c, unsigned aSize, lir::Constant* a, subtractCR(c, 4, &al, 4, b); subtractBorrowCR(c, 4, &ah, &bh); } else { - if (isInt32(v)) { + if (vm::fitsInInt32(v)) { maybeRex(c, aSize, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xe8 + regCode(b)); c->code.append(v); } else { @@ -1537,9 +1268,9 @@ andCR(Context* c, unsigned aSize, lir::Constant* a, andCR(c, 4, &al, 4, b); andCR(c, 4, &ah, 4, &bh); } else { - if (isInt32(v)) { + if (vm::fitsInInt32(v)) { maybeRex(c, aSize, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xe0 + regCode(b)); c->code.append(v); } else { @@ -1595,9 +1326,9 @@ orCR(Context* c, unsigned aSize, lir::Constant* a, orCR(c, 4, &al, 4, b); orCR(c, 4, &ah, 4, &bh); } else { - if (isInt32(v)) { + if (vm::fitsInInt32(v)) { maybeRex(c, aSize, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xc8 + regCode(b)); c->code.append(v); } else { @@ -1652,9 +1383,9 @@ xorCR(Context* c, unsigned aSize, lir::Constant* a, xorCR(c, 4, &al, 4, b); xorCR(c, 4, &ah, 4, &bh); } else { - if (isInt32(v)) { + if (vm::fitsInInt32(v)) { maybeRex(c, aSize, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xf0 + regCode(b)); c->code.append(v); } else { @@ -1828,10 +1559,10 @@ compareCR(Context* c, unsigned aSize, lir::Constant* a, assert(c, aSize == bSize); assert(c, TargetBytesPerWord == 8 or aSize == 4); - if (a->value->resolved() and isInt32(a->value->value())) { + if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { int64_t v = a->value->value(); maybeRex(c, aSize, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x83, 0xf8 + regCode(b)); c->code.append(v); } else { @@ -1871,12 +1602,12 @@ compareCM(Context* c, unsigned aSize, lir::Constant* a, if (a->value->resolved()) { int64_t v = a->value->value(); maybeRex(c, aSize, b); - opcode(c, isInt8(v) ? 0x83 : 0x81); + opcode(c, vm::fitsInInt8(v) ? 0x83 : 0x81); modrmSibImm(c, rdi, b->scale, b->index, b->base, b->offset); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { c->code.append(v); - } else if (isInt32(v)) { + } else if (vm::fitsInInt32(v)) { c->code.append4(v); } else { abort(c); @@ -2070,9 +1801,9 @@ multiplyCR(Context* c, unsigned aSize, lir::Constant* a, } else { int64_t v = a->value->value(); if (v != 1) { - if (isInt32(v)) { + if (vm::fitsInInt32(v)) { maybeRex(c, bSize, b, b); - if (isInt8(v)) { + if (vm::fitsInInt8(v)) { opcode(c, 0x6b); modrm(c, 0xc0, b, b); c->code.append(v); @@ -2150,7 +1881,7 @@ doShift(Context* c, UNUSED void (*shift) maybeRex(c, bSize, b); if (v == 1) { opcode(c, 0xd1, type + regCode(b)); - } else if (isInt8(v)) { + } else if (vm::fitsInInt8(v)) { opcode(c, 0xc1, type + regCode(b)); c->code.append(v); } else { @@ -2796,7 +2527,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentFootprint(unsigned footprint) { - return local::argumentFootprint(footprint); + return x86::argumentFootprint(footprint); } virtual bool argumentAlignment() { @@ -2904,7 +2635,7 @@ class MyArchitecture: public Assembler::Architecture { intptr_t v = static_cast(newTarget) - static_cast(returnAddress); - assert(&c, isInt32(v)); + assert(&c, vm::fitsInInt32(v)); int32_t v32 = v; @@ -2939,7 +2670,7 @@ class MyArchitecture: public Assembler::Architecture { unsigned targetParameterFootprint, void** ip, void** stack) { - local::nextFrame(&c, static_cast(start), size, footprint, + x86::nextFrame(&c, static_cast(start), size, footprint, link, mostRecent, targetParameterFootprint, ip, stack); } @@ -3393,7 +3124,7 @@ class MyAssembler: public Assembler { { lir::Register stack(rsp); lir::Memory stackLimit(rbx, stackLimitOffsetFromThread); - lir::Constant handlerConstant(resolved(&c, handler)); + lir::Constant handlerConstant(resolvedPromise(&c, handler)); branchRM(&c, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } @@ -3470,7 +3201,7 @@ class MyAssembler: public Assembler { OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &base)); } - lir::Constant footprintConstant(resolved(&c, footprint * TargetBytesPerWord)); + lir::Constant footprintConstant(resolvedPromise(&c, footprint * TargetBytesPerWord)); apply(lir::Subtract, OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &footprintConstant), OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), @@ -3479,7 +3210,7 @@ class MyAssembler: public Assembler { virtual void adjustFrame(unsigned difference) { lir::Register stack(rsp); - lir::Constant differenceConstant(resolved(&c, difference * TargetBytesPerWord)); + lir::Constant differenceConstant(resolvedPromise(&c, difference * TargetBytesPerWord)); apply(lir::Subtract, OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &differenceConstant), OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), @@ -3497,7 +3228,7 @@ class MyAssembler: public Assembler { popR(&c, TargetBytesPerWord, &base); } else { lir::Register stack(rsp); - lir::Constant footprint(resolved(&c, frameFootprint * TargetBytesPerWord)); + lir::Constant footprint(resolvedPromise(&c, frameFootprint * TargetBytesPerWord)); apply(lir::Add, OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &footprint), OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack), @@ -3536,7 +3267,7 @@ class MyAssembler: public Assembler { lir::Register stack(rsp); lir::Constant footprint - (resolved + (resolvedPromise (&c, (frameFootprint - offset + baseSize) * TargetBytesPerWord)); addCR(&c, TargetBytesPerWord, &footprint, TargetBytesPerWord, &stack); @@ -3578,7 +3309,7 @@ class MyAssembler: public Assembler { lir::Register stack(rsp); lir::Constant adjustment - (resolved(&c, (argumentFootprint - StackAlignmentInWords) + (resolvedPromise(&c, (argumentFootprint - StackAlignmentInWords) * TargetBytesPerWord)); addCR(&c, TargetBytesPerWord, &adjustment, TargetBytesPerWord, &stack); @@ -3674,7 +3405,7 @@ class MyAssembler: public Assembler { } virtual Promise* offset(bool) { - return local::offset(&c); + return x86::offsetPromise(&c); } virtual Block* endBlock(bool startNew) { @@ -3713,17 +3444,12 @@ Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { new(zone) MyAssembler(c.s, allocator, zone, this); } -} // namespace local - -} // namespace - -namespace avian { -namespace codegen { +} // namespace x86 Assembler::Architecture* makeArchitectureX86(System* system, bool useNativeFeatures) { - return new (allocate(system, sizeof(local::MyArchitecture))) - local::MyArchitecture(system, useNativeFeatures); + return new (allocate(system, sizeof(x86::MyArchitecture))) + x86::MyArchitecture(system, useNativeFeatures); } } // namespace codegen diff --git a/src/codegen/x86/block.cpp b/src/codegen/x86/block.cpp new file mode 100644 index 0000000000..152fd99a8d --- /dev/null +++ b/src/codegen/x86/block.cpp @@ -0,0 +1,39 @@ +/* Copyright (c) 2008-2012, 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 "codegen/x86/block.h" +#include "common.h" + +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + +namespace avian { +namespace codegen { +namespace x86 { + +unsigned +padding(AlignmentPadding* p, unsigned index, unsigned offset, AlignmentPadding* limit); + +MyBlock::MyBlock(unsigned offset): + next(0), firstPadding(0), lastPadding(0), offset(offset), start(~0), + size(0) +{ } + +unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) { + this->start = start; + this->next = static_cast(next); + + return start + size + padding(firstPadding, start, offset, lastPadding); +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/block.h b/src/codegen/x86/block.h new file mode 100644 index 0000000000..76f7ff05a6 --- /dev/null +++ b/src/codegen/x86/block.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H + +#include "codegen/assembler.h" + +namespace avian { +namespace codegen { +namespace x86 { + +class AlignmentPadding; + +class MyBlock: public Assembler::Block { + public: + MyBlock(unsigned offset); + + virtual unsigned resolve(unsigned start, Assembler::Block* next); + + MyBlock* next; + AlignmentPadding* firstPadding; + AlignmentPadding* lastPadding; + unsigned offset; + unsigned start; + unsigned size; +}; + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H diff --git a/src/codegen/x86/context.cpp b/src/codegen/x86/context.cpp new file mode 100644 index 0000000000..da73e97606 --- /dev/null +++ b/src/codegen/x86/context.cpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2008-2012, 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 "codegen/x86/context.h" +#include "codegen/x86/block.h" + +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + +namespace avian { +namespace codegen { +namespace x86 { + +ArchitectureContext::ArchitectureContext(vm::System* s, bool useNativeFeatures): + s(s), useNativeFeatures(useNativeFeatures) +{ } + +Context::Context(vm::System* s, vm::Allocator* a, vm::Zone* zone, ArchitectureContext* ac): + s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), + firstBlock(new(zone) MyBlock(0)), + lastBlock(firstBlock), ac(ac) +{ } + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/context.h b/src/codegen/x86/context.h new file mode 100644 index 0000000000..5b3a915b9c --- /dev/null +++ b/src/codegen/x86/context.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H + +#include "codegen/lir.h" +#include "codegen/assembler.h" +#include "alloc-vector.h" + +class Aborter; + +namespace vm { +class System; +class Allocator; +class Zone; +} // namespace vm + +namespace avian { +namespace codegen { +namespace x86 { + +class Context; +class MyBlock; +class Task; + +typedef void (*OperationType)(Context*); + +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); + +typedef void (*BinaryOperationType) +(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); + +typedef void (*BranchOperationType) +(Context*, lir::TernaryOperation, unsigned, lir::Operand*, + lir::Operand*, lir::Operand*); + +class ArchitectureContext { + public: + ArchitectureContext(vm::System* s, bool useNativeFeatures); + + vm::System* s; + bool useNativeFeatures; + OperationType operations[lir::OperationCount]; + UnaryOperationType unaryOperations[lir::UnaryOperationCount + * lir::OperandTypeCount]; + BinaryOperationType binaryOperations + [(lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::OperandTypeCount + * lir::OperandTypeCount]; + BranchOperationType branchOperations + [lir::BranchOperationCount + * lir::OperandTypeCount + * lir::OperandTypeCount]; +}; + +class Context { + public: + Context(vm::System* s, vm::Allocator* a, vm::Zone* zone, ArchitectureContext* ac); + + vm::System* s; + vm::Zone* zone; + Assembler::Client* client; + vm::Vector code; + Task* tasks; + uint8_t* result; + MyBlock* firstBlock; + MyBlock* lastBlock; + ArchitectureContext* ac; +}; + +inline Aborter* getAborter(Context* c) { + return c->s; +} + +inline Aborter* getAborter(ArchitectureContext* c) { + return c->s; +} + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H diff --git a/src/codegen/x86/fixup.cpp b/src/codegen/x86/fixup.cpp new file mode 100644 index 0000000000..f739e1b3e4 --- /dev/null +++ b/src/codegen/x86/fixup.cpp @@ -0,0 +1,106 @@ +/* Copyright (c) 2008-2012, 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 "codegen/assembler.h" +#include "codegen/x86/context.h" +#include "codegen/x86/fixup.h" +#include "codegen/x86/padding.h" +#include "codegen/x86/block.h" + +namespace avian { +namespace codegen { +namespace x86 { + +ResolvedPromise* resolvedPromise(Context* c, int64_t value) { + return new(c->zone) ResolvedPromise(value); +} + +Offset::Offset(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit): + c(c), block(block), offset(offset), limit(limit), value_(-1) +{ } + +bool Offset::resolved() { + return block->start != static_cast(~0); +} + +int64_t Offset::value() { + assert(c, resolved()); + + if (value_ == -1) { + value_ = block->start + (offset - block->offset) + + padding(block->firstPadding, block->start, block->offset, limit); + } + + return value_; +} +Promise* offsetPromise(Context* c) { + return new(c->zone) Offset(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); +} + +void* +resolveOffset(vm::System* s, uint8_t* instruction, unsigned instructionSize, + int64_t value) +{ + intptr_t v = reinterpret_cast(value) + - instruction - instructionSize; + + expect(s, vm::fitsInInt32(v)); + + int32_t v4 = v; + memcpy(instruction + instructionSize - 4, &v4, 4); + return instruction + instructionSize; +} + +OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction, + unsigned instructionSize): + s(s), + instruction(instruction), + instructionSize(instructionSize) +{ } + +bool OffsetListener::resolve(int64_t value, void** location) { + void* p = resolveOffset(s, instruction, instructionSize, value); + if (location) *location = p; + return false; +} + +OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, + unsigned instructionSize): + Task(next), + promise(promise), + instructionOffset(instructionOffset), + instructionSize(instructionSize) +{ } + +void OffsetTask::run(Context* c) { + if (promise->resolved()) { + resolveOffset + (c->s, c->result + instructionOffset->value(), instructionSize, + promise->value()); + } else { + new (promise->listen(sizeof(OffsetListener))) + OffsetListener(c->s, c->result + instructionOffset->value(), + instructionSize); + } +} + +void +appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, + unsigned instructionSize) +{ + OffsetTask* task = + new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, instructionSize); + + c->tasks = task; +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/fixup.h b/src/codegen/x86/fixup.h new file mode 100644 index 0000000000..2b97af9cfb --- /dev/null +++ b/src/codegen/x86/fixup.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H + +namespace vm { +class System; +} + +namespace avian { +namespace codegen { + +class Promise; + +namespace x86 { + +class MyBlock; +class AlignmentPadding; + +ResolvedPromise* resolvedPromise(Context* c, int64_t value); + +class Offset: public Promise { + public: + Offset(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit); + + virtual bool resolved(); + + virtual int64_t value(); + + Context* c; + MyBlock* block; + unsigned offset; + AlignmentPadding* limit; + int value_; +}; + +Promise* offsetPromise(Context* c); + + +class Task { + public: + Task(Task* next): next(next) { } + + virtual void run(Context* c) = 0; + + Task* next; +}; + +void* resolveOffset(vm::System* s, uint8_t* instruction, unsigned instructionSize, int64_t value); + +class OffsetListener: public Promise::Listener { + public: + OffsetListener(vm::System* s, uint8_t* instruction, unsigned instructionSize); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + uint8_t* instruction; + unsigned instructionSize; +}; + +class OffsetTask: public Task { + public: + OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, unsigned instructionSize); + + virtual void run(Context* c); + + Promise* promise; + Promise* instructionOffset; + unsigned instructionSize; +}; + +void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, unsigned instructionSize); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H diff --git a/src/codegen/x86/padding.cpp b/src/codegen/x86/padding.cpp new file mode 100644 index 0000000000..355c30e041 --- /dev/null +++ b/src/codegen/x86/padding.cpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2008-2012, 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 "codegen/assembler.h" +#include "codegen/x86/context.h" +#include "codegen/x86/fixup.h" +#include "codegen/x86/padding.h" +#include "codegen/x86/block.h" + +namespace avian { +namespace codegen { +namespace x86 { + +AlignmentPadding::AlignmentPadding(Context* c, unsigned instructionOffset, unsigned alignment): + offset(c->code.length()), + instructionOffset(instructionOffset), + alignment(alignment), + next(0), + padding(-1) +{ + if (c->lastBlock->firstPadding) { + c->lastBlock->lastPadding->next = this; + } else { + c->lastBlock->firstPadding = this; + } + c->lastBlock->lastPadding = this; +} + +unsigned +padding(AlignmentPadding* p, unsigned start, unsigned offset, + AlignmentPadding* limit) +{ + unsigned padding = 0; + if (limit) { + if (limit->padding == -1) { + for (; p; p = p->next) { + if (p->padding == -1) { + unsigned index = p->offset - offset; + while ((start + index + padding + p->instructionOffset) + % p->alignment) + { + ++ padding; + } + + p->padding = padding; + + if (p == limit) break; + } else { + padding = p->padding; + } + } + } else { + padding = limit->padding; + } + } + return padding; +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/padding.h b/src/codegen/x86/padding.h new file mode 100644 index 0000000000..32fc358142 --- /dev/null +++ b/src/codegen/x86/padding.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_PADDING_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_PADDING_H + +namespace avian { +namespace codegen { +namespace x86 { + + +class AlignmentPadding { + public: + AlignmentPadding(Context* c, unsigned instructionOffset, unsigned alignment); + + unsigned offset; + unsigned instructionOffset; + unsigned alignment; + AlignmentPadding* next; + int padding; +}; + +unsigned +padding(AlignmentPadding* p, unsigned start, unsigned offset, + AlignmentPadding* limit); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_PADDING_H diff --git a/src/common.h b/src/common.h index 7cf763c4bd..d4334f3733 100644 --- a/src/common.h +++ b/src/common.h @@ -359,6 +359,18 @@ nextPowerOfTwo(unsigned n) return r; } +inline bool fitsInInt8(int64_t v) { + return v == static_cast(v); +} + +inline bool fitsInInt16(int64_t v) { + return v == static_cast(v); +} + +inline bool fitsInInt32(int64_t v) { + return v == static_cast(v); +} + inline unsigned log(unsigned n) { From 984f987e03d884cfbc88afd2b8fc551e6bf179f7 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sat, 16 Feb 2013 21:55:28 -0700 Subject: [PATCH 250/378] further break out x86 assembler --- src/codegen/x86/assembler.cpp | 2320 +------------------------------ src/codegen/x86/block.cpp | 4 - src/codegen/x86/context.cpp | 4 - src/codegen/x86/context.h | 4 + src/codegen/x86/detect.cpp | 40 + src/codegen/x86/detect.h | 28 + src/codegen/x86/encode.cpp | 345 +++++ src/codegen/x86/encode.h | 93 ++ src/codegen/x86/fixup.cpp | 56 + src/codegen/x86/fixup.h | 31 + src/codegen/x86/multimethod.cpp | 174 +++ src/codegen/x86/multimethod.h | 38 + src/codegen/x86/operations.cpp | 1532 ++++++++++++++++++++ src/codegen/x86/operations.h | 261 ++++ src/codegen/x86/registers.h | 67 + 15 files changed, 2674 insertions(+), 2323 deletions(-) create mode 100644 src/codegen/x86/detect.cpp create mode 100644 src/codegen/x86/detect.h create mode 100644 src/codegen/x86/encode.cpp create mode 100644 src/codegen/x86/encode.h create mode 100644 src/codegen/x86/multimethod.cpp create mode 100644 src/codegen/x86/multimethod.h create mode 100644 src/codegen/x86/operations.cpp create mode 100644 src/codegen/x86/operations.h create mode 100644 src/codegen/x86/registers.h diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index c455f3e963..b52e1ea4ee 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -19,6 +19,11 @@ #include "codegen/x86/block.h" #include "codegen/x86/fixup.h" #include "codegen/x86/padding.h" +#include "codegen/x86/registers.h" +#include "codegen/x86/encode.h" +#include "codegen/x86/operations.h" +#include "codegen/x86/detect.h" +#include "codegen/x86/multimethod.h" #include "util/runtime-array.h" #include "util/abort.h" @@ -33,2210 +38,13 @@ namespace avian { namespace codegen { namespace x86 { -enum { - rax = 0, - rcx = 1, - rdx = 2, - rbx = 3, - rsp = 4, - rbp = 5, - rsi = 6, - rdi = 7, - r8 = 8, - r9 = 9, - r10 = 10, - r11 = 11, - r12 = 12, - r13 = 13, - r14 = 14, - r15 = 15, -}; - -enum { - xmm0 = r15 + 1, - xmm1, - xmm2, - xmm3, - xmm4, - xmm5, - xmm6, - xmm7, - xmm8, - xmm9, - xmm10, - xmm11, - xmm12, - xmm13, - xmm14, - xmm15, -}; - -const unsigned GeneralRegisterMask -= TargetBytesPerWord == 4 ? 0x000000ff : 0x0000ffff; - -const unsigned FloatRegisterMask -= TargetBytesPerWord == 4 ? 0x00ff0000 : 0xffff0000; - const RegisterFile MyRegisterFile(GeneralRegisterMask, FloatRegisterMask); const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1); -const int LongJumpRegister = r10; - const unsigned StackAlignmentInBytes = 16; const unsigned StackAlignmentInWords = StackAlignmentInBytes / TargetBytesPerWord; -class Task; -class AlignmentPadding; - -unsigned -padding(AlignmentPadding* p, unsigned index, unsigned offset, - AlignmentPadding* limit); - -void -copy(System* s, void* dst, int64_t src, unsigned size) -{ - switch (size) { - case 4: { - int32_t v = src; - memcpy(dst, &v, 4); - } break; - - case 8: { - int64_t v = src; - memcpy(dst, &v, 8); - } break; - - default: abort(s); - } -} - -class ImmediateListener: public Promise::Listener { - public: - ImmediateListener(System* s, void* dst, unsigned size, unsigned offset): - s(s), dst(dst), size(size), offset(offset) - { } - - virtual bool resolve(int64_t value, void** location) { - copy(s, dst, value, size); - if (location) *location = static_cast(dst) + offset; - return offset == 0; - } - - System* s; - void* dst; - unsigned size; - unsigned offset; -}; - -class ImmediateTask: public Task { - public: - ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, - unsigned promiseOffset): - Task(next), - promise(promise), - offset(offset), - size(size), - promiseOffset(promiseOffset) - { } - - virtual void run(Context* c) { - if (promise->resolved()) { - copy(c->s, c->result + offset->value(), promise->value(), size); - } else { - new (promise->listen(sizeof(ImmediateListener))) ImmediateListener - (c->s, c->result + offset->value(), size, promiseOffset); - } - } - - Promise* promise; - Promise* offset; - unsigned size; - unsigned promiseOffset; -}; - -void -appendImmediateTask(Context* c, Promise* promise, Promise* offset, - unsigned size, unsigned promiseOffset = 0) -{ - c->tasks = new(c->zone) ImmediateTask - (c->tasks, promise, offset, size, promiseOffset); -} - -extern "C" bool -detectFeature(unsigned ecx, unsigned edx); - -bool -useSSE(ArchitectureContext* c) -{ - if (TargetBytesPerWord == 8) { - // amd64 implies SSE2 support - return true; - } else if (c->useNativeFeatures) { - static int supported = -1; - if (supported == -1) { - supported = detectFeature(0, 0x2000000) // SSE 1 - and detectFeature(0, 0x4000000); // SSE 2 - } - return supported; - } else { - return false; - } -} - -#define REX_W 0x48 -#define REX_R 0x44 -#define REX_X 0x42 -#define REX_B 0x41 -#define REX_NONE 0x40 - -void maybeRex(Context* c, unsigned size, int a, int index, int base, - bool always) -{ - if (TargetBytesPerWord == 8) { - uint8_t byte; - if (size == 8) { - byte = REX_W; - } else { - byte = REX_NONE; - } - if (a != lir::NoRegister and (a & 8)) byte |= REX_R; - if (index != lir::NoRegister and (index & 8)) byte |= REX_X; - if (base != lir::NoRegister and (base & 8)) byte |= REX_B; - if (always or byte != REX_NONE) c->code.append(byte); - } -} - -void -maybeRex(Context* c, unsigned size, lir::Register* a, - lir::Register* b) -{ - maybeRex(c, size, a->low, lir::NoRegister, b->low, false); -} - -void -alwaysRex(Context* c, unsigned size, lir::Register* a, - lir::Register* b) -{ - maybeRex(c, size, a->low, lir::NoRegister, b->low, true); -} - -void -maybeRex(Context* c, unsigned size, lir::Register* a) -{ - maybeRex(c, size, lir::NoRegister, lir::NoRegister, a->low, false); -} - -void -maybeRex(Context* c, unsigned size, lir::Register* a, - lir::Memory* b) -{ - maybeRex(c, size, a->low, b->index, b->base, size == 1 and (a->low & 4)); -} - -void -maybeRex(Context* c, unsigned size, lir::Memory* a) -{ - maybeRex(c, size, lir::NoRegister, a->index, a->base, false); -} - -int -regCode(int a) -{ - return a & 7; -} - -int -regCode(lir::Register* a) -{ - return regCode(a->low); -} - -void -modrm(Context* c, uint8_t mod, int a, int b) -{ - c->code.append(mod | (regCode(b) << 3) | regCode(a)); -} - -void -modrm(Context* c, uint8_t mod, lir::Register* a, lir::Register* b) -{ - modrm(c, mod, a->low, b->low); -} - -void -sib(Context* c, unsigned scale, int index, int base) -{ - c->code.append((log(scale) << 6) | (regCode(index) << 3) | regCode(base)); -} - -void -modrmSib(Context* c, int width, int a, int scale, int index, int base) -{ - if (index == lir::NoRegister) { - modrm(c, width, base, a); - if (regCode(base) == rsp) { - sib(c, 0x00, rsp, rsp); - } - } else { - modrm(c, width, rsp, a); - sib(c, scale, index, base); - } -} - -void -modrmSibImm(Context* c, int a, int scale, int index, int base, int offset) -{ - if (offset == 0 and regCode(base) != rbp) { - modrmSib(c, 0x00, a, scale, index, base); - } else if (vm::fitsInInt8(offset)) { - modrmSib(c, 0x40, a, scale, index, base); - c->code.append(offset); - } else { - modrmSib(c, 0x80, a, scale, index, base); - c->code.append4(offset); - } -} - - -void -modrmSibImm(Context* c, lir::Register* a, lir::Memory* b) -{ - modrmSibImm(c, a->low, b->scale, b->index, b->base, b->offset); -} - -void -opcode(Context* c, uint8_t op) -{ - c->code.append(op); -} - -void -opcode(Context* c, uint8_t op1, uint8_t op2) -{ - c->code.append(op1); - c->code.append(op2); -} - -void -return_(Context* c) -{ - opcode(c, 0xc3); -} - -void -trap(Context* c) -{ - opcode(c, 0xcc); -} - -void -ignore(Context*) -{ } - -void -storeLoadBarrier(Context* c) -{ - if (useSSE(c->ac)) { - // mfence: - c->code.append(0x0f); - c->code.append(0xae); - c->code.append(0xf0); - } else { - // lock addq $0x0,(%rsp): - c->code.append(0xf0); - if (TargetBytesPerWord == 8) { - c->code.append(0x48); - } - c->code.append(0x83); - c->code.append(0x04); - c->code.append(0x24); - c->code.append(0x00); - } -} - -void -unconditional(Context* c, unsigned jump, lir::Constant* a) -{ - appendOffsetTask(c, a->value, offsetPromise(c), 5); - - opcode(c, jump); - c->code.append4(0); -} - -void -conditional(Context* c, unsigned condition, lir::Constant* a) -{ - appendOffsetTask(c, a->value, offsetPromise(c), 6); - - opcode(c, 0x0f, condition); - c->code.append4(0); -} - -unsigned -index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) -{ - return operation + (lir::UnaryOperationCount * operand); -} - -unsigned -index(ArchitectureContext*, lir::BinaryOperation operation, - lir::OperandType operand1, - lir::OperandType operand2) -{ - return operation - + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) - + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) - * lir::OperandTypeCount * operand2); -} - -unsigned -index(ArchitectureContext* c UNUSED, lir::TernaryOperation operation, - lir::OperandType operand1, lir::OperandType operand2) -{ - assert(c, not isBranch(operation)); - - return lir::BinaryOperationCount + operation - + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) - + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) - * lir::OperandTypeCount * operand2); -} - -unsigned -branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, - lir::OperandType operand2) -{ - return operand1 + (lir::OperandTypeCount * operand2); -} - -void -moveCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b); - -void -moveCR2(Context*, unsigned, lir::Constant*, unsigned, - lir::Register*, unsigned); - -void -callR(Context*, unsigned, lir::Register*); - -void -callC(Context* c, unsigned size UNUSED, lir::Constant* a) -{ - assert(c, size == TargetBytesPerWord); - - unconditional(c, 0xe8, a); -} - -void -longCallC(Context* c, unsigned size, lir::Constant* a) -{ - assert(c, size == TargetBytesPerWord); - - if (TargetBytesPerWord == 8) { - lir::Register r(LongJumpRegister); - moveCR2(c, size, a, size, &r, 11); - callR(c, size, &r); - } else { - callC(c, size, a); - } -} - -void -jumpR(Context* c, unsigned size UNUSED, lir::Register* a) -{ - assert(c, size == TargetBytesPerWord); - - maybeRex(c, 4, a); - opcode(c, 0xff, 0xe0 + regCode(a)); -} - -void -jumpC(Context* c, unsigned size UNUSED, lir::Constant* a) -{ - assert(c, size == TargetBytesPerWord); - - unconditional(c, 0xe9, a); -} - -void -jumpM(Context* c, unsigned size UNUSED, lir::Memory* a) -{ - assert(c, size == TargetBytesPerWord); - - maybeRex(c, 4, a); - opcode(c, 0xff); - modrmSibImm(c, rsp, a->scale, a->index, a->base, a->offset); -} - -void -longJumpC(Context* c, unsigned size, lir::Constant* a) -{ - assert(c, size == TargetBytesPerWord); - - if (TargetBytesPerWord == 8) { - lir::Register r(LongJumpRegister); - moveCR2(c, size, a, size, &r, 11); - jumpR(c, size, &r); - } else { - jumpC(c, size, a); - } -} - -void -callR(Context* c, unsigned size UNUSED, lir::Register* a) -{ - assert(c, size == TargetBytesPerWord); - - // maybeRex.W has no meaning here so we disable it - maybeRex(c, 4, a); - opcode(c, 0xff, 0xd0 + regCode(a)); -} - -void -callM(Context* c, unsigned size UNUSED, lir::Memory* a) -{ - assert(c, size == TargetBytesPerWord); - - maybeRex(c, 4, a); - opcode(c, 0xff); - modrmSibImm(c, rdx, a->scale, a->index, a->base, a->offset); -} - -void -alignedCallC(Context* c, unsigned size, lir::Constant* a) -{ - new(c->zone) AlignmentPadding(c, 1, 4); - callC(c, size, a); -} - -void -alignedLongCallC(Context* c, unsigned size, lir::Constant* a) -{ - assert(c, size == TargetBytesPerWord); - - if (TargetBytesPerWord == 8) { - new (c->zone) AlignmentPadding(c, 2, 8); - longCallC(c, size, a); - } else { - alignedCallC(c, size, a); - } -} - -void -alignedJumpC(Context* c, unsigned size, lir::Constant* a) -{ - new (c->zone) AlignmentPadding(c, 1, 4); - jumpC(c, size, a); -} - -void -alignedLongJumpC(Context* c, unsigned size, lir::Constant* a) -{ - assert(c, size == TargetBytesPerWord); - - if (TargetBytesPerWord == 8) { - new (c->zone) AlignmentPadding(c, 2, 8); - longJumpC(c, size, a); - } else { - alignedJumpC(c, size, a); - } -} - -void -pushR(Context* c, unsigned size, lir::Register* a) -{ - if (TargetBytesPerWord == 4 and size == 8) { - lir::Register ah(a->high); - - pushR(c, 4, &ah); - pushR(c, 4, a); - } else { - maybeRex(c, 4, a); - opcode(c, 0x50 + regCode(a)); - } -} - -void -moveRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b); - -void -popR(Context* c, unsigned size, lir::Register* a) -{ - if (TargetBytesPerWord == 4 and size == 8) { - lir::Register ah(a->high); - - popR(c, 4, a); - popR(c, 4, &ah); - } else { - maybeRex(c, 4, a); - opcode(c, 0x58 + regCode(a)); - if (TargetBytesPerWord == 8 and size == 4) { - moveRR(c, 4, a, 8, a); - } - } -} - -void -addCarryCR(Context* c, unsigned size, lir::Constant* a, - lir::Register* b); - -void -negateR(Context* c, unsigned size, lir::Register* a) -{ - if (TargetBytesPerWord == 4 and size == 8) { - assert(c, a->low == rax and a->high == rdx); - - ResolvedPromise zeroPromise(0); - lir::Constant zero(&zeroPromise); - - lir::Register ah(a->high); - - negateR(c, 4, a); - addCarryCR(c, 4, &zero, &ah); - negateR(c, 4, &ah); - } else { - maybeRex(c, size, a); - opcode(c, 0xf7, 0xd8 + regCode(a)); - } -} - -void -negateRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b UNUSED) -{ - assert(c, aSize == bSize); - - negateR(c, aSize, a); -} - -void -moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, - UNUSED unsigned bSize, lir::Register* b, unsigned promiseOffset) -{ - if (TargetBytesPerWord == 4 and bSize == 8) { - int64_t v = a->value->value(); - - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - - moveCR(c, 4, &al, 4, b); - moveCR(c, 4, &ah, 4, &bh); - } else { - maybeRex(c, TargetBytesPerWord, b); - opcode(c, 0xb8 + regCode(b)); - if (a->value->resolved()) { - c->code.appendTargetAddress(a->value->value()); - } else { - appendImmediateTask - (c, a->value, offsetPromise(c), TargetBytesPerWord, promiseOffset); - c->code.appendTargetAddress(static_cast(0)); - } - } -} - -bool -floatReg(lir::Register* a) -{ - return a->low >= xmm0; -} - -void -sseMoveRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize >= 4); - assert(c, aSize == bSize); - - if (floatReg(a) and floatReg(b)) { - if (aSize == 4) { - opcode(c, 0xf3); - maybeRex(c, 4, a, b); - opcode(c, 0x0f, 0x10); - modrm(c, 0xc0, a, b); - } else { - opcode(c, 0xf2); - maybeRex(c, 4, b, a); - opcode(c, 0x0f, 0x10); - modrm(c, 0xc0, a, b); - } - } else if (floatReg(a)) { - opcode(c, 0x66); - maybeRex(c, aSize, a, b); - opcode(c, 0x0f, 0x7e); - modrm(c, 0xc0, b, a); - } else { - opcode(c, 0x66); - maybeRex(c, aSize, b, a); - opcode(c, 0x0f, 0x6e); - modrm(c, 0xc0, a, b); - } -} - -void -sseMoveCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize <= TargetBytesPerWord); - lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); - moveCR2(c, aSize, a, aSize, &tmp, 0); - sseMoveRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); -} - -void -moveCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - if (floatReg(b)) { - sseMoveCR(c, aSize, a, bSize, b); - } else { - moveCR2(c, aSize, a, bSize, b, 0); - } -} - -void -swapRR(Context* c, unsigned aSize UNUSED, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - assert(c, aSize == TargetBytesPerWord); - - alwaysRex(c, aSize, a, b); - opcode(c, 0x87); - modrm(c, 0xc0, b, a); -} - -void -moveRR(Context* c, unsigned aSize, lir::Register* a, - UNUSED unsigned bSize, lir::Register* b) -{ - if (floatReg(a) or floatReg(b)) { - sseMoveRR(c, aSize, a, bSize, b); - return; - } - - if (TargetBytesPerWord == 4 and aSize == 8 and bSize == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - if (a->high == b->low) { - if (a->low == b->high) { - swapRR(c, 4, a, 4, b); - } else { - moveRR(c, 4, &ah, 4, &bh); - moveRR(c, 4, a, 4, b); - } - } else { - moveRR(c, 4, a, 4, b); - moveRR(c, 4, &ah, 4, &bh); - } - } else { - switch (aSize) { - case 1: - if (TargetBytesPerWord == 4 and a->low > rbx) { - assert(c, b->low <= rbx); - - moveRR(c, TargetBytesPerWord, a, TargetBytesPerWord, b); - moveRR(c, 1, b, TargetBytesPerWord, b); - } else { - alwaysRex(c, aSize, b, a); - opcode(c, 0x0f, 0xbe); - modrm(c, 0xc0, a, b); - } - break; - - case 2: - alwaysRex(c, aSize, b, a); - opcode(c, 0x0f, 0xbf); - modrm(c, 0xc0, a, b); - break; - - case 4: - if (bSize == 8) { - if (TargetBytesPerWord == 8) { - alwaysRex(c, bSize, b, a); - opcode(c, 0x63); - modrm(c, 0xc0, a, b); - } else { - if (a->low == rax and b->low == rax and b->high == rdx) { - opcode(c, 0x99); //cdq - } else { - assert(c, b->low == rax and b->high == rdx); - - moveRR(c, 4, a, 4, b); - moveRR(c, 4, b, 8, b); - } - } - } else { - if (a->low != b->low) { - alwaysRex(c, aSize, a, b); - opcode(c, 0x89); - modrm(c, 0xc0, b, a); - } - } - break; - - case 8: - if (a->low != b->low){ - maybeRex(c, aSize, a, b); - opcode(c, 0x89); - modrm(c, 0xc0, b, a); - } - break; - } - } -} - -void -sseMoveMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize >= 4); - - if (TargetBytesPerWord == 4 and aSize == 8) { - opcode(c, 0xf3); - opcode(c, 0x0f, 0x7e); - modrmSibImm(c, b, a); - } else { - opcode(c, 0x66); - maybeRex(c, aSize, b, a); - opcode(c, 0x0f, 0x6e); - modrmSibImm(c, b, a); - } -} - -void -moveMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize, lir::Register* b) -{ - if (floatReg(b)) { - sseMoveMR(c, aSize, a, bSize, b); - return; - } - - switch (aSize) { - case 1: - maybeRex(c, bSize, b, a); - opcode(c, 0x0f, 0xbe); - modrmSibImm(c, b, a); - break; - - case 2: - maybeRex(c, bSize, b, a); - opcode(c, 0x0f, 0xbf); - modrmSibImm(c, b, a); - break; - - case 4: - if (TargetBytesPerWord == 8) { - maybeRex(c, bSize, b, a); - opcode(c, 0x63); - modrmSibImm(c, b, a); - } else { - if (bSize == 8) { - assert(c, b->low == rax and b->high == rdx); - - moveMR(c, 4, a, 4, b); - moveRR(c, 4, b, 8, b); - } else { - maybeRex(c, bSize, b, a); - opcode(c, 0x8b); - modrmSibImm(c, b, a); - } - } - break; - - case 8: - if (TargetBytesPerWord == 4 and bSize == 8) { - lir::Memory ah(a->base, a->offset + 4, a->index, a->scale); - lir::Register bh(b->high); - - moveMR(c, 4, a, 4, b); - moveMR(c, 4, &ah, 4, &bh); - } else { - maybeRex(c, bSize, b, a); - opcode(c, 0x8b); - modrmSibImm(c, b, a); - } - break; - - default: abort(c); - } -} - -void -sseMoveRM(Context* c, unsigned aSize, lir::Register* a, - UNUSED unsigned bSize, lir::Memory* b) -{ - assert(c, aSize >= 4); - assert(c, aSize == bSize); - - if (TargetBytesPerWord == 4 and aSize == 8) { - opcode(c, 0x66); - opcode(c, 0x0f, 0xd6); - modrmSibImm(c, a, b); - } else { - opcode(c, 0x66); - maybeRex(c, aSize, a, b); - opcode(c, 0x0f, 0x7e); - modrmSibImm(c, a, b); - } -} - -void -moveRM(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Memory* b) -{ - assert(c, aSize == bSize); - - if (floatReg(a)) { - sseMoveRM(c, aSize, a, bSize, b); - return; - } - - switch (aSize) { - case 1: - maybeRex(c, bSize, a, b); - opcode(c, 0x88); - modrmSibImm(c, a, b); - break; - - case 2: - opcode(c, 0x66); - maybeRex(c, bSize, a, b); - opcode(c, 0x89); - modrmSibImm(c, a, b); - break; - - case 4: - if (TargetBytesPerWord == 8) { - maybeRex(c, bSize, a, b); - opcode(c, 0x89); - modrmSibImm(c, a, b); - break; - } else { - opcode(c, 0x89); - modrmSibImm(c, a, b); - } - break; - - case 8: - if (TargetBytesPerWord == 8) { - maybeRex(c, bSize, a, b); - opcode(c, 0x89); - modrmSibImm(c, a, b); - } else { - lir::Register ah(a->high); - lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - moveRM(c, 4, a, 4, b); - moveRM(c, 4, &ah, 4, &bh); - } - break; - - default: abort(c); - } -} - -void -moveAR(Context* c, unsigned aSize, lir::Address* a, - unsigned bSize, lir::Register* b) -{ - assert(c, TargetBytesPerWord == 8 or (aSize == 4 and bSize == 4)); - - lir::Constant constant(a->address); - lir::Memory memory(b->low, 0, -1, 0); - - moveCR(c, aSize, &constant, bSize, b); - moveMR(c, bSize, &memory, bSize, b); -} - -ShiftMaskPromise* -shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) -{ - return new(c->zone) ShiftMaskPromise(base, shift, mask); -} - -void -moveCM(Context* c, unsigned aSize UNUSED, lir::Constant* a, - unsigned bSize, lir::Memory* b) -{ - switch (bSize) { - case 1: - maybeRex(c, bSize, b); - opcode(c, 0xc6); - modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); - c->code.append(a->value->value()); - break; - - case 2: - opcode(c, 0x66); - maybeRex(c, bSize, b); - opcode(c, 0xc7); - modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); - c->code.append2(a->value->value()); - break; - - case 4: - maybeRex(c, bSize, b); - opcode(c, 0xc7); - modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); - if (a->value->resolved()) { - c->code.append4(a->value->value()); - } else { - appendImmediateTask(c, a->value, offsetPromise(c), 4); - c->code.append4(0); - } - break; - - case 8: { - if (TargetBytesPerWord == 8) { - if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { - maybeRex(c, bSize, b); - opcode(c, 0xc7); - modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); - c->code.append4(a->value->value()); - } else { - lir::Register tmp - (c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, 8, a, 8, &tmp); - moveRM(c, 8, &tmp, 8, b); - c->client->releaseTemporary(tmp.low); - } - } else { - lir::Constant ah(shiftMaskPromise(c, a->value, 32, 0xFFFFFFFF)); - lir::Constant al(shiftMaskPromise(c, a->value, 0, 0xFFFFFFFF)); - - lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - moveCM(c, 4, &al, 4, b); - moveCM(c, 4, &ah, 4, &bh); - } - } break; - - default: abort(c); - } -} - -void -moveZRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - switch (aSize) { - case 2: - alwaysRex(c, aSize, b, a); - opcode(c, 0x0f, 0xb7); - modrm(c, 0xc0, a, b); - break; - - default: abort(c); - } -} - -void -moveZMR(Context* c, unsigned aSize UNUSED, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, bSize == TargetBytesPerWord); - assert(c, aSize == 2); - - maybeRex(c, bSize, b, a); - opcode(c, 0x0f, 0xb7); - modrmSibImm(c, b->low, a->scale, a->index, a->base, a->offset); -} - -void -addCarryRR(Context* c, unsigned size, lir::Register* a, - lir::Register* b) -{ - assert(c, TargetBytesPerWord == 8 or size == 4); - - maybeRex(c, size, a, b); - opcode(c, 0x11); - modrm(c, 0xc0, b, a); -} - -void -addRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - - if (TargetBytesPerWord == 4 and aSize == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - addRR(c, 4, a, 4, b); - addCarryRR(c, 4, &ah, &bh); - } else { - maybeRex(c, aSize, a, b); - opcode(c, 0x01); - modrm(c, 0xc0, b, a); - } -} - -void -addCarryCR(Context* c, unsigned size, lir::Constant* a, - lir::Register* b) -{ - - int64_t v = a->value->value(); - maybeRex(c, size, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xd0 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xd0 + regCode(b)); - c->code.append4(v); - } -} - -void -addCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == bSize); - - int64_t v = a->value->value(); - if (v) { - if (TargetBytesPerWord == 4 and bSize == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - - addCR(c, 4, &al, 4, b); - addCarryCR(c, 4, &ah, &bh); - } else { - if (vm::fitsInInt32(v)) { - maybeRex(c, aSize, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xc0 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xc0 + regCode(b)); - c->code.append4(v); - } - } else { - lir::Register tmp - (c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, aSize, &tmp); - addRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } - } - } -} - -void -subtractBorrowCR(Context* c, unsigned size UNUSED, lir::Constant* a, - lir::Register* b) -{ - assert(c, TargetBytesPerWord == 8 or size == 4); - - int64_t v = a->value->value(); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xd8 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xd8 + regCode(b)); - c->code.append4(v); - } -} - -void -subtractRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b); - -void -subtractCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == bSize); - - int64_t v = a->value->value(); - if (v) { - if (TargetBytesPerWord == 4 and bSize == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - - subtractCR(c, 4, &al, 4, b); - subtractBorrowCR(c, 4, &ah, &bh); - } else { - if (vm::fitsInInt32(v)) { - maybeRex(c, aSize, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xe8 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xe8 + regCode(b)); - c->code.append4(v); - } - } else { - lir::Register tmp - (c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, aSize, &tmp); - subtractRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } - } - } -} - -void -subtractBorrowRR(Context* c, unsigned size, lir::Register* a, - lir::Register* b) -{ - assert(c, TargetBytesPerWord == 8 or size == 4); - - maybeRex(c, size, a, b); - opcode(c, 0x19); - modrm(c, 0xc0, b, a); -} - -void -subtractRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - - if (TargetBytesPerWord == 4 and aSize == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - subtractRR(c, 4, a, 4, b); - subtractBorrowRR(c, 4, &ah, &bh); - } else { - maybeRex(c, aSize, a, b); - opcode(c, 0x29); - modrm(c, 0xc0, b, a); - } -} - -void -andRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - - - if (TargetBytesPerWord == 4 and aSize == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - andRR(c, 4, a, 4, b); - andRR(c, 4, &ah, 4, &bh); - } else { - maybeRex(c, aSize, a, b); - opcode(c, 0x21); - modrm(c, 0xc0, b, a); - } -} - -void -andCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == bSize); - - int64_t v = a->value->value(); - - if (TargetBytesPerWord == 4 and bSize == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - - andCR(c, 4, &al, 4, b); - andCR(c, 4, &ah, 4, &bh); - } else { - if (vm::fitsInInt32(v)) { - maybeRex(c, aSize, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xe0 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xe0 + regCode(b)); - c->code.append4(v); - } - } else { - lir::Register tmp - (c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, aSize, &tmp); - andRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } - } -} - -void -orRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - - if (TargetBytesPerWord == 4 and aSize == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - orRR(c, 4, a, 4, b); - orRR(c, 4, &ah, 4, &bh); - } else { - maybeRex(c, aSize, a, b); - opcode(c, 0x09); - modrm(c, 0xc0, b, a); - } -} - -void -orCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == bSize); - - int64_t v = a->value->value(); - if (v) { - if (TargetBytesPerWord == 4 and bSize == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - - orCR(c, 4, &al, 4, b); - orCR(c, 4, &ah, 4, &bh); - } else { - if (vm::fitsInInt32(v)) { - maybeRex(c, aSize, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xc8 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xc8 + regCode(b)); - c->code.append4(v); - } - } else { - lir::Register tmp - (c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, aSize, &tmp); - orRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } - } - } -} - -void -xorRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - if (TargetBytesPerWord == 4 and aSize == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - xorRR(c, 4, a, 4, b); - xorRR(c, 4, &ah, 4, &bh); - } else { - maybeRex(c, aSize, a, b); - opcode(c, 0x31); - modrm(c, 0xc0, b, a); - } -} - -void -xorCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == bSize); - - int64_t v = a->value->value(); - if (v) { - if (TargetBytesPerWord == 4 and bSize == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - - xorCR(c, 4, &al, 4, b); - xorCR(c, 4, &ah, 4, &bh); - } else { - if (vm::fitsInInt32(v)) { - maybeRex(c, aSize, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xf0 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xf0 + regCode(b)); - c->code.append4(v); - } - } else { - lir::Register tmp - (c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, aSize, &tmp); - xorRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } - } - } -} - -void -multiplyRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - - - if (TargetBytesPerWord == 4 and aSize == 8) { - assert(c, b->high == rdx); - assert(c, b->low != rax); - assert(c, a->low != rax); - assert(c, a->high != rax); - - c->client->save(rax); - - lir::Register axdx(rax, rdx); - lir::Register ah(a->high); - lir::Register bh(b->high); - - lir::Register tmp(-1); - lir::Register* scratch; - if (a->low == b->low) { - tmp.low = c->client->acquireTemporary - (GeneralRegisterMask & ~(1 << rax)); - scratch = &tmp; - moveRR(c, 4, b, 4, scratch); - } else { - scratch = b; - } - - moveRR(c, 4, b, 4, &axdx); - multiplyRR(c, 4, &ah, 4, scratch); - multiplyRR(c, 4, a, 4, &bh); - addRR(c, 4, &bh, 4, scratch); - - // mul a->low,%eax%edx - opcode(c, 0xf7, 0xe0 + a->low); - - addRR(c, 4, scratch, 4, &bh); - moveRR(c, 4, &axdx, 4, b); - - if (tmp.low != -1) { - c->client->releaseTemporary(tmp.low); - } - } else { - maybeRex(c, aSize, b, a); - opcode(c, 0x0f, 0xaf); - modrm(c, 0xc0, a, b); - } -} - -void -branch(Context* c, lir::TernaryOperation op, lir::Constant* target) -{ - switch (op) { - case lir::JumpIfEqual: - conditional(c, 0x84, target); - break; - - case lir::JumpIfNotEqual: - conditional(c, 0x85, target); - break; - - case lir::JumpIfLess: - conditional(c, 0x8c, target); - break; - - case lir::JumpIfGreater: - conditional(c, 0x8f, target); - break; - - case lir::JumpIfLessOrEqual: - conditional(c, 0x8e, target); - break; - - case lir::JumpIfGreaterOrEqual: - conditional(c, 0x8d, target); - break; - - default: - abort(c); - } -} - -void -branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) -{ - switch (op) { - case lir::JumpIfFloatEqual: - conditional(c, 0x84, target); - break; - - case lir::JumpIfFloatNotEqual: - conditional(c, 0x85, target); - break; - - case lir::JumpIfFloatLess: - conditional(c, 0x82, target); - break; - - case lir::JumpIfFloatGreater: - conditional(c, 0x87, target); - break; - - case lir::JumpIfFloatLessOrEqual: - conditional(c, 0x86, target); - break; - - case lir::JumpIfFloatGreaterOrEqual: - conditional(c, 0x83, target); - break; - - case lir::JumpIfFloatLessOrUnordered: - conditional(c, 0x82, target); - conditional(c, 0x8a, target); - break; - - case lir::JumpIfFloatGreaterOrUnordered: - conditional(c, 0x87, target); - conditional(c, 0x8a, target); - break; - - case lir::JumpIfFloatLessOrEqualOrUnordered: - conditional(c, 0x86, target); - conditional(c, 0x8a, target); - break; - - case lir::JumpIfFloatGreaterOrEqualOrUnordered: - conditional(c, 0x83, target); - conditional(c, 0x8a, target); - break; - - default: - abort(c); - } -} - -void -compareRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - assert(c, aSize <= TargetBytesPerWord); - - maybeRex(c, aSize, a, b); - opcode(c, 0x39); - modrm(c, 0xc0, b, a); -} - -void -compareCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == bSize); - assert(c, TargetBytesPerWord == 8 or aSize == 4); - - if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { - int64_t v = a->value->value(); - maybeRex(c, aSize, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x83, 0xf8 + regCode(b)); - c->code.append(v); - } else { - opcode(c, 0x81, 0xf8 + regCode(b)); - c->code.append4(v); - } - } else { - lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, aSize, &tmp); - compareRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } -} - -void -compareRM(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Memory* b) -{ - assert(c, aSize == bSize); - assert(c, TargetBytesPerWord == 8 or aSize == 4); - - if (TargetBytesPerWord == 8 and aSize == 4) { - moveRR(c, 4, a, 8, a); - } - maybeRex(c, bSize, a, b); - opcode(c, 0x39); - modrmSibImm(c, a, b); -} - -void -compareCM(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Memory* b) -{ - assert(c, aSize == bSize); - assert(c, TargetBytesPerWord == 8 or aSize == 4); - - if (a->value->resolved()) { - int64_t v = a->value->value(); - maybeRex(c, aSize, b); - opcode(c, vm::fitsInInt8(v) ? 0x83 : 0x81); - modrmSibImm(c, rdi, b->scale, b->index, b->base, b->offset); - - if (vm::fitsInInt8(v)) { - c->code.append(v); - } else if (vm::fitsInInt32(v)) { - c->code.append4(v); - } else { - abort(c); - } - } else { - lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, bSize, &tmp); - compareRM(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } -} - -void -compareFloatRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - - if (aSize == 8) { - opcode(c, 0x66); - } - maybeRex(c, 4, a, b); - opcode(c, 0x0f, 0x2e); - modrm(c, 0xc0, a, b); -} - -void -branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, - lir::Operand* ah, lir::Operand* bl, - lir::Operand* bh, lir::Constant* target, - BinaryOperationType compare) -{ - compare(c, 4, ah, 4, bh); - - unsigned next = 0; - - switch (op) { - case lir::JumpIfEqual: - opcode(c, 0x75); // jne - next = c->code.length(); - c->code.append(0); - - compare(c, 4, al, 4, bl); - conditional(c, 0x84, target); // je - break; - - case lir::JumpIfNotEqual: - conditional(c, 0x85, target); // jne - - compare(c, 4, al, 4, bl); - conditional(c, 0x85, target); // jne - break; - - case lir::JumpIfLess: - conditional(c, 0x8c, target); // jl - - opcode(c, 0x7f); // jg - next = c->code.length(); - c->code.append(0); - - compare(c, 4, al, 4, bl); - conditional(c, 0x82, target); // jb - break; - - case lir::JumpIfGreater: - conditional(c, 0x8f, target); // jg - - opcode(c, 0x7c); // jl - next = c->code.length(); - c->code.append(0); - - compare(c, 4, al, 4, bl); - conditional(c, 0x87, target); // ja - break; - - case lir::JumpIfLessOrEqual: - conditional(c, 0x8c, target); // jl - - opcode(c, 0x7f); // jg - next = c->code.length(); - c->code.append(0); - - compare(c, 4, al, 4, bl); - conditional(c, 0x86, target); // jbe - break; - - case lir::JumpIfGreaterOrEqual: - conditional(c, 0x8f, target); // jg - - opcode(c, 0x7c); // jl - next = c->code.length(); - c->code.append(0); - - compare(c, 4, al, 4, bl); - conditional(c, 0x83, target); // jae - break; - - default: - abort(c); - } - - if (next) { - int8_t nextOffset = c->code.length() - next - 1; - c->code.set(next, &nextOffset, 1); - } -} - -void -branchRR(Context* c, lir::TernaryOperation op, unsigned size, - lir::Register* a, lir::Register* b, - lir::Constant* target) -{ - if (isFloatBranch(op)) { - compareFloatRR(c, size, a, size, b); - branchFloat(c, op, target); - } else if (size > TargetBytesPerWord) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR)); - } else { - compareRR(c, size, a, size, b); - branch(c, op, target); - } -} - -void -branchCR(Context* c, lir::TernaryOperation op, unsigned size, - lir::Constant* a, lir::Register* b, - lir::Constant* target) -{ - assert(c, not isFloatBranch(op)); - - if (size > TargetBytesPerWord) { - int64_t v = a->value->value(); - - ResolvedPromise low(v & ~static_cast(0)); - lir::Constant al(&low); - - ResolvedPromise high((v >> 32) & ~static_cast(0)); - lir::Constant ah(&high); - - lir::Register bh(b->high); - - branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR)); - } else { - compareCR(c, size, a, size, b); - branch(c, op, target); - } -} - -void -branchRM(Context* c, lir::TernaryOperation op, unsigned size, - lir::Register* a, lir::Memory* b, - lir::Constant* target) -{ - assert(c, not isFloatBranch(op)); - assert(c, size <= TargetBytesPerWord); - - compareRM(c, size, a, size, b); - branch(c, op, target); -} - -void -branchCM(Context* c, lir::TernaryOperation op, unsigned size, - lir::Constant* a, lir::Memory* b, - lir::Constant* target) -{ - assert(c, not isFloatBranch(op)); - assert(c, size <= TargetBytesPerWord); - - compareCM(c, size, a, size, b); - branch(c, op, target); -} - -void -multiplyCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == bSize); - - if (TargetBytesPerWord == 4 and aSize == 8) { - const uint32_t mask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); - lir::Register tmp(c->client->acquireTemporary(mask), - c->client->acquireTemporary(mask)); - - moveCR(c, aSize, a, aSize, &tmp); - multiplyRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - c->client->releaseTemporary(tmp.high); - } else { - int64_t v = a->value->value(); - if (v != 1) { - if (vm::fitsInInt32(v)) { - maybeRex(c, bSize, b, b); - if (vm::fitsInInt8(v)) { - opcode(c, 0x6b); - modrm(c, 0xc0, b, b); - c->code.append(v); - } else { - opcode(c, 0x69); - modrm(c, 0xc0, b, b); - c->code.append4(v); - } - } else { - lir::Register tmp - (c->client->acquireTemporary(GeneralRegisterMask)); - moveCR(c, aSize, a, aSize, &tmp); - multiplyRR(c, aSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } - } - } -} - -void -divideRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b UNUSED) -{ - assert(c, aSize == bSize); - - assert(c, b->low == rax); - assert(c, a->low != rdx); - - c->client->save(rdx); - - maybeRex(c, aSize, a, b); - opcode(c, 0x99); // cdq - maybeRex(c, aSize, b, a); - opcode(c, 0xf7, 0xf8 + regCode(a)); -} - -void -remainderRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == bSize); - - assert(c, b->low == rax); - assert(c, a->low != rdx); - - c->client->save(rdx); - - maybeRex(c, aSize, a, b); - opcode(c, 0x99); // cdq - maybeRex(c, aSize, b, a); - opcode(c, 0xf7, 0xf8 + regCode(a)); - - lir::Register dx(rdx); - moveRR(c, TargetBytesPerWord, &dx, TargetBytesPerWord, b); -} - -void -doShift(Context* c, UNUSED void (*shift) - (Context*, unsigned, lir::Register*, unsigned, - lir::Register*), - int type, UNUSED unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - int64_t v = a->value->value(); - - if (TargetBytesPerWord == 4 and bSize == 8) { - c->client->save(rcx); - - lir::Register cx(rcx); - ResolvedPromise promise(v & 0x3F); - lir::Constant masked(&promise); - moveCR(c, 4, &masked, 4, &cx); - shift(c, aSize, &cx, bSize, b); - } else { - maybeRex(c, bSize, b); - if (v == 1) { - opcode(c, 0xd1, type + regCode(b)); - } else if (vm::fitsInInt8(v)) { - opcode(c, 0xc1, type + regCode(b)); - c->code.append(v); - } else { - abort(c); - } - } -} - -void -shiftLeftRR(Context* c, UNUSED unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b) -{ - if (TargetBytesPerWord == 4 and bSize == 8) { - lir::Register cx(rcx); - if (a->low != rcx) { - c->client->save(rcx); - ResolvedPromise promise(0x3F); - lir::Constant mask(&promise); - moveRR(c, 4, a, 4, &cx); - andCR(c, 4, &mask, 4, &cx); - } - - // shld - opcode(c, 0x0f, 0xa5); - modrm(c, 0xc0, b->high, b->low); - - // shl - opcode(c, 0xd3, 0xe0 + b->low); - - ResolvedPromise promise(32); - lir::Constant constant(&promise); - compareCR(c, aSize, &constant, aSize, &cx); - - opcode(c, 0x7c); //jl - c->code.append(2 + 2); - - lir::Register bh(b->high); - moveRR(c, 4, b, 4, &bh); // 2 bytes - xorRR(c, 4, b, 4, b); // 2 bytes - } else { - assert(c, a->low == rcx); - - maybeRex(c, bSize, a, b); - opcode(c, 0xd3, 0xe0 + regCode(b)); - } -} - -void -shiftLeftCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - doShift(c, shiftLeftRR, 0xe0, aSize, a, bSize, b); -} - -void -shiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b) -{ - if (TargetBytesPerWord == 4 and bSize == 8) { - lir::Register cx(rcx); - if (a->low != rcx) { - c->client->save(rcx); - ResolvedPromise promise(0x3F); - lir::Constant mask(&promise); - moveRR(c, 4, a, 4, &cx); - andCR(c, 4, &mask, 4, &cx); - } - - // shrd - opcode(c, 0x0f, 0xad); - modrm(c, 0xc0, b->low, b->high); - - // sar - opcode(c, 0xd3, 0xf8 + b->high); - - ResolvedPromise promise(32); - lir::Constant constant(&promise); - compareCR(c, aSize, &constant, aSize, &cx); - - opcode(c, 0x7c); //jl - c->code.append(2 + 3); - - lir::Register bh(b->high); - moveRR(c, 4, &bh, 4, b); // 2 bytes - - // sar 31,high - opcode(c, 0xc1, 0xf8 + b->high); - c->code.append(31); - } else { - assert(c, a->low == rcx); - - maybeRex(c, bSize, a, b); - opcode(c, 0xd3, 0xf8 + regCode(b)); - } -} - -void -shiftRightCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - doShift(c, shiftRightRR, 0xf8, aSize, a, bSize, b); -} - -void -unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b) -{ - if (TargetBytesPerWord == 4 and bSize == 8) { - lir::Register cx(rcx); - if (a->low != rcx) { - c->client->save(rcx); - ResolvedPromise promise(0x3F); - lir::Constant mask(&promise); - moveRR(c, 4, a, 4, &cx); - andCR(c, 4, &mask, 4, &cx); - } - - // shrd - opcode(c, 0x0f, 0xad); - modrm(c, 0xc0, b->low, b->high); - - // shr - opcode(c, 0xd3, 0xe8 + b->high); - - ResolvedPromise promise(32); - lir::Constant constant(&promise); - compareCR(c, aSize, &constant, aSize, &cx); - - opcode(c, 0x7c); //jl - c->code.append(2 + 2); - - lir::Register bh(b->high); - moveRR(c, 4, &bh, 4, b); // 2 bytes - xorRR(c, 4, &bh, 4, &bh); // 2 bytes - } else { - assert(c, a->low == rcx); - - maybeRex(c, bSize, a, b); - opcode(c, 0xd3, 0xe8 + regCode(b)); - } -} - -void -unsignedShiftRightCR(Context* c, unsigned aSize UNUSED, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - doShift(c, unsignedShiftRightRR, 0xe8, aSize, a, bSize, b); -} - -void -floatRegOp(Context* c, unsigned aSize, lir::Register* a, unsigned bSize, - lir::Register* b, uint8_t op, uint8_t mod = 0xc0) -{ - if (aSize == 4) { - opcode(c, 0xf3); - } else { - opcode(c, 0xf2); - } - maybeRex(c, bSize, b, a); - opcode(c, 0x0f, op); - modrm(c, mod, a, b); -} - -void -floatMemOp(Context* c, unsigned aSize, lir::Memory* a, unsigned bSize, - lir::Register* b, uint8_t op) -{ - if (aSize == 4) { - opcode(c, 0xf3); - } else { - opcode(c, 0xf2); - } - maybeRex(c, bSize, b, a); - opcode(c, 0x0f, op); - modrmSibImm(c, b, a); -} - -void -floatSqrtRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatRegOp(c, aSize, a, 4, b, 0x51); -} - -void -floatSqrtMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatMemOp(c, aSize, a, 4, b, 0x51); -} - -void -floatAddRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatRegOp(c, aSize, a, 4, b, 0x58); -} - -void -floatAddMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatMemOp(c, aSize, a, 4, b, 0x58); -} - -void -floatSubtractRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatRegOp(c, aSize, a, 4, b, 0x5c); -} - -void -floatSubtractMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatMemOp(c, aSize, a, 4, b, 0x5c); -} - -void -floatMultiplyRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatRegOp(c, aSize, a, 4, b, 0x59); -} - -void -floatMultiplyMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatMemOp(c, aSize, a, 4, b, 0x59); -} - -void -floatDivideRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatRegOp(c, aSize, a, 4, b, 0x5e); -} - -void -floatDivideMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatMemOp(c, aSize, a, 4, b, 0x5e); -} - -void -float2FloatRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatRegOp(c, aSize, a, 4, b, 0x5a); -} - -void -float2FloatMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize UNUSED, lir::Register* b) -{ - floatMemOp(c, aSize, a, 4, b, 0x5a); -} - -void -float2IntRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b) -{ - assert(c, not floatReg(b)); - floatRegOp(c, aSize, a, bSize, b, 0x2c); -} - -void -float2IntMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize, lir::Register* b) -{ - floatMemOp(c, aSize, a, bSize, b, 0x2c); -} - -void -int2FloatRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b) -{ - floatRegOp(c, bSize, a, aSize, b, 0x2a); -} - -void -int2FloatMR(Context* c, unsigned aSize, lir::Memory* a, - unsigned bSize, lir::Register* b) -{ - floatMemOp(c, bSize, a, aSize, b, 0x2a); -} - -void -floatNegateRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, floatReg(a) and floatReg(b)); - // unlike most of the other floating point code, this does NOT - // support doubles: - assert(c, aSize == 4); - ResolvedPromise pcon(0x80000000); - lir::Constant con(&pcon); - if (a->low == b->low) { - lir::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); - moveCR(c, 4, &con, 4, &tmp); - maybeRex(c, 4, a, &tmp); - opcode(c, 0x0f, 0x57); - modrm(c, 0xc0, &tmp, a); - c->client->releaseTemporary(tmp.low); - } else { - moveCR(c, 4, &con, 4, b); - if (aSize == 8) opcode(c, 0x66); - maybeRex(c, 4, a, b); - opcode(c, 0x0f, 0x57); - modrm(c, 0xc0, a, b); - } -} - -void -floatAbsoluteRR(Context* c, unsigned aSize UNUSED, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, floatReg(a) and floatReg(b)); - // unlike most of the other floating point code, this does NOT - // support doubles: - assert(c, aSize == 4); - ResolvedPromise pcon(0x7fffffff); - lir::Constant con(&pcon); - if (a->low == b->low) { - lir::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); - moveCR(c, 4, &con, 4, &tmp); - maybeRex(c, 4, a, &tmp); - opcode(c, 0x0f, 0x54); - modrm(c, 0xc0, &tmp, a); - c->client->releaseTemporary(tmp.low); - } else { - moveCR(c, 4, &con, 4, b); - maybeRex(c, 4, a, b); - opcode(c, 0x0f, 0x54); - modrm(c, 0xc0, a, b); - } -} - -void -absoluteRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b UNUSED) -{ - assert(c, aSize == bSize and a->low == rax and b->low == rax); - lir::Register d - (c->client->acquireTemporary(static_cast(1) << rdx)); - maybeRex(c, aSize, a, b); - opcode(c, 0x99); - xorRR(c, aSize, &d, aSize, a); - subtractRR(c, aSize, &d, aSize, a); - c->client->releaseTemporary(rdx); -} - unsigned argumentFootprint(unsigned footprint) { @@ -2327,124 +135,6 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, *stack = static_cast(*stack) + offset; } -void -populateTables(ArchitectureContext* c) -{ - const lir::OperandType C = lir::ConstantOperand; - const lir::OperandType A = lir::AddressOperand; - const lir::OperandType R = lir::RegisterOperand; - const lir::OperandType M = lir::MemoryOperand; - - OperationType* zo = c->operations; - UnaryOperationType* uo = c->unaryOperations; - BinaryOperationType* bo = c->binaryOperations; - BranchOperationType* bro = c->branchOperations; - - zo[lir::Return] = return_; - zo[lir::LoadBarrier] = ignore; - zo[lir::StoreStoreBarrier] = ignore; - zo[lir::StoreLoadBarrier] = storeLoadBarrier; - zo[lir::Trap] = trap; - - uo[index(c, lir::Call, C)] = CAST1(callC); - uo[index(c, lir::Call, R)] = CAST1(callR); - uo[index(c, lir::Call, M)] = CAST1(callM); - - uo[index(c, lir::AlignedCall, C)] = CAST1(alignedCallC); - - uo[index(c, lir::LongCall, C)] = CAST1(longCallC); - - uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); - - uo[index(c, lir::Jump, R)] = CAST1(jumpR); - uo[index(c, lir::Jump, C)] = CAST1(jumpC); - uo[index(c, lir::Jump, M)] = CAST1(jumpM); - - uo[index(c, lir::AlignedJump, C)] = CAST1(alignedJumpC); - - uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); - - uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); - - bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); - - bo[index(c, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); - - bo[index(c, lir::Move, R, R)] = CAST2(moveRR); - bo[index(c, lir::Move, C, R)] = CAST2(moveCR); - bo[index(c, lir::Move, M, R)] = CAST2(moveMR); - bo[index(c, lir::Move, R, M)] = CAST2(moveRM); - bo[index(c, lir::Move, C, M)] = CAST2(moveCM); - bo[index(c, lir::Move, A, R)] = CAST2(moveAR); - - bo[index(c, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); - bo[index(c, lir::FloatSquareRoot, M, R)] = CAST2(floatSqrtMR); - - bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); - bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); - bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR); - - bo[index(c, lir::Add, R, R)] = CAST2(addRR); - bo[index(c, lir::Add, C, R)] = CAST2(addCR); - - bo[index(c, lir::Subtract, C, R)] = CAST2(subtractCR); - bo[index(c, lir::Subtract, R, R)] = CAST2(subtractRR); - - bo[index(c, lir::FloatAdd, R, R)] = CAST2(floatAddRR); - bo[index(c, lir::FloatAdd, M, R)] = CAST2(floatAddMR); - - bo[index(c, lir::FloatSubtract, R, R)] = CAST2(floatSubtractRR); - bo[index(c, lir::FloatSubtract, M, R)] = CAST2(floatSubtractMR); - - bo[index(c, lir::And, R, R)] = CAST2(andRR); - bo[index(c, lir::And, C, R)] = CAST2(andCR); - - bo[index(c, lir::Or, R, R)] = CAST2(orRR); - bo[index(c, lir::Or, C, R)] = CAST2(orCR); - - bo[index(c, lir::Xor, R, R)] = CAST2(xorRR); - bo[index(c, lir::Xor, C, R)] = CAST2(xorCR); - - bo[index(c, lir::Multiply, R, R)] = CAST2(multiplyRR); - bo[index(c, lir::Multiply, C, R)] = CAST2(multiplyCR); - - bo[index(c, lir::Divide, R, R)] = CAST2(divideRR); - - bo[index(c, lir::FloatMultiply, R, R)] = CAST2(floatMultiplyRR); - bo[index(c, lir::FloatMultiply, M, R)] = CAST2(floatMultiplyMR); - - bo[index(c, lir::FloatDivide, R, R)] = CAST2(floatDivideRR); - bo[index(c, lir::FloatDivide, M, R)] = CAST2(floatDivideMR); - - bo[index(c, lir::Remainder, R, R)] = CAST2(remainderRR); - - bo[index(c, lir::ShiftLeft, R, R)] = CAST2(shiftLeftRR); - bo[index(c, lir::ShiftLeft, C, R)] = CAST2(shiftLeftCR); - - bo[index(c, lir::ShiftRight, R, R)] = CAST2(shiftRightRR); - bo[index(c, lir::ShiftRight, C, R)] = CAST2(shiftRightCR); - - bo[index(c, lir::UnsignedShiftRight, R, R)] = CAST2(unsignedShiftRightRR); - bo[index(c, lir::UnsignedShiftRight, C, R)] = CAST2(unsignedShiftRightCR); - - bo[index(c, lir::Float2Float, R, R)] = CAST2(float2FloatRR); - bo[index(c, lir::Float2Float, M, R)] = CAST2(float2FloatMR); - - bo[index(c, lir::Float2Int, R, R)] = CAST2(float2IntRR); - bo[index(c, lir::Float2Int, M, R)] = CAST2(float2IntMR); - - bo[index(c, lir::Int2Float, R, R)] = CAST2(int2FloatRR); - bo[index(c, lir::Int2Float, M, R)] = CAST2(int2FloatMR); - - bo[index(c, lir::Absolute, R, R)] = CAST2(absoluteRR); - bo[index(c, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); - - bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); - bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); - bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM); - bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM); -} - class MyArchitecture: public Assembler::Architecture { public: MyArchitecture(System* system, bool useNativeFeatures): diff --git a/src/codegen/x86/block.cpp b/src/codegen/x86/block.cpp index 152fd99a8d..97bac8dbf1 100644 --- a/src/codegen/x86/block.cpp +++ b/src/codegen/x86/block.cpp @@ -11,10 +11,6 @@ #include "codegen/x86/block.h" #include "common.h" -#define CAST1(x) reinterpret_cast(x) -#define CAST2(x) reinterpret_cast(x) -#define CAST_BRANCH(x) reinterpret_cast(x) - namespace avian { namespace codegen { namespace x86 { diff --git a/src/codegen/x86/context.cpp b/src/codegen/x86/context.cpp index da73e97606..4c996f2b75 100644 --- a/src/codegen/x86/context.cpp +++ b/src/codegen/x86/context.cpp @@ -11,10 +11,6 @@ #include "codegen/x86/context.h" #include "codegen/x86/block.h" -#define CAST1(x) reinterpret_cast(x) -#define CAST2(x) reinterpret_cast(x) -#define CAST_BRANCH(x) reinterpret_cast(x) - namespace avian { namespace codegen { namespace x86 { diff --git a/src/codegen/x86/context.h b/src/codegen/x86/context.h index 5b3a915b9c..70233dd399 100644 --- a/src/codegen/x86/context.h +++ b/src/codegen/x86/context.h @@ -11,6 +11,10 @@ #ifndef AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H #define AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + #include "codegen/lir.h" #include "codegen/assembler.h" #include "alloc-vector.h" diff --git a/src/codegen/x86/detect.cpp b/src/codegen/x86/detect.cpp new file mode 100644 index 0000000000..eaf6af54ac --- /dev/null +++ b/src/codegen/x86/detect.cpp @@ -0,0 +1,40 @@ + +/* Copyright (c) 2008-2012, 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 "codegen/x86/context.h" +#include "codegen/x86/block.h" + +namespace avian { +namespace codegen { +namespace x86 { + +extern "C" bool +detectFeature(unsigned ecx, unsigned edx); + +bool useSSE(ArchitectureContext* c) { + if (vm::TargetBytesPerWord == 8) { + // amd64 implies SSE2 support + return true; + } else if (c->useNativeFeatures) { + static int supported = -1; + if (supported == -1) { + supported = detectFeature(0, 0x2000000) // SSE 1 + and detectFeature(0, 0x4000000); // SSE 2 + } + return supported; + } else { + return false; + } +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/detect.h b/src/codegen/x86/detect.h new file mode 100644 index 0000000000..13c7e58be1 --- /dev/null +++ b/src/codegen/x86/detect.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H + +#include "codegen/assembler.h" + +namespace avian { +namespace codegen { +namespace x86 { + +class ArchitectureContext; + +bool useSSE(ArchitectureContext* c); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H diff --git a/src/codegen/x86/encode.cpp b/src/codegen/x86/encode.cpp new file mode 100644 index 0000000000..8c34c426f9 --- /dev/null +++ b/src/codegen/x86/encode.cpp @@ -0,0 +1,345 @@ +/* Copyright (c) 2008-2012, 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 "target.h" + +#include "codegen/x86/context.h" +#include "codegen/x86/encode.h" +#include "codegen/x86/registers.h" +#include "codegen/x86/fixup.h" + +namespace avian { +namespace codegen { +namespace x86 { + + +#define REX_W 0x48 +#define REX_R 0x44 +#define REX_X 0x42 +#define REX_B 0x41 +#define REX_NONE 0x40 + +void maybeRex(Context* c, unsigned size, int a, int index, int base, bool always) { + if (vm::TargetBytesPerWord == 8) { + uint8_t byte; + if (size == 8) { + byte = REX_W; + } else { + byte = REX_NONE; + } + if (a != lir::NoRegister and (a & 8)) byte |= REX_R; + if (index != lir::NoRegister and (index & 8)) byte |= REX_X; + if (base != lir::NoRegister and (base & 8)) byte |= REX_B; + if (always or byte != REX_NONE) c->code.append(byte); + } +} + +void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Register* b) { + maybeRex(c, size, a->low, lir::NoRegister, b->low, false); +} + +void alwaysRex(Context* c, unsigned size, lir::Register* a, lir::Register* b) { + maybeRex(c, size, a->low, lir::NoRegister, b->low, true); +} + +void maybeRex(Context* c, unsigned size, lir::Register* a) { + maybeRex(c, size, lir::NoRegister, lir::NoRegister, a->low, false); +} + +void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Memory* b) { + maybeRex(c, size, a->low, b->index, b->base, size == 1 and (a->low & 4)); +} + +void maybeRex(Context* c, unsigned size, lir::Memory* a) { + maybeRex(c, size, lir::NoRegister, a->index, a->base, false); +} + +void modrm(Context* c, uint8_t mod, int a, int b) { + c->code.append(mod | (regCode(b) << 3) | regCode(a)); +} + +void modrm(Context* c, uint8_t mod, lir::Register* a, lir::Register* b) { + modrm(c, mod, a->low, b->low); +} + +void sib(Context* c, unsigned scale, int index, int base) { + c->code.append((vm::log(scale) << 6) | (regCode(index) << 3) | regCode(base)); +} + +void modrmSib(Context* c, int width, int a, int scale, int index, int base) { + if (index == lir::NoRegister) { + modrm(c, width, base, a); + if (regCode(base) == rsp) { + sib(c, 0x00, rsp, rsp); + } + } else { + modrm(c, width, rsp, a); + sib(c, scale, index, base); + } +} + +void modrmSibImm(Context* c, int a, int scale, int index, int base, int offset) { + if (offset == 0 and regCode(base) != rbp) { + modrmSib(c, 0x00, a, scale, index, base); + } else if (vm::fitsInInt8(offset)) { + modrmSib(c, 0x40, a, scale, index, base); + c->code.append(offset); + } else { + modrmSib(c, 0x80, a, scale, index, base); + c->code.append4(offset); + } +} + +void modrmSibImm(Context* c, lir::Register* a, lir::Memory* b) { + modrmSibImm(c, a->low, b->scale, b->index, b->base, b->offset); +} + +void opcode(Context* c, uint8_t op) { + c->code.append(op); +} + +void opcode(Context* c, uint8_t op1, uint8_t op2) { + c->code.append(op1); + c->code.append(op2); +} + +void unconditional(Context* c, unsigned jump, lir::Constant* a) { + appendOffsetTask(c, a->value, offsetPromise(c), 5); + + opcode(c, jump); + c->code.append4(0); +} + +void conditional(Context* c, unsigned condition, lir::Constant* a) { + appendOffsetTask(c, a->value, offsetPromise(c), 6); + + opcode(c, 0x0f, condition); + c->code.append4(0); +} + +void sseMoveRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize >= 4); + assert(c, aSize == bSize); + + if (isFloatReg(a) and isFloatReg(b)) { + if (aSize == 4) { + opcode(c, 0xf3); + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x10); + modrm(c, 0xc0, a, b); + } else { + opcode(c, 0xf2); + maybeRex(c, 4, b, a); + opcode(c, 0x0f, 0x10); + modrm(c, 0xc0, a, b); + } + } else if (isFloatReg(a)) { + opcode(c, 0x66); + maybeRex(c, aSize, a, b); + opcode(c, 0x0f, 0x7e); + modrm(c, 0xc0, b, a); + } else { + opcode(c, 0x66); + maybeRex(c, aSize, b, a); + opcode(c, 0x0f, 0x6e); + modrm(c, 0xc0, a, b); + } +} + +void sseMoveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize <= vm::TargetBytesPerWord); + lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR2(c, aSize, a, aSize, &tmp, 0); + sseMoveRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); +} + +void sseMoveMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize >= 4); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + opcode(c, 0xf3); + opcode(c, 0x0f, 0x7e); + modrmSibImm(c, b, a); + } else { + opcode(c, 0x66); + maybeRex(c, aSize, b, a); + opcode(c, 0x0f, 0x6e); + modrmSibImm(c, b, a); + } +} + +void sseMoveRM(Context* c, unsigned aSize, lir::Register* a, + UNUSED unsigned bSize, lir::Memory* b) +{ + assert(c, aSize >= 4); + assert(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + opcode(c, 0x66); + opcode(c, 0x0f, 0xd6); + modrmSibImm(c, a, b); + } else { + opcode(c, 0x66); + maybeRex(c, aSize, a, b); + opcode(c, 0x0f, 0x7e); + modrmSibImm(c, a, b); + } +} + +void branch(Context* c, lir::TernaryOperation op, lir::Constant* target) { + switch (op) { + case lir::JumpIfEqual: + conditional(c, 0x84, target); + break; + + case lir::JumpIfNotEqual: + conditional(c, 0x85, target); + break; + + case lir::JumpIfLess: + conditional(c, 0x8c, target); + break; + + case lir::JumpIfGreater: + conditional(c, 0x8f, target); + break; + + case lir::JumpIfLessOrEqual: + conditional(c, 0x8e, target); + break; + + case lir::JumpIfGreaterOrEqual: + conditional(c, 0x8d, target); + break; + + default: + abort(c); + } +} + +void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) { + switch (op) { + case lir::JumpIfFloatEqual: + conditional(c, 0x84, target); + break; + + case lir::JumpIfFloatNotEqual: + conditional(c, 0x85, target); + break; + + case lir::JumpIfFloatLess: + conditional(c, 0x82, target); + break; + + case lir::JumpIfFloatGreater: + conditional(c, 0x87, target); + break; + + case lir::JumpIfFloatLessOrEqual: + conditional(c, 0x86, target); + break; + + case lir::JumpIfFloatGreaterOrEqual: + conditional(c, 0x83, target); + break; + + case lir::JumpIfFloatLessOrUnordered: + conditional(c, 0x82, target); + conditional(c, 0x8a, target); + break; + + case lir::JumpIfFloatGreaterOrUnordered: + conditional(c, 0x87, target); + conditional(c, 0x8a, target); + break; + + case lir::JumpIfFloatLessOrEqualOrUnordered: + conditional(c, 0x86, target); + conditional(c, 0x8a, target); + break; + + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + conditional(c, 0x83, target); + conditional(c, 0x8a, target); + break; + + default: + abort(c); + } +} + +void floatRegOp(Context* c, unsigned aSize, lir::Register* a, unsigned bSize, + lir::Register* b, uint8_t op, uint8_t mod) +{ + if (aSize == 4) { + opcode(c, 0xf3); + } else { + opcode(c, 0xf2); + } + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, op); + modrm(c, mod, a, b); +} + +void floatMemOp(Context* c, unsigned aSize, lir::Memory* a, unsigned bSize, + lir::Register* b, uint8_t op) +{ + if (aSize == 4) { + opcode(c, 0xf3); + } else { + opcode(c, 0xf2); + } + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, op); + modrmSibImm(c, b, a); +} + +void moveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, + UNUSED unsigned bSize, lir::Register* b, unsigned promiseOffset) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + int64_t v = a->value->value(); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + + moveCR(c, 4, &al, 4, b); + moveCR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, vm::TargetBytesPerWord, b); + opcode(c, 0xb8 + regCode(b)); + if (a->value->resolved()) { + c->code.appendTargetAddress(a->value->value()); + } else { + appendImmediateTask + (c, a->value, offsetPromise(c), vm::TargetBytesPerWord, promiseOffset); + c->code.appendTargetAddress(static_cast(0)); + } + } +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/encode.h b/src/codegen/x86/encode.h new file mode 100644 index 0000000000..293eeab2a9 --- /dev/null +++ b/src/codegen/x86/encode.h @@ -0,0 +1,93 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H + +#include "codegen/assembler.h" +#include "codegen/x86/registers.h" + +namespace avian { +namespace codegen { +namespace x86 { +void maybeRex(Context* c, unsigned size, int a, int index, int base, bool always); + +void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Register* b); + +void alwaysRex(Context* c, unsigned size, lir::Register* a, lir::Register* b); + +void maybeRex(Context* c, unsigned size, lir::Register* a); + +void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Memory* b); + +void maybeRex(Context* c, unsigned size, lir::Memory* a); + +inline int regCode(int a) { + return a & 7; +} + +inline int regCode(lir::Register* a) { + return regCode(a->low); +} + +inline bool isFloatReg(lir::Register* a) { + return a->low >= xmm0; +} + +void modrm(Context* c, uint8_t mod, int a, int b); + +void modrm(Context* c, uint8_t mod, lir::Register* a, lir::Register* b); + +void sib(Context* c, unsigned scale, int index, int base); + +void modrmSib(Context* c, int width, int a, int scale, int index, int base); + +void modrmSibImm(Context* c, int a, int scale, int index, int base, int offset); + +void modrmSibImm(Context* c, lir::Register* a, lir::Memory* b); + +void opcode(Context* c, uint8_t op); + +void opcode(Context* c, uint8_t op1, uint8_t op2); + +void unconditional(Context* c, unsigned jump, lir::Constant* a); + +void conditional(Context* c, unsigned condition, lir::Constant* a); + +void sseMoveRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void sseMoveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void sseMoveMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void sseMoveRM(Context* c, unsigned aSize, lir::Register* a, + UNUSED unsigned bSize, lir::Memory* b); + +void branch(Context* c, lir::TernaryOperation op, lir::Constant* target); + +void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target); + +void floatRegOp(Context* c, unsigned aSize, lir::Register* a, unsigned bSize, + lir::Register* b, uint8_t op, uint8_t mod = 0xc0); + +void floatMemOp(Context* c, unsigned aSize, lir::Memory* a, unsigned bSize, + lir::Register* b, uint8_t op); + +void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, + UNUSED unsigned bSize, lir::Register* b, unsigned promiseOffset); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H diff --git a/src/codegen/x86/fixup.cpp b/src/codegen/x86/fixup.cpp index f739e1b3e4..5892fbd9e2 100644 --- a/src/codegen/x86/fixup.cpp +++ b/src/codegen/x86/fixup.cpp @@ -101,6 +101,62 @@ appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, c->tasks = task; } +ImmediateListener::ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset): + s(s), dst(dst), size(size), offset(offset) +{ } + +void copy(vm::System* s, void* dst, int64_t src, unsigned size) { + switch (size) { + case 4: { + int32_t v = src; + memcpy(dst, &v, 4); + } break; + + case 8: { + int64_t v = src; + memcpy(dst, &v, 8); + } break; + + default: abort(s); + } +} + +bool ImmediateListener::resolve(int64_t value, void** location) { + copy(s, dst, value, size); + if (location) *location = static_cast(dst) + offset; + return offset == 0; +} + +ImmediateTask::ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, + unsigned promiseOffset): + Task(next), + promise(promise), + offset(offset), + size(size), + promiseOffset(promiseOffset) +{ } + +void ImmediateTask::run(Context* c) { + if (promise->resolved()) { + copy(c->s, c->result + offset->value(), promise->value(), size); + } else { + new (promise->listen(sizeof(ImmediateListener))) ImmediateListener + (c->s, c->result + offset->value(), size, promiseOffset); + } +} + +void +appendImmediateTask(Context* c, Promise* promise, Promise* offset, + unsigned size, unsigned promiseOffset) +{ + c->tasks = new(c->zone) ImmediateTask + (c->tasks, promise, offset, size, promiseOffset); +} + +ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { + return new(c->zone) ShiftMaskPromise(base, shift, mask); +} + } // namespace x86 } // namespace codegen } // namespace avian diff --git a/src/codegen/x86/fixup.h b/src/codegen/x86/fixup.h index 2b97af9cfb..2bf8ff3481 100644 --- a/src/codegen/x86/fixup.h +++ b/src/codegen/x86/fixup.h @@ -80,6 +80,37 @@ class OffsetTask: public Task { void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, unsigned instructionSize); +class ImmediateListener: public Promise::Listener { + public: + ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + void* dst; + unsigned size; + unsigned offset; +}; + +class ImmediateTask: public Task { + public: + ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, + unsigned promiseOffset); + + virtual void run(Context* c); + + Promise* promise; + Promise* offset; + unsigned size; + unsigned promiseOffset; +}; + +void +appendImmediateTask(Context* c, Promise* promise, Promise* offset, + unsigned size, unsigned promiseOffset = 0); + +ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask); + } // namespace x86 } // namespace codegen } // namespace avian diff --git a/src/codegen/x86/multimethod.cpp b/src/codegen/x86/multimethod.cpp new file mode 100644 index 0000000000..d665fef895 --- /dev/null +++ b/src/codegen/x86/multimethod.cpp @@ -0,0 +1,174 @@ +/* Copyright (c) 2008-2012, 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 "common.h" + +#include "codegen/lir.h" + +#include "codegen/x86/context.h" +#include "codegen/x86/multimethod.h" +#include "codegen/x86/operations.h" + +namespace avian { +namespace codegen { +namespace x86 { + + +unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) { + return operation + (lir::UnaryOperationCount * operand); +} + +unsigned index(ArchitectureContext*, lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2) +{ + return operation + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::OperandTypeCount * operand2); +} + +unsigned index(ArchitectureContext* c UNUSED, lir::TernaryOperation operation, + lir::OperandType operand1, lir::OperandType operand2) +{ + assert(c, not isBranch(operation)); + + return lir::BinaryOperationCount + operation + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::OperandTypeCount * operand2); +} + +unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, + lir::OperandType operand2) +{ + return operand1 + (lir::OperandTypeCount * operand2); +} + + +void populateTables(ArchitectureContext* c) { + const lir::OperandType C = lir::ConstantOperand; + const lir::OperandType A = lir::AddressOperand; + const lir::OperandType R = lir::RegisterOperand; + const lir::OperandType M = lir::MemoryOperand; + + OperationType* zo = c->operations; + UnaryOperationType* uo = c->unaryOperations; + BinaryOperationType* bo = c->binaryOperations; + BranchOperationType* bro = c->branchOperations; + + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = ignore; + zo[lir::StoreStoreBarrier] = ignore; + zo[lir::StoreLoadBarrier] = storeLoadBarrier; + zo[lir::Trap] = trap; + + uo[index(c, lir::Call, C)] = CAST1(callC); + uo[index(c, lir::Call, R)] = CAST1(callR); + uo[index(c, lir::Call, M)] = CAST1(callM); + + uo[index(c, lir::AlignedCall, C)] = CAST1(alignedCallC); + + uo[index(c, lir::LongCall, C)] = CAST1(longCallC); + + uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); + + uo[index(c, lir::Jump, R)] = CAST1(jumpR); + uo[index(c, lir::Jump, C)] = CAST1(jumpC); + uo[index(c, lir::Jump, M)] = CAST1(jumpM); + + uo[index(c, lir::AlignedJump, C)] = CAST1(alignedJumpC); + + uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); + + uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); + + bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); + + bo[index(c, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); + + bo[index(c, lir::Move, R, R)] = CAST2(moveRR); + bo[index(c, lir::Move, C, R)] = CAST2(moveCR); + bo[index(c, lir::Move, M, R)] = CAST2(moveMR); + bo[index(c, lir::Move, R, M)] = CAST2(moveRM); + bo[index(c, lir::Move, C, M)] = CAST2(moveCM); + bo[index(c, lir::Move, A, R)] = CAST2(moveAR); + + bo[index(c, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + bo[index(c, lir::FloatSquareRoot, M, R)] = CAST2(floatSqrtMR); + + bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR); + + bo[index(c, lir::Add, R, R)] = CAST2(addRR); + bo[index(c, lir::Add, C, R)] = CAST2(addCR); + + bo[index(c, lir::Subtract, C, R)] = CAST2(subtractCR); + bo[index(c, lir::Subtract, R, R)] = CAST2(subtractRR); + + bo[index(c, lir::FloatAdd, R, R)] = CAST2(floatAddRR); + bo[index(c, lir::FloatAdd, M, R)] = CAST2(floatAddMR); + + bo[index(c, lir::FloatSubtract, R, R)] = CAST2(floatSubtractRR); + bo[index(c, lir::FloatSubtract, M, R)] = CAST2(floatSubtractMR); + + bo[index(c, lir::And, R, R)] = CAST2(andRR); + bo[index(c, lir::And, C, R)] = CAST2(andCR); + + bo[index(c, lir::Or, R, R)] = CAST2(orRR); + bo[index(c, lir::Or, C, R)] = CAST2(orCR); + + bo[index(c, lir::Xor, R, R)] = CAST2(xorRR); + bo[index(c, lir::Xor, C, R)] = CAST2(xorCR); + + bo[index(c, lir::Multiply, R, R)] = CAST2(multiplyRR); + bo[index(c, lir::Multiply, C, R)] = CAST2(multiplyCR); + + bo[index(c, lir::Divide, R, R)] = CAST2(divideRR); + + bo[index(c, lir::FloatMultiply, R, R)] = CAST2(floatMultiplyRR); + bo[index(c, lir::FloatMultiply, M, R)] = CAST2(floatMultiplyMR); + + bo[index(c, lir::FloatDivide, R, R)] = CAST2(floatDivideRR); + bo[index(c, lir::FloatDivide, M, R)] = CAST2(floatDivideMR); + + bo[index(c, lir::Remainder, R, R)] = CAST2(remainderRR); + + bo[index(c, lir::ShiftLeft, R, R)] = CAST2(shiftLeftRR); + bo[index(c, lir::ShiftLeft, C, R)] = CAST2(shiftLeftCR); + + bo[index(c, lir::ShiftRight, R, R)] = CAST2(shiftRightRR); + bo[index(c, lir::ShiftRight, C, R)] = CAST2(shiftRightCR); + + bo[index(c, lir::UnsignedShiftRight, R, R)] = CAST2(unsignedShiftRightRR); + bo[index(c, lir::UnsignedShiftRight, C, R)] = CAST2(unsignedShiftRightCR); + + bo[index(c, lir::Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(c, lir::Float2Float, M, R)] = CAST2(float2FloatMR); + + bo[index(c, lir::Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(c, lir::Float2Int, M, R)] = CAST2(float2IntMR); + + bo[index(c, lir::Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(c, lir::Int2Float, M, R)] = CAST2(int2FloatMR); + + bo[index(c, lir::Absolute, R, R)] = CAST2(absoluteRR); + bo[index(c, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + + bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); + bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); + bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM); + bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM); +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/multimethod.h b/src/codegen/x86/multimethod.h new file mode 100644 index 0000000000..5a73850f29 --- /dev/null +++ b/src/codegen/x86/multimethod.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H + +namespace avian { +namespace codegen { +namespace x86 { + +class ArchitectureContext; + +unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand); + +unsigned index(ArchitectureContext*, lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2); + +unsigned index(ArchitectureContext* c UNUSED, lir::TernaryOperation operation, + lir::OperandType operand1, lir::OperandType operand2); + +unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, + lir::OperandType operand2); + +void populateTables(ArchitectureContext* c); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H diff --git a/src/codegen/x86/operations.cpp b/src/codegen/x86/operations.cpp new file mode 100644 index 0000000000..bf92b399b8 --- /dev/null +++ b/src/codegen/x86/operations.cpp @@ -0,0 +1,1532 @@ +/* Copyright (c) 2008-2012, 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 "codegen/x86/context.h" +#include "codegen/x86/encode.h" +#include "codegen/x86/registers.h" +#include "codegen/x86/detect.h" +#include "codegen/x86/operations.h" +#include "codegen/x86/padding.h" +#include "codegen/x86/fixup.h" + +namespace avian { +namespace codegen { +namespace x86 { + +void return_(Context* c) { + opcode(c, 0xc3); +} + +void trap(Context* c) { + opcode(c, 0xcc); +} + +void ignore(Context*) { } + +void storeLoadBarrier(Context* c) { + if (useSSE(c->ac)) { + // mfence: + c->code.append(0x0f); + c->code.append(0xae); + c->code.append(0xf0); + } else { + // lock addq $0x0,(%rsp): + c->code.append(0xf0); + if (vm::TargetBytesPerWord == 8) { + c->code.append(0x48); + } + c->code.append(0x83); + c->code.append(0x04); + c->code.append(0x24); + c->code.append(0x00); + } +} + +void callC(Context* c, unsigned size UNUSED, lir::Constant* a) { + assert(c, size == vm::TargetBytesPerWord); + + unconditional(c, 0xe8, a); +} + +void longCallC(Context* c, unsigned size, lir::Constant* a) { + assert(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + lir::Register r(LongJumpRegister); + moveCR2(c, size, a, size, &r, 11); + callR(c, size, &r); + } else { + callC(c, size, a); + } +} + +void jumpR(Context* c, unsigned size UNUSED, lir::Register* a) { + assert(c, size == vm::TargetBytesPerWord); + + maybeRex(c, 4, a); + opcode(c, 0xff, 0xe0 + regCode(a)); +} + +void jumpC(Context* c, unsigned size UNUSED, lir::Constant* a) { + assert(c, size == vm::TargetBytesPerWord); + + unconditional(c, 0xe9, a); +} + +void jumpM(Context* c, unsigned size UNUSED, lir::Memory* a) { + assert(c, size == vm::TargetBytesPerWord); + + maybeRex(c, 4, a); + opcode(c, 0xff); + modrmSibImm(c, rsp, a->scale, a->index, a->base, a->offset); +} + +void longJumpC(Context* c, unsigned size, lir::Constant* a) { + assert(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + lir::Register r(LongJumpRegister); + moveCR2(c, size, a, size, &r, 11); + jumpR(c, size, &r); + } else { + jumpC(c, size, a); + } +} + +void callR(Context* c, unsigned size UNUSED, lir::Register* a) { + assert(c, size == vm::TargetBytesPerWord); + + // maybeRex.W has no meaning here so we disable it + maybeRex(c, 4, a); + opcode(c, 0xff, 0xd0 + regCode(a)); +} + +void callM(Context* c, unsigned size UNUSED, lir::Memory* a) { + assert(c, size == vm::TargetBytesPerWord); + + maybeRex(c, 4, a); + opcode(c, 0xff); + modrmSibImm(c, rdx, a->scale, a->index, a->base, a->offset); +} + +void alignedCallC(Context* c, unsigned size, lir::Constant* a) { + new(c->zone) AlignmentPadding(c, 1, 4); + callC(c, size, a); +} + +void alignedLongCallC(Context* c, unsigned size, lir::Constant* a) { + assert(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + new (c->zone) AlignmentPadding(c, 2, 8); + longCallC(c, size, a); + } else { + alignedCallC(c, size, a); + } +} + +void alignedJumpC(Context* c, unsigned size, lir::Constant* a) { + new (c->zone) AlignmentPadding(c, 1, 4); + jumpC(c, size, a); +} + +void alignedLongJumpC(Context* c, unsigned size, lir::Constant* a) { + assert(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + new (c->zone) AlignmentPadding(c, 2, 8); + longJumpC(c, size, a); + } else { + alignedJumpC(c, size, a); + } +} + +void pushR(Context* c, unsigned size, lir::Register* a) +{ + if (vm::TargetBytesPerWord == 4 and size == 8) { + lir::Register ah(a->high); + + pushR(c, 4, &ah); + pushR(c, 4, a); + } else { + maybeRex(c, 4, a); + opcode(c, 0x50 + regCode(a)); + } +} + +void popR(Context* c, unsigned size, lir::Register* a) +{ + if (vm::TargetBytesPerWord == 4 and size == 8) { + lir::Register ah(a->high); + + popR(c, 4, a); + popR(c, 4, &ah); + } else { + maybeRex(c, 4, a); + opcode(c, 0x58 + regCode(a)); + if (vm::TargetBytesPerWord == 8 and size == 4) { + moveRR(c, 4, a, 8, a); + } + } +} + +void negateR(Context* c, unsigned size, lir::Register* a) +{ + if (vm::TargetBytesPerWord == 4 and size == 8) { + assert(c, a->low == rax and a->high == rdx); + + ResolvedPromise zeroPromise(0); + lir::Constant zero(&zeroPromise); + + lir::Register ah(a->high); + + negateR(c, 4, a); + addCarryCR(c, 4, &zero, &ah); + negateR(c, 4, &ah); + } else { + maybeRex(c, size, a); + opcode(c, 0xf7, 0xd8 + regCode(a)); + } +} + +void negateRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED) +{ + assert(c, aSize == bSize); + + negateR(c, aSize, a); +} + +void moveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + if (isFloatReg(b)) { + sseMoveCR(c, aSize, a, bSize, b); + } else { + moveCR2(c, aSize, a, bSize, b, 0); + } +} + +void swapRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + assert(c, aSize == vm::TargetBytesPerWord); + + alwaysRex(c, aSize, a, b); + opcode(c, 0x87); + modrm(c, 0xc0, b, a); +} + +void moveRR(Context* c, unsigned aSize, lir::Register* a, + UNUSED unsigned bSize, lir::Register* b) +{ + if (isFloatReg(a) or isFloatReg(b)) { + sseMoveRR(c, aSize, a, bSize, b); + return; + } + + if (vm::TargetBytesPerWord == 4 and aSize == 8 and bSize == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + if (a->high == b->low) { + if (a->low == b->high) { + swapRR(c, 4, a, 4, b); + } else { + moveRR(c, 4, &ah, 4, &bh); + moveRR(c, 4, a, 4, b); + } + } else { + moveRR(c, 4, a, 4, b); + moveRR(c, 4, &ah, 4, &bh); + } + } else { + switch (aSize) { + case 1: + if (vm::TargetBytesPerWord == 4 and a->low > rbx) { + assert(c, b->low <= rbx); + + moveRR(c, vm::TargetBytesPerWord, a, vm::TargetBytesPerWord, b); + moveRR(c, 1, b, vm::TargetBytesPerWord, b); + } else { + alwaysRex(c, aSize, b, a); + opcode(c, 0x0f, 0xbe); + modrm(c, 0xc0, a, b); + } + break; + + case 2: + alwaysRex(c, aSize, b, a); + opcode(c, 0x0f, 0xbf); + modrm(c, 0xc0, a, b); + break; + + case 4: + if (bSize == 8) { + if (vm::TargetBytesPerWord == 8) { + alwaysRex(c, bSize, b, a); + opcode(c, 0x63); + modrm(c, 0xc0, a, b); + } else { + if (a->low == rax and b->low == rax and b->high == rdx) { + opcode(c, 0x99); //cdq + } else { + assert(c, b->low == rax and b->high == rdx); + + moveRR(c, 4, a, 4, b); + moveRR(c, 4, b, 8, b); + } + } + } else { + if (a->low != b->low) { + alwaysRex(c, aSize, a, b); + opcode(c, 0x89); + modrm(c, 0xc0, b, a); + } + } + break; + + case 8: + if (a->low != b->low){ + maybeRex(c, aSize, a, b); + opcode(c, 0x89); + modrm(c, 0xc0, b, a); + } + break; + } + } +} + +void moveMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b) +{ + if (isFloatReg(b)) { + sseMoveMR(c, aSize, a, bSize, b); + return; + } + + switch (aSize) { + case 1: + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, 0xbe); + modrmSibImm(c, b, a); + break; + + case 2: + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, 0xbf); + modrmSibImm(c, b, a); + break; + + case 4: + if (vm::TargetBytesPerWord == 8) { + maybeRex(c, bSize, b, a); + opcode(c, 0x63); + modrmSibImm(c, b, a); + } else { + if (bSize == 8) { + assert(c, b->low == rax and b->high == rdx); + + moveMR(c, 4, a, 4, b); + moveRR(c, 4, b, 8, b); + } else { + maybeRex(c, bSize, b, a); + opcode(c, 0x8b); + modrmSibImm(c, b, a); + } + } + break; + + case 8: + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::Memory ah(a->base, a->offset + 4, a->index, a->scale); + lir::Register bh(b->high); + + moveMR(c, 4, a, 4, b); + moveMR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, bSize, b, a); + opcode(c, 0x8b); + modrmSibImm(c, b, a); + } + break; + + default: abort(c); + } +} + +void moveRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Memory* b) +{ + assert(c, aSize == bSize); + + if (isFloatReg(a)) { + sseMoveRM(c, aSize, a, bSize, b); + return; + } + + switch (aSize) { + case 1: + maybeRex(c, bSize, a, b); + opcode(c, 0x88); + modrmSibImm(c, a, b); + break; + + case 2: + opcode(c, 0x66); + maybeRex(c, bSize, a, b); + opcode(c, 0x89); + modrmSibImm(c, a, b); + break; + + case 4: + if (vm::TargetBytesPerWord == 8) { + maybeRex(c, bSize, a, b); + opcode(c, 0x89); + modrmSibImm(c, a, b); + break; + } else { + opcode(c, 0x89); + modrmSibImm(c, a, b); + } + break; + + case 8: + if (vm::TargetBytesPerWord == 8) { + maybeRex(c, bSize, a, b); + opcode(c, 0x89); + modrmSibImm(c, a, b); + } else { + lir::Register ah(a->high); + lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); + + moveRM(c, 4, a, 4, b); + moveRM(c, 4, &ah, 4, &bh); + } + break; + + default: abort(c); + } +} + +void moveAR(Context* c, unsigned aSize, lir::Address* a, + unsigned bSize, lir::Register* b) +{ + assert(c, vm::TargetBytesPerWord == 8 or (aSize == 4 and bSize == 4)); + + lir::Constant constant(a->address); + lir::Memory memory(b->low, 0, -1, 0); + + moveCR(c, aSize, &constant, bSize, b); + moveMR(c, bSize, &memory, bSize, b); +} + +void moveCM(Context* c, unsigned aSize UNUSED, lir::Constant* a, + unsigned bSize, lir::Memory* b) +{ + switch (bSize) { + case 1: + maybeRex(c, bSize, b); + opcode(c, 0xc6); + modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); + c->code.append(a->value->value()); + break; + + case 2: + opcode(c, 0x66); + maybeRex(c, bSize, b); + opcode(c, 0xc7); + modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); + c->code.append2(a->value->value()); + break; + + case 4: + maybeRex(c, bSize, b); + opcode(c, 0xc7); + modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); + if (a->value->resolved()) { + c->code.append4(a->value->value()); + } else { + appendImmediateTask(c, a->value, offsetPromise(c), 4); + c->code.append4(0); + } + break; + + case 8: { + if (vm::TargetBytesPerWord == 8) { + if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { + maybeRex(c, bSize, b); + opcode(c, 0xc7); + modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset); + c->code.append4(a->value->value()); + } else { + lir::Register tmp + (c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, 8, a, 8, &tmp); + moveRM(c, 8, &tmp, 8, b); + c->client->releaseTemporary(tmp.low); + } + } else { + lir::Constant ah(shiftMaskPromise(c, a->value, 32, 0xFFFFFFFF)); + lir::Constant al(shiftMaskPromise(c, a->value, 0, 0xFFFFFFFF)); + + lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); + + moveCM(c, 4, &al, 4, b); + moveCM(c, 4, &ah, 4, &bh); + } + } break; + + default: abort(c); + } +} + +void moveZRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + switch (aSize) { + case 2: + alwaysRex(c, aSize, b, a); + opcode(c, 0x0f, 0xb7); + modrm(c, 0xc0, a, b); + break; + + default: abort(c); + } +} + +void moveZMR(Context* c, unsigned aSize UNUSED, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, bSize == vm::TargetBytesPerWord); + assert(c, aSize == 2); + + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, 0xb7); + modrmSibImm(c, b->low, a->scale, a->index, a->base, a->offset); +} + +void addCarryRR(Context* c, unsigned size, lir::Register* a, + lir::Register* b) +{ + assert(c, vm::TargetBytesPerWord == 8 or size == 4); + + maybeRex(c, size, a, b); + opcode(c, 0x11); + modrm(c, 0xc0, b, a); +} + +void addRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + addRR(c, 4, a, 4, b); + addCarryRR(c, 4, &ah, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x01); + modrm(c, 0xc0, b, a); + } +} + +void addCarryCR(Context* c, unsigned size, lir::Constant* a, + lir::Register* b) +{ + + int64_t v = a->value->value(); + maybeRex(c, size, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xd0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xd0 + regCode(b)); + c->code.append4(v); + } +} + +void addCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + + addCR(c, 4, &al, 4, b); + addCarryCR(c, 4, &ah, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xc0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xc0 + regCode(b)); + c->code.append4(v); + } + } else { + lir::Register tmp + (c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + addRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void subtractBorrowCR(Context* c, unsigned size UNUSED, lir::Constant* a, + lir::Register* b) +{ + assert(c, vm::TargetBytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xd8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xd8 + regCode(b)); + c->code.append4(v); + } +} + +void subtractCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + + subtractCR(c, 4, &al, 4, b); + subtractBorrowCR(c, 4, &ah, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xe8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xe8 + regCode(b)); + c->code.append4(v); + } + } else { + lir::Register tmp + (c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + subtractRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void subtractBorrowRR(Context* c, unsigned size, lir::Register* a, + lir::Register* b) +{ + assert(c, vm::TargetBytesPerWord == 8 or size == 4); + + maybeRex(c, size, a, b); + opcode(c, 0x19); + modrm(c, 0xc0, b, a); +} + +void subtractRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + subtractRR(c, 4, a, 4, b); + subtractBorrowRR(c, 4, &ah, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x29); + modrm(c, 0xc0, b, a); + } +} + +void andRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + andRR(c, 4, a, 4, b); + andRR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x21); + modrm(c, 0xc0, b, a); + } +} + +void andCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize == bSize); + + int64_t v = a->value->value(); + + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + + andCR(c, 4, &al, 4, b); + andCR(c, 4, &ah, 4, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xe0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xe0 + regCode(b)); + c->code.append4(v); + } + } else { + lir::Register tmp + (c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + andRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } +} + +void orRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + orRR(c, 4, a, 4, b); + orRR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x09); + modrm(c, 0xc0, b, a); + } +} + +void orCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + + orCR(c, 4, &al, 4, b); + orCR(c, 4, &ah, 4, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xc8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xc8 + regCode(b)); + c->code.append4(v); + } + } else { + lir::Register tmp + (c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + orRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void xorRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + xorRR(c, 4, a, 4, b); + xorRR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x31); + modrm(c, 0xc0, b, a); + } +} + +void xorCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + + xorCR(c, 4, &al, 4, b); + xorCR(c, 4, &ah, 4, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xf0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xf0 + regCode(b)); + c->code.append4(v); + } + } else { + lir::Register tmp + (c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + xorRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void multiplyRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + assert(c, b->high == rdx); + assert(c, b->low != rax); + assert(c, a->low != rax); + assert(c, a->high != rax); + + c->client->save(rax); + + lir::Register axdx(rax, rdx); + lir::Register ah(a->high); + lir::Register bh(b->high); + + lir::Register tmp(-1); + lir::Register* scratch; + if (a->low == b->low) { + tmp.low = c->client->acquireTemporary + (GeneralRegisterMask & ~(1 << rax)); + scratch = &tmp; + moveRR(c, 4, b, 4, scratch); + } else { + scratch = b; + } + + moveRR(c, 4, b, 4, &axdx); + multiplyRR(c, 4, &ah, 4, scratch); + multiplyRR(c, 4, a, 4, &bh); + addRR(c, 4, &bh, 4, scratch); + + // mul a->low,%eax%edx + opcode(c, 0xf7, 0xe0 + a->low); + + addRR(c, 4, scratch, 4, &bh); + moveRR(c, 4, &axdx, 4, b); + + if (tmp.low != -1) { + c->client->releaseTemporary(tmp.low); + } + } else { + maybeRex(c, aSize, b, a); + opcode(c, 0x0f, 0xaf); + modrm(c, 0xc0, a, b); + } +} + +void compareRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + assert(c, aSize <= vm::TargetBytesPerWord); + + maybeRex(c, aSize, a, b); + opcode(c, 0x39); + modrm(c, 0xc0, b, a); +} + +void compareCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize == bSize); + assert(c, vm::TargetBytesPerWord == 8 or aSize == 4); + + if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { + int64_t v = a->value->value(); + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xf8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xf8 + regCode(b)); + c->code.append4(v); + } + } else { + lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + compareRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } +} + +void compareRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Memory* b) +{ + assert(c, aSize == bSize); + assert(c, vm::TargetBytesPerWord == 8 or aSize == 4); + + if (vm::TargetBytesPerWord == 8 and aSize == 4) { + moveRR(c, 4, a, 8, a); + } + maybeRex(c, bSize, a, b); + opcode(c, 0x39); + modrmSibImm(c, a, b); +} + +void compareCM(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b) +{ + assert(c, aSize == bSize); + assert(c, vm::TargetBytesPerWord == 8 or aSize == 4); + + if (a->value->resolved()) { + int64_t v = a->value->value(); + maybeRex(c, aSize, b); + opcode(c, vm::fitsInInt8(v) ? 0x83 : 0x81); + modrmSibImm(c, rdi, b->scale, b->index, b->base, b->offset); + + if (vm::fitsInInt8(v)) { + c->code.append(v); + } else if (vm::fitsInInt32(v)) { + c->code.append4(v); + } else { + abort(c); + } + } else { + lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, bSize, &tmp); + compareRM(c, bSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } +} + +void compareFloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + + if (aSize == 8) { + opcode(c, 0x66); + } + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x2e); + modrm(c, 0xc0, a, b); +} + +void branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, + BinaryOperationType compare) +{ + compare(c, 4, ah, 4, bh); + + unsigned next = 0; + + switch (op) { + case lir::JumpIfEqual: + opcode(c, 0x75); // jne + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x84, target); // je + break; + + case lir::JumpIfNotEqual: + conditional(c, 0x85, target); // jne + + compare(c, 4, al, 4, bl); + conditional(c, 0x85, target); // jne + break; + + case lir::JumpIfLess: + conditional(c, 0x8c, target); // jl + + opcode(c, 0x7f); // jg + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x82, target); // jb + break; + + case lir::JumpIfGreater: + conditional(c, 0x8f, target); // jg + + opcode(c, 0x7c); // jl + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x87, target); // ja + break; + + case lir::JumpIfLessOrEqual: + conditional(c, 0x8c, target); // jl + + opcode(c, 0x7f); // jg + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x86, target); // jbe + break; + + case lir::JumpIfGreaterOrEqual: + conditional(c, 0x8f, target); // jg + + opcode(c, 0x7c); // jl + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x83, target); // jae + break; + + default: + abort(c); + } + + if (next) { + int8_t nextOffset = c->code.length() - next - 1; + c->code.set(next, &nextOffset, 1); + } +} + +void branchRR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target) +{ + if (isFloatBranch(op)) { + compareFloatRR(c, size, a, size, b); + branchFloat(c, op, target); + } else if (size > vm::TargetBytesPerWord) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR)); + } else { + compareRR(c, size, a, size, b); + branch(c, op, target); + } +} + +void branchCR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target) +{ + assert(c, not isFloatBranch(op)); + + if (size > vm::TargetBytesPerWord) { + int64_t v = a->value->value(); + + ResolvedPromise low(v & ~static_cast(0)); + lir::Constant al(&low); + + ResolvedPromise high((v >> 32) & ~static_cast(0)); + lir::Constant ah(&high); + + lir::Register bh(b->high); + + branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR)); + } else { + compareCR(c, size, a, size, b); + branch(c, op, target); + } +} + +void branchRM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target) +{ + assert(c, not isFloatBranch(op)); + assert(c, size <= vm::TargetBytesPerWord); + + compareRM(c, size, a, size, b); + branch(c, op, target); +} + +void branchCM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target) +{ + assert(c, not isFloatBranch(op)); + assert(c, size <= vm::TargetBytesPerWord); + + compareCM(c, size, a, size, b); + branch(c, op, target); +} + +void multiplyCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + const uint32_t mask = GeneralRegisterMask & ~((1 << rax) | (1 << rdx)); + lir::Register tmp(c->client->acquireTemporary(mask), + c->client->acquireTemporary(mask)); + + moveCR(c, aSize, a, aSize, &tmp); + multiplyRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + c->client->releaseTemporary(tmp.high); + } else { + int64_t v = a->value->value(); + if (v != 1) { + if (vm::fitsInInt32(v)) { + maybeRex(c, bSize, b, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x6b); + modrm(c, 0xc0, b, b); + c->code.append(v); + } else { + opcode(c, 0x69); + modrm(c, 0xc0, b, b); + c->code.append4(v); + } + } else { + lir::Register tmp + (c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + multiplyRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void divideRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED) +{ + assert(c, aSize == bSize); + + assert(c, b->low == rax); + assert(c, a->low != rdx); + + c->client->save(rdx); + + maybeRex(c, aSize, a, b); + opcode(c, 0x99); // cdq + maybeRex(c, aSize, b, a); + opcode(c, 0xf7, 0xf8 + regCode(a)); +} + +void remainderRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, aSize == bSize); + + assert(c, b->low == rax); + assert(c, a->low != rdx); + + c->client->save(rdx); + + maybeRex(c, aSize, a, b); + opcode(c, 0x99); // cdq + maybeRex(c, aSize, b, a); + opcode(c, 0xf7, 0xf8 + regCode(a)); + + lir::Register dx(rdx); + moveRR(c, vm::TargetBytesPerWord, &dx, vm::TargetBytesPerWord, b); +} + +void doShift(Context* c, UNUSED void (*shift) + (Context*, unsigned, lir::Register*, unsigned, + lir::Register*), + int type, UNUSED unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + int64_t v = a->value->value(); + + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + c->client->save(rcx); + + lir::Register cx(rcx); + ResolvedPromise promise(v & 0x3F); + lir::Constant masked(&promise); + moveCR(c, 4, &masked, 4, &cx); + shift(c, aSize, &cx, bSize, b); + } else { + maybeRex(c, bSize, b); + if (v == 1) { + opcode(c, 0xd1, type + regCode(b)); + } else if (vm::fitsInInt8(v)) { + opcode(c, 0xc1, type + regCode(b)); + c->code.append(v); + } else { + abort(c); + } + } +} + +void shiftLeftRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::Register cx(rcx); + if (a->low != rcx) { + c->client->save(rcx); + ResolvedPromise promise(0x3F); + lir::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + + // shld + opcode(c, 0x0f, 0xa5); + modrm(c, 0xc0, b->high, b->low); + + // shl + opcode(c, 0xd3, 0xe0 + b->low); + + ResolvedPromise promise(32); + lir::Constant constant(&promise); + compareCR(c, aSize, &constant, aSize, &cx); + + opcode(c, 0x7c); //jl + c->code.append(2 + 2); + + lir::Register bh(b->high); + moveRR(c, 4, b, 4, &bh); // 2 bytes + xorRR(c, 4, b, 4, b); // 2 bytes + } else { + assert(c, a->low == rcx); + + maybeRex(c, bSize, a, b); + opcode(c, 0xd3, 0xe0 + regCode(b)); + } +} + +void shiftLeftCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + doShift(c, shiftLeftRR, 0xe0, aSize, a, bSize, b); +} + +void shiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::Register cx(rcx); + if (a->low != rcx) { + c->client->save(rcx); + ResolvedPromise promise(0x3F); + lir::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + + // shrd + opcode(c, 0x0f, 0xad); + modrm(c, 0xc0, b->low, b->high); + + // sar + opcode(c, 0xd3, 0xf8 + b->high); + + ResolvedPromise promise(32); + lir::Constant constant(&promise); + compareCR(c, aSize, &constant, aSize, &cx); + + opcode(c, 0x7c); //jl + c->code.append(2 + 3); + + lir::Register bh(b->high); + moveRR(c, 4, &bh, 4, b); // 2 bytes + + // sar 31,high + opcode(c, 0xc1, 0xf8 + b->high); + c->code.append(31); + } else { + assert(c, a->low == rcx); + + maybeRex(c, bSize, a, b); + opcode(c, 0xd3, 0xf8 + regCode(b)); + } +} + +void shiftRightCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + doShift(c, shiftRightRR, 0xf8, aSize, a, bSize, b); +} + +void unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::Register cx(rcx); + if (a->low != rcx) { + c->client->save(rcx); + ResolvedPromise promise(0x3F); + lir::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + + // shrd + opcode(c, 0x0f, 0xad); + modrm(c, 0xc0, b->low, b->high); + + // shr + opcode(c, 0xd3, 0xe8 + b->high); + + ResolvedPromise promise(32); + lir::Constant constant(&promise); + compareCR(c, aSize, &constant, aSize, &cx); + + opcode(c, 0x7c); //jl + c->code.append(2 + 2); + + lir::Register bh(b->high); + moveRR(c, 4, &bh, 4, b); // 2 bytes + xorRR(c, 4, &bh, 4, &bh); // 2 bytes + } else { + assert(c, a->low == rcx); + + maybeRex(c, bSize, a, b); + opcode(c, 0xd3, 0xe8 + regCode(b)); + } +} + +void unsignedShiftRightCR(Context* c, unsigned aSize UNUSED, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + doShift(c, unsignedShiftRightRR, 0xe8, aSize, a, bSize, b); +} + +void floatSqrtRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x51); +} + +void floatSqrtMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x51); +} + +void floatAddRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x58); +} + +void floatAddMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x58); +} + +void floatSubtractRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x5c); +} + +void floatSubtractMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x5c); +} + +void floatMultiplyRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x59); +} + +void floatMultiplyMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x59); +} + +void floatDivideRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x5e); +} + +void floatDivideMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x5e); +} + +void float2FloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x5a); +} + +void float2FloatMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x5a); +} + +void float2IntRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) +{ + assert(c, not isFloatReg(b)); + floatRegOp(c, aSize, a, bSize, b, 0x2c); +} + +void float2IntMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b) +{ + floatMemOp(c, aSize, a, bSize, b, 0x2c); +} + +void int2FloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) +{ + floatRegOp(c, bSize, a, aSize, b, 0x2a); +} + +void int2FloatMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b) +{ + floatMemOp(c, bSize, a, aSize, b, 0x2a); +} + +void floatNegateRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, isFloatReg(a) and isFloatReg(b)); + // unlike most of the other floating point code, this does NOT + // support doubles: + assert(c, aSize == 4); + ResolvedPromise pcon(0x80000000); + lir::Constant con(&pcon); + if (a->low == b->low) { + lir::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); + moveCR(c, 4, &con, 4, &tmp); + maybeRex(c, 4, a, &tmp); + opcode(c, 0x0f, 0x57); + modrm(c, 0xc0, &tmp, a); + c->client->releaseTemporary(tmp.low); + } else { + moveCR(c, 4, &con, 4, b); + if (aSize == 8) opcode(c, 0x66); + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x57); + modrm(c, 0xc0, a, b); + } +} + +void floatAbsoluteRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, isFloatReg(a) and isFloatReg(b)); + // unlike most of the other floating point code, this does NOT + // support doubles: + assert(c, aSize == 4); + ResolvedPromise pcon(0x7fffffff); + lir::Constant con(&pcon); + if (a->low == b->low) { + lir::Register tmp(c->client->acquireTemporary(FloatRegisterMask)); + moveCR(c, 4, &con, 4, &tmp); + maybeRex(c, 4, a, &tmp); + opcode(c, 0x0f, 0x54); + modrm(c, 0xc0, &tmp, a); + c->client->releaseTemporary(tmp.low); + } else { + moveCR(c, 4, &con, 4, b); + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x54); + modrm(c, 0xc0, a, b); + } +} + +void absoluteRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED) +{ + assert(c, aSize == bSize and a->low == rax and b->low == rax); + lir::Register d + (c->client->acquireTemporary(static_cast(1) << rdx)); + maybeRex(c, aSize, a, b); + opcode(c, 0x99); + xorRR(c, aSize, &d, aSize, a); + subtractRR(c, aSize, &d, aSize, a); + c->client->releaseTemporary(rdx); +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/src/codegen/x86/operations.h b/src/codegen/x86/operations.h new file mode 100644 index 0000000000..52d0d8dc0f --- /dev/null +++ b/src/codegen/x86/operations.h @@ -0,0 +1,261 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H + +namespace avian { +namespace codegen { +namespace x86 { + +void return_(Context* c); + +void trap(Context* c); + +void ignore(Context*); + +void storeLoadBarrier(Context* c); + +void callC(Context* c, unsigned size UNUSED, lir::Constant* a); + +void longCallC(Context* c, unsigned size, lir::Constant* a); + +void jumpR(Context* c, unsigned size UNUSED, lir::Register* a); + +void jumpC(Context* c, unsigned size UNUSED, lir::Constant* a); + +void jumpM(Context* c, unsigned size UNUSED, lir::Memory* a); + +void longJumpC(Context* c, unsigned size, lir::Constant* a); + +void callR(Context* c, unsigned size UNUSED, lir::Register* a); + +void callM(Context* c, unsigned size UNUSED, lir::Memory* a); + +void alignedCallC(Context* c, unsigned size, lir::Constant* a); + +void alignedLongCallC(Context* c, unsigned size, lir::Constant* a); + +void alignedJumpC(Context* c, unsigned size, lir::Constant* a); + +void alignedLongJumpC(Context* c, unsigned size, lir::Constant* a); + +void pushR(Context* c, unsigned size, lir::Register* a); + +void popR(Context* c, unsigned size, lir::Register* a); + +void negateR(Context* c, unsigned size, lir::Register* a); + +void negateRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED); + +void moveCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void swapRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void moveRR(Context* c, unsigned aSize, lir::Register* a, + UNUSED unsigned bSize, lir::Register* b); + +void moveMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b); + +void moveRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Memory* b); + +void moveAR(Context* c, unsigned aSize, lir::Address* a, + unsigned bSize, lir::Register* b); + +void moveCM(Context* c, unsigned aSize UNUSED, lir::Constant* a, + unsigned bSize, lir::Memory* b); + +void moveZRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void moveZMR(Context* c, unsigned aSize UNUSED, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void addCarryRR(Context* c, unsigned size, lir::Register* a, + lir::Register* b); + +void addRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void addCarryCR(Context* c, unsigned size, lir::Constant* a, + lir::Register* b); + +void addCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void subtractBorrowCR(Context* c, unsigned size UNUSED, lir::Constant* a, + lir::Register* b); + +void subtractCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void subtractBorrowRR(Context* c, unsigned size, lir::Register* a, + lir::Register* b); + +void subtractRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void andRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void andCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void orRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void orCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void xorRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void xorCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void multiplyRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void compareRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void compareCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void compareRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Memory* b); + +void compareCM(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b); + +void compareFloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, + BinaryOperationType compare); + +void branchRR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target); + +void branchCR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target); + +void branchRM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target); + +void branchCM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target); + +void multiplyCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void divideRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED); + +void remainderRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void doShift(Context* c, UNUSED void (*shift) + (Context*, unsigned, lir::Register*, unsigned, + lir::Register*), + int type, UNUSED unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void shiftLeftRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); + +void shiftLeftCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void shiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); + +void shiftRightCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); + +void unsignedShiftRightCR(Context* c, unsigned aSize UNUSED, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void floatSqrtRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatSqrtMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatAddRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatAddMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatSubtractRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatSubtractMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatMultiplyRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatMultiplyMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatDivideRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatDivideMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void float2FloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void float2FloatMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize UNUSED, lir::Register* b); + +void float2IntRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); + +void float2IntMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b); + +void int2FloatRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); + +void int2FloatMR(Context* c, unsigned aSize, lir::Memory* a, + unsigned bSize, lir::Register* b); + +void floatNegateRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void floatAbsoluteRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void absoluteRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b UNUSED); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H diff --git a/src/codegen/x86/registers.h b/src/codegen/x86/registers.h new file mode 100644 index 0000000000..d5f325bca0 --- /dev/null +++ b/src/codegen/x86/registers.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_REGISTERS_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_REGISTERS_H + +namespace avian { +namespace codegen { +namespace x86 { + +enum { + rax = 0, + rcx = 1, + rdx = 2, + rbx = 3, + rsp = 4, + rbp = 5, + rsi = 6, + rdi = 7, + r8 = 8, + r9 = 9, + r10 = 10, + r11 = 11, + r12 = 12, + r13 = 13, + r14 = 14, + r15 = 15, +}; + +enum { + xmm0 = r15 + 1, + xmm1, + xmm2, + xmm3, + xmm4, + xmm5, + xmm6, + xmm7, + xmm8, + xmm9, + xmm10, + xmm11, + xmm12, + xmm13, + xmm14, + xmm15, +}; + +const int LongJumpRegister = r10; + +const unsigned GeneralRegisterMask = vm::TargetBytesPerWord == 4 ? 0x000000ff : 0x0000ffff; + +const unsigned FloatRegisterMask = vm::TargetBytesPerWord == 4 ? 0x00ff0000 : 0xffff0000; + + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_REGISTERS_H From e9be3c4e074664c5691724014521ff703628bec9 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 17 Feb 2013 11:19:07 -0700 Subject: [PATCH 251/378] move arg parser out of bootimage.cpp --- makefile | 2 +- src/bootimage.cpp | 103 ++-------------------------------------- src/util/arg-parser.cpp | 94 ++++++++++++++++++++++++++++++++++++ src/util/arg-parser.h | 46 ++++++++++++++++++ 4 files changed, 145 insertions(+), 100 deletions(-) create mode 100644 src/util/arg-parser.cpp create mode 100644 src/util/arg-parser.h diff --git a/makefile b/makefile index d0d451c9ae..9cbd83b65a 100755 --- a/makefile +++ b/makefile @@ -1041,7 +1041,7 @@ ifeq ($(continuations),true) asmflags += -DAVIAN_CONTINUATIONS endif -bootimage-generator-sources = $(src)/bootimage.cpp +bootimage-generator-sources = $(src)/bootimage.cpp $(src)/util/arg-parser.cpp ifneq ($(lzma),) bootimage-generator-sources += $(src)/lzma-encode.cpp endif diff --git a/src/bootimage.cpp b/src/bootimage.cpp index c2879403a2..d32ca69281 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -19,12 +19,16 @@ #include "binaryToObject/tools.h" #include "lzma.h" +#include "util/arg-parser.h" +#include "util/abort.h" + // since we aren't linking against libstdc++, we must implement this // ourselves: extern "C" void __cxa_pure_virtual(void) { abort(); } using namespace vm; using namespace avian::tools; +using namespace avian::util; namespace { @@ -1714,105 +1718,6 @@ writeBootImage(Thread* t, uintptr_t* arguments) return 1; } -class Arg; - -class ArgParser { -public: - Arg* first; - Arg** last; - - ArgParser(): - first(0), - last(&first) {} - - bool parse(int ac, const char** av); - void printUsage(const char* exe); -}; - -class Arg { -public: - Arg* next; - bool required; - const char* name; - const char* desc; - - const char* value; - - Arg(ArgParser& parser, bool required, const char* name, const char* desc): - next(0), - required(required), - name(name), - desc(desc), - value(0) - { - *parser.last = this; - parser.last = &next; - } -}; - -bool ArgParser::parse(int ac, const char** av) { - Arg* state = 0; - - for(int i = 1; i < ac; i++) { - if(state) { - if(state->value) { - fprintf(stderr, "duplicate parameter %s: '%s' and '%s'\n", state->name, state->value, av[i]); - return false; - } - state->value = av[i]; - state = 0; - } else { - if(av[i][0] != '-') { - fprintf(stderr, "expected -parameter\n"); - return false; - } - bool found = false; - for(Arg* arg = first; arg; arg = arg->next) { - if(::strcmp(arg->name, &av[i][1]) == 0) { - found = true; - if (arg->desc == 0) { - arg->value = "true"; - } else { - state = arg; - } - } - } - if (not found) { - fprintf(stderr, "unrecognized parameter %s\n", av[i]); - return false; - } - } - } - - if(state) { - fprintf(stderr, "expected argument after -%s\n", state->name); - return false; - } - - for(Arg* arg = first; arg; arg = arg->next) { - if(arg->required && !arg->value) { - fprintf(stderr, "expected value for %s\n", arg->name); - return false; - } - } - - return true; -} - -void ArgParser::printUsage(const char* exe) { - fprintf(stderr, "usage:\n%s \\\n", exe); - for(Arg* arg = first; arg; arg = arg->next) { - const char* lineEnd = arg->next ? " \\" : ""; - if(arg->required) { - fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); - } else if (arg->desc) { - fprintf(stderr, " [-%s\t%s]%s\n", arg->name, arg->desc, lineEnd); - } else { - fprintf(stderr, " [-%s]%s\n", arg->name, lineEnd); - } - } -} - char* myStrndup(const char* src, unsigned length) { diff --git a/src/util/arg-parser.cpp b/src/util/arg-parser.cpp new file mode 100644 index 0000000000..697bfd4fef --- /dev/null +++ b/src/util/arg-parser.cpp @@ -0,0 +1,94 @@ +/* Copyright (c) 2008-2012, 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 +#include + +#include "util/arg-parser.h" + +namespace avian { +namespace util { + +Arg::Arg(ArgParser& parser, bool required, const char* name, const char* desc): + next(0), + required(required), + name(name), + desc(desc), + value(0) +{ + *parser.last = this; + parser.last = &next; +} + +bool ArgParser::parse(int ac, const char** av) { + Arg* state = 0; + + for(int i = 1; i < ac; i++) { + if(state) { + if(state->value) { + fprintf(stderr, "duplicate parameter %s: '%s' and '%s'\n", state->name, state->value, av[i]); + return false; + } + state->value = av[i]; + state = 0; + } else { + if(av[i][0] != '-') { + fprintf(stderr, "expected -parameter\n"); + return false; + } + bool found = false; + for(Arg* arg = first; arg; arg = arg->next) { + if(strcmp(arg->name, &av[i][1]) == 0) { + found = true; + if (arg->desc == 0) { + arg->value = "true"; + } else { + state = arg; + } + } + } + if (not found) { + fprintf(stderr, "unrecognized parameter %s\n", av[i]); + return false; + } + } + } + + if(state) { + fprintf(stderr, "expected argument after -%s\n", state->name); + return false; + } + + for(Arg* arg = first; arg; arg = arg->next) { + if(arg->required && !arg->value) { + fprintf(stderr, "expected value for %s\n", arg->name); + return false; + } + } + + return true; +} + +void ArgParser::printUsage(const char* exe) { + fprintf(stderr, "usage:\n%s \\\n", exe); + for(Arg* arg = first; arg; arg = arg->next) { + const char* lineEnd = arg->next ? " \\" : ""; + if(arg->required) { + fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); + } else if (arg->desc) { + fprintf(stderr, " [-%s\t%s]%s\n", arg->name, arg->desc, lineEnd); + } else { + fprintf(stderr, " [-%s]%s\n", arg->name, lineEnd); + } + } +} + +} // namespace util +} // namespace avian diff --git a/src/util/arg-parser.h b/src/util/arg-parser.h new file mode 100644 index 0000000000..bba913c4d9 --- /dev/null +++ b/src/util/arg-parser.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2008-2011, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_ARG_PARSER_H +#define AVIAN_UTIL_ARG_PARSER_H + +namespace avian { +namespace util { + +class Arg; + +class ArgParser { +public: + Arg* first; + Arg** last; + + ArgParser(); + + bool parse(int ac, const char** av); + void printUsage(const char* exe); +}; + +class Arg { +public: + Arg* next; + bool required; + const char* name; + const char* desc; + + const char* value; + + Arg(ArgParser& parser, bool required, const char* name, const char* desc); +}; + + +} // namespace avian +} // namespace util + +#endif // AVIAN_UTIL_ARG_PARSER_H \ No newline at end of file From 24c0fab9bf37e77e1fdad2122783dee332c9a9ef Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 17 Feb 2013 12:10:18 -0700 Subject: [PATCH 252/378] add unit tests for arg parser --- makefile | 3 +- src/util/arg-parser.cpp | 4 ++ test/test.sh | 1 + unittest/test-harness.h | 10 +++++ unittest/util/arg-parser-test.cpp | 69 +++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 unittest/util/arg-parser-test.cpp diff --git a/makefile b/makefile index 9cbd83b65a..5d1178f77f 100755 --- a/makefile +++ b/makefile @@ -1214,6 +1214,7 @@ test-extra-dep = $(test-build)-extra.dep unittest-sources = \ $(wildcard $(unittest)/*.cpp) \ + $(wildcard $(unittest)/util/*.cpp) \ $(wildcard $(unittest)/codegen/*.cpp) unittest-depends = \ @@ -1583,7 +1584,7 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) -unittest-executable-objects = $(unittest-objects) $(vm-objects) +unittest-executable-objects = $(unittest-objects) $(vm-objects) $(build)/util/arg-parser.o ifeq ($(process),interpret) unittest-executable-objects += $(all-codegen-target-objects) diff --git a/src/util/arg-parser.cpp b/src/util/arg-parser.cpp index 697bfd4fef..30e50cadfb 100644 --- a/src/util/arg-parser.cpp +++ b/src/util/arg-parser.cpp @@ -27,6 +27,10 @@ Arg::Arg(ArgParser& parser, bool required, const char* name, const char* desc): parser.last = &next; } +ArgParser::ArgParser(): + first(0), + last(&first) {} + bool ArgParser::parse(int ac, const char** av) { Arg* state = 0; diff --git a/test/test.sh b/test/test.sh index e30e90c1cb..f5de5ff81c 100644 --- a/test/test.sh +++ b/test/test.sh @@ -20,6 +20,7 @@ printf "%12s------- Unit tests -------\n" "" ${unit_tester} 2>>${log} if [ "${?}" != "0" ]; then trouble=1 + echo "unit tests failed!" fi echo diff --git a/unittest/test-harness.h b/unittest/test-harness.h index 717cfc317f..d9a5ed81a7 100644 --- a/unittest/test-harness.h +++ b/unittest/test-harness.h @@ -11,6 +11,8 @@ #ifndef TEST_HARNESS_H #define TEST_HARNESS_H +#include + class Test { private: Test* next; @@ -53,6 +55,14 @@ protected: } runs++; } + + void assertEqual(const char* expected, const char* actual) { + if((expected == 0 && actual != 0) || (expected != 0 && actual == 0) || strcmp(expected, actual) != 0) { + fprintf(stderr, "assertion failure, expected: \"%s\", actual: \"%s\"\n", expected, actual); + failures++; + } + runs++; + } template void assertNotEqual(T expected, T actual) { diff --git a/unittest/util/arg-parser-test.cpp b/unittest/util/arg-parser-test.cpp new file mode 100644 index 0000000000..bd93a04c99 --- /dev/null +++ b/unittest/util/arg-parser-test.cpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2008-2011, 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 + +#include "common.h" + +#include "util/arg-parser.h" + +#include "test-harness.h" + +using namespace avian::util; + +class ArgParserTest : public Test { +public: + ArgParserTest(): + Test("ArgParser") + {} + + virtual void run() { + { + ArgParser parser; + Arg arg1(parser, false, "arg1", ""); + Arg required2(parser, true, "required2", ""); + const char* args[] = { + "myExecutable", + "-arg1", "myValue1", + "-required2", "myRequired2", + 0 + }; + assertTrue(parser.parse(sizeof(args) / sizeof(char*) - 1, args)); + assertEqual("myValue1", arg1.value); + assertEqual("myRequired2", required2.value); + } + + { + ArgParser parser; + Arg arg1(parser, false, "arg1", ""); + Arg required2(parser, true, "required2", ""); + const char* args[] = { + "myExecutable", + "-arg1", "myValue1", + "-required2", + 0 + }; + assertFalse(parser.parse(sizeof(args) / sizeof(char*) - 1, args)); + } + + { + ArgParser parser; + Arg arg1(parser, false, "arg1", ""); + Arg required2(parser, true, "required2", ""); + const char* args[] = { + "myExecutable", + "-arg1", "myValue1", + 0 + }; + assertFalse(parser.parse(sizeof(args) / sizeof(char*) - 1, args)); + } + } +} argParserTest; \ No newline at end of file From 46029939d375ae1605bcae2fae2da90c89db220c Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 18 Feb 2013 07:50:37 -0700 Subject: [PATCH 253/378] begin work on audit-codegen --- makefile | 92 ++++++++++++++++++++------------ src/tools/audit-codegen/main.cpp | 63 ++++++++++++++++++++++ src/util/arg-parser.cpp | 2 +- src/util/arg-parser.h | 2 +- 4 files changed, 123 insertions(+), 36 deletions(-) create mode 100644 src/tools/audit-codegen/main.cpp diff --git a/makefile b/makefile index 5d1178f77f..bed84761d5 100755 --- a/makefile +++ b/makefile @@ -994,6 +994,8 @@ all-assembler-sources = \ native-assembler-sources = $($(target-asm)-assembler-sources) native-assembler-objects = $($(target-asm)-assembler-objects) +audit-codegen-sources = $(wildcard $(src)/tools/audit-codegen/*.cpp) + all-codegen-target-sources = \ $(compiler-sources) \ $(native-assembler-sources) @@ -1154,6 +1156,7 @@ dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) executable-dynamic = $(build)/$(name)-dynamic$(exe-suffix) unittest-executable = $(build)/$(name)-unittest${exe-suffix} +audit-codegen-executable = $(build)/audit-codegen${exe-suffix} ifneq ($(classpath),avian) # Assembler, ConstantPool, and Stream are not technically needed for a @@ -1304,6 +1307,14 @@ else ssh -p$(remote-test-port) $(remote-test-user)@$(remote-test-host) sh "$(remote-test-dir)/$(platform)-$(arch)$(options)/run-tests.sh" endif +PHONY: audit-baseline +audit-baseline: $(audit-codegen-executable) + $(<) -output $(build)/codegen-audit-output/baseline.o -format macho + +PHONY: audit +audit: $(audit-codegen-executable) + $(<) -output $(build)/codegen-audit-output/baseline.o -format macho + .PHONY: tarball tarball: @echo "creating build/avian-$(version).tar.bz2" @@ -1412,6 +1423,9 @@ endif $(unittest-objects): $(build)/unittest/%.o: $(unittest)/%.cpp $(vm-depends) $(unittest-depends) $(compile-unittest-object) +$(build)/tools/audit-codegen/main.o: $(build)/%.o: $(src)/%.cpp $(vm-depends) + $(compile-object) + $(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) $(compile-object) @@ -1590,43 +1604,53 @@ ifeq ($(process),interpret) unittest-executable-objects += $(all-codegen-target-objects) endif -$(executable): $(executable-objects) - @echo "linking $(@)" -ifeq ($(platform),windows) -ifdef ms_cl_compiler - $(ld) $(lflags) $(executable-objects) -out:$(@) \ - -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) -ifdef mt - $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" -endif -else - $(dlltool) -z $(@).def $(executable-objects) - $(dlltool) -d $(@).def -e $(@).exp - $(ld) $(@).exp $(executable-objects) $(lflags) -o $(@) -endif -else - $(ld) $(executable-objects) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@) -endif - $(strip) $(strip-all) $(@) +audit-codegen-objects = $(call cpp-objects,$(audit-codegen-sources),$(src),$(build)) +audit-codegen-executable-objects = $(audit-codegen-objects) $(vm-objects) $(build)/util/arg-parser.o +.PHONY: print +print: + @echo $(audit-codegen-objects) + +# apparently, make does poorly with ifs inside of defines, and indented defines. +# I suggest re-indenting the following before making edits (and unindenting afterwards): +ifneq ($(platform),windows) +define link-executable + @echo linking $(@) + $(ld) $(^) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@) +endef +else +ifdef ms_cl_compiler +ifdef mt +define link-executable + @echo linking $(@) + $(ld) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endef +else +define link-executable + @echo linking $(@) + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endef +endif +else +define link-executable + @echo linking $(@) + $(dlltool) -z $(@).def $(^) + $(dlltool) -d $(@).def -e $(@).exp + $(ld) $(@).exp $(^) $(lflags) -o $(@) +endef +endif +endif + +$(executable): $(executable-objects) + $(link-executable) $(unittest-executable): $(unittest-executable-objects) - @echo "linking $(@)" -ifeq ($(platform),windows) -ifdef ms_cl_compiler - $(ld) $(lflags) $(unittest-executable-objects) -out:$(@) \ - -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) -ifdef mt - $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" -endif -else - $(dlltool) -z $(@).def $(unittest-executable-objects) - $(dlltool) -d $(@).def -e $(@).exp - $(ld) $(@).exp $(unittest-executable-objects) $(lflags) -o $(@) -endif -else - $(ld) $(unittest-executable-objects) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@) -endif + $(link-executable) + +$(audit-codegen-executable): $(audit-codegen-executable-objects) + $(link-executable) $(bootimage-generator): $(bootimage-generator-objects) echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform) diff --git a/src/tools/audit-codegen/main.cpp b/src/tools/audit-codegen/main.cpp new file mode 100644 index 0000000000..9fc8d10119 --- /dev/null +++ b/src/tools/audit-codegen/main.cpp @@ -0,0 +1,63 @@ +/* Copyright (c) 2008-2012, 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 "system.h" + +#include "util/arg-parser.h" + +#include "codegen/lir.h" +#include "codegen/assembler.h" +#include "codegen/targets.h" + +// since we aren't linking against libstdc++, we must implement this +// ourselves: +extern "C" void __cxa_pure_virtual(void) { abort(); } + +using namespace avian::codegen; +using namespace avian::util; + +void generateCode(Assembler::Architecture* arch) { + for() +} + +class Arguments { +public: + const char* output; + const char* outputFormat; + + Arguments(int argc, char** argv) { + ArgParser parser; + Arg out(parser, true, "output", ""); + Arg format(parser, true, "format", ""); + + if(!parser.parse(argc, argv)) { + exit(1); + } + + output = out.value; + outputFormat = format.value; + + // TODO: sanitize format values + } +}; + +int main(int argc, char** argv) { + Arguments args(argc, argv); + + vm::System* s = vm::makeSystem(0); + Assembler::Architecture* arch = makeArchitectureNative(s, true); + arch->acquire(); + + generateCode(arch); + + arch->release(); + s->dispose(); + return 0; +} \ No newline at end of file diff --git a/src/util/arg-parser.cpp b/src/util/arg-parser.cpp index 30e50cadfb..ac652563be 100644 --- a/src/util/arg-parser.cpp +++ b/src/util/arg-parser.cpp @@ -31,7 +31,7 @@ ArgParser::ArgParser(): first(0), last(&first) {} -bool ArgParser::parse(int ac, const char** av) { +bool ArgParser::parse(int ac, const char* const* av) { Arg* state = 0; for(int i = 1; i < ac; i++) { diff --git a/src/util/arg-parser.h b/src/util/arg-parser.h index bba913c4d9..1f887764f2 100644 --- a/src/util/arg-parser.h +++ b/src/util/arg-parser.h @@ -23,7 +23,7 @@ public: ArgParser(); - bool parse(int ac, const char** av); + bool parse(int ac, const char* const* av); void printUsage(const char* exe); }; From 0f524fcf16ba999cb31f20f8fe14c70346dc6681 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 19 Feb 2013 09:36:19 -0700 Subject: [PATCH 254/378] first pass at Android classpath support Stuff compiles, but linking breaks spectacularly. Next step is to figure out how to build the dependencies without checking out and building the entire Android platform. --- makefile | 66 ++++++++++++++- src/classpath-android.cpp | 172 ++++++++++++++++++++++++++++++++++++++ src/types.def | 8 +- 3 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 src/classpath-android.cpp diff --git a/makefile b/makefile index 1e29f0ca91..1d9ade13f4 100755 --- a/makefile +++ b/makefile @@ -148,6 +148,41 @@ ifneq ($(openjdk),) build-javahome = $(openjdk)/jre endif +ifneq ($(android),) + options := $(options)-android + classpath-jar-dep = $(build)/android.dep + luni-native = $(android)/libcore/luni/src/main/native + android-cflags := -I$(luni-native) \ + -I$(android)/libnativehelper/include/nativehelper \ + -I$(android)/core/include \ + -I$(android)/zlib \ + -I$(android)/icu4c/i18n \ + -I$(android)/icu4c/common \ + -I$(android)/expat \ + -I$(android)/openssl/include \ + -I$(android)/libcore/include \ + -I$(build)/android-src/external/fdlibm \ + -I$(build)/android-src \ + -fpermissive \ + -fno-exceptions \ + -DHAVE_SYS_UIO_H \ + -D_FILE_OFFSET_BITS=64 + luni-cpps := $(shell find $(luni-native) -name '*.cpp') + classpath-objects = \ + $(call cpp-objects,$(luni-cpps),$(luni-native),$(build)) + luni-java = $(android)/libcore/luni/src/main/java + luni-javas := $(shell find $(luni-java) -name '*.java') + dalvik-java = $(android)/libcore/dalvik/src/main/java + dalvik-javas := $(shell find $(dalvik-java) -name '*.java') + xml-java = $(android)/libcore/xml/src/main/java + xml-javas := $(shell find $(xml-java) -name '*.java') + android-classes = \ + $(call java-classes,$(luni-javas),$(luni-java),$(build)/android) \ + $(call java-classes,$(dalvik-javas),$(dalvik-java),$(build)/android) \ + $(call java-classes,$(xml-javas),$(xml-java),$(build)/android) + classpath = android +endif + ifeq ($(classpath),avian) jni-sources := $(shell find $(classpath-src) -name '*.cpp') jni-objects = $(call cpp-objects,$(jni-sources),$(classpath-src),$(build)) @@ -1178,6 +1213,11 @@ ifneq ($(classpath),avian) ifneq ($(openjdk),) classpath-sources := $(classpath-sources) \ $(classpath-src)/avian/OpenJDK.java + else + classpath-sources := $(classpath-sources) \ + $(classpath-src)/sun/reflect/ConstantPool.java \ + $(classpath-src)/java/lang/ReflectiveOperationException.java \ + $(classpath-src)/sun/misc/Cleaner.java endif else classpath-sources := $(shell find $(classpath-src) -name '*.java') @@ -1346,7 +1386,7 @@ $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) $(classpath-build)/%.class: $(classpath-src)/%.java @echo $(<) -$(classpath-dep): $(classpath-sources) +$(classpath-dep): $(classpath-sources) $(classpath-jar-dep) @echo "compiling classpath classes" @mkdir -p $(classpath-build) $(javac) -d $(classpath-build) -bootclasspath $(boot-classpath) \ @@ -1354,6 +1394,28 @@ $(classpath-dep): $(classpath-sources) $(classpath-classes)) @touch $(@) +$(build)/%.o: $(luni-native)/%.cpp $(build)/android.dep + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(android-cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) + +$(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas) + @echo "compiling luni classes" + @mkdir -p $(classpath-build) + @mkdir -p $(build)/android + @mkdir -p $(build)/android-src/external/fdlibm + @mkdir -p $(build)/android-src/libexpat + cp $(android)/fdlibm/fdlibm.h $(build)/android-src/external/fdlibm/ + cp $(android)/expat/lib/expat.h $(build)/android-src/libexpat/ + cp -a $(luni-java)/* $(dalvik-java)/* $(xml-java)/* $(build)/android-src/ + sed -i 's/return ordinal - o.ordinal;/return ordinal - o.ordinal();/' \ + $(build)/android-src/java/lang/Enum.java + find $(build)/android-src -name '*.java' > $(build)/android.txt + $(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \ + @$(build)/android.txt + cp -r $(build)/android/* $(classpath-build) + @touch $(@) + $(test-build)/%.class: $(test)/%.java @echo $(<) @@ -1568,7 +1630,7 @@ else endif $(bootimage-object) $(codeimage-object): $(bootimage-generator) \ - $(openjdk-jar-dep) + $(classpath-jar-dep) @echo "generating bootimage and codeimage binaries from $(classpath-build) using $(<)" $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ -bootimage-symbols $(bootimage-symbols) \ diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp new file mode 100644 index 0000000000..3fe5996aec --- /dev/null +++ b/src/classpath-android.cpp @@ -0,0 +1,172 @@ +/* Copyright (c) 2010-2012, 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 "machine.h" +#include "classpath-common.h" +#include "process.h" + +#include "util/runtime-array.h" + +using namespace vm; + +namespace { + +namespace local { + +class MyClasspath : public Classpath { + public: + MyClasspath(Allocator* allocator): + allocator(allocator) + { } + + virtual object + makeJclass(Thread* t, object class_) + { + PROTECT(t, class_); + + object c = allocate(t, FixedSizeOfJclass, true); + setObjectClass(t, c, type(t, Machine::JclassType)); + set(t, c, JclassVmClass, class_); + + return c; + } + + virtual object + makeString(Thread* t, object array, int32_t offset, int32_t length) + { + if (objectClass(t, array) == type(t, Machine::ByteArrayType)) { + PROTECT(t, array); + + object charArray = makeCharArray(t, length); + for (int i = 0; i < length; ++i) { + expect(t, (byteArrayBody(t, array, offset + i) & 0x80) == 0); + + charArrayBody(t, charArray, i) = byteArrayBody(t, array, offset + i); + } + + array = charArray; + } else { + expect(t, objectClass(t, array) == type(t, Machine::CharArrayType)); + } + + return vm::makeString(t, array, offset, length, 0); + } + + virtual object + makeThread(Thread* t, Thread* parent) + { + const unsigned MaxPriority = 10; + const unsigned NormalPriority = 5; + + object group; + if (parent) { + group = threadGroup(t, parent->javaThread); + } else { + group = allocate(t, FixedSizeOfThreadGroup, true); + setObjectClass(t, group, type(t, Machine::ThreadGroupType)); + threadGroupMaxPriority(t, group) = MaxPriority; + } + + PROTECT(t, group); + object thread = allocate(t, FixedSizeOfThread, true); + setObjectClass(t, thread, type(t, Machine::ThreadType)); + threadPriority(t, thread) = NormalPriority; + threadGroup(t, thread) = group; + + return thread; + } + + virtual object + makeJMethod(Thread* t, object) + { + abort(t); // todo + } + + virtual object + getVMMethod(Thread* t, object) + { + abort(t); // todo + } + + virtual object + makeJField(Thread* t, object) + { + abort(t); // todo + } + + virtual object + getVMField(Thread* t, object) + { + abort(t); // todo + } + + virtual void + clearInterrupted(Thread*) + { + // ignore + } + + virtual void + runThread(Thread* t) + { + object method = resolveMethod + (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", + "(Ljava/lang/Thread;)V"); + + t->m->processor->invoke(t, method, 0, t->javaThread); + } + + virtual void + resolveNative(Thread* t, object method) + { + vm::resolveNative(t, method); + } + + virtual void + boot(Thread*) + { + // ignore + } + + virtual const char* + bootClasspath() + { + return AVIAN_CLASSPATH; + } + + virtual void + updatePackageMap(Thread*, object) + { + // ignore + } + + virtual void + dispose() + { + allocator->free(this, sizeof(*this)); + } + + Allocator* allocator; +}; + +} // namespace local + +} // namespace + +namespace vm { + +Classpath* +makeClasspath(System*, Allocator* allocator, const char*, const char*) +{ + return new (allocator->allocate(sizeof(local::MyClasspath))) + local::MyClasspath(allocator); +} + +} // namespace vm diff --git a/src/types.def b/src/types.def index 31d96404a8..36f345e4c4 100644 --- a/src/types.def +++ b/src/types.def @@ -188,7 +188,8 @@ (require object interruptLock) (require uint8_t interrupted) (require uint8_t unparked) - (alias peer uint64_t eetop)) + (alias peer uint64_t eetop) + (require uint64_t peer)) (type threadGroup java/lang/ThreadGroup) @@ -196,7 +197,8 @@ (type throwable java/lang/Throwable (alias message object detailMessage) - (alias trace object backtrace)) + (alias trace object backtrace) + (alias trace object stackState)) (type exception java/lang/Exception) @@ -286,7 +288,9 @@ (alias target object referent) (alias queue object queue) (alias jNext object next) + (alias jNext object queueNext) (alias vmNext object discovered) + (alias vmNext object pendingNext) (nogc object target) (nogc object queue) (nogc object vmNext)) From f45b95e1b556943fc5cbb81de0a367f9e88d1c21 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 19 Feb 2013 16:48:33 -0700 Subject: [PATCH 255/378] progress towards Android classpath support It now builds and links, but fails at runtime because register_libcore_icu_ICU can't find the file it wants. We'll probably need to replace register_libcore_icu_ICU with a better-behaved version. --- makefile | 19 +++++- src/classpath-android.cpp | 133 +++++++++++++++++++++++++++++++++++++- src/jnienv.cpp | 2 +- 3 files changed, 148 insertions(+), 6 deletions(-) diff --git a/makefile b/makefile index 1d9ade13f4..a50fc6cb53 100755 --- a/makefile +++ b/makefile @@ -166,7 +166,16 @@ ifneq ($(android),) -fpermissive \ -fno-exceptions \ -DHAVE_SYS_UIO_H \ - -D_FILE_OFFSET_BITS=64 + -D_FILE_OFFSET_BITS=64 \ + -g3 + classpath-lflags := $(android)/icu4c/lib/libicuuc.a \ + $(android)/icu4c/lib/libicui18n.a \ + $(android)/icu4c/lib/libicudata.a \ + $(android)/fdlibm/libfdm.a \ + $(android)/expat/.libs/libexpat.a \ + $(android)/openssl-1.0.1e/libssl.a \ + $(android)/openssl-1.0.1e/libcrypto.a \ + -lstdc++ luni-cpps := $(shell find $(luni-native) -name '*.cpp') classpath-objects = \ $(call cpp-objects,$(luni-cpps),$(luni-native),$(build)) @@ -279,7 +288,7 @@ common-lflags = -lm -lz $(classpath-lflags) build-lflags = -lz -lpthread -ldl -lflags = $(common-lflags) -lpthread -ldl +lflags = $(common-lflags) $(classpath-lflags) -lpthread -ldl soname-flag = -Wl,-soname -Wl,$(so-prefix)jvm$(so-suffix) version-script-flag = -Wl,--version-script=openjdk.ld @@ -1217,7 +1226,10 @@ ifneq ($(classpath),avian) classpath-sources := $(classpath-sources) \ $(classpath-src)/sun/reflect/ConstantPool.java \ $(classpath-src)/java/lang/ReflectiveOperationException.java \ - $(classpath-src)/sun/misc/Cleaner.java + $(classpath-src)/java/net/ProtocolFamily.java \ + $(classpath-src)/java/net/StandardProtocolFamily.java \ + $(classpath-src)/sun/misc/Cleaner.java \ + $(classpath-src)/sun/misc/Unsafe.java endif else classpath-sources := $(shell find $(classpath-src) -name '*.java') @@ -1413,6 +1425,7 @@ $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas) find $(build)/android-src -name '*.java' > $(build)/android.txt $(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \ @$(build)/android.txt + rm $(build)/android/sun/misc/Unsafe* cp -r $(build)/android/* $(classpath-build) @touch $(@) diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 3fe5996aec..d50be47057 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -8,6 +8,12 @@ There is NO WARRANTY for this software. See license.txt for details. */ +struct JavaVM; + +extern "C" int JNI_OnLoad(JavaVM*, void*); + +#define _POSIX_C_SOURCE 200112L +#undef _GNU_SOURCE #include "machine.h" #include "classpath-common.h" #include "process.h" @@ -130,9 +136,9 @@ class MyClasspath : public Classpath { } virtual void - boot(Thread*) + boot(Thread* t) { - // ignore + JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); } virtual const char* @@ -170,3 +176,126 @@ makeClasspath(System*, Allocator* allocator, const char*, const char*) } } // namespace vm + +extern "C" int +jniRegisterNativeMethods(JNIEnv* e, const char* className, + const JNINativeMethod* methods, int methodCount) +{ + jclass c = e->vtable->FindClass(e, className); + + if (c) { + e->vtable->RegisterNatives(e, c, methods, methodCount); + } + + return 0; +} + +extern "C" void +jniLogException(JNIEnv*, int, const char*, jthrowable) +{ + // ignore +} + +extern "C" int +jniThrowException(JNIEnv* e, const char* className, const char* message) +{ + jclass c = e->vtable->FindClass(e, className); + + if (c) { + e->vtable->ThrowNew(e, c, message); + } + + return 0; +} + +extern "C" int +jniThrowExceptionFmt(JNIEnv* e, const char* className, const char* format, + va_list args) +{ + const unsigned size = 4096; + char buffer[size]; + ::vsnprintf(buffer, size, format, args); + return jniThrowException(e, className, buffer); +} + +extern "C" int +jniThrowNullPointerException(JNIEnv* e, const char* message) +{ + return jniThrowException(e, "java/lang/NullPointerException", message); +} + +extern "C" int +jniThrowRuntimeException(JNIEnv* e, const char* message) +{ + return jniThrowException(e, "java/lang/RuntimeException", message); +} + +extern "C" int +jniThrowIOException(JNIEnv* e, const char* message) +{ + return jniThrowException(e, "java/lang/IOException", message); +} + +extern "C" const char* +jniStrError(int error, char* buffer, size_t length) +{ + if (static_cast(strerror_r(error, buffer, length)) == 0) { + return buffer; + } else { + return 0; + } +} + +extern "C" int +__android_log_print(int priority, const char* tag, const char* format, ...) +{ + va_list a; + const unsigned size = 4096; + char buffer[size]; + + va_start(a, format); + ::vsnprintf(buffer, size, format, a); + va_end(a); + + return fprintf(stderr, "%d %s %s\n", priority, tag, buffer); +} + +extern "C" int +jniGetFDFromFileDescriptor(JNIEnv* e, jobject descriptor) +{ + return e->vtable->GetIntField + (e, descriptor, e->vtable->GetFieldID + (e, e->vtable->FindClass + (e, "java/io/FileDescriptor"), "descriptor", "I")); +} + +extern "C" void +jniSetFileDescriptorOfFD(JNIEnv* e, jobject descriptor, int value) +{ + e->vtable->SetIntField + (e, descriptor, e->vtable->GetFieldID + (e, e->vtable->FindClass + (e, "java/io/FileDescriptor"), "descriptor", "I"), value); +} + +extern "C" jobject +jniCreateFileDescriptor(JNIEnv* e, int fd) +{ + jobject descriptor = e->vtable->NewObject + (e, e->vtable->FindClass(e, "java/io/FileDescriptor"), + e->vtable->GetMethodID + (e, e->vtable->FindClass(e, "java/io/FileDescriptor"), "", "()V")); + + jniSetFileDescriptorOfFD(e, descriptor, fd); + + return descriptor; +} + +extern "C" struct _JNIEnv; + +int +register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) +{ + // ignore + return 0; +} diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 37d3a65f13..12fd3d9fbc 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -104,7 +104,7 @@ GetEnv(Machine* m, Thread** t, jint version) { *t = static_cast(m->localThread->get()); if (*t) { - if (version <= JNI_VERSION_1_4) { + if (version <= JNI_VERSION_1_6) { return JNI_OK; } else { return JNI_EVERSION; From 77365dfcc14b6cdf2def0813c83e757aab68cb24 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 19 Feb 2013 20:23:11 -0700 Subject: [PATCH 256/378] move binary-to-object to new tree structure --- .../avian/tools/object-writer}/tools.h | 0 makefile | 29 ++++++++++--------- src/bootimage.cpp | 2 +- .../binary-to-object}/main.cpp | 2 +- .../object-writer}/elf.cpp | 2 +- .../object-writer}/endianness.h | 0 .../object-writer}/mach-o.cpp | 2 +- .../object-writer}/pe.cpp | 2 +- .../object-writer}/tools.cpp | 2 +- 9 files changed, 22 insertions(+), 19 deletions(-) rename {src/binaryToObject => include/avian/tools/object-writer}/tools.h (100%) rename src/{binaryToObject => tools/binary-to-object}/main.cpp (98%) rename src/{binaryToObject => tools/object-writer}/elf.cpp (99%) rename src/{binaryToObject => tools/object-writer}/endianness.h (100%) rename src/{binaryToObject => tools/object-writer}/mach-o.cpp (99%) rename src/{binaryToObject => tools/object-writer}/pe.cpp (99%) rename src/{binaryToObject => tools/object-writer}/tools.cpp (98%) diff --git a/src/binaryToObject/tools.h b/include/avian/tools/object-writer/tools.h similarity index 100% rename from src/binaryToObject/tools.h rename to include/avian/tools/object-writer/tools.h diff --git a/makefile b/makefile index 1e29f0ca91..38872186bf 100755 --- a/makefile +++ b/makefile @@ -214,7 +214,7 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \ target-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) common-cflags = $(warnings) -fno-rtti -fno-exceptions -I$(classpath-src) \ - "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) $(classpath-cflags) \ + "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) -Iinclude $(classpath-cflags) \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ -DAVIAN_INFO="\"$(info)\"" \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ @@ -232,7 +232,7 @@ endif build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread -converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject -Isrc/ \ +converter-cflags = -D__STDC_CONSTANT_MACROS -Iinclude/ -Isrc/ \ -fno-rtti -fno-exceptions \ -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ -DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_UNKNOWN \ @@ -1126,18 +1126,20 @@ generator-lzma-objects = \ $(call generator-c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) generator = $(build)/generator -converter-depends = \ - $(src)/binaryToObject/tools.h \ - $(src)/binaryToObject/endianness.h +all-depends = $(shell find include -name '*.h') -converter-sources = \ - $(src)/binaryToObject/tools.cpp \ - $(src)/binaryToObject/elf.cpp \ - $(src)/binaryToObject/mach-o.cpp \ - $(src)/binaryToObject/pe.cpp +object-writer-depends = $(shell find $(src)/tools/object-writer -name '*.h') +object-writer-sources = $(shell find $(src)/tools/object-writer -name '*.cpp') +object-writer-objects = $(call cpp-objects,$(object-writer-sources),$(src),$(build)) -converter-tool-sources = \ - $(src)/binaryToObject/main.cpp +binary-to-object-depends = $(shell find $(src)/tools/binary-to-object/ -name '*.h') +binary-to-object-sources = $(shell find $(src)/tools/binary-to-object/ -name '*.cpp') +binary-to-object-objects = $(call cpp-objects,$(binary-to-object-sources),$(src),$(build)) + +converter-sources = $(object-writer-sources) + +converter-tool-depends = $(binary-to-object-depends) $(all-depends) +converter-tool-sources = $(binary-to-object-sources) converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) @@ -1497,11 +1499,12 @@ $(boot-object): $(boot-source) $(boot-javahome-object): $(src)/boot-javahome.cpp $(compile-object) -$(converter-objects) $(converter-tool-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends) +$(object-writer-objects) $(binary-to-object-objects): $(build)/%.o: $(src)/%.cpp $(binary-to-object-depends) $(object-writer-depends) $(all-depends) @mkdir -p $(dir $(@)) $(build-cxx) $(converter-cflags) -c $(<) -o $(@) $(converter): $(converter-objects) $(converter-tool-objects) + @mkdir -p $(dir $(@)) $(build-cc) $(^) -g -o $(@) $(lzma-encoder-objects): $(build)/lzma/%.o: $(src)/lzma/%.cpp diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 0dba4af877..05fef8158d 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -17,7 +17,7 @@ #include "codegen/assembler.h" #include "codegen/promise.h" #include "target.h" -#include "binaryToObject/tools.h" +#include #include "lzma.h" // since we aren't linking against libstdc++, we must implement this diff --git a/src/binaryToObject/main.cpp b/src/tools/binary-to-object/main.cpp similarity index 98% rename from src/binaryToObject/main.cpp rename to src/tools/binary-to-object/main.cpp index fe389f3d29..86d780bbec 100644 --- a/src/binaryToObject/main.cpp +++ b/src/tools/binary-to-object/main.cpp @@ -22,7 +22,7 @@ #endif #include -#include "tools.h" +#include extern "C" void __cxa_pure_virtual() { diff --git a/src/binaryToObject/elf.cpp b/src/tools/object-writer/elf.cpp similarity index 99% rename from src/binaryToObject/elf.cpp rename to src/tools/object-writer/elf.cpp index a2277c3488..bf220e1e04 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/tools/object-writer/elf.cpp @@ -15,7 +15,7 @@ #include "endianness.h" -#include "tools.h" +#include #define EI_NIDENT 16 diff --git a/src/binaryToObject/endianness.h b/src/tools/object-writer/endianness.h similarity index 100% rename from src/binaryToObject/endianness.h rename to src/tools/object-writer/endianness.h diff --git a/src/binaryToObject/mach-o.cpp b/src/tools/object-writer/mach-o.cpp similarity index 99% rename from src/binaryToObject/mach-o.cpp rename to src/tools/object-writer/mach-o.cpp index 96dd63aafd..fac134f272 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/tools/object-writer/mach-o.cpp @@ -14,7 +14,7 @@ #include "endianness.h" -#include "tools.h" +#include #define MH_MAGIC_64 0xfeedfacf #define MH_MAGIC 0xfeedface diff --git a/src/binaryToObject/pe.cpp b/src/tools/object-writer/pe.cpp similarity index 99% rename from src/binaryToObject/pe.cpp rename to src/tools/object-writer/pe.cpp index 186e491447..0fdc4a16e0 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/tools/object-writer/pe.cpp @@ -13,7 +13,7 @@ #include #include -#include "tools.h" +#include namespace { diff --git a/src/binaryToObject/tools.cpp b/src/tools/object-writer/tools.cpp similarity index 98% rename from src/binaryToObject/tools.cpp rename to src/tools/object-writer/tools.cpp index 9cc9059b93..49726245c7 100644 --- a/src/binaryToObject/tools.cpp +++ b/src/tools/object-writer/tools.cpp @@ -13,7 +13,7 @@ #include #include -#include "tools.h" +#include namespace avian { From 987af120d81d7763d9fdd929a5fe5046b2f51c68 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 19 Feb 2013 22:12:28 -0700 Subject: [PATCH 257/378] move codegen headers to include/ --- {src => include/avian/vm}/codegen/assembler.h | 4 ++-- {src => include/avian/vm}/codegen/compiler.h | 0 {src => include/avian/vm}/codegen/lir-ops.inc.cpp | 0 {src => include/avian/vm}/codegen/lir.h | 0 {src => include/avian/vm}/codegen/promise.h | 0 {src => include/avian/vm}/codegen/registers.h | 0 {src => include/avian/vm}/codegen/targets.h | 2 +- src/codegen/arm/assembler.cpp | 4 ++-- src/codegen/compiler.cpp | 6 +++--- src/codegen/compiler/context.h | 4 ++-- src/codegen/compiler/regalloc.h | 4 ++-- src/codegen/compiler/value.h | 5 ++--- src/codegen/powerpc/assembler.cpp | 4 ++-- src/codegen/registers.cpp | 2 +- src/codegen/targets.cpp | 3 ++- src/codegen/x86/assembler.cpp | 4 ++-- src/compile.cpp | 7 ++++--- unittest/codegen/assembler-test.cpp | 6 +++--- 18 files changed, 28 insertions(+), 27 deletions(-) rename {src => include/avian/vm}/codegen/assembler.h (98%) rename {src => include/avian/vm}/codegen/compiler.h (100%) rename {src => include/avian/vm}/codegen/lir-ops.inc.cpp (100%) rename {src => include/avian/vm}/codegen/lir.h (100%) rename {src => include/avian/vm}/codegen/promise.h (100%) rename {src => include/avian/vm}/codegen/registers.h (100%) rename {src => include/avian/vm}/codegen/targets.h (95%) diff --git a/src/codegen/assembler.h b/include/avian/vm/codegen/assembler.h similarity index 98% rename from src/codegen/assembler.h rename to include/avian/vm/codegen/assembler.h index 21301fd71f..593e0e6fe7 100644 --- a/src/codegen/assembler.h +++ b/include/avian/vm/codegen/assembler.h @@ -14,8 +14,8 @@ #include "system.h" #include "zone.h" -#include "codegen/lir.h" -#include "codegen/promise.h" +#include +#include namespace avian { namespace codegen { diff --git a/src/codegen/compiler.h b/include/avian/vm/codegen/compiler.h similarity index 100% rename from src/codegen/compiler.h rename to include/avian/vm/codegen/compiler.h diff --git a/src/codegen/lir-ops.inc.cpp b/include/avian/vm/codegen/lir-ops.inc.cpp similarity index 100% rename from src/codegen/lir-ops.inc.cpp rename to include/avian/vm/codegen/lir-ops.inc.cpp diff --git a/src/codegen/lir.h b/include/avian/vm/codegen/lir.h similarity index 100% rename from src/codegen/lir.h rename to include/avian/vm/codegen/lir.h diff --git a/src/codegen/promise.h b/include/avian/vm/codegen/promise.h similarity index 100% rename from src/codegen/promise.h rename to include/avian/vm/codegen/promise.h diff --git a/src/codegen/registers.h b/include/avian/vm/codegen/registers.h similarity index 100% rename from src/codegen/registers.h rename to include/avian/vm/codegen/registers.h diff --git a/src/codegen/targets.h b/include/avian/vm/codegen/targets.h similarity index 95% rename from src/codegen/targets.h rename to include/avian/vm/codegen/targets.h index 1d146e4b4d..e3ffbd981a 100644 --- a/src/codegen/targets.h +++ b/include/avian/vm/codegen/targets.h @@ -11,7 +11,7 @@ #ifndef AVIAN_CODEGEN_TARGETS_H #define AVIAN_CODEGEN_TARGETS_H -#include "codegen/assembler.h" +#include namespace avian { namespace codegen { diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index c15007835f..2298fb50d6 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/assembler.h" -#include "codegen/registers.h" +#include +#include #include "alloc-vector.h" #include "util/abort.h" diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 23c62a8b5e..d67b979406 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -12,9 +12,9 @@ #include "util/runtime-array.h" -#include "codegen/compiler.h" -#include "codegen/assembler.h" -#include "codegen/promise.h" +#include +#include +#include #include "codegen/compiler/regalloc.h" #include "codegen/compiler/context.h" diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index 974de8e17a..58118b57dc 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -11,8 +11,8 @@ #ifndef AVIAN_CODEGEN_COMPILER_CONTEXT_H #define AVIAN_CODEGEN_COMPILER_CONTEXT_H -#include "codegen/assembler.h" -#include "codegen/compiler.h" +#include +#include #include "codegen/compiler/regalloc.h" diff --git a/src/codegen/compiler/regalloc.h b/src/codegen/compiler/regalloc.h index cfbf154f1f..c121614799 100644 --- a/src/codegen/compiler/regalloc.h +++ b/src/codegen/compiler/regalloc.h @@ -13,8 +13,8 @@ #include "common.h" -#include "codegen/lir.h" -#include "codegen/registers.h" +#include +#include class Aborter; diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index 9cdac0bba3..60fe0461a3 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -11,9 +11,8 @@ #ifndef AVIAN_CODEGEN_COMPILER_VALUE_H #define AVIAN_CODEGEN_COMPILER_VALUE_H -#include "codegen/lir.h" - -#include "codegen/compiler.h" +#include +#include namespace avian { namespace codegen { diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 426891d475..f45819d869 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/assembler.h" -#include "codegen/registers.h" +#include +#include #include "alloc-vector.h" #include "util/abort.h" diff --git a/src/codegen/registers.cpp b/src/codegen/registers.cpp index 6e8dea822a..c3bf451176 100644 --- a/src/codegen/registers.cpp +++ b/src/codegen/registers.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/registers.h" +#include namespace avian { namespace codegen { diff --git a/src/codegen/targets.cpp b/src/codegen/targets.cpp index 2df6636120..4b9d44fc7e 100644 --- a/src/codegen/targets.cpp +++ b/src/codegen/targets.cpp @@ -8,7 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/targets.h" +#include + #include "environment.h" namespace avian { diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 5e3fa6aa3c..9c19bc2544 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -12,8 +12,8 @@ #include "target.h" #include "alloc-vector.h" -#include "codegen/assembler.h" -#include "codegen/registers.h" +#include +#include #include "util/runtime-array.h" #include "util/abort.h" diff --git a/src/compile.cpp b/src/compile.cpp index 5b9245df15..63ff48ec94 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -13,11 +13,12 @@ #include "alloc-vector.h" #include "process.h" #include "target.h" -#include "codegen/assembler.h" -#include "codegen/compiler.h" -#include "codegen/targets.h" #include "arch.h" +#include +#include +#include + #include "util/runtime-array.h" using namespace vm; diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp index 3fe8a07427..760e770bd8 100644 --- a/unittest/codegen/assembler-test.cpp +++ b/unittest/codegen/assembler-test.cpp @@ -15,9 +15,9 @@ #include "system.h" #include "target.h" -#include "codegen/assembler.h" -#include "codegen/targets.h" -#include "codegen/lir.h" +#include +#include +#include #include "test-harness.h" From 263c0dee4f427e6bf97dbaf140deb3b12bbb6908 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 19 Feb 2013 22:42:07 -0700 Subject: [PATCH 258/378] move abort.h to include, add namespacing --- {src => include/avian}/util/abort.h | 8 +++++++- src/codegen/arm/assembler.cpp | 3 ++- src/codegen/compiler/context.h | 4 +++- src/codegen/compiler/regalloc.h | 9 +++++++-- src/codegen/powerpc/assembler.cpp | 3 ++- src/codegen/x86/assembler.cpp | 3 ++- src/heap/heap.cpp | 1 + src/machine.h | 2 ++ src/system.h | 6 +++--- 9 files changed, 29 insertions(+), 10 deletions(-) rename {src => include/avian}/util/abort.h (87%) diff --git a/src/util/abort.h b/include/avian/util/abort.h similarity index 87% rename from src/util/abort.h rename to include/avian/util/abort.h index 7624ea5b8f..d209479b97 100644 --- a/src/util/abort.h +++ b/include/avian/util/abort.h @@ -11,6 +11,9 @@ #ifndef AVIAN_UTIL_ABORT_H #define AVIAN_UTIL_ABORT_H +namespace avian { +namespace util { + class Aborter { public: virtual void NO_RETURN abort() = 0; @@ -37,5 +40,8 @@ inline void assert(T t, bool v) { expect(t, v); } #endif + +} // namespace util +} // namespace avian -#endif // AVIAN_UTIL_ABORT_H \ No newline at end of file +#endif // AVIAN_UTIL_ABORT_H diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index 2298fb50d6..119cc2b31f 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -12,7 +12,7 @@ #include #include "alloc-vector.h" -#include "util/abort.h" +#include #include "util/runtime-array.h" @@ -23,6 +23,7 @@ using namespace vm; using namespace avian::codegen; +using namespace avian::util; namespace local { diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index 58118b57dc..d9894eda8c 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -14,7 +14,9 @@ #include #include -#include "codegen/compiler/regalloc.h" +#include "regalloc.h" + +using namespace avian::util; namespace avian { namespace codegen { diff --git a/src/codegen/compiler/regalloc.h b/src/codegen/compiler/regalloc.h index c121614799..7bc7b6e8e0 100644 --- a/src/codegen/compiler/regalloc.h +++ b/src/codegen/compiler/regalloc.h @@ -16,12 +16,17 @@ #include #include -class Aborter; - namespace avian { + +namespace util { +class Aborter; +} // namespace util + namespace codegen { namespace compiler { +using namespace avian::util; + class Context; class Value; class SiteMask; diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index f45819d869..1ef611be1a 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -12,7 +12,7 @@ #include #include "alloc-vector.h" -#include "util/abort.h" +#include #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) @@ -21,6 +21,7 @@ using namespace vm; using namespace avian::codegen; +using namespace avian::util; namespace { diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 9c19bc2544..c7fcab491b 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -16,7 +16,7 @@ #include #include "util/runtime-array.h" -#include "util/abort.h" +#include #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) @@ -24,6 +24,7 @@ using namespace vm; using namespace avian::codegen; +using namespace avian::util; namespace { diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index 119a250572..3d060e256d 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -14,6 +14,7 @@ #include "arch.h" using namespace vm; +using namespace avian::util; namespace { diff --git a/src/machine.h b/src/machine.h index 1d29cbc88a..bba9c8dfbf 100644 --- a/src/machine.h +++ b/src/machine.h @@ -19,6 +19,8 @@ #include "constants.h" #include "arch.h" +using namespace avian::util; + #ifdef PLATFORM_WINDOWS # define JNICALL __stdcall #else diff --git a/src/system.h b/src/system.h index 1a95980da3..ba6193a1ac 100644 --- a/src/system.h +++ b/src/system.h @@ -13,11 +13,11 @@ #include "common.h" #include "allocator.h" -#include "util/abort.h" +#include namespace vm { -class System : public Aborter { +class System : public avian::util::Aborter { public: typedef intptr_t Status; @@ -165,7 +165,7 @@ allocate(System* s, unsigned size) #define ACQUIRE_MONITOR(t, m) \ System::MonitorResource MAKE_NAME(monitorResource_) (t, m) -inline Aborter* getAborter(System* s) { +inline avian::util::Aborter* getAborter(System* s) { return s; } From b9e281612b99584b7739c1442e39e1da336f4859 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 19 Feb 2013 22:56:05 -0700 Subject: [PATCH 259/378] move runtime-array to include --- classpath/jni-util.h | 2 +- {src => include/avian}/util/runtime-array.h | 0 src/arm.h | 2 +- src/builtin.cpp | 2 +- src/classpath-avian.cpp | 2 +- src/classpath-common.h | 2 +- src/codegen/arm/assembler.cpp | 2 +- src/codegen/compiler.cpp | 2 +- src/codegen/compiler/event.cpp | 2 +- src/codegen/x86/assembler.cpp | 2 +- src/compile.cpp | 2 +- src/finder.cpp | 2 +- src/interpret.cpp | 2 +- src/jnienv.cpp | 2 +- src/machine.cpp | 2 +- src/main.cpp | 2 +- src/process.cpp | 2 +- src/windows.cpp | 2 +- 18 files changed, 17 insertions(+), 17 deletions(-) rename {src => include/avian}/util/runtime-array.h (100%) diff --git a/classpath/jni-util.h b/classpath/jni-util.h index a73905fadf..bed4658953 100644 --- a/classpath/jni-util.h +++ b/classpath/jni-util.h @@ -15,7 +15,7 @@ #include "stdlib.h" #include "string.h" -#include "util/runtime-array.h" +#include #undef JNIEXPORT diff --git a/src/util/runtime-array.h b/include/avian/util/runtime-array.h similarity index 100% rename from src/util/runtime-array.h rename to include/avian/util/runtime-array.h diff --git a/src/arm.h b/src/arm.h index 5d2835de14..5b8cdab3db 100644 --- a/src/arm.h +++ b/src/arm.h @@ -13,7 +13,7 @@ #include "types.h" #include "common.h" -#include "util/runtime-array.h" +#include #ifdef __APPLE__ # include "libkern/OSAtomic.h" diff --git a/src/builtin.cpp b/src/builtin.cpp index eaa66ed101..865cb5708c 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -13,7 +13,7 @@ #include "processor.h" #include "util.h" -#include "util/runtime-array.h" +#include using namespace vm; diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index f313bffa01..de85398707 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -12,7 +12,7 @@ #include "classpath-common.h" #include "process.h" -#include "util/runtime-array.h" +#include using namespace vm; diff --git a/src/classpath-common.h b/src/classpath-common.h index 11c22b913f..6298d47695 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -13,7 +13,7 @@ #include "tokenizer.h" -#include "util/runtime-array.h" +#include namespace vm { diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index 119cc2b31f..56bd71938d 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -14,7 +14,7 @@ #include "alloc-vector.h" #include -#include "util/runtime-array.h" +#include #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index d67b979406..fa453974e5 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -10,7 +10,7 @@ #include "target.h" -#include "util/runtime-array.h" +#include #include #include diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index ba8c0c222a..c9bb0dcf79 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -9,7 +9,7 @@ details. */ #include "target.h" -#include "util/runtime-array.h" +#include #include "codegen/compiler/context.h" #include "codegen/compiler/event.h" diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index c7fcab491b..90eea322fc 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -15,7 +15,7 @@ #include #include -#include "util/runtime-array.h" +#include #include #define CAST1(x) reinterpret_cast(x) diff --git a/src/compile.cpp b/src/compile.cpp index 63ff48ec94..02a87cd4c8 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -19,7 +19,7 @@ #include #include -#include "util/runtime-array.h" +#include using namespace vm; diff --git a/src/finder.cpp b/src/finder.cpp index 479761c19f..93e95250fd 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -14,7 +14,7 @@ #include "finder.h" #include "lzma.h" -#include "util/runtime-array.h" +#include using namespace vm; diff --git a/src/interpret.cpp b/src/interpret.cpp index 8b9f4e12d9..c025957d48 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -16,7 +16,7 @@ #include "process.h" #include "arch.h" -#include "util/runtime-array.h" +#include using namespace vm; diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 37d3a65f13..2f9492bd58 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -14,7 +14,7 @@ #include "processor.h" #include "constants.h" -#include "util/runtime-array.h" +#include using namespace vm; diff --git a/src/machine.cpp b/src/machine.cpp index 8555878c41..f18ff06552 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -17,7 +17,7 @@ #include "arch.h" #include "lzma.h" -#include "util/runtime-array.h" +#include #if defined(PLATFORM_WINDOWS) # define WIN32_LEAN_AND_MEAN diff --git a/src/main.cpp b/src/main.cpp index e70555e73e..ccd8255940 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,7 @@ #include "system.h" #include "finder.h" -#include "util/runtime-array.h" +#include #if (defined __MINGW32__) || (defined _MSC_VER) # define PATH_SEPARATOR ';' diff --git a/src/process.cpp b/src/process.cpp index b13aa7ca4f..6f1c5dbbd8 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -10,7 +10,7 @@ #include "process.h" -#include "util/runtime-array.h" +#include using namespace vm; diff --git a/src/windows.cpp b/src/windows.cpp index 5c85eb906e..640117ed2c 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -25,7 +25,7 @@ #include "arch.h" #include "system.h" -#include "util/runtime-array.h" +#include #if defined(WINAPI_FAMILY) From 52b2fd74ef98fc26124635e9f3f10e1d287a55c1 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 20 Feb 2013 07:51:57 -0700 Subject: [PATCH 260/378] move math functions out of common.h, and into include/avian/util/math.h --- include/avian/util/math.h | 53 ++++++++++++++++++++++++++++++++++ src/alloc-vector.h | 6 ++-- src/bootimage-template.cpp | 4 +-- src/bootimage.h | 2 ++ src/codegen/compiler/event.cpp | 21 ++++++++------ src/common.h | 47 ------------------------------ src/heap/heap.cpp | 2 ++ src/machine.cpp | 2 ++ src/posix.cpp | 3 ++ src/zone.h | 6 ++-- 10 files changed, 84 insertions(+), 62 deletions(-) create mode 100644 include/avian/util/math.h diff --git a/include/avian/util/math.h b/include/avian/util/math.h new file mode 100644 index 0000000000..ecd4f18fc5 --- /dev/null +++ b/include/avian/util/math.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_MATH_H +#define AVIAN_UTIL_MATH_H + +namespace avian { +namespace util { + +inline unsigned max(unsigned a, unsigned b) { + return (a > b ? a : b); +} + +inline unsigned min(unsigned a, unsigned b) { + return (a < b ? a : b); +} + +inline unsigned avg(unsigned a, unsigned b) { + return (a + b) / 2; +} + +inline unsigned ceilingDivide(unsigned n, unsigned d) { + return (n + d - 1) / d; +} + +inline bool powerOfTwo(unsigned n) { + for (; n > 2; n >>= 1) if (n & 1) return false; + return true; +} + +inline unsigned nextPowerOfTwo(unsigned n) { + unsigned r = 1; + while (r < n) r <<= 1; + return r; +} + +inline unsigned log(unsigned n) { + unsigned r = 0; + for (unsigned i = 1; i < n; ++r) i <<= 1; + return r; +} + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_MATH_H diff --git a/src/alloc-vector.h b/src/alloc-vector.h index 6714573b0d..4032987655 100644 --- a/src/alloc-vector.h +++ b/src/alloc-vector.h @@ -14,6 +14,8 @@ #include "system.h" #include "target.h" +#include + namespace vm { class Vector { @@ -51,8 +53,8 @@ class Vector { if (position + space > capacity) { assert(s, minimumCapacity >= 0); - unsigned newCapacity = max - (position + space, max(minimumCapacity, capacity * 2)); + unsigned newCapacity = avian::util::max + (position + space, avian::util::max(minimumCapacity, capacity * 2)); uint8_t* newData = static_cast (allocator->allocate(newCapacity)); if (data) { diff --git a/src/bootimage-template.cpp b/src/bootimage-template.cpp index 72374f3392..86df096777 100644 --- a/src/bootimage-template.cpp +++ b/src/bootimage-template.cpp @@ -9,13 +9,13 @@ const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1); inline unsigned LABEL(codeMapSize)(unsigned codeSize) { - return ceilingDivide(codeSize, TargetBitsPerWord) * TargetBytesPerWord; + return avian::util::ceilingDivide(codeSize, TargetBitsPerWord) * TargetBytesPerWord; } inline unsigned LABEL(heapMapSize)(unsigned heapSize) { - return ceilingDivide(heapSize, TargetBitsPerWord * TargetBytesPerWord) + return avian::util::ceilingDivide(heapSize, TargetBitsPerWord * TargetBytesPerWord) * TargetBytesPerWord; } diff --git a/src/bootimage.h b/src/bootimage.h index 16f11ab379..bf96cdaf17 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -15,6 +15,8 @@ #include "target.h" #include "machine.h" +#include + namespace vm { class BootImage { diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index c9bb0dcf79..f07706e499 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -10,6 +10,7 @@ #include "target.h" #include +#include #include "codegen/compiler/context.h" #include "codegen/compiler/event.h" @@ -20,6 +21,8 @@ #include "codegen/compiler/frame.h" #include "codegen/compiler/ir.h" +using namespace avian::util; + namespace avian { namespace codegen { namespace compiler { @@ -921,11 +924,11 @@ appendCombine(Context* c, lir::TernaryOperation type, intptr_t handler = c->client->getThunk (type, firstSize, resultSize, &threadParameter); - unsigned stackSize = vm::ceilingDivide(secondSize, vm::TargetBytesPerWord) - + vm::ceilingDivide(firstSize, vm::TargetBytesPerWord); + unsigned stackSize = ceilingDivide(secondSize, vm::TargetBytesPerWord) + + ceilingDivide(firstSize, vm::TargetBytesPerWord); - compiler::push(c, vm::ceilingDivide(secondSize, vm::TargetBytesPerWord), second); - compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), first); + compiler::push(c, ceilingDivide(secondSize, vm::TargetBytesPerWord), second); + compiler::push(c, ceilingDivide(firstSize, vm::TargetBytesPerWord), first); if (threadParameter) { ++ stackSize; @@ -1047,7 +1050,7 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, if (thunk) { Stack* oldStack = c->stack; - compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), first); + compiler::push(c, ceilingDivide(firstSize, vm::TargetBytesPerWord), first); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -1057,7 +1060,7 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, (c, lir::ValueGeneral, constantSite (c, c->client->getThunk(type, firstSize, resultSize))), 0, 0, result, resultSize, argumentStack, - vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), 0); + ceilingDivide(firstSize, vm::TargetBytesPerWord), 0); } else { append(c, new(c->zone) TranslateEvent @@ -1404,8 +1407,8 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first assert(c, not threadParameter); - compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), second); - compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), first); + compiler::push(c, ceilingDivide(size, vm::TargetBytesPerWord), second); + compiler::push(c, ceilingDivide(size, vm::TargetBytesPerWord), first); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -1414,7 +1417,7 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first appendCall (c, value (c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4, - argumentStack, vm::ceilingDivide(size, vm::TargetBytesPerWord) * 2, 0); + argumentStack, ceilingDivide(size, vm::TargetBytesPerWord) * 2, 0); appendBranch(c, thunkBranch(c, type), 4, value (c, lir::ValueGeneral, constantSite(c, static_cast(0))), diff --git a/src/common.h b/src/common.h index 7cf763c4bd..b7408e289a 100644 --- a/src/common.h +++ b/src/common.h @@ -296,24 +296,6 @@ const uintptr_t PointerMask const unsigned LikelyPageSizeInBytes = 4 * 1024; -inline unsigned -max(unsigned a, unsigned b) -{ - return (a > b ? a : b); -} - -inline unsigned -min(unsigned a, unsigned b) -{ - return (a < b ? a : b); -} - -inline unsigned -avg(unsigned a, unsigned b) -{ - return (a + b) / 2; -} - inline unsigned pad(unsigned n, unsigned alignment) { @@ -338,35 +320,6 @@ padWord(uintptr_t n) return padWord(n, BytesPerWord); } -inline unsigned -ceilingDivide(unsigned n, unsigned d) -{ - return (n + d - 1) / d; -} - -inline bool -powerOfTwo(unsigned n) -{ - for (; n > 2; n >>= 1) if (n & 1) return false; - return true; -} - -inline unsigned -nextPowerOfTwo(unsigned n) -{ - unsigned r = 1; - while (r < n) r <<= 1; - return r; -} - -inline unsigned -log(unsigned n) -{ - unsigned r = 0; - for (unsigned i = 1; i < n; ++r) i <<= 1; - return r; -} - template inline unsigned wordOf(unsigned i) diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index 3d060e256d..1fc3cae022 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -13,6 +13,8 @@ #include "common.h" #include "arch.h" +#include + using namespace vm; using namespace avian::util; diff --git a/src/machine.cpp b/src/machine.cpp index f18ff06552..06a86a562c 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -18,6 +18,7 @@ #include "lzma.h" #include +#include #if defined(PLATFORM_WINDOWS) # define WIN32_LEAN_AND_MEAN @@ -25,6 +26,7 @@ #endif using namespace vm; +using namespace avian::util; namespace { diff --git a/src/posix.cpp b/src/posix.cpp index 4c320e0167..1f643d93d6 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -51,10 +51,13 @@ #include "arch.h" #include "system.h" +#include + #define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x) using namespace vm; +using namespace avian::util; namespace { diff --git a/src/zone.h b/src/zone.h index 900ea5d3ab..d0009d77c4 100644 --- a/src/zone.h +++ b/src/zone.h @@ -14,6 +14,8 @@ #include "system.h" #include "allocator.h" +#include + namespace vm { class Zone: public Allocator { @@ -59,8 +61,8 @@ class Zone: public Allocator { bool tryEnsure(unsigned space) { if (segment == 0 or segment->position + space > segment->size) { unsigned size = padToPage - (max - (space, max + (avian::util::max + (space, avian::util::max (minimumFootprint, segment == 0 ? 0 : segment->size * 2)) + sizeof(Segment)); From d414fd4c7bf0eff4f6508c2f74078d12caed8732 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 20 Feb 2013 10:22:40 -0700 Subject: [PATCH 261/378] more progress on Android class library port Hello.java works. Yay. --- classpath/avian/Android.java | 30 ++++++ classpath/sun/misc/Unsafe.java | 7 ++ makefile | 14 ++- src/builtin.cpp | 13 +++ src/classpath-android.cpp | 170 ++++++++++++++++++++++++++++++++- src/classpath-common.h | 24 +++++ src/classpath-openjdk.cpp | 39 +------- 7 files changed, 255 insertions(+), 42 deletions(-) create mode 100644 classpath/avian/Android.java diff --git a/classpath/avian/Android.java b/classpath/avian/Android.java new file mode 100644 index 0000000000..720f82341c --- /dev/null +++ b/classpath/avian/Android.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2013, 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. */ + +package avian; + +public class Android { + public static VMField findField(VMClass vmClass, String name) { + if (vmClass.fieldTable != null) { + Classes.link(vmClass); + + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (getName(vmClass.fieldTable[i]).equals(name)) { + return vmClass.fieldTable[i]; + } + } + } + return null; + } + + public static String getName(VMField vmField) { + return new String(vmField.name, 0, vmField.name.length - 1); + } +} diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index 4f395718c9..5fea56c54a 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -1,5 +1,7 @@ package sun.misc; +import java.lang.reflect.Field; + public final class Unsafe { private void Unsafe() { } @@ -50,10 +52,15 @@ public final class Unsafe { public native int arrayBaseOffset(Class arrayClass); + public native long objectFieldOffset(Field field); + public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long count); + public native boolean compareAndSwapInt(Object o, long offset, int old, + int new_); + public void copyMemory(long src, long dst, long count) { copyMemory(null, src, null, dst, count); } diff --git a/makefile b/makefile index a50fc6cb53..a023f4b6f2 100755 --- a/makefile +++ b/makefile @@ -1229,7 +1229,8 @@ ifneq ($(classpath),avian) $(classpath-src)/java/net/ProtocolFamily.java \ $(classpath-src)/java/net/StandardProtocolFamily.java \ $(classpath-src)/sun/misc/Cleaner.java \ - $(classpath-src)/sun/misc/Unsafe.java + $(classpath-src)/sun/misc/Unsafe.java \ + $(classpath-src)/avian/Android.java endif else classpath-sources := $(shell find $(classpath-src) -name '*.java') @@ -1406,7 +1407,13 @@ $(classpath-dep): $(classpath-sources) $(classpath-jar-dep) $(classpath-classes)) @touch $(@) -$(build)/%.o: $(luni-native)/%.cpp $(build)/android.dep +$(build)/android-src/%.cpp: $(luni-native)/%.cpp + if [ "$(luni-native)/libcore_icu_ICU.cpp" = "$(<)" ]; then \ + sed 's/register_libcore_icu_ICU/hide_register_libcore_icu_ICU/' \ + < $(<) > $(@).tmp && cat $(@).tmp $(src)/android/icu.cpp > $(@); else \ + cp $(<) $(@); fi + +$(build)/%.o: $(build)/android-src/%.cpp $(build)/android.dep @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(cxx) $(android-cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) @@ -1653,7 +1660,8 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) -unittest-executable-objects = $(unittest-objects) $(vm-objects) +unittest-executable-objects = $(unittest-objects) $(vm-objects) \ + $(classpath-objects) ifeq ($(process),interpret) unittest-executable-objects += $(all-codegen-target-objects) diff --git a/src/builtin.cpp b/src/builtin.cpp index eaa66ed101..b9cfde971d 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -565,3 +565,16 @@ Avian_java_nio_FixedArrayByteBuffer_allocateFixed return reinterpret_cast(array); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_compareAndSwapInt +(Thread*, object, uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + uint32_t expect = arguments[4]; + uint32_t update = arguments[5]; + + return atomicCompareAndSwap32 + (&fieldAtOffset(target, offset), expect, update); +} diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index d50be47057..ef26c514ca 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -291,7 +291,7 @@ jniCreateFileDescriptor(JNIEnv* e, int fd) return descriptor; } -extern "C" struct _JNIEnv; +struct _JNIEnv; int register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) @@ -299,3 +299,171 @@ register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) // ignore return 0; } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_isEmpty +(Thread* t, object, uintptr_t* arguments) +{ + return stringLength(t, reinterpret_cast(arguments[0])) == 0; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_length +(Thread* t, object, uintptr_t* arguments) +{ + return stringLength(t, reinterpret_cast(arguments[0])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_charAt +(Thread* t, object, uintptr_t* arguments) +{ + return stringCharAt(t, reinterpret_cast(arguments[0]), arguments[1]); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_equals +(Thread* t, object, uintptr_t* arguments) +{ + return stringEqual(t, reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_fastIndexOf +(Thread* t, object, uintptr_t* arguments) +{ + object s = reinterpret_cast(arguments[0]); + unsigned c = arguments[1]; + unsigned start = arguments[2]; + + for (unsigned i = start; i < stringLength(t, s); ++i) { + if (stringCharAt(t, s, i) == c) { + return i; + } + } + + return -1; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getComponentType +(Thread* t, object, uintptr_t* arguments) +{ + object c = reinterpret_cast(arguments[0]); + + if (classArrayDimensions(t, jclassVmClass(t, c))) { + uint8_t n = byteArrayBody(t, className(t, jclassVmClass(t, c)), 1); + if (n != 'L' and n != '[') { + return reinterpret_cast + (getJClass(t, primitiveClass(t, n))); + } else { + return reinterpret_cast + (getJClass(t, classStaticTable(t, jclassVmClass(t, c)))); + } + } else { + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getDeclaredField +(Thread* t, object, uintptr_t* arguments) +{ + object c = reinterpret_cast(arguments[0]); + PROTECT(t, c); + + object name = reinterpret_cast(arguments[1]); + PROTECT(t, name); + + object method = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Android", "findField", + "(Lavian/VMClass;Ljava/lang/String;)Lavian/VMField;"); + + object field = t->m->processor->invoke + (t, method, 0, jclassVmClass(t, c), name); + + if (field) { + PROTECT(t, field); + + object type = resolveClassBySpec + (t, classLoader(t, fieldClass(t, field)), + reinterpret_cast + (&byteArrayBody(t, fieldSpec(t, field), 0)), + byteArrayLength(t, fieldSpec(t, field)) - 1); + PROTECT(t, type); + + unsigned index = 0xFFFFFFFF; + object table = classFieldTable(t, fieldClass(t, field)); + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (field == arrayBody(t, table, i)) { + index = i; + break; + } + } + + return reinterpret_cast + (makeJfield(t, 0, c, type, 0, 0, name, index)); + } else { + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_bootClassPath +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(root(t, Machine::BootLoader)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_classPath +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(root(t, Machine::AppLoader)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_vmVersion +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(makeString(t, "%s", AVIAN_VERSION)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_properties +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast + (makeObjectArray(t, type(t, Machine::StringType), 0)); +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_System_arraycopy +(Thread* t, object, uintptr_t* arguments) +{ + arrayCopy(t, reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2]), + arguments[3], + arguments[4]); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_objectFieldOffset +(Thread* t, object, uintptr_t* arguments) +{ + object jfield = reinterpret_cast(arguments[1]); + return fieldOffset + (t, arrayBody + (t, classFieldTable + (t, jclassVmClass(t, jfieldDeclaringClass(t, jfield))), + jfieldSlot(t, jfield))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMThread_currentThread +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(t->javaThread); +} diff --git a/src/classpath-common.h b/src/classpath-common.h index 11c22b913f..ca6649a01e 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -331,6 +331,30 @@ translateInvokeResult(Thread* t, unsigned returnCode, object o) } } +object +resolveClassBySpec(Thread* t, object loader, const char* spec, + unsigned specLength) +{ + switch (*spec) { + case 'L': { + THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); + memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); + RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; + return resolveClass(t, loader, s); + } + + case '[': { + THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); + memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); + RUNTIME_ARRAY_BODY(s)[specLength] = 0; + return resolveClass(t, loader, s); + } + + default: + return primitiveClass(t, *spec); + } +} + } // namespace vm #endif//CLASSPATH_COMMON_H diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 074f3cf5f3..df37efceaf 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2185,30 +2185,6 @@ countConstructors(Thread* t, object c, bool publicOnly) return count; } -object -resolveClassBySpec(Thread* t, object loader, const char* spec, - unsigned specLength) -{ - switch (*spec) { - case 'L': { - THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); - memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); - RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; - return resolveClass(t, loader, s); - } - - case '[': { - THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); - memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); - RUNTIME_ARRAY_BODY(s)[specLength] = 0; - return resolveClass(t, loader, s); - } - - default: - return primitiveClass(t, *spec); - } -} - object resolveJType(Thread* t, object loader, const char* spec, unsigned specLength) { @@ -2498,7 +2474,7 @@ makeJfield(Thread* t, object vmField, int index) (t, fieldName(t, vmField)) - 1)); PROTECT(t, name); - object type = local::resolveClassBySpec + object type = resolveClassBySpec (t, classLoader(t, fieldClass(t, vmField)), reinterpret_cast (&byteArrayBody(t, fieldSpec(t, vmField), 0)), @@ -3055,19 +3031,6 @@ Avian_sun_misc_Unsafe_putOrderedObject Avian_sun_misc_Unsafe_putObjectVolatile(t, method, arguments); } -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_compareAndSwapInt -(Thread*, object, uintptr_t* arguments) -{ - object target = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - uint32_t expect = arguments[4]; - uint32_t update = arguments[5]; - - return atomicCompareAndSwap32 - (&fieldAtOffset(target, offset), expect, update); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_compareAndSwapObject (Thread* t, object, uintptr_t* arguments) From 24ff91c229eca7ddb399ffe5025a59daa8d042fb Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 20 Feb 2013 10:23:20 -0700 Subject: [PATCH 262/378] move heap.h to include --- {src => include/avian/vm}/heap/heap.h | 0 src/bootimage.cpp | 2 +- src/heap/heap.cpp | 2 +- src/machine.h | 2 +- src/processor.h | 2 +- unittest/codegen/assembler-test.cpp | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename {src => include/avian/vm}/heap/heap.h (100%) diff --git a/src/heap/heap.h b/include/avian/vm/heap/heap.h similarity index 100% rename from src/heap/heap.h rename to include/avian/vm/heap/heap.h diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 05fef8158d..d6046d459f 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "heap/heap.h" +#include #include "heapwalk.h" #include "common.h" #include "machine.h" diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index 1fc3cae022..0a0778797b 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "heap/heap.h" +#include #include "system.h" #include "common.h" #include "arch.h" diff --git a/src/machine.h b/src/machine.h index bba9c8dfbf..a2ebb7c538 100644 --- a/src/machine.h +++ b/src/machine.h @@ -13,7 +13,7 @@ #include "common.h" #include "system.h" -#include "heap/heap.h" +#include #include "finder.h" #include "processor.h" #include "constants.h" diff --git a/src/processor.h b/src/processor.h index 47e8d3c02d..7ce69458d4 100644 --- a/src/processor.h +++ b/src/processor.h @@ -13,7 +13,7 @@ #include "common.h" #include "system.h" -#include "heap/heap.h" +#include #include "bootimage.h" #include "heapwalk.h" #include "zone.h" diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp index 760e770bd8..237b8f7209 100644 --- a/unittest/codegen/assembler-test.cpp +++ b/unittest/codegen/assembler-test.cpp @@ -11,7 +11,7 @@ #include #include "common.h" -#include "heap/heap.h" +#include #include "system.h" #include "target.h" From 41d84f7d5a950cec84e816350c03410e91844b90 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 20 Feb 2013 13:40:11 -0700 Subject: [PATCH 263/378] fix bootimage build --- src/bootimage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index d6046d459f..5f33a489b3 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -14,8 +14,8 @@ #include "machine.h" #include "util.h" #include "stream.h" -#include "codegen/assembler.h" -#include "codegen/promise.h" +#include +#include #include "target.h" #include #include "lzma.h" From fd047bd6e97e75bf9d7e2527cd7bc56521e4213b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 20 Feb 2013 17:20:10 -0700 Subject: [PATCH 264/378] find headers regardless of directory layout in vm-depends definition --- makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 38872186bf..076145e1ba 100755 --- a/makefile +++ b/makefile @@ -939,7 +939,8 @@ generated-code = \ $(build)/type-name-initializations.cpp \ $(build)/type-maps.cpp -vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) $(wildcard $(src)/codegen/compiler/*.h) +vm-depends := $(generated-code) \ + $(shell find src include -name '*.h' -or -name '*.inc.cpp') vm-sources = \ $(src)/$(system).cpp \ @@ -1019,7 +1020,7 @@ heapwalk-sources = $(src)/heapwalk.cpp heapwalk-objects = \ $(call cpp-objects,$(heapwalk-sources),$(src),$(build)) -unittest-objects = $(call cpp-objects,$(unittest-sources),$(unittest),$(build)/unittest/) +unittest-objects = $(call cpp-objects,$(unittest-sources),$(unittest),$(build)/unittest) ifeq ($(heapdump),true) vm-sources += $(src)/heapdump.cpp From f04f444f2348f41465bc8566a31f9a17728cb7b2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 20 Feb 2013 17:20:17 -0700 Subject: [PATCH 265/378] modify (THREAD_)RUNTIME_ARRAY definition so RUNTIME_ARRAY_BODY must be used Previously, if you forgot to use RUNTIME_ARRAY_BODY to reference an array declared with (THREAD_)RUNTIME_ARRAY, you wouldn't get a compiler error until you tried to build on e.g. MSVC, where runtime-sized stack arrays aren't supported. This change ensures you find out regardless of what compiler you're using, which ought to protect us from regressions going forward. --- include/avian/util/runtime-array.h | 6 +-- src/bootimage.cpp | 65 ++++++++++++++++-------------- src/interpret.cpp | 11 ++--- src/machine.cpp | 8 ++-- src/machine.h | 3 +- 5 files changed, 49 insertions(+), 44 deletions(-) diff --git a/include/avian/util/runtime-array.h b/include/avian/util/runtime-array.h index ffd8e3348b..5d169ed95e 100644 --- a/include/avian/util/runtime-array.h +++ b/include/avian/util/runtime-array.h @@ -32,9 +32,9 @@ class RuntimeArray { #else // not _MSC_VER -# define RUNTIME_ARRAY(type, name, size) type name[size]; -# define RUNTIME_ARRAY_BODY(name) name +# define RUNTIME_ARRAY(type, name, size) type name##_body[size]; +# define RUNTIME_ARRAY_BODY(name) name##_body #endif -#endif // AVIAN_UTIL_RUNTIME_ARRAY_H \ No newline at end of file +#endif // AVIAN_UTIL_RUNTIME_ARRAY_H diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 5f33a489b3..6d7b36c995 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -18,6 +18,7 @@ #include #include "target.h" #include +#include #include "lzma.h" // since we aren't linking against libstdc++, we must implement this @@ -345,20 +346,20 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, unsigned count = s.read2() - 1; if (count) { THREAD_RUNTIME_ARRAY(t, Type, types, count + 2); - types[0] = Type_object; - types[1] = Type_intptr_t; + RUNTIME_ARRAY_BODY(types)[0] = Type_object; + RUNTIME_ARRAY_BODY(types)[1] = Type_intptr_t; for (unsigned i = 2; i < count + 2; ++i) { switch (s.read1()) { case CONSTANT_Class: case CONSTANT_String: - types[i] = Type_object; + RUNTIME_ARRAY_BODY(types)[i] = Type_object; s.skip(2); break; case CONSTANT_Integer: case CONSTANT_Float: - types[i] = Type_int32_t; + RUNTIME_ARRAY_BODY(types)[i] = Type_int32_t; s.skip(4); break; @@ -366,24 +367,24 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: - types[i] = Type_object; + RUNTIME_ARRAY_BODY(types)[i] = Type_object; s.skip(4); break; case CONSTANT_Long: - types[i++] = Type_int64_t; - types[i] = Type_int64_t_pad; + RUNTIME_ARRAY_BODY(types)[i++] = Type_int64_t; + RUNTIME_ARRAY_BODY(types)[i] = Type_int64_t_pad; s.skip(8); break; case CONSTANT_Double: - types[i++] = Type_double; - types[i] = Type_double_pad; + RUNTIME_ARRAY_BODY(types)[i++] = Type_double; + RUNTIME_ARRAY_BODY(types)[i] = Type_double_pad; s.skip(8); break; case CONSTANT_Utf8: - types[i] = Type_object; + RUNTIME_ARRAY_BODY(types)[i] = Type_object; s.skip(s.read2()); break; @@ -403,7 +404,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, map->targetFixedOffsets()[i * BytesPerWord] = i * TargetBytesPerWord; - init(new (map->fixedFields() + i) Field, types[i], + init(new (map->fixedFields() + i) Field, RUNTIME_ARRAY_BODY(types)[i], i * BytesPerWord, BytesPerWord, i * TargetBytesPerWord, TargetBytesPerWord); } @@ -439,15 +440,15 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, for (unsigned j = 0; j < map->fixedFieldCount; ++j) { Field* f = map->fixedFields() + j; - memberFields[memberIndex] = *f; + RUNTIME_ARRAY_BODY(memberFields)[memberIndex] = *f; targetMemberOffset = f->targetOffset + f->targetSize; ++ memberIndex; } } else { - init(new (&memberFields[0]) Field, Type_object, 0, BytesPerWord, 0, - TargetBytesPerWord); + init(new (RUNTIME_ARRAY_BODY(memberFields)) Field, Type_object, 0, + BytesPerWord, 0, TargetBytesPerWord); memberIndex = 1; buildMemberOffset = BytesPerWord; @@ -458,14 +459,16 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, THREAD_RUNTIME_ARRAY(t, Field, staticFields, count + StaticHeader); - init(new (&staticFields[0]) Field, Type_object, 0, BytesPerWord, 0, + init(new (RUNTIME_ARRAY_BODY(staticFields)) Field, Type_object, 0, + BytesPerWord, 0, TargetBytesPerWord); + + init(new (RUNTIME_ARRAY_BODY(staticFields) + 1) Field, Type_intptr_t, + BytesPerWord, BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); - init(new (&staticFields[1]) Field, Type_intptr_t, BytesPerWord, - BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); - - init(new (&staticFields[2]) Field, Type_object, BytesPerWord * 2, - BytesPerWord, TargetBytesPerWord * 2, TargetBytesPerWord); + init(new (RUNTIME_ARRAY_BODY(staticFields) + 2) Field, Type_object, + BytesPerWord * 2, BytesPerWord, TargetBytesPerWord * 2, + TargetBytesPerWord); unsigned staticIndex = StaticHeader; unsigned buildStaticOffset = BytesPerWord * StaticHeader; @@ -514,8 +517,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildStaticOffset = fieldOffset(t, field); - init(new (&staticFields[staticIndex]) Field, type, - buildStaticOffset, buildSize, targetStaticOffset, + init(new (RUNTIME_ARRAY_BODY(staticFields) + staticIndex) Field, + type, buildStaticOffset, buildSize, targetStaticOffset, targetSize); targetStaticOffset += targetSize; @@ -528,8 +531,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildMemberOffset = fieldOffset(t, field); - init(new (&memberFields[memberIndex]) Field, type, - buildMemberOffset, buildSize, targetMemberOffset, + init(new (RUNTIME_ARRAY_BODY(memberFields) + memberIndex) Field, + type, buildMemberOffset, buildSize, targetMemberOffset, targetSize); targetMemberOffset += targetSize; @@ -551,7 +554,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ceilingDivide(targetMemberOffset, TargetBytesPerWord), memberIndex); for (unsigned i = 0; i < memberIndex; ++i) { - Field* f = &memberFields[i]; + Field* f = RUNTIME_ARRAY_BODY(memberFields) + i; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -575,7 +578,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, TypeMap::SingletonKind); for (unsigned i = 0; i < staticIndex; ++i) { - Field* f = &staticFields[i]; + Field* f = RUNTIME_ARRAY_BODY(staticFields) + i; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); @@ -1338,8 +1341,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp THREAD_RUNTIME_ARRAY(t, Field, fields, count); - init(new (&fields[0]) Field, Type_object, 0, BytesPerWord, 0, - TargetBytesPerWord); + init(new (RUNTIME_ARRAY_BODY(fields)) Field, Type_object, 0, + BytesPerWord, 0, TargetBytesPerWord); unsigned buildOffset = BytesPerWord; unsigned targetOffset = TargetBytesPerWord; @@ -1416,8 +1419,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp ++ targetOffset; } - init(new (&fields[j]) Field, type, buildOffset, buildSize, - targetOffset, targetSize); + init(new (RUNTIME_ARRAY_BODY(fields) + j) Field, type, buildOffset, + buildSize, targetOffset, targetSize); buildOffset += buildSize; targetOffset += targetSize; @@ -1451,7 +1454,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp targetArrayElementSize, arrayElementType); for (unsigned j = 0; j < fixedFieldCount; ++j) { - Field* f = &fields[j]; + Field* f = RUNTIME_ARRAY_BODY(fields) + j; expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); diff --git a/src/interpret.cpp b/src/interpret.cpp index c025957d48..8d7dc425e2 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2325,19 +2325,20 @@ interpret3(Thread* t, const int base) THREAD_RUNTIME_ARRAY(t, int32_t, counts, dimensions); for (int i = dimensions - 1; i >= 0; --i) { - counts[i] = popInt(t); - if (UNLIKELY(counts[i] < 0)) { + RUNTIME_ARRAY_BODY(counts)[i] = popInt(t); + if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) { exception = makeThrowable - (t, Machine::NegativeArraySizeExceptionType, "%d", counts[i]); + (t, Machine::NegativeArraySizeExceptionType, "%d", + RUNTIME_ARRAY_BODY(counts)[i]); goto throw_; } } - object array = makeArray(t, counts[0]); + object array = makeArray(t, RUNTIME_ARRAY_BODY(counts)[0]); setObjectClass(t, array, class_); PROTECT(t, array); - populateMultiArray(t, array, counts, 0, dimensions); + populateMultiArray(t, array, RUNTIME_ARRAY_BODY(counts), 0, dimensions); pushObject(t, array); } goto loop; diff --git a/src/machine.cpp b/src/machine.cpp index 06a86a562c..bcb7ec0876 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -4777,13 +4777,13 @@ logTrace(FILE* f, const char* fmt, ...) RUNTIME_ARRAY(char, buffer, length + 1); va_start(a, fmt); - vsnprintf(&buffer[0], length + 1, fmt, a); + vsnprintf(RUNTIME_ARRAY_BODY(buffer), length + 1, fmt, a); va_end(a); - buffer[length] = 0; + RUNTIME_ARRAY_BODY(buffer)[length] = 0; - ::fprintf(f, "%s", &buffer[0]); + ::fprintf(f, "%s", RUNTIME_ARRAY_BODY(buffer)); #ifdef PLATFORM_WINDOWS - ::OutputDebugStringA(&buffer[0]); + ::OutputDebugStringA(RUNTIME_ARRAY_BODY(buffer)); #endif } diff --git a/src/machine.h b/src/machine.h index a2ebb7c538..22fe7f3845 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1603,7 +1603,8 @@ class ThreadRuntimeArray: public Thread::Resource { #else // not _MSC_VER -# define THREAD_RUNTIME_ARRAY(thread, type, name, size) type name[size]; +# define THREAD_RUNTIME_ARRAY(thread, type, name, size) \ + type name##_body[size]; #endif // not _MSC_VER From f17b8cef08d69b6c58ef420ddfebf0747282755f Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 20 Feb 2013 20:42:09 -0700 Subject: [PATCH 266/378] move system.h to include --- include/avian/vm/codegen/assembler.h | 2 +- include/avian/vm/codegen/compiler.h | 2 +- include/avian/vm/heap/heap.h | 2 +- {src => include/avian/vm/system}/system.h | 0 src/alloc-vector.h | 2 +- src/finder.cpp | 2 +- src/finder.h | 2 +- src/heap/heap.cpp | 2 +- src/interpret.cpp | 2 +- src/lzma-util.h | 2 +- src/lzma.h | 2 +- src/machine.h | 2 +- src/main.cpp | 2 +- src/posix.cpp | 2 +- src/process.h | 2 +- src/processor.h | 2 +- src/windows.cpp | 2 +- src/zone.h | 2 +- unittest/codegen/assembler-test.cpp | 2 +- 19 files changed, 18 insertions(+), 18 deletions(-) rename {src => include/avian/vm/system}/system.h (100%) diff --git a/include/avian/vm/codegen/assembler.h b/include/avian/vm/codegen/assembler.h index 593e0e6fe7..d61684c92e 100644 --- a/include/avian/vm/codegen/assembler.h +++ b/include/avian/vm/codegen/assembler.h @@ -11,7 +11,7 @@ #ifndef AVIAN_CODEGEN_ASSEMBLER_H #define AVIAN_CODEGEN_ASSEMBLER_H -#include "system.h" +#include #include "zone.h" #include diff --git a/include/avian/vm/codegen/compiler.h b/include/avian/vm/codegen/compiler.h index b7aeeed2dc..663cb071ea 100644 --- a/include/avian/vm/codegen/compiler.h +++ b/include/avian/vm/codegen/compiler.h @@ -11,7 +11,7 @@ #ifndef AVIAN_CODEGEN_COMPILER_H #define AVIAN_CODEGEN_COMPILER_H -#include "system.h" +#include #include "zone.h" #include "assembler.h" diff --git a/include/avian/vm/heap/heap.h b/include/avian/vm/heap/heap.h index 2a6734438d..5b0fbc1ba1 100644 --- a/include/avian/vm/heap/heap.h +++ b/include/avian/vm/heap/heap.h @@ -11,7 +11,7 @@ #ifndef HEAP_H #define HEAP_H -#include "system.h" +#include #include "allocator.h" namespace vm { diff --git a/src/system.h b/include/avian/vm/system/system.h similarity index 100% rename from src/system.h rename to include/avian/vm/system/system.h diff --git a/src/alloc-vector.h b/src/alloc-vector.h index 4032987655..fbdd1f5561 100644 --- a/src/alloc-vector.h +++ b/src/alloc-vector.h @@ -11,7 +11,7 @@ #ifndef VECTOR_H #define VECTOR_H -#include "system.h" +#include #include "target.h" #include diff --git a/src/finder.cpp b/src/finder.cpp index 93e95250fd..879796075b 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -9,7 +9,7 @@ details. */ #include "zlib-custom.h" -#include "system.h" +#include #include "tokenizer.h" #include "finder.h" #include "lzma.h" diff --git a/src/finder.h b/src/finder.h index f4582417fa..d9f8480577 100644 --- a/src/finder.h +++ b/src/finder.h @@ -12,7 +12,7 @@ #define FINDER_H #include "common.h" -#include "system.h" +#include #include "allocator.h" namespace vm { diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index 0a0778797b..6257e45618 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -9,7 +9,7 @@ details. */ #include -#include "system.h" +#include #include "common.h" #include "arch.h" diff --git a/src/interpret.cpp b/src/interpret.cpp index c025957d48..9812b07091 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -9,7 +9,7 @@ details. */ #include "common.h" -#include "system.h" +#include #include "constants.h" #include "machine.h" #include "processor.h" diff --git a/src/lzma-util.h b/src/lzma-util.h index e7fc3093a0..76a249b378 100644 --- a/src/lzma-util.h +++ b/src/lzma-util.h @@ -13,7 +13,7 @@ #include "lzma.h" #include "C/Types.h" -#include "system.h" +#include #include "allocator.h" namespace vm { diff --git a/src/lzma.h b/src/lzma.h index 5e6ba35a82..e0b9dd1e49 100644 --- a/src/lzma.h +++ b/src/lzma.h @@ -11,7 +11,7 @@ #ifndef LZMA_H #define LZMA_H -#include "system.h" +#include #include "allocator.h" namespace vm { diff --git a/src/machine.h b/src/machine.h index a2ebb7c538..ff5741c0a2 100644 --- a/src/machine.h +++ b/src/machine.h @@ -12,7 +12,7 @@ #define MACHINE_H #include "common.h" -#include "system.h" +#include #include #include "finder.h" #include "processor.h" diff --git a/src/main.cpp b/src/main.cpp index ccd8255940..f6ae72eec7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include "string.h" #include "jni.h" -#include "system.h" +#include #include "finder.h" #include diff --git a/src/posix.cpp b/src/posix.cpp index 1f643d93d6..5fcfd4d3ae 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -49,7 +49,7 @@ #include "dirent.h" #include "sched.h" #include "arch.h" -#include "system.h" +#include #include diff --git a/src/process.h b/src/process.h index 04fcf57c7d..71430c02b5 100644 --- a/src/process.h +++ b/src/process.h @@ -12,7 +12,7 @@ #define PROCESS_H #include "common.h" -#include "system.h" +#include #include "machine.h" #include "constants.h" diff --git a/src/processor.h b/src/processor.h index 7ce69458d4..63bf1c1d00 100644 --- a/src/processor.h +++ b/src/processor.h @@ -12,7 +12,7 @@ #define PROCESSOR_H #include "common.h" -#include "system.h" +#include #include #include "bootimage.h" #include "heapwalk.h" diff --git a/src/windows.cpp b/src/windows.cpp index 640117ed2c..be3cfbeeef 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -24,7 +24,7 @@ #undef min #include "arch.h" -#include "system.h" +#include #include #if defined(WINAPI_FAMILY) diff --git a/src/zone.h b/src/zone.h index d0009d77c4..ca467de7d6 100644 --- a/src/zone.h +++ b/src/zone.h @@ -11,7 +11,7 @@ #ifndef ZONE_H #define ZONE_H -#include "system.h" +#include #include "allocator.h" #include diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp index 237b8f7209..f0135d2d64 100644 --- a/unittest/codegen/assembler-test.cpp +++ b/unittest/codegen/assembler-test.cpp @@ -12,7 +12,7 @@ #include "common.h" #include -#include "system.h" +#include #include "target.h" #include From 48691bb50a543f7841c97f661dc1921d0a016162 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 20 Feb 2013 21:26:34 -0700 Subject: [PATCH 267/378] move stream.h to include, and type-generator to src/tools --- {src => include/avian/util}/stream.h | 0 makefile | 2 +- src/bootimage.cpp | 2 +- src/machine.cpp | 2 +- src/{type-generator.cpp => tools/type-generator/main.cpp} | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename {src => include/avian/util}/stream.h (100%) rename src/{type-generator.cpp => tools/type-generator/main.cpp} (99%) diff --git a/src/stream.h b/include/avian/util/stream.h similarity index 100% rename from src/stream.h rename to include/avian/util/stream.h diff --git a/makefile b/makefile index 38872186bf..30cf4faf70 100755 --- a/makefile +++ b/makefile @@ -1071,7 +1071,7 @@ boot-object = $(build)/boot.o generator-depends := $(wildcard $(src)/*.h) generator-sources = \ - $(src)/type-generator.cpp \ + $(src)/tools/type-generator/main.cpp \ $(src)/$(build-system).cpp \ $(src)/finder.cpp diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 5f33a489b3..8d0fe3d302 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -13,7 +13,7 @@ #include "common.h" #include "machine.h" #include "util.h" -#include "stream.h" +#include #include #include #include "target.h" diff --git a/src/machine.cpp b/src/machine.cpp index 06a86a562c..f093eb6b0b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -11,7 +11,7 @@ #include "jnienv.h" #include "machine.h" #include "util.h" -#include "stream.h" +#include #include "constants.h" #include "processor.h" #include "arch.h" diff --git a/src/type-generator.cpp b/src/tools/type-generator/main.cpp similarity index 99% rename from src/type-generator.cpp rename to src/tools/type-generator/main.cpp index 290aec459a..e0ba6a0169 100644 --- a/src/type-generator.cpp +++ b/src/tools/type-generator/main.cpp @@ -16,7 +16,7 @@ #include "constants.h" #include "finder.h" -#include "stream.h" +#include #include "assert.h" From 810a0676138c7162c33e05f9fce809a1e72d9586 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 20 Feb 2013 22:14:18 -0700 Subject: [PATCH 268/378] move java-specific declarations out of common.h --- src/bootimage.h | 1 + src/common.h | 53 +----------------------------------- src/heapwalk.h | 1 + src/java-common.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++ src/machine.h | 1 + 5 files changed, 73 insertions(+), 52 deletions(-) create mode 100644 src/java-common.h diff --git a/src/bootimage.h b/src/bootimage.h index bf96cdaf17..6baf15ec00 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -12,6 +12,7 @@ #define BOOTIMAGE_H #include "common.h" +#include "java-common.h" #include "target.h" #include "machine.h" diff --git a/src/common.h b/src/common.h index b7408e289a..498c96b7be 100644 --- a/src/common.h +++ b/src/common.h @@ -535,57 +535,6 @@ equal(const void* a, unsigned al, const void* b, unsigned bl) } } -class Machine; -class Thread; - -struct Object { }; - -typedef Object* object; - -typedef uint8_t jboolean; -typedef int8_t jbyte; -typedef uint16_t jchar; -typedef int16_t jshort; -typedef int32_t jint; -typedef int64_t jlong; -typedef float jfloat; -typedef double jdouble; - -typedef jint jsize; - -typedef object* jobject; - -typedef jobject jclass; -typedef jobject jthrowable; -typedef jobject jstring; -typedef jobject jweak; - -typedef jobject jarray; -typedef jarray jbooleanArray; -typedef jarray jbyteArray; -typedef jarray jcharArray; -typedef jarray jshortArray; -typedef jarray jintArray; -typedef jarray jlongArray; -typedef jarray jfloatArray; -typedef jarray jdoubleArray; -typedef jarray jobjectArray; - -typedef uintptr_t jfieldID; -typedef uintptr_t jmethodID; - -union jvalue { - jboolean z; - jbyte b; - jchar c; - jshort s; - jint i; - jlong j; - jfloat f; - jdouble d; - jobject l; -}; - } // namespace vm -#endif//COMMON_H +#endif // COMMON_H diff --git a/src/heapwalk.h b/src/heapwalk.h index 25c681d6a3..96c2374745 100644 --- a/src/heapwalk.h +++ b/src/heapwalk.h @@ -12,6 +12,7 @@ #define HEAPWALK_H #include "common.h" +#include "java-common.h" namespace vm { diff --git a/src/java-common.h b/src/java-common.h new file mode 100644 index 0000000000..ba1be9269a --- /dev/null +++ b/src/java-common.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2008-2012, 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 JAVA_COMMON_H +#define JAVA_COMMON_H + +namespace vm { + +class Machine; +class Thread; + +struct Object { }; + +typedef Object* object; + +typedef uint8_t jboolean; +typedef int8_t jbyte; +typedef uint16_t jchar; +typedef int16_t jshort; +typedef int32_t jint; +typedef int64_t jlong; +typedef float jfloat; +typedef double jdouble; + +typedef jint jsize; + +typedef object* jobject; + +typedef jobject jclass; +typedef jobject jthrowable; +typedef jobject jstring; +typedef jobject jweak; + +typedef jobject jarray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jarray jobjectArray; + +typedef uintptr_t jfieldID; +typedef uintptr_t jmethodID; + +union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +}; + +} // namespace vm + +#endif // JAVA_COMMON_H diff --git a/src/machine.h b/src/machine.h index ff5741c0a2..c39505d20c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -12,6 +12,7 @@ #define MACHINE_H #include "common.h" +#include "java-common.h" #include #include #include "finder.h" From 05b90b65449537a4dc3775001252b8f13a38eeb3 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 07:51:42 -0700 Subject: [PATCH 269/378] begin splitting up type-generator --- src/tools/type-generator/io.h | 149 ++++++++++++++++++++ src/tools/type-generator/main.cpp | 227 +----------------------------- src/tools/type-generator/sexpr.h | 102 ++++++++++++++ 3 files changed, 258 insertions(+), 220 deletions(-) create mode 100644 src/tools/type-generator/io.h create mode 100644 src/tools/type-generator/sexpr.h diff --git a/src/tools/type-generator/io.h b/src/tools/type-generator/io.h new file mode 100644 index 0000000000..f8c7116636 --- /dev/null +++ b/src/tools/type-generator/io.h @@ -0,0 +1,149 @@ +/* Copyright (c) 2008-2011, 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 "assert.h" + +#ifndef AVIAN_TOOLS_TYPE_GENERATOR_IO_H +#define AVIAN_TOOLS_TYPE_GENERATOR_IO_H + +namespace avian { +namespace tools { +namespace typegenerator { + +class Input { + public: + virtual ~Input() { } + + virtual void dispose() = 0; + + virtual int peek() = 0; + + virtual int read() = 0; + + virtual unsigned line() = 0; + + virtual unsigned column() = 0; + + void skipSpace() { + bool quit = false; + while (not quit) { + int c = peek(); + switch (c) { + case ' ': case '\t': case '\n': + read(); + break; + + default: quit = true; + } + } + } +}; + +class FileInput : public Input { + public: + const char* file; + FILE* stream; + unsigned line_; + unsigned column_; + bool close; + + FileInput(const char* file, FILE* stream = 0, bool close = true): + file(file), stream(stream), line_(1), column_(1), close(close) + { } + + virtual ~FileInput() { + dispose(); + } + + virtual void dispose() { + if (stream and close) { + fclose(stream); + stream = 0; + } + } + + virtual int peek() { + int c = getc(stream); + ungetc(c, stream); + return c; + } + + virtual int read() { + int c = getc(stream); + if (c == '\n') { + ++ line_; + column_ = 1; + } else { + ++ column_; + } + return c; + } + + virtual unsigned line() { + return line_; + } + + virtual unsigned column() { + return column_; + } +}; + +class Output { + public: + virtual ~Output() { } + + virtual void dispose() = 0; + + virtual void write(const char* s) = 0; + + void write(int i) { + static const int Size = 32; + char s[Size]; + int c UNUSED = ::snprintf(s, Size, "%d", i); + assert(c > 0 and c < Size); + write(s); + } +}; + +class FileOutput : public Output { + public: + const char* file; + FILE* stream; + bool close; + + FileOutput(const char* file, FILE* stream = 0, bool close = true): + file(file), stream(stream), close(close) + { } + + virtual ~FileOutput() { + dispose(); + } + + virtual void dispose() { + if (stream and close) { + fclose(stream); + stream = 0; + } + } + + virtual void write(const char* s) { + fputs(s, stream); + } + + const char* filename() { + return file; + } +}; + +} // namespace typegenerator +} // namespace tools +} // namespace avian + +#endif // AVIAN_TOOLS_TYPE_GENERATOR_IO_H diff --git a/src/tools/type-generator/main.cpp b/src/tools/type-generator/main.cpp index e0ba6a0169..9186bc68ae 100644 --- a/src/tools/type-generator/main.cpp +++ b/src/tools/type-generator/main.cpp @@ -18,6 +18,9 @@ #include "finder.h" #include +#include "io.h" +#include "sexpr.h" + #include "assert.h" #define UNREACHABLE abort() @@ -29,6 +32,7 @@ inline void operator delete(void*) { abort(); } extern "C" void __cxa_pure_virtual(void) { abort(); } using namespace vm; +using namespace avian::tools::typegenerator; namespace { @@ -55,15 +59,6 @@ pad(unsigned n) return (extra ? n + BytesPerWord - extra : n); } -template -T* -allocate() -{ - T* t = static_cast(malloc(sizeof(T))); - assert(t); - return t; -} - inline bool equal(const char* a, const char* b) { @@ -88,214 +83,6 @@ take(unsigned n, const char* c) return r; } -class Input { - public: - virtual ~Input() { } - - virtual void dispose() = 0; - - virtual int peek() = 0; - - virtual int read() = 0; - - virtual unsigned line() = 0; - - virtual unsigned column() = 0; - - void skipSpace() { - bool quit = false; - while (not quit) { - int c = peek(); - switch (c) { - case ' ': case '\t': case '\n': - read(); - break; - - default: quit = true; - } - } - } -}; - -class FileInput : public Input { - public: - const char* file; - FILE* stream; - unsigned line_; - unsigned column_; - bool close; - - FileInput(const char* file, FILE* stream = 0, bool close = true): - file(file), stream(stream), line_(1), column_(1), close(close) - { } - - virtual ~FileInput() { - dispose(); - } - - virtual void dispose() { - if (stream and close) { - fclose(stream); - stream = 0; - } - } - - virtual int peek() { - int c = getc(stream); - ungetc(c, stream); - return c; - } - - virtual int read() { - int c = getc(stream); - if (c == '\n') { - ++ line_; - column_ = 1; - } else { - ++ column_; - } - return c; - } - - virtual unsigned line() { - return line_; - } - - virtual unsigned column() { - return column_; - } -}; - -class Output { - public: - virtual ~Output() { } - - virtual void dispose() = 0; - - virtual void write(const char* s) = 0; - - void write(int i) { - static const int Size = 32; - char s[Size]; - int c UNUSED = ::snprintf(s, Size, "%d", i); - assert(c > 0 and c < Size); - write(s); - } -}; - -class FileOutput : public Output { - public: - const char* file; - FILE* stream; - bool close; - - FileOutput(const char* file, FILE* stream = 0, bool close = true): - file(file), stream(stream), close(close) - { } - - virtual ~FileOutput() { - dispose(); - } - - virtual void dispose() { - if (stream and close) { - fclose(stream); - stream = 0; - } - } - - virtual void write(const char* s) { - fputs(s, stream); - } - - const char* filename() { - return file; - } -}; - -class Object { - public: - typedef enum { - Scalar, - Array, - Method, - Type, - Pair, - Number, - Character, - String, - Eos - } ObjectType; - - ObjectType type; -}; - -class Pair : public Object { - public: - Object* car; - Object* cdr; - - static Pair* make(Object* car, Object* cdr) { - Pair* o = allocate(); - o->type = Object::Pair; - o->car = car; - o->cdr = cdr; - return o; - } -}; - -Object* -cons(Object* car, Object* cdr) -{ - return Pair::make(car, cdr); -} - -Object*& -car(Object* o) -{ - assert(o->type == Object::Pair); - return static_cast(o)->car; -} - -void -setCar(Object* o, Object* v) -{ - assert(o->type == Object::Pair); - static_cast(o)->car = v; -} - -Object*& -cdr(Object* o) -{ - assert(o->type == Object::Pair); - return static_cast(o)->cdr; -} - -void -setCdr(Object* o, Object* v) -{ - assert(o->type == Object::Pair); - static_cast(o)->cdr = v; -} - -class List { - public: - Object* first; - Object* last; - - List(): first(0), last(0) { } - - void append(Object* o) { - Object* p = cons(o, 0); - if (last) { - setCdr(last, p); - last = p; - } else { - first = last = p; - } - } -}; - class Scalar : public Object { public: Object* owner; @@ -2176,9 +1963,9 @@ main(int ac, char** av) fprintf(stderr, "unable to open %s: %s\n", av[2], strerror(errno)); return -1; } - local::FileInput in(0, inStream, false); + FileInput in(0, inStream, false); - local::Object* declarations = local::parse(finder, &in); + Object* declarations = local::parse(finder, &in); finder->dispose(); system->dispose(); @@ -2188,7 +1975,7 @@ main(int ac, char** av) fprintf(stderr, "unable to open %s: %s\n", av[3], strerror(errno)); return -1; } - local::FileOutput out(0, outStream, false); + FileOutput out(0, outStream, false); if (local::equal(av[4], "enums")) { local::writeEnums(&out, declarations); diff --git a/src/tools/type-generator/sexpr.h b/src/tools/type-generator/sexpr.h new file mode 100644 index 0000000000..cc0b7dc750 --- /dev/null +++ b/src/tools/type-generator/sexpr.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2008-2011, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_TOOLS_TYPE_GENERATOR_SEXPR_H +#define AVIAN_TOOLS_TYPE_GENERATOR_SEXPR_H + +namespace avian { +namespace tools { +namespace typegenerator { + +template +inline T* allocate() { + T* t = static_cast(malloc(sizeof(T))); + assert(t); + return t; +} + +class Object { + public: + typedef enum { + Scalar, + Array, + Method, + Type, + Pair, + Number, + Character, + String, + Eos + } ObjectType; + + ObjectType type; +}; + +class Pair : public Object { + public: + Object* car; + Object* cdr; + + static Pair* make(Object* car, Object* cdr) { + Pair* o = allocate(); + o->type = Object::Pair; + o->car = car; + o->cdr = cdr; + return o; + } +}; + +inline Object* cons(Object* car, Object* cdr) { + return Pair::make(car, cdr); +} + +inline Object*& car(Object* o) { + assert(o->type == Object::Pair); + return static_cast(o)->car; +} + +inline void setCar(Object* o, Object* v) { + assert(o->type == Object::Pair); + static_cast(o)->car = v; +} + +inline Object*& cdr(Object* o) { + assert(o->type == Object::Pair); + return static_cast(o)->cdr; +} + +inline void setCdr(Object* o, Object* v) { + assert(o->type == Object::Pair); + static_cast(o)->cdr = v; +} + +class List { + public: + Object* first; + Object* last; + + List(): first(0), last(0) { } + + void append(Object* o) { + Object* p = cons(o, 0); + if (last) { + setCdr(last, p); + last = p; + } else { + first = last = p; + } + } +}; + +} // namespace typegenerator +} // namespace tools +} // namespace avian + +#endif // AVIAN_TOOLS_TYPE_GENERATOR_SEXPR_H From 186a3993b59f4593fa1368590c37ecbd8db07011 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 13:11:29 -0700 Subject: [PATCH 270/378] move system implementations to src/vm/system/ --- makefile | 4 ++-- src/{ => vm/system}/posix.cpp | 0 src/{ => vm/system}/windows.cpp | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/{ => vm/system}/posix.cpp (100%) rename src/{ => vm/system}/windows.cpp (100%) diff --git a/makefile b/makefile index 30cf4faf70..ac70fe3f1b 100755 --- a/makefile +++ b/makefile @@ -942,7 +942,7 @@ generated-code = \ vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) $(wildcard $(src)/codegen/compiler/*.h) vm-sources = \ - $(src)/$(system).cpp \ + $(src)/vm/system/$(system).cpp \ $(src)/finder.cpp \ $(src)/machine.cpp \ $(src)/util.cpp \ @@ -1072,7 +1072,7 @@ boot-object = $(build)/boot.o generator-depends := $(wildcard $(src)/*.h) generator-sources = \ $(src)/tools/type-generator/main.cpp \ - $(src)/$(build-system).cpp \ + $(src)/vm/system/$(build-system).cpp \ $(src)/finder.cpp ifneq ($(lzma),) diff --git a/src/posix.cpp b/src/vm/system/posix.cpp similarity index 100% rename from src/posix.cpp rename to src/vm/system/posix.cpp diff --git a/src/windows.cpp b/src/vm/system/windows.cpp similarity index 100% rename from src/windows.cpp rename to src/vm/system/windows.cpp From 32044637cd220b7c682b4bcbed802139da73b535 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 13:15:45 -0700 Subject: [PATCH 271/378] move bootimage generator to src/tools --- makefile | 2 +- src/{bootimage.cpp => tools/bootimage-generator/main.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{bootimage.cpp => tools/bootimage-generator/main.cpp} (100%) diff --git a/makefile b/makefile index ac70fe3f1b..7524a163c1 100755 --- a/makefile +++ b/makefile @@ -1036,7 +1036,7 @@ ifeq ($(continuations),true) asmflags += -DAVIAN_CONTINUATIONS endif -bootimage-generator-sources = $(src)/bootimage.cpp +bootimage-generator-sources = $(src)/tools/bootimage-generator/main.cpp ifneq ($(lzma),) bootimage-generator-sources += $(src)/lzma-encode.cpp endif diff --git a/src/bootimage.cpp b/src/tools/bootimage-generator/main.cpp similarity index 100% rename from src/bootimage.cpp rename to src/tools/bootimage-generator/main.cpp From 204bbc134d188fc12d85f25767c8d287fcf09951 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 21 Feb 2013 15:36:01 -0700 Subject: [PATCH 272/378] fix invalid size calculation in ReleaseStringUTFChars --- src/jnienv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 12fd3d9fbc..bcd2c2f05c 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -219,7 +219,7 @@ ReleaseStringUTFChars(Thread* t, jstring s, const char* chars) { ENTER(t, Thread::ActiveState); - t->m->heap->free(chars, stringLength(t, *s) + 1); + t->m->heap->free(chars, stringUTFLength(t, *s) + 1); } void JNICALL From 42d39b1af1fbf06d72b1e02b77999fc58b7eab6f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 21 Feb 2013 15:37:17 -0700 Subject: [PATCH 273/378] more Android class library work --- classpath/avian/Android.java | 30 - classpath/avian/Classes.java | 154 +++++ classpath/avian/SystemClassLoader.java | 26 + classpath/java/lang/Class.java | 105 +--- classpath/java/lang/reflect/Method.java | 69 +-- classpath/java/lang/reflect/Proxy.java | 33 +- makefile | 7 +- src/builtin.cpp | 37 ++ src/classpath-android.cpp | 712 +++++++++++++++++++++++- src/classpath-avian.cpp | 29 - src/classpath-common.h | 254 +++++++++ src/classpath-openjdk.cpp | 259 +-------- src/jnienv.cpp | 45 +- src/machine.cpp | 31 +- src/machine.h | 14 +- src/target.h | 31 +- src/types.def | 4 + 17 files changed, 1327 insertions(+), 513 deletions(-) delete mode 100644 classpath/avian/Android.java diff --git a/classpath/avian/Android.java b/classpath/avian/Android.java deleted file mode 100644 index 720f82341c..0000000000 --- a/classpath/avian/Android.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (c) 2013, 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. */ - -package avian; - -public class Android { - public static VMField findField(VMClass vmClass, String name) { - if (vmClass.fieldTable != null) { - Classes.link(vmClass); - - for (int i = 0; i < vmClass.fieldTable.length; ++i) { - if (getName(vmClass.fieldTable[i]).equals(name)) { - return vmClass.fieldTable[i]; - } - } - } - return null; - } - - public static String getName(VMField vmField) { - return new String(vmField.name, 0, vmField.name.length - 1); - } -} diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index a445114022..e5c3d9fa69 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -16,6 +16,8 @@ import static avian.Stream.read2; import java.lang.reflect.Modifier; import java.lang.reflect.Method; import java.lang.reflect.Field; +import java.lang.reflect.Proxy; +import java.lang.annotation.Annotation; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -262,6 +264,158 @@ public class Classes { link(c, c.loader); } + public static Class forName(String name, boolean initialize, + ClassLoader loader) + throws ClassNotFoundException + { + if (loader == null) { + loader = Class.class.getClassLoader(); + } + Class c = loader.loadClass(name); + VMClass vmc = SystemClassLoader.vmClass(c); + Classes.link(vmc, loader); + if (initialize) { + Classes.initialize(vmc); + } + return c; + } + + public static Class forCanonicalName(String name) { + return forCanonicalName(null, name); + } + + public static Class forCanonicalName(ClassLoader loader, String name) { + try { + if (name.startsWith("[")) { + return forName(name, true, loader); + } else if (name.startsWith("L")) { + return forName(name.substring(1, name.length() - 1), true, loader); + } else { + if (name.length() == 1) { + return SystemClassLoader.getClass + (Classes.primitiveClass(name.charAt(0))); + } else { + throw new ClassNotFoundException(name); + } + } + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static int next(char c, String s, int start) { + for (int i = start; i < s.length(); ++i) { + if (s.charAt(i) == c) return i; + } + throw new RuntimeException(); + } + + public static Class[] getParameterTypes(VMMethod vmMethod) { + int count = vmMethod.parameterCount; + + Class[] types = new Class[count]; + int index = 0; + + String spec = new String + (vmMethod.spec, 1, vmMethod.spec.length - 1); + + try { + for (int i = 0; i < spec.length(); ++i) { + char c = spec.charAt(i); + if (c == ')') { + break; + } else if (c == 'L') { + int start = i + 1; + i = next(';', spec, start); + String name = spec.substring(start, i).replace('/', '.'); + types[index++] = Class.forName(name, true, vmMethod.class_.loader); + } else if (c == '[') { + int start = i; + while (spec.charAt(i) == '[') ++i; + + if (spec.charAt(i) == 'L') { + i = next(';', spec, i + 1); + String name = spec.substring(start, i).replace('/', '.'); + types[index++] = Class.forName + (name, true, vmMethod.class_.loader); + } else { + String name = spec.substring(start, i + 1); + types[index++] = forCanonicalName(vmMethod.class_.loader, name); + } + } else { + String name = spec.substring(i, i + 1); + types[index++] = forCanonicalName(vmMethod.class_.loader, name); + } + } + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + return types; + } + public static int findField(VMClass vmClass, String name) { + if (vmClass.fieldTable != null) { + Classes.link(vmClass); + + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (toString(vmClass.fieldTable[i].name).equals(name)) { + return i; + } + } + } + return -1; + } + + public static String toString(byte[] array) { + return new String(array, 0, array.length - 1); + } + + private static boolean match(Class[] a, Class[] b) { + if (a.length == b.length) { + for (int i = 0; i < a.length; ++i) { + if (! a[i].isAssignableFrom(b[i])) { + return false; + } + } + return true; + } else { + return false; + } + } + + private static int findMethod(VMClass vmClass, String name, + Class[] parameterTypes) + { + if (vmClass.methodTable != null) { + Classes.link(vmClass); + + if (parameterTypes == null) { + parameterTypes = new Class[0]; + } + + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (toString(vmClass.methodTable[i].name).equals(name) + && match(parameterTypes, + getParameterTypes(vmClass.methodTable[i]))) + { + return i; + } + } + } + return -1; + } + + public static Annotation getAnnotation(ClassLoader loader, Object[] a) { + if (a[0] == null) { + a[0] = Proxy.newProxyInstance + (loader, new Class[] { (Class) a[1] }, + new AnnotationInvocationHandler(a)); + } + return (Annotation) a[0]; + } + + public static native Method makeMethod(Class c, int slot); + private static native void acquireClassLock(); private static native void releaseClassLock(); diff --git a/classpath/avian/SystemClassLoader.java b/classpath/avian/SystemClassLoader.java index 5c228cd9c1..db704c6c26 100644 --- a/classpath/avian/SystemClassLoader.java +++ b/classpath/avian/SystemClassLoader.java @@ -28,6 +28,8 @@ public class SystemClassLoader extends ClassLoader { public static native Class getClass(VMClass vmClass); + public static native VMClass vmClass(Class jClass); + private native VMClass findLoadedVMClass(String name); protected Class reallyFindLoadedClass(String name){ @@ -35,6 +37,30 @@ public class SystemClassLoader extends ClassLoader { return c == null ? null : getClass(c); } + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + Class c = findLoadedClass(name); + if (c == null) { + ClassLoader parent = getParent(); + if (parent != null) { + try { + c = parent.loadClass(name); + } catch (ClassNotFoundException ok) { } + } + + if (c == null) { + c = findClass(name); + } + } + + if (resolve) { + resolveClass(c); + } + + return c; + } + private native String resourceURLPrefix(String name); protected URL findResource(String name) { diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index dcef601f12..a37fb96e59 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -145,38 +145,7 @@ public final class Class implements Type, AnnotatedElement { ClassLoader loader) throws ClassNotFoundException { - if (loader == null) { - loader = Class.class.vmClass.loader; - } - Class c = loader.loadClass(name); - Classes.link(c.vmClass, loader); - if (initialize) { - Classes.initialize(c.vmClass); - } - return c; - } - - public static Class forCanonicalName(String name) { - return forCanonicalName(null, name); - } - - public static Class forCanonicalName(ClassLoader loader, String name) { - try { - if (name.startsWith("[")) { - return forName(name, true, loader); - } else if (name.startsWith("L")) { - return forName(name.substring(1, name.length() - 1), true, loader); - } else { - if (name.length() == 1) { - return SystemClassLoader.getClass - (Classes.primitiveClass(name.charAt(0))); - } else { - throw new ClassNotFoundException(name); - } - } - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } + return Classes.forName(name, initialize, loader); } public Class getComponentType() { @@ -211,84 +180,36 @@ public final class Class implements Type, AnnotatedElement { return Classes.isAssignableFrom(vmClass, c.vmClass); } - private static Field findField(VMClass vmClass, String name) { - if (vmClass.fieldTable != null) { - Classes.link(vmClass); - - for (int i = 0; i < vmClass.fieldTable.length; ++i) { - if (Field.getName(vmClass.fieldTable[i]).equals(name)) { - return new Field(vmClass.fieldTable[i]); - } - } - } - return null; - } - public Field getDeclaredField(String name) throws NoSuchFieldException { - Field f = findField(vmClass, name); - if (f == null) { + int index = Classes.findField(vmClass, name); + if (index < 0) { throw new NoSuchFieldException(name); } else { - return f; + return new Field(vmClass.fieldTable[index]); } } public Field getField(String name) throws NoSuchFieldException { for (VMClass c = vmClass; c != null; c = c.super_) { - Field f = findField(c, name); - if (f != null) { - return f; + int index = findField(c, name); + if (index >= 0) { + return new Field(vmClass.fieldTable[index]); } } throw new NoSuchFieldException(name); } - private static boolean match(Class[] a, Class[] b) { - if (a.length == b.length) { - for (int i = 0; i < a.length; ++i) { - if (! a[i].isAssignableFrom(b[i])) { - return false; - } - } - return true; - } else { - return false; - } - } - - private static Method findMethod(VMClass vmClass, String name, - Class[] parameterTypes) - { - if (vmClass.methodTable != null) { - Classes.link(vmClass); - - if (parameterTypes == null) { - parameterTypes = new Class[0]; - } - - for (int i = 0; i < vmClass.methodTable.length; ++i) { - if (Method.getName(vmClass.methodTable[i]).equals(name) - && match(parameterTypes, - Method.getParameterTypes(vmClass.methodTable[i]))) - { - return new Method(vmClass.methodTable[i]); - } - } - } - return null; - } - public Method getDeclaredMethod(String name, Class ... parameterTypes) throws NoSuchMethodException { if (name.startsWith("<")) { throw new NoSuchMethodException(name); } - Method m = findMethod(vmClass, name, parameterTypes); - if (m == null) { + int index = Classes.findMethod(vmClass, name, parameterTypes); + if (index < 0) { throw new NoSuchMethodException(name); } else { - return m; + return new Method(vmClass.methodTable[index]); } } @@ -299,9 +220,9 @@ public final class Class implements Type, AnnotatedElement { throw new NoSuchMethodException(name); } for (VMClass c = vmClass; c != null; c = c.super_) { - Method m = findMethod(c, name, parameterTypes); - if (m != null) { - return m; + int index = findMethod(c, name, parameterTypes); + if (index >= 0) { + return new Method(vmClass.methodTable[index]); } } throw new NoSuchMethodException(name); diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index f90ed311a5..a572f3eb49 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -58,61 +58,8 @@ public class Method extends AccessibleObject implements Member { return new String(vmMethod.spec, 0, vmMethod.spec.length - 1, false); } - private static int next(char c, String s, int start) { - for (int i = start; i < s.length(); ++i) { - if (s.charAt(i) == c) return i; - } - throw new RuntimeException(); - } - public Class[] getParameterTypes() { - return getParameterTypes(vmMethod); - } - - public static Class[] getParameterTypes(VMMethod vmMethod) { - int count = vmMethod.parameterCount; - - Class[] types = new Class[count]; - int index = 0; - - String spec = new String - (vmMethod.spec, 1, vmMethod.spec.length - 1, false); - - try { - for (int i = 0; i < spec.length(); ++i) { - char c = spec.charAt(i); - if (c == ')') { - break; - } else if (c == 'L') { - int start = i + 1; - i = next(';', spec, start); - String name = spec.substring(start, i).replace('/', '.'); - types[index++] = Class.forName(name, true, vmMethod.class_.loader); - } else if (c == '[') { - int start = i; - while (spec.charAt(i) == '[') ++i; - - if (spec.charAt(i) == 'L') { - i = next(';', spec, i + 1); - String name = spec.substring(start, i).replace('/', '.'); - types[index++] = Class.forName - (name, true, vmMethod.class_.loader); - } else { - String name = spec.substring(start, i + 1); - types[index++] = Class.forCanonicalName - (vmMethod.class_.loader, name); - } - } else { - String name = spec.substring(i, i + 1); - types[index++] = Class.forCanonicalName - (vmMethod.class_.loader, name); - } - } - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - - return types; + return Classes.getParameterTypes(vmMethod); } public Object invoke(Object instance, Object ... arguments) @@ -160,22 +107,13 @@ public class Method extends AccessibleObject implements Member { throw new RuntimeException(); } - private Annotation getAnnotation(Object[] a) { - if (a[0] == null) { - a[0] = Proxy.newProxyInstance - (vmMethod.class_.loader, new Class[] { (Class) a[1] }, - new AnnotationInvocationHandler(a)); - } - return (Annotation) a[0]; - } - public T getAnnotation(Class class_) { if (vmMethod.hasAnnotations()) { Object[] table = (Object[]) vmMethod.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; if (a[1] == class_) { - return (T) getAnnotation(a); + return (T) Classes.getAnnotation(vmMethod.class_.loader, a); } } } @@ -187,7 +125,8 @@ public class Method extends AccessibleObject implements Member { Object[] table = (Object[]) vmMethod.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; for (int i = 0; i < table.length; ++i) { - array[i] = getAnnotation((Object[]) table[i]); + array[i] = Classes.getAnnotation + (vmMethod.class_.loader, (Object[]) table[i]); } return array; } else { diff --git a/classpath/java/lang/reflect/Proxy.java b/classpath/java/lang/reflect/Proxy.java index cfc35a6077..f3db1434b5 100644 --- a/classpath/java/lang/reflect/Proxy.java +++ b/classpath/java/lang/reflect/Proxy.java @@ -16,6 +16,9 @@ import static avian.Stream.write4; import static avian.Stream.set4; import static avian.Assembler.*; +import avian.SystemClassLoader; +import avian.Classes; + import avian.ConstantPool; import avian.ConstantPool.PoolEntry; @@ -87,26 +90,15 @@ public class Proxy { write1(out, aload_0); - write1(out, new_); - write2(out, ConstantPool.addClass(pool, "java/lang/reflect/Method") + 1); - write1(out, dup); write1(out, ldc_w); write2(out, ConstantPool.addClass(pool, className) + 1); - write1(out, getfield); - write2(out, ConstantPool.addFieldRef - (pool, "java/lang/Class", - "vmClass", "Lavian/VMClass;") + 1); - write1(out, getfield); - write2(out, ConstantPool.addFieldRef - (pool, "avian/VMClass", - "methodTable", "[Lavian/VMMethod;") + 1); write1(out, ldc_w); write2(out, ConstantPool.addInteger(pool, index) + 1); - write1(out, aaload); - write1(out, invokespecial); + write1(out, invokestatic); write2(out, ConstantPool.addMethodRef - (pool, "java/lang/reflect/Method", - "", "(Lavian/VMMethod;)V") + 1); + (pool, "avian/Classes", + "makeMethod", "(Ljava/lang/Class;I)Ljava/lang/reflect/Method;") + + 1); write1(out, ldc_w); write2(out, ConstantPool.addInteger(pool, parameterCount) + 1); @@ -363,10 +355,11 @@ public class Proxy { Map virtualMap = new HashMap(); for (Class c: interfaces) { - avian.VMMethod[] ivtable = c.vmClass.virtualTable; + avian.VMMethod[] ivtable = SystemClassLoader.vmClass(c).virtualTable; if (ivtable != null) { for (avian.VMMethod m: ivtable) { - virtualMap.put(Method.getName(m) + Method.getSpec(m), m); + virtualMap.put + (Classes.toString(m.name) + Classes.toString(m.spec), m); } } } @@ -376,15 +369,15 @@ public class Proxy { for (avian.VMMethod m: virtualMap.values()) { methodTable[i] = new MethodData (0, - ConstantPool.addUtf8(pool, Method.getName(m)), - ConstantPool.addUtf8(pool, Method.getSpec(m)), + ConstantPool.addUtf8(pool, Classes.toString(m.name)), + ConstantPool.addUtf8(pool, Classes.toString(m.spec)), makeInvokeCode(pool, name, m.spec, m.parameterCount, m.parameterFootprint, i)); ++ i; } methodTable[i++] = new MethodData - (0, + (Modifier.PUBLIC, ConstantPool.addUtf8(pool, ""), ConstantPool.addUtf8 (pool, "(Ljava/lang/reflect/InvocationHandler;)V"), diff --git a/makefile b/makefile index a023f4b6f2..61b3f9b920 100755 --- a/makefile +++ b/makefile @@ -163,7 +163,6 @@ ifneq ($(android),) -I$(android)/libcore/include \ -I$(build)/android-src/external/fdlibm \ -I$(build)/android-src \ - -fpermissive \ -fno-exceptions \ -DHAVE_SYS_UIO_H \ -D_FILE_OFFSET_BITS=64 \ @@ -1200,6 +1199,7 @@ ifneq ($(classpath),avian) # them to synthesize a class: classpath-sources := \ $(classpath-src)/avian/Addendum.java \ + $(classpath-src)/avian/AnnotationInvocationHandler.java \ $(classpath-src)/avian/Assembler.java \ $(classpath-src)/avian/Callback.java \ $(classpath-src)/avian/CallbackReceiver.java \ @@ -1230,7 +1230,7 @@ ifneq ($(classpath),avian) $(classpath-src)/java/net/StandardProtocolFamily.java \ $(classpath-src)/sun/misc/Cleaner.java \ $(classpath-src)/sun/misc/Unsafe.java \ - $(classpath-src)/avian/Android.java + $(classpath-src)/java/lang/reflect/Proxy.java endif else classpath-sources := $(shell find $(classpath-src) -name '*.java') @@ -1432,7 +1432,8 @@ $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas) find $(build)/android-src -name '*.java' > $(build)/android.txt $(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \ @$(build)/android.txt - rm $(build)/android/sun/misc/Unsafe* + rm $(build)/android/sun/misc/Unsafe* \ + $(build)/android/java/lang/reflect/Proxy* cp -r $(build)/android/* $(classpath-build) @touch $(@) diff --git a/src/builtin.cpp b/src/builtin.cpp index b9cfde971d..8ec81eec14 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -50,6 +50,15 @@ resolveSystemClassThrow(Thread* t, object loader, object spec) } // namespace +extern "C" JNIEXPORT void JNICALL +Avian_avian_Classes_initialize +(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + initClass(t, this_); +} + extern "C" JNIEXPORT void JNICALL Avian_avian_Classes_acquireClassLock (Thread* t, object, uintptr_t*) @@ -75,6 +84,26 @@ Avian_avian_Classes_resolveVMClass (resolveClass(t, loader, spec, true, Machine::ClassNotFoundExceptionType)); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_defineVMClass +(Thread* t, object, uintptr_t* arguments) +{ + object loader = reinterpret_cast(arguments[0]); + object b = reinterpret_cast(arguments[1]); + int offset = arguments[2]; + int length = arguments[3]; + + uint8_t* buffer = static_cast + (t->m->heap->allocate(length)); + + THREAD_RESOURCE2(t, uint8_t*, buffer, int, length, + t->m->heap->free(buffer, length)); + + memcpy(buffer, &byteArrayBody(t, b, offset), length); + + return reinterpret_cast(defineClass(t, loader, buffer, length)); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_avian_SystemClassLoader_findLoadedVMClass (Thread* t, object, uintptr_t* arguments) @@ -85,6 +114,14 @@ Avian_avian_SystemClassLoader_findLoadedVMClass return search(t, loader, name, findLoadedClass, true); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_SystemClassLoader_vmClass +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (jclassVmClass(t, reinterpret_cast(arguments[0]))); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_avian_SystemClassLoader_findVMClass (Thread* t, object, uintptr_t* arguments) diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index ef26c514ca..6cbb5a68b2 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -26,6 +26,24 @@ namespace { namespace local { +void JNICALL +loadLibrary(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[1]); + + unsigned length = stringLength(t, name); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), true, true); +} + +int64_t JNICALL +appLoader(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(root(t, Machine::AppLoader)); +} + class MyClasspath : public Classpath { public: MyClasspath(Allocator* allocator): @@ -85,6 +103,21 @@ class MyClasspath : public Classpath { setObjectClass(t, thread, type(t, Machine::ThreadType)); threadPriority(t, thread) = NormalPriority; threadGroup(t, thread) = group; + PROTECT(t, thread); + + { object listClass = resolveClass + (t, root(t, Machine::BootLoader), "java/util/ArrayList"); + PROTECT(t, listClass); + + object instance = makeNew(t, listClass); + PROTECT(t, instance); + + object constructor = resolveMethod(t, listClass, "", "()V"); + + t->m->processor->invoke(t, constructor, instance); + + set(t, thread, ThreadInterruptActions, instance); + } return thread; } @@ -138,6 +171,30 @@ class MyClasspath : public Classpath { virtual void boot(Thread* t) { + { object runtimeClass = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/Runtime", false); + + if (runtimeClass) { + PROTECT(t, runtimeClass); + + intercept(t, runtimeClass, "loadLibrary", + "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", + voidPointer(loadLibrary)); + } + } + + { object classLoaderClass = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/ClassLoader", false); + + if (classLoaderClass) { + PROTECT(t, classLoaderClass); + + intercept(t, classLoaderClass, "createSystemClassLoader", + "()Ljava/lang/ClassLoader;", + voidPointer(appLoader)); + } + } + JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); } @@ -153,6 +210,48 @@ class MyClasspath : public Classpath { // ignore } + virtual object + makeDirectByteBuffer(Thread* t, void* p, jlong capacity) + { + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/nio/ReadWriteDirectByteBuffer"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod(t, c, "", "(II)V"); + + t->m->processor->invoke + (t, constructor, instance, reinterpret_cast(p), + static_cast(capacity)); + + return instance; + } + + virtual void* + getDirectBufferAddress(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField + (t, objectClass(t, b), "effectiveDirectAddress", "I"); + + return reinterpret_cast + (fieldAtOffset(b, fieldOffset(t, field))); + } + + virtual int64_t + getDirectBufferCapacity(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField + (t, objectClass(t, b), "capacity", "I"); + + return fieldAtOffset(b, fieldOffset(t, field)); + } + virtual void dispose() { @@ -162,6 +261,47 @@ class MyClasspath : public Classpath { Allocator* allocator; }; +object +makeMethodOrConstructor(Thread* t, object c, unsigned index) +{ + PROTECT(t, c); + + object method = arrayBody + (t, classMethodTable(t, jclassVmClass(t, c)), index); + PROTECT(t, method); + + unsigned parameterCount; + unsigned returnTypeSpec; + object parameterTypes = resolveParameterJTypes + (t, classLoader(t, methodClass(t, method)), methodSpec(t, method), + ¶meterCount, &returnTypeSpec); + PROTECT(t, parameterTypes); + + object returnType = resolveJType + (t, classLoader(t, methodClass(t, method)), reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), returnTypeSpec)), + byteArrayLength(t, methodSpec(t, method)) - 1 - returnTypeSpec); + PROTECT(t, returnType); + + object exceptionTypes = resolveExceptionJTypes + (t, classLoader(t, methodClass(t, method)), methodAddendum(t, method)); + + if (byteArrayBody(t, methodName(t, method), 0) == '<') { + return makeJconstructor + (t, 0, c, parameterTypes, exceptionTypes, 0, 0, 0, 0, index); + } else { + PROTECT(t, exceptionTypes); + + object name = t->m->classpath->makeString + (t, methodName(t, method), 0, + byteArrayLength(t, methodName(t, method)) - 1); + + return makeJmethod + (t, 0, index, c, name, parameterTypes, exceptionTypes, returnType, 0, 0, + 0, 0, 0); + } +} + } // namespace local } // namespace @@ -346,6 +486,23 @@ Avian_java_lang_String_fastIndexOf return -1; } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_newInstanceImpl +(Thread* t, object, uintptr_t* arguments) +{ + object c = jclassVmClass(t, reinterpret_cast(arguments[0])); + + object method = resolveMethod(t, c, "", "()V"); + PROTECT(t, method); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + t->m->processor->invoke(t, method, instance); + + return reinterpret_cast(instance); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Class_getComponentType (Thread* t, object, uintptr_t* arguments) @@ -366,6 +523,25 @@ Avian_java_lang_Class_getComponentType } } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_classForName +(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[0]); + PROTECT(t, name); + + object loader = reinterpret_cast(arguments[2]); + PROTECT(t, loader); + + object method = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Classes", "forName", + "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); + + return reinterpret_cast + (t->m->processor->invoke + (t, method, 0, name, static_cast(arguments[1]), loader)); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Class_getDeclaredField (Thread* t, object, uintptr_t* arguments) @@ -377,13 +553,17 @@ Avian_java_lang_Class_getDeclaredField PROTECT(t, name); object method = resolveMethod - (t, root(t, Machine::BootLoader), "avian/Android", "findField", - "(Lavian/VMClass;Ljava/lang/String;)Lavian/VMField;"); + (t, root(t, Machine::BootLoader), "avian/Classes", "findField", + "(Lavian/VMClass;Ljava/lang/String;)I"); - object field = t->m->processor->invoke - (t, method, 0, jclassVmClass(t, c), name); + int index = intValue + (t, t->m->processor->invoke + (t, method, 0, jclassVmClass(t, c), name)); + + if (index >= 0) { + object field = arrayBody + (t, classFieldTable(t, jclassVmClass(t, c)), index); - if (field) { PROTECT(t, field); object type = resolveClassBySpec @@ -409,6 +589,75 @@ Avian_java_lang_Class_getDeclaredField } } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getDeclaredConstructorOrMethod +(Thread* t, object, uintptr_t* arguments) +{ + object c = reinterpret_cast(arguments[0]); + PROTECT(t, c); + + object name = reinterpret_cast(arguments[1]); + PROTECT(t, name); + + object parameterTypes = reinterpret_cast(arguments[2]); + PROTECT(t, parameterTypes); + + object method = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Classes", "findMethod", + "(Lavian/VMClass;Ljava/lang/String;[Ljava/lang/Class;)I"); + + int index = intValue + (t, t->m->processor->invoke + (t, method, 0, jclassVmClass(t, c), name, parameterTypes)); + + if (index >= 0) { + return reinterpret_cast + (local::makeMethodOrConstructor(t, c, index)); + } else { + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_SystemClassLoader_findLoadedVMClass +(Thread*, object, uintptr_t*); + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMClassLoader_findLoadedClass +(Thread* t, object method, uintptr_t* arguments) +{ + int64_t v = Avian_avian_SystemClassLoader_findLoadedVMClass + (t, method, arguments); + + if (v) { + return reinterpret_cast + (getJClass(t, reinterpret_cast(v))); + } else { + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_defineVMClass +(Thread*, object, uintptr_t*); + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMClassLoader_defineClass__Ljava_lang_ClassLoader_2Ljava_lang_String_2_3BII +(Thread* t, object method, uintptr_t* arguments) +{ + uintptr_t args[] + = { arguments[0], arguments[2], arguments[3], arguments[4] }; + + int64_t v = Avian_avian_Classes_defineVMClass(t, method, args); + + if (v) { + return reinterpret_cast + (getJClass(t, reinterpret_cast(v))); + } else { + return 0; + } +} + extern "C" JNIEXPORT int64_t JNICALL Avian_dalvik_system_VMRuntime_bootClassPath (Thread* t, object, uintptr_t*) @@ -467,3 +716,456 @@ Avian_java_lang_VMThread_currentThread { return reinterpret_cast(t->javaThread); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMStack_getCallingClassLoader +(Thread* t, object, uintptr_t*) +{ + class Visitor: public Processor::StackVisitor { + public: + Visitor(Thread* t): + t(t), loader(0), counter(2) + { } + + virtual bool visit(Processor::StackWalker* walker) { + if (counter--) { + return true; + } else { + this->loader = classLoader(t, methodClass(t, walker->method())); + return false; + } + } + + Thread* t; + object loader; + unsigned counter; + } v(t); + + t->m->processor->walkStack(t, &v); + + return reinterpret_cast(v.loader); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_min +(Thread*, object, uintptr_t* arguments) +{ + return min(static_cast(arguments[0]), static_cast(arguments[1])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_max +(Thread*, object, uintptr_t* arguments) +{ + return max(static_cast(arguments[0]), static_cast(arguments[1])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Object_getClass +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (getJClass(t, objectClass(t, reinterpret_cast(arguments[0])))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Object_hashCode +(Thread* t, object, uintptr_t* arguments) +{ + return objectHash(t, reinterpret_cast(arguments[0])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Object_internalClone +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (clone(t, reinterpret_cast(arguments[1]))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getModifiers +(Thread* t, object, uintptr_t* arguments) +{ + return classFlags + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getSuperclass +(Thread* t, object, uintptr_t* arguments) +{ + object c = jclassVmClass(t, reinterpret_cast(arguments[0])); + if (classFlags(t, c) & ACC_INTERFACE) { + return 0; + } else { + object s = classSuper(t, c); + return s ? reinterpret_cast(getJClass(t, s)) : 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_desiredAssertionStatus +(Thread*, object, uintptr_t*) +{ + return 1; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getNameNative +(Thread* t, object, uintptr_t* arguments) +{ + object name = className + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))); + + return reinterpret_cast + (t->m->classpath->makeString(t, name, 0, byteArrayLength(t, name) - 1)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_isInterface +(Thread* t, object, uintptr_t* arguments) +{ + return (classFlags + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))) + & ACC_INTERFACE) != 0; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_isPrimitive +(Thread* t, object, uintptr_t* arguments) +{ + return (classVmFlags + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))) + & PrimitiveFlag) != 0; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getClassLoader +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (classLoader + (t, jclassVmClass(t, reinterpret_cast(arguments[0])))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_isAssignableFrom +(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + object that = reinterpret_cast(arguments[1]); + + if (LIKELY(that)) { + return vm::isAssignableFrom + (t, jclassVmClass(t, this_), jclassVmClass(t, that)); + } else { + throwNew(t, Machine::NullPointerExceptionType); + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Method_invokeNative +(Thread* t, object, uintptr_t* arguments) +{ + object instance = reinterpret_cast(arguments[1]); + object args = reinterpret_cast(arguments[2]); + object method = arrayBody + (t, classMethodTable + (t, jclassVmClass(t, reinterpret_cast(arguments[3]))), + arguments[6]); + + return reinterpret_cast(invoke(t, method, instance, args)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Method_getMethodModifiers +(Thread* t, object, uintptr_t* arguments) +{ + return methodFlags + (t, arrayBody + (t, classMethodTable + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))), + arguments[1])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Method_isAnnotationPresent +(Thread* t, object, uintptr_t* arguments) +{ + object method = arrayBody + (t, classMethodTable + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))), + arguments[1]); + + object addendum = methodAddendum(t, method); + if (addendum) { + object table = addendumAnnotationTable(t, addendum); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + if (objectArrayBody(t, objectArrayBody(t, table, i), 1) + == reinterpret_cast(arguments[2])) + { + return true; + } + } + } + } + + return false; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Method_getAnnotation +(Thread* t, object, uintptr_t* arguments) +{ + object method = arrayBody + (t, classMethodTable + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))), + arguments[1]); + + object addendum = methodAddendum(t, method); + if (addendum) { + object table = addendumAnnotationTable(t, addendum); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + if (objectArrayBody(t, objectArrayBody(t, table, i), 1) + == reinterpret_cast(arguments[2])) + { + PROTECT(t, method); + PROTECT(t, table); + + object get = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Classes", "getAnnotation", + "(Ljava/lang/ClassLoader;[Ljava/lang/Object;)" + "Ljava/lang/annotation/Annotation;"); + + return reinterpret_cast + (t->m->processor->invoke + (t, get, 0, classLoader(t, methodClass(t, method)), + objectArrayBody(t, table, i))); + } + } + } + } + + return false; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Method_getDeclaredAnnotations +(Thread* t, object, uintptr_t* arguments) +{ + object method = arrayBody + (t, classMethodTable + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))), + arguments[1]); + + object addendum = methodAddendum(t, method); + if (addendum) { + object table = addendumAnnotationTable(t, addendum); + if (table) { + PROTECT(t, method); + PROTECT(t, table); + + object array = makeObjectArray + (t, resolveClass + (t, root(t, Machine::BootLoader), "java/lang/annotation/Annotation"), + objectArrayLength(t, table)); + PROTECT(t, array); + + object get = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Classes", "getAnnotation", + "(Ljava/lang/ClassLoader;[Ljava/lang/Object;)" + "Ljava/lang/annotation/Annotation;"); + PROTECT(t, get); + + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + object a = t->m->processor->invoke + (t, get, 0, classLoader(t, methodClass(t, method)), + objectArrayBody(t, table, i)); + + set(t, array, ArrayBody + (i * BytesPerWord), a); + } + + return reinterpret_cast(array); + } + } + + return reinterpret_cast + (makeObjectArray + (t, resolveClass + (t, root(t, Machine::BootLoader), "java/lang/annotation/Annotation"), + 0)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Constructor_constructNative +(Thread* t, object, uintptr_t* arguments) +{ + object args = reinterpret_cast(arguments[1]); + PROTECT(t, args); + + object c = jclassVmClass(t, reinterpret_cast(arguments[2])); + + object method = arrayBody(t, classMethodTable(t, c), arguments[4]); + PROTECT(t, method); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + t->m->processor->invokeArray(t, method, instance, args); + + return reinterpret_cast(instance); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Throwable_nativeFillInStackTrace +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(getTrace(t, 2)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_makeMethod +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (local::makeMethodOrConstructor + (t, reinterpret_cast(arguments[0]), arguments[1])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Array_createObjectArray +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (makeObjectArray + (t, jclassVmClass(t, reinterpret_cast(arguments[0])), + arguments[1])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_nio_ByteOrder_isLittleEndian +(Thread*, object, uintptr_t*) +{ +#ifdef ARCH_powerpc + return false; +#else + return true; +#endif +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_newNonMovableArray +(Thread* t, object, uintptr_t* arguments) +{ + if (jclassVmClass(t, reinterpret_cast(arguments[1])) + == type(t, Machine::JbyteType)) + { + object array = allocate3 + (t, t->m->heap, Machine::FixedAllocation, + ArrayBody + arguments[2], false); + + setObjectClass(t, array, type(t, Machine::ByteArrayType)); + byteArrayLength(t, array) = arguments[2]; + + return reinterpret_cast(array); + } else { + // todo + abort(t); + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMRuntime_addressOf +(Thread*, object, uintptr_t* arguments) +{ + return arguments[1] + ArrayBody; +} + +extern "C" JNIEXPORT void JNICALL +Avian_libcore_io_Memory_pokeLong +(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, arguments + 1, 8); + if (arguments[3]) { + v = swapV8(v); + } + memcpy(reinterpret_cast(arguments[0]), &v, 8); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_libcore_io_Memory_peekLong +(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, reinterpret_cast(arguments[0]), 8); + return arguments[1] ? swapV8(v) : v; +} + +extern "C" JNIEXPORT void JNICALL +Avian_libcore_io_Memory_pokeInt +(Thread*, object, uintptr_t* arguments) +{ + int32_t v = arguments[2] ? swapV4(arguments[1]) : arguments[1]; + memcpy(reinterpret_cast(arguments[0]), &v, 4); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_libcore_io_Memory_peekInt +(Thread*, object, uintptr_t* arguments) +{ + int32_t v; memcpy(&v, reinterpret_cast(arguments[0]), 4); + return arguments[1] ? swapV4(v) : v; +} + +extern "C" JNIEXPORT void JNICALL +Avian_libcore_io_Memory_pokeShort +(Thread*, object, uintptr_t* arguments) +{ + int16_t v = arguments[2] ? swapV2(arguments[1]) : arguments[1]; + memcpy(reinterpret_cast(arguments[0]), &v, 2); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_libcore_io_Memory_peekShort +(Thread*, object, uintptr_t* arguments) +{ + int16_t v; memcpy(&v, reinterpret_cast(arguments[0]), 2); + return arguments[1] ? swapV2(v) : v; +} + +extern "C" JNIEXPORT void JNICALL +Avian_libcore_io_Memory_pokeByte +(Thread*, object, uintptr_t* arguments) +{ + *reinterpret_cast(arguments[0]) = arguments[1]; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_libcore_io_Memory_peekByte +(Thread*, object, uintptr_t* arguments) +{ + return *reinterpret_cast(arguments[0]); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_System_nanoTime +(Thread* t, object, uintptr_t*) +{ + return t->m->system->now() * 1000 * 1000; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_System_currentTimeMillis +(Thread* t, object, uintptr_t*) +{ + return t->m->system->now(); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_System_identityHashCode +(Thread* t, object, uintptr_t* arguments) +{ + return objectHash(t, reinterpret_cast(arguments[0])); +} diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index f313bffa01..d5a6ba367a 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -684,35 +684,6 @@ Avian_avian_Classes_primitiveClass return reinterpret_cast(primitiveClass(t, arguments[0])); } -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_Classes_defineVMClass -(Thread* t, object, uintptr_t* arguments) -{ - object loader = reinterpret_cast(arguments[0]); - object b = reinterpret_cast(arguments[1]); - int offset = arguments[2]; - int length = arguments[3]; - - uint8_t* buffer = static_cast - (t->m->heap->allocate(length)); - - THREAD_RESOURCE2(t, uint8_t*, buffer, int, length, - t->m->heap->free(buffer, length)); - - memcpy(buffer, &byteArrayBody(t, b, offset), length); - - return reinterpret_cast(defineClass(t, loader, buffer, length)); -} - -extern "C" JNIEXPORT void JNICALL -Avian_avian_Classes_initialize -(Thread* t, object, uintptr_t* arguments) -{ - object this_ = reinterpret_cast(arguments[0]); - - initClass(t, this_); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_avian_Classes_isAssignableFrom (Thread* t, object, uintptr_t* arguments) diff --git a/src/classpath-common.h b/src/classpath-common.h index ca6649a01e..20b631d8a7 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -355,6 +355,260 @@ resolveClassBySpec(Thread* t, object loader, const char* spec, } } +object +resolveJType(Thread* t, object loader, const char* spec, unsigned specLength) +{ + return getJClass(t, resolveClassBySpec(t, loader, spec, specLength)); +} + +object +resolveParameterTypes(Thread* t, object loader, object spec, + unsigned* parameterCount, unsigned* returnTypeSpec) +{ + PROTECT(t, loader); + PROTECT(t, spec); + + object list = 0; + PROTECT(t, list); + + unsigned offset = 1; + unsigned count = 0; + while (byteArrayBody(t, spec, offset) != ')') { + switch (byteArrayBody(t, spec, offset)) { + case 'L': { + unsigned start = offset; + ++ offset; + while (byteArrayBody(t, spec, offset) != ';') ++ offset; + ++ offset; + + object type = resolveClassBySpec + (t, loader, reinterpret_cast(&byteArrayBody(t, spec, start)), + offset - start); + + list = makePair(t, type, list); + + ++ count; + } break; + + case '[': { + unsigned start = offset; + while (byteArrayBody(t, spec, offset) == '[') ++ offset; + switch (byteArrayBody(t, spec, offset)) { + case 'L': + ++ offset; + while (byteArrayBody(t, spec, offset) != ';') ++ offset; + ++ offset; + break; + + default: + ++ offset; + break; + } + + object type = resolveClassBySpec + (t, loader, reinterpret_cast(&byteArrayBody(t, spec, start)), + offset - start); + + list = makePair(t, type, list); + ++ count; + } break; + + default: + list = makePair + (t, primitiveClass(t, byteArrayBody(t, spec, offset)), list); + ++ offset; + ++ count; + break; + } + } + + *parameterCount = count; + *returnTypeSpec = offset + 1; + return list; +} + +object +resolveParameterJTypes(Thread* t, object loader, object spec, + unsigned* parameterCount, unsigned* returnTypeSpec) +{ + object list = resolveParameterTypes + (t, loader, spec, parameterCount, returnTypeSpec); + + PROTECT(t, list); + + object array = makeObjectArray + (t, type(t, Machine::JclassType), *parameterCount); + PROTECT(t, array); + + for (int i = *parameterCount - 1; i >= 0; --i) { + object c = getJClass(t, pairFirst(t, list)); + set(t, array, ArrayBody + (i * BytesPerWord), c); + list = pairSecond(t, list); + } + + return array; +} + +object +resolveExceptionJTypes(Thread* t, object loader, object addendum) +{ + if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) { + return makeObjectArray(t, type(t, Machine::JclassType), 0); + } + + PROTECT(t, loader); + PROTECT(t, addendum); + + object array = makeObjectArray + (t, type(t, Machine::JclassType), + shortArrayLength(t, methodAddendumExceptionTable(t, addendum))); + PROTECT(t, array); + + for (unsigned i = 0; i < shortArrayLength + (t, methodAddendumExceptionTable(t, addendum)); ++i) + { + uint16_t index = shortArrayBody + (t, methodAddendumExceptionTable(t, addendum), i) - 1; + + object o = singletonObject(t, addendumPool(t, addendum), index); + + if (objectClass(t, o) == type(t, Machine::ReferenceType)) { + o = resolveClass(t, loader, referenceName(t, o)); + + set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord), + o); + } + + o = getJClass(t, o); + + set(t, array, ArrayBody + (i * BytesPerWord), o); + } + + return array; +} + +object +invoke(Thread* t, object method, object instance, object args) +{ + PROTECT(t, method); + PROTECT(t, instance); + PROTECT(t, args); + + if (methodFlags(t, method) & ACC_STATIC) { + instance = 0; + } + + if ((args == 0 ? 0 : objectArrayLength(t, args)) + != methodParameterCount(t, method)) + { + throwNew(t, Machine::IllegalArgumentExceptionType); + } + + if (methodParameterCount(t, method)) { + PROTECT(t, method); + + unsigned specLength = byteArrayLength(t, methodSpec(t, method)); + THREAD_RUNTIME_ARRAY(t, char, spec, specLength); + memcpy(spec, &byteArrayBody(t, methodSpec(t, method), 0), specLength); + unsigned i = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + object type; + bool objectType = false; + const char* p = it.next(); + switch (*p) { + case 'Z': type = vm::type(t, Machine::BooleanType); break; + case 'B': type = vm::type(t, Machine::ByteType); break; + case 'S': type = vm::type(t, Machine::ShortType); break; + case 'C': type = vm::type(t, Machine::CharType); break; + case 'I': type = vm::type(t, Machine::IntType); break; + case 'F': type = vm::type(t, Machine::FloatType); break; + case 'J': type = vm::type(t, Machine::LongType); break; + case 'D': type = vm::type(t, Machine::DoubleType); break; + + case 'L': ++ p; + case '[': { + objectType = true; + unsigned nameLength = it.s - p; + THREAD_RUNTIME_ARRAY(t, char, name, nameLength); + memcpy(name, p, nameLength - 1); + name[nameLength - 1] = 0; + type = resolveClass + (t, classLoader(t, methodClass(t, method)), name); + } break; + + default: + abort(); + } + + object arg = objectArrayBody(t, args, i++); + if ((arg == 0 and (not objectType)) + or (arg and (not instanceOf(t, type, arg)))) + { + // fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast(""), &byteArrayBody(t, className(t, type), 0)); + + throwNew(t, Machine::IllegalArgumentExceptionType); + } + } + } + + unsigned returnCode = methodReturnCode(t, method); + + THREAD_RESOURCE0(t, { + if (t->exception) { + object exception = t->exception; + t->exception = makeThrowable + (t, Machine::InvocationTargetExceptionType, 0, 0, exception); + } + }); + + object result; + if (args) { + result = t->m->processor->invokeArray(t, method, instance, args); + } else { + result = t->m->processor->invoke(t, method, instance); + } + + return translateInvokeResult(t, returnCode, result); +} + +// only safe to call during bootstrap when there's only one thread +// running: +void +intercept(Thread* t, object c, const char* name, const char* spec, + void* function) +{ + object m = findMethodOrNull(t, c, name, spec); + if (m) { + PROTECT(t, m); + + object clone = methodClone(t, m); + + // make clone private to prevent vtable updates at compilation + // time. Otherwise, our interception might be bypassed by calls + // through the vtable. + methodFlags(t, clone) |= ACC_PRIVATE; + + methodFlags(t, m) |= ACC_NATIVE; + + object native = makeNativeIntercept(t, function, true, clone); + + PROTECT(t, native); + + object runtimeData = getMethodRuntimeData(t, m); + + set(t, runtimeData, MethodRuntimeDataNative, native); + } else { + // If we can't find the method, just ignore it, since ProGuard may + // have stripped it out as unused. Otherwise, the code below can + // be uncommented for debugging purposes. + + // fprintf(stderr, "unable to find %s%s in %s\n", + // name, spec, &byteArrayBody(t, className(t, c), 0)); + + // abort(t); + } +} + } // namespace vm #endif//CLASSPATH_COMMON_H diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index df37efceaf..ba49a5f009 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1918,44 +1918,6 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) RUNTIME_ARRAY_BODY(n), not absolute, true); } -// only safe to call during bootstrap when there's only one thread -// running: -void -intercept(Thread* t, object c, const char* name, const char* spec, - void* function) -{ - object m = findMethodOrNull(t, c, name, spec); - if (m) { - PROTECT(t, m); - - object clone = methodClone(t, m); - - // make clone private to prevent vtable updates at compilation - // time. Otherwise, our interception might be bypassed by calls - // through the vtable. - methodFlags(t, clone) |= ACC_PRIVATE; - - methodFlags(t, m) |= ACC_NATIVE; - - object native = makeNativeIntercept(t, function, true, clone); - - PROTECT(t, native); - - object runtimeData = getMethodRuntimeData(t, m); - - set(t, runtimeData, MethodRuntimeDataNative, native); - } else { - // If we can't find the method, just ignore it, since ProGuard may - // have stripped it out as unused. Otherwise, the code below can - // be uncommented for debugging purposes. - - // fprintf(stderr, "unable to find %s%s in %s\n", - // name, spec, &byteArrayBody(t, className(t, c), 0)); - - // abort(t); - } -} - void interceptFileOperations(Thread* t) { @@ -2185,138 +2147,6 @@ countConstructors(Thread* t, object c, bool publicOnly) return count; } -object -resolveJType(Thread* t, object loader, const char* spec, unsigned specLength) -{ - return getJClass(t, resolveClassBySpec(t, loader, spec, specLength)); -} - -object -resolveParameterTypes(Thread* t, object loader, object spec, - unsigned* parameterCount, unsigned* returnTypeSpec) -{ - PROTECT(t, loader); - PROTECT(t, spec); - - object list = 0; - PROTECT(t, list); - - unsigned offset = 1; - unsigned count = 0; - while (byteArrayBody(t, spec, offset) != ')') { - switch (byteArrayBody(t, spec, offset)) { - case 'L': { - unsigned start = offset; - ++ offset; - while (byteArrayBody(t, spec, offset) != ';') ++ offset; - ++ offset; - - object type = resolveClassBySpec - (t, loader, reinterpret_cast(&byteArrayBody(t, spec, start)), - offset - start); - - list = makePair(t, type, list); - - ++ count; - } break; - - case '[': { - unsigned start = offset; - while (byteArrayBody(t, spec, offset) == '[') ++ offset; - switch (byteArrayBody(t, spec, offset)) { - case 'L': - ++ offset; - while (byteArrayBody(t, spec, offset) != ';') ++ offset; - ++ offset; - break; - - default: - ++ offset; - break; - } - - object type = resolveClassBySpec - (t, loader, reinterpret_cast(&byteArrayBody(t, spec, start)), - offset - start); - - list = makePair(t, type, list); - ++ count; - } break; - - default: - list = makePair - (t, primitiveClass(t, byteArrayBody(t, spec, offset)), list); - ++ offset; - ++ count; - break; - } - } - - *parameterCount = count; - *returnTypeSpec = offset + 1; - return list; -} - -object -resolveParameterJTypes(Thread* t, object loader, object spec, - unsigned* parameterCount, unsigned* returnTypeSpec) -{ - object list = resolveParameterTypes - (t, loader, spec, parameterCount, returnTypeSpec); - - PROTECT(t, list); - - object array = makeObjectArray - (t, type(t, Machine::JclassType), *parameterCount); - PROTECT(t, array); - - for (int i = *parameterCount - 1; i >= 0; --i) { - object c = getJClass(t, pairFirst(t, list)); - set(t, array, ArrayBody + (i * BytesPerWord), c); - list = pairSecond(t, list); - } - - return array; -} - -object -resolveExceptionJTypes(Thread* t, object loader, object addendum) -{ - if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) { - return makeObjectArray(t, type(t, Machine::JclassType), 0); - } - - PROTECT(t, loader); - PROTECT(t, addendum); - - object array = makeObjectArray - (t, type(t, Machine::JclassType), - shortArrayLength(t, methodAddendumExceptionTable(t, addendum))); - PROTECT(t, array); - - for (unsigned i = 0; i < shortArrayLength - (t, methodAddendumExceptionTable(t, addendum)); ++i) - { - uint16_t index = shortArrayBody - (t, methodAddendumExceptionTable(t, addendum), i) - 1; - - object o = singletonObject(t, addendumPool(t, addendum), index); - - if (objectClass(t, o) == type(t, Machine::ReferenceType)) { - o = resolveClass(t, loader, referenceName(t, o)); - - set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord), - o); - } - - o = getJClass(t, o); - - set(t, array, ArrayBody + (i * BytesPerWord), o); - } - - return array; -} - object makeJmethod(Thread* t, object vmMethod, int index) { @@ -2330,18 +2160,18 @@ makeJmethod(Thread* t, object vmMethod, int index) unsigned parameterCount; unsigned returnTypeSpec; - object parameterTypes = local::resolveParameterJTypes + object parameterTypes = resolveParameterJTypes (t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod), ¶meterCount, &returnTypeSpec); PROTECT(t, parameterTypes); - object returnType = local::resolveJType + object returnType = resolveJType (t, classLoader(t, methodClass(t, vmMethod)), reinterpret_cast (&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)), byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec); PROTECT(t, returnType); - object exceptionTypes = local::resolveExceptionJTypes + object exceptionTypes = resolveExceptionJTypes (t, classLoader(t, methodClass(t, vmMethod)), methodAddendum(t, vmMethod)); PROTECT(t, exceptionTypes); @@ -2406,12 +2236,12 @@ makeJconstructor(Thread* t, object vmMethod, int index) unsigned parameterCount; unsigned returnTypeSpec; - object parameterTypes = local::resolveParameterJTypes + object parameterTypes = resolveParameterJTypes (t, classLoader(t, methodClass(t, vmMethod)), methodSpec(t, vmMethod), ¶meterCount, &returnTypeSpec); PROTECT(t, parameterTypes); - object exceptionTypes = local::resolveExceptionJTypes + object exceptionTypes = resolveExceptionJTypes (t, classLoader(t, methodClass(t, vmMethod)), methodAddendum(t, vmMethod)); PROTECT(t, exceptionTypes); @@ -4777,83 +4607,10 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) (t, jclassVmClass(t, jmethodClazz(t, *method))), jmethodSlot(t, *method)); - if (methodFlags(t, vmMethod) & ACC_STATIC) { - instance = 0; - } - - if ((args == 0 ? 0 : objectArrayLength(t, *args)) - != methodParameterCount(t, vmMethod)) - { - throwNew(t, Machine::IllegalArgumentExceptionType); - } - - if (methodParameterCount(t, vmMethod)) { - PROTECT(t, vmMethod); - - unsigned specLength = byteArrayLength(t, methodSpec(t, vmMethod)); - THREAD_RUNTIME_ARRAY(t, char, spec, specLength); - memcpy(spec, &byteArrayBody(t, methodSpec(t, vmMethod), 0), specLength); - unsigned i = 0; - for (MethodSpecIterator it(t, spec); it.hasNext();) { - object type; - bool objectType = false; - const char* p = it.next(); - switch (*p) { - case 'Z': type = vm::type(t, Machine::BooleanType); break; - case 'B': type = vm::type(t, Machine::ByteType); break; - case 'S': type = vm::type(t, Machine::ShortType); break; - case 'C': type = vm::type(t, Machine::CharType); break; - case 'I': type = vm::type(t, Machine::IntType); break; - case 'F': type = vm::type(t, Machine::FloatType); break; - case 'J': type = vm::type(t, Machine::LongType); break; - case 'D': type = vm::type(t, Machine::DoubleType); break; - - case 'L': ++ p; - case '[': { - objectType = true; - unsigned nameLength = it.s - p; - THREAD_RUNTIME_ARRAY(t, char, name, nameLength); - memcpy(name, p, nameLength - 1); - name[nameLength - 1] = 0; - type = resolveClass - (t, classLoader(t, methodClass(t, vmMethod)), name); - } break; - - default: - abort(); - } - - object arg = objectArrayBody(t, *args, i++); - if ((arg == 0 and (not objectType)) - or (arg and (not instanceOf(t, type, arg)))) - { - // fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast(""), &byteArrayBody(t, className(t, type), 0)); - - throwNew(t, Machine::IllegalArgumentExceptionType); - } - } - } - - unsigned returnCode = methodReturnCode(t, vmMethod); - - THREAD_RESOURCE0(t, { - if (t->exception) { - object exception = t->exception; - t->exception = makeThrowable - (t, Machine::InvocationTargetExceptionType, 0, 0, exception); - } - }); - - object result; - if (args) { - result = t->m->processor->invokeArray - (t, vmMethod, instance ? *instance : 0, *args); - } else { - result = t->m->processor->invoke(t, vmMethod, instance ? *instance : 0); - } - return reinterpret_cast - (makeLocalReference(t, translateInvokeResult(t, returnCode, result))); + (makeLocalReference + (t, invoke + (t, vmMethod, instance ? *instance : 0, args ? *args : 0))); } extern "C" JNIEXPORT jobject JNICALL diff --git a/src/jnienv.cpp b/src/jnienv.cpp index bcd2c2f05c..b563993369 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3401,27 +3401,56 @@ PopLocalFrame(Thread* t, jobject result) return reinterpret_cast(run(t, popLocalFrame, arguments)); } +uint64_t +newDirectByteBuffer(Thread* t, uintptr_t* arguments) +{ + jlong capacity; memcpy(&capacity, arguments + 1, sizeof(jlong)); + + return reinterpret_cast + (makeLocalReference + (t, t->m->classpath->makeDirectByteBuffer + (t, reinterpret_cast(arguments[0]), capacity))); +} + jobject JNICALL NewDirectByteBuffer(Thread* t, void* p, jlong capacity) { - jclass c = FindClass(t, "java/nio/DirectByteBuffer"); - return NewObject(t, c, GetMethodID(t, c, "", "(JI)V"), - reinterpret_cast(p), - static_cast(capacity)); + uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)]; + arguments[0] = reinterpret_cast(p); + memcpy(arguments + 1, &capacity, sizeof(jlong)); + + return reinterpret_cast(run(t, newDirectByteBuffer, arguments)); +} + +uint64_t +getDirectBufferAddress(Thread* t, uintptr_t* arguments) +{ + return reinterpret_cast + (t->m->classpath->getDirectBufferAddress + (t, *reinterpret_cast(arguments[0]))); } void* JNICALL GetDirectBufferAddress(Thread* t, jobject b) { - return reinterpret_cast - (GetLongField(t, b, GetFieldID(t, GetObjectClass(t, b), "address", "J"))); + uintptr_t arguments[] = { reinterpret_cast(b) }; + + return reinterpret_cast(run(t, getDirectBufferAddress, arguments)); +} + +uint64_t +getDirectBufferCapacity(Thread* t, uintptr_t* arguments) +{ + return t->m->classpath->getDirectBufferCapacity + (t, *reinterpret_cast(arguments[0])); } jlong JNICALL GetDirectBufferCapacity(Thread* t, jobject b) { - return GetIntField - (t, b, GetFieldID(t, GetObjectClass(t, b), "capacity", "I")); + uintptr_t arguments[] = { reinterpret_cast(b) }; + + return run(t, getDirectBufferCapacity, arguments); } struct JavaVMOption { diff --git a/src/machine.cpp b/src/machine.cpp index 8555878c41..ff3fdf814d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2369,8 +2369,6 @@ object makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec, object elementClass) { - // todo: arrays should implement Cloneable and Serializable - if (classVmFlags(t, type(t, Machine::JobjectType)) & BootstrapFlag) { PROTECT(t, loader); PROTECT(t, spec); @@ -2398,7 +2396,7 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec, spec, 0, type(t, Machine::JobjectType), - 0, + root(t, Machine::ArrayInterfaceTable), vtable, 0, 0, @@ -2733,6 +2731,33 @@ boot(Thread* t) setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0)); + { object interfaceTable = makeArray(t, 4); + + set(t, interfaceTable, ArrayBody, type(t, Machine::SerializableType)); + + set(t, interfaceTable, ArrayBody + (2 * BytesPerWord), + type(t, Machine::CloneableType)); + + setRoot(t, Machine::ArrayInterfaceTable, interfaceTable); + } + + set(t, type(t, Machine::BooleanArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + set(t, type(t, Machine::ByteArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + set(t, type(t, Machine::CharArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + set(t, type(t, Machine::ShortArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + set(t, type(t, Machine::IntArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + set(t, type(t, Machine::LongArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + set(t, type(t, Machine::FloatArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + set(t, type(t, Machine::DoubleArrayType), ClassInterfaceTable, + root(t, Machine::ArrayInterfaceTable)); + m->processor->boot(t, 0, 0); { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 1); diff --git a/src/machine.h b/src/machine.h index 1d29cbc88a..1d79cea6d8 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1227,10 +1227,11 @@ class Machine { OutOfMemoryError, Shutdown, VirtualFileFinders, - VirtualFiles + VirtualFiles, + ArrayInterfaceTable }; - static const unsigned RootCount = VirtualFiles + 1; + static const unsigned RootCount = ArrayInterfaceTable + 1; Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, @@ -1569,6 +1570,15 @@ class Classpath { virtual void updatePackageMap(Thread* t, object class_) = 0; + virtual object + makeDirectByteBuffer(Thread* t, void* p, jlong capacity) = 0; + + virtual void* + getDirectBufferAddress(Thread* t, object buffer) = 0; + + virtual int64_t + getDirectBufferCapacity(Thread* t, object buffer) = 0; + virtual void dispose() = 0; }; diff --git a/src/target.h b/src/target.h index f75e575eef..42b07b1dc4 100644 --- a/src/target.h +++ b/src/target.h @@ -23,11 +23,9 @@ targetV1(T v) return v; } -#ifdef TARGET_OPPOSITE_ENDIAN - template inline T -targetV2(T v) +swapV2(T v) { return (((v >> 8) & 0xFF) | ((v << 8))); @@ -35,7 +33,7 @@ targetV2(T v) template inline T -targetV4(T v) +swapV4(T v) { return (((v >> 24) & 0x000000FF) | ((v >> 8) & 0x0000FF00) | @@ -45,7 +43,7 @@ targetV4(T v) template inline T -targetV8(T v) +swapV8(T v) { return (((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | @@ -57,6 +55,29 @@ targetV8(T v) ((static_cast(v) << 56))); } +#ifdef TARGET_OPPOSITE_ENDIAN + +template +inline T +targetV2(T v) +{ + return swapV2(v); +} + +template +inline T +targetV4(T v) +{ + return swapV4(v); +} + +template +inline T +targetV8(T v) +{ + return swapV8(v); +} + #else template inline T diff --git a/src/types.def b/src/types.def index 36f345e4c4..faf1d1341c 100644 --- a/src/types.def +++ b/src/types.def @@ -16,6 +16,10 @@ (type constantPool sun/reflect/ConstantPool) +(type serializable java/io/Serializable) + +(type cloneable java/lang/Cloneable) + (type singleton (array uintptr_t body)) From ab9f9550cf28060b7e78472b20911c0c867327fd Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 16:18:20 -0700 Subject: [PATCH 274/378] move tokenizer.h to include/avian/util/string.h, merge in the String declaration from object-writer/tools.h --- include/avian/tools/object-writer/tools.h | 21 +++------ .../avian/util/string.h | 43 ++++++++++++------- makefile | 6 ++- src/classpath-common.h | 9 ++-- src/finder.cpp | 18 ++++---- src/tools/object-writer/elf.cpp | 1 + src/tools/object-writer/mach-o.cpp | 1 + src/tools/object-writer/pe.cpp | 1 + src/tools/object-writer/tools.cpp | 6 +-- 9 files changed, 58 insertions(+), 48 deletions(-) rename src/tokenizer.h => include/avian/util/string.h (56%) diff --git a/include/avian/tools/object-writer/tools.h b/include/avian/tools/object-writer/tools.h index 46bcd691e8..411dfaec9e 100644 --- a/include/avian/tools/object-writer/tools.h +++ b/include/avian/tools/object-writer/tools.h @@ -12,6 +12,9 @@ #define AVIAN_TOOLS_H_ #include + +#include + #include "environment.h" namespace avian { @@ -38,24 +41,12 @@ public: virtual void write(uint8_t byte); }; -class String { -public: - const char* text; - size_t length; - - String(const char* text); - - inline String(const char* text, size_t length): - text(text), - length(length) {} -}; - class SymbolInfo { public: unsigned addr; - String name; + util::String name; - inline SymbolInfo(uint64_t addr, const String& name): + inline SymbolInfo(uint64_t addr, const util::String& name): addr(addr), name(name) {} @@ -78,7 +69,7 @@ public: class StringTable : public Buffer { public: - unsigned add(String str); + unsigned add(util::String str); }; template diff --git a/src/tokenizer.h b/include/avian/util/string.h similarity index 56% rename from src/tokenizer.h rename to include/avian/util/string.h index 5699227c74..b0b338abfa 100644 --- a/src/tokenizer.h +++ b/include/avian/util/string.h @@ -8,27 +8,37 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#ifndef TOKENIZER_H -#define TOKENIZER_H +#ifndef AVIAN_UTIL_STRING_H +#define AVIAN_UTIL_STRING_H -namespace vm { +#include + +namespace avian { +namespace util { + +class String { +public: + const char* text; + size_t length; + + String(const char* text): + text(text), + length(strlen(text)) {} + + inline String(const char* text, size_t length): + text(text), + length(length) {} +}; class Tokenizer { public: - class Token { - public: - Token(const char* s, unsigned length): s(s), length(length) { } - - const char* s; - unsigned length; - }; Tokenizer(const char* s, char delimiter): s(s), limit(0), delimiter(delimiter) { } - Tokenizer(const char* s, unsigned length, char delimiter): - s(s), limit(s + length), delimiter(delimiter) + Tokenizer(String str, char delimiter): + s(str.text), limit(str.text + str.length), delimiter(delimiter) { } bool hasMore() { @@ -36,10 +46,10 @@ class Tokenizer { return s != limit and *s != 0; } - Token next() { + String next() { const char* p = s; while (s != limit and *s and *s != delimiter) ++s; - return Token(p, s - p); + return String(p, s - p); } const char* s; @@ -47,6 +57,7 @@ class Tokenizer { char delimiter; }; -} // namespace +} // namespace util +} // namespace avain -#endif//TOKENIZER_H +#endif//AVIAN_UTIL_STRING_H diff --git a/makefile b/makefile index 7524a163c1..1251933442 100755 --- a/makefile +++ b/makefile @@ -939,7 +939,11 @@ generated-code = \ $(build)/type-name-initializations.cpp \ $(build)/type-maps.cpp -vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) $(wildcard $(src)/codegen/compiler/*.h) +vm-depends := $(generated-code) \ + $(wildcard $(src)/*.h) \ + $(wildcard $(src)/codegen/*.h) \ + $(wildcard $(src)/codegen/compiler/*.h) \ + $(shell find include -name '*.h') vm-sources = \ $(src)/vm/system/$(system).cpp \ diff --git a/src/classpath-common.h b/src/classpath-common.h index 6298d47695..92ae23c165 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -11,10 +11,11 @@ #ifndef CLASSPATH_COMMON_H #define CLASSPATH_COMMON_H -#include "tokenizer.h" - +#include #include +using namespace avian::util; + namespace vm { object @@ -217,13 +218,13 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, for (Tokenizer tokenizer(path, t->m->system->pathSeparator()); tokenizer.hasMore();) { - Tokenizer::Token token(tokenizer.next()); + String token(tokenizer.next()); unsigned fullNameLength = token.length + 1 + nameLength; THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1); snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1, - "%.*s/%s", token.length, token.s, name); + "%.*s/%s", token.length, token.text, name); lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName)); if (lib) break; diff --git a/src/finder.cpp b/src/finder.cpp index 879796075b..a3fa539910 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -8,15 +8,17 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "zlib-custom.h" #include -#include "tokenizer.h" +#include +#include + +#include "zlib-custom.h" #include "finder.h" #include "lzma.h" -#include using namespace vm; +using namespace avian::util; namespace { @@ -658,12 +660,12 @@ addTokens(System* s, Element** first, Element** last, Allocator* allocator, const char* jarName, unsigned jarNameBase, const char* tokens, unsigned tokensLength, const char* bootLibrary) { - for (Tokenizer t(tokens, tokensLength, ' '); t.hasMore();) { - Tokenizer::Token token(t.next()); + for (Tokenizer t(String(tokens, tokensLength), ' '); t.hasMore();) { + String token(t.next()); RUNTIME_ARRAY(char, n, jarNameBase + token.length + 1); memcpy(RUNTIME_ARRAY_BODY(n), jarName, jarNameBase); - memcpy(RUNTIME_ARRAY_BODY(n) + jarNameBase, token.s, token.length); + memcpy(RUNTIME_ARRAY_BODY(n) + jarNameBase, token.text, token.length); RUNTIME_ARRAY_BODY(n)[jarNameBase + token.length] = 0; add(s, first, last, allocator, RUNTIME_ARRAY_BODY(n), @@ -813,9 +815,9 @@ parsePath(System* s, Allocator* allocator, const char* path, Element* first = 0; Element* last = 0; for (Tokenizer t(path, s->pathSeparator()); t.hasMore();) { - Tokenizer::Token token(t.next()); + String token(t.next()); - add(s, &first, &last, allocator, token.s, token.length, bootLibrary); + add(s, &first, &last, allocator, token.text, token.length, bootLibrary); } return first; diff --git a/src/tools/object-writer/elf.cpp b/src/tools/object-writer/elf.cpp index bf220e1e04..555d6fd9ca 100644 --- a/src/tools/object-writer/elf.cpp +++ b/src/tools/object-writer/elf.cpp @@ -72,6 +72,7 @@ namespace { using namespace avian::tools; +using namespace avian::util; template struct ElfTypes { diff --git a/src/tools/object-writer/mach-o.cpp b/src/tools/object-writer/mach-o.cpp index fac134f272..03066fc247 100644 --- a/src/tools/object-writer/mach-o.cpp +++ b/src/tools/object-writer/mach-o.cpp @@ -43,6 +43,7 @@ namespace { using namespace avian::tools; +using namespace avian::util; typedef int cpu_type_t; typedef int cpu_subtype_t; diff --git a/src/tools/object-writer/pe.cpp b/src/tools/object-writer/pe.cpp index 0fdc4a16e0..b96124582b 100644 --- a/src/tools/object-writer/pe.cpp +++ b/src/tools/object-writer/pe.cpp @@ -86,6 +86,7 @@ pad(unsigned n) } using namespace avian::tools; +using namespace avian::util; template class WindowsPlatform : public Platform { diff --git a/src/tools/object-writer/tools.cpp b/src/tools/object-writer/tools.cpp index 49726245c7..4284778550 100644 --- a/src/tools/object-writer/tools.cpp +++ b/src/tools/object-writer/tools.cpp @@ -15,14 +15,12 @@ #include +using namespace avian::util; + namespace avian { namespace tools { -String::String(const char* text): - text(text), - length(strlen(text)) {} - Buffer::Buffer(): capacity(100), length(0), From 68d28eab2e62697f568013c4cb352a6a1cc54f4c Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 16:29:19 -0700 Subject: [PATCH 275/378] insert RUNTIME_ARRAY_BODY to fix windows.cpp --- src/vm/system/windows.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vm/system/windows.cpp b/src/vm/system/windows.cpp index be3cfbeeef..45b03f6dfe 100644 --- a/src/vm/system/windows.cpp +++ b/src/vm/system/windows.cpp @@ -806,12 +806,12 @@ class MySystem: public System { Status status = 1; size_t nameLen = strlen(name) * 2; RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); - MultiByteToWideChar(CP_UTF8, 0, name, -1, wideName, nameLen + 1); + MultiByteToWideChar(CP_UTF8, 0, name, -1, RUNTIME_ARRAY_BODY(wideName), nameLen + 1); #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - HANDLE file = CreateFileW(wideName, FILE_READ_DATA, FILE_SHARE_READ, 0, + HANDLE file = CreateFileW(RUNTIME_ARRAY_BODY(wideName), FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); #else - HANDLE file = CreateFile2(wideName, GENERIC_READ, FILE_SHARE_READ, + HANDLE file = CreateFile2(RUNTIME_ARRAY_BODY(wideName), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0); #endif if (file != INVALID_HANDLE_VALUE) { @@ -883,10 +883,10 @@ class MySystem: public System { virtual FileType stat(const char* name, unsigned* length) { size_t nameLen = strlen(name) * 2; RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); - MultiByteToWideChar(CP_UTF8, 0, name, -1, wideName, nameLen + 1); + MultiByteToWideChar(CP_UTF8, 0, name, -1, RUNTIME_ARRAY_BODY(wideName), nameLen + 1); WIN32_FILE_ATTRIBUTE_DATA data; if (GetFileAttributesExW - (wideName, GetFileExInfoStandard, &data)) + (RUNTIME_ARRAY_BODY(wideName), GetFileExInfoStandard, &data)) { if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { return TypeDirectory; @@ -935,12 +935,12 @@ class MySystem: public System { if (name) { size_t nameLen = nameLength * 2; RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); - MultiByteToWideChar(CP_UTF8, 0, name, -1, wideName, nameLen + 1); + MultiByteToWideChar(CP_UTF8, 0, name, -1, RUNTIME_ARRAY_BODY(wideName), nameLen + 1); #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - handle = LoadLibraryW(wideName); + handle = LoadLibraryW(RUNTIME_ARRAY_BODY(wideName)); #else - handle = LoadPackagedLibrary(wideName, 0); + handle = LoadPackagedLibrary(RUNTIME_ARRAY_BODY(wideName), 0); #endif } else { #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) From a9e2984aaf60c16981d3124ed2179796e3670d65 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 16:51:31 -0700 Subject: [PATCH 276/378] fix arm and powerpc build --- src/arm.h | 12 ++++++------ src/codegen/arm/assembler.cpp | 8 -------- src/codegen/powerpc/assembler.cpp | 8 -------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/arm.h b/src/arm.h index 5b8cdab3db..47c79ff099 100644 --- a/src/arm.h +++ b/src/arm.h @@ -206,7 +206,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, ++ stackIndex; } - memcpy(stack + stackIndex, arguments + ai, 8); + memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8); stackIndex += 8 / BytesPerWord; } ai += 8 / BytesPerWord; @@ -219,7 +219,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, } else if (vfpIndex < VfpCount) { vfpTable[vfpIndex++] = arguments[ai]; } else { - stack[stackIndex++] = arguments[ai]; + RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai]; } ++ ai; break; @@ -231,7 +231,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, and gprIndex + Alignment == GprCount) { gprTable[gprIndex++] = arguments[ai]; - stack[stackIndex++] = arguments[ai + 1]; + RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1]; } else { if (gprIndex % Alignment) { ++gprIndex; @@ -246,7 +246,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, ++stackIndex; } - memcpy(stack + stackIndex, arguments + ai, 8); + memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8); stackIndex += 8 / BytesPerWord; } ai += 8 / BytesPerWord; @@ -256,7 +256,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, if (gprIndex < GprCount) { gprTable[gprIndex++] = arguments[ai]; } else { - stack[stackIndex++] = arguments[ai]; + RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai]; } ++ ai; } break; @@ -274,7 +274,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2); return vmNativeCall - (function, stackSize, stack, stackIndex * BytesPerWord, + (function, stackSize, RUNTIME_ARRAY_BODY(stack), stackIndex * BytesPerWord, (gprIndex ? gprTable : 0), (vfpIndex ? vfpTable : 0), returnType); } diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index 56bd71938d..26e57a5cb5 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -2236,14 +2236,6 @@ class MyArchitecture: public Assembler::Architecture { virtual int framePointerOffset() { return 0; } - - virtual lir::BinaryOperation hasBinaryIntrinsic(Thread*, object) { - return lir::NoBinaryOperation; - } - - virtual lir::TernaryOperation hasTernaryIntrinsic(Thread*, object) { - return lir::NoTernaryOperation; - } virtual bool alwaysCondensed(lir::BinaryOperation) { return false; diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 1ef611be1a..5086d48403 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -2240,14 +2240,6 @@ class MyArchitecture: public Assembler::Architecture { virtual int framePointerOffset() { return 0; } - - virtual lir::BinaryOperation hasBinaryIntrinsic(Thread*, object) { - return lir::NoBinaryOperation; - } - - virtual lir::TernaryOperation hasTernaryIntrinsic(Thread*, object) { - return lir::NoTernaryOperation; - } virtual bool alwaysCondensed(lir::BinaryOperation) { return false; From 494f773bc9be7e190428b5e48ade2fa924066a8c Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 19:42:29 -0700 Subject: [PATCH 277/378] remove redundency in vm-depends --- makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/makefile b/makefile index 7dabfc197d..81f90291ea 100755 --- a/makefile +++ b/makefile @@ -940,9 +940,6 @@ generated-code = \ $(build)/type-maps.cpp vm-depends := $(generated-code) \ - $(wildcard $(src)/*.h) \ - $(wildcard $(src)/codegen/*.h) \ - $(wildcard $(src)/codegen/compiler/*.h) \ $(shell find src include -name '*.h' -or -name '*.inc.cpp') vm-sources = \ From aaa076f1dfbf7d289ea3d9e75f054b279622d83c Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 20:14:17 -0700 Subject: [PATCH 278/378] move arg-parser.h to include --- {src => include/avian}/util/arg-parser.h | 0 src/tools/audit-codegen/main.cpp | 2 +- src/tools/bootimage-generator/main.cpp | 2 +- src/util/arg-parser.cpp | 2 +- unittest/util/arg-parser-test.cpp | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename {src => include/avian}/util/arg-parser.h (100%) diff --git a/src/util/arg-parser.h b/include/avian/util/arg-parser.h similarity index 100% rename from src/util/arg-parser.h rename to include/avian/util/arg-parser.h diff --git a/src/tools/audit-codegen/main.cpp b/src/tools/audit-codegen/main.cpp index 9fc8d10119..77f0b36e8a 100644 --- a/src/tools/audit-codegen/main.cpp +++ b/src/tools/audit-codegen/main.cpp @@ -10,7 +10,7 @@ #include "system.h" -#include "util/arg-parser.h" +#include #include "codegen/lir.h" #include "codegen/assembler.h" diff --git a/src/tools/bootimage-generator/main.cpp b/src/tools/bootimage-generator/main.cpp index 7688613913..6f27cb5d70 100644 --- a/src/tools/bootimage-generator/main.cpp +++ b/src/tools/bootimage-generator/main.cpp @@ -21,7 +21,7 @@ #include #include "lzma.h" -#include "util/arg-parser.h" +#include #include "util/abort.h" // since we aren't linking against libstdc++, we must implement this diff --git a/src/util/arg-parser.cpp b/src/util/arg-parser.cpp index ac652563be..cefc221532 100644 --- a/src/util/arg-parser.cpp +++ b/src/util/arg-parser.cpp @@ -11,7 +11,7 @@ #include #include -#include "util/arg-parser.h" +#include namespace avian { namespace util { diff --git a/unittest/util/arg-parser-test.cpp b/unittest/util/arg-parser-test.cpp index bd93a04c99..799acba040 100644 --- a/unittest/util/arg-parser-test.cpp +++ b/unittest/util/arg-parser-test.cpp @@ -13,7 +13,7 @@ #include "common.h" -#include "util/arg-parser.h" +#include #include "test-harness.h" From d1a149a0a1e98d99dc521a7f86cc597eb47cb9bb Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 21 Feb 2013 21:57:53 -0700 Subject: [PATCH 279/378] audit-codegen prototype working --- include/avian/vm/codegen/registers.h | 22 ++++++++ src/tools/audit-codegen/main.cpp | 77 +++++++++++++++++++++++----- unittest/codegen/registers-test.cpp | 44 ++++++++++++++++ 3 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 unittest/codegen/registers-test.cpp diff --git a/include/avian/vm/codegen/registers.h b/include/avian/vm/codegen/registers.h index 317bb2215a..32b005d61a 100644 --- a/include/avian/vm/codegen/registers.h +++ b/include/avian/vm/codegen/registers.h @@ -45,6 +45,28 @@ public: { } }; +class RegisterIterator { +public: + int index; + const RegisterMask& mask; + + inline RegisterIterator(const RegisterMask& mask): + index(mask.start), + mask(mask) {} + + inline bool hasNext() { + return index < mask.limit; + } + + inline int next() { + int r = index; + do { + index++; + } while(index < mask.limit && !(mask.mask & (1 << index))); + return r; + } +}; + } // namespace codegen } // namespace avian diff --git a/src/tools/audit-codegen/main.cpp b/src/tools/audit-codegen/main.cpp index 77f0b36e8a..d201cd43a4 100644 --- a/src/tools/audit-codegen/main.cpp +++ b/src/tools/audit-codegen/main.cpp @@ -8,23 +8,80 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "system.h" +#include #include -#include "codegen/lir.h" -#include "codegen/assembler.h" -#include "codegen/targets.h" +#include +#include +#include +#include + +#include // since we aren't linking against libstdc++, we must implement this // ourselves: extern "C" void __cxa_pure_virtual(void) { abort(); } +using namespace vm; using namespace avian::codegen; using namespace avian::util; -void generateCode(Assembler::Architecture* arch) { - for() +class BasicEnv { +public: + System* s; + Heap* heap; + Assembler::Architecture* arch; + + BasicEnv(): + s(makeSystem(0)), + heap(makeHeap(s, 32 * 1024)), + arch(makeArchitectureNative(s, true)) + { + arch->acquire(); + } + + ~BasicEnv() { + arch->release(); + s->dispose(); + } +}; + +class Asm { +public: + Zone zone; + Assembler* a; + + Asm(BasicEnv& env): + zone(env.s, env.heap, 8192), + a(env.arch->makeAssembler(env.heap, &zone)) + { } + + ~Asm() { + a->dispose(); + } +}; + +void generateCode(BasicEnv& env) { + Asm a(env); + for(RegisterIterator it(env.arch->registerFile()->generalRegisters); it.hasNext(); ) { + int r = it.next(); + lir::Register reg(r); + a.a->apply(lir::Add, + OperandInfo(4, lir::RegisterOperand, ®), + OperandInfo(4, lir::RegisterOperand, ®), + OperandInfo(4, lir::RegisterOperand, ®)); + } + unsigned length = a.a->endBlock(false)->resolve(0, 0); + printf("length: %d\n", length); + uint8_t* data = static_cast(env.s->tryAllocate(length)); + a.a->setDestination(data); + a.a->write(); + for(unsigned i = 0; i < length; i++) { + printf("%02x ", data[i]); + } + printf("\n"); + env.s->free(data); } class Arguments { @@ -51,13 +108,9 @@ public: int main(int argc, char** argv) { Arguments args(argc, argv); - vm::System* s = vm::makeSystem(0); - Assembler::Architecture* arch = makeArchitectureNative(s, true); - arch->acquire(); + BasicEnv env; - generateCode(arch); + generateCode(env); - arch->release(); - s->dispose(); return 0; } \ No newline at end of file diff --git a/unittest/codegen/registers-test.cpp b/unittest/codegen/registers-test.cpp new file mode 100644 index 0000000000..946e45ebab --- /dev/null +++ b/unittest/codegen/registers-test.cpp @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2011, 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 + +#include + +#include "test-harness.h" + + +using namespace avian::codegen; +using namespace vm; + + +class RegisterIteratorTest : public Test { +public: + RegisterIteratorTest(): + Test("RegisterIterator") + {} + + virtual void run() { + RegisterMask regs(0x55); + assertEqual(0, regs.start); + assertEqual(7, regs.limit); + + RegisterIterator it(regs); + assertTrue(it.hasNext()); + assertEqual(0, it.next()); + assertTrue(it.hasNext()); + assertEqual(2, it.next()); + assertTrue(it.hasNext()); + assertEqual(4, it.next()); + assertTrue(it.hasNext()); + assertEqual(6, it.next()); + assertFalse(it.hasNext()); + } +} registerIteratorTest; From 201473cf8722585bff7c644178e660a08706da96 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 22 Feb 2013 11:06:49 -0700 Subject: [PATCH 280/378] more work on Android classpath port --- src/android/icu.cpp | 12 + src/builtin.cpp | 7 + src/classpath-android.cpp | 520 +++++++++++++++++++++++++++++++------- src/classpath-avian.cpp | 7 - src/jnienv.cpp | 8 +- src/machine.cpp | 4 - 6 files changed, 447 insertions(+), 111 deletions(-) create mode 100644 src/android/icu.cpp diff --git a/src/android/icu.cpp b/src/android/icu.cpp new file mode 100644 index 0000000000..15b661e4c7 --- /dev/null +++ b/src/android/icu.cpp @@ -0,0 +1,12 @@ +void +register_libcore_icu_ICU(JNIEnv* e) +{ + UErrorCode status = U_ZERO_ERROR; + udata_setFileAccess(UDATA_NO_FILES, &status); + if (status != U_ZERO_ERROR) abort(); + + u_init(&status); + if (status != U_ZERO_ERROR) abort(); + + jniRegisterNativeMethods(e, "libcore/icu/ICU", gMethods, NELEM(gMethods)); +} diff --git a/src/builtin.cpp b/src/builtin.cpp index 8ec81eec14..35a576725d 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -615,3 +615,10 @@ Avian_sun_misc_Unsafe_compareAndSwapInt return atomicCompareAndSwap32 (&fieldAtOffset(target, offset), expect, update); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_primitiveClass +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast(primitiveClass(t, arguments[0])); +} diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 6cbb5a68b2..fbb1dad75e 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -44,6 +44,118 @@ appLoader(Thread* t, object, uintptr_t*) return reinterpret_cast(root(t, Machine::AppLoader)); } +object +makeMethodOrConstructor(Thread* t, object c, unsigned index) +{ + PROTECT(t, c); + + object method = arrayBody + (t, classMethodTable(t, jclassVmClass(t, c)), index); + PROTECT(t, method); + + unsigned parameterCount; + unsigned returnTypeSpec; + object parameterTypes = resolveParameterJTypes + (t, classLoader(t, methodClass(t, method)), methodSpec(t, method), + ¶meterCount, &returnTypeSpec); + PROTECT(t, parameterTypes); + + object returnType = resolveJType + (t, classLoader(t, methodClass(t, method)), reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), returnTypeSpec)), + byteArrayLength(t, methodSpec(t, method)) - 1 - returnTypeSpec); + PROTECT(t, returnType); + + object exceptionTypes = resolveExceptionJTypes + (t, classLoader(t, methodClass(t, method)), methodAddendum(t, method)); + + if (byteArrayBody(t, methodName(t, method), 0) == '<') { + return makeJconstructor + (t, 0, c, parameterTypes, exceptionTypes, 0, 0, 0, 0, index); + } else { + PROTECT(t, exceptionTypes); + + object name = t->m->classpath->makeString + (t, methodName(t, method), 0, + byteArrayLength(t, methodName(t, method)) - 1); + + return makeJmethod + (t, 0, index, c, name, parameterTypes, exceptionTypes, returnType, 0, 0, + 0, 0, 0); + } +} + +object +makeField(Thread* t, object c, unsigned index) +{ + PROTECT(t, c); + + object field = arrayBody + (t, classFieldTable(t, jclassVmClass(t, c)), index); + + PROTECT(t, field); + + object type = resolveClassBySpec + (t, classLoader(t, fieldClass(t, field)), + reinterpret_cast + (&byteArrayBody(t, fieldSpec(t, field), 0)), + byteArrayLength(t, fieldSpec(t, field)) - 1); + PROTECT(t, type); + + object name = t->m->classpath->makeString + (t, fieldName(t, field), 0, + byteArrayLength(t, fieldName(t, field)) - 1); + + return makeJfield(t, 0, c, type, 0, 0, name, index); +} + +void +initVmThread(Thread* t, object thread) +{ + PROTECT(t, thread); + + object field = resolveField + (t, objectClass(t, thread), "vmThread", "Ljava/lang/VMThread;"); + + if (fieldAtOffset(thread, fieldOffset(t, field)) == 0) { + PROTECT(t, field); + + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/VMThread"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod + (t, c, "", "(Ljava/lang/Thread;)V"); + + t->m->processor->invoke(t, constructor, instance, thread); + + set(t, thread, fieldOffset(t, field), instance); + } +} + +object +translateStackTrace(Thread* t, object raw) +{ + PROTECT(t, raw); + + object array = makeObjectArray + (t, resolveClass + (t, root(t, Machine::BootLoader), "java/lang/StackTraceElement"), + objectArrayLength(t, raw)); + PROTECT(t, array); + + for (unsigned i = 0; i < objectArrayLength(t, array); ++i) { + object e = makeStackTraceElement(t, objectArrayBody(t, raw, i)); + + set(t, array, ArrayBody + (i * BytesPerWord), e); + } + + return array; +} + class MyClasspath : public Classpath { public: MyClasspath(Allocator* allocator): @@ -86,64 +198,90 @@ class MyClasspath : public Classpath { virtual object makeThread(Thread* t, Thread* parent) { - const unsigned MaxPriority = 10; const unsigned NormalPriority = 5; - object group; + object group = 0; + PROTECT(t, group); if (parent) { group = threadGroup(t, parent->javaThread); } else { - group = allocate(t, FixedSizeOfThreadGroup, true); - setObjectClass(t, group, type(t, Machine::ThreadGroupType)); - threadGroupMaxPriority(t, group) = MaxPriority; + resolveSystemClass + (t, root(t, Machine::BootLoader), + className(t, type(t, Machine::ThreadGroupType)), false); + + group = makeNew(t, type(t, Machine::ThreadGroupType)); + + object constructor = resolveMethod + (t, type(t, Machine::ThreadGroupType), "", "()V"); + + t->m->processor->invoke(t, constructor, group); } - PROTECT(t, group); - object thread = allocate(t, FixedSizeOfThread, true); - setObjectClass(t, thread, type(t, Machine::ThreadType)); - threadPriority(t, thread) = NormalPriority; - threadGroup(t, thread) = group; + resolveSystemClass + (t, root(t, Machine::BootLoader), + className(t, type(t, Machine::ThreadType)), false); + + object thread = makeNew(t, type(t, Machine::ThreadType)); PROTECT(t, thread); - { object listClass = resolveClass - (t, root(t, Machine::BootLoader), "java/util/ArrayList"); - PROTECT(t, listClass); + object constructor = resolveMethod + (t, type(t, Machine::ThreadType), "", + "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V"); - object instance = makeNew(t, listClass); - PROTECT(t, instance); + t->m->processor->invoke + (t, constructor, thread, group, 0, NormalPriority, false); - object constructor = resolveMethod(t, listClass, "", "()V"); - - t->m->processor->invoke(t, constructor, instance); - - set(t, thread, ThreadInterruptActions, instance); - } + initVmThread(t, thread); return thread; } virtual object - makeJMethod(Thread* t, object) + makeJMethod(Thread* t, object vmMethod) { - abort(t); // todo + object table = classMethodTable(t, methodClass(t, vmMethod)); + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (vmMethod == arrayBody(t, table, i)) { + return makeMethodOrConstructor + (t, getJClass(t, methodClass(t, vmMethod)), i); + } + } + abort(t); } virtual object - getVMMethod(Thread* t, object) + getVMMethod(Thread* t, object jmethod) { - abort(t); // todo + return objectClass(t, jmethod) == type(t, Machine::JmethodType) + ? arrayBody + (t, classMethodTable + (t, jclassVmClass(t, jmethodDeclaringClass(t, jmethod))), + jmethodSlot(t, jmethod)) + : arrayBody + (t, classMethodTable + (t, jclassVmClass(t, jconstructorDeclaringClass(t, jmethod))), + jconstructorSlot(t, jmethod)); } virtual object - makeJField(Thread* t, object) + makeJField(Thread* t, object vmField) { - abort(t); // todo + object table = classFieldTable(t, fieldClass(t, vmField)); + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + if (vmField == arrayBody(t, table, i)) { + return makeField(t, getJClass(t, fieldClass(t, vmField)), i); + } + } + abort(t); } virtual object - getVMField(Thread* t, object) + getVMField(Thread* t, object jfield) { - abort(t); // todo + return arrayBody + (t, classFieldTable + (t, jclassVmClass(t, jfieldDeclaringClass(t, jfield))), + jfieldSlot(t, jfield)); } virtual void @@ -155,11 +293,23 @@ class MyClasspath : public Classpath { virtual void runThread(Thread* t) { - object method = resolveMethod - (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", - "(Ljava/lang/Thread;)V"); + // force monitor creation so we don't get an OutOfMemory error + // later when we try to acquire it: + objectMonitor(t, t->javaThread, true); - t->m->processor->invoke(t, method, 0, t->javaThread); + THREAD_RESOURCE0(t, { + vm::acquire(t, t->javaThread); + t->flags &= ~Thread::ActiveFlag; + vm::notifyAll(t, t->javaThread); + vm::release(t, t->javaThread); + }); + + initVmThread(t, t->javaThread); + + object method = resolveMethod + (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V"); + + t->m->processor->invoke(t, method, t->javaThread); } virtual void @@ -261,47 +411,6 @@ class MyClasspath : public Classpath { Allocator* allocator; }; -object -makeMethodOrConstructor(Thread* t, object c, unsigned index) -{ - PROTECT(t, c); - - object method = arrayBody - (t, classMethodTable(t, jclassVmClass(t, c)), index); - PROTECT(t, method); - - unsigned parameterCount; - unsigned returnTypeSpec; - object parameterTypes = resolveParameterJTypes - (t, classLoader(t, methodClass(t, method)), methodSpec(t, method), - ¶meterCount, &returnTypeSpec); - PROTECT(t, parameterTypes); - - object returnType = resolveJType - (t, classLoader(t, methodClass(t, method)), reinterpret_cast - (&byteArrayBody(t, methodSpec(t, method), returnTypeSpec)), - byteArrayLength(t, methodSpec(t, method)) - 1 - returnTypeSpec); - PROTECT(t, returnType); - - object exceptionTypes = resolveExceptionJTypes - (t, classLoader(t, methodClass(t, method)), methodAddendum(t, method)); - - if (byteArrayBody(t, methodName(t, method), 0) == '<') { - return makeJconstructor - (t, 0, c, parameterTypes, exceptionTypes, 0, 0, 0, 0, index); - } else { - PROTECT(t, exceptionTypes); - - object name = t->m->classpath->makeString - (t, methodName(t, method), 0, - byteArrayLength(t, methodName(t, method)) - 1); - - return makeJmethod - (t, 0, index, c, name, parameterTypes, exceptionTypes, returnType, 0, 0, - 0, 0, 0); - } -} - } // namespace local } // namespace @@ -440,6 +549,28 @@ register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) return 0; } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_String_compareTo +(Thread* t, object, uintptr_t* arguments) +{ + object a = reinterpret_cast(arguments[0]); + object b = reinterpret_cast(arguments[1]); + + unsigned length = stringLength(t, a); + if (length > stringLength(t, b)) { + length = stringLength(t, b); + } + + for (unsigned i = 0; i < length; ++i) { + int d = stringCharAt(t, a, i) - stringCharAt(t, b, i); + if (d) { + return d; + } + } + + return stringLength(t, a) - stringLength(t, b); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_String_isEmpty (Thread* t, object, uintptr_t* arguments) @@ -486,6 +617,34 @@ Avian_java_lang_String_fastIndexOf return -1; } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_getInterfaces +(Thread* t, object, uintptr_t* arguments) +{ + object c = reinterpret_cast(arguments[0]); + + object addendum = classAddendum(t, jclassVmClass(t, c)); + if (addendum) { + object table = classAddendumInterfaceTable(t, addendum); + if (table) { + PROTECT(t, table); + + object array = makeObjectArray(t, arrayLength(t, table)); + PROTECT(t, array); + + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + object c = getJClass(t, arrayBody(t, table, i)); + set(t, array, ArrayBody + (i * BytesPerWord), c); + } + + return reinterpret_cast(array); + } + } + + return reinterpret_cast + (makeObjectArray(t, type(t, Machine::JclassType), 0)); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Class_newInstanceImpl (Thread* t, object, uintptr_t* arguments) @@ -561,29 +720,7 @@ Avian_java_lang_Class_getDeclaredField (t, method, 0, jclassVmClass(t, c), name)); if (index >= 0) { - object field = arrayBody - (t, classFieldTable(t, jclassVmClass(t, c)), index); - - PROTECT(t, field); - - object type = resolveClassBySpec - (t, classLoader(t, fieldClass(t, field)), - reinterpret_cast - (&byteArrayBody(t, fieldSpec(t, field), 0)), - byteArrayLength(t, fieldSpec(t, field)) - 1); - PROTECT(t, type); - - unsigned index = 0xFFFFFFFF; - object table = classFieldTable(t, fieldClass(t, field)); - for (unsigned i = 0; i < arrayLength(t, table); ++i) { - if (field == arrayBody(t, table, i)) { - index = i; - break; - } - } - - return reinterpret_cast - (makeJfield(t, 0, c, type, 0, 0, name, index)); + return reinterpret_cast(local::makeField(t, c, index)); } else { return 0; } @@ -687,6 +824,13 @@ Avian_dalvik_system_VMRuntime_properties (makeObjectArray(t, type(t, Machine::StringType), 0)); } +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_Runtime_gc +(Thread* t, object, uintptr_t*) +{ + collect(t, Heap::MajorCollection); +} + extern "C" JNIEXPORT void JNICALL Avian_java_lang_System_arraycopy (Thread* t, object, uintptr_t* arguments) @@ -710,6 +854,50 @@ Avian_sun_misc_Unsafe_objectFieldOffset jfieldSlot(t, jfield))); } +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_VMThread_interrupt +(Thread* t, object, uintptr_t* arguments) +{ + object vmThread = reinterpret_cast(arguments[0]); + PROTECT(t, vmThread); + + object field = resolveField + (t, objectClass(t, vmThread), "thread", "Ljava/lang/Thread;"); + + interrupt + (t, reinterpret_cast + (threadPeer(t, fieldAtOffset(vmThread, fieldOffset(t, field))))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMThread_interrupted +(Thread* t, object, uintptr_t*) +{ + return getAndClearInterrupted(t, t); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMThread_isInterrupted +(Thread* t, object, uintptr_t* arguments) +{ + object vmThread = reinterpret_cast(arguments[0]); + PROTECT(t, vmThread); + + object field = resolveField + (t, objectClass(t, vmThread), "thread", "Ljava/lang/Thread;"); + + return threadInterrupted + (t, fieldAtOffset(vmThread, fieldOffset(t, field))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_VMThread_getStatus +(Thread*, object, uintptr_t*) +{ + // todo + return -1; +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_VMThread_currentThread (Thread* t, object, uintptr_t*) @@ -717,6 +905,45 @@ Avian_java_lang_VMThread_currentThread return reinterpret_cast(t->javaThread); } +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_VMThread_create +(Thread* t, object, uintptr_t* arguments) +{ + startThread(t, reinterpret_cast(arguments[0])); +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_VMThread_sleep +(Thread* t, object, uintptr_t* arguments) +{ + int64_t milliseconds; memcpy(&milliseconds, arguments, 8); + if (arguments[2] > 0) ++ milliseconds; + if (milliseconds <= 0) milliseconds = 1; + + if (threadSleepLock(t, t->javaThread) == 0) { + object lock = makeJobject(t); + set(t, t->javaThread, ThreadSleepLock, lock); + } + + acquire(t, threadSleepLock(t, t->javaThread)); + vm::wait(t, threadSleepLock(t, t->javaThread), milliseconds); + release(t, threadSleepLock(t, t->javaThread)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_dalvik_system_VMStack_getThreadStackTrace +(Thread* t, object, uintptr_t* arguments) +{ + Thread* p = reinterpret_cast + (threadPeer(t, reinterpret_cast(arguments[0]))); + + return reinterpret_cast + (local::translateStackTrace + (t, p == t + ? makeTrace(t) + : t->m->processor->getStackTrace(t, p))); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_dalvik_system_VMStack_getCallingClassLoader (Thread* t, object, uintptr_t*) @@ -760,6 +987,50 @@ Avian_java_lang_Math_max return max(static_cast(arguments[0]), static_cast(arguments[1])); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_floor +(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, arguments, 8); + return doubleToBits(floor(bitsToDouble(v))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Float_intBitsToFloat +(Thread*, object, uintptr_t* arguments) +{ + return arguments[0]; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Float_floatToIntBits +(Thread*, object, uintptr_t* arguments) +{ + if (((arguments[0] & 0x7F800000) == 0x7F800000) + and ((arguments[0] & 0x007FFFFF) != 0)) + { + return 0x7fc00000; + } else { + return arguments[0]; + } +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_Object_wait +(Thread* t, object, uintptr_t* arguments) +{ + jlong milliseconds; memcpy(&milliseconds, arguments + 1, sizeof(jlong)); + + wait(t, reinterpret_cast(arguments[0]), milliseconds); +} + +extern "C" JNIEXPORT void JNICALL +Avian_java_lang_Object_notifyAll +(Thread* t, object, uintptr_t* arguments) +{ + notifyAll(t, reinterpret_cast(arguments[0])); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Object_getClass (Thread* t, object, uintptr_t* arguments) @@ -857,13 +1128,27 @@ Avian_java_lang_Class_isAssignableFrom object that = reinterpret_cast(arguments[1]); if (LIKELY(that)) { - return vm::isAssignableFrom + return isAssignableFrom (t, jclassVmClass(t, this_), jclassVmClass(t, that)); } else { throwNew(t, Machine::NullPointerExceptionType); } } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Class_isInstance +(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + object o = reinterpret_cast(arguments[1]); + + if (o) { + return instanceOf(t, jclassVmClass(t, this_), o); + } else { + return 0; + } +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_reflect_Method_invokeNative (Thread* t, object, uintptr_t* arguments) @@ -1019,6 +1304,37 @@ Avian_java_lang_reflect_Constructor_constructNative return reinterpret_cast(instance); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Field_getField +(Thread* t, object, uintptr_t* arguments) +{ + object field = arrayBody + (t, classFieldTable + (t, jclassVmClass(t, reinterpret_cast(arguments[2]))), + arguments[4]); + + if (fieldFlags(t, field) & ACC_STATIC) { + return reinterpret_cast + (fieldAtOffset + (classStaticTable(t, fieldClass(t, field)), fieldOffset(t, field))); + } else { + return reinterpret_cast + (fieldAtOffset + (reinterpret_cast(arguments[1]), fieldOffset(t, field))); + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_reflect_Field_getFieldModifiers +(Thread* t, object, uintptr_t* arguments) +{ + return fieldFlags + (t, arrayBody + (t, classFieldTable + (t, jclassVmClass(t, reinterpret_cast(arguments[1]))), + arguments[2])); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Throwable_nativeFillInStackTrace (Thread* t, object, uintptr_t*) @@ -1026,6 +1342,14 @@ Avian_java_lang_Throwable_nativeFillInStackTrace return reinterpret_cast(getTrace(t, 2)); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Throwable_nativeGetStackTrace +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (local::translateStackTrace(t, reinterpret_cast(arguments[0]))); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_avian_Classes_makeMethod (Thread* t, object, uintptr_t* arguments) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index d5a6ba367a..58ab70e792 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -677,13 +677,6 @@ Avian_avian_Atomic_compareAndSwapObject return success; } -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_Classes_primitiveClass -(Thread* t, object, uintptr_t* arguments) -{ - return reinterpret_cast(primitiveClass(t, arguments[0])); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_avian_Classes_isAssignableFrom (Thread* t, object, uintptr_t* arguments) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index b563993369..1a761659b4 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3513,12 +3513,16 @@ boot(Thread* t, uintptr_t*) setRoot(t, Machine::Shutdown, makeThrowable(t, Machine::ThrowableType)); + t->m->classpath->boot(t); + + t->javaThread = t->m->classpath->makeThread(t, 0); + + threadPeer(t, t->javaThread) = reinterpret_cast(t); + setRoot(t, Machine::FinalizerThread, t->m->classpath->makeThread(t, t)); threadDaemon(t, root(t, Machine::FinalizerThread)) = true; - t->m->classpath->boot(t); - enter(t, Thread::IdleState); return 1; diff --git a/src/machine.cpp b/src/machine.cpp index ff3fdf814d..85174ca93c 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3209,10 +3209,6 @@ Thread::init() setRoot(this, Machine::JNIFieldTable, makeVector(this, 0, 0)); m->localThread->set(this); - - javaThread = m->classpath->makeThread(this, 0); - - threadPeer(this, javaThread) = reinterpret_cast(this); } expect(this, m->system->success(m->system->make(&lock))); From 8546ca56701b5b85055fbdca5f60386b5c912543 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 22 Feb 2013 11:55:01 -0700 Subject: [PATCH 281/378] fix Avian classpath build --- classpath/avian/Classes.java | 7 ++- classpath/java/lang/Boolean.java | 2 +- classpath/java/lang/Byte.java | 2 +- classpath/java/lang/Character.java | 2 +- classpath/java/lang/Class.java | 12 ++-- classpath/java/lang/Double.java | 2 +- classpath/java/lang/Float.java | 2 +- classpath/java/lang/Integer.java | 2 +- classpath/java/lang/Long.java | 2 +- classpath/java/lang/Short.java | 2 +- classpath/java/lang/String.java | 5 ++ classpath/java/lang/Void.java | 2 +- classpath/java/lang/reflect/Field.java | 2 +- classpath/java/lang/reflect/Method.java | 3 +- src/classpath-avian.cpp | 79 +++++++++++++++++++++++++ 15 files changed, 106 insertions(+), 20 deletions(-) diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index e5c3d9fa69..a50118e1b3 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -317,7 +317,7 @@ public class Classes { int index = 0; String spec = new String - (vmMethod.spec, 1, vmMethod.spec.length - 1); + (vmMethod.spec, 1, vmMethod.spec.length - 2); try { for (int i = 0; i < spec.length(); ++i) { @@ -353,6 +353,7 @@ public class Classes { return types; } + public static int findField(VMClass vmClass, String name) { if (vmClass.fieldTable != null) { Classes.link(vmClass); @@ -370,7 +371,7 @@ public class Classes { return new String(array, 0, array.length - 1); } - private static boolean match(Class[] a, Class[] b) { + public static boolean match(Class[] a, Class[] b) { if (a.length == b.length) { for (int i = 0; i < a.length; ++i) { if (! a[i].isAssignableFrom(b[i])) { @@ -383,7 +384,7 @@ public class Classes { } } - private static int findMethod(VMClass vmClass, String name, + public static int findMethod(VMClass vmClass, String name, Class[] parameterTypes) { if (vmClass.methodTable != null) { diff --git a/classpath/java/lang/Boolean.java b/classpath/java/lang/Boolean.java index ddd3bec725..be8b57ddcb 100644 --- a/classpath/java/lang/Boolean.java +++ b/classpath/java/lang/Boolean.java @@ -11,7 +11,7 @@ package java.lang; public final class Boolean implements Comparable { - public static final Class TYPE = Class.forCanonicalName("Z"); + public static final Class TYPE = avian.Classes.forCanonicalName("Z"); public static final Boolean FALSE = new Boolean(false); public static final Boolean TRUE = new Boolean(true); diff --git a/classpath/java/lang/Byte.java b/classpath/java/lang/Byte.java index 1133d6ec03..460ff0a51f 100644 --- a/classpath/java/lang/Byte.java +++ b/classpath/java/lang/Byte.java @@ -11,7 +11,7 @@ package java.lang; public final class Byte extends Number implements Comparable { - public static final Class TYPE = Class.forCanonicalName("B"); + public static final Class TYPE = avian.Classes.forCanonicalName("B"); private final byte value; diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 3e7f1ed269..1cbeb1cea7 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -14,7 +14,7 @@ public final class Character implements Comparable { public static final int MIN_RADIX = 2; public static final int MAX_RADIX = 36; - public static final Class TYPE = Class.forCanonicalName("C"); + public static final Class TYPE = avian.Classes.forCanonicalName("C"); private final char value; diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index a37fb96e59..baebcae4c9 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -191,7 +191,7 @@ public final class Class implements Type, AnnotatedElement { public Field getField(String name) throws NoSuchFieldException { for (VMClass c = vmClass; c != null; c = c.super_) { - int index = findField(c, name); + int index = Classes.findField(c, name); if (index >= 0) { return new Field(vmClass.fieldTable[index]); } @@ -220,7 +220,7 @@ public final class Class implements Type, AnnotatedElement { throw new NoSuchMethodException(name); } for (VMClass c = vmClass; c != null; c = c.super_) { - int index = findMethod(c, name, parameterTypes); + int index = Classes.findMethod(c, name, parameterTypes); if (index >= 0) { return new Method(vmClass.methodTable[index]); } @@ -231,11 +231,11 @@ public final class Class implements Type, AnnotatedElement { public Constructor getConstructor(Class ... parameterTypes) throws NoSuchMethodException { - Method m = findMethod(vmClass, "", parameterTypes); - if (m == null) { + int index = Classes.findMethod(vmClass, "", parameterTypes); + if (index < 0) { throw new NoSuchMethodException(); } else { - return new Constructor(m); + return new Constructor(new Method(vmClass.methodTable[index])); } } @@ -246,7 +246,7 @@ public final class Class implements Type, AnnotatedElement { Constructor[] constructors = getDeclaredConstructors(); for (int i = 0; i < constructors.length; ++i) { - if (match(parameterTypes, constructors[i].getParameterTypes())) { + if (Classes.match(parameterTypes, constructors[i].getParameterTypes())) { c = constructors[i]; } } diff --git a/classpath/java/lang/Double.java b/classpath/java/lang/Double.java index a58f9fcb39..8d145ce4d9 100644 --- a/classpath/java/lang/Double.java +++ b/classpath/java/lang/Double.java @@ -11,7 +11,7 @@ package java.lang; public final class Double extends Number { - public static final Class TYPE = Class.forCanonicalName("D"); + public static final Class TYPE = avian.Classes.forCanonicalName("D"); public static final double NEGATIVE_INFINITY = -1.0 / 0.0; public static final double POSITIVE_INFINITY = 1.0 / 0.0; diff --git a/classpath/java/lang/Float.java b/classpath/java/lang/Float.java index f04e728bac..652659f307 100644 --- a/classpath/java/lang/Float.java +++ b/classpath/java/lang/Float.java @@ -11,7 +11,7 @@ package java.lang; public final class Float extends Number { - public static final Class TYPE = Class.forCanonicalName("F"); + public static final Class TYPE = avian.Classes.forCanonicalName("F"); private static final int EXP_BIT_MASK = 0x7F800000; private static final int SIGNIF_BIT_MASK = 0x007FFFFF; diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index 9bd399f227..f5e4052904 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -11,7 +11,7 @@ package java.lang; public final class Integer extends Number implements Comparable { - public static final Class TYPE = Class.forCanonicalName("I"); + public static final Class TYPE = avian.Classes.forCanonicalName("I"); public static final int MIN_VALUE = 0x80000000; public static final int MAX_VALUE = 0x7FFFFFFF; diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index 425e68383a..3023ad03de 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -14,7 +14,7 @@ public final class Long extends Number implements Comparable { public static final long MIN_VALUE = -9223372036854775808l; public static final long MAX_VALUE = 9223372036854775807l; - public static final Class TYPE = Class.forCanonicalName("J"); + public static final Class TYPE = avian.Classes.forCanonicalName("J"); private final long value; diff --git a/classpath/java/lang/Short.java b/classpath/java/lang/Short.java index f218bb8cec..2158c8ebec 100644 --- a/classpath/java/lang/Short.java +++ b/classpath/java/lang/Short.java @@ -11,7 +11,7 @@ package java.lang; public final class Short extends Number implements Comparable { - public static final Class TYPE = Class.forCanonicalName("S"); + public static final Class TYPE = avian.Classes.forCanonicalName("S"); public static final short MAX_VALUE = 32767; private final short value; diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 24a893ad87..ff91fdbc78 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -127,6 +127,11 @@ public final class String } else { c = Utf8.decode((byte[])data, offset, length); if(c instanceof char[]) length = ((char[])c).length; + if (c == null) { + throw new RuntimeException + ("unable to parse \"" + new String(data, offset, length, false) + + "\""); + } } this.data = c; diff --git a/classpath/java/lang/Void.java b/classpath/java/lang/Void.java index 89137eea57..55e28e2abf 100644 --- a/classpath/java/lang/Void.java +++ b/classpath/java/lang/Void.java @@ -11,7 +11,7 @@ package java.lang; public final class Void { - public static final Class TYPE = Class.forCanonicalName("V"); + public static final Class TYPE = avian.Classes.forCanonicalName("V"); private Void() { } } diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 8d76a6258f..f366341534 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -61,7 +61,7 @@ public class Field extends AccessibleObject { } public Class getType() { - return Class.forCanonicalName + return Classes.forCanonicalName (vmField.class_.loader, new String(vmField.spec, 0, vmField.spec.length - 1, false)); } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index a572f3eb49..f06edf4c03 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -13,6 +13,7 @@ package java.lang.reflect; import avian.VMMethod; import avian.AnnotationInvocationHandler; import avian.SystemClassLoader; +import avian.Classes; import java.lang.annotation.Annotation; @@ -98,7 +99,7 @@ public class Method extends AccessibleObject implements Member { public Class getReturnType() { for (int i = 0; i < vmMethod.spec.length - 1; ++i) { if (vmMethod.spec[i] == ')') { - return Class.forCanonicalName + return Classes.forCanonicalName (vmMethod.class_.loader, new String (vmMethod.spec, i + 1, vmMethod.spec.length - i - 2, false)); diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 58ab70e792..7e637c2581 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -127,6 +127,47 @@ class MyClasspath : public Classpath { // ignore } + virtual object + makeDirectByteBuffer(Thread* t, void* p, jlong capacity) + { + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/nio/DirectByteBuffer"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod(t, c, "", "(JI)V"); + + t->m->processor->invoke + (t, constructor, instance, reinterpret_cast(p), + static_cast(capacity)); + + return instance; + } + + virtual void* + getDirectBufferAddress(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField(t, objectClass(t, b), "address", "J"); + + return reinterpret_cast + (fieldAtOffset(b, fieldOffset(t, field))); + } + + virtual int64_t + getDirectBufferCapacity(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField + (t, objectClass(t, b), "capacity", "I"); + + return fieldAtOffset(b, fieldOffset(t, field)); + } + virtual void dispose() { @@ -698,3 +739,41 @@ Avian_avian_Classes_getVMClass return reinterpret_cast (objectClass(t, reinterpret_cast(arguments[0]))); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_makeMethod +(Thread* t, object, uintptr_t* arguments) +{ + object method = arrayBody + (t, classMethodTable + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))), + arguments[1]); + PROTECT(t, method); + + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/reflect/Method"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod(t, c, "", "(Lavian/VMMethod;)V"); + + t->m->processor->invoke(t, constructor, instance, method); + + if (byteArrayBody(t, methodName(t, method), 0) == '<') { + method = instance; + + c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/reflect/Constructor"); + + object instance = makeNew(t, c); + + object constructor = resolveMethod + (t, c, "", "(Ljava/lang/Method;)V"); + + t->m->processor->invoke(t, constructor, instance, method); + } + + return reinterpret_cast(instance); +} From 2f549dd3a3fec3a74cd4c53f5ee42bb87c817e38 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 22 Feb 2013 14:20:09 -0700 Subject: [PATCH 282/378] fix RUNTIME_ARRAY_BODY regressions in classpath-openjdk.cpp --- src/classpath-openjdk.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 074f3cf5f3..d2f628968d 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -339,7 +339,7 @@ makeClassNameString(Thread* t, object name) replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast(&byteArrayBody(t, name, 0))); - return makeString(t, "%s", s); + return makeString(t, "%s", RUNTIME_ARRAY_BODY(s)); } object @@ -755,7 +755,8 @@ class MyClasspath : public Classpath { length); RUNTIME_ARRAY_BODY(packageName)[length] = 0; - object key = vm::makeByteArray(t, "%s", packageName); + object key = vm::makeByteArray + (t, "%s", RUNTIME_ARRAY_BODY(packageName)); PROTECT(t, key); hashMapRemove @@ -775,7 +776,7 @@ class MyClasspath : public Classpath { &byteArrayBody(t, source, PrefixLength), sourceNameLength); - source = vm::makeByteArray(t, "%s", sourceName); + source = vm::makeByteArray(t, "%s", RUNTIME_ARRAY_BODY(sourceName)); } else { source = vm::makeByteArray(t, "avian-dummy-package-source"); } @@ -1528,7 +1529,8 @@ getZipFileEntry(Thread* t, object method, uintptr_t* arguments) RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path) + 1] = 0; } - return reinterpret_cast(find(file, p, byteArrayLength(t, path))); + return reinterpret_cast + (find(file, RUNTIME_ARRAY_BODY(p), byteArrayLength(t, path))); } else { int64_t entry = longValue (t, t->m->processor->invoke @@ -2194,14 +2196,14 @@ resolveClassBySpec(Thread* t, object loader, const char* spec, THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; - return resolveClass(t, loader, s); + return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s)); } case '[': { THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); RUNTIME_ARRAY_BODY(s)[specLength] = 0; - return resolveClass(t, loader, s); + return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s)); } default: @@ -3429,8 +3431,8 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) if (*p == '=') { THREAD_RUNTIME_ARRAY(t, char, name, (p - start) + 1); - memcpy(name, start, p - start); - name[p - start] = 0; + memcpy(RUNTIME_ARRAY_BODY(name), start, p - start); + RUNTIME_ARRAY_BODY(name)[p - start] = 0; local::setProperty (t, method, *properties, RUNTIME_ARRAY_BODY(name), p + 1); } @@ -4829,9 +4831,10 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) unsigned specLength = byteArrayLength(t, methodSpec(t, vmMethod)); THREAD_RUNTIME_ARRAY(t, char, spec, specLength); - memcpy(spec, &byteArrayBody(t, methodSpec(t, vmMethod), 0), specLength); + memcpy(RUNTIME_ARRAY_BODY(spec), + &byteArrayBody(t, methodSpec(t, vmMethod), 0), specLength); unsigned i = 0; - for (MethodSpecIterator it(t, spec); it.hasNext();) { + for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) { object type; bool objectType = false; const char* p = it.next(); @@ -4850,10 +4853,11 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) objectType = true; unsigned nameLength = it.s - p; THREAD_RUNTIME_ARRAY(t, char, name, nameLength); - memcpy(name, p, nameLength - 1); - name[nameLength - 1] = 0; + memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1); + RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0; type = resolveClass - (t, classLoader(t, methodClass(t, vmMethod)), name); + (t, classLoader(t, methodClass(t, vmMethod)), + RUNTIME_ARRAY_BODY(name)); } break; default: From d152f8cf74af4e363292924559c274c94d28bda7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 22 Feb 2013 14:41:24 -0700 Subject: [PATCH 283/378] fix openjdk build --- src/classpath-android.cpp | 8 ++++++- src/classpath-avian.cpp | 6 +++++ src/classpath-openjdk.cpp | 47 +++++++++++++++++++++++++++++++++++++++ src/jnienv.cpp | 4 +++- src/machine.h | 3 +++ 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index fbb1dad75e..4f4b6f7d92 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -319,7 +319,7 @@ class MyClasspath : public Classpath { } virtual void - boot(Thread* t) + preBoot(Thread* t) { { object runtimeClass = resolveClass (t, root(t, Machine::BootLoader), "java/lang/Runtime", false); @@ -348,6 +348,12 @@ class MyClasspath : public Classpath { JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); } + virtual void + boot(Thread*) + { + // ignore + } + virtual const char* bootClasspath() { diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 7e637c2581..1aa165ef36 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -109,6 +109,12 @@ class MyClasspath : public Classpath { vm::resolveNative(t, method); } + virtual void + preBoot(Thread*) + { + // ignore + } + virtual void boot(Thread*) { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index ba49a5f009..516fad4fb1 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -639,6 +639,12 @@ class MyClasspath : public Classpath { vm::resolveNative(t, method); } + virtual void + preBoot(Thread*) + { + // ignore + } + virtual void boot(Thread* t) { @@ -786,6 +792,47 @@ class MyClasspath : public Classpath { } } + virtual object + makeDirectByteBuffer(Thread* t, void* p, jlong capacity) + { + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/nio/DirectByteBuffer"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod(t, c, "", "(JI)V"); + + t->m->processor->invoke + (t, constructor, instance, reinterpret_cast(p), + static_cast(capacity)); + + return instance; + } + + virtual void* + getDirectBufferAddress(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField(t, objectClass(t, b), "address", "J"); + + return reinterpret_cast + (fieldAtOffset(b, fieldOffset(t, field))); + } + + virtual int64_t + getDirectBufferCapacity(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField + (t, objectClass(t, b), "capacity", "I"); + + return fieldAtOffset(b, fieldOffset(t, field)); + } + virtual void dispose() { diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 1a761659b4..3884f04208 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3513,7 +3513,7 @@ boot(Thread* t, uintptr_t*) setRoot(t, Machine::Shutdown, makeThrowable(t, Machine::ThrowableType)); - t->m->classpath->boot(t); + t->m->classpath->preBoot(t); t->javaThread = t->m->classpath->makeThread(t, 0); @@ -3523,6 +3523,8 @@ boot(Thread* t, uintptr_t*) threadDaemon(t, root(t, Machine::FinalizerThread)) = true; + t->m->classpath->boot(t); + enter(t, Thread::IdleState); return 1; diff --git a/src/machine.h b/src/machine.h index 1d79cea6d8..9b425690a3 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1561,6 +1561,9 @@ class Classpath { virtual void resolveNative(Thread* t, object method) = 0; + virtual void + preBoot(Thread* t) = 0; + virtual void boot(Thread* t) = 0; From 5e65468fefa78a4bf38727af6375fbc6e54b3c26 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 22 Feb 2013 14:50:15 -0700 Subject: [PATCH 284/378] fix merge fallout --- src/classpath-android.cpp | 2 -- src/classpath-common.h | 16 +++++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 4f4b6f7d92..34455a4a51 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -18,8 +18,6 @@ extern "C" int JNI_OnLoad(JavaVM*, void*); #include "classpath-common.h" #include "process.h" -#include "util/runtime-array.h" - using namespace vm; namespace { diff --git a/src/classpath-common.h b/src/classpath-common.h index 7501f20281..8ad6bd30fb 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -341,14 +341,14 @@ resolveClassBySpec(Thread* t, object loader, const char* spec, THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; - return resolveClass(t, loader, s); + return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s)); } case '[': { THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); RUNTIME_ARRAY_BODY(s)[specLength] = 0; - return resolveClass(t, loader, s); + return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s)); } default: @@ -510,9 +510,10 @@ invoke(Thread* t, object method, object instance, object args) unsigned specLength = byteArrayLength(t, methodSpec(t, method)); THREAD_RUNTIME_ARRAY(t, char, spec, specLength); - memcpy(spec, &byteArrayBody(t, methodSpec(t, method), 0), specLength); + memcpy(RUNTIME_ARRAY_BODY(spec), + &byteArrayBody(t, methodSpec(t, method), 0), specLength); unsigned i = 0; - for (MethodSpecIterator it(t, spec); it.hasNext();) { + for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) { object type; bool objectType = false; const char* p = it.next(); @@ -531,10 +532,11 @@ invoke(Thread* t, object method, object instance, object args) objectType = true; unsigned nameLength = it.s - p; THREAD_RUNTIME_ARRAY(t, char, name, nameLength); - memcpy(name, p, nameLength - 1); - name[nameLength - 1] = 0; + memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1); + RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0; type = resolveClass - (t, classLoader(t, methodClass(t, method)), name); + (t, classLoader(t, methodClass(t, method)), + RUNTIME_ARRAY_BODY(name)); } break; default: From b32dfb674cb1cb7ad52b1ff696fefe8019413a44 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 22 Feb 2013 14:54:13 -0700 Subject: [PATCH 285/378] fix merge fallout (take 2) --- src/classpath-openjdk.cpp | 80 --------------------------------------- 1 file changed, 80 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 42ff4d5274..ea49d403d3 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4656,86 +4656,6 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) (t, jclassVmClass(t, jmethodClazz(t, *method))), jmethodSlot(t, *method)); -<<<<<<< HEAD -======= - if (methodFlags(t, vmMethod) & ACC_STATIC) { - instance = 0; - } - - if ((args == 0 ? 0 : objectArrayLength(t, *args)) - != methodParameterCount(t, vmMethod)) - { - throwNew(t, Machine::IllegalArgumentExceptionType); - } - - if (methodParameterCount(t, vmMethod)) { - PROTECT(t, vmMethod); - - unsigned specLength = byteArrayLength(t, methodSpec(t, vmMethod)); - THREAD_RUNTIME_ARRAY(t, char, spec, specLength); - memcpy(RUNTIME_ARRAY_BODY(spec), - &byteArrayBody(t, methodSpec(t, vmMethod), 0), specLength); - unsigned i = 0; - for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) { - object type; - bool objectType = false; - const char* p = it.next(); - switch (*p) { - case 'Z': type = vm::type(t, Machine::BooleanType); break; - case 'B': type = vm::type(t, Machine::ByteType); break; - case 'S': type = vm::type(t, Machine::ShortType); break; - case 'C': type = vm::type(t, Machine::CharType); break; - case 'I': type = vm::type(t, Machine::IntType); break; - case 'F': type = vm::type(t, Machine::FloatType); break; - case 'J': type = vm::type(t, Machine::LongType); break; - case 'D': type = vm::type(t, Machine::DoubleType); break; - - case 'L': ++ p; - case '[': { - objectType = true; - unsigned nameLength = it.s - p; - THREAD_RUNTIME_ARRAY(t, char, name, nameLength); - memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1); - RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0; - type = resolveClass - (t, classLoader(t, methodClass(t, vmMethod)), - RUNTIME_ARRAY_BODY(name)); - } break; - - default: - abort(); - } - - object arg = objectArrayBody(t, *args, i++); - if ((arg == 0 and (not objectType)) - or (arg and (not instanceOf(t, type, arg)))) - { - // fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast(""), &byteArrayBody(t, className(t, type), 0)); - - throwNew(t, Machine::IllegalArgumentExceptionType); - } - } - } - - unsigned returnCode = methodReturnCode(t, vmMethod); - - THREAD_RESOURCE0(t, { - if (t->exception) { - object exception = t->exception; - t->exception = makeThrowable - (t, Machine::InvocationTargetExceptionType, 0, 0, exception); - } - }); - - object result; - if (args) { - result = t->m->processor->invokeArray - (t, vmMethod, instance ? *instance : 0, *args); - } else { - result = t->m->processor->invoke(t, vmMethod, instance ? *instance : 0); - } - ->>>>>>> github/master return reinterpret_cast (makeLocalReference (t, invoke From dbbd4e7d40a6f8a9ac9238f5cac2abb7ebe4cf34 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 22 Feb 2013 15:12:05 -0700 Subject: [PATCH 286/378] attempt fix for openjdk tests --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 81f90291ea..e207d5f47c 100755 --- a/makefile +++ b/makefile @@ -1333,7 +1333,7 @@ endif $(build)/run-tests.sh: $(test-classes) makefile echo 'cd $$(dirname $$0)' > $(@) echo "sh ./test.sh 2>/dev/null \\" >> $(@) - echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(name)${exe-suffix} $(mode) \"-Djava.library.path=$$(pwd) -cp test\" \\" >> $(@) + echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(name)${exe-suffix} $(mode) \"-Djava.library.path=. -cp test\" \\" >> $(@) echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@) echo "$(continuation-tests) $(tail-tests)" >> $(@) From fc84f62a65e638ea2231492028fd60704957b8a9 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 22 Feb 2013 16:33:07 -0700 Subject: [PATCH 287/378] prevent garbage collection as vm shuts down --- src/machine.cpp | 5 +++-- src/machine.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index c070391f2a..b65d57360e 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2885,7 +2885,8 @@ doCollect(Thread* t, Heap::CollectionType type) } if ((root(t, Machine::ObjectsToFinalize) or root(t, Machine::ObjectsToClean)) - and m->finalizeThread == 0) + and m->finalizeThread == 0 + and t->state != Thread::ExitState) { m->finalizeThread = m->processor->makeThread (m, root(t, Machine::FinalizerThread), m->rootThread); @@ -3452,7 +3453,7 @@ enter(Thread* t, Thread::State s) switch (t->state) { case Thread::ExclusiveState: { assert(t, t->m->exclusive == t); - t->m->exclusive = 0; + // exit state should also be exclusive, so don't set exclusive = 0 t->m->stateLock->notifyAll(t->systemThread); } break; diff --git a/src/machine.h b/src/machine.h index f00f5a3328..982b4fb086 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1972,6 +1972,7 @@ addThread(Thread* t, Thread* p) ACQUIRE_RAW(t, t->m->stateLock); assert(t, p->state == Thread::NoState); + expect(t, t->state == Thread::ActiveState || t->state == Thread::ExclusiveState); p->state = Thread::IdleState; ++ t->m->threadCount; From 686c2352c102fef3e0a09d4e513eed2d7b1aef6a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 22 Feb 2013 17:23:59 -0700 Subject: [PATCH 288/378] all tests now pass for Android class library build --- makefile | 6 ++ src/classpath-android.cpp | 138 +++++++++++++++++++++++++++++++++++--- src/classpath-common.h | 43 ++++++++++++ src/classpath-openjdk.cpp | 43 ------------ 4 files changed, 178 insertions(+), 52 deletions(-) diff --git a/makefile b/makefile index 68a6fec003..cbe41b04f6 100755 --- a/makefile +++ b/makefile @@ -152,6 +152,7 @@ ifneq ($(android),) options := $(options)-android classpath-jar-dep = $(build)/android.dep luni-native = $(android)/libcore/luni/src/main/native + classpath-cflags = -DBOOT_JAVAHOME android-cflags := -I$(luni-native) \ -I$(android)/libnativehelper/include/nativehelper \ -I$(android)/core/include \ @@ -189,6 +190,11 @@ ifneq ($(android),) $(call java-classes,$(dalvik-javas),$(dalvik-java),$(build)/android) \ $(call java-classes,$(xml-javas),$(xml-java),$(build)/android) classpath = android + + javahome-files = tzdata + javahome-object = $(build)/javahome-jar.o + boot-javahome-object = $(build)/boot-javahome.o + build-javahome = $(android)/bionic/libc/zoneinfo endif ifeq ($(classpath),avian) diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 34455a4a51..bf753540b0 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -42,6 +42,12 @@ appLoader(Thread* t, object, uintptr_t*) return reinterpret_cast(root(t, Machine::AppLoader)); } +int64_t JNICALL +mapData(Thread*, object, uintptr_t*); + +void JNICALL +closeMemoryMappedFile(Thread*, object, uintptr_t*); + object makeMethodOrConstructor(Thread* t, object c, unsigned index) { @@ -319,29 +325,50 @@ class MyClasspath : public Classpath { virtual void preBoot(Thread* t) { - { object runtimeClass = resolveClass + { object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/Runtime", false); - if (runtimeClass) { - PROTECT(t, runtimeClass); + if (c) { + PROTECT(t, c); - intercept(t, runtimeClass, "loadLibrary", + intercept(t, c, "loadLibrary", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", voidPointer(loadLibrary)); } } - { object classLoaderClass = resolveClass + { object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/ClassLoader", false); - if (classLoaderClass) { - PROTECT(t, classLoaderClass); + if (c) { + PROTECT(t, c); - intercept(t, classLoaderClass, "createSystemClassLoader", - "()Ljava/lang/ClassLoader;", + intercept(t, c, "createSystemClassLoader", "()Ljava/lang/ClassLoader;", voidPointer(appLoader)); } } + + { object c = resolveClass + (t, root(t, Machine::BootLoader), "libcore/util/ZoneInfoDB", false); + + if (c) { + PROTECT(t, c); + + intercept(t, c, "mapData", "()Llibcore/io/MemoryMappedFile;", + voidPointer(mapData)); + } + } + + { object c = resolveClass + (t, root(t, Machine::BootLoader), "libcore/io/MemoryMappedFile", + false); + + if (c) { + PROTECT(t, c); + + intercept(t, c, "close", "()V", voidPointer(closeMemoryMappedFile)); + } + } JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); } @@ -409,12 +436,78 @@ class MyClasspath : public Classpath { virtual void dispose() { + if (tzdata) { + tzdata->dispose(); + } allocator->free(this, sizeof(*this)); } Allocator* allocator; + System::Region* tzdata; }; +int64_t JNICALL +mapData(Thread* t, object, uintptr_t*) +{ + object c = resolveClass + (t, root(t, Machine::BootLoader), "libcore/io/MemoryMappedFile"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod(t, c, "", "(JJ)V"); + + const char* jar = "javahomeJar"; + Finder* finder = getFinder(t, jar, strlen(jar)); + if (finder) { + System::Region* r = finder->find("tzdata"); + if (r) { + MyClasspath* cp = static_cast(t->m->classpath); + + expect(t, cp->tzdata == 0); + + cp->tzdata = r; + + t->m->processor->invoke + (t, constructor, instance, reinterpret_cast(r->start()), + static_cast(r->length())); + + return reinterpret_cast(instance); + } + } + + throwNew(t, Machine::RuntimeExceptionType); +} + +void JNICALL +closeMemoryMappedFile(Thread* t, object method, uintptr_t* arguments) +{ + object file = reinterpret_cast(arguments[0]); + PROTECT(t, file); + + MyClasspath* cp = static_cast(t->m->classpath); + + if (cp->tzdata) { + object field = resolveField(t, objectClass(t, file), "address", "J"); + + if (fieldAtOffset(file, fieldOffset(t, field)) + == reinterpret_cast(cp->tzdata->start())) + { + cp->tzdata->dispose(); + cp->tzdata = 0; + + fieldAtOffset(file, fieldOffset(t, field)) = 0; + return; + } + } + + t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + file); +} + } // namespace local } // namespace @@ -999,6 +1092,22 @@ Avian_java_lang_Math_floor return doubleToBits(floor(bitsToDouble(v))); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_ceil +(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, arguments, 8); + return doubleToBits(ceil(bitsToDouble(v))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_log +(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, arguments, 8); + return doubleToBits(log(bitsToDouble(v))); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Float_intBitsToFloat (Thread*, object, uintptr_t* arguments) @@ -1019,6 +1128,17 @@ Avian_java_lang_Float_floatToIntBits } } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Double_doubleToRawLongBits +(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, arguments, 8); + // todo: do we need to do NaN checks as in + // Avian_java_lang_Float_floatToIntBits above? If so, update + // Double.doubleToRawLongBits in the Avian class library too. + return v; +} + extern "C" JNIEXPORT void JNICALL Avian_java_lang_Object_wait (Thread* t, object, uintptr_t* arguments) diff --git a/src/classpath-common.h b/src/classpath-common.h index 8ad6bd30fb..c13d447386 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -612,6 +612,49 @@ intercept(Thread* t, object c, const char* name, const char* spec, } } +Finder* +getFinder(Thread* t, const char* name, unsigned nameLength) +{ + ACQUIRE(t, t->m->referenceLock); + + for (object p = root(t, Machine::VirtualFileFinders); + p; p = finderNext(t, p)) + { + if (byteArrayLength(t, finderName(t, p)) == nameLength + and strncmp(reinterpret_cast + (&byteArrayBody(t, finderName(t, p), 0)), + name, nameLength)) + { + return static_cast(finderFinder(t, p)); + } + } + + object n = makeByteArray(t, nameLength + 1); + memcpy(&byteArrayBody(t, n, 0), name, nameLength); + + void* p = t->m->libraries->resolve + (reinterpret_cast(&byteArrayBody(t, n, 0))); + + if (p) { + uint8_t* (*function)(unsigned*); + memcpy(&function, &p, BytesPerWord); + + unsigned size; + uint8_t* data = function(&size); + if (data) { + Finder* f = makeFinder(t->m->system, t->m->heap, data, size); + object finder = makeFinder + (t, f, n, root(t, Machine::VirtualFileFinders)); + + setRoot(t, Machine::VirtualFileFinders, finder); + + return f; + } + } + + return 0; +} + } // namespace vm #endif//CLASSPATH_COMMON_H diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index ea49d403d3..1b44fdada5 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -886,49 +886,6 @@ struct jvm_version_info { unsigned: 32; }; -Finder* -getFinder(Thread* t, const char* name, unsigned nameLength) -{ - ACQUIRE(t, t->m->referenceLock); - - for (object p = root(t, Machine::VirtualFileFinders); - p; p = finderNext(t, p)) - { - if (byteArrayLength(t, finderName(t, p)) == nameLength - and strncmp(reinterpret_cast - (&byteArrayBody(t, finderName(t, p), 0)), - name, nameLength)) - { - return static_cast(finderFinder(t, p)); - } - } - - object n = makeByteArray(t, nameLength + 1); - memcpy(&byteArrayBody(t, n, 0), name, nameLength); - - void* p = t->m->libraries->resolve - (reinterpret_cast(&byteArrayBody(t, n, 0))); - - if (p) { - uint8_t* (*function)(unsigned*); - memcpy(&function, &p, BytesPerWord); - - unsigned size; - uint8_t* data = function(&size); - if (data) { - Finder* f = makeFinder(t->m->system, t->m->heap, data, size); - object finder = makeFinder - (t, f, n, root(t, Machine::VirtualFileFinders)); - - setRoot(t, Machine::VirtualFileFinders, finder); - - return f; - } - } - - return 0; -} - bool pathEqual(const char* a, const char* b, unsigned length) { From fd59e1e08d50ab05a830a1a30f598aed1822edf8 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 22 Feb 2013 20:47:56 -0700 Subject: [PATCH 289/378] begin splitting out arm assembler --- src/codegen/arm/assembler.cpp | 147 ++++++---------------------------- src/codegen/arm/block.cpp | 39 +++++++++ src/codegen/arm/block.h | 47 +++++++++++ src/codegen/arm/context.cpp | 27 +++++++ src/codegen/arm/context.h | 108 +++++++++++++++++++++++++ 5 files changed, 244 insertions(+), 124 deletions(-) create mode 100644 src/codegen/arm/block.cpp create mode 100644 src/codegen/arm/block.h create mode 100644 src/codegen/arm/context.cpp create mode 100644 src/codegen/arm/context.h diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index 5053654610..c4b4ca7dfe 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -8,13 +8,17 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include + #include #include +#include "context.h" +#include "block.h" + #include "alloc-vector.h" #include -#include #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) @@ -25,7 +29,8 @@ using namespace vm; using namespace avian::codegen; using namespace avian::util; -namespace local { +namespace avian { +namespace codegen { namespace isa { // SYSTEM REGISTERS @@ -196,6 +201,8 @@ bool vfpSupported() { } } +namespace arm { + const uint64_t MASK_LO32 = 0xffffffff; const unsigned MASK_LO16 = 0xffff; const unsigned MASK_LO8 = 0xff; @@ -239,8 +246,6 @@ const int32_t PoolOffsetMask = 0xFFF; const bool DebugPool = false; -class Context; -class MyBlock; class PoolOffset; class PoolEvent; @@ -250,113 +255,12 @@ resolve(MyBlock*); unsigned padding(MyBlock*, unsigned); -class MyBlock: public Assembler::Block { - public: - MyBlock(Context* context, unsigned offset): - context(context), next(0), poolOffsetHead(0), poolOffsetTail(0), - lastPoolOffsetTail(0), poolEventHead(0), poolEventTail(0), - lastEventOffset(0), offset(offset), start(~0), size(0) - { } - - virtual unsigned resolve(unsigned start, Assembler::Block* next) { - this->start = start; - this->next = static_cast(next); - - local::resolve(this); - - return start + size + padding(this, size); - } - - Context* context; - MyBlock* next; - PoolOffset* poolOffsetHead; - PoolOffset* poolOffsetTail; - PoolOffset* lastPoolOffsetTail; - PoolEvent* poolEventHead; - PoolEvent* poolEventTail; - unsigned lastEventOffset; - unsigned offset; - unsigned start; - unsigned size; -}; - class Task; class ConstantPoolEntry; -class Context { +class OffsetPromise: public Promise { public: - Context(System* s, Allocator* a, Zone* zone): - s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new(zone) MyBlock(this, 0)), - lastBlock(firstBlock), poolOffsetHead(0), poolOffsetTail(0), - constantPool(0), constantPoolCount(0) - { } - - System* s; - Zone* zone; - Assembler::Client* client; - Vector code; - Task* tasks; - uint8_t* result; - MyBlock* firstBlock; - MyBlock* lastBlock; - PoolOffset* poolOffsetHead; - PoolOffset* poolOffsetTail; - ConstantPoolEntry* constantPool; - unsigned constantPoolCount; -}; - -class Task { - public: - Task(Task* next): next(next) { } - - virtual void run(Context* con) = 0; - - Task* next; -}; - -typedef void (*OperationType)(Context*); - -typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); - -typedef void (*BinaryOperationType) -(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); - -typedef void (*TernaryOperationType) -(Context*, unsigned, lir::Operand*, lir::Operand*, - lir::Operand*); - -typedef void (*BranchOperationType) -(Context*, lir::TernaryOperation, unsigned, lir::Operand*, - lir::Operand*, lir::Operand*); - -class ArchitectureContext { - public: - ArchitectureContext(System* s): s(s) { } - - System* s; - OperationType operations[lir::OperationCount]; - UnaryOperationType unaryOperations[lir::UnaryOperationCount - * lir::OperandTypeCount]; - BinaryOperationType binaryOperations - [lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; - TernaryOperationType ternaryOperations - [lir::NonBranchTernaryOperationCount * lir::OperandTypeCount]; - BranchOperationType branchOperations - [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; -}; - -inline Aborter* getAborter(Context* con) { - return con->s; -} - -inline Aborter* getAborter(ArchitectureContext* con) { - return con->s; -} - -class Offset: public Promise { - public: - Offset(Context* con, MyBlock* block, unsigned offset, bool forTrace): + OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace): con(con), block(block), offset(offset), forTrace(forTrace) { } @@ -378,10 +282,8 @@ class Offset: public Promise { bool forTrace; }; -Promise* -offset(Context* con, bool forTrace = false) -{ - return new(con->zone) Offset(con, con->lastBlock, con->code.length(), forTrace); +Promise* offsetPromise(Context* con, bool forTrace = false) { + return new(con->zone) OffsetPromise(con, con->lastBlock, con->code.length(), forTrace); } bool @@ -1626,7 +1528,7 @@ branch(Context* con, lir::TernaryOperation op) void conditional(Context* con, int32_t branch, lir::Constant* target) { - appendOffsetTask(con, target->value, offset(con)); + appendOffsetTask(con, target->value, offsetPromise(con)); emit(con, branch); } @@ -1845,7 +1747,7 @@ callC(Context* con, unsigned size UNUSED, lir::Constant* target) { assert(con, size == TargetBytesPerWord); - appendOffsetTask(con, target->value, offset(con)); + appendOffsetTask(con, target->value, offsetPromise(con)); emit(con, bl(0)); } @@ -1855,7 +1757,7 @@ longCallC(Context* con, unsigned size UNUSED, lir::Constant* target) assert(con, size == TargetBytesPerWord); lir::Register tmp(4); - moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); + moveCR2(con, TargetBytesPerWord, target, &tmp, offsetPromise(con)); callR(con, TargetBytesPerWord, &tmp); } @@ -1865,7 +1767,7 @@ longJumpC(Context* con, unsigned size UNUSED, lir::Constant* target) assert(con, size == TargetBytesPerWord); lir::Register tmp(4); // a non-arg reg that we don't mind clobbering - moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); + moveCR2(con, TargetBytesPerWord, target, &tmp, offsetPromise(con)); jumpR(con, TargetBytesPerWord, &tmp); } @@ -1874,7 +1776,7 @@ jumpC(Context* con, unsigned size UNUSED, lir::Constant* target) { assert(con, size == TargetBytesPerWord); - appendOffsetTask(con, target->value, offset(con)); + appendOffsetTask(con, target->value, offsetPromise(con)); emit(con, b(0)); } @@ -2120,7 +2022,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentFootprint(unsigned footprint) { - return local::argumentFootprint(footprint); + return arm::argumentFootprint(footprint); } virtual bool argumentAlignment() { @@ -2209,7 +2111,7 @@ class MyArchitecture: public Assembler::Architecture { unsigned targetParameterFootprint, void** ip, void** stack) { - local::nextFrame(&con, static_cast(start), size, footprint, link, + arm::nextFrame(&con, static_cast(start), size, footprint, link, mostRecent, targetParameterFootprint, ip, stack); } @@ -2796,7 +2698,7 @@ class MyAssembler: public Assembler { } virtual Promise* offset(bool forTrace) { - return local::offset(&con, forTrace); + return arm::offsetPromise(&con, forTrace); } virtual Block* endBlock(bool startNew) { @@ -2864,15 +2766,12 @@ Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { return new(zone) MyAssembler(this->con.s, allocator, zone, this); } -} // namespace - -namespace avian { -namespace codegen { +} // namespace arm Assembler::Architecture* makeArchitectureArm(System* system, bool) { - return new (allocate(system, sizeof(local::MyArchitecture))) local::MyArchitecture(system); + return new (allocate(system, sizeof(arm::MyArchitecture))) arm::MyArchitecture(system); } } // namespace codegen diff --git a/src/codegen/arm/block.cpp b/src/codegen/arm/block.cpp new file mode 100644 index 0000000000..7216e86f55 --- /dev/null +++ b/src/codegen/arm/block.cpp @@ -0,0 +1,39 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace arm { + +void resolve(MyBlock*); + +unsigned padding(MyBlock*, unsigned); + +MyBlock::MyBlock(Context* context, unsigned offset): + context(context), next(0), poolOffsetHead(0), poolOffsetTail(0), + lastPoolOffsetTail(0), poolEventHead(0), poolEventTail(0), + lastEventOffset(0), offset(offset), start(~0), size(0) +{ } + +unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) { + this->start = start; + this->next = static_cast(next); + + arm::resolve(this); + + return start + size + padding(this, size); +} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/arm/block.h b/src/codegen/arm/block.h new file mode 100644 index 0000000000..42f3cceaa3 --- /dev/null +++ b/src/codegen/arm/block.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H + +#include +#include +#include "alloc-vector.h" + +namespace avian { +namespace codegen { +namespace arm { + +class PoolEvent; + +class MyBlock: public Assembler::Block { + public: + MyBlock(Context* context, unsigned offset); + + virtual unsigned resolve(unsigned start, Assembler::Block* next); + + Context* context; + MyBlock* next; + PoolOffset* poolOffsetHead; + PoolOffset* poolOffsetTail; + PoolOffset* lastPoolOffsetTail; + PoolEvent* poolEventHead; + PoolEvent* poolEventTail; + unsigned lastEventOffset; + unsigned offset; + unsigned start; + unsigned size; +}; + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H diff --git a/src/codegen/arm/context.cpp b/src/codegen/arm/context.cpp new file mode 100644 index 0000000000..d3619adf85 --- /dev/null +++ b/src/codegen/arm/context.cpp @@ -0,0 +1,27 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace arm { + +Context::Context(vm::System* s, vm::Allocator* a, vm::Zone* zone): + s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), + firstBlock(new(zone) MyBlock(this, 0)), + lastBlock(firstBlock), poolOffsetHead(0), poolOffsetTail(0), + constantPool(0), constantPoolCount(0) +{ } + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/arm/context.h b/src/codegen/arm/context.h new file mode 100644 index 0000000000..ccba7e403d --- /dev/null +++ b/src/codegen/arm/context.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H + +#include +#include +#include "alloc-vector.h" + +namespace vm { +class System; +class Allocator; +class Zone; +} // namespace vm + +namespace avian { + +namespace util { +class Aborter; +} // namespace util + +namespace codegen { +namespace arm { + +class Task; +class MyBlock; +class PoolOffset; +class ConstantPoolEntry; + +class Context { + public: + Context(vm::System* s, vm::Allocator* a, vm::Zone* zone); + + vm::System* s; + vm::Zone* zone; + Assembler::Client* client; + vm::Vector code; + Task* tasks; + uint8_t* result; + MyBlock* firstBlock; + MyBlock* lastBlock; + PoolOffset* poolOffsetHead; + PoolOffset* poolOffsetTail; + ConstantPoolEntry* constantPool; + unsigned constantPoolCount; +}; + +class Task { + public: + Task(Task* next): next(next) { } + + virtual void run(Context* con) = 0; + + Task* next; +}; + +typedef void (*OperationType)(Context*); + +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); + +typedef void (*BinaryOperationType) +(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); + +typedef void (*TernaryOperationType) +(Context*, unsigned, lir::Operand*, lir::Operand*, + lir::Operand*); + +typedef void (*BranchOperationType) +(Context*, lir::TernaryOperation, unsigned, lir::Operand*, + lir::Operand*, lir::Operand*); + +class ArchitectureContext { + public: + ArchitectureContext(vm::System* s): s(s) { } + + vm::System* s; + OperationType operations[lir::OperationCount]; + UnaryOperationType unaryOperations[lir::UnaryOperationCount + * lir::OperandTypeCount]; + BinaryOperationType binaryOperations + [lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; + TernaryOperationType ternaryOperations + [lir::NonBranchTernaryOperationCount * lir::OperandTypeCount]; + BranchOperationType branchOperations + [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; +}; + +inline avian::util::Aborter* getAborter(Context* c) { + return c->s; +} + +inline avian::util::Aborter* getAborter(ArchitectureContext* c) { + return c->s; +} + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H From 22d6ed1becde1d1507b6a7c5ad0ca348a9213b38 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 22 Feb 2013 21:19:53 -0700 Subject: [PATCH 290/378] further split out arm assembler --- src/codegen/arm/assembler.cpp | 1830 +------------------------------ src/codegen/arm/block.h | 1 - src/codegen/arm/context.h | 9 - src/codegen/arm/encode.h | 184 ++++ src/codegen/arm/fixup.cpp | 175 +++ src/codegen/arm/fixup.h | 140 +++ src/codegen/arm/multimethod.cpp | 142 +++ src/codegen/arm/multimethod.h | 46 + src/codegen/arm/operations.cpp | 1235 +++++++++++++++++++++ src/codegen/arm/operations.h | 240 ++++ src/codegen/arm/registers.h | 52 + src/common.h | 6 + 12 files changed, 2227 insertions(+), 1833 deletions(-) create mode 100644 src/codegen/arm/encode.h create mode 100644 src/codegen/arm/fixup.cpp create mode 100644 src/codegen/arm/fixup.h create mode 100644 src/codegen/arm/multimethod.cpp create mode 100644 src/codegen/arm/multimethod.h create mode 100644 src/codegen/arm/operations.cpp create mode 100644 src/codegen/arm/operations.h create mode 100644 src/codegen/arm/registers.h diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index c4b4ca7dfe..ac00fdb5cb 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -15,176 +15,24 @@ #include "context.h" #include "block.h" +#include "fixup.h" +#include "multimethod.h" +#include "encode.h" +#include "operations.h" +#include "registers.h" #include "alloc-vector.h" #include - -#define CAST1(x) reinterpret_cast(x) -#define CAST2(x) reinterpret_cast(x) -#define CAST3(x) reinterpret_cast(x) -#define CAST_BRANCH(x) reinterpret_cast(x) - using namespace vm; using namespace avian::codegen; using namespace avian::util; namespace avian { namespace codegen { +namespace arm { namespace isa { -// SYSTEM REGISTERS -const int FPSID = 0x0; -const int FPSCR = 0x1; -const int FPEXC = 0x8; -// INSTRUCTION OPTIONS -enum CONDITION { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV }; -enum SHIFTOP { LSL, LSR, ASR, ROR }; -// INSTRUCTION FORMATS -inline int DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int Rm) -{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; } -inline int DATAS(int cond, int opcode, int S, int Rn, int Rd, int Rs, int Sh, int Rm) -{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | Rs<<8 | Sh<<5 | 1<<4 | Rm; } -inline int DATAI(int cond, int opcode, int S, int Rn, int Rd, int rot, int imm) -{ return cond<<28 | 1<<25 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | rot<<8 | (imm&0xff); } -inline int BRANCH(int cond, int L, int offset) -{ return cond<<28 | 5<<25 | L<<24 | (offset&0xffffff); } -inline int BRANCHX(int cond, int L, int Rm) -{ return cond<<28 | 0x4bffc<<6 | L<<5 | 1<<4 | Rm; } -inline int MULTIPLY(int cond, int mul, int S, int Rd, int Rn, int Rs, int Rm) -{ return cond<<28 | mul<<21 | S<<20 | Rd<<16 | Rn<<12 | Rs<<8 | 9<<4 | Rm; } -inline int XFER(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int shift, int Sh, int Rm) -{ return cond<<28 | 3<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; } -inline int XFERI(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int offset) -{ return cond<<28 | 2<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | (offset&0xfff); } -inline int XFER2(int cond, int P, int U, int W, int L, int Rn, int Rd, int S, int H, int Rm) -{ return cond<<28 | P<<24 | U<<23 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | 1<<7 | S<<6 | H<<5 | 1<<4 | Rm; } -inline int XFER2I(int cond, int P, int U, int W, int L, int Rn, int Rd, int offsetH, int S, int H, int offsetL) -{ return cond<<28 | P<<24 | U<<23 | 1<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | offsetH<<8 | 1<<7 | S<<6 | H<<5 | 1<<4 | (offsetL&0xf); } -inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm) -{ return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; } -inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) // offset is in words, not bytes -{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff)>>2; } -inline int COREG(int cond, int opcode_1, int L, int CRn, int Rd, int cp_num, int opcode_2, int CRm) -{ return cond<<28 | 0xe<<24 | opcode_1<<21 | L<<20 | CRn<<16 | Rd<<12 | cp_num<<8 | opcode_2<<5 | 1<<4 | CRm; } -inline int COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm) -{ return cond<<28 | 0xc4<<20 | L<<20 | Rn<<16 | Rd<<12 | cp_num<<8 | opcode<<4 | CRm;} -// FIELD CALCULATORS -inline int calcU(int imm) { return imm >= 0 ? 1 : 0; } -// INSTRUCTIONS -// The "cond" and "S" fields are set using the SETCOND() and SETS() functions -inline int b(int offset) { return BRANCH(AL, 0, offset); } -inline int bl(int offset) { return BRANCH(AL, 1, offset); } -inline int bx(int Rm) { return BRANCHX(AL, 0, Rm); } -inline int blx(int Rm) { return BRANCHX(AL, 1, Rm); } -inline int and_(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm); } -inline int eor(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm); } -inline int rsb(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm); } -inline int add(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm); } -inline int adc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm); } -inline int rsc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm); } -inline int cmp(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xa, 1, Rn, 0, shift, Sh, Rm); } -inline int orr(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm); } -inline int mov(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xd, 0, 0, Rd, shift, Sh, Rm); } -inline int mvn(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xf, 0, 0, Rd, shift, Sh, Rm); } -inline int andi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm); } -inline int subi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm); } -inline int rsbi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm); } -inline int addi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm); } -inline int adci(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm); } -inline int bici(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm); } -inline int cmpi(int Rn, int imm, int rot=0) { return DATAI(AL, 0xa, 1, Rn, 0, rot, imm); } -inline int movi(int Rd, int imm, int rot=0) { return DATAI(AL, 0xd, 0, 0, Rd, rot, imm); } -inline int orrsh(int Rd, int Rn, int Rm, int Rs, int Sh) { return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm); } -inline int movsh(int Rd, int Rm, int Rs, int Sh) { return DATAS(AL, 0xd, 0, 0, Rd, Rs, Sh, Rm); } -inline int mul(int Rd, int Rm, int Rs) { return MULTIPLY(AL, 0, 0, Rd, 0, Rs, Rm); } -inline int mla(int Rd, int Rm, int Rs, int Rn) { return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm); } -inline int umull(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm); } -inline int ldr(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm); } -inline int ldri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm)); } -inline int ldrb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm); } -inline int ldrbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 1, Rn, Rd, abs(imm)); } -inline int str(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 0, Rn, Rd, 0, 0, Rm); } -inline int stri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 0, Rn, Rd, abs(imm)); } -inline int strb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 0, Rn, Rd, 0, 0, Rm); } -inline int strbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 0, Rn, Rd, abs(imm)); } -inline int ldrh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 0, 1, Rm); } -inline int ldrhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); } -inline int strh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 0, Rn, Rd, 0, 1, Rm); } -inline int strhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 0, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); } -inline int ldrsh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 1, Rm); } -inline int ldrshi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 1, abs(imm)&0xf); } -inline int ldrsb(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm); } -inline int ldrsbi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 0, abs(imm)&0xf); } -// breakpoint instruction, this really has its own instruction format -inline int bkpt(int16_t immed) { return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf); } -// COPROCESSOR INSTRUCTIONS -inline int mcr(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); } -inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); } -inline int mrc(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); } -inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); } -// VFP FLOATING-POINT INSTRUCTIONS -inline int fmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } -inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } -inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } -inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } -inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); } -inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } -inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } -inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } -inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 2|(Sm&1), Sm>>1); } -inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 6|(Sm&1), Sm>>1); } -inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 2|(Sm&1), Sm>>1); } -inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 6|(Sm&1), Sm>>1); } -inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 2|(Sm&1), Sm>>1); } -inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb, 7, Dd, 10, 6|(Sm&1), Sm>>1); } -inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 6|(Sm&1), Sm>>1); } -inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 6|(Sm&1), Sm>>1); } -inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); } -inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); } -inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); } -inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); } -// double-precision comparison instructions -inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); } -// double-precision conversion instructions -inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); } -inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); } -inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); } -// single load/store instructions for both precision types -inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); }; -inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); }; -inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); }; -inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); }; -// move between GPRs and FPRs -inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } -inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } -// move to/from VFP system registers -inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); } -// these move around pairs of single-precision registers -inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); } -inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); } -// FLAG SETTERS -inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); } -inline int SETS(int ins) { return ins | 1<<20; } -// PSEUDO-INSTRUCTIONS -inline int lsl(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSL); } -inline int lsli(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSL, imm); } -inline int lsr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSR); } -inline int lsri(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSR, imm); } -inline int asr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, ASR); } -inline int asri(int Rd, int Rm, int imm) { return mov(Rd, Rm, ASR, imm); } -inline int beq(int offset) { return SETCOND(b(offset), EQ); } -inline int bne(int offset) { return SETCOND(b(offset), NE); } -inline int bls(int offset) { return SETCOND(b(offset), LS); } -inline int bhi(int offset) { return SETCOND(b(offset), HI); } -inline int blt(int offset) { return SETCOND(b(offset), LT); } -inline int bgt(int offset) { return SETCOND(b(offset), GT); } -inline int ble(int offset) { return SETCOND(b(offset), LE); } -inline int bge(int offset) { return SETCOND(b(offset), GE); } -inline int blo(int offset) { return SETCOND(b(offset), CC); } -inline int bhs(int offset) { return SETCOND(b(offset), CS); } -inline int bpl(int offset) { return SETCOND(b(offset), PL); } -inline int fmstat() { return fmrx(15, FPSCR); } // HARDWARE FLAGS bool vfpSupported() { // TODO: Use at runtime detection @@ -199,1602 +47,31 @@ bool vfpSupported() { return false; #endif } -} +} // namespace isa -namespace arm { - -const uint64_t MASK_LO32 = 0xffffffff; -const unsigned MASK_LO16 = 0xffff; -const unsigned MASK_LO8 = 0xff; inline unsigned lo8(int64_t i) { return (unsigned)(i&MASK_LO8); } -inline bool isOfWidth(int64_t i, int size) { return static_cast(i) >> size == 0; } - -const int N_GPRS = 16; -const int N_FPRS = 16; -const uint32_t GPR_MASK = 0xffff; -const uint32_t FPR_MASK = 0xffff0000; -// for source-to-destination masks -const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32; -// making the following const somehow breaks debug symbol output in GDB -/* const */ uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32; - const RegisterFile MyRegisterFileWithoutFloats(GPR_MASK, 0); const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK); -inline bool isFpr(lir::Register* reg) { - return reg->low >= N_GPRS; -} - -inline int fpr64(int reg) { return reg - N_GPRS; } -inline int fpr64(lir::Register* reg) { return fpr64(reg->low); } -inline int fpr32(int reg) { return fpr64(reg) << 1; } -inline int fpr32(lir::Register* reg) { return fpr64(reg) << 1; } - const unsigned FrameHeaderSize = 1; const unsigned StackAlignmentInBytes = 8; const unsigned StackAlignmentInWords = StackAlignmentInBytes / TargetBytesPerWord; -const int ThreadRegister = 8; -const int StackRegister = 13; -const int LinkRegister = 14; -const int ProgramCounter = 15; - -const int32_t PoolOffsetMask = 0xFFF; - -const bool DebugPool = false; - -class PoolOffset; -class PoolEvent; - void resolve(MyBlock*); unsigned padding(MyBlock*, unsigned); -class Task; class ConstantPoolEntry; -class OffsetPromise: public Promise { - public: - OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace): - con(con), block(block), offset(offset), forTrace(forTrace) - { } - - virtual bool resolved() { - return block->start != static_cast(~0); - } - - virtual int64_t value() { - assert(con, resolved()); - - unsigned o = offset - block->offset; - return block->start + padding - (block, forTrace ? o - TargetBytesPerWord : o) + o; - } - - Context* con; - MyBlock* block; - unsigned offset; - bool forTrace; -}; - -Promise* offsetPromise(Context* con, bool forTrace = false) { - return new(con->zone) OffsetPromise(con, con->lastBlock, con->code.length(), forTrace); -} - -bool -bounded(int right, int left, int32_t v) -{ - return ((v << left) >> left) == v and ((v >> right) << right) == v; -} - -void* -updateOffset(System* s, uint8_t* instruction, int64_t value) -{ - // ARM's PC is two words ahead, and branches drop the bottom 2 bits. - int32_t v = (reinterpret_cast(value) - (instruction + 8)) >> 2; - - int32_t mask; - expect(s, bounded(0, 8, v)); - mask = 0xFFFFFF; - - int32_t* p = reinterpret_cast(instruction); - *p = (v & mask) | ((~mask) & *p); - - return instruction + 4; -} - -class OffsetListener: public Promise::Listener { - public: - OffsetListener(System* s, uint8_t* instruction): - s(s), - instruction(instruction) - { } - - virtual bool resolve(int64_t value, void** location) { - void* p = updateOffset(s, instruction, value); - if (location) *location = p; - return false; - } - - System* s; - uint8_t* instruction; -}; - -class OffsetTask: public Task { - public: - OffsetTask(Task* next, Promise* promise, Promise* instructionOffset): - Task(next), - promise(promise), - instructionOffset(instructionOffset) - { } - - virtual void run(Context* con) { - if (promise->resolved()) { - updateOffset - (con->s, con->result + instructionOffset->value(), promise->value()); - } else { - new (promise->listen(sizeof(OffsetListener))) - OffsetListener(con->s, con->result + instructionOffset->value()); - } - } - - Promise* promise; - Promise* instructionOffset; -}; - -void -appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) -{ - con->tasks = new(con->zone) OffsetTask(con->tasks, promise, instructionOffset); -} - -inline unsigned -index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) -{ - return operation + (lir::UnaryOperationCount * operand); -} - -inline unsigned -index(ArchitectureContext*, - lir::BinaryOperation operation, - lir::OperandType operand1, - lir::OperandType operand2) -{ - return operation - + (lir::BinaryOperationCount * operand1) - + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); -} - -inline unsigned -index(ArchitectureContext* con UNUSED, - lir::TernaryOperation operation, - lir::OperandType operand1) -{ - assert(con, not isBranch(operation)); - - return operation + (lir::NonBranchTernaryOperationCount * operand1); -} - -unsigned -branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1, - lir::OperandType operand2) -{ - return operand1 + (lir::OperandTypeCount * operand2); -} - // BEGIN OPERATION COMPILERS using namespace isa; -// shortcut functions -inline void emit(Context* con, int code) { con->code.append4(code); } - -inline int newTemp(Context* con) { - return con->client->acquireTemporary(GPR_MASK); -} - -inline int newTemp(Context* con, unsigned mask) { - return con->client->acquireTemporary(mask); -} - -inline void freeTemp(Context* con, int r) { - con->client->releaseTemporary(r); -} - -inline int64_t getValue(lir::Constant* con) { - return con->value->value(); -} - -inline lir::Register makeTemp(Context* con) { - lir::Register tmp(newTemp(con)); - return tmp; -} - -inline lir::Register makeTemp64(Context* con) { - lir::Register tmp(newTemp(con), newTemp(con)); - return tmp; -} - -inline void freeTemp(Context* con, const lir::Register& tmp) { - if (tmp.low != lir::NoRegister) freeTemp(con, tmp.low); - if (tmp.high != lir::NoRegister) freeTemp(con, tmp.high); -} - -inline void -write4(uint8_t* dst, uint32_t v) -{ - memcpy(dst, &v, 4); -} - -void -andC(Context* con, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst); - -void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) -{ - if (size == 8) { - int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); - ResolvedPromise maskPromise(0x3F); - lir::Constant mask(&maskPromise); - lir::Register dst(tmp3); - andC(con, 4, &mask, a, &dst); - emit(con, lsl(tmp1, b->high, tmp3)); - emit(con, rsbi(tmp2, tmp3, 32)); - emit(con, orrsh(tmp1, tmp1, b->low, tmp2, LSR)); - emit(con, SETS(subi(t->high, tmp3, 32))); - emit(con, SETCOND(mov(t->high, tmp1), MI)); - emit(con, SETCOND(lsl(t->high, b->low, t->high), PL)); - emit(con, lsl(t->low, b->low, tmp3)); - freeTemp(con, tmp1); freeTemp(con, tmp2); freeTemp(con, tmp3); - } else { - int tmp = newTemp(con); - ResolvedPromise maskPromise(0x1F); - lir::Constant mask(&maskPromise); - lir::Register dst(tmp); - andC(con, size, &mask, a, &dst); - emit(con, lsl(t->low, b->low, tmp)); - freeTemp(con, tmp); - } -} - -void -moveRR(Context* con, unsigned srcSize, lir::Register* src, - unsigned dstSize, lir::Register* dst); - -void shiftLeftC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) -{ - assert(con, size == TargetBytesPerWord); - if (getValue(a) & 0x1F) { - emit(con, lsli(t->low, b->low, getValue(a) & 0x1F)); - } else { - moveRR(con, size, b, size, t); - } -} - -void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) -{ - if (size == 8) { - int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); - ResolvedPromise maskPromise(0x3F); - lir::Constant mask(&maskPromise); - lir::Register dst(tmp3); - andC(con, 4, &mask, a, &dst); - emit(con, lsr(tmp1, b->low, tmp3)); - emit(con, rsbi(tmp2, tmp3, 32)); - emit(con, orrsh(tmp1, tmp1, b->high, tmp2, LSL)); - emit(con, SETS(subi(t->low, tmp3, 32))); - emit(con, SETCOND(mov(t->low, tmp1), MI)); - emit(con, SETCOND(asr(t->low, b->high, t->low), PL)); - emit(con, asr(t->high, b->high, tmp3)); - freeTemp(con, tmp1); freeTemp(con, tmp2); freeTemp(con, tmp3); - } else { - int tmp = newTemp(con); - ResolvedPromise maskPromise(0x1F); - lir::Constant mask(&maskPromise); - lir::Register dst(tmp); - andC(con, size, &mask, a, &dst); - emit(con, asr(t->low, b->low, tmp)); - freeTemp(con, tmp); - } -} - -void shiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) -{ - assert(con, size == TargetBytesPerWord); - if (getValue(a) & 0x1F) { - emit(con, asri(t->low, b->low, getValue(a) & 0x1F)); - } else { - moveRR(con, size, b, size, t); - } -} - -void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) -{ - int tmpShift = newTemp(con); - ResolvedPromise maskPromise(size == 8 ? 0x3F : 0x1F); - lir::Constant mask(&maskPromise); - lir::Register dst(tmpShift); - andC(con, 4, &mask, a, &dst); - emit(con, lsr(t->low, b->low, tmpShift)); - if (size == 8) { - int tmpHi = newTemp(con), tmpLo = newTemp(con); - emit(con, SETS(rsbi(tmpHi, tmpShift, 32))); - emit(con, lsl(tmpLo, b->high, tmpHi)); - emit(con, orr(t->low, t->low, tmpLo)); - emit(con, addi(tmpHi, tmpShift, -32)); - emit(con, lsr(tmpLo, b->high, tmpHi)); - emit(con, orr(t->low, t->low, tmpLo)); - emit(con, lsr(t->high, b->high, tmpShift)); - freeTemp(con, tmpHi); freeTemp(con, tmpLo); - } - freeTemp(con, tmpShift); -} - -void unsignedShiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) -{ - assert(con, size == TargetBytesPerWord); - if (getValue(a) & 0x1F) { - emit(con, lsri(t->low, b->low, getValue(a) & 0x1F)); - } else { - moveRR(con, size, b, size, t); - } -} - -class ConstantPoolEntry: public Promise { - public: - ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next, - Promise* callOffset): - con(con), constant(constant), next(next), callOffset(callOffset), - address(0) - { } - - virtual int64_t value() { - assert(con, resolved()); - - return reinterpret_cast(address); - } - - virtual bool resolved() { - return address != 0; - } - - Context* con; - Promise* constant; - ConstantPoolEntry* next; - Promise* callOffset; - void* address; - unsigned constantPoolCount; -}; - -class ConstantPoolListener: public Promise::Listener { - public: - ConstantPoolListener(System* s, target_uintptr_t* address, - uint8_t* returnAddress): - s(s), - address(address), - returnAddress(returnAddress) - { } - - virtual bool resolve(int64_t value, void** location) { - *address = value; - if (location) { - *location = returnAddress ? static_cast(returnAddress) : address; - } - return true; - } - - System* s; - target_uintptr_t* address; - uint8_t* returnAddress; -}; - -class PoolOffset { - public: - PoolOffset(MyBlock* block, ConstantPoolEntry* entry, unsigned offset): - block(block), entry(entry), next(0), offset(offset) - { } - - MyBlock* block; - ConstantPoolEntry* entry; - PoolOffset* next; - unsigned offset; -}; - -class PoolEvent { - public: - PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail, - unsigned offset): - poolOffsetHead(poolOffsetHead), poolOffsetTail(poolOffsetTail), next(0), - offset(offset) - { } - - PoolOffset* poolOffsetHead; - PoolOffset* poolOffsetTail; - PoolEvent* next; - unsigned offset; -}; - -void -appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset) -{ - if (constant->resolved()) { - // make a copy, since the original might be allocated on the - // stack, and we need our copy to live until assembly is complete - constant = new(con->zone) ResolvedPromise(constant->value()); - } - - con->constantPool = new(con->zone) ConstantPoolEntry(con, constant, con->constantPool, callOffset); - - ++ con->constantPoolCount; - - PoolOffset* o = new(con->zone) PoolOffset(con->lastBlock, con->constantPool, con->code.length() - con->lastBlock->offset); - - if (DebugPool) { - fprintf(stderr, "add pool offset %p %d to block %p\n", - o, o->offset, con->lastBlock); - } - - if (con->lastBlock->poolOffsetTail) { - con->lastBlock->poolOffsetTail->next = o; - } else { - con->lastBlock->poolOffsetHead = o; - } - con->lastBlock->poolOffsetTail = o; -} - -void -appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head, - PoolOffset* tail) -{ - PoolEvent* e = new(con->zone) PoolEvent(head, tail, offset); - - if (b->poolEventTail) { - b->poolEventTail->next = e; - } else { - b->poolEventHead = e; - } - b->poolEventTail = e; -} - -bool -needJump(MyBlock* b) -{ - return b->next or b->size != (b->size & PoolOffsetMask); -} - -unsigned -padding(MyBlock* b, unsigned offset) -{ - unsigned total = 0; - for (PoolEvent* e = b->poolEventHead; e; e = e->next) { - if (e->offset <= offset) { - if (needJump(b)) { - total += TargetBytesPerWord; - } - for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) { - total += TargetBytesPerWord; - } - } else { - break; - } - } - return total; -} - -void -resolve(MyBlock* b) -{ - Context* con = b->context; - - if (b->poolOffsetHead) { - if (con->poolOffsetTail) { - con->poolOffsetTail->next = b->poolOffsetHead; - } else { - con->poolOffsetHead = b->poolOffsetHead; - } - con->poolOffsetTail = b->poolOffsetTail; - } - - if (con->poolOffsetHead) { - bool append; - if (b->next == 0 or b->next->poolEventHead) { - append = true; - } else { - int32_t v = (b->start + b->size + b->next->size + TargetBytesPerWord - 8) - - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); - - append = (v != (v & PoolOffsetMask)); - - if (DebugPool) { - fprintf(stderr, - "current %p %d %d next %p %d %d\n", - b, b->start, b->size, b->next, b->start + b->size, - b->next->size); - fprintf(stderr, - "offset %p %d is of distance %d to next block; append? %d\n", - con->poolOffsetHead, con->poolOffsetHead->offset, v, append); - } - } - - if (append) { -#ifndef NDEBUG - int32_t v = (b->start + b->size - 8) - - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); - - expect(con, v == (v & PoolOffsetMask)); -#endif // not NDEBUG - - appendPoolEvent(con, b, b->size, con->poolOffsetHead, con->poolOffsetTail); - - if (DebugPool) { - for (PoolOffset* o = con->poolOffsetHead; o; o = o->next) { - fprintf(stderr, - "include %p %d in pool event %p at offset %d in block %p\n", - o, o->offset, b->poolEventTail, b->size, b); - } - } - - con->poolOffsetHead = 0; - con->poolOffsetTail = 0; - } - } -} - -void -jumpR(Context* con, unsigned size UNUSED, lir::Register* target) -{ - assert(con, size == TargetBytesPerWord); - emit(con, bx(target->low)); -} - -void -swapRR(Context* con, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b) -{ - assert(con, aSize == TargetBytesPerWord); - assert(con, bSize == TargetBytesPerWord); - - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - moveRR(con, aSize, a, bSize, &tmp); - moveRR(con, bSize, b, aSize, a); - moveRR(con, bSize, &tmp, bSize, b); - con->client->releaseTemporary(tmp.low); -} - -void -moveRR(Context* con, unsigned srcSize, lir::Register* src, - unsigned dstSize, lir::Register* dst) -{ - bool srcIsFpr = isFpr(src); - bool dstIsFpr = isFpr(dst); - if (srcIsFpr || dstIsFpr) { // FPR(s) involved - assert(con, srcSize == dstSize); - const bool dprec = srcSize == 8; - if (srcIsFpr && dstIsFpr) { // FPR to FPR - if (dprec) emit(con, fcpyd(fpr64(dst), fpr64(src))); // double - else emit(con, fcpys(fpr32(dst), fpr32(src))); // single - } else if (srcIsFpr) { // FPR to GPR - if (dprec) emit(con, fmrrd(dst->low, dst->high, fpr64(src))); - else emit(con, fmrs(dst->low, fpr32(src))); - } else { // GPR to FPR - if (dprec) emit(con, fmdrr(fpr64(dst->low), src->low, src->high)); - else emit(con, fmsr(fpr32(dst), src->low)); - } - return; - } - - switch (srcSize) { - case 1: - emit(con, lsli(dst->low, src->low, 24)); - emit(con, asri(dst->low, dst->low, 24)); - break; - - case 2: - emit(con, lsli(dst->low, src->low, 16)); - emit(con, asri(dst->low, dst->low, 16)); - break; - - case 4: - case 8: - if (srcSize == 4 and dstSize == 8) { - moveRR(con, 4, src, 4, dst); - emit(con, asri(dst->high, src->low, 31)); - } else if (srcSize == 8 and dstSize == 8) { - lir::Register srcHigh(src->high); - lir::Register dstHigh(dst->high); - - if (src->high == dst->low) { - if (src->low == dst->high) { - swapRR(con, 4, src, 4, dst); - } else { - moveRR(con, 4, &srcHigh, 4, &dstHigh); - moveRR(con, 4, src, 4, dst); - } - } else { - moveRR(con, 4, src, 4, dst); - moveRR(con, 4, &srcHigh, 4, &dstHigh); - } - } else if (src->low != dst->low) { - emit(con, mov(dst->low, src->low)); - } - break; - - default: abort(con); - } -} - -void -moveZRR(Context* con, unsigned srcSize, lir::Register* src, - unsigned, lir::Register* dst) -{ - switch (srcSize) { - case 2: - emit(con, lsli(dst->low, src->low, 16)); - emit(con, lsri(dst->low, dst->low, 16)); - break; - - default: abort(con); - } -} - -void moveCR(Context* con, unsigned size, lir::Constant* src, - unsigned, lir::Register* dst); - -void -moveCR2(Context* con, unsigned size, lir::Constant* src, - lir::Register* dst, Promise* callOffset) -{ - if (isFpr(dst)) { // floating-point - lir::Register tmp = size > 4 ? makeTemp64(con) : - makeTemp(con); - moveCR(con, size, src, size, &tmp); - moveRR(con, size, &tmp, size, dst); - freeTemp(con, tmp); - } else if (size > 4) { - uint64_t value = (uint64_t)src->value->value(); - ResolvedPromise loBits(value & MASK_LO32); - lir::Constant srcLo(&loBits); - ResolvedPromise hiBits(value >> 32); - lir::Constant srcHi(&hiBits); - lir::Register dstHi(dst->high); - moveCR(con, 4, &srcLo, 4, dst); - moveCR(con, 4, &srcHi, 4, &dstHi); - } else if (src->value->resolved() and isOfWidth(getValue(src), 8)) { - emit(con, movi(dst->low, lo8(getValue(src)))); // fits in immediate - } else { - appendConstantPoolEntry(con, src->value, callOffset); - emit(con, ldri(dst->low, ProgramCounter, 0)); // load 32 bits - } -} - -void -moveCR(Context* con, unsigned size, lir::Constant* src, - unsigned, lir::Register* dst) -{ - moveCR2(con, size, src, dst, 0); -} - -void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if (size == 8) { - emit(con, SETS(add(t->low, a->low, b->low))); - emit(con, adc(t->high, a->high, b->high)); - } else { - emit(con, add(t->low, a->low, b->low)); - } -} - -void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if (size == 8) { - emit(con, SETS(rsb(t->low, a->low, b->low))); - emit(con, rsc(t->high, a->high, b->high)); - } else { - emit(con, rsb(t->low, a->low, b->low)); - } -} - -void -addC(Context* con, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst) -{ - assert(con, size == TargetBytesPerWord); - - int32_t v = a->value->value(); - if (v) { - if (v > 0 and v < 256) { - emit(con, addi(dst->low, b->low, v)); - } else if (v > 0 and v < 1024 and v % 4 == 0) { - emit(con, addi(dst->low, b->low, v >> 2, 15)); - } else { - // todo - abort(con); - } - } else { - moveRR(con, size, b, size, dst); - } -} - -void -subC(Context* con, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst) -{ - assert(con, size == TargetBytesPerWord); - - int32_t v = a->value->value(); - if (v) { - if (v > 0 and v < 256) { - emit(con, subi(dst->low, b->low, v)); - } else if (v > 0 and v < 1024 and v % 4 == 0) { - emit(con, subi(dst->low, b->low, v >> 2, 15)); - } else { - // todo - abort(con); - } - } else { - moveRR(con, size, b, size, dst); - } -} - -void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if (size == 8) { - bool useTemporaries = b->low == t->low; - int tmpLow = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->low; - int tmpHigh = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->high; - - emit(con, umull(tmpLow, tmpHigh, a->low, b->low)); - emit(con, mla(tmpHigh, a->low, b->high, tmpHigh)); - emit(con, mla(tmpHigh, a->high, b->low, tmpHigh)); - - if (useTemporaries) { - emit(con, mov(t->low, tmpLow)); - emit(con, mov(t->high, tmpHigh)); - con->client->releaseTemporary(tmpLow); - con->client->releaseTemporary(tmpHigh); - } - } else { - emit(con, mul(t->low, a->low, b->low)); - } -} - -void floatAbsoluteRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { - if (size == 8) { - emit(con, fabsd(fpr64(b), fpr64(a))); - } else { - emit(con, fabss(fpr32(b), fpr32(a))); - } -} - -void floatNegateRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { - if (size == 8) { - emit(con, fnegd(fpr64(b), fpr64(a))); - } else { - emit(con, fnegs(fpr32(b), fpr32(a))); - } -} - -void float2FloatRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { - if (size == 8) { - emit(con, fcvtsd(fpr32(b), fpr64(a))); - } else { - emit(con, fcvtds(fpr64(b), fpr32(a))); - } -} - -void float2IntRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { - int tmp = newTemp(con, FPR_MASK); - int ftmp = fpr32(tmp); - if (size == 8) { // double to int - emit(con, ftosizd(ftmp, fpr64(a))); - } else { // float to int - emit(con, ftosizs(ftmp, fpr32(a))); - } // else thunked - emit(con, fmrs(b->low, ftmp)); - freeTemp(con, tmp); -} - -void int2FloatRR(Context* con, unsigned, lir::Register* a, unsigned size, lir::Register* b) { - emit(con, fmsr(fpr32(b), a->low)); - if (size == 8) { // int to double - emit(con, fsitod(fpr64(b), fpr32(b))); - } else { // int to float - emit(con, fsitos(fpr32(b), fpr32(b))); - } // else thunked -} - -void floatSqrtRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { - if (size == 8) { - emit(con, fsqrtd(fpr64(b), fpr64(a))); - } else { - emit(con, fsqrts(fpr32(b), fpr32(a))); - } -} - -void floatAddR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if (size == 8) { - emit(con, faddd(fpr64(t), fpr64(a), fpr64(b))); - } else { - emit(con, fadds(fpr32(t), fpr32(a), fpr32(b))); - } -} - -void floatSubtractR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if (size == 8) { - emit(con, fsubd(fpr64(t), fpr64(b), fpr64(a))); - } else { - emit(con, fsubs(fpr32(t), fpr32(b), fpr32(a))); - } -} - -void floatMultiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if (size == 8) { - emit(con, fmuld(fpr64(t), fpr64(a), fpr64(b))); - } else { - emit(con, fmuls(fpr32(t), fpr32(a), fpr32(b))); - } -} - -void floatDivideR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if (size == 8) { - emit(con, fdivd(fpr64(t), fpr64(b), fpr64(a))); - } else { - emit(con, fdivs(fpr32(t), fpr32(b), fpr32(a))); - } -} - -int -normalize(Context* con, int offset, int index, unsigned scale, - bool* preserveIndex, bool* release) -{ - if (offset != 0 or scale != 1) { - lir::Register normalizedIndex - (*preserveIndex ? con->client->acquireTemporary(GPR_MASK) : index); - - if (*preserveIndex) { - *release = true; - *preserveIndex = false; - } else { - *release = false; - } - - int scaled; - - if (scale != 1) { - lir::Register unscaledIndex(index); - - ResolvedPromise scalePromise(log(scale)); - lir::Constant scaleConstant(&scalePromise); - - shiftLeftC(con, TargetBytesPerWord, &scaleConstant, - &unscaledIndex, &normalizedIndex); - - scaled = normalizedIndex.low; - } else { - scaled = index; - } - - if (offset != 0) { - lir::Register untranslatedIndex(scaled); - - ResolvedPromise offsetPromise(offset); - lir::Constant offsetConstant(&offsetPromise); - - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); - addR(con, TargetBytesPerWord, &tmp, &untranslatedIndex, &normalizedIndex); - con->client->releaseTemporary(tmp.low); - } - - return normalizedIndex.low; - } else { - *release = false; - return index; - } -} - -void -store(Context* con, unsigned size, lir::Register* src, - int base, int offset, int index, unsigned scale, bool preserveIndex) -{ - if (index != lir::NoRegister) { - bool release; - int normalized = normalize - (con, offset, index, scale, &preserveIndex, &release); - - if (!isFpr(src)) { // GPR store - switch (size) { - case 1: - emit(con, strb(src->low, base, normalized)); - break; - - case 2: - emit(con, strh(src->low, base, normalized)); - break; - - case 4: - emit(con, str(src->low, base, normalized)); - break; - - case 8: { // split into 2 32-bit stores - lir::Register srcHigh(src->high); - store(con, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); - store(con, 4, src, base, 4, normalized, 1, preserveIndex); - } break; - - default: abort(con); - } - } else { // FPR store - lir::Register base_(base), - normalized_(normalized), - absAddr = makeTemp(con); - // FPR stores have only bases, so we must add the index - addR(con, TargetBytesPerWord, &base_, &normalized_, &absAddr); - // double-precision - if (size == 8) emit(con, fstd(fpr64(src), absAddr.low)); - // single-precision - else emit(con, fsts(fpr32(src), absAddr.low)); - freeTemp(con, absAddr); - } - - if (release) con->client->releaseTemporary(normalized); - } else if (size == 8 - or abs(offset) == (abs(offset) & 0xFF) - or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) - { - if (!isFpr(src)) { // GPR store - switch (size) { - case 1: - emit(con, strbi(src->low, base, offset)); - break; - - case 2: - emit(con, strhi(src->low, base, offset)); - break; - - case 4: - emit(con, stri(src->low, base, offset)); - break; - - case 8: { // split into 2 32-bit stores - lir::Register srcHigh(src->high); - store(con, 4, &srcHigh, base, offset, lir::NoRegister, 1, false); - store(con, 4, src, base, offset + 4, lir::NoRegister, 1, false); - } break; - - default: abort(con); - } - } else { // FPR store - // double-precision - if (size == 8) emit(con, fstd(fpr64(src), base, offset)); - // single-precision - else emit(con, fsts(fpr32(src), base, offset)); - } - } else { - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - ResolvedPromise offsetPromise(offset); - lir::Constant offsetConstant(&offsetPromise); - moveCR(con, TargetBytesPerWord, &offsetConstant, - TargetBytesPerWord, &tmp); - - store(con, size, src, base, 0, tmp.low, 1, false); - - con->client->releaseTemporary(tmp.low); - } -} - -void -moveRM(Context* con, unsigned srcSize, lir::Register* src, - unsigned dstSize UNUSED, lir::Memory* dst) -{ - assert(con, srcSize == dstSize); - - store(con, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); -} - -void -load(Context* con, unsigned srcSize, int base, int offset, int index, - unsigned scale, unsigned dstSize, lir::Register* dst, - bool preserveIndex, bool signExtend) -{ - if (index != lir::NoRegister) { - bool release; - int normalized = normalize - (con, offset, index, scale, &preserveIndex, &release); - - if (!isFpr(dst)) { // GPR load - switch (srcSize) { - case 1: - if (signExtend) { - emit(con, ldrsb(dst->low, base, normalized)); - } else { - emit(con, ldrb(dst->low, base, normalized)); - } - break; - - case 2: - if (signExtend) { - emit(con, ldrsh(dst->low, base, normalized)); - } else { - emit(con, ldrh(dst->low, base, normalized)); - } - break; - - case 4: - case 8: { - if (srcSize == 4 and dstSize == 8) { - load(con, 4, base, 0, normalized, 1, 4, dst, preserveIndex, - false); - moveRR(con, 4, dst, 8, dst); - } else if (srcSize == 8 and dstSize == 8) { - lir::Register dstHigh(dst->high); - load(con, 4, base, 0, normalized, 1, 4, &dstHigh, - preserveIndex, false); - load(con, 4, base, 4, normalized, 1, 4, dst, preserveIndex, - false); - } else { - emit(con, ldr(dst->low, base, normalized)); - } - } break; - - default: abort(con); - } - } else { // FPR load - lir::Register base_(base), - normalized_(normalized), - absAddr = makeTemp(con); - // VFP loads only have bases, so we must add the index - addR(con, TargetBytesPerWord, &base_, &normalized_, &absAddr); - // double-precision - if (srcSize == 8) emit(con, fldd(fpr64(dst), absAddr.low)); - // single-precision - else emit(con, flds(fpr32(dst), absAddr.low)); - freeTemp(con, absAddr); - } - - if (release) con->client->releaseTemporary(normalized); - } else if ((srcSize == 8 and dstSize == 8) - or abs(offset) == (abs(offset) & 0xFF) - or (srcSize != 2 - and (srcSize != 1 or not signExtend) - and abs(offset) == (abs(offset) & 0xFFF))) - { - if (!isFpr(dst)) { // GPR load - switch (srcSize) { - case 1: - if (signExtend) { - emit(con, ldrsbi(dst->low, base, offset)); - } else { - emit(con, ldrbi(dst->low, base, offset)); - } - break; - - case 2: - if (signExtend) { - emit(con, ldrshi(dst->low, base, offset)); - } else { - emit(con, ldrhi(dst->low, base, offset)); - } - break; - - case 4: - emit(con, ldri(dst->low, base, offset)); - break; - - case 8: { - if (dstSize == 8) { - lir::Register dstHigh(dst->high); - load(con, 4, base, offset, lir::NoRegister, 1, 4, &dstHigh, false, - false); - load(con, 4, base, offset + 4, lir::NoRegister, 1, 4, dst, false, - false); - } else { - emit(con, ldri(dst->low, base, offset)); - } - } break; - - default: abort(con); - } - } else { // FPR load - // double-precision - if (srcSize == 8) emit(con, fldd(fpr64(dst), base, offset)); - // single-precision - else emit(con, flds(fpr32(dst), base, offset)); - } - } else { - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - ResolvedPromise offsetPromise(offset); - lir::Constant offsetConstant(&offsetPromise); - moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, - &tmp); - - load(con, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, - signExtend); - - con->client->releaseTemporary(tmp.low); - } -} - -void -moveMR(Context* con, unsigned srcSize, lir::Memory* src, - unsigned dstSize, lir::Register* dst) -{ - load(con, srcSize, src->base, src->offset, src->index, src->scale, - dstSize, dst, true, true); -} - -void -moveZMR(Context* con, unsigned srcSize, lir::Memory* src, - unsigned dstSize, lir::Register* dst) -{ - load(con, srcSize, src->base, src->offset, src->index, src->scale, - dstSize, dst, true, false); -} - -void -andR(Context* con, unsigned size, lir::Register* a, - lir::Register* b, lir::Register* dst) -{ - if (size == 8) emit(con, and_(dst->high, a->high, b->high)); - emit(con, and_(dst->low, a->low, b->low)); -} - -void -andC(Context* con, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst) -{ - int64_t v = a->value->value(); - - if (size == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - lir::Register dh(dst->high); - - andC(con, 4, &al, b, dst); - andC(con, 4, &ah, &bh, &dh); - } else { - uint32_t v32 = static_cast(v); - if (v32 != 0xFFFFFFFF) { - if ((v32 & 0xFFFFFF00) == 0xFFFFFF00) { - emit(con, bici(dst->low, b->low, (~(v32 & 0xFF)) & 0xFF)); - } else if ((v32 & 0xFFFFFF00) == 0) { - emit(con, andi(dst->low, b->low, v32 & 0xFF)); - } else { - // todo: there are other cases we can handle in one - // instruction - - bool useTemporary = b->low == dst->low; - lir::Register tmp(dst->low); - if (useTemporary) { - tmp.low = con->client->acquireTemporary(GPR_MASK); - } - - moveCR(con, 4, a, 4, &tmp); - andR(con, 4, b, &tmp, dst); - - if (useTemporary) { - con->client->releaseTemporary(tmp.low); - } - } - } else { - moveRR(con, size, b, size, dst); - } - } -} - -void -orR(Context* con, unsigned size, lir::Register* a, - lir::Register* b, lir::Register* dst) -{ - if (size == 8) emit(con, orr(dst->high, a->high, b->high)); - emit(con, orr(dst->low, a->low, b->low)); -} - -void -xorR(Context* con, unsigned size, lir::Register* a, - lir::Register* b, lir::Register* dst) -{ - if (size == 8) emit(con, eor(dst->high, a->high, b->high)); - emit(con, eor(dst->low, a->low, b->low)); -} - -void -moveAR2(Context* con, unsigned srcSize, lir::Address* src, - unsigned dstSize, lir::Register* dst) -{ - assert(con, srcSize == 4 and dstSize == 4); - - lir::Constant constant(src->address); - moveCR(con, srcSize, &constant, dstSize, dst); - - lir::Memory memory(dst->low, 0, -1, 0); - moveMR(con, dstSize, &memory, dstSize, dst); -} - -void -moveAR(Context* con, unsigned srcSize, lir::Address* src, - unsigned dstSize, lir::Register* dst) -{ - moveAR2(con, srcSize, src, dstSize, dst); -} - -void -compareRR(Context* con, unsigned aSize, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type - - if (!isFpr(a)) { // GPR compare - assert(con, aSize == 4 && bSize == 4); - /**///assert(con, b->low != a->low); - emit(con, cmp(b->low, a->low)); - } else { // FPR compare - assert(con, aSize == bSize); - if (aSize == 8) emit(con, fcmpd(fpr64(b), fpr64(a))); // double - else emit(con, fcmps(fpr32(b), fpr32(a))); // single - emit(con, fmstat()); - } -} - -void -compareCR(Context* con, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(con, aSize == 4 and bSize == 4); - - if (!isFpr(b) && a->value->resolved() && - isOfWidth(a->value->value(), 8)) { - emit(con, cmpi(b->low, a->value->value())); - } else { - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - moveCR(con, aSize, a, bSize, &tmp); - compareRR(con, bSize, &tmp, bSize, b); - con->client->releaseTemporary(tmp.low); - } -} - -void -compareCM(Context* con, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Memory* b) -{ - assert(con, aSize == 4 and bSize == 4); - - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - moveMR(con, bSize, b, bSize, &tmp); - compareCR(con, aSize, a, bSize, &tmp); - con->client->releaseTemporary(tmp.low); -} - -void -compareRM(Context* con, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Memory* b) -{ - assert(con, aSize == 4 and bSize == 4); - - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - moveMR(con, bSize, b, bSize, &tmp); - compareRR(con, aSize, a, bSize, &tmp); - con->client->releaseTemporary(tmp.low); -} - -int32_t -branch(Context* con, lir::TernaryOperation op) -{ - switch (op) { - case lir::JumpIfEqual: - case lir::JumpIfFloatEqual: - return beq(0); - - case lir::JumpIfNotEqual: - case lir::JumpIfFloatNotEqual: - return bne(0); - - case lir::JumpIfLess: - case lir::JumpIfFloatLess: - case lir::JumpIfFloatLessOrUnordered: - return blt(0); - - case lir::JumpIfGreater: - case lir::JumpIfFloatGreater: - return bgt(0); - - case lir::JumpIfLessOrEqual: - case lir::JumpIfFloatLessOrEqual: - case lir::JumpIfFloatLessOrEqualOrUnordered: - return ble(0); - - case lir::JumpIfGreaterOrEqual: - case lir::JumpIfFloatGreaterOrEqual: - return bge(0); - - case lir::JumpIfFloatGreaterOrUnordered: - return bhi(0); - - case lir::JumpIfFloatGreaterOrEqualOrUnordered: - return bpl(0); - - default: - abort(con); - } -} - -void -conditional(Context* con, int32_t branch, lir::Constant* target) -{ - appendOffsetTask(con, target->value, offsetPromise(con)); - emit(con, branch); -} - -void -branch(Context* con, lir::TernaryOperation op, lir::Constant* target) -{ - conditional(con, branch(con, op), target); -} - -void -branchLong(Context* con, lir::TernaryOperation op, lir::Operand* al, - lir::Operand* ah, lir::Operand* bl, - lir::Operand* bh, lir::Constant* target, - BinaryOperationType compareSigned, - BinaryOperationType compareUnsigned) -{ - compareSigned(con, 4, ah, 4, bh); - - unsigned next = 0; - - switch (op) { - case lir::JumpIfEqual: - case lir::JumpIfFloatEqual: - next = con->code.length(); - emit(con, bne(0)); - - compareSigned(con, 4, al, 4, bl); - conditional(con, beq(0), target); - break; - - case lir::JumpIfNotEqual: - case lir::JumpIfFloatNotEqual: - conditional(con, bne(0), target); - - compareSigned(con, 4, al, 4, bl); - conditional(con, bne(0), target); - break; - - case lir::JumpIfLess: - case lir::JumpIfFloatLess: - conditional(con, blt(0), target); - - next = con->code.length(); - emit(con, bgt(0)); - - compareUnsigned(con, 4, al, 4, bl); - conditional(con, blo(0), target); - break; - - case lir::JumpIfGreater: - case lir::JumpIfFloatGreater: - conditional(con, bgt(0), target); - - next = con->code.length(); - emit(con, blt(0)); - - compareUnsigned(con, 4, al, 4, bl); - conditional(con, bhi(0), target); - break; - - case lir::JumpIfLessOrEqual: - case lir::JumpIfFloatLessOrEqual: - conditional(con, blt(0), target); - - next = con->code.length(); - emit(con, bgt(0)); - - compareUnsigned(con, 4, al, 4, bl); - conditional(con, bls(0), target); - break; - - case lir::JumpIfGreaterOrEqual: - case lir::JumpIfFloatGreaterOrEqual: - conditional(con, bgt(0), target); - - next = con->code.length(); - emit(con, blt(0)); - - compareUnsigned(con, 4, al, 4, bl); - conditional(con, bhs(0), target); - break; - - default: - abort(con); - } - - if (next) { - updateOffset - (con->s, con->code.data + next, reinterpret_cast - (con->code.data + con->code.length())); - } -} - -void -branchRR(Context* con, lir::TernaryOperation op, unsigned size, - lir::Register* a, lir::Register* b, - lir::Constant* target) -{ - if (!isFpr(a) && size > TargetBytesPerWord) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - branchLong(con, op, a, &ah, b, &bh, target, CAST2(compareRR), - CAST2(compareRR)); - } else { - compareRR(con, size, a, size, b); - branch(con, op, target); - } -} - -void -branchCR(Context* con, lir::TernaryOperation op, unsigned size, - lir::Constant* a, lir::Register* b, - lir::Constant* target) -{ - assert(con, !isFloatBranch(op)); - - if (size > TargetBytesPerWord) { - int64_t v = a->value->value(); - - ResolvedPromise low(v & ~static_cast(0)); - lir::Constant al(&low); - - ResolvedPromise high((v >> 32) & ~static_cast(0)); - lir::Constant ah(&high); - - lir::Register bh(b->high); - - branchLong(con, op, &al, &ah, b, &bh, target, CAST2(compareCR), - CAST2(compareCR)); - } else { - compareCR(con, size, a, size, b); - branch(con, op, target); - } -} - -void -branchRM(Context* con, lir::TernaryOperation op, unsigned size, - lir::Register* a, lir::Memory* b, - lir::Constant* target) -{ - assert(con, !isFloatBranch(op)); - assert(con, size <= TargetBytesPerWord); - - compareRM(con, size, a, size, b); - branch(con, op, target); -} - -void -branchCM(Context* con, lir::TernaryOperation op, unsigned size, - lir::Constant* a, lir::Memory* b, - lir::Constant* target) -{ - assert(con, !isFloatBranch(op)); - assert(con, size <= TargetBytesPerWord); - - compareCM(con, size, a, size, b); - branch(con, op, target); -} - -ShiftMaskPromise* -shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask) -{ - return new(con->zone) ShiftMaskPromise(base, shift, mask); -} - -void -moveCM(Context* con, unsigned srcSize, lir::Constant* src, - unsigned dstSize, lir::Memory* dst) -{ - switch (dstSize) { - case 8: { - lir::Constant srcHigh - (shiftMaskPromise(con, src->value, 32, 0xFFFFFFFF)); - lir::Constant srcLow - (shiftMaskPromise(con, src->value, 0, 0xFFFFFFFF)); - - lir::Memory dstLow - (dst->base, dst->offset + 4, dst->index, dst->scale); - - moveCM(con, 4, &srcLow, 4, &dstLow); - moveCM(con, 4, &srcHigh, 4, dst); - } break; - - default: - lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); - moveCR(con, srcSize, src, dstSize, &tmp); - moveRM(con, dstSize, &tmp, dstSize, dst); - con->client->releaseTemporary(tmp.low); - } -} - -void -negateRR(Context* con, unsigned srcSize, lir::Register* src, - unsigned dstSize UNUSED, lir::Register* dst) -{ - assert(con, srcSize == dstSize); - - emit(con, mvn(dst->low, src->low)); - emit(con, SETS(addi(dst->low, dst->low, 1))); - if (srcSize == 8) { - emit(con, mvn(dst->high, src->high)); - emit(con, adci(dst->high, dst->high, 0)); - } -} - -void -callR(Context* con, unsigned size UNUSED, lir::Register* target) -{ - assert(con, size == TargetBytesPerWord); - emit(con, blx(target->low)); -} - -void -callC(Context* con, unsigned size UNUSED, lir::Constant* target) -{ - assert(con, size == TargetBytesPerWord); - - appendOffsetTask(con, target->value, offsetPromise(con)); - emit(con, bl(0)); -} - -void -longCallC(Context* con, unsigned size UNUSED, lir::Constant* target) -{ - assert(con, size == TargetBytesPerWord); - - lir::Register tmp(4); - moveCR2(con, TargetBytesPerWord, target, &tmp, offsetPromise(con)); - callR(con, TargetBytesPerWord, &tmp); -} - -void -longJumpC(Context* con, unsigned size UNUSED, lir::Constant* target) -{ - assert(con, size == TargetBytesPerWord); - - lir::Register tmp(4); // a non-arg reg that we don't mind clobbering - moveCR2(con, TargetBytesPerWord, target, &tmp, offsetPromise(con)); - jumpR(con, TargetBytesPerWord, &tmp); -} - -void -jumpC(Context* con, unsigned size UNUSED, lir::Constant* target) -{ - assert(con, size == TargetBytesPerWord); - - appendOffsetTask(con, target->value, offsetPromise(con)); - emit(con, b(0)); -} - -void -return_(Context* con) -{ - emit(con, bx(LinkRegister)); -} - -void -trap(Context* con) -{ - emit(con, bkpt(0)); -} - -void -memoryBarrier(Context*) {} - // END OPERATION COMPILERS unsigned @@ -1861,99 +138,6 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED, *stack = static_cast(*stack) + offset; } -void -populateTables(ArchitectureContext* con) -{ - const lir::OperandType C = lir::ConstantOperand; - const lir::OperandType A = lir::AddressOperand; - const lir::OperandType R = lir::RegisterOperand; - const lir::OperandType M = lir::MemoryOperand; - - OperationType* zo = con->operations; - UnaryOperationType* uo = con->unaryOperations; - BinaryOperationType* bo = con->binaryOperations; - TernaryOperationType* to = con->ternaryOperations; - BranchOperationType* bro = con->branchOperations; - - zo[lir::Return] = return_; - zo[lir::LoadBarrier] = memoryBarrier; - zo[lir::StoreStoreBarrier] = memoryBarrier; - zo[lir::StoreLoadBarrier] = memoryBarrier; - zo[lir::Trap] = trap; - - uo[index(con, lir::LongCall, C)] = CAST1(longCallC); - - uo[index(con, lir::AlignedLongCall, C)] = CAST1(longCallC); - - uo[index(con, lir::LongJump, C)] = CAST1(longJumpC); - - uo[index(con, lir::AlignedLongJump, C)] = CAST1(longJumpC); - - uo[index(con, lir::Jump, R)] = CAST1(jumpR); - uo[index(con, lir::Jump, C)] = CAST1(jumpC); - - uo[index(con, lir::AlignedJump, R)] = CAST1(jumpR); - uo[index(con, lir::AlignedJump, C)] = CAST1(jumpC); - - uo[index(con, lir::Call, C)] = CAST1(callC); - uo[index(con, lir::Call, R)] = CAST1(callR); - - uo[index(con, lir::AlignedCall, C)] = CAST1(callC); - uo[index(con, lir::AlignedCall, R)] = CAST1(callR); - - bo[index(con, lir::Move, R, R)] = CAST2(moveRR); - bo[index(con, lir::Move, C, R)] = CAST2(moveCR); - bo[index(con, lir::Move, C, M)] = CAST2(moveCM); - bo[index(con, lir::Move, M, R)] = CAST2(moveMR); - bo[index(con, lir::Move, R, M)] = CAST2(moveRM); - bo[index(con, lir::Move, A, R)] = CAST2(moveAR); - - bo[index(con, lir::MoveZ, R, R)] = CAST2(moveZRR); - bo[index(con, lir::MoveZ, M, R)] = CAST2(moveZMR); - bo[index(con, lir::MoveZ, C, R)] = CAST2(moveCR); - - bo[index(con, lir::Negate, R, R)] = CAST2(negateRR); - - bo[index(con, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); - bo[index(con, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); - bo[index(con, lir::Float2Float, R, R)] = CAST2(float2FloatRR); - bo[index(con, lir::Float2Int, R, R)] = CAST2(float2IntRR); - bo[index(con, lir::Int2Float, R, R)] = CAST2(int2FloatRR); - bo[index(con, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); - - to[index(con, lir::Add, R)] = CAST3(addR); - - to[index(con, lir::Subtract, R)] = CAST3(subR); - - to[index(con, lir::Multiply, R)] = CAST3(multiplyR); - - to[index(con, lir::FloatAdd, R)] = CAST3(floatAddR); - to[index(con, lir::FloatSubtract, R)] = CAST3(floatSubtractR); - to[index(con, lir::FloatMultiply, R)] = CAST3(floatMultiplyR); - to[index(con, lir::FloatDivide, R)] = CAST3(floatDivideR); - - to[index(con, lir::ShiftLeft, R)] = CAST3(shiftLeftR); - to[index(con, lir::ShiftLeft, C)] = CAST3(shiftLeftC); - - to[index(con, lir::ShiftRight, R)] = CAST3(shiftRightR); - to[index(con, lir::ShiftRight, C)] = CAST3(shiftRightC); - - to[index(con, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); - to[index(con, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); - - to[index(con, lir::And, R)] = CAST3(andR); - to[index(con, lir::And, C)] = CAST3(andC); - - to[index(con, lir::Or, R)] = CAST3(orR); - - to[index(con, lir::Xor, R)] = CAST3(xorR); - - bro[branchIndex(con, R, R)] = CAST_BRANCH(branchRR); - bro[branchIndex(con, C, R)] = CAST_BRANCH(branchCR); - bro[branchIndex(con, C, M)] = CAST_BRANCH(branchCM); - bro[branchIndex(con, R, M)] = CAST_BRANCH(branchRM); -} - class MyArchitecture: public Assembler::Architecture { public: MyArchitecture(System* system): con(system), referenceCount(0) { diff --git a/src/codegen/arm/block.h b/src/codegen/arm/block.h index 42f3cceaa3..cc634f7f75 100644 --- a/src/codegen/arm/block.h +++ b/src/codegen/arm/block.h @@ -13,7 +13,6 @@ #include #include -#include "alloc-vector.h" namespace avian { namespace codegen { diff --git a/src/codegen/arm/context.h b/src/codegen/arm/context.h index ccba7e403d..a5388527ed 100644 --- a/src/codegen/arm/context.h +++ b/src/codegen/arm/context.h @@ -53,15 +53,6 @@ class Context { unsigned constantPoolCount; }; -class Task { - public: - Task(Task* next): next(next) { } - - virtual void run(Context* con) = 0; - - Task* next; -}; - typedef void (*OperationType)(Context*); typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); diff --git a/src/codegen/arm/encode.h b/src/codegen/arm/encode.h new file mode 100644 index 0000000000..d6d3e983b9 --- /dev/null +++ b/src/codegen/arm/encode.h @@ -0,0 +1,184 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H + +#include +#include + +namespace avian { +namespace codegen { +namespace arm { + +namespace isa { + +// SYSTEM REGISTERS +const int FPSID = 0x0; +const int FPSCR = 0x1; +const int FPEXC = 0x8; +// INSTRUCTION OPTIONS +enum CONDITION { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV }; +enum SHIFTOP { LSL, LSR, ASR, ROR }; +// INSTRUCTION FORMATS +inline int DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int Rm) +{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; } +inline int DATAS(int cond, int opcode, int S, int Rn, int Rd, int Rs, int Sh, int Rm) +{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | Rs<<8 | Sh<<5 | 1<<4 | Rm; } +inline int DATAI(int cond, int opcode, int S, int Rn, int Rd, int rot, int imm) +{ return cond<<28 | 1<<25 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | rot<<8 | (imm&0xff); } +inline int BRANCH(int cond, int L, int offset) +{ return cond<<28 | 5<<25 | L<<24 | (offset&0xffffff); } +inline int BRANCHX(int cond, int L, int Rm) +{ return cond<<28 | 0x4bffc<<6 | L<<5 | 1<<4 | Rm; } +inline int MULTIPLY(int cond, int mul, int S, int Rd, int Rn, int Rs, int Rm) +{ return cond<<28 | mul<<21 | S<<20 | Rd<<16 | Rn<<12 | Rs<<8 | 9<<4 | Rm; } +inline int XFER(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int shift, int Sh, int Rm) +{ return cond<<28 | 3<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; } +inline int XFERI(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int offset) +{ return cond<<28 | 2<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | (offset&0xfff); } +inline int XFER2(int cond, int P, int U, int W, int L, int Rn, int Rd, int S, int H, int Rm) +{ return cond<<28 | P<<24 | U<<23 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | 1<<7 | S<<6 | H<<5 | 1<<4 | Rm; } +inline int XFER2I(int cond, int P, int U, int W, int L, int Rn, int Rd, int offsetH, int S, int H, int offsetL) +{ return cond<<28 | P<<24 | U<<23 | 1<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | offsetH<<8 | 1<<7 | S<<6 | H<<5 | 1<<4 | (offsetL&0xf); } +inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm) +{ return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; } +inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) // offset is in words, not bytes +{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff)>>2; } +inline int COREG(int cond, int opcode_1, int L, int CRn, int Rd, int cp_num, int opcode_2, int CRm) +{ return cond<<28 | 0xe<<24 | opcode_1<<21 | L<<20 | CRn<<16 | Rd<<12 | cp_num<<8 | opcode_2<<5 | 1<<4 | CRm; } +inline int COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm) +{ return cond<<28 | 0xc4<<20 | L<<20 | Rn<<16 | Rd<<12 | cp_num<<8 | opcode<<4 | CRm;} +// FIELD CALCULATORS +inline int calcU(int imm) { return imm >= 0 ? 1 : 0; } +// INSTRUCTIONS +// The "cond" and "S" fields are set using the SETCOND() and SETS() functions +inline int b(int offset) { return BRANCH(AL, 0, offset); } +inline int bl(int offset) { return BRANCH(AL, 1, offset); } +inline int bx(int Rm) { return BRANCHX(AL, 0, Rm); } +inline int blx(int Rm) { return BRANCHX(AL, 1, Rm); } +inline int and_(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm); } +inline int eor(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm); } +inline int rsb(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm); } +inline int add(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm); } +inline int adc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm); } +inline int rsc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm); } +inline int cmp(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xa, 1, Rn, 0, shift, Sh, Rm); } +inline int orr(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm); } +inline int mov(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xd, 0, 0, Rd, shift, Sh, Rm); } +inline int mvn(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xf, 0, 0, Rd, shift, Sh, Rm); } +inline int andi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm); } +inline int subi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm); } +inline int rsbi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm); } +inline int addi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm); } +inline int adci(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm); } +inline int bici(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm); } +inline int cmpi(int Rn, int imm, int rot=0) { return DATAI(AL, 0xa, 1, Rn, 0, rot, imm); } +inline int movi(int Rd, int imm, int rot=0) { return DATAI(AL, 0xd, 0, 0, Rd, rot, imm); } +inline int orrsh(int Rd, int Rn, int Rm, int Rs, int Sh) { return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm); } +inline int movsh(int Rd, int Rm, int Rs, int Sh) { return DATAS(AL, 0xd, 0, 0, Rd, Rs, Sh, Rm); } +inline int mul(int Rd, int Rm, int Rs) { return MULTIPLY(AL, 0, 0, Rd, 0, Rs, Rm); } +inline int mla(int Rd, int Rm, int Rs, int Rn) { return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm); } +inline int umull(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm); } +inline int ldr(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm); } +inline int ldri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm)); } +inline int ldrb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm); } +inline int ldrbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 1, Rn, Rd, abs(imm)); } +inline int str(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 0, Rn, Rd, 0, 0, Rm); } +inline int stri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 0, Rn, Rd, abs(imm)); } +inline int strb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 0, Rn, Rd, 0, 0, Rm); } +inline int strbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 0, Rn, Rd, abs(imm)); } +inline int ldrh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 0, 1, Rm); } +inline int ldrhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); } +inline int strh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 0, Rn, Rd, 0, 1, Rm); } +inline int strhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 0, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); } +inline int ldrsh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 1, Rm); } +inline int ldrshi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 1, abs(imm)&0xf); } +inline int ldrsb(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm); } +inline int ldrsbi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 0, abs(imm)&0xf); } +// breakpoint instruction, this really has its own instruction format +inline int bkpt(int16_t immed) { return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf); } +// COPROCESSOR INSTRUCTIONS +inline int mcr(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); } +inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); } +inline int mrc(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); } +inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); } +// VFP FLOATING-POINT INSTRUCTIONS +inline int fmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); } +inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } +inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } +inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } +inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb, 7, Dd, 10, 6|(Sm&1), Sm>>1); } +inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); } +inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); } +inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); } +inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); } +// double-precision comparison instructions +inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); } +// double-precision conversion instructions +inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); } +inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); } +inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); } +// single load/store instructions for both precision types +inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); }; +inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); }; +inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); }; +inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); }; +// move between GPRs and FPRs +inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } +inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } +// move to/from VFP system registers +inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); } +// these move around pairs of single-precision registers +inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); } +inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); } +// FLAG SETTERS +inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); } +inline int SETS(int ins) { return ins | 1<<20; } +// PSEUDO-INSTRUCTIONS +inline int lsl(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSL); } +inline int lsli(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSL, imm); } +inline int lsr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSR); } +inline int lsri(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSR, imm); } +inline int asr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, ASR); } +inline int asri(int Rd, int Rm, int imm) { return mov(Rd, Rm, ASR, imm); } +inline int beq(int offset) { return SETCOND(b(offset), EQ); } +inline int bne(int offset) { return SETCOND(b(offset), NE); } +inline int bls(int offset) { return SETCOND(b(offset), LS); } +inline int bhi(int offset) { return SETCOND(b(offset), HI); } +inline int blt(int offset) { return SETCOND(b(offset), LT); } +inline int bgt(int offset) { return SETCOND(b(offset), GT); } +inline int ble(int offset) { return SETCOND(b(offset), LE); } +inline int bge(int offset) { return SETCOND(b(offset), GE); } +inline int blo(int offset) { return SETCOND(b(offset), CC); } +inline int bhs(int offset) { return SETCOND(b(offset), CS); } +inline int bpl(int offset) { return SETCOND(b(offset), PL); } +inline int fmstat() { return fmrx(15, FPSCR); } + +} // namespace isa + +inline void emit(Context* con, int code) { con->code.append4(code); } + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H diff --git a/src/codegen/arm/fixup.cpp b/src/codegen/arm/fixup.cpp new file mode 100644 index 0000000000..2cf0b01216 --- /dev/null +++ b/src/codegen/arm/fixup.cpp @@ -0,0 +1,175 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "fixup.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace arm { + +unsigned padding(MyBlock*, unsigned); + +OffsetPromise::OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace): + con(con), block(block), offset(offset), forTrace(forTrace) +{ } + +bool OffsetPromise::resolved() { + return block->start != static_cast(~0); +} + +int64_t OffsetPromise::value() { + assert(con, resolved()); + + unsigned o = offset - block->offset; + return block->start + padding + (block, forTrace ? o - vm::TargetBytesPerWord : o) + o; +} + + +Promise* offsetPromise(Context* con, bool forTrace) { + return new(con->zone) OffsetPromise(con, con->lastBlock, con->code.length(), forTrace); +} + + +OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction): + s(s), + instruction(instruction) +{ } + +bool OffsetListener::resolve(int64_t value, void** location) { + void* p = updateOffset(s, instruction, value); + if (location) *location = p; + return false; +} + + +OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset): + Task(next), + promise(promise), + instructionOffset(instructionOffset) +{ } + +void OffsetTask::run(Context* con) { + if (promise->resolved()) { + updateOffset + (con->s, con->result + instructionOffset->value(), promise->value()); + } else { + new (promise->listen(sizeof(OffsetListener))) + OffsetListener(con->s, con->result + instructionOffset->value()); + } +} + +void appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) { + con->tasks = new(con->zone) OffsetTask(con->tasks, promise, instructionOffset); +} + +bool bounded(int right, int left, int32_t v) { + return ((v << left) >> left) == v and ((v >> right) << right) == v; +} + +void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value) { + // ARM's PC is two words ahead, and branches drop the bottom 2 bits. + int32_t v = (reinterpret_cast(value) - (instruction + 8)) >> 2; + + int32_t mask; + expect(s, bounded(0, 8, v)); + mask = 0xFFFFFF; + + int32_t* p = reinterpret_cast(instruction); + *p = (v & mask) | ((~mask) & *p); + + return instruction + 4; +} + +ConstantPoolEntry::ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next, + Promise* callOffset): + con(con), constant(constant), next(next), callOffset(callOffset), + address(0) +{ } + +int64_t ConstantPoolEntry::value() { + assert(con, resolved()); + + return reinterpret_cast(address); +} + +bool ConstantPoolEntry::resolved() { + return address != 0; +} + +ConstantPoolListener::ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address, + uint8_t* returnAddress): + s(s), + address(address), + returnAddress(returnAddress) +{ } + +bool ConstantPoolListener::resolve(int64_t value, void** location) { + *address = value; + if (location) { + *location = returnAddress ? static_cast(returnAddress) : address; + } + return true; +} + +PoolOffset::PoolOffset(MyBlock* block, ConstantPoolEntry* entry, unsigned offset): + block(block), entry(entry), next(0), offset(offset) +{ } + +PoolEvent::PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail, + unsigned offset): + poolOffsetHead(poolOffsetHead), poolOffsetTail(poolOffsetTail), next(0), + offset(offset) +{ } + +void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset) { + if (constant->resolved()) { + // make a copy, since the original might be allocated on the + // stack, and we need our copy to live until assembly is complete + constant = new(con->zone) ResolvedPromise(constant->value()); + } + + con->constantPool = new(con->zone) ConstantPoolEntry(con, constant, con->constantPool, callOffset); + + ++ con->constantPoolCount; + + PoolOffset* o = new(con->zone) PoolOffset(con->lastBlock, con->constantPool, con->code.length() - con->lastBlock->offset); + + if (DebugPool) { + fprintf(stderr, "add pool offset %p %d to block %p\n", + o, o->offset, con->lastBlock); + } + + if (con->lastBlock->poolOffsetTail) { + con->lastBlock->poolOffsetTail->next = o; + } else { + con->lastBlock->poolOffsetHead = o; + } + con->lastBlock->poolOffsetTail = o; +} + +void appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head, + PoolOffset* tail) +{ + PoolEvent* e = new(con->zone) PoolEvent(head, tail, offset); + + if (b->poolEventTail) { + b->poolEventTail->next = e; + } else { + b->poolEventHead = e; + } + b->poolEventTail = e; +} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/arm/fixup.h b/src/codegen/arm/fixup.h new file mode 100644 index 0000000000..77abf003bf --- /dev/null +++ b/src/codegen/arm/fixup.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H + +#include "target.h" + +#include +#include +#include "alloc-vector.h" + +namespace vm { +class System; +} + +namespace avian { +namespace codegen { +namespace arm { + +const bool DebugPool = false; + +const int32_t PoolOffsetMask = 0xFFF; + +class Task { + public: + Task(Task* next): next(next) { } + + virtual void run(Context* con) = 0; + + Task* next; +}; + +class OffsetPromise: public Promise { + public: + OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace); + + virtual bool resolved(); + + virtual int64_t value(); + + Context* con; + MyBlock* block; + unsigned offset; + bool forTrace; +}; + +Promise* offsetPromise(Context* con, bool forTrace = false); + +class OffsetListener: public Promise::Listener { + public: + OffsetListener(vm::System* s, uint8_t* instruction); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + uint8_t* instruction; +}; + +class OffsetTask: public Task { + public: + OffsetTask(Task* next, Promise* promise, Promise* instructionOffset); + + virtual void run(Context* con); + + Promise* promise; + Promise* instructionOffset; +}; + +void appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset); + +void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value); + +class ConstantPoolEntry: public Promise { + public: + ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next, + Promise* callOffset); + + virtual int64_t value(); + + virtual bool resolved(); + + Context* con; + Promise* constant; + ConstantPoolEntry* next; + Promise* callOffset; + void* address; + unsigned constantPoolCount; +}; + +class ConstantPoolListener: public Promise::Listener { + public: + ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address, + uint8_t* returnAddress); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + vm::target_uintptr_t* address; + uint8_t* returnAddress; +}; + +class PoolOffset { + public: + PoolOffset(MyBlock* block, ConstantPoolEntry* entry, unsigned offset); + + MyBlock* block; + ConstantPoolEntry* entry; + PoolOffset* next; + unsigned offset; +}; + +class PoolEvent { + public: + PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail, + unsigned offset); + + PoolOffset* poolOffsetHead; + PoolOffset* poolOffsetTail; + PoolEvent* next; + unsigned offset; +}; + +void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset); + +void appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head, + PoolOffset* tail); + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H diff --git a/src/codegen/arm/multimethod.cpp b/src/codegen/arm/multimethod.cpp new file mode 100644 index 0000000000..76c681a60f --- /dev/null +++ b/src/codegen/arm/multimethod.cpp @@ -0,0 +1,142 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "multimethod.h" +#include "operations.h" + +namespace avian { +namespace codegen { +namespace arm { + +unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) +{ + return operation + (lir::UnaryOperationCount * operand); +} + +unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2) +{ + return operation + + (lir::BinaryOperationCount * operand1) + + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); +} + +unsigned index(ArchitectureContext* con UNUSED, + lir::TernaryOperation operation, + lir::OperandType operand1) +{ + assert(con, not isBranch(operation)); + + return operation + (lir::NonBranchTernaryOperationCount * operand1); +} + +unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1, + lir::OperandType operand2) +{ + return operand1 + (lir::OperandTypeCount * operand2); +} + +void populateTables(ArchitectureContext* con) { + const lir::OperandType C = lir::ConstantOperand; + const lir::OperandType A = lir::AddressOperand; + const lir::OperandType R = lir::RegisterOperand; + const lir::OperandType M = lir::MemoryOperand; + + OperationType* zo = con->operations; + UnaryOperationType* uo = con->unaryOperations; + BinaryOperationType* bo = con->binaryOperations; + TernaryOperationType* to = con->ternaryOperations; + BranchOperationType* bro = con->branchOperations; + + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = memoryBarrier; + zo[lir::StoreStoreBarrier] = memoryBarrier; + zo[lir::StoreLoadBarrier] = memoryBarrier; + zo[lir::Trap] = trap; + + uo[index(con, lir::LongCall, C)] = CAST1(longCallC); + + uo[index(con, lir::AlignedLongCall, C)] = CAST1(longCallC); + + uo[index(con, lir::LongJump, C)] = CAST1(longJumpC); + + uo[index(con, lir::AlignedLongJump, C)] = CAST1(longJumpC); + + uo[index(con, lir::Jump, R)] = CAST1(jumpR); + uo[index(con, lir::Jump, C)] = CAST1(jumpC); + + uo[index(con, lir::AlignedJump, R)] = CAST1(jumpR); + uo[index(con, lir::AlignedJump, C)] = CAST1(jumpC); + + uo[index(con, lir::Call, C)] = CAST1(callC); + uo[index(con, lir::Call, R)] = CAST1(callR); + + uo[index(con, lir::AlignedCall, C)] = CAST1(callC); + uo[index(con, lir::AlignedCall, R)] = CAST1(callR); + + bo[index(con, lir::Move, R, R)] = CAST2(moveRR); + bo[index(con, lir::Move, C, R)] = CAST2(moveCR); + bo[index(con, lir::Move, C, M)] = CAST2(moveCM); + bo[index(con, lir::Move, M, R)] = CAST2(moveMR); + bo[index(con, lir::Move, R, M)] = CAST2(moveRM); + bo[index(con, lir::Move, A, R)] = CAST2(moveAR); + + bo[index(con, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(con, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(con, lir::MoveZ, C, R)] = CAST2(moveCR); + + bo[index(con, lir::Negate, R, R)] = CAST2(negateRR); + + bo[index(con, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + bo[index(con, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); + bo[index(con, lir::Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(con, lir::Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(con, lir::Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(con, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + + to[index(con, lir::Add, R)] = CAST3(addR); + + to[index(con, lir::Subtract, R)] = CAST3(subR); + + to[index(con, lir::Multiply, R)] = CAST3(multiplyR); + + to[index(con, lir::FloatAdd, R)] = CAST3(floatAddR); + to[index(con, lir::FloatSubtract, R)] = CAST3(floatSubtractR); + to[index(con, lir::FloatMultiply, R)] = CAST3(floatMultiplyR); + to[index(con, lir::FloatDivide, R)] = CAST3(floatDivideR); + + to[index(con, lir::ShiftLeft, R)] = CAST3(shiftLeftR); + to[index(con, lir::ShiftLeft, C)] = CAST3(shiftLeftC); + + to[index(con, lir::ShiftRight, R)] = CAST3(shiftRightR); + to[index(con, lir::ShiftRight, C)] = CAST3(shiftRightC); + + to[index(con, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); + to[index(con, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); + + to[index(con, lir::And, R)] = CAST3(andR); + to[index(con, lir::And, C)] = CAST3(andC); + + to[index(con, lir::Or, R)] = CAST3(orR); + + to[index(con, lir::Xor, R)] = CAST3(xorR); + + bro[branchIndex(con, R, R)] = CAST_BRANCH(branchRR); + bro[branchIndex(con, C, R)] = CAST_BRANCH(branchCR); + bro[branchIndex(con, C, M)] = CAST_BRANCH(branchCM); + bro[branchIndex(con, R, M)] = CAST_BRANCH(branchRM); +} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/arm/multimethod.h b/src/codegen/arm/multimethod.h new file mode 100644 index 0000000000..7c574b588c --- /dev/null +++ b/src/codegen/arm/multimethod.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H + +#include +#include + +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST3(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + +namespace avian { +namespace codegen { +namespace arm { + +unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand); + +unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2); + +unsigned index(ArchitectureContext* con UNUSED, + lir::TernaryOperation operation, + lir::OperandType operand1); + +unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1, + lir::OperandType operand2); + +void populateTables(ArchitectureContext* con); + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H diff --git a/src/codegen/arm/operations.cpp b/src/codegen/arm/operations.cpp new file mode 100644 index 0000000000..b896a88f00 --- /dev/null +++ b/src/codegen/arm/operations.cpp @@ -0,0 +1,1235 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "operations.h" +#include "encode.h" +#include "block.h" +#include "fixup.h" +#include "multimethod.h" + +namespace avian { +namespace codegen { +namespace arm { + +using namespace isa; +using namespace avian::util; + +inline bool isOfWidth(int64_t i, int size) { return static_cast(i) >> size == 0; } + +inline unsigned lo8(int64_t i) { return (unsigned)(i&MASK_LO8); } + +void andC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) +{ + if (size == 8) { + int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); + ResolvedPromise maskPromise(0x3F); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp3); + andC(con, 4, &mask, a, &dst); + emit(con, lsl(tmp1, b->high, tmp3)); + emit(con, rsbi(tmp2, tmp3, 32)); + emit(con, orrsh(tmp1, tmp1, b->low, tmp2, LSR)); + emit(con, SETS(subi(t->high, tmp3, 32))); + emit(con, SETCOND(mov(t->high, tmp1), MI)); + emit(con, SETCOND(lsl(t->high, b->low, t->high), PL)); + emit(con, lsl(t->low, b->low, tmp3)); + freeTemp(con, tmp1); freeTemp(con, tmp2); freeTemp(con, tmp3); + } else { + int tmp = newTemp(con); + ResolvedPromise maskPromise(0x1F); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp); + andC(con, size, &mask, a, &dst); + emit(con, lsl(t->low, b->low, tmp)); + freeTemp(con, tmp); + } +} + +void moveRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); + +void shiftLeftC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) +{ + assert(con, size == vm::TargetBytesPerWord); + if (getValue(a) & 0x1F) { + emit(con, lsli(t->low, b->low, getValue(a) & 0x1F)); + } else { + moveRR(con, size, b, size, t); + } +} + +void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) +{ + if (size == 8) { + int tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); + ResolvedPromise maskPromise(0x3F); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp3); + andC(con, 4, &mask, a, &dst); + emit(con, lsr(tmp1, b->low, tmp3)); + emit(con, rsbi(tmp2, tmp3, 32)); + emit(con, orrsh(tmp1, tmp1, b->high, tmp2, LSL)); + emit(con, SETS(subi(t->low, tmp3, 32))); + emit(con, SETCOND(mov(t->low, tmp1), MI)); + emit(con, SETCOND(asr(t->low, b->high, t->low), PL)); + emit(con, asr(t->high, b->high, tmp3)); + freeTemp(con, tmp1); freeTemp(con, tmp2); freeTemp(con, tmp3); + } else { + int tmp = newTemp(con); + ResolvedPromise maskPromise(0x1F); + lir::Constant mask(&maskPromise); + lir::Register dst(tmp); + andC(con, size, &mask, a, &dst); + emit(con, asr(t->low, b->low, tmp)); + freeTemp(con, tmp); + } +} + +void shiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) +{ + assert(con, size == vm::TargetBytesPerWord); + if (getValue(a) & 0x1F) { + emit(con, asri(t->low, b->low, getValue(a) & 0x1F)); + } else { + moveRR(con, size, b, size, t); + } +} + +void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) +{ + int tmpShift = newTemp(con); + ResolvedPromise maskPromise(size == 8 ? 0x3F : 0x1F); + lir::Constant mask(&maskPromise); + lir::Register dst(tmpShift); + andC(con, 4, &mask, a, &dst); + emit(con, lsr(t->low, b->low, tmpShift)); + if (size == 8) { + int tmpHi = newTemp(con), tmpLo = newTemp(con); + emit(con, SETS(rsbi(tmpHi, tmpShift, 32))); + emit(con, lsl(tmpLo, b->high, tmpHi)); + emit(con, orr(t->low, t->low, tmpLo)); + emit(con, addi(tmpHi, tmpShift, -32)); + emit(con, lsr(tmpLo, b->high, tmpHi)); + emit(con, orr(t->low, t->low, tmpLo)); + emit(con, lsr(t->high, b->high, tmpShift)); + freeTemp(con, tmpHi); freeTemp(con, tmpLo); + } + freeTemp(con, tmpShift); +} + +void unsignedShiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t) +{ + assert(con, size == vm::TargetBytesPerWord); + if (getValue(a) & 0x1F) { + emit(con, lsri(t->low, b->low, getValue(a) & 0x1F)); + } else { + moveRR(con, size, b, size, t); + } +} + +bool +needJump(MyBlock* b) +{ + return b->next or b->size != (b->size & PoolOffsetMask); +} + +unsigned +padding(MyBlock* b, unsigned offset) +{ + unsigned total = 0; + for (PoolEvent* e = b->poolEventHead; e; e = e->next) { + if (e->offset <= offset) { + if (needJump(b)) { + total += vm::TargetBytesPerWord; + } + for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) { + total += vm::TargetBytesPerWord; + } + } else { + break; + } + } + return total; +} + +void resolve(MyBlock* b) +{ + Context* con = b->context; + + if (b->poolOffsetHead) { + if (con->poolOffsetTail) { + con->poolOffsetTail->next = b->poolOffsetHead; + } else { + con->poolOffsetHead = b->poolOffsetHead; + } + con->poolOffsetTail = b->poolOffsetTail; + } + + if (con->poolOffsetHead) { + bool append; + if (b->next == 0 or b->next->poolEventHead) { + append = true; + } else { + int32_t v = (b->start + b->size + b->next->size + vm::TargetBytesPerWord - 8) + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); + + append = (v != (v & PoolOffsetMask)); + + if (DebugPool) { + fprintf(stderr, + "current %p %d %d next %p %d %d\n", + b, b->start, b->size, b->next, b->start + b->size, + b->next->size); + fprintf(stderr, + "offset %p %d is of distance %d to next block; append? %d\n", + con->poolOffsetHead, con->poolOffsetHead->offset, v, append); + } + } + + if (append) { +#ifndef NDEBUG + int32_t v = (b->start + b->size - 8) + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); + + expect(con, v == (v & PoolOffsetMask)); +#endif // not NDEBUG + + appendPoolEvent(con, b, b->size, con->poolOffsetHead, con->poolOffsetTail); + + if (DebugPool) { + for (PoolOffset* o = con->poolOffsetHead; o; o = o->next) { + fprintf(stderr, + "include %p %d in pool event %p at offset %d in block %p\n", + o, o->offset, b->poolEventTail, b->size, b); + } + } + + con->poolOffsetHead = 0; + con->poolOffsetTail = 0; + } + } +} + +void jumpR(Context* con, unsigned size UNUSED, lir::Register* target) +{ + assert(con, size == vm::TargetBytesPerWord); + emit(con, bx(target->low)); +} + +void swapRR(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) +{ + assert(con, aSize == vm::TargetBytesPerWord); + assert(con, bSize == vm::TargetBytesPerWord); + + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveRR(con, aSize, a, bSize, &tmp); + moveRR(con, bSize, b, aSize, a); + moveRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); +} + +void moveRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst) +{ + bool srcIsFpr = isFpr(src); + bool dstIsFpr = isFpr(dst); + if (srcIsFpr || dstIsFpr) { // FPR(s) involved + assert(con, srcSize == dstSize); + const bool dprec = srcSize == 8; + if (srcIsFpr && dstIsFpr) { // FPR to FPR + if (dprec) emit(con, fcpyd(fpr64(dst), fpr64(src))); // double + else emit(con, fcpys(fpr32(dst), fpr32(src))); // single + } else if (srcIsFpr) { // FPR to GPR + if (dprec) emit(con, fmrrd(dst->low, dst->high, fpr64(src))); + else emit(con, fmrs(dst->low, fpr32(src))); + } else { // GPR to FPR + if (dprec) emit(con, fmdrr(fpr64(dst->low), src->low, src->high)); + else emit(con, fmsr(fpr32(dst), src->low)); + } + return; + } + + switch (srcSize) { + case 1: + emit(con, lsli(dst->low, src->low, 24)); + emit(con, asri(dst->low, dst->low, 24)); + break; + + case 2: + emit(con, lsli(dst->low, src->low, 16)); + emit(con, asri(dst->low, dst->low, 16)); + break; + + case 4: + case 8: + if (srcSize == 4 and dstSize == 8) { + moveRR(con, 4, src, 4, dst); + emit(con, asri(dst->high, src->low, 31)); + } else if (srcSize == 8 and dstSize == 8) { + lir::Register srcHigh(src->high); + lir::Register dstHigh(dst->high); + + if (src->high == dst->low) { + if (src->low == dst->high) { + swapRR(con, 4, src, 4, dst); + } else { + moveRR(con, 4, &srcHigh, 4, &dstHigh); + moveRR(con, 4, src, 4, dst); + } + } else { + moveRR(con, 4, src, 4, dst); + moveRR(con, 4, &srcHigh, 4, &dstHigh); + } + } else if (src->low != dst->low) { + emit(con, mov(dst->low, src->low)); + } + break; + + default: abort(con); + } +} + +void moveZRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned, lir::Register* dst) +{ + switch (srcSize) { + case 2: + emit(con, lsli(dst->low, src->low, 16)); + emit(con, lsri(dst->low, dst->low, 16)); + break; + + default: abort(con); + } +} + +void moveCR(Context* con, unsigned size, lir::Constant* src, + unsigned, lir::Register* dst); + +void moveCR2(Context* con, unsigned size, lir::Constant* src, + lir::Register* dst, Promise* callOffset) +{ + if (isFpr(dst)) { // floating-point + lir::Register tmp = size > 4 ? makeTemp64(con) : + makeTemp(con); + moveCR(con, size, src, size, &tmp); + moveRR(con, size, &tmp, size, dst); + freeTemp(con, tmp); + } else if (size > 4) { + uint64_t value = (uint64_t)src->value->value(); + ResolvedPromise loBits(value & MASK_LO32); + lir::Constant srcLo(&loBits); + ResolvedPromise hiBits(value >> 32); + lir::Constant srcHi(&hiBits); + lir::Register dstHi(dst->high); + moveCR(con, 4, &srcLo, 4, dst); + moveCR(con, 4, &srcHi, 4, &dstHi); + } else if (src->value->resolved() and isOfWidth(getValue(src), 8)) { + emit(con, movi(dst->low, lo8(getValue(src)))); // fits in immediate + } else { + appendConstantPoolEntry(con, src->value, callOffset); + emit(con, ldri(dst->low, ProgramCounter, 0)); // load 32 bits + } +} + +void moveCR(Context* con, unsigned size, lir::Constant* src, + unsigned, lir::Register* dst) +{ + moveCR2(con, size, src, dst, 0); +} + +void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if (size == 8) { + emit(con, SETS(add(t->low, a->low, b->low))); + emit(con, adc(t->high, a->high, b->high)); + } else { + emit(con, add(t->low, a->low, b->low)); + } +} + +void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if (size == 8) { + emit(con, SETS(rsb(t->low, a->low, b->low))); + emit(con, rsc(t->high, a->high, b->high)); + } else { + emit(con, rsb(t->low, a->low, b->low)); + } +} + +void addC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) +{ + assert(con, size == vm::TargetBytesPerWord); + + int32_t v = a->value->value(); + if (v) { + if (v > 0 and v < 256) { + emit(con, addi(dst->low, b->low, v)); + } else if (v > 0 and v < 1024 and v % 4 == 0) { + emit(con, addi(dst->low, b->low, v >> 2, 15)); + } else { + // todo + abort(con); + } + } else { + moveRR(con, size, b, size, dst); + } +} + +void subC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) +{ + assert(con, size == vm::TargetBytesPerWord); + + int32_t v = a->value->value(); + if (v) { + if (v > 0 and v < 256) { + emit(con, subi(dst->low, b->low, v)); + } else if (v > 0 and v < 1024 and v % 4 == 0) { + emit(con, subi(dst->low, b->low, v >> 2, 15)); + } else { + // todo + abort(con); + } + } else { + moveRR(con, size, b, size, dst); + } +} + +void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if (size == 8) { + bool useTemporaries = b->low == t->low; + int tmpLow = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->low; + int tmpHigh = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->high; + + emit(con, umull(tmpLow, tmpHigh, a->low, b->low)); + emit(con, mla(tmpHigh, a->low, b->high, tmpHigh)); + emit(con, mla(tmpHigh, a->high, b->low, tmpHigh)); + + if (useTemporaries) { + emit(con, mov(t->low, tmpLow)); + emit(con, mov(t->high, tmpHigh)); + con->client->releaseTemporary(tmpLow); + con->client->releaseTemporary(tmpHigh); + } + } else { + emit(con, mul(t->low, a->low, b->low)); + } +} + +void floatAbsoluteRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { + if (size == 8) { + emit(con, fabsd(fpr64(b), fpr64(a))); + } else { + emit(con, fabss(fpr32(b), fpr32(a))); + } +} + +void floatNegateRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { + if (size == 8) { + emit(con, fnegd(fpr64(b), fpr64(a))); + } else { + emit(con, fnegs(fpr32(b), fpr32(a))); + } +} + +void float2FloatRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { + if (size == 8) { + emit(con, fcvtsd(fpr32(b), fpr64(a))); + } else { + emit(con, fcvtds(fpr64(b), fpr32(a))); + } +} + +void float2IntRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { + int tmp = newTemp(con, FPR_MASK); + int ftmp = fpr32(tmp); + if (size == 8) { // double to int + emit(con, ftosizd(ftmp, fpr64(a))); + } else { // float to int + emit(con, ftosizs(ftmp, fpr32(a))); + } // else thunked + emit(con, fmrs(b->low, ftmp)); + freeTemp(con, tmp); +} + +void int2FloatRR(Context* con, unsigned, lir::Register* a, unsigned size, lir::Register* b) { + emit(con, fmsr(fpr32(b), a->low)); + if (size == 8) { // int to double + emit(con, fsitod(fpr64(b), fpr32(b))); + } else { // int to float + emit(con, fsitos(fpr32(b), fpr32(b))); + } // else thunked +} + +void floatSqrtRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b) { + if (size == 8) { + emit(con, fsqrtd(fpr64(b), fpr64(a))); + } else { + emit(con, fsqrts(fpr32(b), fpr32(a))); + } +} + +void floatAddR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if (size == 8) { + emit(con, faddd(fpr64(t), fpr64(a), fpr64(b))); + } else { + emit(con, fadds(fpr32(t), fpr32(a), fpr32(b))); + } +} + +void floatSubtractR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if (size == 8) { + emit(con, fsubd(fpr64(t), fpr64(b), fpr64(a))); + } else { + emit(con, fsubs(fpr32(t), fpr32(b), fpr32(a))); + } +} + +void floatMultiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if (size == 8) { + emit(con, fmuld(fpr64(t), fpr64(a), fpr64(b))); + } else { + emit(con, fmuls(fpr32(t), fpr32(a), fpr32(b))); + } +} + +void floatDivideR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if (size == 8) { + emit(con, fdivd(fpr64(t), fpr64(b), fpr64(a))); + } else { + emit(con, fdivs(fpr32(t), fpr32(b), fpr32(a))); + } +} + +int normalize(Context* con, int offset, int index, unsigned scale, + bool* preserveIndex, bool* release) +{ + if (offset != 0 or scale != 1) { + lir::Register normalizedIndex + (*preserveIndex ? con->client->acquireTemporary(GPR_MASK) : index); + + if (*preserveIndex) { + *release = true; + *preserveIndex = false; + } else { + *release = false; + } + + int scaled; + + if (scale != 1) { + lir::Register unscaledIndex(index); + + ResolvedPromise scalePromise(log(scale)); + lir::Constant scaleConstant(&scalePromise); + + shiftLeftC(con, vm::TargetBytesPerWord, &scaleConstant, + &unscaledIndex, &normalizedIndex); + + scaled = normalizedIndex.low; + } else { + scaled = index; + } + + if (offset != 0) { + lir::Register untranslatedIndex(scaled); + + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, vm::TargetBytesPerWord, &offsetConstant, vm::TargetBytesPerWord, &tmp); + addR(con, vm::TargetBytesPerWord, &tmp, &untranslatedIndex, &normalizedIndex); + con->client->releaseTemporary(tmp.low); + } + + return normalizedIndex.low; + } else { + *release = false; + return index; + } +} + +void store(Context* con, unsigned size, lir::Register* src, + int base, int offset, int index, unsigned scale, bool preserveIndex) +{ + if (index != lir::NoRegister) { + bool release; + int normalized = normalize + (con, offset, index, scale, &preserveIndex, &release); + + if (!isFpr(src)) { // GPR store + switch (size) { + case 1: + emit(con, strb(src->low, base, normalized)); + break; + + case 2: + emit(con, strh(src->low, base, normalized)); + break; + + case 4: + emit(con, str(src->low, base, normalized)); + break; + + case 8: { // split into 2 32-bit stores + lir::Register srcHigh(src->high); + store(con, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); + store(con, 4, src, base, 4, normalized, 1, preserveIndex); + } break; + + default: abort(con); + } + } else { // FPR store + lir::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + // FPR stores have only bases, so we must add the index + addR(con, vm::TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (size == 8) emit(con, fstd(fpr64(src), absAddr.low)); + // single-precision + else emit(con, fsts(fpr32(src), absAddr.low)); + freeTemp(con, absAddr); + } + + if (release) con->client->releaseTemporary(normalized); + } else if (size == 8 + or abs(offset) == (abs(offset) & 0xFF) + or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) + { + if (!isFpr(src)) { // GPR store + switch (size) { + case 1: + emit(con, strbi(src->low, base, offset)); + break; + + case 2: + emit(con, strhi(src->low, base, offset)); + break; + + case 4: + emit(con, stri(src->low, base, offset)); + break; + + case 8: { // split into 2 32-bit stores + lir::Register srcHigh(src->high); + store(con, 4, &srcHigh, base, offset, lir::NoRegister, 1, false); + store(con, 4, src, base, offset + 4, lir::NoRegister, 1, false); + } break; + + default: abort(con); + } + } else { // FPR store + // double-precision + if (size == 8) emit(con, fstd(fpr64(src), base, offset)); + // single-precision + else emit(con, fsts(fpr32(src), base, offset)); + } + } else { + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + moveCR(con, vm::TargetBytesPerWord, &offsetConstant, + vm::TargetBytesPerWord, &tmp); + + store(con, size, src, base, 0, tmp.low, 1, false); + + con->client->releaseTemporary(tmp.low); + } +} + +void moveRM(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst) +{ + assert(con, srcSize == dstSize); + + store(con, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); +} + +void load(Context* con, unsigned srcSize, int base, int offset, int index, + unsigned scale, unsigned dstSize, lir::Register* dst, + bool preserveIndex, bool signExtend) +{ + if (index != lir::NoRegister) { + bool release; + int normalized = normalize + (con, offset, index, scale, &preserveIndex, &release); + + if (!isFpr(dst)) { // GPR load + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsb(dst->low, base, normalized)); + } else { + emit(con, ldrb(dst->low, base, normalized)); + } + break; + + case 2: + if (signExtend) { + emit(con, ldrsh(dst->low, base, normalized)); + } else { + emit(con, ldrh(dst->low, base, normalized)); + } + break; + + case 4: + case 8: { + if (srcSize == 4 and dstSize == 8) { + load(con, 4, base, 0, normalized, 1, 4, dst, preserveIndex, + false); + moveRR(con, 4, dst, 8, dst); + } else if (srcSize == 8 and dstSize == 8) { + lir::Register dstHigh(dst->high); + load(con, 4, base, 0, normalized, 1, 4, &dstHigh, + preserveIndex, false); + load(con, 4, base, 4, normalized, 1, 4, dst, preserveIndex, + false); + } else { + emit(con, ldr(dst->low, base, normalized)); + } + } break; + + default: abort(con); + } + } else { // FPR load + lir::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + // VFP loads only have bases, so we must add the index + addR(con, vm::TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (srcSize == 8) emit(con, fldd(fpr64(dst), absAddr.low)); + // single-precision + else emit(con, flds(fpr32(dst), absAddr.low)); + freeTemp(con, absAddr); + } + + if (release) con->client->releaseTemporary(normalized); + } else if ((srcSize == 8 and dstSize == 8) + or abs(offset) == (abs(offset) & 0xFF) + or (srcSize != 2 + and (srcSize != 1 or not signExtend) + and abs(offset) == (abs(offset) & 0xFFF))) + { + if (!isFpr(dst)) { // GPR load + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsbi(dst->low, base, offset)); + } else { + emit(con, ldrbi(dst->low, base, offset)); + } + break; + + case 2: + if (signExtend) { + emit(con, ldrshi(dst->low, base, offset)); + } else { + emit(con, ldrhi(dst->low, base, offset)); + } + break; + + case 4: + emit(con, ldri(dst->low, base, offset)); + break; + + case 8: { + if (dstSize == 8) { + lir::Register dstHigh(dst->high); + load(con, 4, base, offset, lir::NoRegister, 1, 4, &dstHigh, false, + false); + load(con, 4, base, offset + 4, lir::NoRegister, 1, 4, dst, false, + false); + } else { + emit(con, ldri(dst->low, base, offset)); + } + } break; + + default: abort(con); + } + } else { // FPR load + // double-precision + if (srcSize == 8) emit(con, fldd(fpr64(dst), base, offset)); + // single-precision + else emit(con, flds(fpr32(dst), base, offset)); + } + } else { + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + moveCR(con, vm::TargetBytesPerWord, &offsetConstant, vm::TargetBytesPerWord, + &tmp); + + load(con, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, + signExtend); + + con->client->releaseTemporary(tmp.low); + } +} + +void moveMR(Context* con, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) +{ + load(con, srcSize, src->base, src->offset, src->index, src->scale, + dstSize, dst, true, true); +} + +void moveZMR(Context* con, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) +{ + load(con, srcSize, src->base, src->offset, src->index, src->scale, + dstSize, dst, true, false); +} + +void andR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) +{ + if (size == 8) emit(con, and_(dst->high, a->high, b->high)); + emit(con, and_(dst->low, a->low, b->low)); +} + +void andC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) +{ + int64_t v = a->value->value(); + + if (size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + lir::Register dh(dst->high); + + andC(con, 4, &al, b, dst); + andC(con, 4, &ah, &bh, &dh); + } else { + uint32_t v32 = static_cast(v); + if (v32 != 0xFFFFFFFF) { + if ((v32 & 0xFFFFFF00) == 0xFFFFFF00) { + emit(con, bici(dst->low, b->low, (~(v32 & 0xFF)) & 0xFF)); + } else if ((v32 & 0xFFFFFF00) == 0) { + emit(con, andi(dst->low, b->low, v32 & 0xFF)); + } else { + // todo: there are other cases we can handle in one + // instruction + + bool useTemporary = b->low == dst->low; + lir::Register tmp(dst->low); + if (useTemporary) { + tmp.low = con->client->acquireTemporary(GPR_MASK); + } + + moveCR(con, 4, a, 4, &tmp); + andR(con, 4, b, &tmp, dst); + + if (useTemporary) { + con->client->releaseTemporary(tmp.low); + } + } + } else { + moveRR(con, size, b, size, dst); + } + } +} + +void orR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) +{ + if (size == 8) emit(con, orr(dst->high, a->high, b->high)); + emit(con, orr(dst->low, a->low, b->low)); +} + +void xorR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) +{ + if (size == 8) emit(con, eor(dst->high, a->high, b->high)); + emit(con, eor(dst->low, a->low, b->low)); +} + +void moveAR2(Context* con, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst) +{ + assert(con, srcSize == 4 and dstSize == 4); + + lir::Constant constant(src->address); + moveCR(con, srcSize, &constant, dstSize, dst); + + lir::Memory memory(dst->low, 0, -1, 0); + moveMR(con, dstSize, &memory, dstSize, dst); +} + +void moveAR(Context* con, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst) +{ + moveAR2(con, srcSize, src, dstSize, dst); +} + +void compareRR(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type + + if (!isFpr(a)) { // GPR compare + assert(con, aSize == 4 && bSize == 4); + /**///assert(con, b->low != a->low); + emit(con, cmp(b->low, a->low)); + } else { // FPR compare + assert(con, aSize == bSize); + if (aSize == 8) emit(con, fcmpd(fpr64(b), fpr64(a))); // double + else emit(con, fcmps(fpr32(b), fpr32(a))); // single + emit(con, fmstat()); + } +} + +void compareCR(Context* con, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) +{ + assert(con, aSize == 4 and bSize == 4); + + if (!isFpr(b) && a->value->resolved() && + isOfWidth(a->value->value(), 8)) { + emit(con, cmpi(b->low, a->value->value())); + } else { + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, aSize, a, bSize, &tmp); + compareRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); + } +} + +void compareCM(Context* con, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b) +{ + assert(con, aSize == 4 and bSize == 4); + + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareCR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); +} + +void compareRM(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Memory* b) +{ + assert(con, aSize == 4 and bSize == 4); + + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareRR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); +} + +int32_t +branch(Context* con, lir::TernaryOperation op) +{ + switch (op) { + case lir::JumpIfEqual: + case lir::JumpIfFloatEqual: + return beq(0); + + case lir::JumpIfNotEqual: + case lir::JumpIfFloatNotEqual: + return bne(0); + + case lir::JumpIfLess: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatLessOrUnordered: + return blt(0); + + case lir::JumpIfGreater: + case lir::JumpIfFloatGreater: + return bgt(0); + + case lir::JumpIfLessOrEqual: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqualOrUnordered: + return ble(0); + + case lir::JumpIfGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + return bge(0); + + case lir::JumpIfFloatGreaterOrUnordered: + return bhi(0); + + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return bpl(0); + + default: + abort(con); + } +} + +void conditional(Context* con, int32_t branch, lir::Constant* target) +{ + appendOffsetTask(con, target->value, offsetPromise(con)); + emit(con, branch); +} + +void branch(Context* con, lir::TernaryOperation op, lir::Constant* target) +{ + conditional(con, branch(con, op), target); +} + +void branchLong(Context* con, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, + BinaryOperationType compareSigned, + BinaryOperationType compareUnsigned) +{ + compareSigned(con, 4, ah, 4, bh); + + unsigned next = 0; + + switch (op) { + case lir::JumpIfEqual: + case lir::JumpIfFloatEqual: + next = con->code.length(); + emit(con, bne(0)); + + compareSigned(con, 4, al, 4, bl); + conditional(con, beq(0), target); + break; + + case lir::JumpIfNotEqual: + case lir::JumpIfFloatNotEqual: + conditional(con, bne(0), target); + + compareSigned(con, 4, al, 4, bl); + conditional(con, bne(0), target); + break; + + case lir::JumpIfLess: + case lir::JumpIfFloatLess: + conditional(con, blt(0), target); + + next = con->code.length(); + emit(con, bgt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, blo(0), target); + break; + + case lir::JumpIfGreater: + case lir::JumpIfFloatGreater: + conditional(con, bgt(0), target); + + next = con->code.length(); + emit(con, blt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhi(0), target); + break; + + case lir::JumpIfLessOrEqual: + case lir::JumpIfFloatLessOrEqual: + conditional(con, blt(0), target); + + next = con->code.length(); + emit(con, bgt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bls(0), target); + break; + + case lir::JumpIfGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + conditional(con, bgt(0), target); + + next = con->code.length(); + emit(con, blt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhs(0), target); + break; + + default: + abort(con); + } + + if (next) { + updateOffset + (con->s, con->code.data + next, reinterpret_cast + (con->code.data + con->code.length())); + } +} + +void branchRR(Context* con, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target) +{ + if (!isFpr(a) && size > vm::TargetBytesPerWord) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + branchLong(con, op, a, &ah, b, &bh, target, CAST2(compareRR), + CAST2(compareRR)); + } else { + compareRR(con, size, a, size, b); + branch(con, op, target); + } +} + +void branchCR(Context* con, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target) +{ + assert(con, !isFloatBranch(op)); + + if (size > vm::TargetBytesPerWord) { + int64_t v = a->value->value(); + + ResolvedPromise low(v & ~static_cast(0)); + lir::Constant al(&low); + + ResolvedPromise high((v >> 32) & ~static_cast(0)); + lir::Constant ah(&high); + + lir::Register bh(b->high); + + branchLong(con, op, &al, &ah, b, &bh, target, CAST2(compareCR), + CAST2(compareCR)); + } else { + compareCR(con, size, a, size, b); + branch(con, op, target); + } +} + +void branchRM(Context* con, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target) +{ + assert(con, !isFloatBranch(op)); + assert(con, size <= vm::TargetBytesPerWord); + + compareRM(con, size, a, size, b); + branch(con, op, target); +} + +void branchCM(Context* con, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target) +{ + assert(con, !isFloatBranch(op)); + assert(con, size <= vm::TargetBytesPerWord); + + compareCM(con, size, a, size, b); + branch(con, op, target); +} + +ShiftMaskPromise* +shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask) +{ + return new(con->zone) ShiftMaskPromise(base, shift, mask); +} + +void moveCM(Context* con, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Memory* dst) +{ + switch (dstSize) { + case 8: { + lir::Constant srcHigh + (shiftMaskPromise(con, src->value, 32, 0xFFFFFFFF)); + lir::Constant srcLow + (shiftMaskPromise(con, src->value, 0, 0xFFFFFFFF)); + + lir::Memory dstLow + (dst->base, dst->offset + 4, dst->index, dst->scale); + + moveCM(con, 4, &srcLow, 4, &dstLow); + moveCM(con, 4, &srcHigh, 4, dst); + } break; + + default: + lir::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, srcSize, src, dstSize, &tmp); + moveRM(con, dstSize, &tmp, dstSize, dst); + con->client->releaseTemporary(tmp.low); + } +} + +void negateRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Register* dst) +{ + assert(con, srcSize == dstSize); + + emit(con, mvn(dst->low, src->low)); + emit(con, SETS(addi(dst->low, dst->low, 1))); + if (srcSize == 8) { + emit(con, mvn(dst->high, src->high)); + emit(con, adci(dst->high, dst->high, 0)); + } +} + +void callR(Context* con, unsigned size UNUSED, lir::Register* target) +{ + assert(con, size == vm::TargetBytesPerWord); + emit(con, blx(target->low)); +} + +void callC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assert(con, size == vm::TargetBytesPerWord); + + appendOffsetTask(con, target->value, offsetPromise(con)); + emit(con, bl(0)); +} + +void longCallC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assert(con, size == vm::TargetBytesPerWord); + + lir::Register tmp(4); + moveCR2(con, vm::TargetBytesPerWord, target, &tmp, offsetPromise(con)); + callR(con, vm::TargetBytesPerWord, &tmp); +} + +void longJumpC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assert(con, size == vm::TargetBytesPerWord); + + lir::Register tmp(4); // a non-arg reg that we don't mind clobbering + moveCR2(con, vm::TargetBytesPerWord, target, &tmp, offsetPromise(con)); + jumpR(con, vm::TargetBytesPerWord, &tmp); +} + +void jumpC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assert(con, size == vm::TargetBytesPerWord); + + appendOffsetTask(con, target->value, offsetPromise(con)); + emit(con, b(0)); +} + +void return_(Context* con) +{ + emit(con, bx(LinkRegister)); +} + +void trap(Context* con) +{ + emit(con, bkpt(0)); +} + +void memoryBarrier(Context*) {} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/src/codegen/arm/operations.h b/src/codegen/arm/operations.h new file mode 100644 index 0000000000..2d598b6d9e --- /dev/null +++ b/src/codegen/arm/operations.h @@ -0,0 +1,240 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H + +#include "registers.h" + +namespace vm { +class System; +} + +namespace avian { +namespace codegen { +namespace arm { + +class Context; + +// shortcut functions + +inline int newTemp(Context* con) { + return con->client->acquireTemporary(GPR_MASK); +} + +inline int newTemp(Context* con, unsigned mask) { + return con->client->acquireTemporary(mask); +} + +inline void freeTemp(Context* con, int r) { + con->client->releaseTemporary(r); +} + +inline int64_t getValue(lir::Constant* con) { + return con->value->value(); +} + +inline lir::Register makeTemp(Context* con) { + lir::Register tmp(newTemp(con)); + return tmp; +} + +inline lir::Register makeTemp64(Context* con) { + lir::Register tmp(newTemp(con), newTemp(con)); + return tmp; +} + +inline void freeTemp(Context* con, const lir::Register& tmp) { + if (tmp.low != lir::NoRegister) freeTemp(con, tmp.low); + if (tmp.high != lir::NoRegister) freeTemp(con, tmp.high); +} + +void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void moveRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); + +void shiftLeftC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t); + +void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void shiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t); + +void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void unsignedShiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t); + +bool needJump(MyBlock* b); + +unsigned padding(MyBlock* b, unsigned offset); + +void resolve(MyBlock* b); + +void jumpR(Context* con, unsigned size UNUSED, lir::Register* target); + +void swapRR(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); + +void moveRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); + +void moveZRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned, lir::Register* dst); + +void moveCR(Context* con, unsigned size, lir::Constant* src, + unsigned, lir::Register* dst); + +void moveCR2(Context* con, unsigned size, lir::Constant* src, + lir::Register* dst, Promise* callOffset); + +void moveCR(Context* con, unsigned size, lir::Constant* src, + unsigned, lir::Register* dst); + +void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void addC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void subC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void floatAbsoluteRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b); + +void floatNegateRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b); + +void float2FloatRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b); + +void float2IntRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b); + +void int2FloatRR(Context* con, unsigned, lir::Register* a, unsigned size, lir::Register* b); + +void floatSqrtRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b); + +void floatAddR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void floatSubtractR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void floatMultiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void floatDivideR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +int normalize(Context* con, int offset, int index, unsigned scale, + bool* preserveIndex, bool* release); + +void store(Context* con, unsigned size, lir::Register* src, + int base, int offset, int index, unsigned scale, bool preserveIndex); + +void moveRM(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst); + +void load(Context* con, unsigned srcSize, int base, int offset, int index, + unsigned scale, unsigned dstSize, lir::Register* dst, + bool preserveIndex, bool signExtend); + +void moveMR(Context* con, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst); + +void moveZMR(Context* con, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst); + +void andR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst); + +void andC(Context* con, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void orR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst); + +void xorR(Context* con, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst); + +void moveAR2(Context* con, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst); + +void moveAR(Context* con, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst); + +void compareRR(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void compareCR(Context* con, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void compareCM(Context* con, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b); + +void compareRM(Context* con, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Memory* b); + +int32_t +branch(Context* con, lir::TernaryOperation op); + +void conditional(Context* con, int32_t branch, lir::Constant* target); + +void branch(Context* con, lir::TernaryOperation op, lir::Constant* target); + +void branchLong(Context* con, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, + BinaryOperationType compareSigned, + BinaryOperationType compareUnsigned); + +void branchRR(Context* con, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target); + +void branchCR(Context* con, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target); + +void branchRM(Context* con, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target); + +void branchCM(Context* con, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target); + +ShiftMaskPromise* +shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask); + +void moveCM(Context* con, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Memory* dst); + +void negateRR(Context* con, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Register* dst); + +void callR(Context* con, unsigned size UNUSED, lir::Register* target); + +void callC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void longCallC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void longJumpC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void jumpC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void return_(Context* con); + +void trap(Context* con); + +void memoryBarrier(Context*); + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H + diff --git a/src/codegen/arm/registers.h b/src/codegen/arm/registers.h new file mode 100644 index 0000000000..85c389b222 --- /dev/null +++ b/src/codegen/arm/registers.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H + +#include +#include + +namespace avian { +namespace codegen { +namespace arm { + + +const uint64_t MASK_LO32 = 0xffffffff; +const unsigned MASK_LO16 = 0xffff; +const unsigned MASK_LO8 = 0xff; + +const int N_GPRS = 16; +const int N_FPRS = 16; +const uint32_t GPR_MASK = 0xffff; +const uint32_t FPR_MASK = 0xffff0000; + +const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32; +const uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32; + +inline bool isFpr(lir::Register* reg) { + return reg->low >= N_GPRS; +} + +inline int fpr64(int reg) { return reg - N_GPRS; } +inline int fpr64(lir::Register* reg) { return fpr64(reg->low); } +inline int fpr32(int reg) { return fpr64(reg) << 1; } +inline int fpr32(lir::Register* reg) { return fpr64(reg) << 1; } + +const int ThreadRegister = 8; +const int StackRegister = 13; +const int LinkRegister = 14; +const int ProgramCounter = 15; + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H diff --git a/src/common.h b/src/common.h index a99d246f67..02e52aeae1 100644 --- a/src/common.h +++ b/src/common.h @@ -477,6 +477,12 @@ hash(const uint16_t* s, unsigned length) return h; } +inline void +write4(uint8_t* dst, uint32_t v) +{ + memcpy(dst, &v, 4); +} + inline uint32_t floatToBits(float f) { From 73dda9c26e593eea9b314ec0eb4ff554fdcb08d5 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 22 Feb 2013 23:15:40 -0700 Subject: [PATCH 291/378] begin splitting out powerpc assembler --- src/codegen/powerpc/assembler.cpp | 265 +++--------------------------- src/codegen/powerpc/block.cpp | 42 +++++ src/codegen/powerpc/block.h | 44 +++++ src/codegen/powerpc/context.cpp | 29 ++++ src/codegen/powerpc/context.h | 95 +++++++++++ src/codegen/powerpc/encode.h | 137 +++++++++++++++ src/codegen/powerpc/fixup.h | 32 ++++ 7 files changed, 403 insertions(+), 241 deletions(-) create mode 100644 src/codegen/powerpc/block.cpp create mode 100644 src/codegen/powerpc/block.h create mode 100644 src/codegen/powerpc/context.cpp create mode 100644 src/codegen/powerpc/context.h create mode 100644 src/codegen/powerpc/encode.h create mode 100644 src/codegen/powerpc/fixup.h diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index e470ad61b5..b1ad5f03ba 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -14,129 +14,22 @@ #include "alloc-vector.h" #include +#include "encode.h" +#include "context.h" +#include "fixup.h" +#include "block.h" + #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) #define CAST3(x) reinterpret_cast(x) #define CAST_BRANCH(x) reinterpret_cast(x) using namespace vm; -using namespace avian::codegen; using namespace avian::util; -namespace { - -namespace isa { -// INSTRUCTION FORMATS -inline int D(int op, int rt, int ra, int d) { return op<<26|rt<<21|ra<<16|(d & 0xFFFF); } -// inline int DS(int op, int rt, int ra, int ds, int xo) { return op<<26|rt<<21|ra<<16|ds<<2|xo; } -inline int I(int op, int li, int aa, int lk) { return op<<26|(li & 0x3FFFFFC)|aa<<1|lk; } -inline int B(int op, int bo, int bi, int bd, int aa, int lk) { return op<<26|bo<<21|bi<<16|(bd & 0xFFFC)|aa<<1|lk; } -// inline int SC(int op, int lev) { return op<<26|lev<<5|2; } -inline int X(int op, int rt, int ra, int rb, int xo, int rc) { return op<<26|rt<<21|ra<<16|rb<<11|xo<<1|rc; } -inline int XL(int op, int bt, int ba, int bb, int xo, int lk) { return op<<26|bt<<21|ba<<16|bb<<11|xo<<1|lk; } -inline int XFX(int op, int rt, int spr, int xo) { return op<<26|rt<<21|((spr >> 5) | ((spr << 5) & 0x3E0))<<11|xo<<1; } -// inline int XFL(int op, int flm, int frb, int xo, int rc) { return op<<26|flm<<17|frb<<11|xo<<1|rc; } -// inline int XS(int op, int rs, int ra, int sh, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|xo<<2|sh2<<1|rc; } -inline int XO(int op, int rt, int ra, int rb, int oe, int xo, int rc) { return op<<26|rt<<21|ra<<16|rb<<11|oe<<10|xo<<1|rc; } -// inline int A(int op, int frt, int fra, int frb, int frc, int xo, int rc) { return op<<26|frt<<21|fra<<16|frb<<11|frc<<6|xo<<1|rc; } -inline int M(int op, int rs, int ra, int rb, int mb, int me, int rc) { return op<<26|rs<<21|ra<<16|rb<<11|mb<<6|me<<1|rc; } -// inline int MD(int op, int rs, int ra, int sh, int mb, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|mb<<5|xo<<2|sh2<<1|rc; } -// inline int MDS(int op, int rs, int ra, int rb, int mb, int xo, int rc) { return op<<26|rs<<21|ra<<16|rb<<11|mb<<5|xo<<1|rc; } -// INSTRUCTIONS -inline int lbz(int rt, int ra, int i) { return D(34, rt, ra, i); } -inline int lbzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 87, 0); } -inline int lha(int rt, int ra, int i) { return D(42, rt, ra, i); } -inline int lhax(int rt, int ra, int rb) { return X(31, rt, ra, rb, 343, 0); } -// inline int lhz(int rt, int ra, int i) { return D(40, rt, ra, i); } -inline int lhzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 279, 0); } -inline int lwz(int rt, int ra, int i) { return D(32, rt, ra, i); } -inline int lwzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 23, 0); } -inline int stb(int rs, int ra, int i) { return D(38, rs, ra, i); } -inline int stbx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 215, 0); } -inline int sth(int rs, int ra, int i) { return D(44, rs, ra, i); } -inline int sthx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 407, 0); } -inline int stw(int rs, int ra, int i) { return D(36, rs, ra, i); } -inline int stwu(int rs, int ra, int i) { return D(37, rs, ra, i); } -inline int stwux(int rs, int ra, int rb) { return X(31, rs, ra, rb, 183, 0); } -inline int stwx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 151, 0); } -inline int add(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 266, 0); } -inline int addc(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 10, 0); } -inline int adde(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 138, 0); } -inline int addi(int rt, int ra, int i) { return D(14, rt, ra, i); } -inline int addic(int rt, int ra, int i) { return D(12, rt, ra, i); } -inline int addis(int rt, int ra, int i) { return D(15, rt, ra, i); } -inline int subf(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 40, 0); } -inline int subfc(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 8, 0); } -inline int subfe(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 136, 0); } -inline int subfic(int rt, int ra, int i) { return D(8, rt, ra, i); } -inline int subfze(int rt, int ra) { return XO(31, rt, ra, 0, 0, 200, 0); } -inline int mullw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 235, 0); } -// inline int mulhw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 75, 0); } -inline int mulhwu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 11, 0); } -// inline int mulli(int rt, int ra, int i) { return D(7, rt, ra, i); } -inline int divw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 491, 0); } -// inline int divwu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 459, 0); } -// inline int divd(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 489, 0); } -// inline int divdu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 457, 0); } -inline int neg(int rt, int ra) { return XO(31, rt, ra, 0, 0, 104, 0); } -inline int and_(int rt, int ra, int rb) { return X(31, ra, rt, rb, 28, 0); } -inline int andi(int rt, int ra, int i) { return D(28, ra, rt, i); } -inline int andis(int rt, int ra, int i) { return D(29, ra, rt, i); } -inline int or_(int rt, int ra, int rb) { return X(31, ra, rt, rb, 444, 0); } -inline int ori(int rt, int ra, int i) { return D(24, rt, ra, i); } -inline int xor_(int rt, int ra, int rb) { return X(31, ra, rt, rb, 316, 0); } -inline int oris(int rt, int ra, int i) { return D(25, rt, ra, i); } -inline int xori(int rt, int ra, int i) { return D(26, rt, ra, i); } -inline int xoris(int rt, int ra, int i) { return D(27, rt, ra, i); } -inline int rlwinm(int rt, int ra, int i, int mb, int me) { return M(21, ra, rt, i, mb, me, 0); } -inline int rlwimi(int rt, int ra, int i, int mb, int me) { return M(20, ra, rt, i, mb, me, 0); } -inline int slw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 24, 0); } -// inline int sld(int rt, int ra, int rb) { return X(31, ra, rt, rb, 27, 0); } -inline int srw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 536, 0); } -inline int sraw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 792, 0); } -inline int srawi(int rt, int ra, int sh) { return X(31, ra, rt, sh, 824, 0); } -inline int extsb(int rt, int rs) { return X(31, rs, rt, 0, 954, 0); } -inline int extsh(int rt, int rs) { return X(31, rs, rt, 0, 922, 0); } -inline int mfspr(int rt, int spr) { return XFX(31, rt, spr, 339); } -inline int mtspr(int spr, int rs) { return XFX(31, rs, spr, 467); } -inline int b(int i) { return I(18, i, 0, 0); } -inline int bl(int i) { return I(18, i, 0, 1); } -inline int bcctr(int bo, int bi, int lk) { return XL(19, bo, bi, 0, 528, lk); } -inline int bclr(int bo, int bi, int lk) { return XL(19, bo, bi, 0, 16, lk); } -inline int bc(int bo, int bi, int bd, int lk) { return B(16, bo, bi, bd, 0, lk); } -inline int cmp(int bf, int ra, int rb) { return X(31, bf << 2, ra, rb, 0, 0); } -inline int cmpl(int bf, int ra, int rb) { return X(31, bf << 2, ra, rb, 32, 0); } -inline int cmpi(int bf, int ra, int i) { return D(11, bf << 2, ra, i); } -inline int cmpli(int bf, int ra, int i) { return D(10, bf << 2, ra, i); } -inline int sync(int L) { return X(31, L, 0, 0, 598, 0); } -// PSEUDO-INSTRUCTIONS -inline int li(int rt, int i) { return addi(rt, 0, i); } -inline int lis(int rt, int i) { return addis(rt, 0, i); } -inline int slwi(int rt, int ra, int i) { return rlwinm(rt, ra, i, 0, 31-i); } -inline int srwi(int rt, int ra, int i) { return rlwinm(rt, ra, 32-i, i, 31); } -// inline int sub(int rt, int ra, int rb) { return subf(rt, rb, ra); } -// inline int subc(int rt, int ra, int rb) { return subfc(rt, rb, ra); } -// inline int subi(int rt, int ra, int i) { return addi(rt, ra, -i); } -// inline int subis(int rt, int ra, int i) { return addis(rt, ra, -i); } -inline int mr(int rt, int ra) { return or_(rt, ra, ra); } -inline int mflr(int rx) { return mfspr(rx, 8); } -inline int mtlr(int rx) { return mtspr(8, rx); } -inline int mtctr(int rd) { return mtspr(9, rd); } -inline int bctr() { return bcctr(20, 0, 0); } -inline int bctrl() { return bcctr(20, 0, 1); } -inline int blr() { return bclr(20, 0, 0); } -inline int blt(int i) { return bc(12, 0, i, 0); } -inline int bgt(int i) { return bc(12, 1, i, 0); } -inline int bge(int i) { return bc(4, 0, i, 0); } -inline int ble(int i) { return bc(4, 1, i, 0); } -inline int beq(int i) { return bc(12, 2, i, 0); } -inline int bne(int i) { return bc(4, 2, i, 0); } -inline int cmpw(int ra, int rb) { return cmp(0, ra, rb); } -inline int cmplw(int ra, int rb) { return cmpl(0, ra, rb); } -inline int cmpwi(int ra, int i) { return cmpi(0, ra, i); } -inline int cmplwi(int ra, int i) { return cmpli(0, ra, i); } -inline int trap() { return 0x7fe00008; } // todo: macro-ify -} +namespace avian { +namespace codegen { +namespace powerpc { const int64_t MASK_LO32 = 0x0ffffffff; const int MASK_LO16 = 0x0ffff; @@ -189,10 +82,7 @@ const int ThreadRegister = 13; const bool DebugJumps = false; -class Context; -class MyBlock; class JumpOffset; -class JumpEvent; void resolve(MyBlock*); @@ -200,116 +90,12 @@ resolve(MyBlock*); unsigned padding(MyBlock*, unsigned); -class MyBlock: public Assembler::Block { - public: - MyBlock(Context* context, unsigned offset): - context(context), next(0), jumpOffsetHead(0), jumpOffsetTail(0), - lastJumpOffsetTail(0), jumpEventHead(0), jumpEventTail(0), - lastEventOffset(0), offset(offset), start(~0), size(0), resolved(false) - { } - - virtual unsigned resolve(unsigned start, Assembler::Block* next) { - this->start = start; - this->next = static_cast(next); - - ::resolve(this); - - this->resolved = true; - - return start + size + padding(this, size); - } - - Context* context; - MyBlock* next; - JumpOffset* jumpOffsetHead; - JumpOffset* jumpOffsetTail; - JumpOffset* lastJumpOffsetTail; - JumpEvent* jumpEventHead; - JumpEvent* jumpEventTail; - unsigned lastEventOffset; - unsigned offset; - unsigned start; - unsigned size; - bool resolved; -}; - class Task; class ConstantPoolEntry; -class Context { +class OffsetPromise: public Promise { public: - Context(System* s, Allocator* a, Zone* zone): - s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new(zone) MyBlock(this, 0)), - lastBlock(firstBlock), jumpOffsetHead(0), jumpOffsetTail(0), - constantPool(0), constantPoolCount(0) - { } - - System* s; - Zone* zone; - Assembler::Client* client; - Vector code; - Task* tasks; - uint8_t* result; - MyBlock* firstBlock; - MyBlock* lastBlock; - JumpOffset* jumpOffsetHead; - JumpOffset* jumpOffsetTail; - ConstantPoolEntry* constantPool; - unsigned constantPoolCount; -}; - -class Task { - public: - Task(Task* next): next(next) { } - - virtual void run(Context* c) = 0; - - Task* next; -}; - -typedef void (*OperationType)(Context*); - -typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); - -typedef void (*BinaryOperationType) -(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); - -typedef void (*TernaryOperationType) -(Context*, unsigned, lir::Operand*, lir::Operand*, - lir::Operand*); - -typedef void (*BranchOperationType) -(Context*, lir::TernaryOperation, unsigned, lir::Operand*, - lir::Operand*, lir::Operand*); - -class ArchitectureContext { - public: - ArchitectureContext(System* s): s(s) { } - - System* s; - OperationType operations[lir::OperationCount]; - UnaryOperationType unaryOperations[lir::UnaryOperationCount - * lir::OperandTypeCount]; - BinaryOperationType binaryOperations - [lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; - TernaryOperationType ternaryOperations - [lir::NonBranchTernaryOperationCount * lir::OperandTypeCount]; - BranchOperationType branchOperations - [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; -}; - -inline Aborter* getAborter(Context* con) { - return con->s; -} - -inline Aborter* getAborter(ArchitectureContext* con) { - return con->s; -} - -class Offset: public Promise { - public: - Offset(Context* c, MyBlock* block, unsigned offset): + OffsetPromise(Context* c, MyBlock* block, unsigned offset): c(c), block(block), offset(offset) { } @@ -330,9 +116,9 @@ class Offset: public Promise { }; Promise* -offset(Context* c) +offsetPromise(Context* c) { - return new(c->zone) Offset(c, c->lastBlock, c->code.length()); + return new(c->zone) OffsetPromise(c, c->lastBlock, c->code.length()); } bool @@ -978,7 +764,7 @@ moveCR2(Context* c, unsigned, lir::Constant* src, } } else { appendImmediateTask - (c, src->value, offset(c), TargetBytesPerWord, promiseOffset, false); + (c, src->value, offsetPromise(c), TargetBytesPerWord, promiseOffset, false); emit(c, lis(dst->low, 0)); emit(c, ori(dst->low, dst->low, 0)); } @@ -1505,7 +1291,7 @@ moveAR2(Context* c, unsigned srcSize UNUSED, lir::Address* src, lir::Memory memory(dst->low, 0, -1, 0); appendImmediateTask - (c, src->address, offset(c), TargetBytesPerWord, promiseOffset, true); + (c, src->address, offsetPromise(c), TargetBytesPerWord, promiseOffset, true); emit(c, lis(dst->low, 0)); moveMR(c, dstSize, &memory, dstSize, dst); @@ -1622,7 +1408,7 @@ branch(Context* c, lir::TernaryOperation op) void conditional(Context* c, int32_t branch, lir::Constant* target) { - appendOffsetTask(c, target->value, offset(c), true); + appendOffsetTask(c, target->value, offsetPromise(c), true); emit(c, branch); } @@ -1835,7 +1621,7 @@ callC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); - appendOffsetTask(c, target->value, offset(c), false); + appendOffsetTask(c, target->value, offsetPromise(c), false); emit(c, bl(0)); } @@ -1888,7 +1674,7 @@ jumpC(Context* c, unsigned size UNUSED, lir::Constant* target) { assert(c, size == TargetBytesPerWord); - appendOffsetTask(c, target->value, offset(c), false); + appendOffsetTask(c, target->value, offsetPromise(c), false); emit(c, b(0)); } @@ -1901,7 +1687,7 @@ return_(Context* c) void trap(Context* c) { - emit(c, trap()); + emit(c, isa::trap()); } void @@ -2127,7 +1913,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentFootprint(unsigned footprint) { - return ::argumentFootprint(footprint); + return powerpc::argumentFootprint(footprint); } virtual bool argumentAlignment() { @@ -2213,7 +1999,7 @@ class MyArchitecture: public Assembler::Architecture { unsigned targetParameterFootprint, void** ip, void** stack) { - ::nextFrame(&c, static_cast(start), size, footprint, link, + powerpc::nextFrame(&c, static_cast(start), size, footprint, link, mostRecent, targetParameterFootprint, ip, stack); } @@ -2714,7 +2500,7 @@ class MyAssembler: public Assembler { bool jump = needJump(b); if (jump) { - write4(dst + dstOffset, ::b(jumpTableSize + TargetBytesPerWord)); + write4(dst + dstOffset, isa::b(jumpTableSize + TargetBytesPerWord)); } dstOffset += jumpTableSize + (jump ? TargetBytesPerWord : 0); @@ -2747,7 +2533,7 @@ class MyAssembler: public Assembler { } virtual Promise* offset(bool) { - return ::offset(&c); + return powerpc::offsetPromise(&c); } virtual Block* endBlock(bool startNew) { @@ -2815,15 +2601,12 @@ Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { return new(zone) MyAssembler(this->c.s, allocator, zone, this); } -} // namespace - -namespace avian { -namespace codegen { +} // namespace powerpc Assembler::Architecture* makeArchitecturePowerpc(System* system, bool) { - return new (allocate(system, sizeof(MyArchitecture))) MyArchitecture(system); + return new (allocate(system, sizeof(powerpc::MyArchitecture))) powerpc::MyArchitecture(system); } } // namespace codegen diff --git a/src/codegen/powerpc/block.cpp b/src/codegen/powerpc/block.cpp new file mode 100644 index 0000000000..14453c3bde --- /dev/null +++ b/src/codegen/powerpc/block.cpp @@ -0,0 +1,42 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "block.h" +#include "common.h" + +namespace avian { +namespace codegen { +namespace powerpc { + +void resolve(MyBlock*); + +unsigned padding(MyBlock*, unsigned); + +MyBlock::MyBlock(Context* context, unsigned offset): + context(context), next(0), jumpOffsetHead(0), jumpOffsetTail(0), + lastJumpOffsetTail(0), jumpEventHead(0), jumpEventTail(0), + lastEventOffset(0), offset(offset), start(~0), size(0), resolved(false) +{ } + +unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) { + this->start = start; + this->next = static_cast(next); + + powerpc::resolve(this); + + this->resolved = true; + + return start + size + padding(this, size); +} + +} // namespace powerpc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/powerpc/block.h b/src/codegen/powerpc/block.h new file mode 100644 index 0000000000..e0dd563ad7 --- /dev/null +++ b/src/codegen/powerpc/block.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_BLOCK_H +#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_BLOCK_H + +namespace avian { +namespace codegen { +namespace powerpc { + +class JumpEvent; + +class MyBlock: public Assembler::Block { + public: + MyBlock(Context* context, unsigned offset); + + virtual unsigned resolve(unsigned start, Assembler::Block* next); + + Context* context; + MyBlock* next; + JumpOffset* jumpOffsetHead; + JumpOffset* jumpOffsetTail; + JumpOffset* lastJumpOffsetTail; + JumpEvent* jumpEventHead; + JumpEvent* jumpEventTail; + unsigned lastEventOffset; + unsigned offset; + unsigned start; + unsigned size; + bool resolved; +}; + +} // namespace powerpc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_BLOCK_H diff --git a/src/codegen/powerpc/context.cpp b/src/codegen/powerpc/context.cpp new file mode 100644 index 0000000000..c61b55ef55 --- /dev/null +++ b/src/codegen/powerpc/context.cpp @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "block.h" +#include "common.h" + +namespace avian { +namespace codegen { +namespace powerpc { + + +Context::Context(vm::System* s, vm::Allocator* a, vm::Zone* zone): + s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), + firstBlock(new(zone) MyBlock(this, 0)), + lastBlock(firstBlock), jumpOffsetHead(0), jumpOffsetTail(0), + constantPool(0), constantPoolCount(0) +{ } + +} // namespace powerpc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/powerpc/context.h b/src/codegen/powerpc/context.h new file mode 100644 index 0000000000..f458c74330 --- /dev/null +++ b/src/codegen/powerpc/context.h @@ -0,0 +1,95 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_CONTEXT_H +#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_CONTEXT_H + +#include +#include "alloc-vector.h" + + +namespace vm { +class System; +class Allocator; +class Zone; +} // namespace vm + + +namespace avian { +namespace codegen { +namespace powerpc { + +class Task; +class JumpOffset; +class ConstantPoolEntry; +class MyBlock; + +class Context { + public: + Context(vm::System* s, vm::Allocator* a, vm::Zone* zone); + + vm::System* s; + vm::Zone* zone; + Assembler::Client* client; + vm::Vector code; + Task* tasks; + uint8_t* result; + MyBlock* firstBlock; + MyBlock* lastBlock; + JumpOffset* jumpOffsetHead; + JumpOffset* jumpOffsetTail; + ConstantPoolEntry* constantPool; + unsigned constantPoolCount; +}; + +typedef void (*OperationType)(Context*); + +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); + +typedef void (*BinaryOperationType) +(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); + +typedef void (*TernaryOperationType) +(Context*, unsigned, lir::Operand*, lir::Operand*, + lir::Operand*); + +typedef void (*BranchOperationType) +(Context*, lir::TernaryOperation, unsigned, lir::Operand*, + lir::Operand*, lir::Operand*); + +class ArchitectureContext { + public: + ArchitectureContext(vm::System* s): s(s) { } + + vm::System* s; + OperationType operations[lir::OperationCount]; + UnaryOperationType unaryOperations[lir::UnaryOperationCount + * lir::OperandTypeCount]; + BinaryOperationType binaryOperations + [lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; + TernaryOperationType ternaryOperations + [lir::NonBranchTernaryOperationCount * lir::OperandTypeCount]; + BranchOperationType branchOperations + [lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; +}; + +inline avian::util::Aborter* getAborter(Context* con) { + return con->s; +} + +inline avian::util::Aborter* getAborter(ArchitectureContext* con) { + return con->s; +} + +} // namespace powerpc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_CONTEXT_H diff --git a/src/codegen/powerpc/encode.h b/src/codegen/powerpc/encode.h new file mode 100644 index 0000000000..54f7f7f493 --- /dev/null +++ b/src/codegen/powerpc/encode.h @@ -0,0 +1,137 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_ENCODE_H +#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_ENCODE_H + +namespace avian { +namespace codegen { +namespace powerpc { + +namespace isa { +// INSTRUCTION FORMATS +inline int D(int op, int rt, int ra, int d) { return op<<26|rt<<21|ra<<16|(d & 0xFFFF); } +// inline int DS(int op, int rt, int ra, int ds, int xo) { return op<<26|rt<<21|ra<<16|ds<<2|xo; } +inline int I(int op, int li, int aa, int lk) { return op<<26|(li & 0x3FFFFFC)|aa<<1|lk; } +inline int B(int op, int bo, int bi, int bd, int aa, int lk) { return op<<26|bo<<21|bi<<16|(bd & 0xFFFC)|aa<<1|lk; } +// inline int SC(int op, int lev) { return op<<26|lev<<5|2; } +inline int X(int op, int rt, int ra, int rb, int xo, int rc) { return op<<26|rt<<21|ra<<16|rb<<11|xo<<1|rc; } +inline int XL(int op, int bt, int ba, int bb, int xo, int lk) { return op<<26|bt<<21|ba<<16|bb<<11|xo<<1|lk; } +inline int XFX(int op, int rt, int spr, int xo) { return op<<26|rt<<21|((spr >> 5) | ((spr << 5) & 0x3E0))<<11|xo<<1; } +// inline int XFL(int op, int flm, int frb, int xo, int rc) { return op<<26|flm<<17|frb<<11|xo<<1|rc; } +// inline int XS(int op, int rs, int ra, int sh, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|xo<<2|sh2<<1|rc; } +inline int XO(int op, int rt, int ra, int rb, int oe, int xo, int rc) { return op<<26|rt<<21|ra<<16|rb<<11|oe<<10|xo<<1|rc; } +// inline int A(int op, int frt, int fra, int frb, int frc, int xo, int rc) { return op<<26|frt<<21|fra<<16|frb<<11|frc<<6|xo<<1|rc; } +inline int M(int op, int rs, int ra, int rb, int mb, int me, int rc) { return op<<26|rs<<21|ra<<16|rb<<11|mb<<6|me<<1|rc; } +// inline int MD(int op, int rs, int ra, int sh, int mb, int xo, int sh2, int rc) { return op<<26|rs<<21|ra<<16|sh<<11|mb<<5|xo<<2|sh2<<1|rc; } +// inline int MDS(int op, int rs, int ra, int rb, int mb, int xo, int rc) { return op<<26|rs<<21|ra<<16|rb<<11|mb<<5|xo<<1|rc; } +// INSTRUCTIONS +inline int lbz(int rt, int ra, int i) { return D(34, rt, ra, i); } +inline int lbzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 87, 0); } +inline int lha(int rt, int ra, int i) { return D(42, rt, ra, i); } +inline int lhax(int rt, int ra, int rb) { return X(31, rt, ra, rb, 343, 0); } +// inline int lhz(int rt, int ra, int i) { return D(40, rt, ra, i); } +inline int lhzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 279, 0); } +inline int lwz(int rt, int ra, int i) { return D(32, rt, ra, i); } +inline int lwzx(int rt, int ra, int rb) { return X(31, rt, ra, rb, 23, 0); } +inline int stb(int rs, int ra, int i) { return D(38, rs, ra, i); } +inline int stbx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 215, 0); } +inline int sth(int rs, int ra, int i) { return D(44, rs, ra, i); } +inline int sthx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 407, 0); } +inline int stw(int rs, int ra, int i) { return D(36, rs, ra, i); } +inline int stwu(int rs, int ra, int i) { return D(37, rs, ra, i); } +inline int stwux(int rs, int ra, int rb) { return X(31, rs, ra, rb, 183, 0); } +inline int stwx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 151, 0); } +inline int add(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 266, 0); } +inline int addc(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 10, 0); } +inline int adde(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 138, 0); } +inline int addi(int rt, int ra, int i) { return D(14, rt, ra, i); } +inline int addic(int rt, int ra, int i) { return D(12, rt, ra, i); } +inline int addis(int rt, int ra, int i) { return D(15, rt, ra, i); } +inline int subf(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 40, 0); } +inline int subfc(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 8, 0); } +inline int subfe(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 136, 0); } +inline int subfic(int rt, int ra, int i) { return D(8, rt, ra, i); } +inline int subfze(int rt, int ra) { return XO(31, rt, ra, 0, 0, 200, 0); } +inline int mullw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 235, 0); } +// inline int mulhw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 75, 0); } +inline int mulhwu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 11, 0); } +// inline int mulli(int rt, int ra, int i) { return D(7, rt, ra, i); } +inline int divw(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 491, 0); } +// inline int divwu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 459, 0); } +// inline int divd(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 489, 0); } +// inline int divdu(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 457, 0); } +inline int neg(int rt, int ra) { return XO(31, rt, ra, 0, 0, 104, 0); } +inline int and_(int rt, int ra, int rb) { return X(31, ra, rt, rb, 28, 0); } +inline int andi(int rt, int ra, int i) { return D(28, ra, rt, i); } +inline int andis(int rt, int ra, int i) { return D(29, ra, rt, i); } +inline int or_(int rt, int ra, int rb) { return X(31, ra, rt, rb, 444, 0); } +inline int ori(int rt, int ra, int i) { return D(24, rt, ra, i); } +inline int xor_(int rt, int ra, int rb) { return X(31, ra, rt, rb, 316, 0); } +inline int oris(int rt, int ra, int i) { return D(25, rt, ra, i); } +inline int xori(int rt, int ra, int i) { return D(26, rt, ra, i); } +inline int xoris(int rt, int ra, int i) { return D(27, rt, ra, i); } +inline int rlwinm(int rt, int ra, int i, int mb, int me) { return M(21, ra, rt, i, mb, me, 0); } +inline int rlwimi(int rt, int ra, int i, int mb, int me) { return M(20, ra, rt, i, mb, me, 0); } +inline int slw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 24, 0); } +// inline int sld(int rt, int ra, int rb) { return X(31, ra, rt, rb, 27, 0); } +inline int srw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 536, 0); } +inline int sraw(int rt, int ra, int sh) { return X(31, ra, rt, sh, 792, 0); } +inline int srawi(int rt, int ra, int sh) { return X(31, ra, rt, sh, 824, 0); } +inline int extsb(int rt, int rs) { return X(31, rs, rt, 0, 954, 0); } +inline int extsh(int rt, int rs) { return X(31, rs, rt, 0, 922, 0); } +inline int mfspr(int rt, int spr) { return XFX(31, rt, spr, 339); } +inline int mtspr(int spr, int rs) { return XFX(31, rs, spr, 467); } +inline int b(int i) { return I(18, i, 0, 0); } +inline int bl(int i) { return I(18, i, 0, 1); } +inline int bcctr(int bo, int bi, int lk) { return XL(19, bo, bi, 0, 528, lk); } +inline int bclr(int bo, int bi, int lk) { return XL(19, bo, bi, 0, 16, lk); } +inline int bc(int bo, int bi, int bd, int lk) { return B(16, bo, bi, bd, 0, lk); } +inline int cmp(int bf, int ra, int rb) { return X(31, bf << 2, ra, rb, 0, 0); } +inline int cmpl(int bf, int ra, int rb) { return X(31, bf << 2, ra, rb, 32, 0); } +inline int cmpi(int bf, int ra, int i) { return D(11, bf << 2, ra, i); } +inline int cmpli(int bf, int ra, int i) { return D(10, bf << 2, ra, i); } +inline int sync(int L) { return X(31, L, 0, 0, 598, 0); } +// PSEUDO-INSTRUCTIONS +inline int li(int rt, int i) { return addi(rt, 0, i); } +inline int lis(int rt, int i) { return addis(rt, 0, i); } +inline int slwi(int rt, int ra, int i) { return rlwinm(rt, ra, i, 0, 31-i); } +inline int srwi(int rt, int ra, int i) { return rlwinm(rt, ra, 32-i, i, 31); } +// inline int sub(int rt, int ra, int rb) { return subf(rt, rb, ra); } +// inline int subc(int rt, int ra, int rb) { return subfc(rt, rb, ra); } +// inline int subi(int rt, int ra, int i) { return addi(rt, ra, -i); } +// inline int subis(int rt, int ra, int i) { return addis(rt, ra, -i); } +inline int mr(int rt, int ra) { return or_(rt, ra, ra); } +inline int mflr(int rx) { return mfspr(rx, 8); } +inline int mtlr(int rx) { return mtspr(8, rx); } +inline int mtctr(int rd) { return mtspr(9, rd); } +inline int bctr() { return bcctr(20, 0, 0); } +inline int bctrl() { return bcctr(20, 0, 1); } +inline int blr() { return bclr(20, 0, 0); } +inline int blt(int i) { return bc(12, 0, i, 0); } +inline int bgt(int i) { return bc(12, 1, i, 0); } +inline int bge(int i) { return bc(4, 0, i, 0); } +inline int ble(int i) { return bc(4, 1, i, 0); } +inline int beq(int i) { return bc(12, 2, i, 0); } +inline int bne(int i) { return bc(4, 2, i, 0); } +inline int cmpw(int ra, int rb) { return cmp(0, ra, rb); } +inline int cmplw(int ra, int rb) { return cmpl(0, ra, rb); } +inline int cmpwi(int ra, int i) { return cmpi(0, ra, i); } +inline int cmplwi(int ra, int i) { return cmpli(0, ra, i); } +inline int trap() { return 0x7fe00008; } // todo: macro-ify + +} // namespace isa + +} // namespace powerpc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_ENCODE_H + diff --git a/src/codegen/powerpc/fixup.h b/src/codegen/powerpc/fixup.h new file mode 100644 index 0000000000..42fa62afc7 --- /dev/null +++ b/src/codegen/powerpc/fixup.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_FIXUP_H +#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_FIXUP_H + +namespace avian { +namespace codegen { +namespace powerpc { + + +class Task { + public: + Task(Task* next): next(next) { } + + virtual void run(Context* c) = 0; + + Task* next; +}; + +} // namespace powerpc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_FIXUP_H From 900b447e274032a268921d73140bf2d0d247577a Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sat, 23 Feb 2013 18:08:34 -0700 Subject: [PATCH 292/378] further break out powerpc assembler --- src/codegen/powerpc/assembler.cpp | 1609 +-------------------------- src/codegen/powerpc/fixup.cpp | 242 ++++ src/codegen/powerpc/fixup.h | 128 +++ src/codegen/powerpc/multimethod.cpp | 111 ++ src/codegen/powerpc/multimethod.h | 60 + src/codegen/powerpc/operations.cpp | 1097 ++++++++++++++++++ src/codegen/powerpc/operations.h | 197 ++++ src/codegen/powerpc/registers.h | 23 + 8 files changed, 1862 insertions(+), 1605 deletions(-) create mode 100644 src/codegen/powerpc/fixup.cpp create mode 100644 src/codegen/powerpc/multimethod.cpp create mode 100644 src/codegen/powerpc/multimethod.h create mode 100644 src/codegen/powerpc/operations.cpp create mode 100644 src/codegen/powerpc/operations.h create mode 100644 src/codegen/powerpc/registers.h diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index b1ad5f03ba..39405769bf 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -18,11 +18,8 @@ #include "context.h" #include "fixup.h" #include "block.h" - -#define CAST1(x) reinterpret_cast(x) -#define CAST2(x) reinterpret_cast(x) -#define CAST3(x) reinterpret_cast(x) -#define CAST_BRANCH(x) reinterpret_cast(x) +#include "multimethod.h" +#include "operations.h" using namespace vm; using namespace avian::util; @@ -31,38 +28,12 @@ namespace avian { namespace codegen { namespace powerpc { -const int64_t MASK_LO32 = 0x0ffffffff; -const int MASK_LO16 = 0x0ffff; -const int MASK_LO8 = 0x0ff; -// inline int lo32(int64_t i) { return (int)(i & MASK_LO32); } -// inline int hi32(int64_t i) { return lo32(i >> 32); } -inline int lo16(int64_t i) { return (int)(i & MASK_LO16); } -inline int hi16(int64_t i) { return lo16(i >> 16); } -// inline int lo8(int64_t i) { return (int)(i & MASK_LO8); } -// inline int hi8(int64_t i) { return lo8(i >> 8); } - -inline int ha16(int32_t i) { - return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; -} - inline int unha16(int32_t high, int32_t low) { return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; } const RegisterFile MyRegisterFile(0xFFFFFFFF, 0); -inline bool -isInt16(target_intptr_t v) -{ - return v == static_cast(v); -} - -inline int -carry16(target_intptr_t v) -{ - return static_cast(v) < 0 ? 1 : 0; -} - #ifdef __APPLE__ const unsigned FrameFooterSize = 6; const unsigned ReturnAddressOffset = 2; @@ -84,190 +55,13 @@ const bool DebugJumps = false; class JumpOffset; -void -resolve(MyBlock*); +unsigned padding(MyBlock*, unsigned); -unsigned -padding(MyBlock*, unsigned); +bool bounded(int right, int left, int32_t v); class Task; class ConstantPoolEntry; -class OffsetPromise: public Promise { - public: - OffsetPromise(Context* c, MyBlock* block, unsigned offset): - c(c), block(block), offset(offset) - { } - - virtual bool resolved() { - return block->resolved; - } - - virtual int64_t value() { - assert(c, resolved()); - - unsigned o = offset - block->offset; - return block->start + padding(block, o) + o; - } - - Context* c; - MyBlock* block; - unsigned offset; -}; - -Promise* -offsetPromise(Context* c) -{ - return new(c->zone) OffsetPromise(c, c->lastBlock, c->code.length()); -} - -bool -bounded(int right, int left, int32_t v) -{ - return ((v << left) >> left) == v and ((v >> right) << right) == v; -} - -void* -updateOffset(System* s, uint8_t* instruction, bool conditional, int64_t value, - void* jumpAddress) -{ - int32_t v = reinterpret_cast(value) - instruction; - - int32_t mask; - if (conditional) { - if (not bounded(2, 16, v)) { - *static_cast(jumpAddress) = isa::b(0); - updateOffset(s, static_cast(jumpAddress), false, value, 0); - - v = static_cast(jumpAddress) - instruction; - - expect(s, bounded(2, 16, v)); - } - mask = 0xFFFC; - } else { - expect(s, bounded(2, 6, v)); - mask = 0x3FFFFFC; - } - - int32_t* p = reinterpret_cast(instruction); - *p = targetV4((v & mask) | ((~mask) & targetV4(*p))); - - return instruction + 4; -} - -class OffsetListener: public Promise::Listener { - public: - OffsetListener(System* s, uint8_t* instruction, bool conditional, - void* jumpAddress): - s(s), - instruction(instruction), - jumpAddress(jumpAddress), - conditional(conditional) - { } - - virtual bool resolve(int64_t value, void** location) { - void* p = updateOffset(s, instruction, conditional, value, jumpAddress); - if (location) *location = p; - return false; - } - - System* s; - uint8_t* instruction; - void* jumpAddress; - bool conditional; -}; - -class OffsetTask: public Task { - public: - OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, - bool conditional): - Task(next), - promise(promise), - instructionOffset(instructionOffset), - jumpAddress(0), - conditional(conditional) - { } - - virtual void run(Context* c) { - if (promise->resolved()) { - updateOffset - (c->s, c->result + instructionOffset->value(), conditional, - promise->value(), jumpAddress); - } else { - new (promise->listen(sizeof(OffsetListener))) - OffsetListener(c->s, c->result + instructionOffset->value(), - conditional, jumpAddress); - } - } - - Promise* promise; - Promise* instructionOffset; - void* jumpAddress; - bool conditional; -}; - -class JumpOffset { - public: - JumpOffset(MyBlock* block, OffsetTask* task, unsigned offset): - block(block), task(task), next(0), offset(offset) - { } - - MyBlock* block; - OffsetTask* task; - JumpOffset* next; - unsigned offset; -}; - -class JumpEvent { - public: - JumpEvent(JumpOffset* jumpOffsetHead, JumpOffset* jumpOffsetTail, - unsigned offset): - jumpOffsetHead(jumpOffsetHead), jumpOffsetTail(jumpOffsetTail), next(0), - offset(offset) - { } - - JumpOffset* jumpOffsetHead; - JumpOffset* jumpOffsetTail; - JumpEvent* next; - unsigned offset; -}; - -void -appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, - bool conditional) -{ - OffsetTask* task = new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, conditional); - - c->tasks = task; - - if (conditional) { - JumpOffset* offset = - new(c->zone) JumpOffset(c->lastBlock, task, c->code.length() - c->lastBlock->offset); - - if (c->lastBlock->jumpOffsetTail) { - c->lastBlock->jumpOffsetTail->next = offset; - } else { - c->lastBlock->jumpOffsetHead = offset; - } - c->lastBlock->jumpOffsetTail = offset; - } -} - -void -appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head, - JumpOffset* tail) -{ - JumpEvent* e = new(c->zone) JumpEvent - (head, tail, offset); - - if (b->jumpEventTail) { - b->jumpEventTail->next = e; - } else { - b->jumpEventHead = e; - } - b->jumpEventTail = e; -} - bool needJump(MyBlock* b) { @@ -380,1322 +174,16 @@ resolve(MyBlock* b) } } -inline unsigned -index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) -{ - return operation + (lir::UnaryOperationCount * operand); -} - -inline unsigned -index(ArchitectureContext*, - lir::BinaryOperation operation, - lir::OperandType operand1, - lir::OperandType operand2) -{ - return operation - + (lir::BinaryOperationCount * operand1) - + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); -} - -inline unsigned -index(ArchitectureContext* c UNUSED, - lir::TernaryOperation operation, - lir::OperandType operand1) -{ - assert(c, not isBranch(operation)); - - return operation + (lir::NonBranchTernaryOperationCount * operand1); -} - -unsigned -branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, - lir::OperandType operand2) -{ - return operand1 + (lir::OperandTypeCount * operand2); -} - // BEGIN OPERATION COMPILERS using namespace isa; -inline void emit(Context* con, int code) { con->code.append4(targetV4(code)); } -inline int newTemp(Context* con) { return con->client->acquireTemporary(); } -inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } -inline int64_t getValue(lir::Constant* c) { return c->value->value(); } - inline void write4(uint8_t* dst, uint32_t v) { memcpy(dst, &v, 4); } -void -andC(Context* c, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst); - -void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) -{ - if(size == 8) { - lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; - emit(con, subfic(tmp->high, a->low, 32)); - emit(con, slw(t->high, b->high, a->low)); - emit(con, srw(tmp->low, b->low, tmp->high)); - emit(con, or_(t->high, t->high, tmp->low)); - emit(con, addi(tmp->high, a->low, -32)); - emit(con, slw(tmp->low, b->low, tmp->high)); - emit(con, or_(t->high, t->high, tmp->low)); - emit(con, slw(t->low, b->low, a->low)); - freeTemp(con, tmp->high); freeTemp(con, tmp->low); - } else { - emit(con, slw(t->low, b->low, a->low)); - } -} - -void -moveRR(Context* c, unsigned srcSize, lir::Register* src, - unsigned dstSize, lir::Register* dst); - -void shiftLeftC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) -{ - int sh = getValue(a); - if (size == 8) { - sh &= 0x3F; - if (sh) { - if (sh < 32) { - emit(con, rlwinm(t->high,b->high,sh,0,31-sh)); - emit(con, rlwimi(t->high,b->low,sh,32-sh,31)); - emit(con, slwi(t->low, b->low, sh)); - } else { - emit(con, rlwinm(t->high,b->low,sh-32,0,63-sh)); - emit(con, li(t->low,0)); - } - } else { - moveRR(con, size, b, size, t); - } - } else { - emit(con, slwi(t->low, b->low, sh & 0x1F)); - } -} - -void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) -{ - if(size == 8) { - lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; - emit(con, subfic(tmp->high, a->low, 32)); - emit(con, srw(t->low, b->low, a->low)); - emit(con, slw(tmp->low, b->high, tmp->high)); - emit(con, or_(t->low, t->low, tmp->low)); - emit(con, addic(tmp->high, a->low, -32)); - emit(con, sraw(tmp->low, b->high, tmp->high)); - emit(con, ble(8)); - emit(con, ori(t->low, tmp->low, 0)); - emit(con, sraw(t->high, b->high, a->low)); - freeTemp(con, tmp->high); freeTemp(con, tmp->low); - } else { - emit(con, sraw(t->low, b->low, a->low)); - } -} - -void shiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) -{ - int sh = getValue(a); - if(size == 8) { - sh &= 0x3F; - if (sh) { - if (sh < 32) { - emit(con, rlwinm(t->low,b->low,32-sh,sh,31)); - emit(con, rlwimi(t->low,b->high,32-sh,0,sh-1)); - emit(con, srawi(t->high,b->high,sh)); - } else { - emit(con, srawi(t->high,b->high,31)); - emit(con, srawi(t->low,b->high,sh-32)); - } - } else { - moveRR(con, size, b, size, t); - } - } else { - emit(con, srawi(t->low, b->low, sh & 0x1F)); - } -} - -void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) -{ - emit(con, srw(t->low, b->low, a->low)); - if(size == 8) { - lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; - emit(con, subfic(tmp->high, a->low, 32)); - emit(con, slw(tmp->low, b->high, tmp->high)); - emit(con, or_(t->low, t->low, tmp->low)); - emit(con, addi(tmp->high, a->low, -32)); - emit(con, srw(tmp->low, b->high, tmp->high)); - emit(con, or_(t->low, t->low, tmp->low)); - emit(con, srw(t->high, b->high, a->low)); - freeTemp(con, tmp->high); freeTemp(con, tmp->low); - } -} - -void unsignedShiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) -{ - int sh = getValue(a); - if (size == 8) { - if (sh & 0x3F) { - if (sh == 32) { - lir::Register high(b->high); - moveRR(con, 4, &high, 4, t); - emit(con, li(t->high,0)); - } else if (sh < 32) { - emit(con, srwi(t->low, b->low, sh)); - emit(con, rlwimi(t->low,b->high,32-sh,0,sh-1)); - emit(con, rlwinm(t->high,b->high,32-sh,sh,31)); - } else { - emit(con, rlwinm(t->low,b->high,64-sh,sh-32,31)); - emit(con, li(t->high,0)); - } - } else { - moveRR(con, size, b, size, t); - } - } else { - if (sh & 0x1F) { - emit(con, srwi(t->low, b->low, sh & 0x1F)); - } else { - moveRR(con, size, b, size, t); - } - } -} - -void -updateImmediate(System* s, void* dst, int32_t src, unsigned size, bool address) -{ - switch (size) { - case 4: { - int32_t* p = static_cast(dst); - int r = (targetV4(p[1]) >> 21) & 31; - - if (address) { - p[0] = targetV4(lis(r, ha16(src))); - p[1] |= targetV4(src & 0xFFFF); - } else { - p[0] = targetV4(lis(r, src >> 16)); - p[1] = targetV4(ori(r, r, src)); - } - } break; - - default: abort(s); - } -} - -class ImmediateListener: public Promise::Listener { - public: - ImmediateListener(System* s, void* dst, unsigned size, unsigned offset, - bool address): - s(s), dst(dst), size(size), offset(offset), address(address) - { } - - virtual bool resolve(int64_t value, void** location) { - updateImmediate(s, dst, value, size, address); - if (location) *location = static_cast(dst) + offset; - return false; - } - - System* s; - void* dst; - unsigned size; - unsigned offset; - bool address; -}; - -class ImmediateTask: public Task { - public: - ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, - unsigned promiseOffset, bool address): - Task(next), - promise(promise), - offset(offset), - size(size), - promiseOffset(promiseOffset), - address(address) - { } - - virtual void run(Context* c) { - if (promise->resolved()) { - updateImmediate - (c->s, c->result + offset->value(), promise->value(), size, address); - } else { - new (promise->listen(sizeof(ImmediateListener))) ImmediateListener - (c->s, c->result + offset->value(), size, promiseOffset, address); - } - } - - Promise* promise; - Promise* offset; - unsigned size; - unsigned promiseOffset; - bool address; -}; - -void -appendImmediateTask(Context* c, Promise* promise, Promise* offset, - unsigned size, unsigned promiseOffset, bool address) -{ - c->tasks = new(c->zone) ImmediateTask(c->tasks, promise, offset, size, promiseOffset, address); -} - -class ConstantPoolEntry: public Promise { - public: - ConstantPoolEntry(Context* c, Promise* constant): - c(c), constant(constant), next(c->constantPool), address(0) - { - c->constantPool = this; - ++ c->constantPoolCount; - } - - virtual int64_t value() { - assert(c, resolved()); - - return reinterpret_cast(address); - } - - virtual bool resolved() { - return address != 0; - } - - Context* c; - Promise* constant; - ConstantPoolEntry* next; - void* address; -}; - -ConstantPoolEntry* -appendConstantPoolEntry(Context* c, Promise* constant) -{ - return new (c->zone) ConstantPoolEntry(c, constant); -} - -void -jumpR(Context* c, unsigned size UNUSED, lir::Register* target) -{ - assert(c, size == TargetBytesPerWord); - - emit(c, mtctr(target->low)); - emit(c, bctr()); -} - -void -swapRR(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == TargetBytesPerWord); - assert(c, bSize == TargetBytesPerWord); - - lir::Register tmp(c->client->acquireTemporary()); - moveRR(c, aSize, a, bSize, &tmp); - moveRR(c, bSize, b, aSize, a); - moveRR(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); -} - -void -moveRR(Context* c, unsigned srcSize, lir::Register* src, - unsigned dstSize, lir::Register* dst) -{ - switch (srcSize) { - case 1: - emit(c, extsb(dst->low, src->low)); - break; - - case 2: - emit(c, extsh(dst->low, src->low)); - break; - - case 4: - case 8: - if (srcSize == 4 and dstSize == 8) { - moveRR(c, 4, src, 4, dst); - emit(c, srawi(dst->high, src->low, 31)); - } else if (srcSize == 8 and dstSize == 8) { - lir::Register srcHigh(src->high); - lir::Register dstHigh(dst->high); - - if (src->high == dst->low) { - if (src->low == dst->high) { - swapRR(c, 4, src, 4, dst); - } else { - moveRR(c, 4, &srcHigh, 4, &dstHigh); - moveRR(c, 4, src, 4, dst); - } - } else { - moveRR(c, 4, src, 4, dst); - moveRR(c, 4, &srcHigh, 4, &dstHigh); - } - } else if (src->low != dst->low) { - emit(c, mr(dst->low, src->low)); - } - break; - - default: abort(c); - } -} - -void -moveZRR(Context* c, unsigned srcSize, lir::Register* src, - unsigned, lir::Register* dst) -{ - switch (srcSize) { - case 2: - emit(c, andi(dst->low, src->low, 0xFFFF)); - break; - - default: abort(c); - } -} - -void -moveCR2(Context* c, unsigned, lir::Constant* src, - unsigned dstSize, lir::Register* dst, unsigned promiseOffset) -{ - if (dstSize <= 4) { - if (src->value->resolved()) { - int32_t v = src->value->value(); - if (isInt16(v)) { - emit(c, li(dst->low, v)); - } else { - emit(c, lis(dst->low, v >> 16)); - emit(c, ori(dst->low, dst->low, v)); - } - } else { - appendImmediateTask - (c, src->value, offsetPromise(c), TargetBytesPerWord, promiseOffset, false); - emit(c, lis(dst->low, 0)); - emit(c, ori(dst->low, dst->low, 0)); - } - } else { - abort(c); // todo - } -} - -void -moveCR(Context* c, unsigned srcSize, lir::Constant* src, - unsigned dstSize, lir::Register* dst) -{ - moveCR2(c, srcSize, src, dstSize, dst, 0); -} - -void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if(size == 8) { - emit(con, addc(t->low, a->low, b->low)); - emit(con, adde(t->high, a->high, b->high)); - } else { - emit(con, add(t->low, a->low, b->low)); - } -} - -void addC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { - assert(con, size == TargetBytesPerWord); - - int32_t i = getValue(a); - if(i) { - emit(con, addi(t->low, b->low, lo16(i))); - if(not isInt16(i)) - emit(con, addis(t->low, t->low, hi16(i) + carry16(i))); - } else { - moveRR(con, size, b, size, t); - } -} - -void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if(size == 8) { - emit(con, subfc(t->low, a->low, b->low)); - emit(con, subfe(t->high, a->high, b->high)); - } else { - emit(con, subf(t->low, a->low, b->low)); - } -} - -void subC(Context* c, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { - assert(c, size == TargetBytesPerWord); - - ResolvedPromise promise(- a->value->value()); - lir::Constant constant(&promise); - addC(c, size, &constant, b, t); -} - -void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - if(size == 8) { - bool useTemporaries = b->low == t->low; - int tmpLow; - int tmpHigh; - if (useTemporaries) { - tmpLow = con->client->acquireTemporary(); - tmpHigh = con->client->acquireTemporary(); - } else { - tmpLow = t->low; - tmpHigh = t->high; - } - - emit(con, mullw(tmpHigh, a->high, b->low)); - emit(con, mullw(tmpLow, a->low, b->high)); - emit(con, add(t->high, tmpHigh, tmpLow)); - emit(con, mulhwu(tmpLow, a->low, b->low)); - emit(con, add(t->high, t->high, tmpLow)); - emit(con, mullw(t->low, a->low, b->low)); - - if (useTemporaries) { - con->client->releaseTemporary(tmpLow); - con->client->releaseTemporary(tmpHigh); - } - } else { - emit(con, mullw(t->low, a->low, b->low)); - } -} - -void divideR(Context* con, unsigned size UNUSED, lir::Register* a, lir::Register* b, lir::Register* t) { - assert(con, size == 4); - emit(con, divw(t->low, b->low, a->low)); -} - -void remainderR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { - bool useTemporary = b->low == t->low; - lir::Register tmp(t->low); - if (useTemporary) { - tmp.low = con->client->acquireTemporary(); - } - - divideR(con, size, a, b, &tmp); - multiplyR(con, size, a, &tmp, &tmp); - subR(con, size, &tmp, b, t); - - if (useTemporary) { - con->client->releaseTemporary(tmp.low); - } -} - -int -normalize(Context* c, int offset, int index, unsigned scale, - bool* preserveIndex, bool* release) -{ - if (offset != 0 or scale != 1) { - lir::Register normalizedIndex - (*preserveIndex ? c->client->acquireTemporary() : index); - - if (*preserveIndex) { - *release = true; - *preserveIndex = false; - } else { - *release = false; - } - - int scaled; - - if (scale != 1) { - lir::Register unscaledIndex(index); - - ResolvedPromise scalePromise(log(scale)); - lir::Constant scaleConstant(&scalePromise); - - shiftLeftC(c, TargetBytesPerWord, &scaleConstant, - &unscaledIndex, &normalizedIndex); - - scaled = normalizedIndex.low; - } else { - scaled = index; - } - - if (offset != 0) { - lir::Register untranslatedIndex(scaled); - - ResolvedPromise offsetPromise(offset); - lir::Constant offsetConstant(&offsetPromise); - - addC(c, TargetBytesPerWord, &offsetConstant, - &untranslatedIndex, &normalizedIndex); - } - - return normalizedIndex.low; - } else { - *release = false; - return index; - } -} - -void -store(Context* c, unsigned size, lir::Register* src, - int base, int offset, int index, unsigned scale, bool preserveIndex) -{ - if (index != lir::NoRegister) { - bool release; - int normalized = normalize - (c, offset, index, scale, &preserveIndex, &release); - - switch (size) { - case 1: - emit(c, stbx(src->low, base, normalized)); - break; - - case 2: - emit(c, sthx(src->low, base, normalized)); - break; - - case 4: - emit(c, stwx(src->low, base, normalized)); - break; - - case 8: { - lir::Register srcHigh(src->high); - store(c, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); - store(c, 4, src, base, 4, normalized, 1, preserveIndex); - } break; - - default: abort(c); - } - - if (release) c->client->releaseTemporary(normalized); - } else { - switch (size) { - case 1: - emit(c, stb(src->low, base, offset)); - break; - - case 2: - emit(c, sth(src->low, base, offset)); - break; - - case 4: - emit(c, stw(src->low, base, offset)); - break; - - case 8: { - lir::Register srcHigh(src->high); - store(c, 4, &srcHigh, base, offset, lir::NoRegister, 1, false); - store(c, 4, src, base, offset + 4, lir::NoRegister, 1, false); - } break; - - default: abort(c); - } - } -} - -void -moveRM(Context* c, unsigned srcSize, lir::Register* src, - unsigned dstSize UNUSED, lir::Memory* dst) -{ - assert(c, srcSize == dstSize); - - store(c, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); -} - -void -moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, lir::Register* src, - unsigned dstSize UNUSED, lir::Memory* dst) -{ - assert(c, srcSize == TargetBytesPerWord); - assert(c, dstSize == TargetBytesPerWord); - - if (dst->index == lir::NoRegister) { - emit(c, stwu(src->low, dst->base, dst->offset)); - } else { - assert(c, dst->offset == 0); - assert(c, dst->scale == 1); - - emit(c, stwux(src->low, dst->base, dst->index)); - } -} - -void -load(Context* c, unsigned srcSize, int base, int offset, int index, - unsigned scale, unsigned dstSize, lir::Register* dst, - bool preserveIndex, bool signExtend) -{ - if (index != lir::NoRegister) { - bool release; - int normalized = normalize - (c, offset, index, scale, &preserveIndex, &release); - - switch (srcSize) { - case 1: - emit(c, lbzx(dst->low, base, normalized)); - if (signExtend) { - emit(c, extsb(dst->low, dst->low)); - } - break; - - case 2: - if (signExtend) { - emit(c, lhax(dst->low, base, normalized)); - } else { - emit(c, lhzx(dst->low, base, normalized)); - } - break; - - case 4: - case 8: { - if (srcSize == 4 and dstSize == 8) { - load(c, 4, base, 0, normalized, 1, 4, dst, preserveIndex, false); - moveRR(c, 4, dst, 8, dst); - } else if (srcSize == 8 and dstSize == 8) { - lir::Register dstHigh(dst->high); - load(c, 4, base, 0, normalized, 1, 4, &dstHigh, preserveIndex, false); - load(c, 4, base, 4, normalized, 1, 4, dst, preserveIndex, false); - } else { - emit(c, lwzx(dst->low, base, normalized)); - } - } break; - - default: abort(c); - } - - if (release) c->client->releaseTemporary(normalized); - } else { - switch (srcSize) { - case 1: - emit(c, lbz(dst->low, base, offset)); - if (signExtend) { - emit(c, extsb(dst->low, dst->low)); - } - break; - - case 2: - if (signExtend) { - emit(c, lha(dst->low, base, offset)); - } else { - emit(c, lha(dst->low, base, offset)); - } - break; - - case 4: - emit(c, lwz(dst->low, base, offset)); - break; - - case 8: { - if (dstSize == 8) { - lir::Register dstHigh(dst->high); - load(c, 4, base, offset, lir::NoRegister, 1, 4, &dstHigh, false, false); - load(c, 4, base, offset + 4, lir::NoRegister, 1, 4, dst, false, false); - } else { - emit(c, lwzx(dst->low, base, offset)); - } - } break; - - default: abort(c); - } - } -} - -void -moveMR(Context* c, unsigned srcSize, lir::Memory* src, - unsigned dstSize, lir::Register* dst) -{ - load(c, srcSize, src->base, src->offset, src->index, src->scale, - dstSize, dst, true, true); -} - -void -moveZMR(Context* c, unsigned srcSize, lir::Memory* src, - unsigned dstSize, lir::Register* dst) -{ - load(c, srcSize, src->base, src->offset, src->index, src->scale, - dstSize, dst, true, false); -} - -void -andR(Context* c, unsigned size, lir::Register* a, - lir::Register* b, lir::Register* dst) -{ - if (size == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - lir::Register dh(dst->high); - - andR(c, 4, a, b, dst); - andR(c, 4, &ah, &bh, &dh); - } else { - emit(c, and_(dst->low, a->low, b->low)); - } -} - -void -andC(Context* c, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst) -{ - int64_t v = a->value->value(); - - if (size == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - lir::Register dh(dst->high); - - andC(c, 4, &al, b, dst); - andC(c, 4, &ah, &bh, &dh); - } else { - // bitmasks of the form regex 0*1*0* can be handled in a single - // rlwinm instruction, hence the following: - - uint32_t v32 = static_cast(v); - unsigned state = 0; - unsigned start = 0; - unsigned end = 31; - for (unsigned i = 0; i < 32; ++i) { - unsigned bit = (v32 >> i) & 1; - switch (state) { - case 0: - if (bit) { - start = i; - state = 1; - } - break; - - case 1: - if (bit == 0) { - end = i - 1; - state = 2; - } - break; - - case 2: - if (bit) { - // not in 0*1*0* form. We can only use andi(s) if either - // the topmost or bottommost 16 bits are zero. - - if ((v32 >> 16) == 0) { - emit(c, andi(dst->low, b->low, v32)); - } else if ((v32 & 0xFFFF) == 0) { - emit(c, andis(dst->low, b->low, v32 >> 16)); - } else { - bool useTemporary = b->low == dst->low; - lir::Register tmp(dst->low); - if (useTemporary) { - tmp.low = c->client->acquireTemporary(); - } - - moveCR(c, 4, a, 4, &tmp); - andR(c, 4, b, &tmp, dst); - - if (useTemporary) { - c->client->releaseTemporary(tmp.low); - } - } - return; - } - break; - } - } - - if (state) { - if (start != 0 or end != 31) { - emit(c, rlwinm(dst->low, b->low, 0, 31 - end, 31 - start)); - } else { - moveRR(c, 4, b, 4, dst); - } - } else { - emit(c, li(dst->low, 0)); - } - } -} - -void -orR(Context* c, unsigned size, lir::Register* a, - lir::Register* b, lir::Register* dst) -{ - if (size == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - lir::Register dh(dst->high); - - orR(c, 4, a, b, dst); - orR(c, 4, &ah, &bh, &dh); - } else { - emit(c, or_(dst->low, a->low, b->low)); - } -} - -void -orC(Context* c, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst) -{ - int64_t v = a->value->value(); - - if (size == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - lir::Register dh(dst->high); - - orC(c, 4, &al, b, dst); - orC(c, 4, &ah, &bh, &dh); - } else { - emit(c, ori(b->low, dst->low, v)); - if (v >> 16) { - emit(c, oris(dst->low, dst->low, v >> 16)); - } - } -} - -void -xorR(Context* c, unsigned size, lir::Register* a, - lir::Register* b, lir::Register* dst) -{ - if (size == 8) { - lir::Register ah(a->high); - lir::Register bh(b->high); - lir::Register dh(dst->high); - - xorR(c, 4, a, b, dst); - xorR(c, 4, &ah, &bh, &dh); - } else { - emit(c, xor_(dst->low, a->low, b->low)); - } -} - -void -xorC(Context* c, unsigned size, lir::Constant* a, - lir::Register* b, lir::Register* dst) -{ - uint64_t v = a->value->value(); - - if (size == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - lir::Constant ah(&high); - - ResolvedPromise low(v & 0xFFFFFFFF); - lir::Constant al(&low); - - lir::Register bh(b->high); - lir::Register dh(dst->high); - - xorC(c, 4, &al, b, dst); - xorC(c, 4, &ah, &bh, &dh); - } else { - if (v >> 16) { - emit(c, xoris(b->low, dst->low, v >> 16)); - emit(c, xori(dst->low, dst->low, v)); - } else { - emit(c, xori(b->low, dst->low, v)); - } - } -} - -void -moveAR2(Context* c, unsigned srcSize UNUSED, lir::Address* src, - unsigned dstSize, lir::Register* dst, unsigned promiseOffset) -{ - assert(c, srcSize == 4 and dstSize == 4); - - lir::Memory memory(dst->low, 0, -1, 0); - - appendImmediateTask - (c, src->address, offsetPromise(c), TargetBytesPerWord, promiseOffset, true); - - emit(c, lis(dst->low, 0)); - moveMR(c, dstSize, &memory, dstSize, dst); -} - -void -moveAR(Context* c, unsigned srcSize, lir::Address* src, - unsigned dstSize, lir::Register* dst) -{ - moveAR2(c, srcSize, src, dstSize, dst, 0); -} - -void -compareRR(Context* c, unsigned aSize UNUSED, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == 4 and bSize == 4); - - emit(c, cmpw(b->low, a->low)); -} - -void -compareCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == 4 and bSize == 4); - - if (a->value->resolved() and isInt16(a->value->value())) { - emit(c, cmpwi(b->low, a->value->value())); - } else { - lir::Register tmp(c->client->acquireTemporary()); - moveCR(c, aSize, a, bSize, &tmp); - compareRR(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } -} - -void -compareCM(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Memory* b) -{ - assert(c, aSize == 4 and bSize == 4); - - lir::Register tmp(c->client->acquireTemporary()); - moveMR(c, bSize, b, bSize, &tmp); - compareCR(c, aSize, a, bSize, &tmp); - c->client->releaseTemporary(tmp.low); -} - -void -compareRM(Context* c, unsigned aSize, lir::Register* a, - unsigned bSize, lir::Memory* b) -{ - assert(c, aSize == 4 and bSize == 4); - - lir::Register tmp(c->client->acquireTemporary()); - moveMR(c, bSize, b, bSize, &tmp); - compareRR(c, aSize, a, bSize, &tmp); - c->client->releaseTemporary(tmp.low); -} - -void -compareUnsignedRR(Context* c, unsigned aSize UNUSED, lir::Register* a, - unsigned bSize UNUSED, lir::Register* b) -{ - assert(c, aSize == 4 and bSize == 4); - - emit(c, cmplw(b->low, a->low)); -} - -void -compareUnsignedCR(Context* c, unsigned aSize, lir::Constant* a, - unsigned bSize, lir::Register* b) -{ - assert(c, aSize == 4 and bSize == 4); - - if (a->value->resolved() and (a->value->value() >> 16) == 0) { - emit(c, cmplwi(b->low, a->value->value())); - } else { - lir::Register tmp(c->client->acquireTemporary()); - moveCR(c, aSize, a, bSize, &tmp); - compareUnsignedRR(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); - } -} - -int32_t -branch(Context* c, lir::TernaryOperation op) -{ - switch (op) { - case lir::JumpIfEqual: - return beq(0); - - case lir::JumpIfNotEqual: - return bne(0); - - case lir::JumpIfLess: - return blt(0); - - case lir::JumpIfGreater: - return bgt(0); - - case lir::JumpIfLessOrEqual: - return ble(0); - - case lir::JumpIfGreaterOrEqual: - return bge(0); - - default: - abort(c); - } -} - -void -conditional(Context* c, int32_t branch, lir::Constant* target) -{ - appendOffsetTask(c, target->value, offsetPromise(c), true); - emit(c, branch); -} - -void -branch(Context* c, lir::TernaryOperation op, lir::Constant* target) -{ - conditional(c, branch(c, op), target); -} - -void -branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, - lir::Operand* ah, lir::Operand* bl, - lir::Operand* bh, lir::Constant* target, - BinaryOperationType compareSigned, - BinaryOperationType compareUnsigned) -{ - compareSigned(c, 4, ah, 4, bh); - - unsigned next = 0; - - switch (op) { - case lir::JumpIfEqual: - next = c->code.length(); - emit(c, bne(0)); - - compareSigned(c, 4, al, 4, bl); - conditional(c, beq(0), target); - break; - - case lir::JumpIfNotEqual: - conditional(c, bne(0), target); - - compareSigned(c, 4, al, 4, bl); - conditional(c, bne(0), target); - break; - - case lir::JumpIfLess: - conditional(c, blt(0), target); - - next = c->code.length(); - emit(c, bgt(0)); - - compareUnsigned(c, 4, al, 4, bl); - conditional(c, blt(0), target); - break; - - case lir::JumpIfGreater: - conditional(c, bgt(0), target); - - next = c->code.length(); - emit(c, blt(0)); - - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bgt(0), target); - break; - - case lir::JumpIfLessOrEqual: - conditional(c, blt(0), target); - - next = c->code.length(); - emit(c, bgt(0)); - - compareUnsigned(c, 4, al, 4, bl); - conditional(c, ble(0), target); - break; - - case lir::JumpIfGreaterOrEqual: - conditional(c, bgt(0), target); - - next = c->code.length(); - emit(c, blt(0)); - - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bge(0), target); - break; - - default: - abort(c); - } - - if (next) { - updateOffset - (c->s, c->code.data + next, true, reinterpret_cast - (c->code.data + c->code.length()), 0); - } -} - -void -branchRR(Context* c, lir::TernaryOperation op, unsigned size, - lir::Register* a, lir::Register* b, - lir::Constant* target) -{ - if (size > TargetBytesPerWord) { - lir::Register ah(a->high); - lir::Register bh(b->high); - - branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR), - CAST2(compareUnsignedRR)); - } else { - compareRR(c, size, a, size, b); - branch(c, op, target); - } -} - -void -branchCR(Context* c, lir::TernaryOperation op, unsigned size, - lir::Constant* a, lir::Register* b, - lir::Constant* target) -{ - if (size > TargetBytesPerWord) { - int64_t v = a->value->value(); - - ResolvedPromise low(v & ~static_cast(0)); - lir::Constant al(&low); - - ResolvedPromise high((v >> 32) & ~static_cast(0)); - lir::Constant ah(&high); - - lir::Register bh(b->high); - - branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR), - CAST2(compareUnsignedCR)); - } else { - compareCR(c, size, a, size, b); - branch(c, op, target); - } -} - -void -branchRM(Context* c, lir::TernaryOperation op, unsigned size, - lir::Register* a, lir::Memory* b, - lir::Constant* target) -{ - assert(c, size <= TargetBytesPerWord); - - compareRM(c, size, a, size, b); - branch(c, op, target); -} - -void -branchCM(Context* c, lir::TernaryOperation op, unsigned size, - lir::Constant* a, lir::Memory* b, - lir::Constant* target) -{ - assert(c, size <= TargetBytesPerWord); - - compareCM(c, size, a, size, b); - branch(c, op, target); -} - -ShiftMaskPromise* -shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) -{ - return new (c->zone) ShiftMaskPromise(base, shift, mask); -} - -void -moveCM(Context* c, unsigned srcSize, lir::Constant* src, - unsigned dstSize, lir::Memory* dst) -{ - switch (dstSize) { - case 8: { - lir::Constant srcHigh - (shiftMaskPromise(c, src->value, 32, 0xFFFFFFFF)); - lir::Constant srcLow - (shiftMaskPromise(c, src->value, 0, 0xFFFFFFFF)); - - lir::Memory dstLow - (dst->base, dst->offset + 4, dst->index, dst->scale); - - moveCM(c, 4, &srcLow, 4, &dstLow); - moveCM(c, 4, &srcHigh, 4, dst); - } break; - - default: - lir::Register tmp(c->client->acquireTemporary()); - moveCR(c, srcSize, src, dstSize, &tmp); - moveRM(c, dstSize, &tmp, dstSize, dst); - c->client->releaseTemporary(tmp.low); - } -} - -void -negateRR(Context* c, unsigned srcSize, lir::Register* src, - unsigned dstSize UNUSED, lir::Register* dst) -{ - assert(c, srcSize == dstSize); - - if (srcSize == 8) { - lir::Register dstHigh(dst->high); - - emit(c, subfic(dst->low, src->low, 0)); - emit(c, subfze(dst->high, src->high)); - } else { - emit(c, neg(dst->low, src->low)); - } -} - -void -callR(Context* c, unsigned size UNUSED, lir::Register* target) -{ - assert(c, size == TargetBytesPerWord); - - emit(c, mtctr(target->low)); - emit(c, bctrl()); -} - -void -callC(Context* c, unsigned size UNUSED, lir::Constant* target) -{ - assert(c, size == TargetBytesPerWord); - - appendOffsetTask(c, target->value, offsetPromise(c), false); - emit(c, bl(0)); -} - -void -longCallC(Context* c, unsigned size UNUSED, lir::Constant* target) -{ - assert(c, size == TargetBytesPerWord); - - lir::Register tmp(0); - moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, 12); - callR(c, TargetBytesPerWord, &tmp); -} - -void -alignedLongCallC(Context* c, unsigned size UNUSED, lir::Constant* target) -{ - assert(c, size == TargetBytesPerWord); - - lir::Register tmp(c->client->acquireTemporary()); - lir::Address address(appendConstantPoolEntry(c, target->value)); - moveAR2(c, TargetBytesPerWord, &address, TargetBytesPerWord, &tmp, 12); - callR(c, TargetBytesPerWord, &tmp); - c->client->releaseTemporary(tmp.low); -} - -void -longJumpC(Context* c, unsigned size UNUSED, lir::Constant* target) -{ - assert(c, size == TargetBytesPerWord); - - lir::Register tmp(0); - moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, 12); - jumpR(c, TargetBytesPerWord, &tmp); -} - -void -alignedLongJumpC(Context* c, unsigned size UNUSED, lir::Constant* target) -{ - assert(c, size == TargetBytesPerWord); - - lir::Register tmp(c->client->acquireTemporary()); - lir::Address address(appendConstantPoolEntry(c, target->value)); - moveAR2(c, TargetBytesPerWord, &address, TargetBytesPerWord, &tmp, 12); - jumpR(c, TargetBytesPerWord, &tmp); - c->client->releaseTemporary(tmp.low); -} - -void -jumpC(Context* c, unsigned size UNUSED, lir::Constant* target) -{ - assert(c, size == TargetBytesPerWord); - - appendOffsetTask(c, target->value, offsetPromise(c), false); - emit(c, b(0)); -} - -void -return_(Context* c) -{ - emit(c, blr()); -} - -void -trap(Context* c) -{ - emit(c, isa::trap()); -} - -void -memoryBarrier(Context* c) -{ - emit(c, sync(0)); -} - // END OPERATION COMPILERS unsigned @@ -1753,95 +241,6 @@ nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size, *stack = static_cast(*stack) + offset; } -void -populateTables(ArchitectureContext* c) -{ - const lir::OperandType C = lir::ConstantOperand; - const lir::OperandType A = lir::AddressOperand; - const lir::OperandType R = lir::RegisterOperand; - const lir::OperandType M = lir::MemoryOperand; - - OperationType* zo = c->operations; - UnaryOperationType* uo = c->unaryOperations; - BinaryOperationType* bo = c->binaryOperations; - TernaryOperationType* to = c->ternaryOperations; - BranchOperationType* bro = c->branchOperations; - - zo[lir::Return] = return_; - zo[lir::LoadBarrier] = memoryBarrier; - zo[lir::StoreStoreBarrier] = memoryBarrier; - zo[lir::StoreLoadBarrier] = memoryBarrier; - zo[lir::Trap] = trap; - - uo[index(c, lir::LongCall, C)] = CAST1(longCallC); - - uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); - - uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); - - uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); - - uo[index(c, lir::Jump, R)] = CAST1(jumpR); - uo[index(c, lir::Jump, C)] = CAST1(jumpC); - - uo[index(c, lir::AlignedJump, R)] = CAST1(jumpR); - uo[index(c, lir::AlignedJump, C)] = CAST1(jumpC); - - uo[index(c, lir::Call, C)] = CAST1(callC); - uo[index(c, lir::Call, R)] = CAST1(callR); - - uo[index(c, lir::AlignedCall, C)] = CAST1(callC); - uo[index(c, lir::AlignedCall, R)] = CAST1(callR); - - bo[index(c, lir::Move, R, R)] = CAST2(moveRR); - bo[index(c, lir::Move, C, R)] = CAST2(moveCR); - bo[index(c, lir::Move, C, M)] = CAST2(moveCM); - bo[index(c, lir::Move, M, R)] = CAST2(moveMR); - bo[index(c, lir::Move, R, M)] = CAST2(moveRM); - bo[index(c, lir::Move, A, R)] = CAST2(moveAR); - - bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); - bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); - bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR); - - bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); - - to[index(c, lir::Add, R)] = CAST3(addR); - to[index(c, lir::Add, C)] = CAST3(addC); - - to[index(c, lir::Subtract, R)] = CAST3(subR); - to[index(c, lir::Subtract, C)] = CAST3(subC); - - to[index(c, lir::Multiply, R)] = CAST3(multiplyR); - - to[index(c, lir::Divide, R)] = CAST3(divideR); - - to[index(c, lir::Remainder, R)] = CAST3(remainderR); - - to[index(c, lir::ShiftLeft, R)] = CAST3(shiftLeftR); - to[index(c, lir::ShiftLeft, C)] = CAST3(shiftLeftC); - - to[index(c, lir::ShiftRight, R)] = CAST3(shiftRightR); - to[index(c, lir::ShiftRight, C)] = CAST3(shiftRightC); - - to[index(c, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); - to[index(c, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); - - to[index(c, lir::And, C)] = CAST3(andC); - to[index(c, lir::And, R)] = CAST3(andR); - - to[index(c, lir::Or, C)] = CAST3(orC); - to[index(c, lir::Or, R)] = CAST3(orR); - - to[index(c, lir::Xor, C)] = CAST3(xorC); - to[index(c, lir::Xor, R)] = CAST3(xorR); - - bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); - bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); - bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM); - bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM); -} - class MyArchitecture: public Assembler::Architecture { public: MyArchitecture(System* system): c(system), referenceCount(0) { diff --git a/src/codegen/powerpc/fixup.cpp b/src/codegen/powerpc/fixup.cpp new file mode 100644 index 0000000000..eb8a4aac6d --- /dev/null +++ b/src/codegen/powerpc/fixup.cpp @@ -0,0 +1,242 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "block.h" +#include "fixup.h" +#include "encode.h" + +namespace avian { +namespace codegen { +namespace powerpc { + +using namespace isa; + +unsigned padding(MyBlock*, unsigned); + +inline int ha16(int32_t i); + +bool bounded(int right, int left, int32_t v) { + return ((v << left) >> left) == v and ((v >> right) << right) == v; +} + +OffsetPromise::OffsetPromise(Context* c, MyBlock* block, unsigned offset): + c(c), block(block), offset(offset) +{ } + +bool OffsetPromise::resolved() { + return block->resolved; +} + +int64_t OffsetPromise::value() { + assert(c, resolved()); + + unsigned o = offset - block->offset; + return block->start + padding(block, o) + o; +} + +Promise* offsetPromise(Context* c) { + return new(c->zone) OffsetPromise(c, c->lastBlock, c->code.length()); +} + +void* updateOffset(vm::System* s, uint8_t* instruction, bool conditional, int64_t value, + void* jumpAddress) +{ + int32_t v = reinterpret_cast(value) - instruction; + + int32_t mask; + if (conditional) { + if (not bounded(2, 16, v)) { + *static_cast(jumpAddress) = isa::b(0); + updateOffset(s, static_cast(jumpAddress), false, value, 0); + + v = static_cast(jumpAddress) - instruction; + + expect(s, bounded(2, 16, v)); + } + mask = 0xFFFC; + } else { + expect(s, bounded(2, 6, v)); + mask = 0x3FFFFFC; + } + + int32_t* p = reinterpret_cast(instruction); + *p = vm::targetV4((v & mask) | ((~mask) & vm::targetV4(*p))); + + return instruction + 4; +} + +OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction, bool conditional, + void* jumpAddress): + s(s), + instruction(instruction), + jumpAddress(jumpAddress), + conditional(conditional) +{ } + +bool OffsetListener::resolve(int64_t value, void** location) { + void* p = updateOffset(s, instruction, conditional, value, jumpAddress); + if (location) *location = p; + return false; +} + +OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, + bool conditional): + Task(next), + promise(promise), + instructionOffset(instructionOffset), + jumpAddress(0), + conditional(conditional) +{ } + +void OffsetTask::run(Context* c) { + if (promise->resolved()) { + updateOffset + (c->s, c->result + instructionOffset->value(), conditional, + promise->value(), jumpAddress); + } else { + new (promise->listen(sizeof(OffsetListener))) + OffsetListener(c->s, c->result + instructionOffset->value(), + conditional, jumpAddress); + } +} + +JumpOffset::JumpOffset(MyBlock* block, OffsetTask* task, unsigned offset): + block(block), task(task), next(0), offset(offset) +{ } + +JumpEvent::JumpEvent(JumpOffset* jumpOffsetHead, JumpOffset* jumpOffsetTail, + unsigned offset): + jumpOffsetHead(jumpOffsetHead), jumpOffsetTail(jumpOffsetTail), next(0), + offset(offset) +{ } + +void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, + bool conditional) +{ + OffsetTask* task = new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, conditional); + + c->tasks = task; + + if (conditional) { + JumpOffset* offset = + new(c->zone) JumpOffset(c->lastBlock, task, c->code.length() - c->lastBlock->offset); + + if (c->lastBlock->jumpOffsetTail) { + c->lastBlock->jumpOffsetTail->next = offset; + } else { + c->lastBlock->jumpOffsetHead = offset; + } + c->lastBlock->jumpOffsetTail = offset; + } +} + +void appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head, + JumpOffset* tail) +{ + JumpEvent* e = new(c->zone) JumpEvent + (head, tail, offset); + + if (b->jumpEventTail) { + b->jumpEventTail->next = e; + } else { + b->jumpEventHead = e; + } + b->jumpEventTail = e; +} + +ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { + return new (c->zone) ShiftMaskPromise(base, shift, mask); +} + +void +updateImmediate(vm::System* s, void* dst, int32_t src, unsigned size, bool address) +{ + switch (size) { + case 4: { + int32_t* p = static_cast(dst); + int r = (vm::targetV4(p[1]) >> 21) & 31; + + if (address) { + p[0] = vm::targetV4(lis(r, ha16(src))); + p[1] |= vm::targetV4(src & 0xFFFF); + } else { + p[0] = vm::targetV4(lis(r, src >> 16)); + p[1] = vm::targetV4(ori(r, r, src)); + } + } break; + + default: abort(s); + } +} + +ImmediateListener::ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset, + bool address): + s(s), dst(dst), size(size), offset(offset), address(address) +{ } + +bool ImmediateListener::resolve(int64_t value, void** location) { + updateImmediate(s, dst, value, size, address); + if (location) *location = static_cast(dst) + offset; + return false; +} + +ImmediateTask::ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, + unsigned promiseOffset, bool address): + Task(next), + promise(promise), + offset(offset), + size(size), + promiseOffset(promiseOffset), + address(address) +{ } + +void ImmediateTask::run(Context* c) { + if (promise->resolved()) { + updateImmediate + (c->s, c->result + offset->value(), promise->value(), size, address); + } else { + new (promise->listen(sizeof(ImmediateListener))) ImmediateListener + (c->s, c->result + offset->value(), size, promiseOffset, address); + } +} + +void +appendImmediateTask(Context* c, Promise* promise, Promise* offset, + unsigned size, unsigned promiseOffset, bool address) +{ + c->tasks = new(c->zone) ImmediateTask(c->tasks, promise, offset, size, promiseOffset, address); +} + +ConstantPoolEntry::ConstantPoolEntry(Context* c, Promise* constant): + c(c), constant(constant), next(c->constantPool), address(0) +{ + c->constantPool = this; + ++ c->constantPoolCount; +} + +int64_t ConstantPoolEntry::value() { + assert(c, resolved()); + + return reinterpret_cast(address); +} + +bool ConstantPoolEntry::resolved() { + return address != 0; +} + +ConstantPoolEntry* appendConstantPoolEntry(Context* c, Promise* constant) { + return new (c->zone) ConstantPoolEntry(c, constant); +} + + +} // namespace powerpc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/powerpc/fixup.h b/src/codegen/powerpc/fixup.h index 42fa62afc7..a51e5f6d5b 100644 --- a/src/codegen/powerpc/fixup.h +++ b/src/codegen/powerpc/fixup.h @@ -25,6 +25,134 @@ class Task { Task* next; }; +class OffsetPromise: public Promise { + public: + OffsetPromise(Context* c, MyBlock* block, unsigned offset); + + virtual bool resolved(); + + virtual int64_t value(); + + Context* c; + MyBlock* block; + unsigned offset; +}; + +Promise* offsetPromise(Context* c); + +void* +updateOffset(vm::System* s, uint8_t* instruction, bool conditional, int64_t value, + void* jumpAddress); + +class OffsetListener: public Promise::Listener { + public: + OffsetListener(vm::System* s, uint8_t* instruction, bool conditional, + void* jumpAddress); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + uint8_t* instruction; + void* jumpAddress; + bool conditional; +}; + +class OffsetTask: public Task { + public: + OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, + bool conditional); + + virtual void run(Context* c); + + Promise* promise; + Promise* instructionOffset; + void* jumpAddress; + bool conditional; +}; + +class JumpOffset { + public: + JumpOffset(MyBlock* block, OffsetTask* task, unsigned offset); + + MyBlock* block; + OffsetTask* task; + JumpOffset* next; + unsigned offset; +}; + +class JumpEvent { + public: + JumpEvent(JumpOffset* jumpOffsetHead, JumpOffset* jumpOffsetTail, + unsigned offset); + + JumpOffset* jumpOffsetHead; + JumpOffset* jumpOffsetTail; + JumpEvent* next; + unsigned offset; +}; + +void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, + bool conditional); + +void appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head, + JumpOffset* tail); + +ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask); + +void updateImmediate(vm::System* s, void* dst, int32_t src, unsigned size, bool address); + +class ImmediateListener: public Promise::Listener { + public: + ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset, + bool address); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + void* dst; + unsigned size; + unsigned offset; + bool address; +}; + +class ImmediateTask: public Task { + public: + ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, + unsigned promiseOffset, bool address); + + virtual void run(Context* c); + + Promise* promise; + Promise* offset; + unsigned size; + unsigned promiseOffset; + bool address; +}; + +void +appendImmediateTask(Context* c, Promise* promise, Promise* offset, + unsigned size, unsigned promiseOffset, bool address); + +class ConstantPoolEntry: public Promise { + public: + ConstantPoolEntry(Context* c, Promise* constant); + + virtual int64_t value(); + + virtual bool resolved(); + + Context* c; + Promise* constant; + ConstantPoolEntry* next; + void* address; +}; + +ConstantPoolEntry* appendConstantPoolEntry(Context* c, Promise* constant); + +inline int ha16(int32_t i) { + return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; +} + } // namespace powerpc } // namespace codegen } // namespace avian diff --git a/src/codegen/powerpc/multimethod.cpp b/src/codegen/powerpc/multimethod.cpp new file mode 100644 index 0000000000..79b5f9bf7b --- /dev/null +++ b/src/codegen/powerpc/multimethod.cpp @@ -0,0 +1,111 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "block.h" +#include "common.h" + +#include "operations.h" +#include "multimethod.h" + +namespace avian { +namespace codegen { +namespace powerpc { + +void populateTables(ArchitectureContext* c) { + const lir::OperandType C = lir::ConstantOperand; + const lir::OperandType A = lir::AddressOperand; + const lir::OperandType R = lir::RegisterOperand; + const lir::OperandType M = lir::MemoryOperand; + + OperationType* zo = c->operations; + UnaryOperationType* uo = c->unaryOperations; + BinaryOperationType* bo = c->binaryOperations; + TernaryOperationType* to = c->ternaryOperations; + BranchOperationType* bro = c->branchOperations; + + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = memoryBarrier; + zo[lir::StoreStoreBarrier] = memoryBarrier; + zo[lir::StoreLoadBarrier] = memoryBarrier; + zo[lir::Trap] = trap; + + uo[index(c, lir::LongCall, C)] = CAST1(longCallC); + + uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); + + uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); + + uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); + + uo[index(c, lir::Jump, R)] = CAST1(jumpR); + uo[index(c, lir::Jump, C)] = CAST1(jumpC); + + uo[index(c, lir::AlignedJump, R)] = CAST1(jumpR); + uo[index(c, lir::AlignedJump, C)] = CAST1(jumpC); + + uo[index(c, lir::Call, C)] = CAST1(callC); + uo[index(c, lir::Call, R)] = CAST1(callR); + + uo[index(c, lir::AlignedCall, C)] = CAST1(callC); + uo[index(c, lir::AlignedCall, R)] = CAST1(callR); + + bo[index(c, lir::Move, R, R)] = CAST2(moveRR); + bo[index(c, lir::Move, C, R)] = CAST2(moveCR); + bo[index(c, lir::Move, C, M)] = CAST2(moveCM); + bo[index(c, lir::Move, M, R)] = CAST2(moveMR); + bo[index(c, lir::Move, R, M)] = CAST2(moveRM); + bo[index(c, lir::Move, A, R)] = CAST2(moveAR); + + bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR); + + bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); + + to[index(c, lir::Add, R)] = CAST3(addR); + to[index(c, lir::Add, C)] = CAST3(addC); + + to[index(c, lir::Subtract, R)] = CAST3(subR); + to[index(c, lir::Subtract, C)] = CAST3(subC); + + to[index(c, lir::Multiply, R)] = CAST3(multiplyR); + + to[index(c, lir::Divide, R)] = CAST3(divideR); + + to[index(c, lir::Remainder, R)] = CAST3(remainderR); + + to[index(c, lir::ShiftLeft, R)] = CAST3(shiftLeftR); + to[index(c, lir::ShiftLeft, C)] = CAST3(shiftLeftC); + + to[index(c, lir::ShiftRight, R)] = CAST3(shiftRightR); + to[index(c, lir::ShiftRight, C)] = CAST3(shiftRightC); + + to[index(c, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); + to[index(c, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); + + to[index(c, lir::And, C)] = CAST3(andC); + to[index(c, lir::And, R)] = CAST3(andR); + + to[index(c, lir::Or, C)] = CAST3(orC); + to[index(c, lir::Or, R)] = CAST3(orR); + + to[index(c, lir::Xor, C)] = CAST3(xorC); + to[index(c, lir::Xor, R)] = CAST3(xorR); + + bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); + bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); + bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM); + bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM); +} + +} // namespace powerpc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/powerpc/multimethod.h b/src/codegen/powerpc/multimethod.h new file mode 100644 index 0000000000..b2fe6f206d --- /dev/null +++ b/src/codegen/powerpc/multimethod.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_MULTIMETHOD_H +#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_MULTIMETHOD_H + +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST3(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + +namespace avian { +namespace codegen { +namespace powerpc { + + +inline unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) +{ + return operation + (lir::UnaryOperationCount * operand); +} + +inline unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2) +{ + return operation + + (lir::BinaryOperationCount * operand1) + + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); +} + +inline unsigned index(ArchitectureContext* c UNUSED, + lir::TernaryOperation operation, + lir::OperandType operand1) +{ + assert(c, not isBranch(operation)); + + return operation + (lir::NonBranchTernaryOperationCount * operand1); +} + +inline unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, + lir::OperandType operand2) +{ + return operand1 + (lir::OperandTypeCount * operand2); +} + +void populateTables(ArchitectureContext* c); + +} // namespace powerpc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_MULTIMETHOD_H diff --git a/src/codegen/powerpc/operations.cpp b/src/codegen/powerpc/operations.cpp new file mode 100644 index 0000000000..8127e85591 --- /dev/null +++ b/src/codegen/powerpc/operations.cpp @@ -0,0 +1,1097 @@ +/* Copyright (c) 2008-2012, 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 "context.h" +#include "block.h" +#include "common.h" +#include "encode.h" +#include "operations.h" +#include "fixup.h" +#include "multimethod.h" + +using namespace vm; + +namespace avian { +namespace codegen { +namespace powerpc { + +using namespace isa; +using namespace util; + +const int64_t MASK_LO32 = 0x0ffffffff; +const int MASK_LO16 = 0x0ffff; +const int MASK_LO8 = 0x0ff; +// inline int lo32(int64_t i) { return (int)(i & MASK_LO32); } +// inline int hi32(int64_t i) { return lo32(i >> 32); } +inline int lo16(int64_t i) { return (int)(i & MASK_LO16); } +inline int hi16(int64_t i) { return lo16(i >> 16); } +// inline int lo8(int64_t i) { return (int)(i & MASK_LO8); } +// inline int hi8(int64_t i) { return lo8(i >> 8); } + +inline int carry16(target_intptr_t v) { + return static_cast(v) < 0 ? 1 : 0; +} + +void andC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if(size == 8) { + lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; + emit(con, subfic(tmp->high, a->low, 32)); + emit(con, slw(t->high, b->high, a->low)); + emit(con, srw(tmp->low, b->low, tmp->high)); + emit(con, or_(t->high, t->high, tmp->low)); + emit(con, addi(tmp->high, a->low, -32)); + emit(con, slw(tmp->low, b->low, tmp->high)); + emit(con, or_(t->high, t->high, tmp->low)); + emit(con, slw(t->low, b->low, a->low)); + freeTemp(con, tmp->high); freeTemp(con, tmp->low); + } else { + emit(con, slw(t->low, b->low, a->low)); + } +} + +void moveRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); + +void shiftLeftC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { + int sh = getValue(a); + if (size == 8) { + sh &= 0x3F; + if (sh) { + if (sh < 32) { + emit(con, rlwinm(t->high,b->high,sh,0,31-sh)); + emit(con, rlwimi(t->high,b->low,sh,32-sh,31)); + emit(con, slwi(t->low, b->low, sh)); + } else { + emit(con, rlwinm(t->high,b->low,sh-32,0,63-sh)); + emit(con, li(t->low,0)); + } + } else { + moveRR(con, size, b, size, t); + } + } else { + emit(con, slwi(t->low, b->low, sh & 0x1F)); + } +} + +void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if(size == 8) { + lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; + emit(con, subfic(tmp->high, a->low, 32)); + emit(con, srw(t->low, b->low, a->low)); + emit(con, slw(tmp->low, b->high, tmp->high)); + emit(con, or_(t->low, t->low, tmp->low)); + emit(con, addic(tmp->high, a->low, -32)); + emit(con, sraw(tmp->low, b->high, tmp->high)); + emit(con, ble(8)); + emit(con, ori(t->low, tmp->low, 0)); + emit(con, sraw(t->high, b->high, a->low)); + freeTemp(con, tmp->high); freeTemp(con, tmp->low); + } else { + emit(con, sraw(t->low, b->low, a->low)); + } +} + +void shiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { + int sh = getValue(a); + if(size == 8) { + sh &= 0x3F; + if (sh) { + if (sh < 32) { + emit(con, rlwinm(t->low,b->low,32-sh,sh,31)); + emit(con, rlwimi(t->low,b->high,32-sh,0,sh-1)); + emit(con, srawi(t->high,b->high,sh)); + } else { + emit(con, srawi(t->high,b->high,31)); + emit(con, srawi(t->low,b->high,sh-32)); + } + } else { + moveRR(con, size, b, size, t); + } + } else { + emit(con, srawi(t->low, b->low, sh & 0x1F)); + } +} + +void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + emit(con, srw(t->low, b->low, a->low)); + if(size == 8) { + lir::Register Tmp(newTemp(con), newTemp(con)); lir::Register* tmp = &Tmp; + emit(con, subfic(tmp->high, a->low, 32)); + emit(con, slw(tmp->low, b->high, tmp->high)); + emit(con, or_(t->low, t->low, tmp->low)); + emit(con, addi(tmp->high, a->low, -32)); + emit(con, srw(tmp->low, b->high, tmp->high)); + emit(con, or_(t->low, t->low, tmp->low)); + emit(con, srw(t->high, b->high, a->low)); + freeTemp(con, tmp->high); freeTemp(con, tmp->low); + } +} + +void unsignedShiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { + int sh = getValue(a); + if (size == 8) { + if (sh & 0x3F) { + if (sh == 32) { + lir::Register high(b->high); + moveRR(con, 4, &high, 4, t); + emit(con, li(t->high,0)); + } else if (sh < 32) { + emit(con, srwi(t->low, b->low, sh)); + emit(con, rlwimi(t->low,b->high,32-sh,0,sh-1)); + emit(con, rlwinm(t->high,b->high,32-sh,sh,31)); + } else { + emit(con, rlwinm(t->low,b->high,64-sh,sh-32,31)); + emit(con, li(t->high,0)); + } + } else { + moveRR(con, size, b, size, t); + } + } else { + if (sh & 0x1F) { + emit(con, srwi(t->low, b->low, sh & 0x1F)); + } else { + moveRR(con, size, b, size, t); + } + } +} + +void jumpR(Context* c, unsigned size UNUSED, lir::Register* target) { + assert(c, size == TargetBytesPerWord); + + emit(c, mtctr(target->low)); + emit(c, bctr()); +} + +void swapRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b) { + assert(c, aSize == TargetBytesPerWord); + assert(c, bSize == TargetBytesPerWord); + + lir::Register tmp(c->client->acquireTemporary()); + moveRR(c, aSize, a, bSize, &tmp); + moveRR(c, bSize, b, aSize, a); + moveRR(c, bSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); +} + +void moveRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst) { + switch (srcSize) { + case 1: + emit(c, extsb(dst->low, src->low)); + break; + + case 2: + emit(c, extsh(dst->low, src->low)); + break; + + case 4: + case 8: + if (srcSize == 4 and dstSize == 8) { + moveRR(c, 4, src, 4, dst); + emit(c, srawi(dst->high, src->low, 31)); + } else if (srcSize == 8 and dstSize == 8) { + lir::Register srcHigh(src->high); + lir::Register dstHigh(dst->high); + + if (src->high == dst->low) { + if (src->low == dst->high) { + swapRR(c, 4, src, 4, dst); + } else { + moveRR(c, 4, &srcHigh, 4, &dstHigh); + moveRR(c, 4, src, 4, dst); + } + } else { + moveRR(c, 4, src, 4, dst); + moveRR(c, 4, &srcHigh, 4, &dstHigh); + } + } else if (src->low != dst->low) { + emit(c, mr(dst->low, src->low)); + } + break; + + default: abort(c); + } +} + +void moveZRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned, lir::Register* dst) { + switch (srcSize) { + case 2: + emit(c, andi(dst->low, src->low, 0xFFFF)); + break; + + default: abort(c); + } +} + +void moveCR2(Context* c, unsigned, lir::Constant* src, + unsigned dstSize, lir::Register* dst, unsigned promiseOffset) { + if (dstSize <= 4) { + if (src->value->resolved()) { + int32_t v = src->value->value(); + if (fitsInInt16(v)) { + emit(c, li(dst->low, v)); + } else { + emit(c, lis(dst->low, v >> 16)); + emit(c, ori(dst->low, dst->low, v)); + } + } else { + appendImmediateTask + (c, src->value, offsetPromise(c), TargetBytesPerWord, promiseOffset, false); + emit(c, lis(dst->low, 0)); + emit(c, ori(dst->low, dst->low, 0)); + } + } else { + abort(c); // todo + } +} + +void moveCR(Context* c, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Register* dst) { + moveCR2(c, srcSize, src, dstSize, dst, 0); +} + +void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if(size == 8) { + emit(con, addc(t->low, a->low, b->low)); + emit(con, adde(t->high, a->high, b->high)); + } else { + emit(con, add(t->low, a->low, b->low)); + } +} + +void addC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { + assert(con, size == TargetBytesPerWord); + + int32_t i = getValue(a); + if(i) { + emit(con, addi(t->low, b->low, lo16(i))); + if(not fitsInInt16(i)) + emit(con, addis(t->low, t->low, hi16(i) + carry16(i))); + } else { + moveRR(con, size, b, size, t); + } +} + +void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if(size == 8) { + emit(con, subfc(t->low, a->low, b->low)); + emit(con, subfe(t->high, a->high, b->high)); + } else { + emit(con, subf(t->low, a->low, b->low)); + } +} + +void subC(Context* c, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t) { + assert(c, size == TargetBytesPerWord); + + ResolvedPromise promise(- a->value->value()); + lir::Constant constant(&promise); + addC(c, size, &constant, b, t); +} + +void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + if(size == 8) { + bool useTemporaries = b->low == t->low; + int tmpLow; + int tmpHigh; + if (useTemporaries) { + tmpLow = con->client->acquireTemporary(); + tmpHigh = con->client->acquireTemporary(); + } else { + tmpLow = t->low; + tmpHigh = t->high; + } + + emit(con, mullw(tmpHigh, a->high, b->low)); + emit(con, mullw(tmpLow, a->low, b->high)); + emit(con, add(t->high, tmpHigh, tmpLow)); + emit(con, mulhwu(tmpLow, a->low, b->low)); + emit(con, add(t->high, t->high, tmpLow)); + emit(con, mullw(t->low, a->low, b->low)); + + if (useTemporaries) { + con->client->releaseTemporary(tmpLow); + con->client->releaseTemporary(tmpHigh); + } + } else { + emit(con, mullw(t->low, a->low, b->low)); + } +} + +void divideR(Context* con, unsigned size UNUSED, lir::Register* a, lir::Register* b, lir::Register* t) { + assert(con, size == 4); + emit(con, divw(t->low, b->low, a->low)); +} + +void remainderR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t) { + bool useTemporary = b->low == t->low; + lir::Register tmp(t->low); + if (useTemporary) { + tmp.low = con->client->acquireTemporary(); + } + + divideR(con, size, a, b, &tmp); + multiplyR(con, size, a, &tmp, &tmp); + subR(con, size, &tmp, b, t); + + if (useTemporary) { + con->client->releaseTemporary(tmp.low); + } +} + +int +normalize(Context* c, int offset, int index, unsigned scale, + bool* preserveIndex, bool* release) { + if (offset != 0 or scale != 1) { + lir::Register normalizedIndex + (*preserveIndex ? c->client->acquireTemporary() : index); + + if (*preserveIndex) { + *release = true; + *preserveIndex = false; + } else { + *release = false; + } + + int scaled; + + if (scale != 1) { + lir::Register unscaledIndex(index); + + ResolvedPromise scalePromise(log(scale)); + lir::Constant scaleConstant(&scalePromise); + + shiftLeftC(c, TargetBytesPerWord, &scaleConstant, + &unscaledIndex, &normalizedIndex); + + scaled = normalizedIndex.low; + } else { + scaled = index; + } + + if (offset != 0) { + lir::Register untranslatedIndex(scaled); + + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + + addC(c, TargetBytesPerWord, &offsetConstant, + &untranslatedIndex, &normalizedIndex); + } + + return normalizedIndex.low; + } else { + *release = false; + return index; + } +} + +void store(Context* c, unsigned size, lir::Register* src, + int base, int offset, int index, unsigned scale, bool preserveIndex) { + if (index != lir::NoRegister) { + bool release; + int normalized = normalize + (c, offset, index, scale, &preserveIndex, &release); + + switch (size) { + case 1: + emit(c, stbx(src->low, base, normalized)); + break; + + case 2: + emit(c, sthx(src->low, base, normalized)); + break; + + case 4: + emit(c, stwx(src->low, base, normalized)); + break; + + case 8: { + lir::Register srcHigh(src->high); + store(c, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); + store(c, 4, src, base, 4, normalized, 1, preserveIndex); + } break; + + default: abort(c); + } + + if (release) c->client->releaseTemporary(normalized); + } else { + switch (size) { + case 1: + emit(c, stb(src->low, base, offset)); + break; + + case 2: + emit(c, sth(src->low, base, offset)); + break; + + case 4: + emit(c, stw(src->low, base, offset)); + break; + + case 8: { + lir::Register srcHigh(src->high); + store(c, 4, &srcHigh, base, offset, lir::NoRegister, 1, false); + store(c, 4, src, base, offset + 4, lir::NoRegister, 1, false); + } break; + + default: abort(c); + } + } +} + +void moveRM(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst) { + assert(c, srcSize == dstSize); + + store(c, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); +} + +void moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst) { + assert(c, srcSize == TargetBytesPerWord); + assert(c, dstSize == TargetBytesPerWord); + + if (dst->index == lir::NoRegister) { + emit(c, stwu(src->low, dst->base, dst->offset)); + } else { + assert(c, dst->offset == 0); + assert(c, dst->scale == 1); + + emit(c, stwux(src->low, dst->base, dst->index)); + } +} + +void load(Context* c, unsigned srcSize, int base, int offset, int index, + unsigned scale, unsigned dstSize, lir::Register* dst, + bool preserveIndex, bool signExtend) { + if (index != lir::NoRegister) { + bool release; + int normalized = normalize + (c, offset, index, scale, &preserveIndex, &release); + + switch (srcSize) { + case 1: + emit(c, lbzx(dst->low, base, normalized)); + if (signExtend) { + emit(c, extsb(dst->low, dst->low)); + } + break; + + case 2: + if (signExtend) { + emit(c, lhax(dst->low, base, normalized)); + } else { + emit(c, lhzx(dst->low, base, normalized)); + } + break; + + case 4: + case 8: { + if (srcSize == 4 and dstSize == 8) { + load(c, 4, base, 0, normalized, 1, 4, dst, preserveIndex, false); + moveRR(c, 4, dst, 8, dst); + } else if (srcSize == 8 and dstSize == 8) { + lir::Register dstHigh(dst->high); + load(c, 4, base, 0, normalized, 1, 4, &dstHigh, preserveIndex, false); + load(c, 4, base, 4, normalized, 1, 4, dst, preserveIndex, false); + } else { + emit(c, lwzx(dst->low, base, normalized)); + } + } break; + + default: abort(c); + } + + if (release) c->client->releaseTemporary(normalized); + } else { + switch (srcSize) { + case 1: + emit(c, lbz(dst->low, base, offset)); + if (signExtend) { + emit(c, extsb(dst->low, dst->low)); + } + break; + + case 2: + if (signExtend) { + emit(c, lha(dst->low, base, offset)); + } else { + emit(c, lha(dst->low, base, offset)); + } + break; + + case 4: + emit(c, lwz(dst->low, base, offset)); + break; + + case 8: { + if (dstSize == 8) { + lir::Register dstHigh(dst->high); + load(c, 4, base, offset, lir::NoRegister, 1, 4, &dstHigh, false, false); + load(c, 4, base, offset + 4, lir::NoRegister, 1, 4, dst, false, false); + } else { + emit(c, lwzx(dst->low, base, offset)); + } + } break; + + default: abort(c); + } + } +} + +void moveMR(Context* c, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) { + load(c, srcSize, src->base, src->offset, src->index, src->scale, + dstSize, dst, true, true); +} + +void moveZMR(Context* c, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst) { + load(c, srcSize, src->base, src->offset, src->index, src->scale, + dstSize, dst, true, false); +} + +void andR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { + if (size == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); + + andR(c, 4, a, b, dst); + andR(c, 4, &ah, &bh, &dh); + } else { + emit(c, and_(dst->low, a->low, b->low)); + } +} + +void andC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { + int64_t v = a->value->value(); + + if (size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + lir::Register dh(dst->high); + + andC(c, 4, &al, b, dst); + andC(c, 4, &ah, &bh, &dh); + } else { + // bitmasks of the form regex 0*1*0* can be handled in a single + // rlwinm instruction, hence the following: + + uint32_t v32 = static_cast(v); + unsigned state = 0; + unsigned start = 0; + unsigned end = 31; + for (unsigned i = 0; i < 32; ++i) { + unsigned bit = (v32 >> i) & 1; + switch (state) { + case 0: + if (bit) { + start = i; + state = 1; + } + break; + + case 1: + if (bit == 0) { + end = i - 1; + state = 2; + } + break; + + case 2: + if (bit) { + // not in 0*1*0* form. We can only use andi(s) if either + // the topmost or bottommost 16 bits are zero. + + if ((v32 >> 16) == 0) { + emit(c, andi(dst->low, b->low, v32)); + } else if ((v32 & 0xFFFF) == 0) { + emit(c, andis(dst->low, b->low, v32 >> 16)); + } else { + bool useTemporary = b->low == dst->low; + lir::Register tmp(dst->low); + if (useTemporary) { + tmp.low = c->client->acquireTemporary(); + } + + moveCR(c, 4, a, 4, &tmp); + andR(c, 4, b, &tmp, dst); + + if (useTemporary) { + c->client->releaseTemporary(tmp.low); + } + } + return; + } + break; + } + } + + if (state) { + if (start != 0 or end != 31) { + emit(c, rlwinm(dst->low, b->low, 0, 31 - end, 31 - start)); + } else { + moveRR(c, 4, b, 4, dst); + } + } else { + emit(c, li(dst->low, 0)); + } + } +} + +void orR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { + if (size == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); + + orR(c, 4, a, b, dst); + orR(c, 4, &ah, &bh, &dh); + } else { + emit(c, or_(dst->low, a->low, b->low)); + } +} + +void orC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { + int64_t v = a->value->value(); + + if (size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + lir::Register dh(dst->high); + + orC(c, 4, &al, b, dst); + orC(c, 4, &ah, &bh, &dh); + } else { + emit(c, ori(b->low, dst->low, v)); + if (v >> 16) { + emit(c, oris(dst->low, dst->low, v >> 16)); + } + } +} + +void xorR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst) { + if (size == 8) { + lir::Register ah(a->high); + lir::Register bh(b->high); + lir::Register dh(dst->high); + + xorR(c, 4, a, b, dst); + xorR(c, 4, &ah, &bh, &dh); + } else { + emit(c, xor_(dst->low, a->low, b->low)); + } +} + +void xorC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst) { + uint64_t v = a->value->value(); + + if (size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::Register bh(b->high); + lir::Register dh(dst->high); + + xorC(c, 4, &al, b, dst); + xorC(c, 4, &ah, &bh, &dh); + } else { + if (v >> 16) { + emit(c, xoris(b->low, dst->low, v >> 16)); + emit(c, xori(dst->low, dst->low, v)); + } else { + emit(c, xori(b->low, dst->low, v)); + } + } +} + +void moveAR2(Context* c, unsigned srcSize UNUSED, lir::Address* src, + unsigned dstSize, lir::Register* dst, unsigned promiseOffset) { + assert(c, srcSize == 4 and dstSize == 4); + + lir::Memory memory(dst->low, 0, -1, 0); + + appendImmediateTask + (c, src->address, offsetPromise(c), TargetBytesPerWord, promiseOffset, true); + + emit(c, lis(dst->low, 0)); + moveMR(c, dstSize, &memory, dstSize, dst); +} + +void moveAR(Context* c, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst) { + moveAR2(c, srcSize, src, dstSize, dst, 0); +} + +void compareRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { + assert(c, aSize == 4 and bSize == 4); + + emit(c, cmpw(b->low, a->low)); +} + +void compareCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { + assert(c, aSize == 4 and bSize == 4); + + if (a->value->resolved() and fitsInInt16(a->value->value())) { + emit(c, cmpwi(b->low, a->value->value())); + } else { + lir::Register tmp(c->client->acquireTemporary()); + moveCR(c, aSize, a, bSize, &tmp); + compareRR(c, bSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } +} + +void compareCM(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b) { + assert(c, aSize == 4 and bSize == 4); + + lir::Register tmp(c->client->acquireTemporary()); + moveMR(c, bSize, b, bSize, &tmp); + compareCR(c, aSize, a, bSize, &tmp); + c->client->releaseTemporary(tmp.low); +} + +void compareRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Memory* b) { + assert(c, aSize == 4 and bSize == 4); + + lir::Register tmp(c->client->acquireTemporary()); + moveMR(c, bSize, b, bSize, &tmp); + compareRR(c, aSize, a, bSize, &tmp); + c->client->releaseTemporary(tmp.low); +} + +void compareUnsignedRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b) { + assert(c, aSize == 4 and bSize == 4); + + emit(c, cmplw(b->low, a->low)); +} + +void compareUnsignedCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b) { + assert(c, aSize == 4 and bSize == 4); + + if (a->value->resolved() and (a->value->value() >> 16) == 0) { + emit(c, cmplwi(b->low, a->value->value())); + } else { + lir::Register tmp(c->client->acquireTemporary()); + moveCR(c, aSize, a, bSize, &tmp); + compareUnsignedRR(c, bSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } +} + +int32_t +branch(Context* c, lir::TernaryOperation op) { + switch (op) { + case lir::JumpIfEqual: + return beq(0); + + case lir::JumpIfNotEqual: + return bne(0); + + case lir::JumpIfLess: + return blt(0); + + case lir::JumpIfGreater: + return bgt(0); + + case lir::JumpIfLessOrEqual: + return ble(0); + + case lir::JumpIfGreaterOrEqual: + return bge(0); + + default: + abort(c); + } +} + +void conditional(Context* c, int32_t branch, lir::Constant* target) { + appendOffsetTask(c, target->value, offsetPromise(c), true); + emit(c, branch); +} + +void branch(Context* c, lir::TernaryOperation op, lir::Constant* target) { + conditional(c, branch(c, op), target); +} + +void branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, + BinaryOperationType compareSigned, + BinaryOperationType compareUnsigned) { + compareSigned(c, 4, ah, 4, bh); + + unsigned next = 0; + + switch (op) { + case lir::JumpIfEqual: + next = c->code.length(); + emit(c, bne(0)); + + compareSigned(c, 4, al, 4, bl); + conditional(c, beq(0), target); + break; + + case lir::JumpIfNotEqual: + conditional(c, bne(0), target); + + compareSigned(c, 4, al, 4, bl); + conditional(c, bne(0), target); + break; + + case lir::JumpIfLess: + conditional(c, blt(0), target); + + next = c->code.length(); + emit(c, bgt(0)); + + compareUnsigned(c, 4, al, 4, bl); + conditional(c, blt(0), target); + break; + + case lir::JumpIfGreater: + conditional(c, bgt(0), target); + + next = c->code.length(); + emit(c, blt(0)); + + compareUnsigned(c, 4, al, 4, bl); + conditional(c, bgt(0), target); + break; + + case lir::JumpIfLessOrEqual: + conditional(c, blt(0), target); + + next = c->code.length(); + emit(c, bgt(0)); + + compareUnsigned(c, 4, al, 4, bl); + conditional(c, ble(0), target); + break; + + case lir::JumpIfGreaterOrEqual: + conditional(c, bgt(0), target); + + next = c->code.length(); + emit(c, blt(0)); + + compareUnsigned(c, 4, al, 4, bl); + conditional(c, bge(0), target); + break; + + default: + abort(c); + } + + if (next) { + updateOffset + (c->s, c->code.data + next, true, reinterpret_cast + (c->code.data + c->code.length()), 0); + } +} + +void branchRR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target) { + if (size > TargetBytesPerWord) { + lir::Register ah(a->high); + lir::Register bh(b->high); + + branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR), + CAST2(compareUnsignedRR)); + } else { + compareRR(c, size, a, size, b); + branch(c, op, target); + } +} + +void branchCR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target) { + if (size > TargetBytesPerWord) { + int64_t v = a->value->value(); + + ResolvedPromise low(v & ~static_cast(0)); + lir::Constant al(&low); + + ResolvedPromise high((v >> 32) & ~static_cast(0)); + lir::Constant ah(&high); + + lir::Register bh(b->high); + + branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR), + CAST2(compareUnsignedCR)); + } else { + compareCR(c, size, a, size, b); + branch(c, op, target); + } +} + +void branchRM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target) { + assert(c, size <= TargetBytesPerWord); + + compareRM(c, size, a, size, b); + branch(c, op, target); +} + +void branchCM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target) { + assert(c, size <= TargetBytesPerWord); + + compareCM(c, size, a, size, b); + branch(c, op, target); +} + +void moveCM(Context* c, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Memory* dst) { + switch (dstSize) { + case 8: { + lir::Constant srcHigh + (shiftMaskPromise(c, src->value, 32, 0xFFFFFFFF)); + lir::Constant srcLow + (shiftMaskPromise(c, src->value, 0, 0xFFFFFFFF)); + + lir::Memory dstLow + (dst->base, dst->offset + 4, dst->index, dst->scale); + + moveCM(c, 4, &srcLow, 4, &dstLow); + moveCM(c, 4, &srcHigh, 4, dst); + } break; + + default: + lir::Register tmp(c->client->acquireTemporary()); + moveCR(c, srcSize, src, dstSize, &tmp); + moveRM(c, dstSize, &tmp, dstSize, dst); + c->client->releaseTemporary(tmp.low); + } +} + +void negateRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Register* dst) { + assert(c, srcSize == dstSize); + + if (srcSize == 8) { + lir::Register dstHigh(dst->high); + + emit(c, subfic(dst->low, src->low, 0)); + emit(c, subfze(dst->high, src->high)); + } else { + emit(c, neg(dst->low, src->low)); + } +} + +void callR(Context* c, unsigned size UNUSED, lir::Register* target) { + assert(c, size == TargetBytesPerWord); + + emit(c, mtctr(target->low)); + emit(c, bctrl()); +} + +void callC(Context* c, unsigned size UNUSED, lir::Constant* target) { + assert(c, size == TargetBytesPerWord); + + appendOffsetTask(c, target->value, offsetPromise(c), false); + emit(c, bl(0)); +} + +void longCallC(Context* c, unsigned size UNUSED, lir::Constant* target) { + assert(c, size == TargetBytesPerWord); + + lir::Register tmp(0); + moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, 12); + callR(c, TargetBytesPerWord, &tmp); +} + +void alignedLongCallC(Context* c, unsigned size UNUSED, lir::Constant* target) { + assert(c, size == TargetBytesPerWord); + + lir::Register tmp(c->client->acquireTemporary()); + lir::Address address(appendConstantPoolEntry(c, target->value)); + moveAR2(c, TargetBytesPerWord, &address, TargetBytesPerWord, &tmp, 12); + callR(c, TargetBytesPerWord, &tmp); + c->client->releaseTemporary(tmp.low); +} + +void longJumpC(Context* c, unsigned size UNUSED, lir::Constant* target) { + assert(c, size == TargetBytesPerWord); + + lir::Register tmp(0); + moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, 12); + jumpR(c, TargetBytesPerWord, &tmp); +} + +void alignedLongJumpC(Context* c, unsigned size UNUSED, lir::Constant* target) { + assert(c, size == TargetBytesPerWord); + + lir::Register tmp(c->client->acquireTemporary()); + lir::Address address(appendConstantPoolEntry(c, target->value)); + moveAR2(c, TargetBytesPerWord, &address, TargetBytesPerWord, &tmp, 12); + jumpR(c, TargetBytesPerWord, &tmp); + c->client->releaseTemporary(tmp.low); +} + +void jumpC(Context* c, unsigned size UNUSED, lir::Constant* target) { + assert(c, size == TargetBytesPerWord); + + appendOffsetTask(c, target->value, offsetPromise(c), false); + emit(c, b(0)); +} + +void return_(Context* c) { + emit(c, blr()); +} + +void trap(Context* c) { + emit(c, isa::trap()); +} + +void memoryBarrier(Context* c) { + emit(c, sync(0)); +} + +} // namespace powerpc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/powerpc/operations.h b/src/codegen/powerpc/operations.h new file mode 100644 index 0000000000..3e16dc5292 --- /dev/null +++ b/src/codegen/powerpc/operations.h @@ -0,0 +1,197 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_OPERATIONS_H +#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_OPERATIONS_H + +#include "context.h" + +namespace avian { +namespace codegen { +namespace powerpc { + +inline void emit(Context* con, int code) { con->code.append4(vm::targetV4(code)); } +inline int newTemp(Context* con) { return con->client->acquireTemporary(); } +inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } +inline int64_t getValue(lir::Constant* c) { return c->value->value(); } + +void andC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void moveRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); + +void shiftLeftC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t); + +void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void shiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t); + +void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void unsignedShiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t); + +void jumpR(Context* c, unsigned size UNUSED, lir::Register* target); + +void swapRR(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Register* b); + +void moveRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize, lir::Register* dst); + +void moveZRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned, lir::Register* dst); + +void moveCR2(Context* c, unsigned, lir::Constant* src, + unsigned dstSize, lir::Register* dst, unsigned promiseOffset); + +void moveCR(Context* c, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Register* dst); + +void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void addC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t); + +void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void subC(Context* c, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t); + +void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +void divideR(Context* con, unsigned size UNUSED, lir::Register* a, lir::Register* b, lir::Register* t); + +void remainderR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t); + +int +normalize(Context* c, int offset, int index, unsigned scale, + bool* preserveIndex, bool* release); + +void store(Context* c, unsigned size, lir::Register* src, + int base, int offset, int index, unsigned scale, bool preserveIndex); + +void moveRM(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst); + +void moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, lir::Register* src, + unsigned dstSize UNUSED, lir::Memory* dst); + +void load(Context* c, unsigned srcSize, int base, int offset, int index, + unsigned scale, unsigned dstSize, lir::Register* dst, + bool preserveIndex, bool signExtend); + +void moveMR(Context* c, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst); + +void moveZMR(Context* c, unsigned srcSize, lir::Memory* src, + unsigned dstSize, lir::Register* dst); + +void andR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst); + +void andC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void orR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst); + +void orC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void xorR(Context* c, unsigned size, lir::Register* a, + lir::Register* b, lir::Register* dst); + +void xorC(Context* c, unsigned size, lir::Constant* a, + lir::Register* b, lir::Register* dst); + +void moveAR2(Context* c, unsigned srcSize UNUSED, lir::Address* src, + unsigned dstSize, lir::Register* dst, unsigned promiseOffset); + +void moveAR(Context* c, unsigned srcSize, lir::Address* src, + unsigned dstSize, lir::Register* dst); + +void compareRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void compareCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +void compareCM(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Memory* b); + +void compareRM(Context* c, unsigned aSize, lir::Register* a, + unsigned bSize, lir::Memory* b); + +void compareUnsignedRR(Context* c, unsigned aSize UNUSED, lir::Register* a, + unsigned bSize UNUSED, lir::Register* b); + +void compareUnsignedCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + +int32_t branch(Context* c, lir::TernaryOperation op); + +void conditional(Context* c, int32_t branch, lir::Constant* target); + +void branch(Context* c, lir::TernaryOperation op, lir::Constant* target); + +void branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, + lir::Operand* ah, lir::Operand* bl, + lir::Operand* bh, lir::Constant* target, + BinaryOperationType compareSigned, + BinaryOperationType compareUnsigned); + +void branchRR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Register* b, + lir::Constant* target); + +void branchCR(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Register* b, + lir::Constant* target); + +void branchRM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Register* a, lir::Memory* b, + lir::Constant* target); + +void branchCM(Context* c, lir::TernaryOperation op, unsigned size, + lir::Constant* a, lir::Memory* b, + lir::Constant* target); + +void moveCM(Context* c, unsigned srcSize, lir::Constant* src, + unsigned dstSize, lir::Memory* dst); + +void negateRR(Context* c, unsigned srcSize, lir::Register* src, + unsigned dstSize UNUSED, lir::Register* dst); + +void callR(Context* c, unsigned size UNUSED, lir::Register* target); + +void callC(Context* c, unsigned size UNUSED, lir::Constant* target); + +void longCallC(Context* c, unsigned size UNUSED, lir::Constant* target); + +void alignedLongCallC(Context* c, unsigned size UNUSED, lir::Constant* target); + +void longJumpC(Context* c, unsigned size UNUSED, lir::Constant* target); + +void alignedLongJumpC(Context* c, unsigned size UNUSED, lir::Constant* target); + +void jumpC(Context* c, unsigned size UNUSED, lir::Constant* target); + +void return_(Context* c); + +void trap(Context* c); + +void memoryBarrier(Context* c); + +} // namespace powerpc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_OPERATIONS_H diff --git a/src/codegen/powerpc/registers.h b/src/codegen/powerpc/registers.h new file mode 100644 index 0000000000..ce395a373e --- /dev/null +++ b/src/codegen/powerpc/registers.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_REGISTERS_H +#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_REGISTERS_H + +namespace avian { +namespace codegen { +namespace powerpc { + + +} // namespace powerpc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_REGISTERS_H From 3d1ae1d517c3b1b11b7be4b4a634ea8e3a4a54e8 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sat, 23 Feb 2013 22:00:15 -0700 Subject: [PATCH 293/378] fix include-what-you-use violations in x86 assembler --- src/codegen/arm/assembler.cpp | 6 ++--- src/codegen/powerpc/assembler.cpp | 6 ----- src/codegen/powerpc/fixup.cpp | 2 +- src/codegen/x86/assembler.cpp | 37 ++++++++++++++++++++----------- src/codegen/x86/block.cpp | 5 +++-- src/codegen/x86/context.cpp | 7 ++++-- src/codegen/x86/context.h | 7 +++++- src/codegen/x86/detect.cpp | 5 +++-- src/codegen/x86/encode.cpp | 15 +++++++++---- src/codegen/x86/encode.h | 12 ++++++++-- src/codegen/x86/fixup.cpp | 20 ++++++++++++----- src/codegen/x86/fixup.h | 8 ++++--- src/codegen/x86/multimethod.cpp | 8 ++++--- src/codegen/x86/multimethod.h | 4 ++++ src/codegen/x86/operations.cpp | 26 ++++++++++++++++------ src/codegen/x86/operations.h | 6 +++++ src/codegen/x86/padding.cpp | 9 ++++---- src/codegen/x86/padding.h | 1 + 18 files changed, 123 insertions(+), 61 deletions(-) diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index ac00fdb5cb..511f7ccc32 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -60,11 +60,9 @@ const unsigned StackAlignmentInBytes = 8; const unsigned StackAlignmentInWords = StackAlignmentInBytes / TargetBytesPerWord; -void -resolve(MyBlock*); +void resolve(MyBlock*); -unsigned -padding(MyBlock*, unsigned); +unsigned padding(MyBlock*, unsigned); class ConstantPoolEntry; diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 39405769bf..cda4fdbc96 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -178,12 +178,6 @@ resolve(MyBlock* b) using namespace isa; -inline void -write4(uint8_t* dst, uint32_t v) -{ - memcpy(dst, &v, 4); -} - // END OPERATION COMPILERS unsigned diff --git a/src/codegen/powerpc/fixup.cpp b/src/codegen/powerpc/fixup.cpp index eb8a4aac6d..06075c00e6 100644 --- a/src/codegen/powerpc/fixup.cpp +++ b/src/codegen/powerpc/fixup.cpp @@ -21,7 +21,7 @@ using namespace isa; unsigned padding(MyBlock*, unsigned); -inline int ha16(int32_t i); +int ha16(int32_t i); bool bounded(int right, int left, int32_t v) { return ((v << left) >> left) == v and ((v >> right) << right) == v; diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 79b5377959..a568430f91 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -8,25 +8,36 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include +#include +#include + #include "environment.h" #include "target.h" #include "alloc-vector.h" - -#include -#include - -#include "codegen/x86/context.h" -#include "codegen/x86/block.h" -#include "codegen/x86/fixup.h" -#include "codegen/x86/padding.h" -#include "codegen/x86/registers.h" -#include "codegen/x86/encode.h" -#include "codegen/x86/operations.h" -#include "codegen/x86/detect.h" -#include "codegen/x86/multimethod.h" +#include "common.h" +#include "allocator.h" +#include "zone.h" #include #include +#include + +#include +#include +#include +#include + +#include + +#include "context.h" +#include "block.h" +#include "fixup.h" +#include "padding.h" +#include "registers.h" +#include "operations.h" +#include "detect.h" +#include "multimethod.h" #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) diff --git a/src/codegen/x86/block.cpp b/src/codegen/x86/block.cpp index 97bac8dbf1..5c2b125283 100644 --- a/src/codegen/x86/block.cpp +++ b/src/codegen/x86/block.cpp @@ -8,8 +8,9 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/x86/block.h" -#include "common.h" +#include "block.h" + +#include namespace avian { namespace codegen { diff --git a/src/codegen/x86/context.cpp b/src/codegen/x86/context.cpp index 4c996f2b75..88de52a2d1 100644 --- a/src/codegen/x86/context.cpp +++ b/src/codegen/x86/context.cpp @@ -8,8 +8,11 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/x86/context.h" -#include "codegen/x86/block.h" +#include "allocator.h" +#include "zone.h" + +#include "context.h" +#include "block.h" namespace avian { namespace codegen { diff --git a/src/codegen/x86/context.h b/src/codegen/x86/context.h index d85eb58758..ce1a3c1e70 100644 --- a/src/codegen/x86/context.h +++ b/src/codegen/x86/context.h @@ -15,9 +15,14 @@ #define CAST2(x) reinterpret_cast(x) #define CAST_BRANCH(x) reinterpret_cast(x) +#include + +#include "alloc-vector.h" + #include #include -#include "alloc-vector.h" + +#include namespace vm { class System; diff --git a/src/codegen/x86/detect.cpp b/src/codegen/x86/detect.cpp index eaf6af54ac..9f154aff0a 100644 --- a/src/codegen/x86/detect.cpp +++ b/src/codegen/x86/detect.cpp @@ -9,8 +9,9 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/x86/context.h" -#include "codegen/x86/block.h" +#include "target.h" + +#include "context.h" namespace avian { namespace codegen { diff --git a/src/codegen/x86/encode.cpp b/src/codegen/x86/encode.cpp index 8293550be6..730d71fdc9 100644 --- a/src/codegen/x86/encode.cpp +++ b/src/codegen/x86/encode.cpp @@ -9,11 +9,18 @@ details. */ #include "target.h" +#include "alloc-vector.h" -#include "codegen/x86/context.h" -#include "codegen/x86/encode.h" -#include "codegen/x86/registers.h" -#include "codegen/x86/fixup.h" +#include +#include + +#include +#include + +#include "context.h" +#include "encode.h" +#include "registers.h" +#include "fixup.h" using namespace avian::util; diff --git a/src/codegen/x86/encode.h b/src/codegen/x86/encode.h index e8fb3f9d7f..853d7324e4 100644 --- a/src/codegen/x86/encode.h +++ b/src/codegen/x86/encode.h @@ -11,12 +11,20 @@ #ifndef AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H #define AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H -#include -#include "codegen/x86/registers.h" +#include + +#include "common.h" + +#include + +#include "registers.h" namespace avian { namespace codegen { namespace x86 { + +class Context; + void maybeRex(Context* c, unsigned size, int a, int index, int base, bool always); void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Register* b); diff --git a/src/codegen/x86/fixup.cpp b/src/codegen/x86/fixup.cpp index d914a22bdb..5e85d7c062 100644 --- a/src/codegen/x86/fixup.cpp +++ b/src/codegen/x86/fixup.cpp @@ -8,12 +8,20 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include - -#include "codegen/x86/context.h" -#include "codegen/x86/fixup.h" -#include "codegen/x86/padding.h" -#include "codegen/x86/block.h" +#include + +#include "allocator.h" +#include "alloc-vector.h" +#include "common.h" +#include "zone.h" + +#include +#include + +#include "context.h" +#include "fixup.h" +#include "padding.h" +#include "block.h" namespace avian { namespace codegen { diff --git a/src/codegen/x86/fixup.h b/src/codegen/x86/fixup.h index 2bf8ff3481..78f77b3044 100644 --- a/src/codegen/x86/fixup.h +++ b/src/codegen/x86/fixup.h @@ -11,17 +11,19 @@ #ifndef AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H #define AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H +#include + +#include + namespace vm { class System; } namespace avian { namespace codegen { - -class Promise; - namespace x86 { +class Context; class MyBlock; class AlignmentPadding; diff --git a/src/codegen/x86/multimethod.cpp b/src/codegen/x86/multimethod.cpp index 5c4663c7f9..f0ad4621b2 100644 --- a/src/codegen/x86/multimethod.cpp +++ b/src/codegen/x86/multimethod.cpp @@ -10,11 +10,13 @@ #include "common.h" +#include + #include -#include "codegen/x86/context.h" -#include "codegen/x86/multimethod.h" -#include "codegen/x86/operations.h" +#include "context.h" +#include "multimethod.h" +#include "operations.h" namespace avian { namespace codegen { diff --git a/src/codegen/x86/multimethod.h b/src/codegen/x86/multimethod.h index 5a73850f29..6ede17f17a 100644 --- a/src/codegen/x86/multimethod.h +++ b/src/codegen/x86/multimethod.h @@ -11,6 +11,10 @@ #ifndef AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H #define AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H +#include "common.h" + +#include + namespace avian { namespace codegen { namespace x86 { diff --git a/src/codegen/x86/operations.cpp b/src/codegen/x86/operations.cpp index 56eb77c127..60d33adedc 100644 --- a/src/codegen/x86/operations.cpp +++ b/src/codegen/x86/operations.cpp @@ -8,13 +8,25 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "codegen/x86/context.h" -#include "codegen/x86/encode.h" -#include "codegen/x86/registers.h" -#include "codegen/x86/detect.h" -#include "codegen/x86/operations.h" -#include "codegen/x86/padding.h" -#include "codegen/x86/fixup.h" +#include + +#include "target.h" +#include "alloc-vector.h" +#include "allocator.h" +#include "zone.h" + +#include + +#include +#include + +#include "context.h" +#include "encode.h" +#include "registers.h" +#include "detect.h" +#include "operations.h" +#include "padding.h" +#include "fixup.h" using namespace avian::util; diff --git a/src/codegen/x86/operations.h b/src/codegen/x86/operations.h index 52d0d8dc0f..2b5081591c 100644 --- a/src/codegen/x86/operations.h +++ b/src/codegen/x86/operations.h @@ -11,6 +11,12 @@ #ifndef AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H #define AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H +#include "common.h" + +#include + +#include "context.h" + namespace avian { namespace codegen { namespace x86 { diff --git a/src/codegen/x86/padding.cpp b/src/codegen/x86/padding.cpp index 7873145bb4..e31e8626e9 100644 --- a/src/codegen/x86/padding.cpp +++ b/src/codegen/x86/padding.cpp @@ -8,12 +8,11 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include +#include "alloc-vector.h" -#include "codegen/x86/context.h" -#include "codegen/x86/fixup.h" -#include "codegen/x86/padding.h" -#include "codegen/x86/block.h" +#include "context.h" +#include "padding.h" +#include "block.h" namespace avian { namespace codegen { diff --git a/src/codegen/x86/padding.h b/src/codegen/x86/padding.h index 32fc358142..ef9f834f18 100644 --- a/src/codegen/x86/padding.h +++ b/src/codegen/x86/padding.h @@ -15,6 +15,7 @@ namespace avian { namespace codegen { namespace x86 { +class Context; class AlignmentPadding { public: From 56625b89d893228e96072842193bd0e66e323a70 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sat, 23 Feb 2013 22:47:52 -0700 Subject: [PATCH 294/378] group x86, arm, and powerpc target directories into 'target' --- makefile | 12 ++++++------ src/codegen/{ => target}/arm/assembler.cpp | 0 src/codegen/{ => target}/arm/block.cpp | 0 src/codegen/{ => target}/arm/block.h | 0 src/codegen/{ => target}/arm/context.cpp | 0 src/codegen/{ => target}/arm/context.h | 0 src/codegen/{ => target}/arm/encode.h | 0 src/codegen/{ => target}/arm/fixup.cpp | 0 src/codegen/{ => target}/arm/fixup.h | 0 src/codegen/{ => target}/arm/multimethod.cpp | 0 src/codegen/{ => target}/arm/multimethod.h | 0 src/codegen/{ => target}/arm/operations.cpp | 0 src/codegen/{ => target}/arm/operations.h | 0 src/codegen/{ => target}/arm/registers.h | 0 src/codegen/{ => target}/powerpc/assembler.cpp | 0 src/codegen/{ => target}/powerpc/block.cpp | 0 src/codegen/{ => target}/powerpc/block.h | 0 src/codegen/{ => target}/powerpc/context.cpp | 0 src/codegen/{ => target}/powerpc/context.h | 0 src/codegen/{ => target}/powerpc/encode.h | 0 src/codegen/{ => target}/powerpc/fixup.cpp | 0 src/codegen/{ => target}/powerpc/fixup.h | 0 src/codegen/{ => target}/powerpc/multimethod.cpp | 0 src/codegen/{ => target}/powerpc/multimethod.h | 0 src/codegen/{ => target}/powerpc/operations.cpp | 0 src/codegen/{ => target}/powerpc/operations.h | 0 src/codegen/{ => target}/powerpc/registers.h | 0 src/codegen/{ => target}/x86/assembler.cpp | 0 src/codegen/{ => target}/x86/block.cpp | 0 src/codegen/{ => target}/x86/block.h | 0 src/codegen/{ => target}/x86/context.cpp | 0 src/codegen/{ => target}/x86/context.h | 0 src/codegen/{ => target}/x86/detect.cpp | 0 src/codegen/{ => target}/x86/detect.h | 0 src/codegen/{ => target}/x86/encode.cpp | 0 src/codegen/{ => target}/x86/encode.h | 0 src/codegen/{ => target}/x86/fixup.cpp | 0 src/codegen/{ => target}/x86/fixup.h | 0 src/codegen/{ => target}/x86/multimethod.cpp | 0 src/codegen/{ => target}/x86/multimethod.h | 0 src/codegen/{ => target}/x86/operations.cpp | 0 src/codegen/{ => target}/x86/operations.h | 0 src/codegen/{ => target}/x86/padding.cpp | 0 src/codegen/{ => target}/x86/padding.h | 0 src/codegen/{ => target}/x86/registers.h | 0 45 files changed, 6 insertions(+), 6 deletions(-) rename src/codegen/{ => target}/arm/assembler.cpp (100%) rename src/codegen/{ => target}/arm/block.cpp (100%) rename src/codegen/{ => target}/arm/block.h (100%) rename src/codegen/{ => target}/arm/context.cpp (100%) rename src/codegen/{ => target}/arm/context.h (100%) rename src/codegen/{ => target}/arm/encode.h (100%) rename src/codegen/{ => target}/arm/fixup.cpp (100%) rename src/codegen/{ => target}/arm/fixup.h (100%) rename src/codegen/{ => target}/arm/multimethod.cpp (100%) rename src/codegen/{ => target}/arm/multimethod.h (100%) rename src/codegen/{ => target}/arm/operations.cpp (100%) rename src/codegen/{ => target}/arm/operations.h (100%) rename src/codegen/{ => target}/arm/registers.h (100%) rename src/codegen/{ => target}/powerpc/assembler.cpp (100%) rename src/codegen/{ => target}/powerpc/block.cpp (100%) rename src/codegen/{ => target}/powerpc/block.h (100%) rename src/codegen/{ => target}/powerpc/context.cpp (100%) rename src/codegen/{ => target}/powerpc/context.h (100%) rename src/codegen/{ => target}/powerpc/encode.h (100%) rename src/codegen/{ => target}/powerpc/fixup.cpp (100%) rename src/codegen/{ => target}/powerpc/fixup.h (100%) rename src/codegen/{ => target}/powerpc/multimethod.cpp (100%) rename src/codegen/{ => target}/powerpc/multimethod.h (100%) rename src/codegen/{ => target}/powerpc/operations.cpp (100%) rename src/codegen/{ => target}/powerpc/operations.h (100%) rename src/codegen/{ => target}/powerpc/registers.h (100%) rename src/codegen/{ => target}/x86/assembler.cpp (100%) rename src/codegen/{ => target}/x86/block.cpp (100%) rename src/codegen/{ => target}/x86/block.h (100%) rename src/codegen/{ => target}/x86/context.cpp (100%) rename src/codegen/{ => target}/x86/context.h (100%) rename src/codegen/{ => target}/x86/detect.cpp (100%) rename src/codegen/{ => target}/x86/detect.h (100%) rename src/codegen/{ => target}/x86/encode.cpp (100%) rename src/codegen/{ => target}/x86/encode.h (100%) rename src/codegen/{ => target}/x86/fixup.cpp (100%) rename src/codegen/{ => target}/x86/fixup.h (100%) rename src/codegen/{ => target}/x86/multimethod.cpp (100%) rename src/codegen/{ => target}/x86/multimethod.h (100%) rename src/codegen/{ => target}/x86/operations.cpp (100%) rename src/codegen/{ => target}/x86/operations.h (100%) rename src/codegen/{ => target}/x86/padding.cpp (100%) rename src/codegen/{ => target}/x86/padding.h (100%) rename src/codegen/{ => target}/x86/registers.h (100%) diff --git a/makefile b/makefile index 05fe57adba..5029fe0b36 100755 --- a/makefile +++ b/makefile @@ -978,17 +978,17 @@ compiler-sources = \ compiler-objects = $(call cpp-objects,$(compiler-sources),$(src),$(build)) $(compiler-objects): $(wildcard $(src)/codegen/compiler/*.h) $(vm-depends) -x86-assembler-sources = $(wildcard $(src)/codegen/x86/*.cpp) +x86-assembler-sources = $(wildcard $(src)/codegen/target/x86/*.cpp) x86-assembler-objects = $(call cpp-objects,$(x86-assembler-sources),$(src),$(build)) -$(x86-assembler-objects): $(wildcard $(src)/codegen/x86/*.h) $(vm-depends) +$(x86-assembler-objects): $(wildcard $(src)/codegen/target/x86/*.h) $(vm-depends) -arm-assembler-sources = $(wildcard $(src)/codegen/arm/*.cpp) +arm-assembler-sources = $(wildcard $(src)/codegen/target/arm/*.cpp) arm-assembler-objects = $(call cpp-objects,$(arm-assembler-sources),$(src),$(build)) -$(arm-assembler-objects): $(wildcard $(src)/codegen/arm/*.h) $(vm-depends) +$(arm-assembler-objects): $(wildcard $(src)/codegen/target/arm/*.h) $(vm-depends) -powerpc-assembler-sources = $(wildcard $(src)/codegen/powerpc/*.cpp) +powerpc-assembler-sources = $(wildcard $(src)/codegen/target/powerpc/*.cpp) powerpc-assembler-objects = $(call cpp-objects,$(powerpc-assembler-sources),$(src),$(build)) -$(powerpc-assembler-objects): $(wildcard $(src)/codegen/powerpc/*.h) $(vm-depends) +$(powerpc-assembler-objects): $(wildcard $(src)/codegen/target/powerpc/*.h) $(vm-depends) all-assembler-sources = \ $(x86-assembler-sources) \ diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/target/arm/assembler.cpp similarity index 100% rename from src/codegen/arm/assembler.cpp rename to src/codegen/target/arm/assembler.cpp diff --git a/src/codegen/arm/block.cpp b/src/codegen/target/arm/block.cpp similarity index 100% rename from src/codegen/arm/block.cpp rename to src/codegen/target/arm/block.cpp diff --git a/src/codegen/arm/block.h b/src/codegen/target/arm/block.h similarity index 100% rename from src/codegen/arm/block.h rename to src/codegen/target/arm/block.h diff --git a/src/codegen/arm/context.cpp b/src/codegen/target/arm/context.cpp similarity index 100% rename from src/codegen/arm/context.cpp rename to src/codegen/target/arm/context.cpp diff --git a/src/codegen/arm/context.h b/src/codegen/target/arm/context.h similarity index 100% rename from src/codegen/arm/context.h rename to src/codegen/target/arm/context.h diff --git a/src/codegen/arm/encode.h b/src/codegen/target/arm/encode.h similarity index 100% rename from src/codegen/arm/encode.h rename to src/codegen/target/arm/encode.h diff --git a/src/codegen/arm/fixup.cpp b/src/codegen/target/arm/fixup.cpp similarity index 100% rename from src/codegen/arm/fixup.cpp rename to src/codegen/target/arm/fixup.cpp diff --git a/src/codegen/arm/fixup.h b/src/codegen/target/arm/fixup.h similarity index 100% rename from src/codegen/arm/fixup.h rename to src/codegen/target/arm/fixup.h diff --git a/src/codegen/arm/multimethod.cpp b/src/codegen/target/arm/multimethod.cpp similarity index 100% rename from src/codegen/arm/multimethod.cpp rename to src/codegen/target/arm/multimethod.cpp diff --git a/src/codegen/arm/multimethod.h b/src/codegen/target/arm/multimethod.h similarity index 100% rename from src/codegen/arm/multimethod.h rename to src/codegen/target/arm/multimethod.h diff --git a/src/codegen/arm/operations.cpp b/src/codegen/target/arm/operations.cpp similarity index 100% rename from src/codegen/arm/operations.cpp rename to src/codegen/target/arm/operations.cpp diff --git a/src/codegen/arm/operations.h b/src/codegen/target/arm/operations.h similarity index 100% rename from src/codegen/arm/operations.h rename to src/codegen/target/arm/operations.h diff --git a/src/codegen/arm/registers.h b/src/codegen/target/arm/registers.h similarity index 100% rename from src/codegen/arm/registers.h rename to src/codegen/target/arm/registers.h diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/target/powerpc/assembler.cpp similarity index 100% rename from src/codegen/powerpc/assembler.cpp rename to src/codegen/target/powerpc/assembler.cpp diff --git a/src/codegen/powerpc/block.cpp b/src/codegen/target/powerpc/block.cpp similarity index 100% rename from src/codegen/powerpc/block.cpp rename to src/codegen/target/powerpc/block.cpp diff --git a/src/codegen/powerpc/block.h b/src/codegen/target/powerpc/block.h similarity index 100% rename from src/codegen/powerpc/block.h rename to src/codegen/target/powerpc/block.h diff --git a/src/codegen/powerpc/context.cpp b/src/codegen/target/powerpc/context.cpp similarity index 100% rename from src/codegen/powerpc/context.cpp rename to src/codegen/target/powerpc/context.cpp diff --git a/src/codegen/powerpc/context.h b/src/codegen/target/powerpc/context.h similarity index 100% rename from src/codegen/powerpc/context.h rename to src/codegen/target/powerpc/context.h diff --git a/src/codegen/powerpc/encode.h b/src/codegen/target/powerpc/encode.h similarity index 100% rename from src/codegen/powerpc/encode.h rename to src/codegen/target/powerpc/encode.h diff --git a/src/codegen/powerpc/fixup.cpp b/src/codegen/target/powerpc/fixup.cpp similarity index 100% rename from src/codegen/powerpc/fixup.cpp rename to src/codegen/target/powerpc/fixup.cpp diff --git a/src/codegen/powerpc/fixup.h b/src/codegen/target/powerpc/fixup.h similarity index 100% rename from src/codegen/powerpc/fixup.h rename to src/codegen/target/powerpc/fixup.h diff --git a/src/codegen/powerpc/multimethod.cpp b/src/codegen/target/powerpc/multimethod.cpp similarity index 100% rename from src/codegen/powerpc/multimethod.cpp rename to src/codegen/target/powerpc/multimethod.cpp diff --git a/src/codegen/powerpc/multimethod.h b/src/codegen/target/powerpc/multimethod.h similarity index 100% rename from src/codegen/powerpc/multimethod.h rename to src/codegen/target/powerpc/multimethod.h diff --git a/src/codegen/powerpc/operations.cpp b/src/codegen/target/powerpc/operations.cpp similarity index 100% rename from src/codegen/powerpc/operations.cpp rename to src/codegen/target/powerpc/operations.cpp diff --git a/src/codegen/powerpc/operations.h b/src/codegen/target/powerpc/operations.h similarity index 100% rename from src/codegen/powerpc/operations.h rename to src/codegen/target/powerpc/operations.h diff --git a/src/codegen/powerpc/registers.h b/src/codegen/target/powerpc/registers.h similarity index 100% rename from src/codegen/powerpc/registers.h rename to src/codegen/target/powerpc/registers.h diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp similarity index 100% rename from src/codegen/x86/assembler.cpp rename to src/codegen/target/x86/assembler.cpp diff --git a/src/codegen/x86/block.cpp b/src/codegen/target/x86/block.cpp similarity index 100% rename from src/codegen/x86/block.cpp rename to src/codegen/target/x86/block.cpp diff --git a/src/codegen/x86/block.h b/src/codegen/target/x86/block.h similarity index 100% rename from src/codegen/x86/block.h rename to src/codegen/target/x86/block.h diff --git a/src/codegen/x86/context.cpp b/src/codegen/target/x86/context.cpp similarity index 100% rename from src/codegen/x86/context.cpp rename to src/codegen/target/x86/context.cpp diff --git a/src/codegen/x86/context.h b/src/codegen/target/x86/context.h similarity index 100% rename from src/codegen/x86/context.h rename to src/codegen/target/x86/context.h diff --git a/src/codegen/x86/detect.cpp b/src/codegen/target/x86/detect.cpp similarity index 100% rename from src/codegen/x86/detect.cpp rename to src/codegen/target/x86/detect.cpp diff --git a/src/codegen/x86/detect.h b/src/codegen/target/x86/detect.h similarity index 100% rename from src/codegen/x86/detect.h rename to src/codegen/target/x86/detect.h diff --git a/src/codegen/x86/encode.cpp b/src/codegen/target/x86/encode.cpp similarity index 100% rename from src/codegen/x86/encode.cpp rename to src/codegen/target/x86/encode.cpp diff --git a/src/codegen/x86/encode.h b/src/codegen/target/x86/encode.h similarity index 100% rename from src/codegen/x86/encode.h rename to src/codegen/target/x86/encode.h diff --git a/src/codegen/x86/fixup.cpp b/src/codegen/target/x86/fixup.cpp similarity index 100% rename from src/codegen/x86/fixup.cpp rename to src/codegen/target/x86/fixup.cpp diff --git a/src/codegen/x86/fixup.h b/src/codegen/target/x86/fixup.h similarity index 100% rename from src/codegen/x86/fixup.h rename to src/codegen/target/x86/fixup.h diff --git a/src/codegen/x86/multimethod.cpp b/src/codegen/target/x86/multimethod.cpp similarity index 100% rename from src/codegen/x86/multimethod.cpp rename to src/codegen/target/x86/multimethod.cpp diff --git a/src/codegen/x86/multimethod.h b/src/codegen/target/x86/multimethod.h similarity index 100% rename from src/codegen/x86/multimethod.h rename to src/codegen/target/x86/multimethod.h diff --git a/src/codegen/x86/operations.cpp b/src/codegen/target/x86/operations.cpp similarity index 100% rename from src/codegen/x86/operations.cpp rename to src/codegen/target/x86/operations.cpp diff --git a/src/codegen/x86/operations.h b/src/codegen/target/x86/operations.h similarity index 100% rename from src/codegen/x86/operations.h rename to src/codegen/target/x86/operations.h diff --git a/src/codegen/x86/padding.cpp b/src/codegen/target/x86/padding.cpp similarity index 100% rename from src/codegen/x86/padding.cpp rename to src/codegen/target/x86/padding.cpp diff --git a/src/codegen/x86/padding.h b/src/codegen/target/x86/padding.h similarity index 100% rename from src/codegen/x86/padding.h rename to src/codegen/target/x86/padding.h diff --git a/src/codegen/x86/registers.h b/src/codegen/target/x86/registers.h similarity index 100% rename from src/codegen/x86/registers.h rename to src/codegen/target/x86/registers.h From 4c8b593539dd927593a43f1e92f521addf33c8c9 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sat, 23 Feb 2013 23:03:01 -0700 Subject: [PATCH 295/378] break Architecture out of Assembler --- include/avian/vm/codegen/architecture.h | 137 +++++++++++++++++++++++ include/avian/vm/codegen/assembler.h | 110 +----------------- include/avian/vm/codegen/targets.h | 14 ++- src/codegen/compiler.cpp | 1 + src/codegen/compiler/context.cpp | 2 + src/codegen/compiler/context.h | 2 +- src/codegen/compiler/frame.cpp | 2 + src/codegen/compiler/site.h | 2 + src/codegen/target/arm/assembler.cpp | 5 +- src/codegen/target/powerpc/assembler.cpp | 5 +- src/codegen/target/x86/assembler.cpp | 5 +- src/codegen/targets.cpp | 4 +- src/compile.cpp | 3 +- src/tools/audit-codegen/main.cpp | 2 +- unittest/codegen/assembler-test.cpp | 3 +- 15 files changed, 172 insertions(+), 125 deletions(-) create mode 100644 include/avian/vm/codegen/architecture.h diff --git a/include/avian/vm/codegen/architecture.h b/include/avian/vm/codegen/architecture.h new file mode 100644 index 0000000000..07c3fc5e35 --- /dev/null +++ b/include/avian/vm/codegen/architecture.h @@ -0,0 +1,137 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ARCHITECTURE_H +#define AVIAN_CODEGEN_ARCHITECTURE_H + +namespace vm { +class Allocator; +class Zone; +} + +namespace avian { +namespace codegen { + +class Assembler; + +class RegisterFile; + +class OperandMask { +public: + uint8_t typeMask; + uint64_t registerMask; + + OperandMask(uint8_t typeMask, uint64_t registerMask): + typeMask(typeMask), + registerMask(registerMask) + { } + + OperandMask(): + typeMask(~0), + registerMask(~static_cast(0)) + { } +}; + +class Architecture { +public: +virtual unsigned floatRegisterSize() = 0; + +virtual const RegisterFile* registerFile() = 0; + +virtual int scratch() = 0; +virtual int stack() = 0; +virtual int thread() = 0; +virtual int returnLow() = 0; +virtual int returnHigh() = 0; +virtual int virtualCallTarget() = 0; +virtual int virtualCallIndex() = 0; + +virtual bool bigEndian() = 0; + +virtual uintptr_t maximumImmediateJump() = 0; + +virtual bool alwaysCondensed(lir::BinaryOperation op) = 0; +virtual bool alwaysCondensed(lir::TernaryOperation op) = 0; + +virtual bool reserved(int register_) = 0; + +virtual unsigned frameFootprint(unsigned footprint) = 0; +virtual unsigned argumentFootprint(unsigned footprint) = 0; +virtual bool argumentAlignment() = 0; +virtual bool argumentRegisterAlignment() = 0; +virtual unsigned argumentRegisterCount() = 0; +virtual int argumentRegister(unsigned index) = 0; + +virtual bool hasLinkRegister() = 0; + +virtual unsigned stackAlignmentInWords() = 0; + +virtual bool matchCall(void* returnAddress, void* target) = 0; + +virtual void updateCall(lir::UnaryOperation op, void* returnAddress, + void* newTarget) = 0; + +virtual void setConstant(void* dst, uint64_t constant) = 0; + +virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; + +virtual void nextFrame(void* start, unsigned size, unsigned footprint, + void* link, bool mostRecent, + unsigned targetParameterFootprint, void** ip, + void** stack) = 0; +virtual void* frameIp(void* stack) = 0; +virtual unsigned frameHeaderSize() = 0; +virtual unsigned frameReturnAddressSize() = 0; +virtual unsigned frameFooterSize() = 0; +virtual int returnAddressOffset() = 0; +virtual int framePointerOffset() = 0; + +virtual void plan +(lir::UnaryOperation op, + unsigned aSize, OperandMask& aMask, + bool* thunk) = 0; + +virtual void planSource +(lir::BinaryOperation op, + unsigned aSize, OperandMask& aMask, + unsigned bSize, bool* thunk) = 0; + +virtual void planDestination +(lir::BinaryOperation op, + unsigned aSize, const OperandMask& aMask, + unsigned bSize, OperandMask& bMask) = 0; + +virtual void planMove +(unsigned size, OperandMask& src, + OperandMask& tmp, + const OperandMask& dst) = 0; + +virtual void planSource +(lir::TernaryOperation op, + unsigned aSize, OperandMask& aMask, + unsigned bSize, OperandMask& bMask, + unsigned cSize, bool* thunk) = 0; + +virtual void planDestination +(lir::TernaryOperation op, + unsigned aSize, const OperandMask& aMask, + unsigned bSize, const OperandMask& bMask, + unsigned cSize, OperandMask& cMask) = 0; + +virtual Assembler* makeAssembler(vm::Allocator*, vm::Zone*) = 0; + +virtual void acquire() = 0; +virtual void release() = 0; +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ARCHITECTURE_H \ No newline at end of file diff --git a/include/avian/vm/codegen/assembler.h b/include/avian/vm/codegen/assembler.h index 6f370cbe3c..8c18176892 100644 --- a/include/avian/vm/codegen/assembler.h +++ b/include/avian/vm/codegen/assembler.h @@ -20,7 +20,7 @@ namespace avian { namespace codegen { -class RegisterFile; +class Architecture; class OperandInfo { public: @@ -35,22 +35,6 @@ public: { } }; -class OperandMask { -public: - uint8_t typeMask; - uint64_t registerMask; - - OperandMask(uint8_t typeMask, uint64_t registerMask): - typeMask(typeMask), - registerMask(registerMask) - { } - - OperandMask(): - typeMask(~0), - registerMask(~static_cast(0)) - { } -}; - #ifdef AVIAN_TAILS const bool TailCalls = true; #else @@ -80,98 +64,6 @@ class Assembler { virtual unsigned resolve(unsigned start, Block* next) = 0; }; - class Architecture { - public: - virtual unsigned floatRegisterSize() = 0; - - virtual const RegisterFile* registerFile() = 0; - - virtual int scratch() = 0; - virtual int stack() = 0; - virtual int thread() = 0; - virtual int returnLow() = 0; - virtual int returnHigh() = 0; - virtual int virtualCallTarget() = 0; - virtual int virtualCallIndex() = 0; - - virtual bool bigEndian() = 0; - - virtual uintptr_t maximumImmediateJump() = 0; - - virtual bool alwaysCondensed(lir::BinaryOperation op) = 0; - virtual bool alwaysCondensed(lir::TernaryOperation op) = 0; - - virtual bool reserved(int register_) = 0; - - virtual unsigned frameFootprint(unsigned footprint) = 0; - virtual unsigned argumentFootprint(unsigned footprint) = 0; - virtual bool argumentAlignment() = 0; - virtual bool argumentRegisterAlignment() = 0; - virtual unsigned argumentRegisterCount() = 0; - virtual int argumentRegister(unsigned index) = 0; - - virtual bool hasLinkRegister() = 0; - - virtual unsigned stackAlignmentInWords() = 0; - - virtual bool matchCall(void* returnAddress, void* target) = 0; - - virtual void updateCall(lir::UnaryOperation op, void* returnAddress, - void* newTarget) = 0; - - virtual void setConstant(void* dst, uint64_t constant) = 0; - - virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; - - virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, bool mostRecent, - unsigned targetParameterFootprint, void** ip, - void** stack) = 0; - virtual void* frameIp(void* stack) = 0; - virtual unsigned frameHeaderSize() = 0; - virtual unsigned frameReturnAddressSize() = 0; - virtual unsigned frameFooterSize() = 0; - virtual int returnAddressOffset() = 0; - virtual int framePointerOffset() = 0; - - virtual void plan - (lir::UnaryOperation op, - unsigned aSize, OperandMask& aMask, - bool* thunk) = 0; - - virtual void planSource - (lir::BinaryOperation op, - unsigned aSize, OperandMask& aMask, - unsigned bSize, bool* thunk) = 0; - - virtual void planDestination - (lir::BinaryOperation op, - unsigned aSize, const OperandMask& aMask, - unsigned bSize, OperandMask& bMask) = 0; - - virtual void planMove - (unsigned size, OperandMask& src, - OperandMask& tmp, - const OperandMask& dst) = 0; - - virtual void planSource - (lir::TernaryOperation op, - unsigned aSize, OperandMask& aMask, - unsigned bSize, OperandMask& bMask, - unsigned cSize, bool* thunk) = 0; - - virtual void planDestination - (lir::TernaryOperation op, - unsigned aSize, const OperandMask& aMask, - unsigned bSize, const OperandMask& bMask, - unsigned cSize, OperandMask& cMask) = 0; - - virtual Assembler* makeAssembler(vm::Allocator*, vm::Zone*) = 0; - - virtual void acquire() = 0; - virtual void release() = 0; - }; - virtual void setClient(Client* client) = 0; virtual Architecture* arch() = 0; diff --git a/include/avian/vm/codegen/targets.h b/include/avian/vm/codegen/targets.h index e3ffbd981a..a8adb246ce 100644 --- a/include/avian/vm/codegen/targets.h +++ b/include/avian/vm/codegen/targets.h @@ -11,16 +11,20 @@ #ifndef AVIAN_CODEGEN_TARGETS_H #define AVIAN_CODEGEN_TARGETS_H -#include +namespace vm { +class System; +} namespace avian { namespace codegen { -Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures); +class Architecture; -Assembler::Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures); -Assembler::Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures); -Assembler::Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures); +Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures); + +Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures); +Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures); +Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures); } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 1985629cfb..a093c1f5bf 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include "codegen/compiler/regalloc.h" diff --git a/src/codegen/compiler/context.cpp b/src/codegen/compiler/context.cpp index dd1f129bad..5d77fdcd77 100644 --- a/src/codegen/compiler/context.cpp +++ b/src/codegen/compiler/context.cpp @@ -11,6 +11,8 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/resource.h" +#include + namespace avian { namespace codegen { namespace compiler { diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index d9894eda8c..cd19097c42 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -75,7 +75,7 @@ class Context { vm::System* system; Assembler* assembler; - Assembler::Architecture* arch; + Architecture* arch; vm::Zone* zone; Compiler::Client* client; Stack* stack; diff --git a/src/codegen/compiler/frame.cpp b/src/codegen/compiler/frame.cpp index e879238b79..cae48b9fee 100644 --- a/src/codegen/compiler/frame.cpp +++ b/src/codegen/compiler/frame.cpp @@ -13,6 +13,8 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/frame.h" +#include + namespace avian { namespace codegen { namespace compiler { diff --git a/src/codegen/compiler/site.h b/src/codegen/compiler/site.h index bf2cef34b6..aedcc7ab09 100644 --- a/src/codegen/compiler/site.h +++ b/src/codegen/compiler/site.h @@ -11,6 +11,8 @@ #ifndef AVIAN_CODEGEN_COMPILER_SITE_H #define AVIAN_CODEGEN_COMPILER_SITE_H +#include + #include "codegen/compiler/value.h" #include "codegen/compiler/context.h" diff --git a/src/codegen/target/arm/assembler.cpp b/src/codegen/target/arm/assembler.cpp index 511f7ccc32..8be76085e1 100644 --- a/src/codegen/target/arm/assembler.cpp +++ b/src/codegen/target/arm/assembler.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include "context.h" @@ -136,7 +137,7 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED, *stack = static_cast(*stack) + offset; } -class MyArchitecture: public Assembler::Architecture { +class MyArchitecture: public Architecture { public: MyArchitecture(System* system): con(system), referenceCount(0) { populateTables(&con); @@ -950,7 +951,7 @@ Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { } // namespace arm -Assembler::Architecture* +Architecture* makeArchitectureArm(System* system, bool) { return new (allocate(system, sizeof(arm::MyArchitecture))) arm::MyArchitecture(system); diff --git a/src/codegen/target/powerpc/assembler.cpp b/src/codegen/target/powerpc/assembler.cpp index cda4fdbc96..5ad517871a 100644 --- a/src/codegen/target/powerpc/assembler.cpp +++ b/src/codegen/target/powerpc/assembler.cpp @@ -9,6 +9,7 @@ details. */ #include +#include #include #include "alloc-vector.h" @@ -235,7 +236,7 @@ nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size, *stack = static_cast(*stack) + offset; } -class MyArchitecture: public Assembler::Architecture { +class MyArchitecture: public Architecture { public: MyArchitecture(System* system): c(system), referenceCount(0) { populateTables(&c); @@ -996,7 +997,7 @@ Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { } // namespace powerpc -Assembler::Architecture* +Architecture* makeArchitecturePowerpc(System* system, bool) { return new (allocate(system, sizeof(powerpc::MyArchitecture))) powerpc::MyArchitecture(system); diff --git a/src/codegen/target/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp index a568430f91..6b1a1679ad 100644 --- a/src/codegen/target/x86/assembler.cpp +++ b/src/codegen/target/x86/assembler.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -147,7 +148,7 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, *stack = static_cast(*stack) + offset; } -class MyArchitecture: public Assembler::Architecture { +class MyArchitecture: public Architecture { public: MyArchitecture(System* system, bool useNativeFeatures): c(system, useNativeFeatures), @@ -1148,7 +1149,7 @@ Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) { } // namespace x86 -Assembler::Architecture* makeArchitectureX86(System* system, bool useNativeFeatures) +Architecture* makeArchitectureX86(System* system, bool useNativeFeatures) { return new (allocate(system, sizeof(x86::MyArchitecture))) x86::MyArchitecture(system, useNativeFeatures); diff --git a/src/codegen/targets.cpp b/src/codegen/targets.cpp index 4b9d44fc7e..af8f66219c 100644 --- a/src/codegen/targets.cpp +++ b/src/codegen/targets.cpp @@ -8,6 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include "common.h" + #include #include "environment.h" @@ -15,7 +17,7 @@ namespace avian { namespace codegen { -Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures UNUSED) { +Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures UNUSED) { #ifndef AVIAN_TARGET_ARCH #error "Must specify native target!" #endif diff --git a/src/compile.cpp b/src/compile.cpp index 02a87cd4c8..b19b45ca7e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -16,6 +16,7 @@ #include "arch.h" #include +#include #include #include @@ -294,7 +295,7 @@ class MyThread: public Thread { void** thunkTable; CallTrace* trace; Reference* reference; - avian::codegen::Assembler::Architecture* arch; + avian::codegen::Architecture* arch; Context* transition; TraceContext* traceContext; uintptr_t stackLimit; diff --git a/src/tools/audit-codegen/main.cpp b/src/tools/audit-codegen/main.cpp index d201cd43a4..5cc7d79709 100644 --- a/src/tools/audit-codegen/main.cpp +++ b/src/tools/audit-codegen/main.cpp @@ -31,7 +31,7 @@ class BasicEnv { public: System* s; Heap* heap; - Assembler::Architecture* arch; + Architecture* arch; BasicEnv(): s(makeSystem(0)), diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp index dde1b1b074..0412766b59 100644 --- a/unittest/codegen/assembler-test.cpp +++ b/unittest/codegen/assembler-test.cpp @@ -16,6 +16,7 @@ #include "target.h" #include +#include #include #include @@ -29,7 +30,7 @@ class BasicEnv { public: System* s; Heap* heap; - Assembler::Architecture* arch; + Architecture* arch; BasicEnv(): s(makeSystem(0)), From d2caf50772201a5aee852589e8985e1431e8d01c Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 24 Feb 2013 16:03:19 -0700 Subject: [PATCH 296/378] fix debug build --- src/codegen/target/arm/fixup.cpp | 2 ++ src/codegen/target/arm/multimethod.cpp | 2 ++ src/codegen/target/powerpc/fixup.cpp | 1 + src/codegen/target/powerpc/multimethod.cpp | 32 ++++++++++++++++++++++ src/codegen/target/powerpc/multimethod.h | 30 +++++--------------- src/codegen/target/x86/fixup.cpp | 2 ++ src/codegen/target/x86/multimethod.cpp | 2 ++ 7 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/codegen/target/arm/fixup.cpp b/src/codegen/target/arm/fixup.cpp index 2cf0b01216..88b5789f5a 100644 --- a/src/codegen/target/arm/fixup.cpp +++ b/src/codegen/target/arm/fixup.cpp @@ -16,6 +16,8 @@ namespace avian { namespace codegen { namespace arm { +using namespace util; + unsigned padding(MyBlock*, unsigned); OffsetPromise::OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace): diff --git a/src/codegen/target/arm/multimethod.cpp b/src/codegen/target/arm/multimethod.cpp index 76c681a60f..4e789cc18c 100644 --- a/src/codegen/target/arm/multimethod.cpp +++ b/src/codegen/target/arm/multimethod.cpp @@ -16,6 +16,8 @@ namespace avian { namespace codegen { namespace arm { +using namespace util; + unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) { return operation + (lir::UnaryOperationCount * operand); diff --git a/src/codegen/target/powerpc/fixup.cpp b/src/codegen/target/powerpc/fixup.cpp index 06075c00e6..6de1698fe2 100644 --- a/src/codegen/target/powerpc/fixup.cpp +++ b/src/codegen/target/powerpc/fixup.cpp @@ -18,6 +18,7 @@ namespace codegen { namespace powerpc { using namespace isa; +using namespace util; unsigned padding(MyBlock*, unsigned); diff --git a/src/codegen/target/powerpc/multimethod.cpp b/src/codegen/target/powerpc/multimethod.cpp index 79b5f9bf7b..d8ffba5008 100644 --- a/src/codegen/target/powerpc/multimethod.cpp +++ b/src/codegen/target/powerpc/multimethod.cpp @@ -19,6 +19,38 @@ namespace avian { namespace codegen { namespace powerpc { +using namespace util; + +unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) +{ + return operation + (lir::UnaryOperationCount * operand); +} + +unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::OperandType operand1, + lir::OperandType operand2) +{ + return operation + + (lir::BinaryOperationCount * operand1) + + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); +} + +unsigned index(ArchitectureContext* c UNUSED, + lir::TernaryOperation operation, + lir::OperandType operand1) +{ + assert(c, not isBranch(operation)); + + return operation + (lir::NonBranchTernaryOperationCount * operand1); +} + +unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, + lir::OperandType operand2) +{ + return operand1 + (lir::OperandTypeCount * operand2); +} + void populateTables(ArchitectureContext* c) { const lir::OperandType C = lir::ConstantOperand; const lir::OperandType A = lir::AddressOperand; diff --git a/src/codegen/target/powerpc/multimethod.h b/src/codegen/target/powerpc/multimethod.h index b2fe6f206d..06b881e97a 100644 --- a/src/codegen/target/powerpc/multimethod.h +++ b/src/codegen/target/powerpc/multimethod.h @@ -21,35 +21,19 @@ namespace codegen { namespace powerpc { -inline unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) -{ - return operation + (lir::UnaryOperationCount * operand); -} +unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand); -inline unsigned index(ArchitectureContext*, +unsigned index(ArchitectureContext*, lir::BinaryOperation operation, lir::OperandType operand1, - lir::OperandType operand2) -{ - return operation - + (lir::BinaryOperationCount * operand1) - + (lir::BinaryOperationCount * lir::OperandTypeCount * operand2); -} + lir::OperandType operand2); -inline unsigned index(ArchitectureContext* c UNUSED, +unsigned index(ArchitectureContext* c UNUSED, lir::TernaryOperation operation, - lir::OperandType operand1) -{ - assert(c, not isBranch(operation)); + lir::OperandType operand1); - return operation + (lir::NonBranchTernaryOperationCount * operand1); -} - -inline unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, - lir::OperandType operand2) -{ - return operand1 + (lir::OperandTypeCount * operand2); -} +unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, + lir::OperandType operand2); void populateTables(ArchitectureContext* c); diff --git a/src/codegen/target/x86/fixup.cpp b/src/codegen/target/x86/fixup.cpp index 5e85d7c062..ba0a06f906 100644 --- a/src/codegen/target/x86/fixup.cpp +++ b/src/codegen/target/x86/fixup.cpp @@ -27,6 +27,8 @@ namespace avian { namespace codegen { namespace x86 { +using namespace util; + ResolvedPromise* resolvedPromise(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } diff --git a/src/codegen/target/x86/multimethod.cpp b/src/codegen/target/x86/multimethod.cpp index f0ad4621b2..9146c9d9cb 100644 --- a/src/codegen/target/x86/multimethod.cpp +++ b/src/codegen/target/x86/multimethod.cpp @@ -22,6 +22,8 @@ namespace avian { namespace codegen { namespace x86 { +using namespace util; + unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) { return operation + (lir::UnaryOperationCount * operand); From 82eec288563dc374994aad340da4f8b6fc6ab806 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 24 Feb 2013 20:48:06 -0700 Subject: [PATCH 297/378] rename x86 Offset for consistency with arm and powerpc OffsetPromise --- src/codegen/target/x86/fixup.cpp | 8 ++++---- src/codegen/target/x86/fixup.h | 23 +++++++++++------------ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/codegen/target/x86/fixup.cpp b/src/codegen/target/x86/fixup.cpp index ba0a06f906..294780fae5 100644 --- a/src/codegen/target/x86/fixup.cpp +++ b/src/codegen/target/x86/fixup.cpp @@ -33,15 +33,15 @@ ResolvedPromise* resolvedPromise(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } -Offset::Offset(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit): +OffsetPromise::OffsetPromise(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit): c(c), block(block), offset(offset), limit(limit), value_(-1) { } -bool Offset::resolved() { +bool OffsetPromise::resolved() { return block->start != static_cast(~0); } -int64_t Offset::value() { +int64_t OffsetPromise::value() { assert(c, resolved()); if (value_ == -1) { @@ -52,7 +52,7 @@ int64_t Offset::value() { return value_; } Promise* offsetPromise(Context* c) { - return new(c->zone) Offset(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); + return new(c->zone) OffsetPromise(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); } void* diff --git a/src/codegen/target/x86/fixup.h b/src/codegen/target/x86/fixup.h index 78f77b3044..fa170bb542 100644 --- a/src/codegen/target/x86/fixup.h +++ b/src/codegen/target/x86/fixup.h @@ -29,9 +29,18 @@ class AlignmentPadding; ResolvedPromise* resolvedPromise(Context* c, int64_t value); -class Offset: public Promise { +class Task { public: - Offset(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit); + Task(Task* next): next(next) { } + + virtual void run(Context* c) = 0; + + Task* next; +}; + +class OffsetPromise: public Promise { + public: + OffsetPromise(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit); virtual bool resolved(); @@ -46,16 +55,6 @@ class Offset: public Promise { Promise* offsetPromise(Context* c); - -class Task { - public: - Task(Task* next): next(next) { } - - virtual void run(Context* c) = 0; - - Task* next; -}; - void* resolveOffset(vm::System* s, uint8_t* instruction, unsigned instructionSize, int64_t value); class OffsetListener: public Promise::Listener { From 4d38873096c337aa6471489ba091bebd4dc8da61 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Sun, 24 Feb 2013 22:38:58 -0700 Subject: [PATCH 298/378] begin merging target assembler multimethod code --- src/codegen/target/arm/assembler.cpp | 3 +- src/codegen/target/arm/multimethod.cpp | 33 ++++++++++------------ src/codegen/target/arm/multimethod.h | 2 -- src/codegen/target/multimethod.h | 29 +++++++++++++++++++ src/codegen/target/powerpc/assembler.cpp | 5 ++-- src/codegen/target/powerpc/multimethod.cpp | 32 +++++++++------------ src/codegen/target/powerpc/multimethod.h | 3 -- src/codegen/target/x86/assembler.cpp | 3 +- src/codegen/target/x86/multimethod.cpp | 33 ++++++++++------------ src/codegen/target/x86/multimethod.h | 2 -- 10 files changed, 80 insertions(+), 65 deletions(-) create mode 100644 src/codegen/target/multimethod.h diff --git a/src/codegen/target/arm/assembler.cpp b/src/codegen/target/arm/assembler.cpp index 8be76085e1..089c56379f 100644 --- a/src/codegen/target/arm/assembler.cpp +++ b/src/codegen/target/arm/assembler.cpp @@ -21,6 +21,7 @@ #include "encode.h" #include "operations.h" #include "registers.h" +#include "../multimethod.h" #include "alloc-vector.h" #include @@ -769,7 +770,7 @@ class MyAssembler: public Assembler { virtual void apply(lir::UnaryOperation op, OperandInfo a) { - arch_->con.unaryOperations[index(&(arch_->con), op, a.type)] + arch_->con.unaryOperations[Multimethod::index(op, a.type)] (&con, a.size, a.operand); } diff --git a/src/codegen/target/arm/multimethod.cpp b/src/codegen/target/arm/multimethod.cpp index 4e789cc18c..a88180fc9b 100644 --- a/src/codegen/target/arm/multimethod.cpp +++ b/src/codegen/target/arm/multimethod.cpp @@ -9,20 +9,17 @@ details. */ #include "context.h" -#include "multimethod.h" #include "operations.h" +#include "multimethod.h" +#include "../multimethod.h" + namespace avian { namespace codegen { namespace arm { using namespace util; -unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) -{ - return operation + (lir::UnaryOperationCount * operand); -} - unsigned index(ArchitectureContext*, lir::BinaryOperation operation, lir::OperandType operand1, @@ -66,25 +63,25 @@ void populateTables(ArchitectureContext* con) { zo[lir::StoreLoadBarrier] = memoryBarrier; zo[lir::Trap] = trap; - uo[index(con, lir::LongCall, C)] = CAST1(longCallC); + uo[Multimethod::index(lir::LongCall, C)] = CAST1(longCallC); - uo[index(con, lir::AlignedLongCall, C)] = CAST1(longCallC); + uo[Multimethod::index(lir::AlignedLongCall, C)] = CAST1(longCallC); - uo[index(con, lir::LongJump, C)] = CAST1(longJumpC); + uo[Multimethod::index(lir::LongJump, C)] = CAST1(longJumpC); - uo[index(con, lir::AlignedLongJump, C)] = CAST1(longJumpC); + uo[Multimethod::index(lir::AlignedLongJump, C)] = CAST1(longJumpC); - uo[index(con, lir::Jump, R)] = CAST1(jumpR); - uo[index(con, lir::Jump, C)] = CAST1(jumpC); + uo[Multimethod::index(lir::Jump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::Jump, C)] = CAST1(jumpC); - uo[index(con, lir::AlignedJump, R)] = CAST1(jumpR); - uo[index(con, lir::AlignedJump, C)] = CAST1(jumpC); + uo[Multimethod::index(lir::AlignedJump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::AlignedJump, C)] = CAST1(jumpC); - uo[index(con, lir::Call, C)] = CAST1(callC); - uo[index(con, lir::Call, R)] = CAST1(callR); + uo[Multimethod::index(lir::Call, C)] = CAST1(callC); + uo[Multimethod::index(lir::Call, R)] = CAST1(callR); - uo[index(con, lir::AlignedCall, C)] = CAST1(callC); - uo[index(con, lir::AlignedCall, R)] = CAST1(callR); + uo[Multimethod::index(lir::AlignedCall, C)] = CAST1(callC); + uo[Multimethod::index(lir::AlignedCall, R)] = CAST1(callR); bo[index(con, lir::Move, R, R)] = CAST2(moveRR); bo[index(con, lir::Move, C, R)] = CAST2(moveCR); diff --git a/src/codegen/target/arm/multimethod.h b/src/codegen/target/arm/multimethod.h index 7c574b588c..cda1daff37 100644 --- a/src/codegen/target/arm/multimethod.h +++ b/src/codegen/target/arm/multimethod.h @@ -23,8 +23,6 @@ namespace avian { namespace codegen { namespace arm { -unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand); - unsigned index(ArchitectureContext*, lir::BinaryOperation operation, lir::OperandType operand1, diff --git a/src/codegen/target/multimethod.h b/src/codegen/target/multimethod.h new file mode 100644 index 0000000000..750a02d8c8 --- /dev/null +++ b/src/codegen/target/multimethod.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_TARGET_MULTIMETHOD_H +#define AVIAN_CODEGEN_TARGET_MULTIMETHOD_H + + +namespace avian { +namespace codegen { + +class Multimethod { +public: + inline static unsigned index(lir::UnaryOperation operation, lir::OperandType operand) { + return operation + (lir::UnaryOperationCount * operand); + } +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_TARGET_MULTIMETHOD_H + diff --git a/src/codegen/target/powerpc/assembler.cpp b/src/codegen/target/powerpc/assembler.cpp index 5ad517871a..414ab71884 100644 --- a/src/codegen/target/powerpc/assembler.cpp +++ b/src/codegen/target/powerpc/assembler.cpp @@ -19,8 +19,9 @@ #include "context.h" #include "fixup.h" #include "block.h" -#include "multimethod.h" #include "operations.h" +#include "multimethod.h" +#include "../multimethod.h" using namespace vm; using namespace avian::util; @@ -824,7 +825,7 @@ class MyAssembler: public Assembler { virtual void apply(lir::UnaryOperation op, OperandInfo a) { - arch_->c.unaryOperations[index(&(arch_->c), op, a.type)] + arch_->c.unaryOperations[Multimethod::index(op, a.type)] (&c, a.size, a.operand); } diff --git a/src/codegen/target/powerpc/multimethod.cpp b/src/codegen/target/powerpc/multimethod.cpp index d8ffba5008..234a4e055c 100644 --- a/src/codegen/target/powerpc/multimethod.cpp +++ b/src/codegen/target/powerpc/multimethod.cpp @@ -11,9 +11,10 @@ #include "context.h" #include "block.h" #include "common.h" - #include "operations.h" + #include "multimethod.h" +#include "../multimethod.h" namespace avian { namespace codegen { @@ -21,11 +22,6 @@ namespace powerpc { using namespace util; -unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) -{ - return operation + (lir::UnaryOperationCount * operand); -} - unsigned index(ArchitectureContext*, lir::BinaryOperation operation, lir::OperandType operand1, @@ -69,25 +65,25 @@ void populateTables(ArchitectureContext* c) { zo[lir::StoreLoadBarrier] = memoryBarrier; zo[lir::Trap] = trap; - uo[index(c, lir::LongCall, C)] = CAST1(longCallC); + uo[Multimethod::index(lir::LongCall, C)] = CAST1(longCallC); - uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); + uo[Multimethod::index(lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); - uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); + uo[Multimethod::index(lir::LongJump, C)] = CAST1(longJumpC); - uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); + uo[Multimethod::index(lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); - uo[index(c, lir::Jump, R)] = CAST1(jumpR); - uo[index(c, lir::Jump, C)] = CAST1(jumpC); + uo[Multimethod::index(lir::Jump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::Jump, C)] = CAST1(jumpC); - uo[index(c, lir::AlignedJump, R)] = CAST1(jumpR); - uo[index(c, lir::AlignedJump, C)] = CAST1(jumpC); + uo[Multimethod::index(lir::AlignedJump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::AlignedJump, C)] = CAST1(jumpC); - uo[index(c, lir::Call, C)] = CAST1(callC); - uo[index(c, lir::Call, R)] = CAST1(callR); + uo[Multimethod::index(lir::Call, C)] = CAST1(callC); + uo[Multimethod::index(lir::Call, R)] = CAST1(callR); - uo[index(c, lir::AlignedCall, C)] = CAST1(callC); - uo[index(c, lir::AlignedCall, R)] = CAST1(callR); + uo[Multimethod::index(lir::AlignedCall, C)] = CAST1(callC); + uo[Multimethod::index(lir::AlignedCall, R)] = CAST1(callR); bo[index(c, lir::Move, R, R)] = CAST2(moveRR); bo[index(c, lir::Move, C, R)] = CAST2(moveCR); diff --git a/src/codegen/target/powerpc/multimethod.h b/src/codegen/target/powerpc/multimethod.h index 06b881e97a..b3565d0ed9 100644 --- a/src/codegen/target/powerpc/multimethod.h +++ b/src/codegen/target/powerpc/multimethod.h @@ -20,9 +20,6 @@ namespace avian { namespace codegen { namespace powerpc { - -unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand); - unsigned index(ArchitectureContext*, lir::BinaryOperation operation, lir::OperandType operand1, diff --git a/src/codegen/target/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp index 6b1a1679ad..deeb6879f2 100644 --- a/src/codegen/target/x86/assembler.cpp +++ b/src/codegen/target/x86/assembler.cpp @@ -39,6 +39,7 @@ #include "operations.h" #include "detect.h" #include "multimethod.h" +#include "../multimethod.h" #define CAST1(x) reinterpret_cast(x) #define CAST2(x) reinterpret_cast(x) @@ -1043,7 +1044,7 @@ class MyAssembler: public Assembler { virtual void apply(lir::UnaryOperation op, OperandInfo a) { - arch_->c.unaryOperations[index(&(arch_->c), op, a.type)] + arch_->c.unaryOperations[Multimethod::index(op, a.type)] (&c, a.size, a.operand); } diff --git a/src/codegen/target/x86/multimethod.cpp b/src/codegen/target/x86/multimethod.cpp index 9146c9d9cb..ddd6a1fe1d 100644 --- a/src/codegen/target/x86/multimethod.cpp +++ b/src/codegen/target/x86/multimethod.cpp @@ -15,20 +15,17 @@ #include #include "context.h" -#include "multimethod.h" #include "operations.h" +#include "multimethod.h" +#include "../multimethod.h" + namespace avian { namespace codegen { namespace x86 { using namespace util; - -unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand) { - return operation + (lir::UnaryOperationCount * operand); -} - unsigned index(ArchitectureContext*, lir::BinaryOperation operation, lir::OperandType operand1, lir::OperandType operand2) @@ -74,25 +71,25 @@ void populateTables(ArchitectureContext* c) { zo[lir::StoreLoadBarrier] = storeLoadBarrier; zo[lir::Trap] = trap; - uo[index(c, lir::Call, C)] = CAST1(callC); - uo[index(c, lir::Call, R)] = CAST1(callR); - uo[index(c, lir::Call, M)] = CAST1(callM); + uo[Multimethod::index(lir::Call, C)] = CAST1(callC); + uo[Multimethod::index(lir::Call, R)] = CAST1(callR); + uo[Multimethod::index(lir::Call, M)] = CAST1(callM); - uo[index(c, lir::AlignedCall, C)] = CAST1(alignedCallC); + uo[Multimethod::index(lir::AlignedCall, C)] = CAST1(alignedCallC); - uo[index(c, lir::LongCall, C)] = CAST1(longCallC); + uo[Multimethod::index(lir::LongCall, C)] = CAST1(longCallC); - uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); + uo[Multimethod::index(lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); - uo[index(c, lir::Jump, R)] = CAST1(jumpR); - uo[index(c, lir::Jump, C)] = CAST1(jumpC); - uo[index(c, lir::Jump, M)] = CAST1(jumpM); + uo[Multimethod::index(lir::Jump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::Jump, C)] = CAST1(jumpC); + uo[Multimethod::index(lir::Jump, M)] = CAST1(jumpM); - uo[index(c, lir::AlignedJump, C)] = CAST1(alignedJumpC); + uo[Multimethod::index(lir::AlignedJump, C)] = CAST1(alignedJumpC); - uo[index(c, lir::LongJump, C)] = CAST1(longJumpC); + uo[Multimethod::index(lir::LongJump, C)] = CAST1(longJumpC); - uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); + uo[Multimethod::index(lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); diff --git a/src/codegen/target/x86/multimethod.h b/src/codegen/target/x86/multimethod.h index 6ede17f17a..6846f2f042 100644 --- a/src/codegen/target/x86/multimethod.h +++ b/src/codegen/target/x86/multimethod.h @@ -21,8 +21,6 @@ namespace x86 { class ArchitectureContext; -unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand); - unsigned index(ArchitectureContext*, lir::BinaryOperation operation, lir::OperandType operand1, lir::OperandType operand2); From fddd3ec49d2eea438050c7a4d233bd33799b50d8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 25 Feb 2013 10:38:06 -0700 Subject: [PATCH 299/378] fix openjdk-src build regression due to RUNTIME_ARRAY changes --- src/classpath-openjdk.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index d2f628968d..aea727b673 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1873,7 +1873,7 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) #ifdef AVIAN_OPENJDK_SRC if (not absolute) { - if (strcmp(n, "net") == 0) { + if (strcmp(RUNTIME_ARRAY_BODY(n), "net") == 0) { bool ran; { ACQUIRE(t, t->m->classLock); @@ -1890,7 +1890,7 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) } return; - } else if (strcmp(n, "management") == 0) { + } else if (strcmp(RUNTIME_ARRAY_BODY(n), "management") == 0) { bool ran; { ACQUIRE(t, t->m->classLock); @@ -1907,8 +1907,8 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) } return; - } else if (strcmp(n, "zip") == 0 - or strcmp(n, "nio") == 0) + } else if (strcmp(RUNTIME_ARRAY_BODY(n), "zip") == 0 + or strcmp(RUNTIME_ARRAY_BODY(n), "nio") == 0) { return; } From 2c12c9b0207feecb6903469d54f695d692f8b381 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 25 Feb 2013 10:38:37 -0700 Subject: [PATCH 300/378] add note about OpenJDK build infrastructure available on GitHub --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52bf9c844e..bc9bfb55b3 100644 --- a/README.md +++ b/README.md @@ -324,7 +324,7 @@ _Stand-alone build:_ openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test ####Windows (Cygwin): -_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). +_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). Alternatively, use https://github.com/alexkasko/openjdk-unofficial-builds. _Conventional build:_ From 1310fbbe4f7288eabb69723701ce4b6c5095376d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 25 Feb 2013 16:37:46 -0700 Subject: [PATCH 301/378] reset alignment at inheritence boundary when iterating over fields In type-generator, we were incorrectly calculating field offsets where a class inherits from another class whose last field has a natural alignment which is different from the native word size. Surprisingly, this only popped up when I built using the Android class library on a 64-bit system. --- src/tools/type-generator/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/type-generator/main.cpp b/src/tools/type-generator/main.cpp index 9186bc68ae..fbd4fd6909 100644 --- a/src/tools/type-generator/main.cpp +++ b/src/tools/type-generator/main.cpp @@ -662,6 +662,7 @@ class MemberIterator { assert(member->type == Object::Scalar); offset_ = ((offset_ + size_) + (BytesPerWord - 1)) & ~(BytesPerWord - 1); + alignment_ = BytesPerWord; member = 0; } From 0bb0b1ec0e07c0c032085754b7e2f86073abf262 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 25 Feb 2013 16:41:46 -0700 Subject: [PATCH 302/378] enable use of Android class library on 64-bit systems This involved patching libcore.git to make it 64-bit safe. --- makefile | 4 ++- src/classpath-android.cpp | 57 ++++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/makefile b/makefile index cbe41b04f6..7bd1e40fe4 100755 --- a/makefile +++ b/makefile @@ -167,7 +167,9 @@ ifneq ($(android),) -fno-exceptions \ -DHAVE_SYS_UIO_H \ -D_FILE_OFFSET_BITS=64 \ - -g3 + -g3 \ + -Werror \ + -fPIC classpath-lflags := $(android)/icu4c/lib/libicuuc.a \ $(android)/icu4c/lib/libicui18n.a \ $(android)/icu4c/lib/libicudata.a \ diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index bf753540b0..369dc3b5c3 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -401,10 +401,10 @@ class MyClasspath : public Classpath { object instance = makeNew(t, c); PROTECT(t, instance); - object constructor = resolveMethod(t, c, "", "(II)V"); + object constructor = resolveMethod(t, c, "", "(JI)V"); t->m->processor->invoke - (t, constructor, instance, reinterpret_cast(p), + (t, constructor, instance, reinterpret_cast(p), static_cast(capacity)); return instance; @@ -416,10 +416,10 @@ class MyClasspath : public Classpath { PROTECT(t, b); object field = resolveField - (t, objectClass(t, b), "effectiveDirectAddress", "I"); + (t, objectClass(t, b), "effectiveDirectAddress", "J"); return reinterpret_cast - (fieldAtOffset(b, fieldOffset(t, field))); + (fieldAtOffset(b, fieldOffset(t, field))); } virtual int64_t @@ -1536,65 +1536,84 @@ extern "C" JNIEXPORT void JNICALL Avian_libcore_io_Memory_pokeLong (Thread*, object, uintptr_t* arguments) { - int64_t v; memcpy(&v, arguments + 1, 8); - if (arguments[3]) { + int64_t address; memcpy(&address, arguments, 8); + int64_t v; memcpy(&v, arguments + 2, 8); + if (arguments[4]) { v = swapV8(v); } - memcpy(reinterpret_cast(arguments[0]), &v, 8); + memcpy(reinterpret_cast(address), &v, 8); } extern "C" JNIEXPORT int64_t JNICALL Avian_libcore_io_Memory_peekLong (Thread*, object, uintptr_t* arguments) { - int64_t v; memcpy(&v, reinterpret_cast(arguments[0]), 8); - return arguments[1] ? swapV8(v) : v; + int64_t address; memcpy(&address, arguments, 8); + int64_t v; memcpy(&v, reinterpret_cast(address), 8); + return arguments[2] ? swapV8(v) : v; } extern "C" JNIEXPORT void JNICALL Avian_libcore_io_Memory_pokeInt (Thread*, object, uintptr_t* arguments) { - int32_t v = arguments[2] ? swapV4(arguments[1]) : arguments[1]; - memcpy(reinterpret_cast(arguments[0]), &v, 4); + int64_t address; memcpy(&address, arguments, 8); + int32_t v = arguments[3] ? swapV4(arguments[2]) : arguments[2]; + memcpy(reinterpret_cast(address), &v, 4); } extern "C" JNIEXPORT int64_t JNICALL Avian_libcore_io_Memory_peekInt (Thread*, object, uintptr_t* arguments) { - int32_t v; memcpy(&v, reinterpret_cast(arguments[0]), 4); - return arguments[1] ? swapV4(v) : v; + int64_t address; memcpy(&address, arguments, 8); + int32_t v; memcpy(&v, reinterpret_cast(address), 4); + return arguments[2] ? swapV4(v) : v; } extern "C" JNIEXPORT void JNICALL Avian_libcore_io_Memory_pokeShort (Thread*, object, uintptr_t* arguments) { - int16_t v = arguments[2] ? swapV2(arguments[1]) : arguments[1]; - memcpy(reinterpret_cast(arguments[0]), &v, 2); + int64_t address; memcpy(&address, arguments, 8); + int16_t v = arguments[3] ? swapV2(arguments[2]) : arguments[2]; + memcpy(reinterpret_cast(address), &v, 2); } extern "C" JNIEXPORT int64_t JNICALL Avian_libcore_io_Memory_peekShort (Thread*, object, uintptr_t* arguments) { - int16_t v; memcpy(&v, reinterpret_cast(arguments[0]), 2); - return arguments[1] ? swapV2(v) : v; + int64_t address; memcpy(&address, arguments, 8); + int16_t v; memcpy(&v, reinterpret_cast(address), 2); + return arguments[2] ? swapV2(v) : v; } extern "C" JNIEXPORT void JNICALL Avian_libcore_io_Memory_pokeByte (Thread*, object, uintptr_t* arguments) { - *reinterpret_cast(arguments[0]) = arguments[1]; + int64_t address; memcpy(&address, arguments, 8); + *reinterpret_cast(address) = arguments[2]; } extern "C" JNIEXPORT int64_t JNICALL Avian_libcore_io_Memory_peekByte (Thread*, object, uintptr_t* arguments) { - return *reinterpret_cast(arguments[0]); + int64_t address; memcpy(&address, arguments, 8); + return *reinterpret_cast(address); +} + +extern "C" JNIEXPORT void JNICALL +Avian_libcore_io_Memory_peekByteArray +(Thread* t, object, uintptr_t* arguments) +{ + int64_t address; memcpy(&address, arguments, 8); + object array = reinterpret_cast(arguments[2]); + memcpy(&byteArrayBody(t, array, arguments[3]), + reinterpret_cast(address), + arguments[4]); } extern "C" JNIEXPORT int64_t JNICALL From 8a976fafa77f98c722966c331a7cff8764ca007b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 25 Feb 2013 16:55:44 -0700 Subject: [PATCH 303/378] fix avian-unittest openjdk-src build --- makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index e207d5f47c..eab0dee9f3 100755 --- a/makefile +++ b/makefile @@ -1582,7 +1582,8 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) -unittest-executable-objects = $(unittest-objects) $(vm-objects) +unittest-executable-objects = $(unittest-objects) $(vm-objects) \ + $(classpath-objects) ifeq ($(process),interpret) unittest-executable-objects += $(all-codegen-target-objects) From e6a46fc014912a39dc9f02d727557504abbedfe5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 26 Feb 2013 16:24:02 -0700 Subject: [PATCH 304/378] various fixes to get avian-swt-examples working with the Android class library --- makefile | 13 +++--- src/classpath-android.cpp | 92 +++++++++++++++++++++++++++------------ src/jnienv.cpp | 10 ++++- src/main.cpp | 5 ++- 4 files changed, 84 insertions(+), 36 deletions(-) diff --git a/makefile b/makefile index 7bd1e40fe4..c0b82b48e7 100755 --- a/makefile +++ b/makefile @@ -169,9 +169,11 @@ ifneq ($(android),) -D_FILE_OFFSET_BITS=64 \ -g3 \ -Werror \ - -fPIC - classpath-lflags := $(android)/icu4c/lib/libicuuc.a \ + -fPIC \ + -fvisibility=hidden + classpath-lflags := \ $(android)/icu4c/lib/libicui18n.a \ + $(android)/icu4c/lib/libicuuc.a \ $(android)/icu4c/lib/libicudata.a \ $(android)/fdlibm/libfdm.a \ $(android)/expat/.libs/libexpat.a \ @@ -1413,9 +1415,10 @@ $(classpath-build)/%.class: $(classpath-src)/%.java $(classpath-dep): $(classpath-sources) $(classpath-jar-dep) @echo "compiling classpath classes" @mkdir -p $(classpath-build) - $(javac) -d $(classpath-build) -bootclasspath $(boot-classpath) \ - $(shell $(MAKE) -s --no-print-directory build=$(build) \ - $(classpath-classes)) + classes="$(shell $(MAKE) -s --no-print-directory build=$(build) \ + $(classpath-classes))"; if [ -n "$${classes}" ]; then \ + $(javac) -d $(classpath-build) -bootclasspath $(boot-classpath) \ + $${classes}; fi @touch $(@) $(build)/android-src/%.cpp: $(luni-native)/%.cpp diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 369dc3b5c3..356c445f4d 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -123,7 +123,7 @@ initVmThread(Thread* t, object thread) if (fieldAtOffset(thread, fieldOffset(t, field)) == 0) { PROTECT(t, field); - + object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/VMThread"); PROTECT(t, c); @@ -235,6 +235,8 @@ class MyClasspath : public Classpath { t->m->processor->invoke (t, constructor, thread, group, 0, NormalPriority, false); + set(t, thread, ThreadContextClassLoader, root(t, Machine::AppLoader)); + initVmThread(t, thread); return thread; @@ -325,6 +327,10 @@ class MyClasspath : public Classpath { virtual void preBoot(Thread* t) { + // Android's System.initSystemProperties throws an NPE if + // LD_LIBRARY_PATH is not set as of this writing: + setenv("LD_LIBRARY_PATH", "", false); + { object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/Runtime", false); @@ -531,6 +537,8 @@ jniRegisterNativeMethods(JNIEnv* e, const char* className, if (c) { e->vtable->RegisterNatives(e, c, methods, methodCount); + } else { + e->vtable->ExceptionClear(e); } return 0; @@ -693,8 +701,9 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_String_equals (Thread* t, object, uintptr_t* arguments) { - return stringEqual(t, reinterpret_cast(arguments[0]), - reinterpret_cast(arguments[1])); + return arguments[1] and stringEqual + (t, reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1])); } extern "C" JNIEXPORT int64_t JNICALL @@ -917,8 +926,14 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_dalvik_system_VMRuntime_properties (Thread* t, object, uintptr_t*) { - return reinterpret_cast - (makeObjectArray(t, type(t, Machine::StringType), 0)); + object array = makeObjectArray(t, type(t, Machine::StringType), 1); + PROTECT(t, array); + + object property = makeString(t, "java.protocol.handler.pkgs=avian"); + + set(t, array, ArrayBody, property); + + return reinterpret_cast(array); } extern "C" JNIEXPORT void JNICALL @@ -928,6 +943,24 @@ Avian_java_lang_Runtime_gc collect(t, Heap::MajorCollection); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Runtime_nativeLoad +(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[0]); + PROTECT(t, name); + + unsigned length = stringLength(t, name); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + if (loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), false, true)) { + return 0; + } else { + return reinterpret_cast(name); + } +} + extern "C" JNIEXPORT void JNICALL Avian_java_lang_System_arraycopy (Thread* t, object, uintptr_t* arguments) @@ -1085,27 +1118,19 @@ Avian_java_lang_Math_max } extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Math_floor +Avian_java_lang_Math_cos (Thread*, object, uintptr_t* arguments) { int64_t v; memcpy(&v, arguments, 8); - return doubleToBits(floor(bitsToDouble(v))); + return doubleToBits(cos(bitsToDouble(v))); } extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Math_ceil +Avian_java_lang_Math_sin (Thread*, object, uintptr_t* arguments) { int64_t v; memcpy(&v, arguments, 8); - return doubleToBits(ceil(bitsToDouble(v))); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Math_log -(Thread*, object, uintptr_t* arguments) -{ - int64_t v; memcpy(&v, arguments, 8); - return doubleToBits(log(bitsToDouble(v))); + return doubleToBits(sin(bitsToDouble(v))); } extern "C" JNIEXPORT int64_t JNICALL @@ -1213,8 +1238,12 @@ Avian_java_lang_Class_getNameNative object name = className (t, jclassVmClass(t, reinterpret_cast(arguments[0]))); + THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, name)); + replace('/', '.', RUNTIME_ARRAY_BODY(s), + reinterpret_cast(&byteArrayBody(t, name, 0))); + return reinterpret_cast - (t->m->classpath->makeString(t, name, 0, byteArrayLength(t, name) - 1)); + (makeString(t, "%s", RUNTIME_ARRAY_BODY(s))); } extern "C" JNIEXPORT int64_t JNICALL @@ -1605,17 +1634,6 @@ Avian_libcore_io_Memory_peekByte return *reinterpret_cast(address); } -extern "C" JNIEXPORT void JNICALL -Avian_libcore_io_Memory_peekByteArray -(Thread* t, object, uintptr_t* arguments) -{ - int64_t address; memcpy(&address, arguments, 8); - object array = reinterpret_cast(arguments[2]); - memcpy(&byteArrayBody(t, array, arguments[3]), - reinterpret_cast(address), - arguments[4]); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_System_nanoTime (Thread* t, object, uintptr_t*) @@ -1636,3 +1654,19 @@ Avian_java_lang_System_identityHashCode { return objectHash(t, reinterpret_cast(arguments[0])); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_System_mapLibraryName +(Thread* t, object, uintptr_t* arguments) +{ + object original = reinterpret_cast(arguments[0]); + unsigned originalLength = stringUTFLength(t, original); + THREAD_RUNTIME_ARRAY(t, char, originalChars, originalLength); + stringUTFChars + (t, original, RUNTIME_ARRAY_BODY(originalChars), originalLength); + + return reinterpret_cast + (makeString(t, "%s%.*s%s", t->m->system->libraryPrefix(), originalLength, + RUNTIME_ARRAY_BODY(originalChars), + t->m->system->librarySuffix())); +} diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 1b070c53ed..8722be07ef 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3254,13 +3254,21 @@ registerNatives(Thread* t, uintptr_t* arguments) for (int i = 0; i < methodCount; ++i) { if (methods[i].function) { + // Android's class library sometimes prepends a mysterious "!" + // to the method signature, which we happily ignore: + const char* sig = methods[i].signature; + if (*sig == '!') ++ sig; + object method = findMethodOrNull - (t, jclassVmClass(t, *c), methods[i].name, methods[i].signature); + (t, jclassVmClass(t, *c), methods[i].name, sig); if (method == 0 or (methodFlags(t, method) & ACC_NATIVE) == 0) { // The JNI spec says we must throw a NoSuchMethodError in this // case, but that would prevent using a code shrinker like // ProGuard effectively. Instead, we just ignore it. + + // fprintf(stderr, "not found: %s.%s%s\n", &byteArrayBody(t, className(t, jclassVmClass(t, *c)), 0), methods[i].name, sig); + // abort(t); } else { registerNative(t, method, methods[i].function); } diff --git a/src/main.cpp b/src/main.cpp index f6ae72eec7..53760b753d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -259,7 +259,10 @@ main(int ac, const char** av) JNI_CreateJavaVM(&vm, &env, &vmArgs); JNIEnv* e = static_cast(env); - jclass c = e->FindClass(class_); + jclass c = 0; + if (not e->ExceptionCheck()) { + c = e->FindClass(class_); + } if (jar) { free(const_cast(class_)); From ce9bc520e1bd15da31fb7d67636b5d581f2c4822 Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Wed, 27 Feb 2013 14:54:50 +0100 Subject: [PATCH 305/378] Keep java.net.SocketTimeoutException for OpenJDK --- openjdk.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/openjdk.pro b/openjdk.pro index 71bc20aadd..4ad548281d 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -136,6 +136,7 @@ public InetSocketAddress(java.net.InetAddress, int); } -keep class java.net.ServerSocket +-keep class java.net.SocketTimeoutException -keepclassmembers class java.net.PlainSocketImpl { ; From 99e5edcc1693f4eeee4b5e477ba2360fcff91b20 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 10:02:47 -0700 Subject: [PATCH 306/378] add android.pro for using Avian, Android, and ProGuard in combination --- android.pro | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 android.pro diff --git a/android.pro b/android.pro new file mode 100644 index 0000000000..cc4e597efd --- /dev/null +++ b/android.pro @@ -0,0 +1,75 @@ +# these are referenced in JniConstants.cpp: + +-keep class java.text.Bidi$Run +-keep class java.math.BigDecimal +-keep class java.lang.Boolean +-keep class java.lang.Byte +-keep class java.nio.charset.CharsetICU { + CharsetICU(java.lang.String, java.lang.String, java.lang.String[]); + } +-keep class java.lang.reflect.Constructor +-keep class java.util.zip.Deflater +-keep class java.lang.Double +-keep class libcore.io.ErrnoException +-keep class java.lang.reflect.Field +-keep class libcore.icu.NativeDecimalFormat$FieldPositionIterator { + void setData(int[]); + } +-keep class java.io.FileDescriptor +-keep class libcore.io.GaiException +-keep class java.net.Inet6Address +-keep class java.net.InetAddress +-keep class java.net.InetSocketAddress +-keep class java.util.zip.Inflater +-keep class java.lang.Integer +-keep class libcore.icu.LocaleData +-keep class java.lang.Long +-keep class java.lang.reflect.Method +-keep class libcore.util.MutableInt +-keep class libcore.util.MutableLong +-keep class java.text.ParsePosition +-keep class java.util.regex.PatternSyntaxException +-keep class java.lang.RealToString +-keep class java.net.Socket +-keep class java.net.SocketImpl +-keep class java.lang.String +-keep class libcore.io.StructAddrinfo +-keep class libcore.io.StructFlock +-keep class libcore.io.StructGroupReq +-keep class libcore.io.StructLinger +-keep class libcore.io.StructPasswd +-keep class libcore.io.StructPollfd +-keep class libcore.io.StructStat { + StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long); + } +-keep class libcore.io.StructStatFs +-keep class libcore.io.StructTimeval +-keep class libcore.io.StructUtsname { + StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String); + } + +# referenced from libcore native code + +-keep class libcore.icu.LocaleData { + ; + } + +# called from the VM + +-keep class java.lang.Thread { + Thread(java.lang.ThreadGroup, java.lang.String, int, boolean); + } + +-keep class avian.Classes { + java.lang.Class forName(java.lang.String, boolean, java.lang.ClassLoader); + int findField(avian.VMClass, java.lang.String); + int findMethod(avian.VMClass, java.lang.String, java.lang.Class[]); + java.lang.annotation.Annotation getAnnotation(java.lang.ClassLoader, java.lang.Object[]); + } + +-keep class java.lang.VMThread { + VMThread(java.lang.Thread); + } + +# loaded reflectively to handle embedded resources: +-keep class avian.avianvmresource.Handler From d4a42c7a26f0066f80e23ec0d34af4f3682b234e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 10:03:17 -0700 Subject: [PATCH 307/378] add Android class library instructions to README.md --- README.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++---- makefile | 4 ++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bc9bfb55b3..1bea99be1e 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,8 @@ certain flags described below, all of which are optional. continuations={true,false} \ use-clang={true,false} \ openjdk= \ - openjdk-src= + openjdk-src= \ + android= * `platform` - the target platform * _default:_ output of $(uname -s | tr [:upper:] [:lower:]), @@ -156,8 +157,8 @@ Note that this does not currently affect cross compiles, only native builds. * _default:_ false - * `openjdk` - if set, use OpenJDK class library instead of the default -Avian class library. See "Building with the OpenJDK Class + * `openjdk` - if set, use the OpenJDK class library instead of the +default Avian class library. See "Building with the OpenJDK Class Library" below for details. * _default:_ not set @@ -168,6 +169,11 @@ sources found under the specified directory. See "Building with the OpenJDK Class Library" below for details. * _default:_ not set + * `android` - if set, use the Android class library instead of the +default Avian class library. See "Building with the Android Class +Library" below for details. + * _default:_ not set + These flags determine the name of the directory used for the build. The name always starts with _${platform}-${arch}_, and each non-default build option is appended to the name. For example, a debug build with @@ -235,6 +241,7 @@ Finally, build with the msvc flag set to the MSVC tool directory: $ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC" + Building with the OpenJDK Class Library --------------------------------------- @@ -306,7 +313,7 @@ _Stand-alone build:_ $ apt-get install openjdk-7-jdk $ apt-get source openjdk-7-jdk $ apt-get build-dep openjdk-7-jdk - (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) + $ (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) $ make openjdk=/usr/lib/jvm/java-7-openjdk \ openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ test @@ -339,6 +346,51 @@ Currently, only OpenJDK 7 is supported. Later versions might work, but have not yet been tested. +Building with the Android Class Library +--------------------------------------- + +As an alternative to both the Avian and OpenJDK class libaries, you +can also build with the Android Class Library on some platforms +(currently just Linux, but possibly others in the future). To build +this way, do the following, starting from the Avian directory: + + $ cd .. + $ mkdir android + $ git clone https://android.googlesource.com/platform/bionic + $ git clone https://android.googlesource.com/platform/system/core + $ git clone https://android.googlesource.com/platform/external/expat + $ git clone https://android.googlesource.com/platform/external/fdlibm + $ git clone https://android.googlesource.com/platform/external/icu4c + $ git clone https://android.googlesource.com/platform/libnativehelper + $ git clone https://android.googlesource.com/platform/external/openssl + $ git clone https://android.googlesource.com/platform/external/zlib + $ git clone git://git.openssl.org/openssl.git openssl-upstream + $ git clone https://github.com/dicej/android-libcore64 libcore + $ (cd expat && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ + && make) + $ (cd fdlibm && CFLAGS=-fPIC bash configure && make) + $ (cd icu4c && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ + && make) + $ (cd openssl-upstream && git checkout OpenSSL_1_0_1e \ + && (for x in ../openssl/patches/*.patch; do patch -p1 < $x; done) \ + && CC="gcc -fPIC" ./config && make) + $ cd ../avian + $ make android=$(pwd)/../android test + +Note that we use https://github.com/dicej/android-libcore64 above +instead of the upstream +https://android.googlesource.com/platform/libcore repository. This is +temporary until upstream has been patched with 64-bit support. + +Also note that we use the upstream OpenSSL repository and apply the +Android patches to it. This is because it is not clear how to build +the Android fork of OpenSSL directly without checking out and building +the entire platform. As of this writing, the patches apply cleanly +against OpenSSL 1.0.1e, so that's the tag we check out, but this may +change in the future when the Android fork rebases against a new +OpenSSL version. + + Installing ---------- diff --git a/makefile b/makefile index c0b82b48e7..64eae5ab4b 100755 --- a/makefile +++ b/makefile @@ -177,8 +177,8 @@ ifneq ($(android),) $(android)/icu4c/lib/libicudata.a \ $(android)/fdlibm/libfdm.a \ $(android)/expat/.libs/libexpat.a \ - $(android)/openssl-1.0.1e/libssl.a \ - $(android)/openssl-1.0.1e/libcrypto.a \ + $(android)/openssl-upstream/libssl.a \ + $(android)/openssl-upstream/libcrypto.a \ -lstdc++ luni-cpps := $(shell find $(luni-native) -name '*.cpp') classpath-objects = \ From 20cb5c70689ca498dac12f0cdad0b867f78cdf26 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 10:57:01 -0700 Subject: [PATCH 308/378] add KQueueArrayWrapper to openjdk-srcs on OS X This is necessary to ensure java.nio.channels.Selector works. --- openjdk-src.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openjdk-src.mk b/openjdk-src.mk index f588f471a8..0f59e03bcb 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -332,7 +332,8 @@ else $(src)/openjdk/my_java_props_macosx.c else openjdk-sources += \ - $(openjdk-src)/solaris/native/java/lang/java_props_macosx.c + $(openjdk-src)/solaris/native/java/lang/java_props_macosx.c \ + $(openjdk-src)/macosx/native/sun/nio/ch/KQueueArrayWrapper.c endif openjdk-cflags += \ From 3c1db46c5773214a76a3a1804e762f4a62107a33 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 11:34:43 -0700 Subject: [PATCH 309/378] don't throw an error if the mawt library can't be loaded --- src/classpath-common.h | 4 ++-- src/classpath-openjdk.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/classpath-common.h b/src/classpath-common.h index c13d447386..ff063982e6 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -165,7 +165,7 @@ loadLibrary(Thread* t, const char* name) System::Library* loadLibrary(Thread* t, const char* path, const char* name, bool mapName, - bool runOnLoad) + bool runOnLoad, bool throw_ = true) { ACQUIRE(t, t->m->classLock); @@ -238,7 +238,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, if (runOnLoad) { runOnLoadIfFound(t, lib); } - } else { + } else if (throw_) { throwNew(t, Machine::UnsatisfiedLinkErrorType, "library not found: %s", name); } diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 9ef7b4ccf8..7944ad0ee0 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -640,7 +640,7 @@ class MyClasspath : public Classpath { } virtual void - preBoot(Thread*) + preBoot(Thread* t) { // ignore } @@ -659,7 +659,7 @@ class MyClasspath : public Classpath { expect(t, loadLibrary(t, libraryPath, "verify", true, true)); expect(t, loadLibrary(t, libraryPath, "java", true, true)); # ifndef PLATFORM_WINDOWS - loadLibrary(t, libraryPath, "mawt", true, true); + loadLibrary(t, libraryPath, "mawt", true, true, false); # endif #endif // not AVIAN_OPENJDK_SRC From 22ecf27aa5b0932e25abb19b431b551d2792cc57 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 12:02:59 -0700 Subject: [PATCH 310/378] use -I$(src) instead of -idirafter $(src) This fixes the iOS build, where the wrong version of util.h was being used. The change to use -idirafter happened way back in 2007, and I can't remember what its intention was. We'll have to watch for regressions on other platforms. --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 20497d054a..be624157e4 100755 --- a/makefile +++ b/makefile @@ -267,7 +267,7 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \ target-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) common-cflags = $(warnings) -fno-rtti -fno-exceptions -I$(classpath-src) \ - "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) -Iinclude $(classpath-cflags) \ + "-I$(JAVA_HOME)/include" -I$(src) -I$(build) -Iinclude $(classpath-cflags) \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ -DAVIAN_INFO="\"$(info)\"" \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ From 726cdb645bc900251058bae7a8e9b9008c6fa460 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 12:04:46 -0700 Subject: [PATCH 311/378] support iOS SDK 6.1 --- makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index be624157e4..fb9cbe3905 100755 --- a/makefile +++ b/makefile @@ -567,7 +567,8 @@ ifeq ($(platform),darwin) ifeq ($(arch),arm) ios-version := \ - $(shell if test -d $(sdk-dir)/iPhoneOS6.0.sdk; then echo 6.0; \ + $(shell if test -d $(sdk-dir)/iPhoneOS6.1.sdk; then echo 6.1; \ + elif test -d $(sdk-dir)/iPhoneOS6.0.sdk; then echo 6.0; \ elif test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ From c261e1c2837019ac9600fe4717eaae5082a50cd3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 12:05:17 -0700 Subject: [PATCH 312/378] fix OpenJDK tests on OS X --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index fb9cbe3905..b6a64695b5 100755 --- a/makefile +++ b/makefile @@ -1397,7 +1397,7 @@ endif $(build)/run-tests.sh: $(test-classes) makefile echo 'cd $$(dirname $$0)' > $(@) echo "sh ./test.sh 2>/dev/null \\" >> $(@) - echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(name)${exe-suffix} $(mode) \"-Djava.library.path=. -cp test\" \\" >> $(@) + echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test\" \\" >> $(@) echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@) echo "$(continuation-tests) $(tail-tests)" >> $(@) From 44defda878cc3dfd0eebf48f784b6a838487bc55 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 12:10:10 -0700 Subject: [PATCH 313/378] fix unused parameter error --- src/classpath-openjdk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 7944ad0ee0..ca79619ade 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -640,7 +640,7 @@ class MyClasspath : public Classpath { } virtual void - preBoot(Thread* t) + preBoot(Thread*) { // ignore } From 5e2d00010bdf4c6b8df90abea5416852e65f82db Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 13:25:50 -0700 Subject: [PATCH 314/378] move headers from src to src/avian This is necessary to avoid name conflicts on various platforms. For example, iOS has its own util.h, and Windows has a process.h. By including our version as e.g. "avian/util.h", we avoid confusion with the system version. --- classpath/java-util-zip.cpp | 2 +- include/avian/tools/object-writer/tools.h | 2 +- include/avian/util/stream.h | 2 +- include/avian/vm/codegen/assembler.h | 2 +- include/avian/vm/codegen/compiler.h | 2 +- include/avian/vm/codegen/promise.h | 2 +- include/avian/vm/codegen/registers.h | 2 +- include/avian/vm/heap/heap.h | 2 +- include/avian/vm/system/system.h | 4 ++-- src/arm.S | 2 +- src/{ => avian}/alloc-vector.h | 2 +- src/{ => avian}/allocator.h | 2 +- src/{ => avian}/arch.h | 2 +- src/{ => avian}/arm.h | 4 ++-- src/{ => avian}/bootimage.h | 6 +++--- src/{ => avian}/classpath-common.h | 0 src/{ => avian}/common.h | 2 +- src/{ => avian}/constants.h | 0 src/{ => avian}/embed.h | 0 src/{ => avian}/environment.h | 0 src/{ => avian}/finder.h | 4 ++-- src/{ => avian}/heapwalk.h | 2 +- src/{ => avian}/java-common.h | 0 src/{ => avian}/jnienv.h | 2 +- src/{ => avian}/lzma-util.h | 4 ++-- src/{ => avian}/lzma.h | 2 +- src/{ => avian}/machine.h | 10 +++++----- src/{ => avian}/powerpc.h | 4 ++-- src/{ => avian}/process.h | 6 +++--- src/{ => avian}/processor.h | 6 +++--- src/{ => avian}/target-fields.h | 0 src/{ => avian}/target.h | 4 ++-- src/{ => avian}/types.h | 0 src/{ => avian}/util.h | 4 ++-- src/{ => avian}/x86.h | 4 ++-- src/{ => avian}/zlib-custom.h | 0 src/{ => avian}/zone.h | 2 +- src/builtin.cpp | 8 ++++---- src/classpath-android.cpp | 6 +++--- src/classpath-avian.cpp | 6 +++--- src/classpath-openjdk.cpp | 8 ++++---- src/codegen/arm/assembler.cpp | 2 +- src/codegen/compiler.cpp | 2 +- src/codegen/compiler/event.cpp | 2 +- src/codegen/compiler/frame.cpp | 2 +- src/codegen/compiler/promise.cpp | 2 +- src/codegen/compiler/read.cpp | 2 +- src/codegen/compiler/regalloc.cpp | 2 +- src/codegen/compiler/regalloc.h | 2 +- src/codegen/compiler/site.cpp | 2 +- src/codegen/compiler/value.cpp | 2 +- src/codegen/powerpc/assembler.cpp | 2 +- src/codegen/targets.cpp | 2 +- src/codegen/x86/assembler.cpp | 6 +++--- src/compile-arm.S | 4 ++-- src/compile-powerpc.S | 4 ++-- src/compile-x86.S | 4 ++-- src/compile.cpp | 12 ++++++------ src/embed.cpp | 2 +- src/embedded-loader.cpp | 2 +- src/finder.cpp | 6 +++--- src/heap/heap.cpp | 4 ++-- src/heapdump.cpp | 4 ++-- src/heapwalk.cpp | 4 ++-- src/interpret.cpp | 12 ++++++------ src/jnienv.cpp | 10 +++++----- src/machine.cpp | 14 +++++++------- src/main.cpp | 2 +- src/powerpc.S | 2 +- src/process.cpp | 2 +- src/tools/bootimage-generator/main.cpp | 12 ++++++------ src/tools/type-generator/main.cpp | 4 ++-- src/util.cpp | 2 +- src/vm/system/posix.cpp | 2 +- src/vm/system/windows.cpp | 2 +- src/x86.S | 2 +- unittest/codegen/assembler-test.cpp | 4 ++-- unittest/test-harness.cpp | 2 +- 78 files changed, 135 insertions(+), 135 deletions(-) rename src/{ => avian}/alloc-vector.h (99%) rename src/{ => avian}/allocator.h (98%) rename src/{ => avian}/arch.h (97%) rename src/{ => avian}/arm.h (99%) rename src/{ => avian}/bootimage.h (94%) rename src/{ => avian}/classpath-common.h (100%) rename src/{ => avian}/common.h (99%) rename src/{ => avian}/constants.h (100%) rename src/{ => avian}/embed.h (100%) rename src/{ => avian}/environment.h (100%) rename src/{ => avian}/finder.h (98%) rename src/{ => avian}/heapwalk.h (97%) rename src/{ => avian}/java-common.h (100%) rename src/{ => avian}/jnienv.h (97%) rename src/{ => avian}/lzma-util.h (95%) rename src/{ => avian}/lzma.h (95%) rename src/{ => avian}/machine.h (99%) rename src/{ => avian}/powerpc.h (99%) rename src/{ => avian}/process.h (94%) rename src/{ => avian}/processor.h (98%) rename src/{ => avian}/target-fields.h (100%) rename src/{ => avian}/target.h (98%) rename src/{ => avian}/types.h (100%) rename src/{ => avian}/util.h (98%) rename src/{ => avian}/x86.h (99%) rename src/{ => avian}/zlib-custom.h (100%) rename src/{ => avian}/zone.h (99%) diff --git a/classpath/java-util-zip.cpp b/classpath/java-util-zip.cpp index 6fb471bdfd..796156d57b 100644 --- a/classpath/java-util-zip.cpp +++ b/classpath/java-util-zip.cpp @@ -10,7 +10,7 @@ #include "stdlib.h" #include "string.h" -#include "zlib-custom.h" +#include "avian/zlib-custom.h" #include "jni.h" #include "jni-util.h" diff --git a/include/avian/tools/object-writer/tools.h b/include/avian/tools/object-writer/tools.h index 411dfaec9e..b9ed905e62 100644 --- a/include/avian/tools/object-writer/tools.h +++ b/include/avian/tools/object-writer/tools.h @@ -15,7 +15,7 @@ #include -#include "environment.h" +#include "avian/environment.h" namespace avian { diff --git a/include/avian/util/stream.h b/include/avian/util/stream.h index a46ad315d8..f3dbed082c 100644 --- a/include/avian/util/stream.h +++ b/include/avian/util/stream.h @@ -11,7 +11,7 @@ #ifndef STREAM_H #define STREAM_H -#include "common.h" +#include "avian/common.h" namespace vm { diff --git a/include/avian/vm/codegen/assembler.h b/include/avian/vm/codegen/assembler.h index d61684c92e..8a5e15d061 100644 --- a/include/avian/vm/codegen/assembler.h +++ b/include/avian/vm/codegen/assembler.h @@ -12,7 +12,7 @@ #define AVIAN_CODEGEN_ASSEMBLER_H #include -#include "zone.h" +#include "avian/zone.h" #include #include diff --git a/include/avian/vm/codegen/compiler.h b/include/avian/vm/codegen/compiler.h index 663cb071ea..49dfa14095 100644 --- a/include/avian/vm/codegen/compiler.h +++ b/include/avian/vm/codegen/compiler.h @@ -12,7 +12,7 @@ #define AVIAN_CODEGEN_COMPILER_H #include -#include "zone.h" +#include "avian/zone.h" #include "assembler.h" namespace avian { diff --git a/include/avian/vm/codegen/promise.h b/include/avian/vm/codegen/promise.h index 1e21943999..a5f0c3db3d 100644 --- a/include/avian/vm/codegen/promise.h +++ b/include/avian/vm/codegen/promise.h @@ -11,7 +11,7 @@ #ifndef AVIAN_CODEGEN_PROMISE_H #define AVIAN_CODEGEN_PROMISE_H -#include "allocator.h" +#include "avian/allocator.h" namespace avian { namespace codegen { diff --git a/include/avian/vm/codegen/registers.h b/include/avian/vm/codegen/registers.h index 317bb2215a..e799f2f40b 100644 --- a/include/avian/vm/codegen/registers.h +++ b/include/avian/vm/codegen/registers.h @@ -11,7 +11,7 @@ #ifndef AVIAN_CODEGEN_REGISTERS_H #define AVIAN_CODEGEN_REGISTERS_H -#include "common.h" +#include "avian/common.h" namespace avian { namespace codegen { diff --git a/include/avian/vm/heap/heap.h b/include/avian/vm/heap/heap.h index 5b0fbc1ba1..b385dcf511 100644 --- a/include/avian/vm/heap/heap.h +++ b/include/avian/vm/heap/heap.h @@ -12,7 +12,7 @@ #define HEAP_H #include -#include "allocator.h" +#include "avian/allocator.h" namespace vm { diff --git a/include/avian/vm/system/system.h b/include/avian/vm/system/system.h index ba6193a1ac..5404a24109 100644 --- a/include/avian/vm/system/system.h +++ b/include/avian/vm/system/system.h @@ -11,8 +11,8 @@ #ifndef SYSTEM_H #define SYSTEM_H -#include "common.h" -#include "allocator.h" +#include "avian/common.h" +#include "avian/allocator.h" #include namespace vm { diff --git a/src/arm.S b/src/arm.S index 23e66cefdd..a8c89f7ea1 100644 --- a/src/arm.S +++ b/src/arm.S @@ -9,7 +9,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "types.h" +#include "avian/types.h" .text diff --git a/src/alloc-vector.h b/src/avian/alloc-vector.h similarity index 99% rename from src/alloc-vector.h rename to src/avian/alloc-vector.h index fbdd1f5561..8b47a055db 100644 --- a/src/alloc-vector.h +++ b/src/avian/alloc-vector.h @@ -12,7 +12,7 @@ #define VECTOR_H #include -#include "target.h" +#include "avian/target.h" #include diff --git a/src/allocator.h b/src/avian/allocator.h similarity index 98% rename from src/allocator.h rename to src/avian/allocator.h index 5bad9044b3..782ff88b5a 100644 --- a/src/allocator.h +++ b/src/avian/allocator.h @@ -11,7 +11,7 @@ #ifndef ALLOCATOR_H #define ALLOCATOR_H -#include "common.h" +#include "avian/common.h" namespace vm { diff --git a/src/arch.h b/src/avian/arch.h similarity index 97% rename from src/arch.h rename to src/avian/arch.h index 70a64fefdb..4190e2a752 100644 --- a/src/arch.h +++ b/src/avian/arch.h @@ -19,7 +19,7 @@ # undef interface #endif -#include "common.h" +#include "avian/common.h" extern "C" void NO_RETURN vmJump(void* address, void* frame, void* stack, void* thread, diff --git a/src/arm.h b/src/avian/arm.h similarity index 99% rename from src/arm.h rename to src/avian/arm.h index 47c79ff099..f8f4a633e7 100644 --- a/src/arm.h +++ b/src/avian/arm.h @@ -11,8 +11,8 @@ #ifndef ARM_H #define ARM_H -#include "types.h" -#include "common.h" +#include "avian/types.h" +#include "avian/common.h" #include #ifdef __APPLE__ diff --git a/src/bootimage.h b/src/avian/bootimage.h similarity index 94% rename from src/bootimage.h rename to src/avian/bootimage.h index 6baf15ec00..b50379e8d8 100644 --- a/src/bootimage.h +++ b/src/avian/bootimage.h @@ -11,10 +11,10 @@ #ifndef BOOTIMAGE_H #define BOOTIMAGE_H -#include "common.h" +#include "avian/common.h" #include "java-common.h" -#include "target.h" -#include "machine.h" +#include "avian/target.h" +#include "avian/machine.h" #include diff --git a/src/classpath-common.h b/src/avian/classpath-common.h similarity index 100% rename from src/classpath-common.h rename to src/avian/classpath-common.h diff --git a/src/common.h b/src/avian/common.h similarity index 99% rename from src/common.h rename to src/avian/common.h index 498c96b7be..7d35383dfd 100644 --- a/src/common.h +++ b/src/avian/common.h @@ -20,7 +20,7 @@ #include "stddef.h" #include "string.h" #include "stdio.h" -#include "types.h" +#include "avian/types.h" #include "math.h" #ifdef _MSC_VER diff --git a/src/constants.h b/src/avian/constants.h similarity index 100% rename from src/constants.h rename to src/avian/constants.h diff --git a/src/embed.h b/src/avian/embed.h similarity index 100% rename from src/embed.h rename to src/avian/embed.h diff --git a/src/environment.h b/src/avian/environment.h similarity index 100% rename from src/environment.h rename to src/avian/environment.h diff --git a/src/finder.h b/src/avian/finder.h similarity index 98% rename from src/finder.h rename to src/avian/finder.h index d9f8480577..935734537e 100644 --- a/src/finder.h +++ b/src/avian/finder.h @@ -11,9 +11,9 @@ #ifndef FINDER_H #define FINDER_H -#include "common.h" +#include "avian/common.h" #include -#include "allocator.h" +#include "avian/allocator.h" namespace vm { diff --git a/src/heapwalk.h b/src/avian/heapwalk.h similarity index 97% rename from src/heapwalk.h rename to src/avian/heapwalk.h index 96c2374745..eac896fd5e 100644 --- a/src/heapwalk.h +++ b/src/avian/heapwalk.h @@ -11,7 +11,7 @@ #ifndef HEAPWALK_H #define HEAPWALK_H -#include "common.h" +#include "avian/common.h" #include "java-common.h" namespace vm { diff --git a/src/java-common.h b/src/avian/java-common.h similarity index 100% rename from src/java-common.h rename to src/avian/java-common.h diff --git a/src/jnienv.h b/src/avian/jnienv.h similarity index 97% rename from src/jnienv.h rename to src/avian/jnienv.h index 8dbd1f8c7d..06036e2b0d 100644 --- a/src/jnienv.h +++ b/src/avian/jnienv.h @@ -11,7 +11,7 @@ #ifndef JNIENV_H #define JNIENV_H -#include "machine.h" +#include "avian/machine.h" #define BOOTSTRAP_PROPERTY "avian.bootstrap" #define CRASHDIR_PROPERTY "avian.crash.dir" diff --git a/src/lzma-util.h b/src/avian/lzma-util.h similarity index 95% rename from src/lzma-util.h rename to src/avian/lzma-util.h index 76a249b378..cfe4103245 100644 --- a/src/lzma-util.h +++ b/src/avian/lzma-util.h @@ -11,10 +11,10 @@ #ifndef LZMA_UTIL_H #define LZMA_UTIL_H -#include "lzma.h" +#include "avian/lzma.h" #include "C/Types.h" #include -#include "allocator.h" +#include "avian/allocator.h" namespace vm { diff --git a/src/lzma.h b/src/avian/lzma.h similarity index 95% rename from src/lzma.h rename to src/avian/lzma.h index e0b9dd1e49..bd30671ed9 100644 --- a/src/lzma.h +++ b/src/avian/lzma.h @@ -12,7 +12,7 @@ #define LZMA_H #include -#include "allocator.h" +#include "avian/allocator.h" namespace vm { diff --git a/src/machine.h b/src/avian/machine.h similarity index 99% rename from src/machine.h rename to src/avian/machine.h index 70944a8a0c..ec0257491d 100644 --- a/src/machine.h +++ b/src/avian/machine.h @@ -11,14 +11,14 @@ #ifndef MACHINE_H #define MACHINE_H -#include "common.h" +#include "avian/common.h" #include "java-common.h" #include #include -#include "finder.h" -#include "processor.h" -#include "constants.h" -#include "arch.h" +#include "avian/finder.h" +#include "avian/processor.h" +#include "avian/constants.h" +#include "avian/arch.h" using namespace avian::util; diff --git a/src/powerpc.h b/src/avian/powerpc.h similarity index 99% rename from src/powerpc.h rename to src/avian/powerpc.h index 6be4d34286..fd1c9eaee5 100644 --- a/src/powerpc.h +++ b/src/avian/powerpc.h @@ -11,8 +11,8 @@ #ifndef POWERPC_H #define POWERPC_H -#include "types.h" -#include "common.h" +#include "avian/types.h" +#include "avian/common.h" #ifdef __APPLE__ # include "mach/mach_types.h" diff --git a/src/process.h b/src/avian/process.h similarity index 94% rename from src/process.h rename to src/avian/process.h index 71430c02b5..42fab2b2c9 100644 --- a/src/process.h +++ b/src/avian/process.h @@ -11,10 +11,10 @@ #ifndef PROCESS_H #define PROCESS_H -#include "common.h" +#include "avian/common.h" #include -#include "machine.h" -#include "constants.h" +#include "avian/machine.h" +#include "avian/constants.h" namespace vm { diff --git a/src/processor.h b/src/avian/processor.h similarity index 98% rename from src/processor.h rename to src/avian/processor.h index 63bf1c1d00..d6e3128433 100644 --- a/src/processor.h +++ b/src/avian/processor.h @@ -11,12 +11,12 @@ #ifndef PROCESSOR_H #define PROCESSOR_H -#include "common.h" +#include "avian/common.h" #include #include #include "bootimage.h" -#include "heapwalk.h" -#include "zone.h" +#include "avian/heapwalk.h" +#include "avian/zone.h" namespace avian { namespace codegen { diff --git a/src/target-fields.h b/src/avian/target-fields.h similarity index 100% rename from src/target-fields.h rename to src/avian/target-fields.h diff --git a/src/target.h b/src/avian/target.h similarity index 98% rename from src/target.h rename to src/avian/target.h index 42b07b1dc4..8f50e39dcd 100644 --- a/src/target.h +++ b/src/avian/target.h @@ -11,8 +11,8 @@ #ifndef TARGET_H #define TARGET_H -#include "target-fields.h" -#include "common.h" +#include "avian/target-fields.h" +#include "avian/common.h" namespace vm { diff --git a/src/types.h b/src/avian/types.h similarity index 100% rename from src/types.h rename to src/avian/types.h diff --git a/src/util.h b/src/avian/util.h similarity index 98% rename from src/util.h rename to src/avian/util.h index 40a70b5bfb..1dceaf108a 100644 --- a/src/util.h +++ b/src/avian/util.h @@ -11,8 +11,8 @@ #ifndef UTIL_H #define UTIL_H -#include "machine.h" -#include "zone.h" +#include "avian/machine.h" +#include "avian/zone.h" namespace vm { diff --git a/src/x86.h b/src/avian/x86.h similarity index 99% rename from src/x86.h rename to src/avian/x86.h index bda55bee7d..be043e70de 100644 --- a/src/x86.h +++ b/src/avian/x86.h @@ -11,8 +11,8 @@ #ifndef X86_H #define X86_H -#include "types.h" -#include "common.h" +#include "avian/types.h" +#include "avian/common.h" #ifdef _MSC_VER # include "windows.h" diff --git a/src/zlib-custom.h b/src/avian/zlib-custom.h similarity index 100% rename from src/zlib-custom.h rename to src/avian/zlib-custom.h diff --git a/src/zone.h b/src/avian/zone.h similarity index 99% rename from src/zone.h rename to src/avian/zone.h index ca467de7d6..56da22faff 100644 --- a/src/zone.h +++ b/src/avian/zone.h @@ -12,7 +12,7 @@ #define ZONE_H #include -#include "allocator.h" +#include "avian/allocator.h" #include diff --git a/src/builtin.cpp b/src/builtin.cpp index 713c4a98ee..6991748de8 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -8,10 +8,10 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "machine.h" -#include "constants.h" -#include "processor.h" -#include "util.h" +#include "avian/machine.h" +#include "avian/constants.h" +#include "avian/processor.h" +#include "avian/util.h" #include diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 356c445f4d..d70f3defe2 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -14,9 +14,9 @@ extern "C" int JNI_OnLoad(JavaVM*, void*); #define _POSIX_C_SOURCE 200112L #undef _GNU_SOURCE -#include "machine.h" -#include "classpath-common.h" -#include "process.h" +#include "avian/machine.h" +#include "avian/classpath-common.h" +#include "avian/process.h" using namespace vm; diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 144e2e42b9..f0ea0367e7 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -8,9 +8,9 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "machine.h" -#include "classpath-common.h" -#include "process.h" +#include "avian/machine.h" +#include "avian/classpath-common.h" +#include "avian/process.h" #include diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index ca79619ade..02522e5126 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -8,10 +8,10 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "machine.h" -#include "classpath-common.h" -#include "util.h" -#include "process.h" +#include "avian/machine.h" +#include "avian/classpath-common.h" +#include "avian/util.h" +#include "avian/process.h" #ifdef PLATFORM_WINDOWS diff --git a/src/codegen/arm/assembler.cpp b/src/codegen/arm/assembler.cpp index 26e57a5cb5..e55676af3a 100644 --- a/src/codegen/arm/assembler.cpp +++ b/src/codegen/arm/assembler.cpp @@ -11,7 +11,7 @@ #include #include -#include "alloc-vector.h" +#include "avian/alloc-vector.h" #include #include diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index fa453974e5..390fc3fd9d 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index f07706e499..326d8e4f1d 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include #include diff --git a/src/codegen/compiler/frame.cpp b/src/codegen/compiler/frame.cpp index e879238b79..4c696f0d83 100644 --- a/src/codegen/compiler/frame.cpp +++ b/src/codegen/compiler/frame.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include "codegen/compiler/context.h" #include "codegen/compiler/frame.h" diff --git a/src/codegen/compiler/promise.cpp b/src/codegen/compiler/promise.cpp index fc5a69da63..4363025a4c 100644 --- a/src/codegen/compiler/promise.cpp +++ b/src/codegen/compiler/promise.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include "codegen/compiler/context.h" #include "codegen/compiler/promise.h" diff --git a/src/codegen/compiler/read.cpp b/src/codegen/compiler/read.cpp index 1b90878c1e..aa6b270cb0 100644 --- a/src/codegen/compiler/read.cpp +++ b/src/codegen/compiler/read.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include "codegen/compiler/context.h" #include "codegen/compiler/value.h" diff --git a/src/codegen/compiler/regalloc.cpp b/src/codegen/compiler/regalloc.cpp index 60fb2c7100..47501fdb87 100644 --- a/src/codegen/compiler/regalloc.cpp +++ b/src/codegen/compiler/regalloc.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include "codegen/compiler/regalloc.h" #include "codegen/compiler/context.h" diff --git a/src/codegen/compiler/regalloc.h b/src/codegen/compiler/regalloc.h index 7bc7b6e8e0..66ab860a07 100644 --- a/src/codegen/compiler/regalloc.h +++ b/src/codegen/compiler/regalloc.h @@ -11,7 +11,7 @@ #ifndef AVIAN_CODEGEN_COMPILER_REGALLOC_H #define AVIAN_CODEGEN_COMPILER_REGALLOC_H -#include "common.h" +#include "avian/common.h" #include #include diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp index dc877b9e1e..30742a56ae 100644 --- a/src/codegen/compiler/site.cpp +++ b/src/codegen/compiler/site.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include "codegen/compiler/context.h" #include "codegen/compiler/value.h" diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp index 58c3f341ae..fcfa7d9946 100644 --- a/src/codegen/compiler/value.cpp +++ b/src/codegen/compiler/value.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "target.h" +#include "avian/target.h" #include "codegen/compiler/regalloc.h" #include "codegen/compiler/site.h" diff --git a/src/codegen/powerpc/assembler.cpp b/src/codegen/powerpc/assembler.cpp index 5086d48403..1d886af252 100644 --- a/src/codegen/powerpc/assembler.cpp +++ b/src/codegen/powerpc/assembler.cpp @@ -11,7 +11,7 @@ #include #include -#include "alloc-vector.h" +#include "avian/alloc-vector.h" #include #define CAST1(x) reinterpret_cast(x) diff --git a/src/codegen/targets.cpp b/src/codegen/targets.cpp index 4b9d44fc7e..ba9276746d 100644 --- a/src/codegen/targets.cpp +++ b/src/codegen/targets.cpp @@ -10,7 +10,7 @@ #include -#include "environment.h" +#include "avian/environment.h" namespace avian { namespace codegen { diff --git a/src/codegen/x86/assembler.cpp b/src/codegen/x86/assembler.cpp index 90eea322fc..e96f855448 100644 --- a/src/codegen/x86/assembler.cpp +++ b/src/codegen/x86/assembler.cpp @@ -8,9 +8,9 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "environment.h" -#include "target.h" -#include "alloc-vector.h" +#include "avian/environment.h" +#include "avian/target.h" +#include "avian/alloc-vector.h" #include #include diff --git a/src/compile-arm.S b/src/compile-arm.S index 7db96279e9..be63018e3e 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "types.h" -#include "target-fields.h" +#include "avian/types.h" +#include "avian/target-fields.h" .text diff --git a/src/compile-powerpc.S b/src/compile-powerpc.S index 667ae40ed7..f843210526 100644 --- a/src/compile-powerpc.S +++ b/src/compile-powerpc.S @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "types.h" -#include "target-fields.h" +#include "avian/types.h" +#include "avian/target-fields.h" .text diff --git a/src/compile-x86.S b/src/compile-x86.S index c15ec2cb7d..9c4f2909d9 100644 --- a/src/compile-x86.S +++ b/src/compile-x86.S @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "types.h" -#include "target-fields.h" +#include "avian/types.h" +#include "avian/target-fields.h" #define LOCAL(x) .L##x diff --git a/src/compile.cpp b/src/compile.cpp index 02a87cd4c8..8033cda49f 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -8,12 +8,12 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "machine.h" -#include "util.h" -#include "alloc-vector.h" -#include "process.h" -#include "target.h" -#include "arch.h" +#include "avian/machine.h" +#include "avian/util.h" +#include "avian/alloc-vector.h" +#include "avian/process.h" +#include "avian/target.h" +#include "avian/arch.h" #include #include diff --git a/src/embed.cpp b/src/embed.cpp index 293169ce78..e853087239 100644 --- a/src/embed.cpp +++ b/src/embed.cpp @@ -15,7 +15,7 @@ #include #include -#include "embed.h" +#include "avian/embed.h" #ifdef __x86_64__ # define BINARY_LOADER(x) _binary_loader_##x diff --git a/src/embedded-loader.cpp b/src/embedded-loader.cpp index eb5b26f359..bea3bec57e 100644 --- a/src/embedded-loader.cpp +++ b/src/embedded-loader.cpp @@ -12,7 +12,7 @@ #include #include -#include "embed.h" +#include "avian/embed.h" #include "jni.h" #if (defined __MINGW32__) || (defined _MSC_VER) diff --git a/src/finder.cpp b/src/finder.cpp index a3fa539910..7f4757803f 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -12,9 +12,9 @@ #include #include -#include "zlib-custom.h" -#include "finder.h" -#include "lzma.h" +#include "avian/zlib-custom.h" +#include "avian/finder.h" +#include "avian/lzma.h" using namespace vm; diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index 6257e45618..01b6cffec8 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -10,8 +10,8 @@ #include #include -#include "common.h" -#include "arch.h" +#include "avian/common.h" +#include "avian/arch.h" #include diff --git a/src/heapdump.cpp b/src/heapdump.cpp index da283e61a1..b68a22b6c7 100644 --- a/src/heapdump.cpp +++ b/src/heapdump.cpp @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "machine.h" -#include "heapwalk.h" +#include "avian/machine.h" +#include "avian/heapwalk.h" using namespace vm; diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index 8732d28497..977ab85bac 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "machine.h" -#include "heapwalk.h" +#include "avian/machine.h" +#include "avian/heapwalk.h" using namespace vm; diff --git a/src/interpret.cpp b/src/interpret.cpp index 68cb0e972b..cc68a4b79f 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -8,13 +8,13 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "common.h" +#include "avian/common.h" #include -#include "constants.h" -#include "machine.h" -#include "processor.h" -#include "process.h" -#include "arch.h" +#include "avian/constants.h" +#include "avian/machine.h" +#include "avian/processor.h" +#include "avian/process.h" +#include "avian/arch.h" #include diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 8722be07ef..b2e9507cd8 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -8,11 +8,11 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "jnienv.h" -#include "machine.h" -#include "util.h" -#include "processor.h" -#include "constants.h" +#include "avian/jnienv.h" +#include "avian/machine.h" +#include "avian/util.h" +#include "avian/processor.h" +#include "avian/constants.h" #include diff --git a/src/machine.cpp b/src/machine.cpp index 528faac785..ca2c57aa86 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -8,14 +8,14 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "jnienv.h" -#include "machine.h" -#include "util.h" +#include "avian/jnienv.h" +#include "avian/machine.h" +#include "avian/util.h" #include -#include "constants.h" -#include "processor.h" -#include "arch.h" -#include "lzma.h" +#include "avian/constants.h" +#include "avian/processor.h" +#include "avian/arch.h" +#include "avian/lzma.h" #include #include diff --git a/src/main.cpp b/src/main.cpp index 53760b753d..8876011e79 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ #include "jni.h" #include -#include "finder.h" +#include "avian/finder.h" #include diff --git a/src/powerpc.S b/src/powerpc.S index ec685da04b..1d85861e0f 100644 --- a/src/powerpc.S +++ b/src/powerpc.S @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "types.h" +#include "avian/types.h" .text diff --git a/src/process.cpp b/src/process.cpp index 6f1c5dbbd8..f2630a0a6f 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "process.h" +#include "avian/process.h" #include diff --git a/src/tools/bootimage-generator/main.cpp b/src/tools/bootimage-generator/main.cpp index 0fadd61034..8836c29970 100644 --- a/src/tools/bootimage-generator/main.cpp +++ b/src/tools/bootimage-generator/main.cpp @@ -9,17 +9,17 @@ details. */ #include -#include "heapwalk.h" -#include "common.h" -#include "machine.h" -#include "util.h" +#include "avian/heapwalk.h" +#include "avian/common.h" +#include "avian/machine.h" +#include "avian/util.h" #include #include #include -#include "target.h" +#include "avian/target.h" #include #include -#include "lzma.h" +#include "avian/lzma.h" // since we aren't linking against libstdc++, we must implement this // ourselves: diff --git a/src/tools/type-generator/main.cpp b/src/tools/type-generator/main.cpp index fbd4fd6909..3ac2ab3a24 100644 --- a/src/tools/type-generator/main.cpp +++ b/src/tools/type-generator/main.cpp @@ -14,8 +14,8 @@ #include "string.h" #include "errno.h" -#include "constants.h" -#include "finder.h" +#include "avian/constants.h" +#include "avian/finder.h" #include #include "io.h" diff --git a/src/util.cpp b/src/util.cpp index 915913e6e1..248277aef6 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "util.h" +#include "avian/util.h" using namespace vm; diff --git a/src/vm/system/posix.cpp b/src/vm/system/posix.cpp index 5fcfd4d3ae..81d9c39246 100644 --- a/src/vm/system/posix.cpp +++ b/src/vm/system/posix.cpp @@ -48,7 +48,7 @@ #include "stdint.h" #include "dirent.h" #include "sched.h" -#include "arch.h" +#include "avian/arch.h" #include #include diff --git a/src/vm/system/windows.cpp b/src/vm/system/windows.cpp index 45b03f6dfe..5c4a68cffd 100644 --- a/src/vm/system/windows.cpp +++ b/src/vm/system/windows.cpp @@ -23,7 +23,7 @@ #undef max #undef min -#include "arch.h" +#include "avian/arch.h" #include #include diff --git a/src/x86.S b/src/x86.S index 2a0096ec85..cd8682f71d 100644 --- a/src/x86.S +++ b/src/x86.S @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "types.h" +#include "avian/types.h" #define LOCAL(x) .L##x diff --git a/unittest/codegen/assembler-test.cpp b/unittest/codegen/assembler-test.cpp index f0135d2d64..99c464a643 100644 --- a/unittest/codegen/assembler-test.cpp +++ b/unittest/codegen/assembler-test.cpp @@ -10,10 +10,10 @@ #include -#include "common.h" +#include "avian/common.h" #include #include -#include "target.h" +#include "avian/target.h" #include #include diff --git a/unittest/test-harness.cpp b/unittest/test-harness.cpp index 30472298ba..2bee3d3363 100644 --- a/unittest/test-harness.cpp +++ b/unittest/test-harness.cpp @@ -10,7 +10,7 @@ #include -#include "common.h" +#include "avian/common.h" #include "test-harness.h" // since we aren't linking against libstdc++, we must implement this From 27d7c8a3c0ac05cf87f9c3e237197f39c91dfd9a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 Feb 2013 13:47:43 -0700 Subject: [PATCH 315/378] skip bootimage test in ci.sh if openjdk is set --- test/ci.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/ci.sh b/test/ci.sh index 555ce4687e..1fb490da3c 100755 --- a/test/ci.sh +++ b/test/ci.sh @@ -5,5 +5,8 @@ set -e make mode=debug test make test make process=interpret test -make bootimage=true test +# bootimage and openjdk builds without openjdk-src don't work: +if [ -z "${openjdk}" ]; then + make bootimage=true test +fi make tails=true continuations=true test From b409bba318513c62b04b3fe44028ca733b26e6bd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 28 Feb 2013 08:17:16 -0700 Subject: [PATCH 316/378] link makefile.in to Makefile.in for Android fdlibm build --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bea99be1e..a608867aec 100644 --- a/README.md +++ b/README.md @@ -368,7 +368,8 @@ this way, do the following, starting from the Avian directory: $ git clone https://github.com/dicej/android-libcore64 libcore $ (cd expat && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ && make) - $ (cd fdlibm && CFLAGS=-fPIC bash configure && make) + $ (cd fdlibm && ln -sf makefile.in Makefile.in \ + && CFLAGS=-fPIC bash configure && make) $ (cd icu4c && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ && make) $ (cd openssl-upstream && git checkout OpenSSL_1_0_1e \ From 625c04e78679cc3dabb3289c832ede3a0e5a1e62 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 28 Feb 2013 10:15:10 -0700 Subject: [PATCH 317/378] a few tweaks to fix the OS X Android class library build With corresponding changes to libcore, all the tests are passing except Datagrams, which fails with a NPE in NetworkInterface.getNetworkInterfacesList due to OS X not having /sys/class/net. Porting that class to OS X looks like a non-trivial task. --- README.md | 12 ++++++++---- makefile | 5 ++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a608867aec..b4d47e1183 100644 --- a/README.md +++ b/README.md @@ -350,9 +350,9 @@ Building with the Android Class Library --------------------------------------- As an alternative to both the Avian and OpenJDK class libaries, you -can also build with the Android Class Library on some platforms -(currently just Linux, but possibly others in the future). To build -this way, do the following, starting from the Avian directory: +can also build with the Android class library on some platforms +(currently Linux works and OS X mostly works). To build this way, do +the following, starting from the Avian directory: $ cd .. $ mkdir android @@ -368,10 +368,14 @@ this way, do the following, starting from the Avian directory: $ git clone https://github.com/dicej/android-libcore64 libcore $ (cd expat && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ && make) - $ (cd fdlibm && ln -sf makefile.in Makefile.in \ + $ (cd fdlibm && (mv makefile.in Makefile.in || true) \ && CFLAGS=-fPIC bash configure && make) $ (cd icu4c && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ && make) + +NB: use 'CC="gcc -fPIC" ./Configure darwin64-x86_64-cc' when building +for x86_64 OS X instead of 'CC="gcc -fPIC" ./config': + $ (cd openssl-upstream && git checkout OpenSSL_1_0_1e \ && (for x in ../openssl/patches/*.patch; do patch -p1 < $x; done) \ && CC="gcc -fPIC" ./config && make) diff --git a/makefile b/makefile index b6a64695b5..b5599dbe89 100755 --- a/makefile +++ b/makefile @@ -169,8 +169,7 @@ ifneq ($(android),) -D_FILE_OFFSET_BITS=64 \ -g3 \ -Werror \ - -fPIC \ - -fvisibility=hidden + -fPIC classpath-lflags := \ $(android)/icu4c/lib/libicui18n.a \ $(android)/icu4c/lib/libicuuc.a \ @@ -1442,7 +1441,7 @@ $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas) cp $(android)/fdlibm/fdlibm.h $(build)/android-src/external/fdlibm/ cp $(android)/expat/lib/expat.h $(build)/android-src/libexpat/ cp -a $(luni-java)/* $(dalvik-java)/* $(xml-java)/* $(build)/android-src/ - sed -i 's/return ordinal - o.ordinal;/return ordinal - o.ordinal();/' \ + sed -i -e 's/return ordinal - o.ordinal;/return ordinal - o.ordinal();/' \ $(build)/android-src/java/lang/Enum.java find $(build)/android-src -name '*.java' > $(build)/android.txt $(javac) -Xmaxerrs 1000 -d $(build)/android -sourcepath $(luni-java) \ From 0b01dd565aa730b395911a06a555aa4f819bfea0 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 28 Feb 2013 15:57:09 -0700 Subject: [PATCH 318/378] fix multiple-include-of-stdint errors --- src/avian/common.h | 8 ++++---- src/codegen/target/x86/assembler.cpp | 1 - src/codegen/target/x86/operations.cpp | 2 -- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/avian/common.h b/src/avian/common.h index dc5281511c..4fad202fe4 100644 --- a/src/avian/common.h +++ b/src/avian/common.h @@ -8,8 +8,8 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#ifndef COMMON_H -#define COMMON_H +#ifndef AVIAN_COMMON_H +#define AVIAN_COMMON_H #ifndef __STDC_CONSTANT_MACROS # define __STDC_CONSTANT_MACROS @@ -113,7 +113,7 @@ typedef intptr_t intptr_alias_t; #else // not _MSC_VER -# include "stdint.h" +# include # define BYTES_PER_WORD __SIZEOF_POINTER__ @@ -554,4 +554,4 @@ equal(const void* a, unsigned al, const void* b, unsigned bl) } // namespace vm -#endif // COMMON_H +#endif // AVIAN_COMMON_H diff --git a/src/codegen/target/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp index d441c0030b..af289135cf 100644 --- a/src/codegen/target/x86/assembler.cpp +++ b/src/codegen/target/x86/assembler.cpp @@ -9,7 +9,6 @@ details. */ #include -#include #include #include "avian/environment.h" diff --git a/src/codegen/target/x86/operations.cpp b/src/codegen/target/x86/operations.cpp index 13f6f1b0d6..477c3a8859 100644 --- a/src/codegen/target/x86/operations.cpp +++ b/src/codegen/target/x86/operations.cpp @@ -8,8 +8,6 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include - #include "avian/target.h" #include "avian/alloc-vector.h" #include "avian/allocator.h" From add029ad3cf81a19df2d20226ac3c59060cab480 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 28 Feb 2013 16:41:44 -0700 Subject: [PATCH 319/378] fix powerpc build Evidently, the powerpc gcc compiler feels it necessary to #define powerpc to 1. Seriously? SERIOUSLY???? --- src/avian/common.h | 8 ++++++++ src/codegen/target/powerpc/context.h | 3 +++ src/codegen/target/powerpc/encode.h | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/src/avian/common.h b/src/avian/common.h index 4fad202fe4..f8a0e22168 100644 --- a/src/avian/common.h +++ b/src/avian/common.h @@ -27,6 +27,14 @@ #include "float.h" +#ifdef powerpc +# undef powerpc +#endif + +#ifdef linux +# undef linux +#endif + // don't complain about using 'this' in member initializers: # pragma warning(disable:4355) diff --git a/src/codegen/target/powerpc/context.h b/src/codegen/target/powerpc/context.h index 4e12f4882c..7726b88cf5 100644 --- a/src/codegen/target/powerpc/context.h +++ b/src/codegen/target/powerpc/context.h @@ -14,6 +14,9 @@ #include #include "avian/alloc-vector.h" +#ifdef powerpc +#undef powerpc +#endif namespace vm { class System; diff --git a/src/codegen/target/powerpc/encode.h b/src/codegen/target/powerpc/encode.h index 54f7f7f493..811ddce402 100644 --- a/src/codegen/target/powerpc/encode.h +++ b/src/codegen/target/powerpc/encode.h @@ -11,6 +11,10 @@ #ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_ENCODE_H #define AVIAN_CODEGEN_ASSEMBLER_POWERPC_ENCODE_H +#ifdef powerpc +#undef powerpc +#endif + namespace avian { namespace codegen { namespace powerpc { From df23c379bfebce0d493db41df456c399fc2fdb90 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 1 Mar 2013 14:52:27 -0700 Subject: [PATCH 320/378] fix windows embed-loader build --- makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/makefile b/makefile index cfbcabd9b2..911861cfce 100755 --- a/makefile +++ b/makefile @@ -1564,19 +1564,18 @@ $(embed-loader-o): $(embed-loader) $(converter) $(converter) $(<) $(@) _binary_loader_start \ _binary_loader_end $(target-format) $(arch) -$(embed-loader): $(embed-loader-objects) $(static-library) - @mkdir -p $(dir $(@)) - cd $(dir $(@)) && $(ar) x ../../../$(static-library) +$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) ifdef ms_cl_compiler - $(ld) $(lflags) $(dir $(@))/*.o -out:$(@) \ + $(ld) $(lflags) $(^) -out:$(@) \ -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" endif else - $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(dir $(@))/*.o + $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(^) $(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@))) - $(ld) $(addsuffix .exp,$(basename $(@))) $(dir $(@))/*.o \ + $(ld) $(addsuffix .exp,$(basename $(@))) $(^) \ $(lflags) $(bootimage-lflags) -o $(@) endif $(strip) $(strip-all) $(@) From 5b973c8fc39bd106d16c02c483e815f61771da04 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 1 Mar 2013 16:27:41 -0700 Subject: [PATCH 321/378] fix bootimage build --- src/tools/bootimage-generator/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/bootimage-generator/main.cpp b/src/tools/bootimage-generator/main.cpp index bb7a2a5b2b..d27d250ab8 100644 --- a/src/tools/bootimage-generator/main.cpp +++ b/src/tools/bootimage-generator/main.cpp @@ -22,7 +22,7 @@ #include "avian/lzma.h" #include -#include "util/abort.h" +#include // since we aren't linking against libstdc++, we must implement this // ourselves: From 7726bf49dea85318309dadd817013565bd42ac2a Mon Sep 17 00:00:00 2001 From: Zsombor Gegesy Date: Sat, 2 Mar 2013 22:26:24 +0100 Subject: [PATCH 322/378] fix lzma includes --- src/lzma-decode.cpp | 2 +- src/lzma-encode.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lzma-decode.cpp b/src/lzma-decode.cpp index 874e6f584d..d0a2c8cbbd 100644 --- a/src/lzma-decode.cpp +++ b/src/lzma-decode.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "lzma-util.h" +#include "avian/lzma-util.h" #include "C/LzmaDec.h" using namespace vm; diff --git a/src/lzma-encode.cpp b/src/lzma-encode.cpp index cc7f8ad178..e488e2441d 100644 --- a/src/lzma-encode.cpp +++ b/src/lzma-encode.cpp @@ -8,7 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "lzma-util.h" +#include "avian/lzma-util.h" #include "C/LzmaEnc.h" using namespace vm; From b3978c0a0a4a3fb598eb38fe6d9e235a1af7f9ba Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Mar 2013 11:09:59 -0700 Subject: [PATCH 323/378] fix msvc build --- classpath/java-io.cpp | 2 +- include/avian/util/math.h | 3 +++ makefile | 34 +++++++++++++++++++--------------- src/avian/alloc-vector.h | 3 +++ src/avian/common.h | 18 +----------------- src/avian/machine.h | 3 --- src/bootimage-template.cpp | 2 +- src/util/arg-parser.cpp | 1 + 8 files changed, 29 insertions(+), 37 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index f2e9fd3c18..ff6bc8fffc 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -859,7 +859,7 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer, uint8_t* dst = reinterpret_cast (e->GetPrimitiveArrayCritical(buffer, 0)); - ssize_t bytesRead = ::read(fd, dst + offset, length); + int64_t bytesRead = ::read(fd, dst + offset, length); e->ReleasePrimitiveArrayCritical(buffer, dst, 0); if(bytesRead == -1) { diff --git a/include/avian/util/math.h b/include/avian/util/math.h index ecd4f18fc5..25337abb47 100644 --- a/include/avian/util/math.h +++ b/include/avian/util/math.h @@ -11,6 +11,9 @@ #ifndef AVIAN_UTIL_MATH_H #define AVIAN_UTIL_MATH_H +#undef max +#undef min + namespace avian { namespace util { diff --git a/makefile b/makefile index 964768539c..912a2c1886 100755 --- a/makefile +++ b/makefile @@ -873,20 +873,23 @@ endif ifdef msvc no-error = + target-format = pe windows-path = $(native-path) windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") zlib := $(shell $(windows-path) "$(win32)/msvc") ms_cl_compiler = regular + as = $(build-cc) cxx = "$(msvc)/BIN/cl.exe" cc = $(cxx) ld = "$(msvc)/BIN/link.exe" mt = "mt.exe" + ar = "$(msvc)/BIN/lib.exe" manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I$(classpath-src) \ - -I"$(build)" \ + -I"$(build)" -Iinclude \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ -DTARGET_BYTES_PER_WORD=$(pointer-size) @@ -899,21 +902,18 @@ ifdef msvc -DEFAULTLIB:zlib -DEFAULTLIB:user32 -MANIFEST -debug output = -Fo$(1) - ifeq ($(mode),debug) - cflags += -Od -Zi -MDd - endif - ifeq ($(mode),debug-fast) - cflags += -Od -Zi -DNDEBUG - endif + cflags_debug = -Od -Zi -MDd + cflags_debug_fast = -Od -Zi -DNDEBUG + cflags_fast = -O2 -GL -Zi -DNDEBUG + cflags_small = -O1s -Zi -GL -DNDEBUG ifeq ($(mode),fast) - cflags += -O2 -GL -Zi -DNDEBUG lflags += -LTCG endif ifeq ($(mode),small) - cflags += -O1s -Zi -GL -DNDEBUG lflags += -LTCG endif + use-lto = false strip = : endif @@ -1026,19 +1026,15 @@ compiler-sources = \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp compiler-objects = $(call cpp-objects,$(compiler-sources),$(src),$(build)) -$(compiler-objects): $(wildcard $(src)/codegen/compiler/*.h) $(vm-depends) x86-assembler-sources = $(wildcard $(src)/codegen/target/x86/*.cpp) x86-assembler-objects = $(call cpp-objects,$(x86-assembler-sources),$(src),$(build)) -$(x86-assembler-objects): $(wildcard $(src)/codegen/target/x86/*.h) $(vm-depends) arm-assembler-sources = $(wildcard $(src)/codegen/target/arm/*.cpp) arm-assembler-objects = $(call cpp-objects,$(arm-assembler-sources),$(src),$(build)) -$(arm-assembler-objects): $(wildcard $(src)/codegen/target/arm/*.h) $(vm-depends) powerpc-assembler-sources = $(wildcard $(src)/codegen/target/powerpc/*.cpp) powerpc-assembler-objects = $(call cpp-objects,$(powerpc-assembler-sources),$(src),$(build)) -$(powerpc-assembler-objects): $(wildcard $(src)/codegen/target/powerpc/*.h) $(vm-depends) all-assembler-sources = \ $(x86-assembler-sources) \ @@ -1352,6 +1348,14 @@ $(test-dep): $(classpath-dep) $(test-extra-dep): $(classpath-dep) +$(compiler-objects): $(wildcard $(src)/codegen/compiler/*.h) $(vm-depends) + +$(x86-assembler-objects): $(wildcard $(src)/codegen/target/x86/*.h) $(vm-depends) + +$(arm-assembler-objects): $(wildcard $(src)/codegen/target/arm/*.h) $(vm-depends) + +$(powerpc-assembler-objects): $(wildcard $(src)/codegen/target/powerpc/*.h) $(vm-depends) + .PHONY: run run: build $(library-path) $(test-executable) $(test-args) @@ -1507,7 +1511,7 @@ endef define compile-unittest-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) $(cflags) -c $$($(windows-path) -I$(unittest) $(<)) $(call output,$(@)) + $(cxx) $(cflags) -c $$($(windows-path) $(<)) -I$(unittest) $(call output,$(@)) endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) @@ -1814,7 +1818,7 @@ $(executable-dynamic): $(driver-dynamic-objects) $(dynamic-library) @echo "linking $(@)" ifdef ms_cl_compiler $(ld) $(lflags) -LIBPATH:$(build) -DEFAULTLIB:$(name) \ - -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) \ $(driver-dynamic-objects) -out:$(@) $(manifest-flags) ifdef mt $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" diff --git a/src/avian/alloc-vector.h b/src/avian/alloc-vector.h index 8b47a055db..940f978bd2 100644 --- a/src/avian/alloc-vector.h +++ b/src/avian/alloc-vector.h @@ -16,6 +16,9 @@ #include +#undef max +#undef min + namespace vm { class Vector { diff --git a/src/avian/common.h b/src/avian/common.h index f8a0e22168..f3618a8e83 100644 --- a/src/avian/common.h +++ b/src/avian/common.h @@ -26,6 +26,7 @@ #ifdef _MSC_VER #include "float.h" +#include #ifdef powerpc # undef powerpc @@ -38,15 +39,6 @@ // don't complain about using 'this' in member initializers: # pragma warning(disable:4355) -typedef char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - #define strncasecmp _strnicmp #define FP_NAN 0 @@ -66,11 +58,6 @@ inline int fpclassify(double d) { return FP_UNDEF; } -#define INT32_MIN ((int32_t) _I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t) _I64_MIN) -#define INT64_MAX _I64_MAX - inline int signbit(double d) { return _copysign(1.0, d) < 0; } @@ -94,19 +81,16 @@ inline int signbit(double d) { # ifdef _M_IX86 typedef int32_t intptr_t; typedef uint32_t uintptr_t; -# define UINT64_C(x) x##LL # define ARCH_x86_32 # define BYTES_PER_WORD 4 # elif defined _M_X64 typedef int64_t intptr_t; typedef uint64_t uintptr_t; -# define UINT64_C(x) x##L # define ARCH_x86_64 # define BYTES_PER_WORD 8 # elif defined _M_ARM_FP typedef int32_t intptr_t; typedef uint32_t uintptr_t; -# define UINT64_C(x) x##LL # define ARCH_arm # define BYTES_PER_WORD 4 # else diff --git a/src/avian/machine.h b/src/avian/machine.h index ec0257491d..fca793c055 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1329,9 +1329,6 @@ checkDaemon(Thread* t); object& root(Thread* t, Machine::Root root); -#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) -# define vmRun vmRun_ -#endif extern "C" uint64_t vmRun(uint64_t (*function)(Thread*, uintptr_t*), uintptr_t* arguments, void* checkpoint); diff --git a/src/bootimage-template.cpp b/src/bootimage-template.cpp index 86df096777..bf32267ece 100644 --- a/src/bootimage-template.cpp +++ b/src/bootimage-template.cpp @@ -1,7 +1,7 @@ const unsigned NAME(BootMask) = (~static_cast(0)) / NAME(BytesPerWord); -const unsigned NAME(BootShift) = 32 - log(NAME(BytesPerWord)); +const unsigned NAME(BootShift) = 32 - avian::util::log(NAME(BytesPerWord)); const unsigned NAME(BootFlatConstant) = 1 << NAME(BootShift); const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1); diff --git a/src/util/arg-parser.cpp b/src/util/arg-parser.cpp index cefc221532..1d87051819 100644 --- a/src/util/arg-parser.cpp +++ b/src/util/arg-parser.cpp @@ -11,6 +11,7 @@ #include #include +#include #include namespace avian { From 5d730fe8fabe71a0456a050b4cad7b0c7d29a22d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Mar 2013 14:24:41 -0700 Subject: [PATCH 324/378] various tweaks to get hello-ios working with the Android library --- makefile | 57 ++++++++++++++++++++++--------------------- src/android/stubs.cpp | 6 +++++ 2 files changed, 35 insertions(+), 28 deletions(-) create mode 100644 src/android/stubs.cpp diff --git a/makefile b/makefile index 912a2c1886..a0ccb8c803 100755 --- a/makefile +++ b/makefile @@ -292,11 +292,11 @@ converter-cflags = -D__STDC_CONSTANT_MACROS -Iinclude/ -Isrc/ \ cflags = $(build-cflags) -common-lflags = -lm -lz $(classpath-lflags) +common-lflags = -lm -lz build-lflags = -lz -lpthread -ldl -lflags = $(common-lflags) $(classpath-lflags) -lpthread -ldl +lflags = $(common-lflags) -lpthread -ldl soname-flag = -Wl,-soname -Wl,$(so-prefix)jvm$(so-suffix) version-script-flag = -Wl,--version-script=openjdk.ld @@ -580,34 +580,37 @@ ifeq ($(platform),darwin) flags = -arch armv7 -isysroot \ $(sdk-dir)/iPhoneOS$(ios-version).sdk/ - openjdk-extra-cflags += $(flags) + classpath-extra-cflags += $(flags) cflags += $(flags) asmflags += $(flags) lflags += $(flags) endif ifeq ($(arch),powerpc) - openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} + classpath-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} lflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} endif ifeq ($(arch),i386) - openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} + classpath-extra-cflags += \ + -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} lflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} endif ifeq ($(arch),x86_64) - openjdk-extra-cflags += -arch x86_64 + classpath-extra-cflags += -arch x86_64 cflags += -arch x86_64 asmflags += -arch x86_64 lflags += -arch x86_64 endif endif +openjdk-extra-cflags += $(classpath-extra-cflags) + ifeq ($(platform),windows) ifeq ($(target-format),) target-format = pe @@ -785,7 +788,7 @@ ifeq ($(platform),wp8) -DTARGET_BYTES_PER_WORD=$(pointer-size) \ -Gd -EHsc - common-lflags = $(classpath-lflags) + common-lflags = ifeq ($(mode),debug) build-type = Debug @@ -1025,16 +1028,12 @@ compiler-sources = \ $(wildcard $(src)/codegen/compiler/*.cpp) \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp -compiler-objects = $(call cpp-objects,$(compiler-sources),$(src),$(build)) x86-assembler-sources = $(wildcard $(src)/codegen/target/x86/*.cpp) -x86-assembler-objects = $(call cpp-objects,$(x86-assembler-sources),$(src),$(build)) arm-assembler-sources = $(wildcard $(src)/codegen/target/arm/*.cpp) -arm-assembler-objects = $(call cpp-objects,$(arm-assembler-sources),$(src),$(build)) powerpc-assembler-sources = $(wildcard $(src)/codegen/target/powerpc/*.cpp) -powerpc-assembler-objects = $(call cpp-objects,$(powerpc-assembler-sources),$(src),$(build)) all-assembler-sources = \ $(x86-assembler-sources) \ @@ -1042,7 +1041,6 @@ all-assembler-sources = \ $(powerpc-assembler-sources) native-assembler-sources = $($(target-asm)-assembler-sources) -native-assembler-objects = $($(target-asm)-assembler-objects) audit-codegen-sources = $(wildcard $(src)/tools/audit-codegen/*.cpp) @@ -1098,6 +1096,9 @@ bootimage-generator-sources = $(src)/tools/bootimage-generator/main.cpp $(src)/u ifneq ($(lzma),) bootimage-generator-sources += $(src)/lzma-encode.cpp endif +ifneq ($(android),) + bootimage-generator-sources += $(src)/android/stubs.cpp +endif bootimage-generator-objects = \ $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build)) bootimage-generator = $(build)/bootimage-generator @@ -1348,14 +1349,6 @@ $(test-dep): $(classpath-dep) $(test-extra-dep): $(classpath-dep) -$(compiler-objects): $(wildcard $(src)/codegen/compiler/*.h) $(vm-depends) - -$(x86-assembler-objects): $(wildcard $(src)/codegen/target/x86/*.h) $(vm-depends) - -$(arm-assembler-objects): $(wildcard $(src)/codegen/target/arm/*.h) $(vm-depends) - -$(powerpc-assembler-objects): $(wildcard $(src)/codegen/target/powerpc/*.h) $(vm-depends) - .PHONY: run run: build $(library-path) $(test-executable) $(test-args) @@ -1452,7 +1445,8 @@ $(build)/android-src/%.cpp: $(luni-native)/%.cpp $(build)/%.o: $(build)/android-src/%.cpp $(build)/android.dep @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) $(android-cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) + $(cxx) $(android-cflags) $(classpath-extra-cflags) -c \ + $$($(windows-path) $(<)) $(call output,$(@)) $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas) @echo "compiling luni classes" @@ -1461,7 +1455,7 @@ $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas) @mkdir -p $(build)/android-src/external/fdlibm @mkdir -p $(build)/android-src/libexpat cp $(android)/fdlibm/fdlibm.h $(build)/android-src/external/fdlibm/ - cp $(android)/expat/lib/expat.h $(build)/android-src/libexpat/ + cp $(android)/expat/lib/expat*.h $(build)/android-src/libexpat/ cp -a $(luni-java)/* $(dalvik-java)/* $(xml-java)/* $(build)/android-src/ sed -i -e 's/return ordinal - o.ordinal;/return ordinal - o.ordinal();/' \ $(build)/android-src/java/lang/Enum.java @@ -1681,11 +1675,17 @@ $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) @echo "creating $(@)" + @rm -rf $(build)/libavian + @mkdir -p $(build)/libavian rm -rf $(@) + let i=0; for x in $(^); \ + do cp $${x} $(build)/libavian/avian_$${i}.o; \ + let i=i+1; \ + done ifdef ms_cl_compiler - $(ar) $(arflags) $(^) -out:$(@) + $(ar) $(arflags) $(build)/libavian/*.o -out:$(@) else - $(ar) cru $(@) $(^) + $(ar) cru $(@) $(build)/libavian/*.o $(ranlib) $(@) endif @@ -1701,7 +1701,7 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) unittest-executable-objects = $(unittest-objects) $(vm-objects) \ - $(classpath-objects) $(build)/util/arg-parser.o + $(build)/util/arg-parser.o ifeq ($(process),interpret) unittest-executable-objects += $(all-codegen-target-objects) @@ -1719,7 +1719,8 @@ print: ifneq ($(platform),windows) define link-executable @echo linking $(@) - $(ld) $(^) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@) + $(ld) $(^) $(rdynamic) $(lflags) $(classpath-lflags) $(bootimage-lflags) \ + -o $(@) endef else ifdef ms_cl_compiler @@ -1773,7 +1774,7 @@ $(bootimage-generator): $(bootimage-generator-objects) $(bootimage-generator) $(build-bootimage-generator): \ - $(vm-objects) $(classpath-object) $(classpath-objects) \ + $(vm-objects) $(classpath-object) \ $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) \ $(lzma-decode-objects) $(lzma-encode-objects) @echo "linking $(@)" @@ -1807,7 +1808,7 @@ ifdef mt endif else $(ld) $(^) $(version-script-flag) $(soname-flag) \ - $(shared) $(lflags) $(bootimage-lflags) \ + $(shared) $(lflags) $(classpath-lflags) $(bootimage-lflags) \ -o $(@) endif $(strip) $(strip-all) $(@) diff --git a/src/android/stubs.cpp b/src/android/stubs.cpp new file mode 100644 index 0000000000..157bdc0ad7 --- /dev/null +++ b/src/android/stubs.cpp @@ -0,0 +1,6 @@ +struct JavaVM; + +extern "C" int JNI_OnLoad(JavaVM*, void*) +{ + return 0; +} From caa632d601bc5823eebd7e65b605a42c163b938c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Mar 2013 14:42:18 -0700 Subject: [PATCH 325/378] fix build when let expressions aren't available --- makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index a0ccb8c803..7ced9b1742 100755 --- a/makefile +++ b/makefile @@ -1678,9 +1678,8 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ @rm -rf $(build)/libavian @mkdir -p $(build)/libavian rm -rf $(@) - let i=0; for x in $(^); \ - do cp $${x} $(build)/libavian/avian_$${i}.o; \ - let i=i+1; \ + for x in $(^); \ + do cp $${x} $(build)/libavian/$$(echo $${x} | sed s:/:_:g); \ done ifdef ms_cl_compiler $(ar) $(arflags) $(build)/libavian/*.o -out:$(@) From 3209f8750a71aaee289e17872f516722311204f0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Mar 2013 16:00:35 -0700 Subject: [PATCH 326/378] fix heapdump build --- src/builtin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index 6991748de8..b8fa0f75f1 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -178,7 +178,8 @@ Avian_avian_Machine_dumpHeap } fclose(out); } else { - throwNew(t, Machine::RuntimeExceptionType, "file not found: %s", n); + throwNew(t, Machine::RuntimeExceptionType, "file not found: %s", + RUNTIME_ARRAY_BODY(n)); } } From c6185c8034444aa6b08941280607f4eadb52d571 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Mar 2013 16:02:59 -0700 Subject: [PATCH 327/378] remove "low memory" heuristic from heap code The original goal was to minimize memory usage by garbage collecting more frequently and more comprehensively as we got closer to the heap limit. In practice, though, this just slowed the VM to a crawl as memory pressure increased. If an app really wants to use a lot of memory, the VM shouldn't penalize it aside from throwing an OutOfMemoryError if it exceeds the limit. --- src/heap/heap.cpp | 51 ++++++----------------------------------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index 01b6cffec8..d70286dd15 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -27,8 +27,6 @@ const unsigned Top = ~static_cast(0); const unsigned InitialGen2CapacityInBytes = 4 * 1024 * 1024; const unsigned InitialTenuredFixieCeilingInBytes = 4 * 1024 * 1024; -const unsigned LowMemoryPaddingInBytes = 1024 * 1024; - const bool Verbose = false; const bool Verbose2 = false; const bool Debug = false; @@ -62,6 +60,7 @@ Aborter* getAborter(Context* c); void* tryAllocate(Context* c, unsigned size); void* allocate(Context* c, unsigned size); +void* allocate(Context* c, unsigned size, bool limit); void free(Context* c, const void* p, unsigned size); #ifdef USE_ATOMIC_OPERATIONS @@ -348,7 +347,8 @@ class Segment { capacity_ = desired; while (data == 0) { data = static_cast - (tryAllocate(context, (footprint(capacity_)) * BytesPerWord)); + (local::allocate + (context, (footprint(capacity_)) * BytesPerWord, false)); if (data == 0) { if (capacity_ > minimum) { @@ -609,7 +609,6 @@ class Context { client(0), count(0), limit(limit), - lowMemoryThreshold(limit / 2), lock(0), immortalHeapStart(0), @@ -680,7 +679,6 @@ class Context { unsigned count; unsigned limit; - unsigned lowMemoryThreshold; System::Mutex* lock; @@ -770,21 +768,6 @@ oversizedGen2(Context* c) and c->gen2.position() < (c->gen2.capacity() / 4); } -inline unsigned -memoryNeeded(Context* c) -{ - return c->count - + ((c->gen1.footprint(minimumNextGen1Capacity(c)) - + c->gen2.footprint(minimumNextGen2Capacity(c))) * BytesPerWord) - + LowMemoryPaddingInBytes; -} - -inline bool -lowMemory(Context* c) -{ - return memoryNeeded(c) > c->lowMemoryThreshold; -} - inline void initNextGen1(Context* c) { @@ -818,7 +801,7 @@ initNextGen2(Context* c) unsigned minimum = minimumNextGen2Capacity(c); unsigned desired = minimum; - if (not (lowMemory(c) or oversizedGen2(c))) { + if (not oversizedGen2(c)) { desired *= 2; } @@ -1666,16 +1649,13 @@ collect2(Context* c) void collect(Context* c) { - if (lowMemory(c) - or oversizedGen2(c) + if (oversizedGen2(c) or c->tenureFootprint + c->tenurePadding > c->gen2.remaining() or c->fixieTenureFootprint + c->tenuredFixieFootprint > c->tenuredFixieCeiling) { if (Verbose) { - if (lowMemory(c)) { - fprintf(stderr, "low memory causes "); - } else if (oversizedGen2(c)) { + if (oversizedGen2(c)) { fprintf(stderr, "oversized gen2 causes "); } else if (c->tenureFootprint + c->tenurePadding > c->gen2.remaining()) { @@ -1699,25 +1679,6 @@ collect(Context* c) then = c->system->now(); } - unsigned count = memoryNeeded(c); - if (count > c->lowMemoryThreshold) { - if (Verbose) { - fprintf(stderr, "increase low memory threshold from %d to %d\n", - c->lowMemoryThreshold, - avg(c->limit, c->lowMemoryThreshold)); - } - - c->lowMemoryThreshold = avg(c->limit, c->lowMemoryThreshold); - } else if (count + (count / 16) < c->lowMemoryThreshold) { - if (Verbose) { - fprintf(stderr, "decrease low memory threshold from %d to %d\n", - c->lowMemoryThreshold, - avg(count, c->lowMemoryThreshold)); - } - - c->lowMemoryThreshold = avg(count, c->lowMemoryThreshold); - } - initNextGen1(c); if (c->mode == Heap::MajorCollection) { From 84f99f0dcad3a274f8118479409eccbc0857ad0a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Mar 2013 09:06:19 -0700 Subject: [PATCH 328/378] remove thread from thread group on termination In the OpenJDK library, ThreadGroup maintains an array of all Threads in that group, so the VM must explicitly remove threads as they exit or else neither they nor any objects they reference will be eligable for GC. --- src/avian/machine.h | 5 +++-- src/classpath-openjdk.cpp | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/avian/machine.h b/src/avian/machine.h index fca793c055..8f1ec1d3d2 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1231,10 +1231,11 @@ class Machine { Shutdown, VirtualFileFinders, VirtualFiles, - ArrayInterfaceTable + ArrayInterfaceTable, + ThreadTerminated }; - static const unsigned RootCount = ArrayInterfaceTable + 1; + static const unsigned RootCount = ThreadTerminated + 1; Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 02522e5126..2fdf0d3b42 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -613,6 +613,10 @@ class MyClasspath : public Classpath { t->flags &= ~Thread::ActiveFlag; vm::notifyAll(t, t->javaThread); vm::release(t, t->javaThread); + + t->m->processor->invoke + (t, root(t, Machine::ThreadTerminated), + threadGroup(t, t->javaThread), t->javaThread); }); object method = resolveMethod @@ -653,6 +657,10 @@ class MyClasspath : public Classpath { resolveSystemClass(t, root(t, Machine::BootLoader), className(t, type(t, Machine::ClassLoaderType))); + setRoot(t, Machine::ThreadTerminated, resolveMethod + (t, root(t, Machine::BootLoader), "java/lang/ThreadGroup", + "threadTerminated", "(Ljava/lang/Thread;)V")); + #ifdef AVIAN_OPENJDK_SRC interceptFileOperations(t); #else // not AVIAN_OPENJDK_SRC From 585186f7d38e906860032fca395f2f71b249f9b1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Mar 2013 09:35:21 -0700 Subject: [PATCH 329/378] avoid allocating a new gen2 heap larger than the available heap capacity --- src/heap/heap.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index d70286dd15..dcc888cacb 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -330,7 +330,8 @@ class Segment { unsigned capacity_; Map* map; - Segment(Context* context, Map* map, unsigned desired, unsigned minimum): + Segment(Context* context, Map* map, unsigned desired, unsigned minimum, + int64_t available = INT64_MAX): context(context), data(0), position_(0), @@ -346,9 +347,13 @@ class Segment { capacity_ = desired; while (data == 0) { - data = static_cast - (local::allocate - (context, (footprint(capacity_)) * BytesPerWord, false)); + if (static_cast(footprint(capacity_)) > available) { + data = 0; + } else { + data = static_cast + (local::allocate + (context, (footprint(capacity_)) * BytesPerWord, false)); + } if (data == 0) { if (capacity_ > minimum) { @@ -809,7 +814,11 @@ initNextGen2(Context* c) desired = InitialGen2CapacityInBytes / BytesPerWord; } - new (&(c->nextGen2)) Segment(c, &(c->nextHeapMap), desired, minimum); + new (&(c->nextGen2)) Segment + (c, &(c->nextHeapMap), desired, minimum, + static_cast(c->limit / BytesPerWord) + - (static_cast(c->count / BytesPerWord) + - c->gen2.footprint(c->gen2.capacity()))); if (Verbose2) { fprintf(stderr, "init nextGen2 to %d bytes\n", From ca84dd26f1dc6f1fd372b184d7e4191cf818a9e0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Mar 2013 15:43:49 -0700 Subject: [PATCH 330/378] fix System.loadLibrary for OpenJDK tails=true build --- src/avian/machine.h | 4 ++++ src/classpath-android.cpp | 6 ++++++ src/classpath-avian.cpp | 6 ++++++ src/classpath-openjdk.cpp | 24 ++++++++++++++++++++++++ src/compile.cpp | 20 ++++++++++++++++---- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/avian/machine.h b/src/avian/machine.h index 8f1ec1d3d2..7263b183a6 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1583,6 +1583,10 @@ class Classpath { virtual int64_t getDirectBufferCapacity(Thread* t, object buffer) = 0; + virtual bool + canTailCall(Thread* t, object caller, object calleeClassName, + object calleeMethodName, object calleeMethodSpec) = 0; + virtual void dispose() = 0; }; diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index d70f3defe2..b2a2a174b3 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -439,6 +439,12 @@ class MyClasspath : public Classpath { return fieldAtOffset(b, fieldOffset(t, field)); } + virtual bool + canTailCall(Thread*, object, object, object, object) + { + return true; + } + virtual void dispose() { diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index f0ea0367e7..5617b92070 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -174,6 +174,12 @@ class MyClasspath : public Classpath { return fieldAtOffset(b, fieldOffset(t, field)); } + virtual bool + canTailCall(Thread*, object, object, object, object) + { + return true; + } + virtual void dispose() { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 2fdf0d3b42..da53a7532e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -842,6 +842,30 @@ class MyClasspath : public Classpath { return fieldAtOffset(b, fieldOffset(t, field)); } + virtual bool + canTailCall(Thread* t, object, object calleeClassName, + object calleeMethodName, object) + { + // we can't tail call System.loadLibrary or Runtime.loadLibrary + // due to their use of System.getCallerClass, which gets confused + // if we elide stack frames. + + return (strcmp("loadLibrary", reinterpret_cast + (&byteArrayBody(t, calleeMethodName, 0))) + or (strcmp("java/lang/System", reinterpret_cast + (&byteArrayBody(t, calleeClassName, 0))) + and strcmp("java/lang/Runtime", reinterpret_cast + (&byteArrayBody(t, calleeClassName, 0))))) + + // and we can't tail call Reflection.getCallerClass because the + // number of stack frames will be wrong + + and (strcmp("getCallerClass", reinterpret_cast + (&byteArrayBody(t, calleeMethodName, 0))) + or strcmp("sun/reflect/Reflection", reinterpret_cast + (&byteArrayBody(t, calleeClassName, 0)))); + } + virtual void dispose() { diff --git a/src/compile.cpp b/src/compile.cpp index d2c509b0ac..259b6f5858 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3730,7 +3730,8 @@ returnsNext(MyThread* t, object code, unsigned ip) bool isTailCall(MyThread* t, object code, unsigned ip, object caller, - int calleeReturnCode) + int calleeReturnCode, object calleeClassName, + object calleeMethodName, object calleeMethodSpec) { return avian::codegen::TailCalls and ((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0) @@ -3738,21 +3739,32 @@ isTailCall(MyThread* t, object code, unsigned ip, object caller, and (not needsReturnBarrier(t, caller)) and (methodReturnCode(t, caller) == VoidField or methodReturnCode(t, caller) == calleeReturnCode) - and returnsNext(t, code, ip); + and returnsNext(t, code, ip) + and t->m->classpath->canTailCall + (t, caller, calleeClassName, calleeMethodName, calleeMethodSpec); } bool isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee) { - return isTailCall(t, code, ip, caller, methodReturnCode(t, callee)); + return isTailCall + (t, code, ip, caller, methodReturnCode(t, callee), + className(t, methodClass(t, callee)), methodName(t, callee), + methodSpec(t, callee)); } bool isReferenceTailCall(MyThread* t, object code, unsigned ip, object caller, object calleeReference) { + object c = referenceClass(t, calleeReference); + if (objectClass(t, c) == type(t, Machine::ClassType)) { + c = className(t, c); + } + return isTailCall - (t, code, ip, caller, methodReferenceReturnCode(t, calleeReference)); + (t, code, ip, caller, methodReferenceReturnCode(t, calleeReference), + c, referenceName(t, calleeReference), referenceSpec(t, calleeReference)); } bool From 3c44cdc50b6be41440529c8dbd648dd972621593 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 7 Mar 2013 20:17:05 -0700 Subject: [PATCH 331/378] fix unintentionally retained finalizables and improve low mem performance Objects which are eligable for finalization must be retained until after their finalize methods are called. However, the VM must determine the entire set of such objects before retaining any of them; otherwise the process of retaining a given object may cause others to become reachable and thus be considered ineligible for finalization even though they are only reachable via other finalizable objects. The end result of this mistake is that only a few of the objects which are finalizable will be recognized at each GC cycle, so it requires many such cycles to find them all, and if new objects become finalizable at a faster rate, the VM will never catch up and eventually run out of memory. This patch fixes the above mistake and also includes tuning to minimize the need for GC in low memory situations. --- include/avian/vm/heap/heap.h | 16 ++-- src/avian/machine.h | 42 ++++++++-- src/heap/heap.cpp | 139 +++++++++++++++++++++---------- src/machine.cpp | 154 +++++++++++++++++++---------------- 4 files changed, 224 insertions(+), 127 deletions(-) diff --git a/include/avian/vm/heap/heap.h b/include/avian/vm/heap/heap.h index b385dcf511..874d40980e 100644 --- a/include/avian/vm/heap/heap.h +++ b/include/avian/vm/heap/heap.h @@ -60,13 +60,15 @@ class Heap: public Allocator { virtual void setClient(Client* client) = 0; virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) = 0; virtual unsigned limit() = 0; - virtual bool limitExceeded() = 0; - virtual void collect(CollectionType type, unsigned footprint) = 0; - virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, - bool objectMask, unsigned* totalInBytes) = 0; - virtual void* tryAllocateImmortalFixed(Allocator* allocator, - unsigned sizeInWords, bool objectMask, - unsigned* totalInBytes) = 0; + virtual bool limitExceeded(int pendingAllocation = 0) = 0; + virtual void collect(CollectionType type, unsigned footprint, + int pendingAllocation) = 0; + virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0; + virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask) = 0; + virtual void* allocateImmortalFixed(Allocator* allocator, + unsigned sizeInWords, + bool objectMask) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void pad(void* p) = 0; virtual void* follow(void* p) = 0; diff --git a/src/avian/machine.h b/src/avian/machine.h index 7263b183a6..b4409551c3 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -104,6 +104,8 @@ const bool DebugStack = false; const bool DebugMonitors = false; const bool DebugReferences = false; +const bool AbortOnOutOfMemoryError = false; + const uintptr_t HashTakenMark = 1; const uintptr_t ExtendedMark = 2; const uintptr_t FixedMark = 3; @@ -1694,7 +1696,7 @@ release(Thread* t, Reference* r) } void -collect(Thread* t, Heap::CollectionType type); +collect(Thread* t, Heap::CollectionType type, int pendingAllocation = 0); void shutDown(Thread* t); @@ -2689,6 +2691,16 @@ makeThrowable(Thread* t, Machine::Type type, const char* format, ...) void popResources(Thread* t); +} // namespace vm + +JNIEXPORT void +vmPrintTrace(vm::Thread* t); + +namespace vm { + +void +dumpHeap(Thread* t, FILE* out); + inline void NO_RETURN throw_(Thread* t, object e) { @@ -2699,6 +2711,28 @@ throw_(Thread* t, object e) t->exception = e; + if (objectClass(t, e) == type(t, Machine::OutOfMemoryErrorType)) { +#ifdef AVIAN_HEAPDUMP + if (not t->m->dumpedHeapOnOOM) { + t->m->dumpedHeapOnOOM = true; + const char* path = findProperty(t, "avian.heap.dump"); + if (path) { + FILE* out = vm::fopen(path, "wb"); + if (out) { + dumpHeap(t, out); + fclose(out); + } + } + } +#endif//AVIAN_HEAPDUMP + + if (AbortOnOutOfMemoryError) { + fprintf(stderr, "OutOfMemoryError\n"); + vmPrintTrace(t); + abort(); + } + } + // printTrace(t, e); popResources(t); @@ -3832,9 +3866,6 @@ getCaller(Thread* t, unsigned target, bool skipMethodInvoke = false); object defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length); -void -dumpHeap(Thread* t, FILE* out); - inline object methodClone(Thread* t, object method) { @@ -3919,9 +3950,6 @@ errorLog(Thread* t) } // namespace vm -JNIEXPORT void -vmPrintTrace(vm::Thread* t); - JNIEXPORT void* vmAddressFromLine(vm::Thread* t, vm::object m, unsigned line); diff --git a/src/heap/heap.cpp b/src/heap/heap.cpp index dcc888cacb..fac8cdb934 100644 --- a/src/heap/heap.cpp +++ b/src/heap/heap.cpp @@ -346,14 +346,41 @@ class Segment { assert(context, desired >= minimum); capacity_ = desired; - while (data == 0) { - if (static_cast(footprint(capacity_)) > available) { - data = 0; - } else { - data = static_cast - (local::allocate - (context, (footprint(capacity_)) * BytesPerWord, false)); + + if (static_cast(footprint(capacity_)) > available) { + unsigned top = capacity_; + unsigned bottom = minimum; + unsigned target = available; + while (true) { + if (static_cast(footprint(capacity_)) > target) { + if (bottom == capacity_) { + break; + } else if (static_cast(footprint(capacity_ - 1)) + <= target) + { + -- capacity_; + break; + } + top = capacity_; + capacity_ = avg(bottom, capacity_); + } else if (static_cast(footprint(capacity_)) < target) { + if (top == capacity_ + or static_cast(footprint(capacity_ + 1)) >= target) + { + break; + } + bottom = capacity_; + capacity_ = avg(top, capacity_); + } else { + break; + } } + } + + while (data == 0) { + data = static_cast + (local::allocate + (context, (footprint(capacity_)) * BytesPerWord, false)); if (data == 0) { if (capacity_ > minimum) { @@ -638,6 +665,7 @@ class Context { gen2Base(0), incomingFootprint(0), + pendingAllocation(0), tenureFootprint(0), gen1Padding(0), tenurePadding(0), @@ -658,7 +686,9 @@ class Context { lastCollectionTime(system->now()), totalCollectionTime(0), - totalTime(0) + totalTime(0), + + limitWasExceeded(false) { if (not system->success(system->make(&lock))) { system->abort(); @@ -709,6 +739,7 @@ class Context { unsigned gen2Base; unsigned incomingFootprint; + int pendingAllocation; unsigned tenureFootprint; unsigned gen1Padding; unsigned tenurePadding; @@ -730,6 +761,8 @@ class Context { int64_t lastCollectionTime; int64_t totalCollectionTime; int64_t totalTime; + + bool limitWasExceeded; }; const char* @@ -818,7 +851,9 @@ initNextGen2(Context* c) (c, &(c->nextHeapMap), desired, minimum, static_cast(c->limit / BytesPerWord) - (static_cast(c->count / BytesPerWord) - - c->gen2.footprint(c->gen2.capacity()))); + - c->gen2.footprint(c->gen2.capacity()) + - c->gen1.footprint(c->gen1.capacity()) + + c->pendingAllocation)); if (Verbose2) { fprintf(stderr, "init nextGen2 to %d bytes\n", @@ -1655,16 +1690,41 @@ collect2(Context* c) c->client->visitRoots(&v); } +bool +limitExceeded(Context* c, int pendingAllocation) +{ + unsigned count = c->count + pendingAllocation + - (c->gen2.remaining() * BytesPerWord); + + if (Verbose) { + if (count > c->limit) { + if (not c->limitWasExceeded) { + c->limitWasExceeded = true; + fprintf(stderr, "heap limit %d exceeded: %d\n", c->limit, count); + } + } else if (c->limitWasExceeded) { + c->limitWasExceeded = false; + fprintf(stderr, "heap limit %d no longer exceeded: %d\n", + c->limit, count); + } + } + + return count > c->limit; +} + void collect(Context* c) { - if (oversizedGen2(c) + if (limitExceeded(c, c->pendingAllocation) + or oversizedGen2(c) or c->tenureFootprint + c->tenurePadding > c->gen2.remaining() or c->fixieTenureFootprint + c->tenuredFixieFootprint > c->tenuredFixieCeiling) { if (Verbose) { - if (oversizedGen2(c)) { + if (limitExceeded(c, c->pendingAllocation)) { + fprintf(stderr, "low memory causes "); + } else if (oversizedGen2(c)) { fprintf(stderr, "oversized gen2 causes "); } else if (c->tenureFootprint + c->tenurePadding > c->gen2.remaining()) { @@ -1832,8 +1892,8 @@ class MyHeap: public Heap { return c.limit; } - virtual bool limitExceeded() { - return c.count > c.limit; + virtual bool limitExceeded(int pendingAllocation = 0) { + return local::limitExceeded(&c, pendingAllocation); } virtual void* tryAllocate(unsigned size) { @@ -1848,50 +1908,45 @@ class MyHeap: public Heap { free_(&c, p, size); } - virtual void collect(CollectionType type, unsigned incomingFootprint) { + virtual void collect(CollectionType type, unsigned incomingFootprint, + int pendingAllocation) + { c.mode = type; c.incomingFootprint = incomingFootprint; + c.pendingAllocation = pendingAllocation; local::collect(&c); } - void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, - bool objectMask, unsigned* totalInBytes, - Fixie** handle, bool immortal) - { - *totalInBytes = 0; + virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) { + return Fixie::totalSize(sizeInWords, objectMask); + } - if (limitExceeded()) { - return 0; - } + void* allocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask, Fixie** handle, bool immortal) + { + expect(&c, not limitExceeded()); unsigned total = Fixie::totalSize(sizeInWords, objectMask); - void* p = allocator->tryAllocate(total); - if (p == 0) { - return 0; - } else if (limitExceeded()) { - allocator->free(p, total); - return 0; - } else { - *totalInBytes = total; - return (new (p) Fixie(&c, sizeInWords, objectMask, handle, immortal)) - ->body(); - } + void* p = allocator->allocate(total); + + expect(&c, not limitExceeded()); + + return (new (p) Fixie(&c, sizeInWords, objectMask, handle, immortal)) + ->body(); } - virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, - bool objectMask, unsigned* totalInBytes) + virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask) { - return tryAllocateFixed - (allocator, sizeInWords, objectMask, totalInBytes, &(c.fixies), false); + return allocateFixed + (allocator, sizeInWords, objectMask, &(c.fixies), false); } - virtual void* tryAllocateImmortalFixed(Allocator* allocator, - unsigned sizeInWords, bool objectMask, - unsigned* totalInBytes) + virtual void* allocateImmortalFixed(Allocator* allocator, + unsigned sizeInWords, bool objectMask) { - return tryAllocateFixed - (allocator, sizeInWords, objectMask, totalInBytes, 0, true); + return allocateFixed(allocator, sizeInWords, objectMask, 0, true); } bool needsMark(void* p) { diff --git a/src/machine.cpp b/src/machine.cpp index ca2c57aa86..94916963aa 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -537,13 +537,22 @@ postVisit(Thread* t, Heap::Visitor* v) object firstNewTenuredFinalizer = 0; object lastNewTenuredFinalizer = 0; - for (object* p = &(m->finalizers); *p;) { - v->visit(p); + { object unreachable = 0; + for (object* p = &(m->finalizers); *p;) { + v->visit(p); - if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) { - // target is unreachable - queue it up for finalization - finalizerTargetUnreachable(t, v, p); - } else { + if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) { + object finalizer = *p; + *p = finalizerNext(t, finalizer); + + finalizerNext(t, finalizer) = unreachable; + unreachable = finalizer; + } else { + p = &finalizerNext(t, *p); + } + } + + for (object* p = &(m->finalizers); *p;) { // target is reachable v->visit(&finalizerTarget(t, *p)); @@ -563,6 +572,11 @@ postVisit(Thread* t, Heap::Visitor* v) p = &finalizerNext(t, *p); } } + + for (object* p = &unreachable; *p;) { + // target is unreachable - queue it up for finalization + finalizerTargetUnreachable(t, v, p); + } } object firstNewTenuredWeakReference = 0; @@ -603,17 +617,31 @@ postVisit(Thread* t, Heap::Visitor* v) } if (major) { - for (object* p = &(m->tenuredFinalizers); *p;) { - v->visit(p); + { object unreachable = 0; + for (object* p = &(m->tenuredFinalizers); *p;) { + v->visit(p); - if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) { - // target is unreachable - queue it up for finalization - finalizerTargetUnreachable(t, v, p); - } else { + if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) { + object finalizer = *p; + *p = finalizerNext(t, finalizer); + + finalizerNext(t, finalizer) = unreachable; + unreachable = finalizer; + } else { + p = &finalizerNext(t, *p); + } + } + + for (object* p = &(m->tenuredFinalizers); *p;) { // target is reachable v->visit(&finalizerTarget(t, *p)); p = &finalizerNext(t, *p); } + + for (object* p = &unreachable; *p;) { + // target is unreachable - queue it up for finalization + finalizerTargetUnreachable(t, v, p); + } } for (object* p = &(m->tenuredWeakReferences); *p;) { @@ -2862,7 +2890,7 @@ class HeapClient: public Heap::Client { }; void -doCollect(Thread* t, Heap::CollectionType type) +doCollect(Thread* t, Heap::CollectionType type, int pendingAllocation) { expect(t, not t->m->collecting); @@ -2877,7 +2905,8 @@ doCollect(Thread* t, Heap::CollectionType type) Machine* m = t->m; m->unsafe = true; - m->heap->collect(type, footprint(m->rootThread)); + m->heap->collect(type, footprint(m->rootThread), pendingAllocation + - (t->m->heapPoolIndex * ThreadHeapSizeInWords)); m->unsafe = false; postCollect(m->rootThread); @@ -3575,13 +3604,16 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, break; } - if (t->heap == 0 or t->m->heap->limitExceeded()) { + int pendingAllocation = t->m->heap->fixedFootprint + (ceilingDivide(sizeInBytes, BytesPerWord), objectMask); + + if (t->heap == 0 or t->m->heap->limitExceeded(pendingAllocation)) { // fprintf(stderr, "gc"); // vmPrintTrace(t); - collect(t, Heap::MinorCollection); + collect(t, Heap::MinorCollection, pendingAllocation); } - if (t->m->heap->limitExceeded()) { + if (t->m->heap->limitExceeded(pendingAllocation)) { throw_(t, root(t, Machine::OutOfMemoryError)); } } while (type == Machine::MovableAllocation @@ -3594,45 +3626,57 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, } case Machine::FixedAllocation: { - unsigned total; object o = static_cast - (t->m->heap->tryAllocateFixed - (allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask, &total)); + (t->m->heap->allocateFixed + (allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask)); - if (o) { - memset(o, 0, sizeInBytes); + memset(o, 0, sizeInBytes); - alias(o, 0) = FixedMark; + alias(o, 0) = FixedMark; + + t->m->fixedFootprint += t->m->heap->fixedFootprint + (ceilingDivide(sizeInBytes, BytesPerWord), objectMask); - t->m->fixedFootprint += total; - - return o; - } else { - throw_(t, root(t, Machine::OutOfMemoryError)); - } + return o; } case Machine::ImmortalAllocation: { - unsigned total; object o = static_cast - (t->m->heap->tryAllocateImmortalFixed - (allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask, &total)); + (t->m->heap->allocateImmortalFixed + (allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask)); - if (o) { - memset(o, 0, sizeInBytes); + memset(o, 0, sizeInBytes); - alias(o, 0) = FixedMark; + alias(o, 0) = FixedMark; - return o; - } else { - throw_(t, root(t, Machine::OutOfMemoryError)); - } + return o; } default: abort(t); } } +void +collect(Thread* t, Heap::CollectionType type, int pendingAllocation) +{ + ENTER(t, Thread::ExclusiveState); + + unsigned pending = pendingAllocation + - (t->m->heapPoolIndex * ThreadHeapSizeInWords); + + if (t->m->heap->limitExceeded(pending)) { + type = Heap::MajorCollection; + } + + doCollect(t, type, pendingAllocation); + + if (t->m->heap->limitExceeded(pending)) { + // try once more, giving the heap a chance to squeeze everything + // into the smallest possible space: + doCollect(t, Heap::MajorCollection, pendingAllocation); + } +} + object makeNewGeneral(Thread* t, object class_) { @@ -4678,38 +4722,6 @@ intern(Thread* t, object s) } } -void -collect(Thread* t, Heap::CollectionType type) -{ - ENTER(t, Thread::ExclusiveState); - - if (t->m->heap->limitExceeded()) { - type = Heap::MajorCollection; - } - - doCollect(t, type); - - if (t->m->heap->limitExceeded()) { - // try once more, giving the heap a chance to squeeze everything - // into the smallest possible space: - doCollect(t, Heap::MajorCollection); - } - -#ifdef AVIAN_HEAPDUMP - if ((not t->m->dumpedHeapOnOOM) and t->m->heap->limitExceeded()) { - t->m->dumpedHeapOnOOM = true; - const char* path = findProperty(t, "avian.heap.dump"); - if (path) { - FILE* out = vm::fopen(path, "wb"); - if (out) { - dumpHeap(t, out); - fclose(out); - } - } - } -#endif//AVIAN_HEAPDUMP -} - void walk(Thread* t, Heap::Walker* w, object o, unsigned start) { From ff19ab6c138a12ef7b67e275c0d3339cb19be885 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 8 Mar 2013 14:47:27 -0700 Subject: [PATCH 332/378] add avian.trace.port property Setting this property (e.g. -Davian.trace.port=5555) will cause the VM to start an extra daemon thread which listens on the specified TCP port for incoming connections and dumps stack traces for all running threads to that socket. You can retrieve that dump using e.g. netcat: nc localhost 5555 --- classpath/avian/Traces.java | 61 +++++++++++++++++++++++++++++++++++++ makefile | 1 + src/jnienv.cpp | 12 ++++++++ 3 files changed, 74 insertions(+) create mode 100644 classpath/avian/Traces.java diff --git a/classpath/avian/Traces.java b/classpath/avian/Traces.java new file mode 100644 index 0000000000..14f7ef7d15 --- /dev/null +++ b/classpath/avian/Traces.java @@ -0,0 +1,61 @@ +package avian; + +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +public class Traces { + private static final String Newline = System.getProperty("line.separator"); + + private static String traceAllThreads() { + StringBuilder buffer = new StringBuilder(); + + Thread[] threads = new Thread[Thread.activeCount()]; + + int count = Thread.enumerate(threads); + for (int i = 0; i < count; ++i) { + traceThread(threads[i], buffer); + } + + return buffer.toString(); + } + + private static String traceThread(Thread thread) { + StringBuilder buffer = new StringBuilder(); + + traceThread(thread, buffer); + + return buffer.toString(); + } + + private static void traceThread(Thread thread, StringBuilder buffer) { + buffer.append(thread).append(Newline); + for (StackTraceElement e: thread.getStackTrace()) { + buffer.append("\tat ").append(e).append(Newline); + } + } + + public static void startTraceListener(final String host, final int port) { + Thread t = new Thread(new Runnable() { + public void run() { + try { + ServerSocketChannel server = ServerSocketChannel.open(); + server.socket().bind(new InetSocketAddress(host, port)); + while (true) { + SocketChannel c = server.accept(); + try { + c.write(ByteBuffer.wrap(traceAllThreads().getBytes())); + } finally { + c.close(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + t.setDaemon(true); + t.start(); + } +} diff --git a/makefile b/makefile index 7ced9b1742..22e79f76f0 100755 --- a/makefile +++ b/makefile @@ -1233,6 +1233,7 @@ ifneq ($(classpath),avian) $(classpath-src)/avian/Singleton.java \ $(classpath-src)/avian/Stream.java \ $(classpath-src)/avian/SystemClassLoader.java \ + $(classpath-src)/avian/Traces.java \ $(classpath-src)/avian/VMClass.java \ $(classpath-src)/avian/VMField.java \ $(classpath-src)/avian/VMMethod.java \ diff --git a/src/jnienv.cpp b/src/jnienv.cpp index b2e9507cd8..741da645dd 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3533,6 +3533,18 @@ boot(Thread* t, uintptr_t*) t->m->classpath->boot(t); + const char* port = findProperty(t, "avian.trace.port"); + if (port) { + object host = makeString(t, "0.0.0.0"); + PROTECT(t, host); + + object method = resolveMethod + (t, root(t, Machine::BootLoader), "avian/Traces", "startTraceListener", + "(Ljava/lang/String;I)V"); + + t->m->processor->invoke(t, method, 0, host, atoi(port)); + } + enter(t, Thread::IdleState); return 1; From 5d3dc707cb1af99cbe335674f148aedef0b09e8a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 8 Mar 2013 18:21:12 -0700 Subject: [PATCH 333/378] briefly enter idle state in get*Volatile In order for a thread to enter the "exclusive" state such that no other threads are active in the VM, it must wait for all active threads to enter the "idle" state. In order for this to happen in a timely manner, threads must check frequently to see if a thread is waiting to enter the exclusive state. These checks happen at every memory allocation, wait, sleep, native call, etc. However, if a thread is in a busy loop that does none of those things, it will block any other thread from entering that state. The proper way to address this is to detect such loops (or tail recursion in tail-call-optimized builds) at compile or interpret time and insert explicit checks. This hasn't been a high priority thus far, though, since we had yet to encounter such code in the wild. Now, however, we find that scala.concurrent.forkjoin.ForkJoinPool.scan (and possibly some versions of java.util.concurrent.ForkJoinPool.scan, on which we assume the former is based) has just such a loop. Fortunately, that loop calls Unsafe.getObjectVolatile, which the VM implements and thus can treat as a checkpoint. That's the workaround we use in this patch. --- src/classpath-openjdk.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index da53a7532e..6350ef5938 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2729,11 +2729,15 @@ Avian_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_getIntVolatile -(Thread*, object, uintptr_t* arguments) +(Thread* t, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); + // avoid blocking the VM if this is being called in a busy loop + PROTECT(t, o); + { ENTER(t, Thread::IdleState); } + int32_t result = fieldAtOffset(o, offset); loadMemoryBarrier(); return result; @@ -2764,6 +2768,10 @@ Avian_sun_misc_Unsafe_getLongVolatile object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); + // avoid blocking the VM if this is being called in a busy loop + PROTECT(t, o); + { ENTER(t, Thread::IdleState); } + object field; if (BytesPerWord < 8) { field = local::fieldForOffset(t, o, offset); @@ -2869,10 +2877,14 @@ Avian_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_getObjectVolatile -(Thread*, object, uintptr_t* arguments) +(Thread* t, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); + + // avoid blocking the VM if this is being called in a busy loop + PROTECT(t, o); + { ENTER(t, Thread::IdleState); } uintptr_t value = fieldAtOffset(o, offset); loadMemoryBarrier(); From d5504d8f58a40800059f7f5edefe5de84356960e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 14 Mar 2013 15:33:05 -0600 Subject: [PATCH 334/378] first step towards supporting Android class library on Windows A majority of the tests are passing, but more work is needed to get them all to pass. --- makefile | 63 ++++++++---- src/android/icu.cpp | 12 --- src/classpath-android.cpp | 208 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 243 insertions(+), 40 deletions(-) delete mode 100644 src/android/icu.cpp diff --git a/makefile b/makefile index 22e79f76f0..7a618ca3e5 100755 --- a/makefile +++ b/makefile @@ -165,21 +165,47 @@ ifneq ($(android),) -I$(build)/android-src/external/fdlibm \ -I$(build)/android-src \ -fno-exceptions \ - -DHAVE_SYS_UIO_H \ -D_FILE_OFFSET_BITS=64 \ -g3 \ - -Werror \ - -fPIC + -Werror + + luni-cpps := $(shell find $(luni-native) -name '*.cpp') + + ifeq ($(platform),windows) + android-cflags += -D__STDC_CONSTANT_MACROS + ifneq ($(arch),i386) + android-cflags += -fPIC + endif + blacklist = $(luni-native)/java_io_Console.cpp \ + $(luni-native)/java_lang_ProcessManager.cpp \ + $(luni-native)/libcore_io_OsConstants.cpp \ + $(luni-native)/libcore_io_Posix.cpp \ + $(luni-native)/libcore_io_AsynchronousCloseMonitor.cpp \ + $(luni-native)/libcore_net_RawSocket.cpp \ + $(luni-native)/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp \ + $(luni-native)/AsynchronousSocketCloseMonitor.cpp \ + $(luni-native)/NetworkUtilities.cpp + luni-cpps := $(filter-out $(blacklist),$(luni-cpps)) + icu-libs := $(android)/icu4c/lib/sicuin.a \ + $(android)/icu4c/lib/sicuuc.a \ + $(android)/icu4c/lib/sicudt.a + platform-lflags := -lgdi32 + else + android-cflags += -fPIC -DHAVE_SYS_UIO_H + icu-libs := $(android)/icu4c/lib/icui18n.a \ + $(android)/icu4c/lib/libicuuc.a \ + $(android)/icu4c/lib/libicudat.a + endif + classpath-lflags := \ - $(android)/icu4c/lib/libicui18n.a \ - $(android)/icu4c/lib/libicuuc.a \ - $(android)/icu4c/lib/libicudata.a \ + $(icu-libs) \ $(android)/fdlibm/libfdm.a \ $(android)/expat/.libs/libexpat.a \ $(android)/openssl-upstream/libssl.a \ $(android)/openssl-upstream/libcrypto.a \ + $(platform-lflags) \ -lstdc++ - luni-cpps := $(shell find $(luni-native) -name '*.cpp') + classpath-objects = \ $(call cpp-objects,$(luni-cpps),$(luni-native),$(build)) luni-java = $(android)/libcore/luni/src/main/java @@ -198,6 +224,8 @@ ifneq ($(android),) javahome-object = $(build)/javahome-jar.o boot-javahome-object = $(build)/boot-javahome.o build-javahome = $(android)/bionic/libc/zoneinfo + stub-sources = $(src)/android/stubs.cpp + stub-objects = $(call cpp-objects,$(stub-sources),$(src),$(build)) endif ifeq ($(classpath),avian) @@ -1017,7 +1045,7 @@ target-asm = $(asm) build-embed = $(build)/embed build-embed-loader = $(build)/embed-loader -embed-loader-sources = $(src)/embedded-loader.cpp +embed-loader-sources = $(src)/embedded-loader.cpp $(stub-sources) embed-loader-objects = $(call cpp-objects,$(embed-loader-sources),$(src),$(build-embed-loader)) embed-sources = $(src)/embed.cpp @@ -1091,14 +1119,12 @@ ifeq ($(continuations),true) asmflags += -DAVIAN_CONTINUATIONS endif -bootimage-generator-sources = $(src)/tools/bootimage-generator/main.cpp $(src)/util/arg-parser.cpp +bootimage-generator-sources = $(src)/tools/bootimage-generator/main.cpp $(src)/util/arg-parser.cpp $(stub-sources) ifneq ($(lzma),) bootimage-generator-sources += $(src)/lzma-encode.cpp endif -ifneq ($(android),) - bootimage-generator-sources += $(src)/android/stubs.cpp -endif + bootimage-generator-objects = \ $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build)) bootimage-generator = $(build)/bootimage-generator @@ -1438,10 +1464,7 @@ $(classpath-dep): $(classpath-sources) $(classpath-jar-dep) @touch $(@) $(build)/android-src/%.cpp: $(luni-native)/%.cpp - if [ "$(luni-native)/libcore_icu_ICU.cpp" = "$(<)" ]; then \ - sed 's/register_libcore_icu_ICU/hide_register_libcore_icu_ICU/' \ - < $(<) > $(@).tmp && cat $(@).tmp $(src)/android/icu.cpp > $(@); else \ - cp $(<) $(@); fi + cp $(<) $(@) $(build)/%.o: $(build)/android-src/%.cpp $(build)/android.dep @echo "compiling $(@)" @@ -1562,8 +1585,8 @@ $(embed-loader-o): $(embed-loader) $(converter) $(converter) $(<) $(@) _binary_loader_start \ _binary_loader_end $(target-format) $(arch) -$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ - $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) +$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-object) \ + $(heapwalk-objects) $(lzma-decode-objects) ifdef ms_cl_compiler $(ld) $(lflags) $(^) -out:$(@) \ -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) @@ -1701,7 +1724,7 @@ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) unittest-executable-objects = $(unittest-objects) $(vm-objects) \ - $(build)/util/arg-parser.o + $(build)/util/arg-parser.o $(stub-objects) ifeq ($(process),interpret) unittest-executable-objects += $(all-codegen-target-objects) @@ -1742,7 +1765,7 @@ define link-executable @echo linking $(@) $(dlltool) -z $(@).def $(^) $(dlltool) -d $(@).def -e $(@).exp - $(ld) $(@).exp $(^) $(lflags) -o $(@) + $(ld) $(@).exp $(^) $(lflags) $(classpath-lflags) -o $(@) endef endif endif diff --git a/src/android/icu.cpp b/src/android/icu.cpp deleted file mode 100644 index 15b661e4c7..0000000000 --- a/src/android/icu.cpp +++ /dev/null @@ -1,12 +0,0 @@ -void -register_libcore_icu_ICU(JNIEnv* e) -{ - UErrorCode status = U_ZERO_ERROR; - udata_setFileAccess(UDATA_NO_FILES, &status); - if (status != U_ZERO_ERROR) abort(); - - u_init(&status); - if (status != U_ZERO_ERROR) abort(); - - jniRegisterNativeMethods(e, "libcore/icu/ICU", gMethods, NELEM(gMethods)); -} diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index b2a2a174b3..93af185a92 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -24,6 +24,18 @@ namespace { namespace local { +void* +getDirectBufferAddress(Thread* t, object b) +{ + PROTECT(t, b); + + object field = resolveField + (t, objectClass(t, b), "effectiveDirectAddress", "J"); + + return reinterpret_cast + (fieldAtOffset(b, fieldOffset(t, field))); +} + void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) { @@ -140,6 +152,28 @@ initVmThread(Thread* t, object thread) } } +void JNICALL +createThread(Thread* t, object method, uintptr_t* arguments) +{ + object thread = reinterpret_cast(arguments[0]); + PROTECT(t, thread); + + object group = reinterpret_cast(arguments[1]); + PROTECT(t, group); + + object name = reinterpret_cast(arguments[2]); + PROTECT(t, name); + + int64_t stackSize; memcpy(&stackSize, arguments + 3, 8); + + initVmThread(t, thread); + + t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + thread, group, name, stackSize); +} + object translateStackTrace(Thread* t, object raw) { @@ -163,7 +197,8 @@ translateStackTrace(Thread* t, object raw) class MyClasspath : public Classpath { public: MyClasspath(Allocator* allocator): - allocator(allocator) + allocator(allocator), + tzdata(0) { } virtual object @@ -329,7 +364,11 @@ class MyClasspath : public Classpath { { // Android's System.initSystemProperties throws an NPE if // LD_LIBRARY_PATH is not set as of this writing: +#ifdef PLATFORM_WINDOWS + _wputenv(L"LD_LIBRARY_PATH=dummy"); +#else setenv("LD_LIBRARY_PATH", "", false); +#endif { object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/Runtime", false); @@ -375,6 +414,19 @@ class MyClasspath : public Classpath { intercept(t, c, "close", "()V", voidPointer(closeMemoryMappedFile)); } } + + { object c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/Thread", false); + + if (c) { + PROTECT(t, c); + + intercept(t, c, "create", + "(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;" + "Ljava/lang/String;J)V", + voidPointer(createThread)); + } + } JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); } @@ -419,13 +471,7 @@ class MyClasspath : public Classpath { virtual void* getDirectBufferAddress(Thread* t, object b) { - PROTECT(t, b); - - object field = resolveField - (t, objectClass(t, b), "effectiveDirectAddress", "J"); - - return reinterpret_cast - (fieldAtOffset(b, fieldOffset(t, field))); + return local::getDirectBufferAddress(t, b); } virtual int64_t @@ -599,11 +645,21 @@ jniThrowIOException(JNIEnv* e, const char* message) extern "C" const char* jniStrError(int error, char* buffer, size_t length) { +#ifdef PLATFORM_WINDOWS + const char* s = strerror(error); + if (strlen(s) < length) { + strncpy(buffer, s, length); + return buffer; + } else { + return 0; + } +#else if (static_cast(strerror_r(error, buffer, length)) == 0) { return buffer; } else { return 0; } +#endif } extern "C" int @@ -1676,3 +1732,139 @@ Avian_java_lang_System_mapLibraryName RUNTIME_ARRAY_BODY(originalChars), t->m->system->librarySuffix())); } + +#ifdef PLATFORM_WINDOWS + +# include + +void register_java_io_Console(_JNIEnv*) { } +void register_java_lang_ProcessManager(_JNIEnv*) { } +void register_libcore_io_OsConstants(_JNIEnv*) { } +void register_libcore_io_AsynchronousCloseMonitor(_JNIEnv*) { } +void register_libcore_io_Posix(_JNIEnv*) { } +void register_libcore_net_RawSocket(_JNIEnv*) { } +void register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(_JNIEnv*) { } + +extern "C" JNIEXPORT void JNICALL +Avian_libcore_io_OsConstants_initConstants +(Thread* t, object method, uintptr_t*) +{ + object c = methodClass(t, method); + PROTECT(t, c); + + object table = classStaticTable(t, c); + PROTECT(t, table); + + object field = resolveField(t, c, "STDIN_FILENO", "I"); + fieldAtOffset(table, fieldOffset(t, field)) = 0; + + field = resolveField(t, c, "STDOUT_FILENO", "I"); + fieldAtOffset(table, fieldOffset(t, field)) = 1; + + field = resolveField(t, c, "STDERR_FILENO", "I"); + fieldAtOffset(table, fieldOffset(t, field)) = 2; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_libcore_io_Posix_getenv(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[1]); + + THREAD_RUNTIME_ARRAY(t, uint16_t, chars, stringLength(t, name) + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(chars)); + + wchar_t* value = _wgetenv + (reinterpret_cast(RUNTIME_ARRAY_BODY(chars))); + + if (value) { + unsigned size = wcslen(value); + + object a = makeCharArray(t, size); + if (size) { + memcpy(&charArrayBody(t, a, 0), value, size * sizeof(jchar)); + } + + return reinterpret_cast + (t->m->classpath->makeString(t, a, 0, size)); + } else { + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_libcore_io_Posix_uname(Thread* t, object, uintptr_t*) +{ + object c = resolveClass + (t, root(t, Machine::BootLoader), "libcore/io/StructUtsname"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + +#ifdef ARCH_x86_32 + object arch = makeString(t, "x86"); +#elif defined ARCH_x86_64 + object arch = makeString(t, "x86_64"); +#elif defined ARCH_powerpc + object arch = makeString(t, "ppc"); +#elif defined ARCH_arm + object arch = makeString(t, "arm"); +#else + object arch = makeString(t, "unknown"); +#endif + + set(t, instance, fieldOffset + (t, resolveField(t, c, "machine", "Ljava/lang/String;")), arch); + + object platform = makeString(t, "Windows"); + + set(t, instance, fieldOffset + (t, resolveField(t, c, "sysname", "Ljava/lang/String;")), platform); + + object version = makeString(t, "unknown"); + + set(t, instance, fieldOffset + (t, resolveField(t, c, "release", "Ljava/lang/String;")), version); + + return reinterpret_cast(instance); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_libcore_io_Posix_writeBytes(Thread* t, object, uintptr_t* arguments) +{ + object fd = reinterpret_cast(arguments[1]); + PROTECT(t, fd); + + object buffer = reinterpret_cast(arguments[2]); + PROTECT(t, buffer); + + int offset = arguments[3]; + int count = arguments[4]; + + int d = jniGetFDFromFileDescriptor(t, &fd); + + int r; + if (objectClass(t, buffer) == type(t, Machine::ByteArrayType)) { + void* tmp = t->m->heap->allocate(count); + memcpy(tmp, &byteArrayBody(t, buffer, offset), count); + { ENTER(t, Thread::IdleState); + r = _write(d, tmp, count); + } + t->m->heap->free(tmp, count); + } else { + void* p = local::getDirectBufferAddress(t, buffer); + { ENTER(t, Thread::IdleState); + r = _write(d, p, count); + } + } + + if (r < 0) { + THREAD_RUNTIME_ARRAY(t, char, message, 256); + throwNew(t, Machine::RuntimeExceptionType, "writeBytes %d: %s", d, + jniStrError(errno, RUNTIME_ARRAY_BODY(message), 0)); + } else { + return r; + } +} + +#endif From 8ac1f68a79166a0b9dbf6b41a72b52f73f2781ab Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 13:15:48 -0600 Subject: [PATCH 335/378] fix Android library build regression for non-Windows platforms --- makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 7a618ca3e5..66b62f7c7b 100755 --- a/makefile +++ b/makefile @@ -192,9 +192,9 @@ ifneq ($(android),) platform-lflags := -lgdi32 else android-cflags += -fPIC -DHAVE_SYS_UIO_H - icu-libs := $(android)/icu4c/lib/icui18n.a \ + icu-libs := $(android)/icu4c/lib/libicui18n.a \ $(android)/icu4c/lib/libicuuc.a \ - $(android)/icu4c/lib/libicudat.a + $(android)/icu4c/lib/libicudata.a endif classpath-lflags := \ From 9f2e0f6c4fc3259b2a63da35cf6a17d62e8f5ec7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 13:16:20 -0600 Subject: [PATCH 336/378] rebuild bootimage-generator when vm-objects have changed --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 66b62f7c7b..82d9999026 100755 --- a/makefile +++ b/makefile @@ -1779,7 +1779,7 @@ $(unittest-executable): $(unittest-executable-objects) $(audit-codegen-executable): $(audit-codegen-executable-objects) $(link-executable) -$(bootimage-generator): $(bootimage-generator-objects) +$(bootimage-generator): $(bootimage-generator-objects) $(vm-objects) echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform) $(MAKE) mode=$(mode) \ build=$(host-build-root) \ From c3e34b94389115dd2240cc866502c99063215f94 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 13:17:04 -0600 Subject: [PATCH 337/378] exit with error code from test.sh if any test fails --- test/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test.sh b/test/test.sh index f5de5ff81c..ddb9f5b1f0 100644 --- a/test/test.sh +++ b/test/test.sh @@ -54,4 +54,5 @@ echo if [ -n "${trouble}" ]; then printf "see ${log} for output\n" + exit -1 fi From 96a4b6e508e2b09fc794e34183b0c5992909e82c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 13:17:53 -0600 Subject: [PATCH 338/378] test non-debug build first in ci.sh If something's broken, the script will fail faster if we test the faster build first, giving us quicker feedback. --- test/ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ci.sh b/test/ci.sh index 1fb490da3c..de7a6a6a47 100755 --- a/test/ci.sh +++ b/test/ci.sh @@ -2,8 +2,8 @@ set -e -make mode=debug test make test +make mode=debug test make process=interpret test # bootimage and openjdk builds without openjdk-src don't work: if [ -z "${openjdk}" ]; then From 3309a9f4ad5e021fa84d1a09c56e451a0373b83d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 13:25:12 -0600 Subject: [PATCH 339/378] ensure that array classes implement Cloneable and Serializable in bootimage build --- src/machine.cpp | 25 ++++++++++++++++--------- test/Misc.java | 6 ++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 94916963aa..4c03e74658 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2650,6 +2650,20 @@ nameClass(Thread* t, Machine::Type type, const char* name) set(t, arrayBody(t, t->m->types, type), ClassName, n); } +void +makeArrayInterfaceTable(Thread* t) +{ + object interfaceTable = makeArray(t, 4); + + set(t, interfaceTable, ArrayBody, type + (t, Machine::SerializableType)); + + set(t, interfaceTable, ArrayBody + (2 * BytesPerWord), + type(t, Machine::CloneableType)); + + setRoot(t, Machine::ArrayInterfaceTable, interfaceTable); +} + void boot(Thread* t) { @@ -2761,15 +2775,7 @@ boot(Thread* t) setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0)); - { object interfaceTable = makeArray(t, 4); - - set(t, interfaceTable, ArrayBody, type(t, Machine::SerializableType)); - - set(t, interfaceTable, ArrayBody + (2 * BytesPerWord), - type(t, Machine::CloneableType)); - - setRoot(t, Machine::ArrayInterfaceTable, interfaceTable); - } + makeArrayInterfaceTable(t); set(t, type(t, Machine::BooleanArrayType), ClassInterfaceTable, root(t, Machine::ArrayInterfaceTable)); @@ -3228,6 +3234,7 @@ Thread::init() if (image and code) { m->processor->boot(this, image, code); + makeArrayInterfaceTable(this); } else { boot(this); } diff --git a/test/Misc.java b/test/Misc.java index 620897332f..669e7bf691 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -250,5 +250,11 @@ public class Misc { μInstance.μMethod(8933); expect(μInstance.μField == 8933); } + + expect(new int[0] instanceof Cloneable); + expect(new int[0] instanceof java.io.Serializable); + + expect(new Object[0] instanceof Cloneable); + expect(new Object[0] instanceof java.io.Serializable); } } From c80ffa041dd0b40a2a580629f108ec0e74d3ab99 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 13:28:01 -0600 Subject: [PATCH 340/378] ensure that we can intercept static Java methods in bootimage build Timezone code was broken in the Android class library bootimage build because the code we use to intercept loading the tzdata file wasn't working. The reason is have no way of intercepting static methods at runtime in the bootimage build without telling the bootimage-generator we're going to do it ahead of time. So now we do tell it so. This commit also removes the need to intercept Thread methods since we can update Thread.vmThread in VMThread.create instead. --- src/avian/classpath-common.h | 31 ++++--- src/avian/machine.h | 3 + src/classpath-android.cpp | 107 ++++++++++++++----------- src/classpath-avian.cpp | 6 ++ src/classpath-openjdk.cpp | 73 ++++++++++------- src/tools/bootimage-generator/main.cpp | 2 + 6 files changed, 133 insertions(+), 89 deletions(-) diff --git a/src/avian/classpath-common.h b/src/avian/classpath-common.h index ff063982e6..a9e4c3a834 100644 --- a/src/avian/classpath-common.h +++ b/src/avian/classpath-common.h @@ -578,28 +578,33 @@ invoke(Thread* t, object method, object instance, object args) // running: void intercept(Thread* t, object c, const char* name, const char* spec, - void* function) + void* function, bool updateRuntimeData) { object m = findMethodOrNull(t, c, name, spec); if (m) { PROTECT(t, m); - object clone = methodClone(t, m); + object clone; + if (updateRuntimeData) { + clone = methodClone(t, m); - // make clone private to prevent vtable updates at compilation - // time. Otherwise, our interception might be bypassed by calls - // through the vtable. - methodFlags(t, clone) |= ACC_PRIVATE; + // make clone private to prevent vtable updates at compilation + // time. Otherwise, our interception might be bypassed by calls + // through the vtable. + methodFlags(t, clone) |= ACC_PRIVATE; + } methodFlags(t, m) |= ACC_NATIVE; - object native = makeNativeIntercept(t, function, true, clone); - - PROTECT(t, native); - - object runtimeData = getMethodRuntimeData(t, m); - - set(t, runtimeData, MethodRuntimeDataNative, native); + if (updateRuntimeData) { + object native = makeNativeIntercept(t, function, true, clone); + + PROTECT(t, native); + + object runtimeData = getMethodRuntimeData(t, m); + + set(t, runtimeData, MethodRuntimeDataNative, native); + } } else { // If we can't find the method, just ignore it, since ProGuard may // have stripped it out as unused. Otherwise, the code below can diff --git a/src/avian/machine.h b/src/avian/machine.h index b4409551c3..5c57bc18e2 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1564,6 +1564,9 @@ class Classpath { virtual void resolveNative(Thread* t, object method) = 0; + virtual void + interceptMethods(Thread* t) = 0; + virtual void preBoot(Thread* t) = 0; diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 93af185a92..3098b7be8d 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -152,28 +152,6 @@ initVmThread(Thread* t, object thread) } } -void JNICALL -createThread(Thread* t, object method, uintptr_t* arguments) -{ - object thread = reinterpret_cast(arguments[0]); - PROTECT(t, thread); - - object group = reinterpret_cast(arguments[1]); - PROTECT(t, group); - - object name = reinterpret_cast(arguments[2]); - PROTECT(t, name); - - int64_t stackSize; memcpy(&stackSize, arguments + 3, 8); - - initVmThread(t, thread); - - t->m->processor->invoke - (t, nativeInterceptOriginal - (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), - thread, group, name, stackSize); -} - object translateStackTrace(Thread* t, object raw) { @@ -359,17 +337,9 @@ class MyClasspath : public Classpath { vm::resolveNative(t, method); } - virtual void - preBoot(Thread* t) + void + interceptMethods(Thread* t, bool updateRuntimeData) { - // Android's System.initSystemProperties throws an NPE if - // LD_LIBRARY_PATH is not set as of this writing: -#ifdef PLATFORM_WINDOWS - _wputenv(L"LD_LIBRARY_PATH=dummy"); -#else - setenv("LD_LIBRARY_PATH", "", false); -#endif - { object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/Runtime", false); @@ -378,7 +348,7 @@ class MyClasspath : public Classpath { intercept(t, c, "loadLibrary", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", - voidPointer(loadLibrary)); + voidPointer(loadLibrary), updateRuntimeData); } } @@ -389,7 +359,7 @@ class MyClasspath : public Classpath { PROTECT(t, c); intercept(t, c, "createSystemClassLoader", "()Ljava/lang/ClassLoader;", - voidPointer(appLoader)); + voidPointer(appLoader), updateRuntimeData); } } @@ -400,7 +370,7 @@ class MyClasspath : public Classpath { PROTECT(t, c); intercept(t, c, "mapData", "()Llibcore/io/MemoryMappedFile;", - voidPointer(mapData)); + voidPointer(mapData), updateRuntimeData); } } @@ -411,23 +381,31 @@ class MyClasspath : public Classpath { if (c) { PROTECT(t, c); - intercept(t, c, "close", "()V", voidPointer(closeMemoryMappedFile)); + intercept(t, c, "close", "()V", voidPointer(closeMemoryMappedFile), + updateRuntimeData); } } + } - { object c = resolveClass - (t, root(t, Machine::BootLoader), "java/lang/Thread", false); + virtual void + interceptMethods(Thread* t) + { + interceptMethods(t, false); + } - if (c) { - PROTECT(t, c); - - intercept(t, c, "create", - "(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;" - "Ljava/lang/String;J)V", - voidPointer(createThread)); - } - } + virtual void + preBoot(Thread* t) + { + // Android's System.initSystemProperties throws an NPE if + // LD_LIBRARY_PATH is not set as of this writing: +#ifdef PLATFORM_WINDOWS + _wputenv(L"LD_LIBRARY_PATH=(dummy)"); +#else + setenv("LD_LIBRARY_PATH", "", false); +#endif + interceptMethods(t, true); + JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); } @@ -1101,7 +1079,11 @@ extern "C" JNIEXPORT void JNICALL Avian_java_lang_VMThread_create (Thread* t, object, uintptr_t* arguments) { - startThread(t, reinterpret_cast(arguments[0])); + object thread = reinterpret_cast(arguments[0]); + PROTECT(t, thread); + + local::initVmThread(t, thread); + startThread(t, thread); } extern "C" JNIEXPORT void JNICALL @@ -1195,6 +1177,35 @@ Avian_java_lang_Math_sin return doubleToBits(sin(bitsToDouble(v))); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_sqrt +(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, arguments, 8); + return doubleToBits(sqrt(bitsToDouble(v))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_abs__I +(Thread*, object, uintptr_t* arguments) +{ + return abs(static_cast(arguments[0])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_abs__J +(Thread*, object, uintptr_t* arguments) +{ + return llabs(arguments[0]); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Math_abs__F +(Thread*, object, uintptr_t* arguments) +{ + return floatToBits(abs(bitsToFloat(arguments[0]))); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Float_intBitsToFloat (Thread*, object, uintptr_t* arguments) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 5617b92070..64c56fc389 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -109,6 +109,12 @@ class MyClasspath : public Classpath { vm::resolveNative(t, method); } + virtual void + interceptMethods(Thread*) + { + // ignore + } + virtual void preBoot(Thread*) { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 6350ef5938..d50059ff2e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -352,7 +352,7 @@ object makeJfield(Thread* t, object vmField, int index = -1); void -interceptFileOperations(Thread*); +interceptFileOperations(Thread*, bool); void clearInterrupted(Thread*); @@ -614,9 +614,16 @@ class MyClasspath : public Classpath { vm::notifyAll(t, t->javaThread); vm::release(t, t->javaThread); + object e = t->exception; + PROTECT(t, e); + + t->exception = 0; + t->m->processor->invoke (t, root(t, Machine::ThreadTerminated), threadGroup(t, t->javaThread), t->javaThread); + + t->exception = e; }); object method = resolveMethod @@ -643,6 +650,14 @@ class MyClasspath : public Classpath { vm::resolveNative(t, method); } + virtual void + interceptMethods(Thread* t UNUSED) + { +#ifdef AVIAN_OPENJDK_SRC + interceptFileOperations(t, false); +#endif + } + virtual void preBoot(Thread*) { @@ -662,7 +677,7 @@ class MyClasspath : public Classpath { "threadTerminated", "(Ljava/lang/Thread;)V")); #ifdef AVIAN_OPENJDK_SRC - interceptFileOperations(t); + interceptFileOperations(t, true); #else // not AVIAN_OPENJDK_SRC expect(t, loadLibrary(t, libraryPath, "verify", true, true)); expect(t, loadLibrary(t, libraryPath, "java", true, true)); @@ -1957,7 +1972,7 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) } void -interceptFileOperations(Thread* t) +interceptFileOperations(Thread* t, bool updateRuntimeData) { MyClasspath* cp = static_cast(t->m->classpath); @@ -2000,22 +2015,22 @@ interceptFileOperations(Thread* t) cp->fileInputStreamFdField = fieldOffset(t, fileInputStreamFdField); intercept(t, fileInputStreamClass, "open", "(Ljava/lang/String;)V", - voidPointer(openFile)); + voidPointer(openFile), updateRuntimeData); intercept(t, fileInputStreamClass, "read", "()I", - voidPointer(readByteFromFile)); + voidPointer(readByteFromFile), updateRuntimeData); intercept(t, fileInputStreamClass, "readBytes", "([BII)I", - voidPointer(readBytesFromFile)); + voidPointer(readBytesFromFile), updateRuntimeData); intercept(t, fileInputStreamClass, "skip", "(J)J", - voidPointer(skipBytesInFile)); + voidPointer(skipBytesInFile), updateRuntimeData); intercept(t, fileInputStreamClass, "available", "()I", - voidPointer(availableBytesInFile)); + voidPointer(availableBytesInFile), updateRuntimeData); intercept(t, fileInputStreamClass, "close0", "()V", - voidPointer(closeFile)); + voidPointer(closeFile), updateRuntimeData); } } } @@ -2033,40 +2048,42 @@ interceptFileOperations(Thread* t) cp->zipFileJzfileField = fieldOffset(t, zipFileJzfileField); intercept(t, zipFileClass, "open", "(Ljava/lang/String;IJZ)J", - voidPointer(openZipFile)); + voidPointer(openZipFile), updateRuntimeData); intercept(t, zipFileClass, "getTotal", "(J)I", - voidPointer(getZipFileEntryCount)); + voidPointer(getZipFileEntryCount), updateRuntimeData); intercept(t, zipFileClass, "getEntry", "(J[BZ)J", - voidPointer(getZipFileEntry)); + voidPointer(getZipFileEntry), updateRuntimeData); intercept(t, zipFileClass, "getEntryBytes", "(JI)[B", - voidPointer(getZipFileEntryBytes)); + voidPointer(getZipFileEntryBytes), updateRuntimeData); intercept(t, zipFileClass, "getNextEntry", "(JI)J", - voidPointer(getNextZipFileEntry)); + voidPointer(getNextZipFileEntry), updateRuntimeData); intercept(t, zipFileClass, "getEntryMethod", "(J)I", - voidPointer(getZipFileEntryMethod)); + voidPointer(getZipFileEntryMethod), updateRuntimeData); intercept(t, zipFileClass, "freeEntry", "(JJ)V", - voidPointer(freeZipFileEntry)); + voidPointer(freeZipFileEntry), updateRuntimeData); intercept(t, zipFileClass, "read", "(JJJ[BII)I", - voidPointer(readZipFileEntry)); + voidPointer(readZipFileEntry), updateRuntimeData); intercept(t, zipFileClass, "getEntryCSize", "(J)J", - voidPointer(getZipFileEntryCompressedSize)); + voidPointer(getZipFileEntryCompressedSize), + updateRuntimeData); intercept(t, zipFileClass, "getEntrySize", "(J)J", - voidPointer(getZipFileEntryUncompressedSize)); + voidPointer(getZipFileEntryUncompressedSize), + updateRuntimeData); intercept(t, zipFileClass, "getZipMessage", "(J)Ljava/lang/String;", - voidPointer(getZipMessage)); + voidPointer(getZipMessage), updateRuntimeData); intercept(t, zipFileClass, "close", "(J)V", - voidPointer(closeZipFile)); + voidPointer(closeZipFile), updateRuntimeData); } } } @@ -2077,7 +2094,7 @@ interceptFileOperations(Thread* t) if (jarFileClass) { intercept(t, jarFileClass, "getMetaInfEntryNames", "()[Ljava/lang/String;", - voidPointer(getJarFileMetaInfEntryNames)); + voidPointer(getJarFileMetaInfEntryNames), updateRuntimeData); } } @@ -2097,27 +2114,27 @@ interceptFileOperations(Thread* t) PROTECT(t, fsClass); intercept(t, fsClass, gbaMethodName, "(Ljava/io/File;)I", - voidPointer(getFileAttributes)); + voidPointer(getFileAttributes), updateRuntimeData); intercept(t, fsClass, "checkAccess", "(Ljava/io/File;I)Z", - voidPointer(checkFileAccess)); + voidPointer(checkFileAccess), updateRuntimeData); intercept(t, fsClass, "getLength", "(Ljava/io/File;)J", - voidPointer(getFileLength)); + voidPointer(getFileLength), updateRuntimeData); } } intercept(t, type(t, Machine::ClassLoaderType), "loadLibrary", "(Ljava/lang/Class;Ljava/lang/String;Z)V", - voidPointer(loadLibrary)); + voidPointer(loadLibrary), updateRuntimeData); intercept(t, type(t, Machine::ClassLoaderType), "getBootstrapResource", "(Ljava/lang/String;)Ljava/net/URL;", - voidPointer(getBootstrapResource)); + voidPointer(getBootstrapResource), updateRuntimeData); intercept(t, type(t, Machine::ClassLoaderType), "getBootstrapResources", "(Ljava/lang/String;)Ljava/util/Enumeration;", - voidPointer(getBootstrapResources)); + voidPointer(getBootstrapResources), updateRuntimeData); } object diff --git a/src/tools/bootimage-generator/main.cpp b/src/tools/bootimage-generator/main.cpp index d27d250ab8..eac0b17de8 100644 --- a/src/tools/bootimage-generator/main.cpp +++ b/src/tools/bootimage-generator/main.cpp @@ -285,6 +285,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, { PROTECT(t, typeMaps); + t->m->classpath->interceptMethods(t); + object constants = 0; PROTECT(t, constants); From 651145bd611cae7367744a5b3f5e5be6fcca4af9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 13:57:44 -0600 Subject: [PATCH 341/378] remove -static-libstdc++ -static-libgcc from bootimage-generator-lflags MinGW-w64's GCC doesn't understand those flags, and we shouldn't be linking statically or dynamically with either of those libraries. --- makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/makefile b/makefile index 82d9999026..f4b45b1b0e 100755 --- a/makefile +++ b/makefile @@ -656,7 +656,6 @@ ifeq ($(platform),windows) rpath = lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mconsole - bootimage-generator-lflags = -static-libstdc++ -static-libgcc cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 ifeq (,$(filter mingw32 cygwin,$(build-platform))) From 54b560b149639fed45ffc719dccf856fb90ded0a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 14:35:29 -0600 Subject: [PATCH 342/378] fix Windows 32-bit bootimage build regression --- src/codegen/target/x86/assembler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codegen/target/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp index af289135cf..e580f197a2 100644 --- a/src/codegen/target/x86/assembler.cpp +++ b/src/codegen/target/x86/assembler.cpp @@ -51,8 +51,6 @@ namespace avian { namespace codegen { namespace x86 { -const RegisterFile MyRegisterFile(GeneralRegisterMask, FloatRegisterMask); - const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1); const unsigned StackAlignmentInBytes = 16; @@ -152,7 +150,8 @@ class MyArchitecture: public Architecture { public: MyArchitecture(System* system, bool useNativeFeatures): c(system, useNativeFeatures), - referenceCount(0) + referenceCount(0), + myRegisterFile(GeneralRegisterMask, useSSE(&c) ? FloatRegisterMask : 0) { populateTables(&c); } @@ -166,7 +165,7 @@ class MyArchitecture: public Architecture { } virtual const RegisterFile* registerFile() { - return &MyRegisterFile; + return &myRegisterFile; } virtual int scratch() { @@ -805,6 +804,7 @@ class MyArchitecture: public Architecture { ArchitectureContext c; unsigned referenceCount; + const RegisterFile myRegisterFile; }; class MyAssembler: public Assembler { From bad3a7979cfcef65fa9be32dc72e03970fc4ad5f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 16:08:55 -0600 Subject: [PATCH 343/378] fix parameter ordering in windows.cpp's MySystem::visit It's amazing to me that ebp and esp have been swapped for over three years without anybody noticing. It was dumb luck that the Trace test (which is designed to catch just such a thing) happened to fail when I ran the whole suite, and further investigation revealed that it was failing maybe five percent of the times it was run. Now we know why. --- src/vm/system/windows.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vm/system/windows.cpp b/src/vm/system/windows.cpp index 5c4a68cffd..9f9de4816e 100644 --- a/src/vm/system/windows.cpp +++ b/src/vm/system/windows.cpp @@ -775,12 +775,12 @@ class MySystem: public System { if (rv) { # ifdef ARCH_x86_32 visitor->visit(reinterpret_cast(context.Eip), - reinterpret_cast(context.Ebp), - reinterpret_cast(context.Esp)); + reinterpret_cast(context.Esp), + reinterpret_cast(context.Ebp)); # elif defined ARCH_x86_64 visitor->visit(reinterpret_cast(context.Rip), - reinterpret_cast(context.Rbp), - reinterpret_cast(context.Rsp)); + reinterpret_cast(context.Rsp), + reinterpret_cast(context.Rbp)); # endif success = true; } From 16307398499b4edc472c9600539678a377aa5dcd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 17:47:15 -0600 Subject: [PATCH 344/378] fix Windows x86_64 build regression due to unspecified AVIAN_TARGET_FORMAT --- makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/makefile b/makefile index f4b45b1b0e..5f8923b19e 100755 --- a/makefile +++ b/makefile @@ -640,9 +640,7 @@ endif openjdk-extra-cflags += $(classpath-extra-cflags) ifeq ($(platform),windows) - ifeq ($(target-format),) - target-format = pe - endif + target-format = pe inc = "$(win32)/include" lib = "$(win32)/lib" @@ -1006,8 +1004,6 @@ endif endif endif -build-cflags += -DAVIAN_HOST_TARGET - c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.$(asm-format),$(3)/%-asm.o,$(x))) From 3497354bbf20822ef4fcb5cb7ece872f57f92062 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Mar 2013 17:48:47 -0600 Subject: [PATCH 345/378] allow extra flags to be passed to make in ci.sh --- test/ci.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/ci.sh b/test/ci.sh index de7a6a6a47..c1863360b2 100755 --- a/test/ci.sh +++ b/test/ci.sh @@ -2,11 +2,11 @@ set -e -make test -make mode=debug test -make process=interpret test +make ${flags} test +make ${flags} mode=debug test +make ${flags} process=interpret test # bootimage and openjdk builds without openjdk-src don't work: if [ -z "${openjdk}" ]; then - make bootimage=true test + make ${flags} bootimage=true test fi -make tails=true continuations=true test +make ${flags} tails=true continuations=true test From a648787e11d5cb937cc61d1ddfa705b9fe999870 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 16 Mar 2013 10:54:35 -0600 Subject: [PATCH 346/378] update method table for all classes in updateClassTables Previously we only updated this table for non-interfaces, but interfaces may have methods which need updating too. --- src/machine.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 4c03e74658..098a60130a 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2353,12 +2353,12 @@ updateClassTables(Thread* t, object newClass, object oldClass) } } } - } else { - object methodTable = classMethodTable(t, newClass); - if (methodTable) { - for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) { - set(t, arrayBody(t, methodTable, i), MethodClass, newClass); - } + } + + object methodTable = classMethodTable(t, newClass); + if (methodTable) { + for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) { + set(t, arrayBody(t, methodTable, i), MethodClass, newClass); } } } From d873f096a1c2eb23204f3298c03122bf32a3475b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 18 Mar 2013 11:43:00 -0600 Subject: [PATCH 347/378] set SO_NOSIGPIPE socket option when available This ensures we avoid SIGPIPE on socket disconnect on Darwin. --- classpath/java-nio.cpp | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index dc15639dc7..5324c7b444 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -262,18 +262,32 @@ setTcpNoDelay(JNIEnv* e, int d, bool on) void doBind(JNIEnv* e, int s, sockaddr_in* address) { - int opt = 1; - int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - reinterpret_cast(&opt), sizeof(int)); - if (r != 0) { - throwIOException(e); - return; + { int opt = 1; + int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast(&opt), sizeof(int)); + if (r != 0) { + throwIOException(e); + return; + } } - r = ::bind(s, reinterpret_cast(address), sizeof(sockaddr_in)); - if (r != 0) { - throwIOException(e); - return; +#ifdef SO_NOSIGPIPE + { int opt = 1; + int r = ::setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, + reinterpret_cast(&opt), sizeof(int)); + if (r != 0) { + throwIOException(e); + return; + } + } +#endif + + { int r = ::bind + (s, reinterpret_cast(address), sizeof(sockaddr_in)); + if (r != 0) { + throwIOException(e); + return; + } } } From e8a1900c2b49fb1f7d02e5142e75c224c7ea3dac Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 26 Mar 2013 08:30:26 -0600 Subject: [PATCH 348/378] fix openjdk-src build regression --- makefile | 2 ++ src/openjdk/stubs.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/openjdk/stubs.cpp diff --git a/makefile b/makefile index 5f8923b19e..be08fe0c3f 100755 --- a/makefile +++ b/makefile @@ -130,6 +130,8 @@ ifneq ($(openjdk),) endif javahome-object = $(build)/javahome-jar.o boot-javahome-object = $(build)/boot-javahome.o + stub-sources = $(src)/openjdk/stubs.cpp + stub-objects = $(call cpp-objects,$(stub-sources),$(src),$(build)) else options := $(options)-openjdk test-executable = $(shell pwd)/$(executable-dynamic) diff --git a/src/openjdk/stubs.cpp b/src/openjdk/stubs.cpp new file mode 100644 index 0000000000..ad0418e5de --- /dev/null +++ b/src/openjdk/stubs.cpp @@ -0,0 +1,11 @@ +struct JavaVM; + +extern "C" int net_JNI_OnLoad(JavaVM*, void*) +{ + return 0; +} + +extern "C" int management_JNI_OnLoad(JavaVM*, void*) +{ + return 0; +} From 4777d1b6beb5fd159863ce35d8066b2d6d744837 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 26 Mar 2013 09:53:47 -0600 Subject: [PATCH 349/378] fix Windows openjdk-src build regression --- src/classpath-openjdk.cpp | 2 +- src/openjdk/stubs.cpp | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index d50059ff2e..ae7bba5264 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -5589,7 +5589,7 @@ Avian_java_util_TimeZone_getSystemTimeZoneID return 0; } - Finder* finder = local::getFinder(t, ef.jar, ef.jarLength); + Finder* finder = getFinder(t, ef.jar, ef.jarLength); if (finder == 0) { return 0; } diff --git a/src/openjdk/stubs.cpp b/src/openjdk/stubs.cpp index ad0418e5de..62b3f94649 100644 --- a/src/openjdk/stubs.cpp +++ b/src/openjdk/stubs.cpp @@ -1,11 +1,20 @@ -struct JavaVM; +#include "avian/machine.h" -extern "C" int net_JNI_OnLoad(JavaVM*, void*) +using namespace vm; + +extern "C" JNIEXPORT jint JNICALL +net_JNI_OnLoad(JavaVM*, void*) { return 0; } -extern "C" int management_JNI_OnLoad(JavaVM*, void*) +extern "C" JNIEXPORT jint JNICALL +management_JNI_OnLoad(JavaVM*, void*) +{ + return 0; +} + +extern "C" char* findJavaTZ_md(const char*, const char*) { return 0; } From 13d128c7bebebd6fd508f6fc93d675dc659da5f9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 29 Mar 2013 14:09:43 -0600 Subject: [PATCH 350/378] look for DirectByteBuffer, not ReadWriteDirectByteBuffer The name of the class we need to use in makeDirectByteBuffer has changed in Android's libcore, so now we use the new name. --- src/classpath-android.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 3098b7be8d..bc325470b4 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -431,7 +431,7 @@ class MyClasspath : public Classpath { makeDirectByteBuffer(Thread* t, void* p, jlong capacity) { object c = resolveClass - (t, root(t, Machine::BootLoader), "java/nio/ReadWriteDirectByteBuffer"); + (t, root(t, Machine::BootLoader), "java/nio/DirectByteBuffer"); PROTECT(t, c); object instance = makeNew(t, c); From 43f41f6e737a5ba91443e66fbcc86a054ae5dca0 Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Tue, 2 Apr 2013 10:37:20 +0200 Subject: [PATCH 351/378] Fixed embed.exe loader --- makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index be08fe0c3f..fda2b32132 100755 --- a/makefile +++ b/makefile @@ -1042,7 +1042,7 @@ target-asm = $(asm) build-embed = $(build)/embed build-embed-loader = $(build)/embed-loader -embed-loader-sources = $(src)/embedded-loader.cpp $(stub-sources) +embed-loader-sources = $(src)/embedded-loader.cpp embed-loader-objects = $(call cpp-objects,$(embed-loader-sources),$(src),$(build-embed-loader)) embed-sources = $(src)/embed.cpp @@ -1582,7 +1582,7 @@ $(embed-loader-o): $(embed-loader) $(converter) $(converter) $(<) $(@) _binary_loader_start \ _binary_loader_end $(target-format) $(arch) -$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-object) \ +$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-objects) \ $(heapwalk-objects) $(lzma-decode-objects) ifdef ms_cl_compiler $(ld) $(lflags) $(^) -out:$(@) \ From cc8d6557622b140ad3307a11bfc800a932e4150c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 3 Apr 2013 16:07:06 -0600 Subject: [PATCH 352/378] use %x,%x format for listing start and end addresses This matches the format expected by recent versions of GDB's disassemble command. --- src/compile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index 259b6f5858..01d3f5c5f2 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -9473,7 +9473,7 @@ logCompile(MyThread* t, const void* code, unsigned size, const char* class_, } if (compileLog) { - fprintf(compileLog, "%p %p %s.%s%s\n", + fprintf(compileLog, "%p,%p %s.%s%s\n", code, static_cast(code) + size, class_, name, spec); } From b436bd460a10fefedbfc7ec8faa2634d1308e788 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 3 Apr 2013 16:08:40 -0600 Subject: [PATCH 353/378] fix NaN handling in floating point comparisons --- src/codegen/target/x86/encode.cpp | 3 +++ src/compile.cpp | 28 ++++++++++++++++++++++++---- src/interpret.cpp | 28 ++++++++++++++++++++++++---- test/Floats.java | 18 ++++++++++++++++++ 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/codegen/target/x86/encode.cpp b/src/codegen/target/x86/encode.cpp index f6c97dcac0..e2f1ee287e 100644 --- a/src/codegen/target/x86/encode.cpp +++ b/src/codegen/target/x86/encode.cpp @@ -243,6 +243,9 @@ void branch(Context* c, lir::TernaryOperation op, lir::Constant* target) { void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) { switch (op) { case lir::JumpIfFloatEqual: + // jp past the je so we don't jump to the target if unordered: + c->code.append(0x7a); + c->code.append(6); conditional(c, 0x84, target); break; diff --git a/src/compile.cpp b/src/compile.cpp index 01d3f5c5f2..fd5ebc1f74 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2467,13 +2467,27 @@ getJClassFromReference(MyThread* t, object pair) referenceName(t, pairSecond(t, pair))))); } +bool +isNaN(double v) +{ + return fpclassify(v) == FP_NAN; +} + +bool +isNaN(float v) +{ + return fpclassify(v) == FP_NAN; +} + int64_t compareDoublesG(uint64_t bi, uint64_t ai) { double a = bitsToDouble(ai); double b = bitsToDouble(bi); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + return 1; + } else if (a < b) { return -1; } else if (a > b) { return 1; @@ -2490,7 +2504,9 @@ compareDoublesL(uint64_t bi, uint64_t ai) double a = bitsToDouble(ai); double b = bitsToDouble(bi); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + return -1; + } else if (a < b) { return -1; } else if (a > b) { return 1; @@ -2507,7 +2523,9 @@ compareFloatsG(uint32_t bi, uint32_t ai) float a = bitsToFloat(ai); float b = bitsToFloat(bi); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + return 1; + } if (a < b) { return -1; } else if (a > b) { return 1; @@ -2524,7 +2542,9 @@ compareFloatsL(uint32_t bi, uint32_t ai) float a = bitsToFloat(ai); float b = bitsToFloat(bi); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + return -1; + } if (a < b) { return -1; } else if (a > b) { return 1; diff --git a/src/interpret.cpp b/src/interpret.cpp index cc68a4b79f..d222d4c1b5 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -680,6 +680,18 @@ store(Thread* t, unsigned index) BytesPerWord * 2); } +bool +isNaN(double v) +{ + return fpclassify(v) == FP_NAN; +} + +bool +isNaN(float v) +{ + return fpclassify(v) == FP_NAN; +} + uint64_t findExceptionHandler(Thread* t, object method, unsigned ip) { @@ -1157,7 +1169,9 @@ interpret3(Thread* t, const int base) double b = popDouble(t); double a = popDouble(t); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + pushInt(t, 1); + } if (a < b) { pushInt(t, static_cast(-1)); } else if (a > b) { pushInt(t, 1); @@ -1172,7 +1186,9 @@ interpret3(Thread* t, const int base) double b = popDouble(t); double a = popDouble(t); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + pushInt(t, static_cast(-1)); + } if (a < b) { pushInt(t, static_cast(-1)); } else if (a > b) { pushInt(t, 1); @@ -1370,7 +1386,9 @@ interpret3(Thread* t, const int base) float b = popFloat(t); float a = popFloat(t); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + pushInt(t, 1); + } if (a < b) { pushInt(t, static_cast(-1)); } else if (a > b) { pushInt(t, 1); @@ -1385,7 +1403,9 @@ interpret3(Thread* t, const int base) float b = popFloat(t); float a = popFloat(t); - if (a < b) { + if (isNaN(a) or isNaN(b)) { + pushInt(t, static_cast(-1)); + } if (a < b) { pushInt(t, static_cast(-1)); } else if (a > b) { pushInt(t, 1); diff --git a/test/Floats.java b/test/Floats.java index b8b80cbd75..eca59b1bc9 100644 --- a/test/Floats.java +++ b/test/Floats.java @@ -329,5 +329,23 @@ public class Floats { { float v = Float.POSITIVE_INFINITY; expect(Long.MAX_VALUE == (long) v); } + + expect(Double.NaN != Double.NaN); + expect(! (Double.NaN == Double.NaN)); + + { double d = Double.NaN; + expect(Double.NaN != d); + expect(! (Double.NaN == d)); + expect(d != d); + expect(! (d == d)); } + + expect(Float.NaN != Float.NaN); + expect(! (Float.NaN == Float.NaN)); + + { float d = Float.NaN; + expect(Float.NaN != d); + expect(! (Float.NaN == d)); + expect(d != d); + expect(! (d == d)); } } } From 8c1419fb8939cb5e0c260208c07b31b3c156b6c1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 4 Apr 2013 20:02:49 -0600 Subject: [PATCH 354/378] jump to target if JumpIfFloatNotEqual comparison is unordered A dcmpl or dcmpg followed by an ifneq should take the branch if an NaN is involved. --- src/codegen/target/x86/encode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen/target/x86/encode.cpp b/src/codegen/target/x86/encode.cpp index e2f1ee287e..97c85d5fc3 100644 --- a/src/codegen/target/x86/encode.cpp +++ b/src/codegen/target/x86/encode.cpp @@ -251,6 +251,7 @@ void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) { case lir::JumpIfFloatNotEqual: conditional(c, 0x85, target); + conditional(c, 0x8a, target); break; case lir::JumpIfFloatLess: From 49d8ccb1bdfecfa49eec051c6e3f2957b44b8b0c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 9 Apr 2013 18:43:46 -0600 Subject: [PATCH 355/378] update Context::executableSize after allocating objectPool This ensures that, if an exception is thrown later but before the method has been fully compiled, we will know exactly how much memory to free. Previously, we would abort when trying to free the wrong amount due to an assertion failure. --- src/compile.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compile.cpp b/src/compile.cpp index fd5ebc1f74..8741fcddbd 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -7307,6 +7307,9 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) FixedSizeOfArray + ((context->objectPoolCount + 1) * BytesPerWord), true); + context->executableSize = (allocator->base + allocator->offset) + - static_cast(context->executableStart); + initArray(t, pool, context->objectPoolCount + 1); mark(t, pool, 0); From 73547db7372c2b02fa1eecad678bd9b0c8fe4241 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 9 Apr 2013 17:43:25 -0600 Subject: [PATCH 356/378] throw IllegalArgumentException in JVM_InvokeMethod on type mismatch --- src/classpath-openjdk.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index ae7bba5264..c244e79d1d 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4674,6 +4674,10 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) (t, jclassVmClass(t, jmethodClazz(t, *method))), jmethodSlot(t, *method)); + if (instance and not instanceOf(t, methodClass(t, vmMethod), *instance)) { + throwNew(t, Machine::IllegalArgumentExceptionType); + } + return reinterpret_cast (makeLocalReference (t, invoke From 83670d1df7c206da78312949ce1ff4f28251443a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 9 Apr 2013 17:44:21 -0600 Subject: [PATCH 357/378] implement JVM_ConstantPoolGetLongAt --- src/classpath-openjdk.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index c244e79d1d..c088b9b987 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4806,8 +4806,15 @@ EXPORT(JVM_ConstantPoolGetIntAt)(Thread* t, jobject, jobject pool, jint index) } extern "C" JNIEXPORT jlong JNICALL -EXPORT(JVM_ConstantPoolGetLongAt)(Thread*, jobject, jobject, jint) -{ abort(); } +EXPORT(JVM_ConstantPoolGetLongAt)(Thread* t, jobject, jobject pool, jint index) +{ + ENTER(t, Thread::ActiveState); + + uint64_t v; + memcpy(&v, &singletonValue(t, *pool, index - 1), 8); + + return v; +} extern "C" JNIEXPORT jfloat JNICALL EXPORT(JVM_ConstantPoolGetFloatAt)(Thread*, jobject, jobject, jint) From dca75df926e48f2a6f3b5ab2c3077d7c21696054 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 9 Apr 2013 17:45:19 -0600 Subject: [PATCH 358/378] add vmfPrintTrace method for dumping traces to a specific stream --- src/avian/machine.h | 3 +++ src/machine.cpp | 25 ++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/avian/machine.h b/src/avian/machine.h index 5c57bc18e2..a53d4c98f2 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -2699,6 +2699,9 @@ popResources(Thread* t); JNIEXPORT void vmPrintTrace(vm::Thread* t); +JNIEXPORT void +vmfPrintTrace(vm::Thread* t, FILE* out); + namespace vm { void diff --git a/src/machine.cpp b/src/machine.cpp index 098a60130a..0f5bf55291 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -5171,11 +5171,11 @@ noop() // for debugging JNIEXPORT void -vmPrintTrace(Thread* t) +vmfPrintTrace(Thread* t, FILE* out) { class Visitor: public Processor::StackVisitor { public: - Visitor(Thread* t): t(t) { } + Visitor(Thread* t, FILE* out): t(t), out(out) { } virtual bool visit(Processor::StackWalker* walker) { const int8_t* class_ = &byteArrayBody @@ -5185,30 +5185,37 @@ vmPrintTrace(Thread* t) int line = t->m->processor->lineNumber (t, walker->method(), walker->ip()); - fprintf(stderr, " at %s.%s ", class_, method); + fprintf(out, " at %s.%s ", class_, method); switch (line) { case NativeLine: - fprintf(stderr, "(native)\n"); + fprintf(out, "(native)\n"); break; case UnknownLine: - fprintf(stderr, "(unknown line)\n"); + fprintf(out, "(unknown line)\n"); break; default: - fprintf(stderr, "(line %d)\n", line); + fprintf(out, "(line %d)\n", line); } return true; } Thread* t; - } v(t); + FILE* out; + } v(t, out); - fprintf(stderr, "debug trace for thread %p\n", t); + fprintf(out, "debug trace for thread %p\n", t); t->m->processor->walkStack(t, &v); - fflush(stderr); + fflush(out); +} + +JNIEXPORT void +vmPrintTrace(Thread* t) +{ + vmfPrintTrace(t, stderr); } // also for debugging From 2c902a26ece0891f8240fcb7c1c67542e7da7ccc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 9 Apr 2013 18:44:54 -0600 Subject: [PATCH 359/378] handle non-ASCII strings properly in MyClasspath::makeString --- src/classpath-openjdk.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index c088b9b987..f39464b5cd 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -504,7 +504,23 @@ class MyClasspath : public Classpath { object charArray = makeCharArray(t, length); for (int i = 0; i < length; ++i) { - expect(t, (byteArrayBody(t, array, offset + i) & 0x80) == 0); + if (byteArrayBody(t, array, offset + i) & 0x80) { + object constructor = resolveMethod + (t, type(t, Machine::StringType), "", + "([BIILjava/lang/String;)V"); + PROTECT(t, constructor); + + object utf8 = vm::makeString(t, "UTF8"); + PROTECT(t, utf8); + + object s = makeNew(t, type(t, Machine::StringType)); + PROTECT(t, s); + + t->m->processor->invoke + (t, constructor, s, array, offset, length, utf8); + + return s; + } charArrayBody(t, charArray, i) = byteArrayBody(t, array, offset + i); } From 9f8369c5cc03d5a0121ed644c0fbb64a2360f7ed Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 15 Apr 2013 12:37:23 -0600 Subject: [PATCH 360/378] enter exclusive state in destroyJavaVM This is necessary to ensure that new threads do not start while we're shutting down (except for the ones that we start to run the shutdown hooks), and that the shutdown hook threads can be safely started (it is not safe to start threads from e.g. an idle state, and an assertion will fail if we do). --- src/jnienv.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 741da645dd..334d36d3ba 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -79,6 +79,8 @@ destroyJavaVM(Thread* t, uintptr_t*) while (t->m->liveCount - t->m->daemonCount > 1) { t->m->stateLock->wait(t->systemThread, 0); } + + enter(t, Thread::ExclusiveState); } shutDown(t); From aa513c2c1dcde7fb9e329f6a7a491da544d73e42 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 16 Apr 2013 19:25:19 -0600 Subject: [PATCH 361/378] set default file.encoding to UTF-8 in classpath-openjdk.cpp This default makes more sense than ASCII, which is what it had been. --- src/classpath-openjdk.cpp | 2 +- test/Strings.java | 47 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index f39464b5cd..c5b7e8769f 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3285,7 +3285,7 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) static_cast (systemClassLoaderFinder(t, root(t, Machine::BootLoader)))->path()); - local::setProperty(t, method, *properties, "file.encoding", "ASCII"); + local::setProperty(t, method, *properties, "file.encoding", "UTF-8"); #ifdef ARCH_x86_32 local::setProperty(t, method, *properties, "os.arch", "x86"); #elif defined ARCH_x86_64 diff --git a/test/Strings.java b/test/Strings.java index a49b37c9e1..7ba502b9d5 100644 --- a/test/Strings.java +++ b/test/Strings.java @@ -7,6 +7,31 @@ public class Strings { return a == b || (a != null && a.equals(b)); } + private static boolean arraysEqual(byte[] a, byte[] b) { + if (a.length != b.length) { + return false; + } + + for (int i = 0; i < a.length; ++i) { + if (a[i] != b[i]) { + return false; + } + } + + return true; + } + + private static byte[] append(byte[] a, byte[] b) { + byte[] c = new byte[a.length + b.length]; + for (int i = 0; i < a.length; ++i) { + c[i] = a[i]; + } + for (int i = 0; i < b.length; ++i) { + c[i + a.length] = b[i]; + } + return c; + } + private static boolean arraysEqual(Object[] a, Object[] b) { if (a.length != b.length) { return false; @@ -146,5 +171,27 @@ public class Strings { "I", "grape", "nuts", "foobar", new Object() { public String toString() { return "you"; } }) .equals("I enjoy grape nuts. do you? you do?")); + + { java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream(); + java.io.PrintStream pout = new java.io.PrintStream(bout); + String s = "I ♥ grape nuts"; + System.out.println(s); + pout.println(s); + + expect + (arraysEqual + (bout.toByteArray(), + (s + System.getProperty("line.separator")).getBytes())); + + // note that this effectively asserts that the VM's default + // charset is UTF-8. If we want to make this test more + // portable, we should specify the charset explicitly. + expect + (arraysEqual + (bout.toByteArray(), append + (new byte[] { 73, 32, -30, -103, -91, 32, 103, 114, 97, 112, 101, + 32, 110, 117, 116, 115 }, + System.getProperty("line.separator").getBytes()))); + } } } From 81d77867160c69040b7f3b01fae1cc93459416ca Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 17 Apr 2013 15:12:58 -0600 Subject: [PATCH 362/378] fix Class.getModifiers for inner classes and implement JVM_GetDeclaringClass and JVM_GetEnclosingMethodInfo properly This fixes a couple of tests in the Scala test suite (run/reflection-modulemirror-toplevel-badpath.scala and run/reflection-constructormirror-nested-good.scala). --- classpath/avian/ClassAddendum.java | 2 + classpath/avian/OpenJDK.java | 16 ------ src/classpath-openjdk.cpp | 86 ++++++++++++++++++++++++++---- src/machine.cpp | 28 ++++++++-- test/Misc.java | 3 ++ 5 files changed, 105 insertions(+), 30 deletions(-) diff --git a/classpath/avian/ClassAddendum.java b/classpath/avian/ClassAddendum.java index 48ac3bdd07..3d2a9addf2 100644 --- a/classpath/avian/ClassAddendum.java +++ b/classpath/avian/ClassAddendum.java @@ -14,4 +14,6 @@ public class ClassAddendum extends Addendum { public Object[] interfaceTable; public Object[] innerClassTable; public Object[] methodTable; + public Object enclosingClass; + public Object enclosingMethod; } diff --git a/classpath/avian/OpenJDK.java b/classpath/avian/OpenJDK.java index 95248b2398..7c60d7238d 100644 --- a/classpath/avian/OpenJDK.java +++ b/classpath/avian/OpenJDK.java @@ -45,20 +45,4 @@ public class OpenJDK { } return array; } - - public static Class getDeclaringClass(VMClass c) { - try { - String name = new String - (replace('/', '.', c.name, 0, c.name.length - 1), 0, - c.name.length - 1); - int index = name.lastIndexOf("$"); - if (index == -1) { - return null; - } else { - return c.loader.loadClass(name.substring(0, index)); - } - } catch (ClassNotFoundException e) { - return null; - } - } } diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index c5b7e8769f..309ecfbea9 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4445,8 +4445,8 @@ jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments) if (innerClassReferenceOuter(t, arrayBody(t, table, i))) { object inner = getJClass (t, resolveClass - (t, classLoader(t, jclassVmClass(t, *c)), referenceName - (t, innerClassReferenceInner(t, arrayBody(t, table, i))))); + (t, classLoader(t, jclassVmClass(t, *c)), + innerClassReferenceInner(t, arrayBody(t, table, i)))); -- count; set(t, result, ArrayBody + (count * BytesPerWord), inner); @@ -4474,13 +4474,29 @@ jvmGetDeclaringClass(Thread* t, uintptr_t* arguments) { jclass c = reinterpret_cast(arguments[0]); - object method = resolveMethod - (t, root(t, Machine::BootLoader), "avian/OpenJDK", "getDeclaringClass", - "(Lavian/VMClass;)Ljava/lang/Class;"); + object class_ = jclassVmClass(t, *c); + object addendum = classAddendum(t, class_); + if (addendum) { + object table = classAddendumInnerClassTable(t, addendum); + if (table) { + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + object reference = arrayBody(t, table, i); + if (strcmp + (&byteArrayBody(t, innerClassReferenceInner(t, reference), 0), + &byteArrayBody(t, className(t, class_), 0)) == 0) + { + return reinterpret_cast + (makeLocalReference + (t, getJClass + (t, resolveClass + (t, classLoader(t, class_), innerClassReferenceOuter + (t, reference))))); + } + } + } + } - return reinterpret_cast - (makeLocalReference - (t, t->m->processor->invoke(t, method, 0, jclassVmClass(t, *c)))); + return 0; } extern "C" JNIEXPORT jclass JNICALL @@ -5517,13 +5533,61 @@ EXPORT(JVM_GetManagement)(jint version) extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_InitAgentProperties)(Thread*, jobject) { abort(); } -extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_GetEnclosingMethodInfo)(JNIEnv*, jclass) +uint64_t +getEnclosingMethodInfo(Thread* t, uintptr_t* arguments) { - // todo: implement properly + jclass c = reinterpret_cast(arguments[0]); + object class_ = jclassVmClass(t, *c); + PROTECT(t, class_); + + object addendum = classAddendum(t, class_); + if (addendum) { + object enclosingClass = classAddendumEnclosingClass(t, addendum); + if (enclosingClass) { + PROTECT(t, enclosingClass); + + object array = makeObjectArray(t, type(t, Machine::JobjectType), 3); + PROTECT(t, array); + + enclosingClass = getJClass + (t, resolveClass(t, classLoader(t, class_), enclosingClass)); + + set(t, array, ArrayBody, enclosingClass); + + object enclosingMethod = classAddendumEnclosingMethod(t, addendum); + + if (enclosingMethod) { + PROTECT(t, enclosingMethod); + + object name = t->m->classpath->makeString + (t, pairFirst(t, enclosingMethod), 0, + byteArrayLength(t, pairFirst(t, enclosingMethod)) - 1); + + set(t, array, ArrayBody + BytesPerWord, name); + + object spec = t->m->classpath->makeString + (t, pairSecond(t, enclosingMethod), 0, + byteArrayLength(t, pairSecond(t, enclosingMethod)) - 1); + + set(t, array, ArrayBody + (2 * BytesPerWord), spec); + } + + return reinterpret_cast(makeLocalReference(t, array)); + } + } return 0; } + +extern "C" JNIEXPORT jobjectArray JNICALL +EXPORT(JVM_GetEnclosingMethodInfo)(Thread* t, jclass c) +{ + uintptr_t arguments[] = { reinterpret_cast(c) }; + + return reinterpret_cast + (run(t, getEnclosingMethodInfo, arguments)); +} + extern "C" JNIEXPORT jintArray JNICALL EXPORT(JVM_GetThreadStateValues)(JNIEnv*, jint) { abort(); } diff --git a/src/machine.cpp b/src/machine.cpp index 0f5bf55291..3f66a3785c 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1123,7 +1123,7 @@ getClassAddendum(Thread* t, object class_, object pool) if (addendum == 0) { PROTECT(t, class_); - addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, 0); + addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, 0, 0, 0); set(t, class_, ClassAddendum, addendum); } return addendum; @@ -2303,12 +2303,20 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) int16_t flags = s.read2(); object reference = makeInnerClassReference - (t, inner ? singletonObject(t, pool, inner - 1) : 0, - outer ? singletonObject(t, pool, outer - 1) : 0, + (t, + inner ? referenceName(t, singletonObject(t, pool, inner - 1)) : 0, + outer ? referenceName(t, singletonObject(t, pool, outer - 1)) : 0, name ? singletonObject(t, pool, name - 1) : 0, flags); set(t, table, ArrayBody + (i * BytesPerWord), reference); + + if (0 == strcmp + (&byteArrayBody(t, className(t, class_), 0), + &byteArrayBody(t, innerClassReferenceInner(t, reference), 0))) + { + classFlags(t, class_) |= flags; + } } object addendum = getClassAddendum(t, class_, pool); @@ -2323,6 +2331,20 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) object addendum = getClassAddendum(t, class_, pool); set(t, addendum, AddendumAnnotationTable, body); + } else if (vm::strcmp(reinterpret_cast + ("EnclosingMethod"), + &byteArrayBody(t, name, 0)) == 0) + { + int16_t enclosingClass = s.read2(); + int16_t enclosingMethod = s.read2(); + + object addendum = getClassAddendum(t, class_, pool); + + set(t, addendum, ClassAddendumEnclosingClass, + referenceName(t, singletonObject(t, pool, enclosingClass - 1))); + + set(t, addendum, ClassAddendumEnclosingMethod, enclosingMethod + ? singletonObject(t, pool, enclosingMethod - 1) : 0); } else { s.skip(length); } diff --git a/test/Misc.java b/test/Misc.java index 669e7bf691..66f290f177 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -256,5 +256,8 @@ public class Misc { expect(new Object[0] instanceof Cloneable); expect(new Object[0] instanceof java.io.Serializable); + + expect((Baz.class.getModifiers() & java.lang.reflect.Modifier.STATIC) + != 0); } } From b4c3eea0f1e7385b679220dd322bb93990ab11fd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 18 Apr 2013 11:23:59 -0600 Subject: [PATCH 363/378] set InvocationTargetException target When using the OpenJDK classpath, the target exception and the Throwable cause are two different fields; we must set them both. --- classpath/java/lang/reflect/InvocationTargetException.java | 2 ++ src/avian/classpath-common.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/classpath/java/lang/reflect/InvocationTargetException.java b/classpath/java/lang/reflect/InvocationTargetException.java index abac51cb43..362bfb0788 100644 --- a/classpath/java/lang/reflect/InvocationTargetException.java +++ b/classpath/java/lang/reflect/InvocationTargetException.java @@ -11,6 +11,8 @@ package java.lang.reflect; public class InvocationTargetException extends Exception { + private Throwable target; // for compatibility with OpenJDK + public InvocationTargetException(Throwable targetException, String message) { super(message, targetException); } diff --git a/src/avian/classpath-common.h b/src/avian/classpath-common.h index a9e4c3a834..eede892293 100644 --- a/src/avian/classpath-common.h +++ b/src/avian/classpath-common.h @@ -561,6 +561,9 @@ invoke(Thread* t, object method, object instance, object args) object exception = t->exception; t->exception = makeThrowable (t, Machine::InvocationTargetExceptionType, 0, 0, exception); + + set(t, t->exception, InvocationTargetExceptionTarget, + throwableCause(t, t->exception)); } }); From e6b6edfc254ba2635a9116101d1e6e499aa57d81 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 18 Apr 2013 11:25:29 -0600 Subject: [PATCH 364/378] ignore instance variable for static method invocations --- src/classpath-openjdk.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 309ecfbea9..c85c8a184c 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4706,6 +4706,10 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) (t, jclassVmClass(t, jmethodClazz(t, *method))), jmethodSlot(t, *method)); + if (methodFlags(t, vmMethod) & ACC_STATIC) { + instance = 0; + } + if (instance and not instanceOf(t, methodClass(t, vmMethod), *instance)) { throwNew(t, Machine::IllegalArgumentExceptionType); } From 9918ea6cddd01648ce09cf9db7537174955fe21b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 18 Apr 2013 11:27:05 -0600 Subject: [PATCH 365/378] fix sign extension from constant to register on x86 scalac may generate a ldc followed by an l2i, whereas javac always seems to condense this into a single ldc_w. The former exposed a bug in the JIT compiler which we never hit with javac-generated bytecode. --- src/codegen/target/x86/encode.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/codegen/target/x86/encode.cpp b/src/codegen/target/x86/encode.cpp index 97c85d5fc3..7f8782b105 100644 --- a/src/codegen/target/x86/encode.cpp +++ b/src/codegen/target/x86/encode.cpp @@ -330,6 +330,10 @@ void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, if (vm::TargetBytesPerWord == 4 and bSize == 8) { int64_t v = a->value->value(); + if (aSize == 4) { + v = static_cast(v); + } + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); lir::Constant ah(&high); @@ -344,8 +348,16 @@ void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, maybeRex(c, vm::TargetBytesPerWord, b); opcode(c, 0xb8 + regCode(b)); if (a->value->resolved()) { - c->code.appendTargetAddress(a->value->value()); + int64_t v = a->value->value(); + + if (aSize == 4 and bSize == 8) { + v = static_cast(v); + } + + c->code.appendTargetAddress(v); } else { + expect(c, aSize == vm::TargetBytesPerWord); + appendImmediateTask (c, a->value, offsetPromise(c), vm::TargetBytesPerWord, promiseOffset); c->code.appendTargetAddress(static_cast(0)); From a09892654714f1f80c36a74bfc1e3fe5a8cd2bd4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 19 Apr 2013 13:00:47 -0600 Subject: [PATCH 366/378] run Shutdown.shutdown on exit when using OpenJDK library The OpenJDK library wants to track and run the shutdown hooks itself rather than let the VM do it, so we need to tell it when we're exiting. Also, in machine.cpp we need to use only the modifiers specified in the InnerClasses attribute for inner classes rather than OR them with the flags given at the top level of the class file. --- src/avian/machine.h | 3 +++ src/classpath-android.cpp | 6 ++++++ src/classpath-avian.cpp | 6 ++++++ src/classpath-openjdk.cpp | 15 +++++++++++++++ src/machine.cpp | 4 +++- test/Misc.java | 5 +++++ 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/avian/machine.h b/src/avian/machine.h index a53d4c98f2..ae6a0368da 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1592,6 +1592,9 @@ class Classpath { canTailCall(Thread* t, object caller, object calleeClassName, object calleeMethodName, object calleeMethodSpec) = 0; + virtual void + shutDown(Thread* t) = 0; + virtual void dispose() = 0; }; diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index bc325470b4..87fa114cf0 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -469,6 +469,12 @@ class MyClasspath : public Classpath { return true; } + virtual void + shutDown(Thread*) + { + // ignore + } + virtual void dispose() { diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 64c56fc389..ef16a767c1 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -186,6 +186,12 @@ class MyClasspath : public Classpath { return true; } + virtual void + shutDown(Thread*) + { + // ignore + } + virtual void dispose() { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index c85c8a184c..1a70816295 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -897,6 +897,21 @@ class MyClasspath : public Classpath { (&byteArrayBody(t, calleeClassName, 0)))); } + virtual void + shutDown(Thread* t) + { + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/Shutdown", false); + + if (c) { + object m = findMethodOrNull(t, c, "shutdown", "()V"); + + if (m) { + t->m->processor->invoke(t, m, 0); + } + } + } + virtual void dispose() { diff --git a/src/machine.cpp b/src/machine.cpp index 3f66a3785c..4e6ccd8ce0 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2315,7 +2315,7 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) (&byteArrayBody(t, className(t, class_), 0), &byteArrayBody(t, innerClassReferenceInner(t, reference), 0))) { - classFlags(t, class_) |= flags; + classFlags(t, class_) = flags; } } @@ -3321,6 +3321,8 @@ shutDown(Thread* t) setRoot(t, Machine::ShutdownHooks, 0); + t->m->classpath->shutDown(t); + object h = hooks; PROTECT(t, h); for (; h; h = pairSecond(t, h)) { diff --git a/test/Misc.java b/test/Misc.java index 66f290f177..91195d5f13 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -259,5 +259,10 @@ public class Misc { expect((Baz.class.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0); + + expect((Protected.class.getModifiers() & java.lang.reflect.Modifier.PUBLIC) + == 0); } + + protected class Protected { } } From e9a8aa2e65b2b061c08a931d5425514a75e7d86d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 19 Apr 2013 18:28:20 -0700 Subject: [PATCH 367/378] set boot library if run as java or javac command If sun.java.command or sun.java.launcher are set, then the VM is being loaded from e.g. libjvm.so, not as a stand-alone executable. This commit allows libjvm.dylib to be used with OpenJDK's java command on OS X. --- src/avian/jnienv.h | 2 ++ src/jnienv.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/avian/jnienv.h b/src/avian/jnienv.h index 06036e2b0d..a1f2ff90aa 100644 --- a/src/avian/jnienv.h +++ b/src/avian/jnienv.h @@ -14,6 +14,8 @@ #include "avian/machine.h" #define BOOTSTRAP_PROPERTY "avian.bootstrap" +#define JAVA_COMMAND_PROPERTY "sun.java.command" +#define JAVA_LAUNCHER_PROPERTY "sun.java.launcher" #define CRASHDIR_PROPERTY "avian.crash.dir" #define EMBED_PREFIX_PROPERTY "avian.embed.prefix" #define CLASSPATH_PROPERTY "java.class.path" diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 334d36d3ba..4fdb0cb618 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3829,6 +3829,14 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) sizeof(BOOTSTRAP_PROPERTY)) == 0) { bootLibraries = p + sizeof(BOOTSTRAP_PROPERTY); + } else if (strncmp(p, JAVA_COMMAND_PROPERTY "=", + sizeof(JAVA_COMMAND_PROPERTY)) == 0 + or strncmp(p, JAVA_LAUNCHER_PROPERTY "=", + sizeof(JAVA_LAUNCHER_PROPERTY)) == 0) + { + // this means we're being invoked via the javac or java + // command, so the bootstrap library should be e.g. libjvm.so + bootLibraries = SO_PREFIX "jvm" SO_SUFFIX; } else if (strncmp(p, CRASHDIR_PROPERTY "=", sizeof(CRASHDIR_PROPERTY)) == 0) { From 64002319c56a5f3bcf8a6664ac5d66520933c69e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 17:10:23 -0600 Subject: [PATCH 368/378] use Android directory layout when accessing class library code Per https://github.com/ReadyTalk/avian/issues/53, Avian should build against a standard AOSP checkout, which means we should look for subprojects in the directories the repo utility would place them. --- README.md | 58 +++++++++++++++++++++++++++++++------------------------ makefile | 32 +++++++++++++++--------------- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index b4d47e1183..1aba5f6f69 100644 --- a/README.md +++ b/README.md @@ -354,38 +354,46 @@ can also build with the Android class library on some platforms (currently Linux works and OS X mostly works). To build this way, do the following, starting from the Avian directory: - $ cd .. - $ mkdir android - $ git clone https://android.googlesource.com/platform/bionic - $ git clone https://android.googlesource.com/platform/system/core - $ git clone https://android.googlesource.com/platform/external/expat - $ git clone https://android.googlesource.com/platform/external/fdlibm - $ git clone https://android.googlesource.com/platform/external/icu4c - $ git clone https://android.googlesource.com/platform/libnativehelper - $ git clone https://android.googlesource.com/platform/external/openssl - $ git clone https://android.googlesource.com/platform/external/zlib - $ git clone git://git.openssl.org/openssl.git openssl-upstream - $ git clone https://github.com/dicej/android-libcore64 libcore - $ (cd expat && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ - && make) - $ (cd fdlibm && (mv makefile.in Makefile.in || true) \ - && CFLAGS=-fPIC bash configure && make) - $ (cd icu4c && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static \ - && make) + cd .. + mkdir -p android/system android/external + cd android + git clone https://android.googlesource.com/platform/bionic + git clone https://android.googlesource.com/platform/system/core \ + system/core + git clone https://android.googlesource.com/platform/external/expat \ + external/expat + git clone https://android.googlesource.com/platform/external/fdlibm \ + external/fdlibm + git clone https://android.googlesource.com/platform/external/icu4c \ + external/icu4c + git clone https://android.googlesource.com/platform/libnativehelper + git clone https://android.googlesource.com/platform/external/openssl \ + external/openssl + git clone https://android.googlesource.com/platform/external/zlib \ + external/zlib + git clone git://git.openssl.org/openssl.git openssl-upstream + git clone https://github.com/dicej/android-libcore64 libcore + (cd external/expat && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure \ + --enable-static && make) + (cd external/fdlibm && (mv makefile.in Makefile.in || true) \ + && CFLAGS=-fPIC bash configure && make) + (cd external/icu4c && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure \ + --enable-static && make) NB: use 'CC="gcc -fPIC" ./Configure darwin64-x86_64-cc' when building for x86_64 OS X instead of 'CC="gcc -fPIC" ./config': - $ (cd openssl-upstream && git checkout OpenSSL_1_0_1e \ - && (for x in ../openssl/patches/*.patch; do patch -p1 < $x; done) \ - && CC="gcc -fPIC" ./config && make) - $ cd ../avian - $ make android=$(pwd)/../android test + (cd openssl-upstream && git checkout OpenSSL_1_0_1e \ + && (for x in ../external/openssl/patches/*.patch; \ + do patch -p1 < $x; done) \ + && CC="gcc -fPIC" ./config && make) + cd ../avian + make android=$(pwd)/../android test Note that we use https://github.com/dicej/android-libcore64 above instead of the upstream -https://android.googlesource.com/platform/libcore repository. This is -temporary until upstream has been patched with 64-bit support. +https://android.googlesource.com/platform/libcore repository, since +the former has patches to provide better support for non-Linux platforms. Also note that we use the upstream OpenSSL repository and apply the Android patches to it. This is because it is not clear how to build diff --git a/makefile b/makefile index fda2b32132..93415db230 100755 --- a/makefile +++ b/makefile @@ -157,12 +157,12 @@ ifneq ($(android),) classpath-cflags = -DBOOT_JAVAHOME android-cflags := -I$(luni-native) \ -I$(android)/libnativehelper/include/nativehelper \ - -I$(android)/core/include \ - -I$(android)/zlib \ - -I$(android)/icu4c/i18n \ - -I$(android)/icu4c/common \ - -I$(android)/expat \ - -I$(android)/openssl/include \ + -I$(android)/system/core/include \ + -I$(android)/external/zlib \ + -I$(android)/external/icu4c/i18n \ + -I$(android)/external/icu4c/common \ + -I$(android)/external/expat \ + -I$(android)/external/openssl/include \ -I$(android)/libcore/include \ -I$(build)/android-src/external/fdlibm \ -I$(build)/android-src \ @@ -188,21 +188,21 @@ ifneq ($(android),) $(luni-native)/AsynchronousSocketCloseMonitor.cpp \ $(luni-native)/NetworkUtilities.cpp luni-cpps := $(filter-out $(blacklist),$(luni-cpps)) - icu-libs := $(android)/icu4c/lib/sicuin.a \ - $(android)/icu4c/lib/sicuuc.a \ - $(android)/icu4c/lib/sicudt.a + icu-libs := $(android)/external/icu4c/lib/sicuin.a \ + $(android)/external/icu4c/lib/sicuuc.a \ + $(android)/external/icu4c/lib/sicudt.a platform-lflags := -lgdi32 else android-cflags += -fPIC -DHAVE_SYS_UIO_H - icu-libs := $(android)/icu4c/lib/libicui18n.a \ - $(android)/icu4c/lib/libicuuc.a \ - $(android)/icu4c/lib/libicudata.a + icu-libs := $(android)/external/icu4c/lib/libicui18n.a \ + $(android)/external/icu4c/lib/libicuuc.a \ + $(android)/external/icu4c/lib/libicudata.a endif classpath-lflags := \ $(icu-libs) \ - $(android)/fdlibm/libfdm.a \ - $(android)/expat/.libs/libexpat.a \ + $(android)/external/fdlibm/libfdm.a \ + $(android)/external/expat/.libs/libexpat.a \ $(android)/openssl-upstream/libssl.a \ $(android)/openssl-upstream/libcrypto.a \ $(platform-lflags) \ @@ -1475,8 +1475,8 @@ $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(xml-javas) @mkdir -p $(build)/android @mkdir -p $(build)/android-src/external/fdlibm @mkdir -p $(build)/android-src/libexpat - cp $(android)/fdlibm/fdlibm.h $(build)/android-src/external/fdlibm/ - cp $(android)/expat/lib/expat*.h $(build)/android-src/libexpat/ + cp $(android)/external/fdlibm/fdlibm.h $(build)/android-src/external/fdlibm/ + cp $(android)/external/expat/lib/expat*.h $(build)/android-src/libexpat/ cp -a $(luni-java)/* $(dalvik-java)/* $(xml-java)/* $(build)/android-src/ sed -i -e 's/return ordinal - o.ordinal;/return ordinal - o.ordinal();/' \ $(build)/android-src/java/lang/Enum.java From f38c4e25c6d8fa1fdfd9f25134fce14c4bb7fab8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 18:57:26 -0600 Subject: [PATCH 369/378] fix array class name length calculation in invoke The original calculation ommitted the last character, changing e.g. "[I" into "[". --- src/avian/classpath-common.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/avian/classpath-common.h b/src/avian/classpath-common.h index eede892293..951d16b97d 100644 --- a/src/avian/classpath-common.h +++ b/src/avian/classpath-common.h @@ -527,10 +527,16 @@ invoke(Thread* t, object method, object instance, object args) case 'J': type = vm::type(t, Machine::LongType); break; case 'D': type = vm::type(t, Machine::DoubleType); break; - case 'L': ++ p; + case 'L': case '[': { objectType = true; - unsigned nameLength = it.s - p; + unsigned nameLength; + if (*p == 'L') { + ++ p; + nameLength = it.s - p; + } else { + nameLength = (it.s - p) + 1; + } THREAD_RUNTIME_ARRAY(t, char, name, nameLength); memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1); RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0; From d8729a7a8db9071e54b66143d53441b39f8378b8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 19:00:54 -0600 Subject: [PATCH 370/378] fix zero-extension of constants in x86 compiler scalac may emit a ldc followed by an i2c, whereas javac does the conversion (including zero extension if necessary) at compile time. This commit ensures we handle the i2c case properly. --- src/codegen/target/x86/multimethod.cpp | 2 +- src/codegen/target/x86/operations.cpp | 13 +++++++++++++ src/codegen/target/x86/operations.h | 3 +++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/codegen/target/x86/multimethod.cpp b/src/codegen/target/x86/multimethod.cpp index fa5e52495c..5086d27db7 100644 --- a/src/codegen/target/x86/multimethod.cpp +++ b/src/codegen/target/x86/multimethod.cpp @@ -107,7 +107,7 @@ void populateTables(ArchitectureContext* c) { bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); - bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR); + bo[index(c, lir::MoveZ, C, R)] = CAST2(moveZCR); bo[index(c, lir::Add, R, R)] = CAST2(addRR); bo[index(c, lir::Add, C, R)] = CAST2(addCR); diff --git a/src/codegen/target/x86/operations.cpp b/src/codegen/target/x86/operations.cpp index 477c3a8859..6e7c337891 100644 --- a/src/codegen/target/x86/operations.cpp +++ b/src/codegen/target/x86/operations.cpp @@ -226,6 +226,19 @@ void moveCR(Context* c, unsigned aSize, lir::Constant* a, } } +void moveZCR(Context* c, unsigned aSize UNUSED, lir::Constant* a, + unsigned bSize UNUSED, lir::Register* b) +{ + assert(c, not isFloatReg(b)); + assert(c, aSize == 2); + assert(c, bSize == vm::TargetBytesPerWord); + assert(c, a->value->resolved()); + + maybeRex(c, vm::TargetBytesPerWord, b); + opcode(c, 0xb8 + regCode(b)); + c->code.appendTargetAddress(static_cast(a->value->value())); +} + void swapRR(Context* c, unsigned aSize UNUSED, lir::Register* a, unsigned bSize UNUSED, lir::Register* b) { diff --git a/src/codegen/target/x86/operations.h b/src/codegen/target/x86/operations.h index 583102b041..e6250ef213 100644 --- a/src/codegen/target/x86/operations.h +++ b/src/codegen/target/x86/operations.h @@ -65,6 +65,9 @@ void negateRR(Context* c, unsigned aSize, lir::Register* a, void moveCR(Context* c, unsigned aSize, lir::Constant* a, unsigned bSize, lir::Register* b); +void moveZCR(Context* c, unsigned aSize, lir::Constant* a, + unsigned bSize, lir::Register* b); + void swapRR(Context* c, unsigned aSize UNUSED, lir::Register* a, unsigned bSize UNUSED, lir::Register* b); From 68c3b241ceb093ef4ff02e2a3b3943dd18ae2525 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 19:11:50 -0600 Subject: [PATCH 371/378] handle sign extension of constants of various lengths This is a generalization of 9918ea6 which handles 8-bit and 16-bit as well as 32-bit values. --- src/codegen/target/x86/encode.cpp | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/codegen/target/x86/encode.cpp b/src/codegen/target/x86/encode.cpp index 7f8782b105..31852f4269 100644 --- a/src/codegen/target/x86/encode.cpp +++ b/src/codegen/target/x86/encode.cpp @@ -24,6 +24,24 @@ using namespace avian::util; +namespace { + +int64_t +signExtend(unsigned size, int64_t v) +{ + if (size == 4) { + return static_cast(v); + } else if (size == 2) { + return static_cast(v); + } else if (size == 1) { + return static_cast(v); + } else { + return v; + } +} + +} // namespace + namespace avian { namespace codegen { namespace x86 { @@ -328,11 +346,7 @@ void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, UNUSED unsigned bSize, lir::Register* b, unsigned promiseOffset) { if (vm::TargetBytesPerWord == 4 and bSize == 8) { - int64_t v = a->value->value(); - - if (aSize == 4) { - v = static_cast(v); - } + int64_t v = signExtend(aSize, a->value->value()); ResolvedPromise high((v >> 32) & 0xFFFFFFFF); lir::Constant ah(&high); @@ -348,13 +362,7 @@ void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a, maybeRex(c, vm::TargetBytesPerWord, b); opcode(c, 0xb8 + regCode(b)); if (a->value->resolved()) { - int64_t v = a->value->value(); - - if (aSize == 4 and bSize == 8) { - v = static_cast(v); - } - - c->code.appendTargetAddress(v); + c->code.appendTargetAddress(signExtend(aSize, a->value->value())); } else { expect(c, aSize == vm::TargetBytesPerWord); From e0ceaa5f435eedfd25040cd812aca91b40936934 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 21:17:31 -0600 Subject: [PATCH 372/378] avoid allocating new memory in hashMapRemove when GCing This ensures that we don't abort when running an internal finalizer that removes from a hash map. --- src/util.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/util.cpp b/src/util.cpp index 248277aef6..1421824919 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -449,6 +449,12 @@ hashMapInsert(Thread* t, object map, object key, object value, set(t, n, TripleThird, arrayBody(t, array, index)); set(t, array, ArrayBody + (index * BytesPerWord), n); + + if (hashMapSize(t, map) <= arrayLength(t, array) / 3) { + // this might happen if nodes were removed during GC in which case + // we weren't able to resize at the time + hashMapResize(t, map, hash, arrayLength(t, array) / 2); + } } object @@ -495,7 +501,9 @@ hashMapRemove(Thread* t, object map, object key, } } - if (hashMapSize(t, map) <= arrayLength(t, array) / 3) { + if ((not t->m->collecting) + and hashMapSize(t, map) <= arrayLength(t, array) / 3) + { PROTECT(t, o); hashMapResize(t, map, hash, arrayLength(t, array) / 2); } From 63ee3ab0a2f0d75dc527e6f8bffa8b7923d3f998 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 21:19:01 -0600 Subject: [PATCH 373/378] throw CloneNotSupportedException if Object.clone called on non-Cloneable --- src/avian/classpath-common.h | 5 ++++- src/types.def | 2 ++ vm.pro | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/avian/classpath-common.h b/src/avian/classpath-common.h index 951d16b97d..1137f9d2c9 100644 --- a/src/avian/classpath-common.h +++ b/src/avian/classpath-common.h @@ -260,11 +260,14 @@ clone(Thread* t, object o) memcpy(clone, o, size); // clear any object header flags: setObjectClass(t, o, objectClass(t, o)); - } else { + } else if (instanceOf(t, type(t, Machine::CloneableType), o)) { clone = make(t, class_); memcpy(reinterpret_cast(clone) + 1, reinterpret_cast(o) + 1, size - BytesPerWord); + } else { + throwNew(t, Machine::CloneNotSupportedExceptionType, "%s", + &byteArrayBody(t, className(t, objectClass(t, o)), 0)); } return clone; diff --git a/src/types.def b/src/types.def index faf1d1341c..c7731f648d 100644 --- a/src/types.def +++ b/src/types.def @@ -226,6 +226,8 @@ (type negativeArraySizeException java/lang/NegativeArraySizeException) +(type cloneNotSupportedException java/lang/CloneNotSupportedException) + (type reflectiveOperationException java/lang/ReflectiveOperationException) (type classCastException java/lang/ClassCastException) diff --git a/vm.pro b/vm.pro index 8d1ab22177..19bc238967 100644 --- a/vm.pro +++ b/vm.pro @@ -54,6 +54,7 @@ -keep public class java.lang.ArrayIndexOutOfBoundsException -keep public class java.lang.ArrayStoreException -keep public class java.lang.NegativeArraySizeException +-keep public class java.lang.CloneNotSupportedException -keep public class java.lang.ClassCastException -keep public class java.lang.ClassNotFoundException -keep public class java.lang.NullPointerException From e3fe9099a2329c3ed380ac38a426944fda79aed8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 21:20:21 -0600 Subject: [PATCH 374/378] filter InnerClasses attribute for relevant classes in JVM_GetDeclaredClasses The InnerClasses attribute may have entries for classes declared inside classes we don't care about, so we must check each entry's outer class reference and make sure it matches the one we do care about. --- src/classpath-openjdk.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 1a70816295..56f8526fcc 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4448,7 +4448,10 @@ jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments) unsigned count = 0; for (unsigned i = 0; i < arrayLength(t, table); ++i) { - if (innerClassReferenceOuter(t, arrayBody(t, table, i))) { + object outer = innerClassReferenceOuter(t, arrayBody(t, table, i)); + if (outer and byteArrayEqual + (t, outer, className(t, jclassVmClass(t, *c)))) + { ++ count; } } @@ -4457,7 +4460,10 @@ jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments) PROTECT(t, result); for (unsigned i = 0; i < arrayLength(t, table); ++i) { - if (innerClassReferenceOuter(t, arrayBody(t, table, i))) { + object outer = innerClassReferenceOuter(t, arrayBody(t, table, i)); + if (outer and byteArrayEqual + (t, outer, className(t, jclassVmClass(t, *c)))) + { object inner = getJClass (t, resolveClass (t, classLoader(t, jclassVmClass(t, *c)), From a18452f6c96f16e699117fe67a9ae84b6ba17075 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 21:23:32 -0600 Subject: [PATCH 375/378] implement JVM_ConstantPoolGetFloatAt This commit also simplifies JVM_ConstantPoolGetDoubleAt, which cannot throw an exception and thus need not go through vmRun. --- src/classpath-openjdk.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 56f8526fcc..fcbf27ea57 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4874,29 +4874,24 @@ EXPORT(JVM_ConstantPoolGetLongAt)(Thread* t, jobject, jobject pool, jint index) } extern "C" JNIEXPORT jfloat JNICALL -EXPORT(JVM_ConstantPoolGetFloatAt)(Thread*, jobject, jobject, jint) -{ abort(); } - -uint64_t -jvmConstantPoolGetDoubleAt(Thread* t, uintptr_t* arguments) +EXPORT(JVM_ConstantPoolGetFloatAt)(Thread* t, jobject, jobject pool, + jint index) { - jobject pool = reinterpret_cast(arguments[0]); - jint index = arguments[1]; + ENTER(t, Thread::ActiveState); - double v; memcpy(&v, &singletonValue(t, *pool, index - 1), 8); - - return doubleToBits(v); + return bitsToFloat(singletonValue(t, *pool, index - 1)); } extern "C" JNIEXPORT jdouble JNICALL EXPORT(JVM_ConstantPoolGetDoubleAt)(Thread* t, jobject, jobject pool, jint index) { - uintptr_t arguments[] = { reinterpret_cast(pool), - static_cast(index) }; + ENTER(t, Thread::ActiveState); - return bitsToDouble - (run(t, jvmConstantPoolGetDoubleAt, arguments)); + double v; + memcpy(&v, &singletonValue(t, *pool, index - 1), 8); + + return v; } extern "C" JNIEXPORT jstring JNICALL From 023787d121f6dc8eade412fab55f62f26d8c3163 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 21:25:15 -0600 Subject: [PATCH 376/378] fix special case of exception handler table translation scalac may generate bytecode such that an exception is thrown within the bounds of a handler for that exception such that the throw is the last instruction in the method, which we weren't handling properly. --- src/compile.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 8741fcddbd..d218048f40 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -6459,11 +6459,11 @@ resolveIpBackwards(Context* context, int start, int end) if (start >= static_cast (codeLength(t, methodCode(t, context->method)))) { - start = codeLength(t, methodCode(t, context->method)) - 1; - } - - while (start >= end and context->visitTable[start] == 0) { - -- start; + start = codeLength(t, methodCode(t, context->method)); + } else { + while (start >= end and context->visitTable[start] == 0) { + -- start; + } } if (start < end) { @@ -6523,7 +6523,8 @@ truncateLineNumberTable(Thread* t, object table, unsigned length) } object -translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start) +translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start, + intptr_t end) { avian::codegen::Compiler* c = context->compiler; @@ -6559,14 +6560,16 @@ translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start) exceptionHandlerStart(oldHandler)); assert(t, handlerEnd >= 0); - assert(t, handlerEnd < static_cast + assert(t, handlerEnd <= static_cast (codeLength(t, methodCode(t, context->method)))); intArrayBody(t, newIndex, ni * 3) = c->machineIp(handlerStart)->value() - start; intArrayBody(t, newIndex, (ni * 3) + 1) - = c->machineIp(handlerEnd)->value() - start; + = (handlerEnd == static_cast + (codeLength(t, methodCode(t, context->method))) + ? end : c->machineIp(handlerEnd)->value()) - start; intArrayBody(t, newIndex, (ni * 3) + 2) = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; @@ -7339,7 +7342,8 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) } { object newExceptionHandlerTable = translateExceptionHandlerTable - (t, context, reinterpret_cast(start)); + (t, context, reinterpret_cast(start), + reinterpret_cast(start) + codeSize); PROTECT(t, newExceptionHandlerTable); From 8995db69d279b240d104bfd2d21398266cb25984 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 21:28:25 -0600 Subject: [PATCH 377/378] fix element spec calculation for multidimensional primitive arrays The element class for e.g. [[[I should be [[I, not [I. --- src/machine.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 4e6ccd8ce0..6fe35a5ab9 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2510,10 +2510,13 @@ makeArrayClass(Thread* t, object loader, object spec, bool throw_, default: if (dimensions > 1) { char c = *s; - elementSpec = makeByteArray(t, 3); - byteArrayBody(t, elementSpec, 0) = '['; - byteArrayBody(t, elementSpec, 1) = c; - byteArrayBody(t, elementSpec, 2) = 0; + elementSpec = makeByteArray(t, dimensions + 1); + unsigned i; + for (i = 0; i < dimensions - 1; ++i) { + byteArrayBody(t, elementSpec, i) = '['; + } + byteArrayBody(t, elementSpec, i++) = c; + byteArrayBody(t, elementSpec, i) = 0; -- dimensions; } else { abort(t); From dfdd1f6e6c55ada96172f40d1256dc219637c492 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Apr 2013 21:29:58 -0600 Subject: [PATCH 378/378] move call to Classpath::shutDown We must be in the Active state, not the Exclusive state when calling this method since it may execute arbitrary Java code. This fixes an assertion failure in makeNew. --- src/jnienv.cpp | 5 +++++ src/machine.cpp | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 4fdb0cb618..5ae0dd7a7a 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -74,6 +74,11 @@ DetachCurrentThread(Machine* m) uint64_t destroyJavaVM(Thread* t, uintptr_t*) { + { ENTER(t, Thread::ActiveState); + + t->m->classpath->shutDown(t); + } + // wait for other non-daemon threads to exit { ACQUIRE(t, t->m->stateLock); while (t->m->liveCount - t->m->daemonCount > 1) { diff --git a/src/machine.cpp b/src/machine.cpp index 6fe35a5ab9..c0cdaaf925 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3324,8 +3324,6 @@ shutDown(Thread* t) setRoot(t, Machine::ShutdownHooks, 0); - t->m->classpath->shutDown(t); - object h = hooks; PROTECT(t, h); for (; h; h = pairSecond(t, h)) {