From b78c772ffbb19e95a46d8150dc9f69656c9d5fa2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 1 Jun 2012 11:46:56 -0600 Subject: [PATCH 01/14] fix C++11 narrowing conversion errors --- classpath/java-util-zip.cpp | 8 ++++++-- src/jnienv.cpp | 37 +++++++++++++++++++------------------ src/posix.cpp | 3 ++- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/classpath/java-util-zip.cpp b/classpath/java-util-zip.cpp index 9ae2833332..6fb471bdfd 100644 --- a/classpath/java-util-zip.cpp +++ b/classpath/java-util-zip.cpp @@ -76,7 +76,9 @@ Java_java_util_zip_Inflater_inflate int r = inflate(s, Z_SYNC_FLUSH); jint resultArray[3] - = { r, inputLength - s->avail_in, outputLength - s->avail_out }; + = { r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out) }; free(in); @@ -147,7 +149,9 @@ Java_java_util_zip_Deflater_deflate int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH); jint resultArray[3] - = { r, inputLength - s->avail_in, outputLength - s->avail_out }; + = { r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out) }; free(in); diff --git a/src/jnienv.cpp b/src/jnienv.cpp index ffc0937789..1631d0f3bb 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -252,7 +252,8 @@ NewString(Thread* t, const jchar* chars, jsize size) { if (chars == 0) return 0; - uintptr_t arguments[] = { reinterpret_cast(chars), size }; + uintptr_t arguments[] = { reinterpret_cast(chars), + static_cast(size) }; return reinterpret_cast(run(t, newString, arguments)); } @@ -311,7 +312,7 @@ DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer, { uintptr_t arguments[] = { reinterpret_cast(loader), reinterpret_cast(buffer), - length }; + static_cast(length) }; return reinterpret_cast(run(t, defineClass, arguments)); } @@ -1495,7 +1496,7 @@ SetByteField(Thread* t, jobject o, jfieldID field, jbyte v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setByteField, arguments); } @@ -1545,7 +1546,7 @@ SetShortField(Thread* t, jobject o, jfieldID field, jshort v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setShortField, arguments); } @@ -1570,7 +1571,7 @@ SetIntField(Thread* t, jobject o, jfieldID field, jint v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setIntField, arguments); } @@ -1975,7 +1976,7 @@ SetStaticByteField(Thread* t, jobject c, jfieldID field, jbyte v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticByteField, arguments); } @@ -2033,7 +2034,7 @@ SetStaticShortField(Thread* t, jobject c, jfieldID field, jshort v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticShortField, arguments); } @@ -2062,7 +2063,7 @@ SetStaticIntField(Thread* t, jobject c, jfieldID field, jint v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticIntField, arguments); } @@ -2261,7 +2262,7 @@ newObjectArray(Thread* t, uintptr_t* arguments) jobjectArray JNICALL NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) { - uintptr_t arguments[] = { length, + uintptr_t arguments[] = { static_cast(length), reinterpret_cast(class_), reinterpret_cast(init) }; @@ -2302,7 +2303,7 @@ NewBooleanArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeBooleanArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2318,7 +2319,7 @@ NewByteArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeByteArray0)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2328,7 +2329,7 @@ NewCharArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeCharArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2338,7 +2339,7 @@ NewShortArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeShortArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2348,7 +2349,7 @@ NewIntArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeIntArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2358,7 +2359,7 @@ NewLongArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeLongArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2368,7 +2369,7 @@ NewFloatArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeFloatArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2378,7 +2379,7 @@ NewDoubleArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeDoubleArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2905,7 +2906,7 @@ RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods, { uintptr_t arguments[] = { reinterpret_cast(c), reinterpret_cast(methods), - methodCount }; + static_cast(methodCount) }; return run(t, registerNatives, arguments) ? 0 : -1; } diff --git a/src/posix.cpp b/src/posix.cpp index 3d0f525013..ea3f133d37 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -340,7 +340,8 @@ class MySystem: public System { // milliseconds) is infinity so as to avoid overflow: if (time and time < INT64_C(31536000000000000)) { int64_t then = s->now() + time; - timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 }; + timespec ts = { static_cast(then / 1000), + static_cast((then % 1000) * 1000 * 1000) }; int rv UNUSED = pthread_cond_timedwait (&(t->condition), &(t->mutex), &ts); expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR); From 879df617df4b7905684646113b43a787372c64ae Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 1 Jun 2012 17:43:42 -0600 Subject: [PATCH 02/14] add use-clang option for building with LLVM Clang instead of GCC This also fixes several errors and warnings emitted by Clang. --- classpath/jni-util.h | 5 --- makefile | 37 +++++++++++----- readme.txt | 7 ++++ src/binaryToObject/elf.cpp | 15 +++---- src/binaryToObject/mach-o.cpp | 14 ++++--- src/binaryToObject/main.cpp | 2 +- src/binaryToObject/pe.cpp | 12 +++--- src/bootimage.cpp | 69 +++++++++++++----------------- src/compile.cpp | 8 ---- src/compiler.cpp | 66 ++++------------------------- src/heap.cpp | 7 ---- src/heapwalk.cpp | 10 ----- src/machine.cpp | 30 ------------- src/type-generator.cpp | 79 ----------------------------------- src/x86.cpp | 40 ------------------ 15 files changed, 94 insertions(+), 307 deletions(-) diff --git a/classpath/jni-util.h b/classpath/jni-util.h index 4973891704..57e545a14b 100644 --- a/classpath/jni-util.h +++ b/classpath/jni-util.h @@ -73,8 +73,6 @@ typedef unsigned __int64 uint64_t; #endif // not _MSC_VER -namespace { - inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...) { @@ -149,7 +147,4 @@ class RuntimeArray { #endif // not _MSC_VER - -} // namespace - #endif//JNI_UTIL diff --git a/makefile b/makefile index 42ef1b95e7..b528fc2fb3 100755 --- a/makefile +++ b/makefile @@ -138,8 +138,13 @@ endif input = List -build-cxx = g++ -build-cc = gcc +ifeq ($(use-clang),true) + build-cxx = clang + build-cc = clang +else + build-cxx = g++ + build-cc = gcc +endif mflag = ifneq ($(platform),darwin) @@ -195,7 +200,8 @@ build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject -Isrc/ \ -fno-rtti -fno-exceptions \ -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ - -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN + -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN \ + -Wall -Wextra -Werror -Wunused-parameter -Winit-self cflags = $(build-cflags) @@ -446,23 +452,32 @@ ifeq ($(mode),stress-major) strip = : endif ifeq ($(mode),fast) - optimization-cflags = -O3 -g3 -DNDEBUG + optimization-cflags = -O4 -g3 -DNDEBUG use-lto = true endif ifeq ($(mode),small) - optimization-cflags = -Os -g3 -DNDEBUG + ifeq ($(use-clang),true) + optimization-cflags = -Oz -g3 -DNDEBUG + else + optimization-cflags = -Os -g3 -DNDEBUG + endif use-lto = true endif ifeq ($(use-lto),true) -# only try to use LTO when GCC 4.6.0 or greater is available - gcc-major := $(shell $(cc) -dumpversion | cut -f1 -d.) - gcc-minor := $(shell $(cc) -dumpversion | cut -f2 -d.) - ifeq ($(shell expr 4 \< $(gcc-major) \ - \| \( 4 \<= $(gcc-major) \& 6 \<= $(gcc-minor) \)),1) + ifeq ($(use-clang),true) optimization-cflags += -flto - no-lto = -fno-lto lflags += $(optimization-cflags) + else +# only try to use LTO when GCC 4.6.0 or greater is available + gcc-major := $(shell $(cc) -dumpversion | cut -f1 -d.) + gcc-minor := $(shell $(cc) -dumpversion | cut -f2 -d.) + ifeq ($(shell expr 4 \< $(gcc-major) \ + \| \( 4 \<= $(gcc-major) \& 6 \<= $(gcc-minor) \)),1) + optimization-cflags += -flto + no-lto = -fno-lto + lflags += $(optimization-cflags) + endif endif endif diff --git a/readme.txt b/readme.txt index 6c08030677..ac54ca700f 100644 --- a/readme.txt +++ b/readme.txt @@ -63,6 +63,7 @@ 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 @@ -83,6 +84,7 @@ certain flags described below, all of which are optional. heapdump={true,false} \ tails={true,false} \ continuations={true,false} \ + use-clang={true,false} \ openjdk= \ openjdk-src= @@ -134,6 +136,11 @@ certain flags described below, all of which are optional. 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. diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index caf7c9c545..b4e0025b02 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -131,8 +131,9 @@ unsigned getElfPlatform(PlatformInfo::Architecture arch) { return EM_ARM; case PlatformInfo::PowerPC: return EM_PPC; + default: + return ~0; } - return ~0; } const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) { @@ -255,8 +256,8 @@ public: SectionWriter(FileWriter& file): file(file), name(""), - data(0), - dataSize(0) + dataSize(0), + data(0) { memset(&header, 0, sizeof(SectionHeader)); file.sectionCount++; @@ -279,8 +280,8 @@ public: file(file), name(chname), - data(data), - dataSize(dataSize) + dataSize(dataSize), + data(data) { if(strcmp(chname, ".shstrtab") == 0) { file.sectionStringTableSectionNumber = file.sectionCount; @@ -359,11 +360,11 @@ public: file.writeHeader(out); - for(int i = 0; i < file.sectionCount; i++) { + for(unsigned i = 0; i < file.sectionCount; i++) { sections[i].writeHeader(out); } - for(int i = 0; i < file.sectionCount; i++) { + for(unsigned i = 0; i < file.sectionCount; i++) { sections[i].writeData(out); } diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 50d7e56d78..dd89ddb304 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -183,14 +183,14 @@ public: FileHeader header = { V4(Magic), // magic - V4(cpuType), - V4(cpuSubType), + static_cast(V4(cpuType)), + static_cast(V4(cpuSubType)), V4(MH_OBJECT), // filetype, V4(2), // ncmds V4(sizeof(SegmentCommand) + sizeof(Section) + sizeof(SymtabCommand)), // sizeofcmds - V4(0) // flags + { V4(0) } // flags }; AddrTy finalSize = pad(data.count); @@ -206,8 +206,8 @@ public: + sizeof(Section) + sizeof(SymtabCommand))), // fileoff VANY(static_cast(finalSize)), // filesize - V4(7), // maxprot - V4(7), // initprot + static_cast(V4(7)), // maxprot + static_cast(V4(7)), // initprot V4(1), // nsects V4(0) // flags }; @@ -243,7 +243,7 @@ public: strings.write("_", 1); strings.add(sym->name); NList symbol = { - V4(offset), // n_un + { V4(offset) }, // n_un V1(N_SECT | N_EXT), // n_type V1(1), // n_sect V2(0), // n_desc @@ -281,6 +281,8 @@ public: out->writeChunk(symbolList.data, symbolList.length); out->writeChunk(strings.data, strings.length); + + return true; } MachOPlatform(PlatformInfo::Architecture arch): diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index d8f801a5e3..851a805bec 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -33,7 +33,7 @@ void* operator new(size_t size) { return malloc(size); } -void operator delete(void* mem) { abort(); } +void operator delete(void*) { abort(); } namespace { diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 32f13cc4fa..69ca719bc1 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -129,11 +129,11 @@ public: void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) { unsigned nameOffset = strings.add(name); IMAGE_SYMBOL symbol = { - { 0 }, // Name + { { 0, 0 } }, // Name addr, // Value - sectionNumber, // SectionNumber - type, // Type - storageClass, // StorageClass + static_cast(sectionNumber), // SectionNumber + static_cast(type), // Type + static_cast(storageClass), // StorageClass 0, // NumberOfAuxSymbols }; symbol.N.Name.Long = nameOffset+4; @@ -165,9 +165,9 @@ public: size_t dataSize): file(file), - data(data), dataSize(dataSize), - finalSize(pad(dataSize)) + finalSize(pad(dataSize)), + data(data) { file.sectionCount++; file.dataStart += sizeof(IMAGE_SECTION_HEADER); diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 17a27f198d..a4555a9f6e 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -62,14 +62,6 @@ enum Type { class Field { public: - Field() { } - - Field(Type type, unsigned buildOffset, unsigned buildSize, - unsigned targetOffset, unsigned targetSize): - type(type), buildOffset(buildOffset), buildSize(buildSize), - targetOffset(targetOffset), targetSize(targetSize) - { } - Type type; unsigned buildOffset; unsigned buildSize; @@ -77,6 +69,17 @@ class Field { unsigned targetSize; }; +void +init(Field* f, Type type, unsigned buildOffset, unsigned buildSize, + unsigned targetOffset, unsigned targetSize) +{ + f->type = type; + f->buildOffset = buildOffset; + f->buildSize = buildSize; + f->targetOffset = targetOffset; + f->targetSize = targetSize; +} + class TypeMap { public: enum Kind { @@ -397,9 +400,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, map->targetFixedOffsets()[i * BytesPerWord] = i * TargetBytesPerWord; - new (map->fixedFields() + i) Field - (types[i], i * BytesPerWord, BytesPerWord, - i * TargetBytesPerWord, TargetBytesPerWord); + init(new (map->fixedFields() + i) Field, types[i], + i * BytesPerWord, BytesPerWord, i * TargetBytesPerWord, + TargetBytesPerWord); } hashMapInsert @@ -446,8 +449,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ++ memberIndex; } } else { - new (memberFields) Field - (Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (memberFields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); memberIndex = 1; buildMemberOffset = BytesPerWord; @@ -456,12 +459,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, Field staticFields[count + 2]; - new (staticFields) Field - (Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); - new (staticFields + 1) Field - (Type_intptr_t, BytesPerWord, BytesPerWord, TargetBytesPerWord, - TargetBytesPerWord); + init(new (staticFields + 1) Field, Type_intptr_t, BytesPerWord, + BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); unsigned staticIndex = 2; unsigned buildStaticOffset = BytesPerWord * 2; @@ -510,9 +512,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildStaticOffset = fieldOffset(t, field); - new (staticFields + staticIndex) Field - (type, buildStaticOffset, buildSize, targetStaticOffset, - targetSize); + init(new (staticFields + staticIndex) Field, type, + buildStaticOffset, buildSize, targetStaticOffset, + targetSize); targetStaticOffset += targetSize; @@ -524,9 +526,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildMemberOffset = fieldOffset(t, field); - new (memberFields + memberIndex) Field - (type, buildMemberOffset, buildSize, targetMemberOffset, - targetSize); + init(new (memberFields + memberIndex) Field, type, + buildMemberOffset, buildSize, targetMemberOffset, + targetSize); targetMemberOffset += targetSize; @@ -693,12 +695,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, return constants; } -unsigned -objectSize(Thread* t, object o) -{ - return baseSize(t, o, objectClass(t, o)); -} - void visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants) { @@ -1267,12 +1263,6 @@ updateConstants(Thread* t, object constants, HeapMap* heapTable) } } -unsigned -offset(object a, uintptr_t* b) -{ - return reinterpret_cast(b) - reinterpret_cast(a); -} - BootImage::Thunk targetThunk(BootImage::Thunk t) { @@ -1347,7 +1337,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp Field fields[count]; - new (fields) Field(Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (fields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); unsigned buildOffset = BytesPerWord; unsigned targetOffset = TargetBytesPerWord; @@ -1424,8 +1415,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp ++ targetOffset; } - new (fields + j) Field - (type, buildOffset, buildSize, targetOffset, targetSize); + init(new (fields + j) Field, type, buildOffset, buildSize, + targetOffset, targetSize); buildOffset += buildSize; targetOffset += targetSize; diff --git a/src/compile.cpp b/src/compile.cpp index 5e54cd8616..157f1fd24b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -288,14 +288,6 @@ transition(MyThread* t, void* ip, void* stack, object continuation, MyThread::doTransition(t, ip, stack, continuation, trace); } -unsigned -parameterOffset(MyThread* t, object method) -{ - return methodParameterFootprint(t, method) - + t->arch->frameFooterSize() - + t->arch->frameReturnAddressSize() - 1; -} - object resolveThisPointer(MyThread* t, void* stack) { diff --git a/src/compiler.cpp b/src/compiler.cpp index 56a2709e42..e3e24103c6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -579,27 +579,6 @@ cons(Context* c, void* value, Cell* next) return new (c->zone) Cell(next, value); } -Cell* -append(Context* c, Cell* first, Cell* second) -{ - if (first) { - if (second) { - Cell* start = cons(c, first->value, second); - Cell* end = start; - for (Cell* cell = first->next; cell; cell = cell->next) { - Cell* n = cons(c, cell->value, second); - end->next = n; - end = n; - } - return start; - } else { - return first; - } - } else { - return second; - } -} - Cell* reverseDestroy(Cell* cell) { @@ -992,25 +971,6 @@ valid(Read* r) return r and r->valid(); } -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; -} - Read* live(Context* c UNUSED, Value* v) { @@ -5302,16 +5262,17 @@ propagateJunctionSites(Context* c, Event* e) class SiteRecord { public: - SiteRecord(Site* site, Value* value): - site(site), value(value) - { } - - SiteRecord() { } - Site* site; Value* value; }; +void +init(SiteRecord* r, Site* s, Value* v) +{ + r->site = s; + r->value = v; +} + class SiteRecordList { public: SiteRecordList(SiteRecord* records, unsigned capacity): @@ -5329,7 +5290,7 @@ freeze(Context* c, SiteRecordList* frozen, Site* s, Value* v) assert(c, frozen->index < frozen->capacity); s->freeze(c, v); - new (frozen->records + (frozen->index ++)) SiteRecord(s, v); + init(new (frozen->records + (frozen->index ++)) SiteRecord, s, v); } void @@ -5866,17 +5827,6 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) c->firstBlock = firstBlock; } -unsigned -count(Stack* s) -{ - unsigned c = 0; - while (s) { - ++ c; - s = s->next; - } - return c; -} - void restore(Context* c, ForkState* state) { diff --git a/src/heap.cpp b/src/heap.cpp index b99de70de7..ed5d8777d4 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -60,7 +60,6 @@ void NO_RETURN abort(Context*); void assert(Context*, bool); #endif -System* system(Context*); void* tryAllocate(Context* c, unsigned size); void* allocate(Context* c, unsigned size); void free(Context* c, const void* p, unsigned size); @@ -689,12 +688,6 @@ class Context { int64_t totalTime; }; -inline System* -system(Context* c) -{ - return c->system; -} - const char* segment(Context* c, void* p) { diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index a34baf96dc..811382a825 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -231,16 +231,6 @@ get(object o, unsigned offsetInWords) (mask(cast(o, offsetInWords * BytesPerWord))); } -unsigned -objectSize(Thread* t, object o) -{ - unsigned n = baseSize(t, o, objectClass(t, o)); - if (objectExtended(t, o)) { - ++ n; - } - return n; -} - unsigned walk(Context* c, HeapVisitor* v, object p) { diff --git a/src/machine.cpp b/src/machine.cpp index 4c99de36de..53b6a0f66d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -35,14 +35,6 @@ atomicIncrement(uint32_t* p, int v) } #endif -bool -find(Thread* t, Thread* o) -{ - return (t == o) - or (t->peer and find(t->peer, o)) - or (t->child and find(t->child, o)); -} - void join(Thread* t, Thread* o) { @@ -56,28 +48,6 @@ join(Thread* t, Thread* o) } } -unsigned -count(Thread* t, Thread* o) -{ - unsigned c = 0; - - if (t != o) ++ c; - if (t->peer) c += count(t->peer, o); - if (t->child) c += count(t->child, o); - - return c; -} - -Thread** -fill(Thread* t, Thread* o, Thread** array) -{ - if (t != o) *(array++) = t; - if (t->peer) array = fill(t->peer, o, array); - if (t->child) array = fill(t->child, o, array); - - return array; -} - void dispose(Thread* t, Thread* o, bool remove) { diff --git a/src/type-generator.cpp b/src/type-generator.cpp index ca5bd37056..813cce7dcd 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -70,12 +70,6 @@ equal(const char* a, const char* b) return strcmp(a, b) == 0; } -inline bool -startsWith(const char* a, const char* b) -{ - return strncmp(a, b, strlen(a)) == 0; -} - inline bool endsWith(const char* a, const char* b) { @@ -284,14 +278,6 @@ setCdr(Object* o, Object* v) static_cast(o)->cdr = v; } -unsigned -length(Object* o) -{ - unsigned c = 0; - for (; o; o = cdr(o)) ++c; - return c; -} - class List { public: Object* first; @@ -1078,53 +1064,6 @@ parseSubdeclaration(Object* t, Object* p, Object* declarations) } } -bool -memberEqual(Object* a, Object* b) -{ - if (a->type == b->type) { - switch (a->type) { - case Object::Scalar: - return equal(memberTypeName(a), memberTypeName(b)) - and memberNoAssert(a) == memberNoAssert(b) - and memberNoGC(a) == memberNoGC(b); - - // todo: compare array fields - - default: return false; - } - } else { - return false; - } -} - -bool -specEqual(Object* a, Object* b) -{ - if (a->type == Object::Type and - b->type == Object::Type) - { - MemberIterator ai(a); - MemberIterator bi(b); - while (ai.hasMore()) { - if (not bi.hasMore()) { - return false; - } - - if (not memberEqual(ai.next(), bi.next())) { - return false; - } - } - - if (bi.hasMore()) { - return false; - } else { - return true; - } - } else { - return false; - } -} - const char* append(const char* a, const char* b, const char* c, const char* d) { @@ -1725,13 +1664,6 @@ writeConstructorInitializations(Output* out, Object* t) } } -unsigned -typeMemberCount(Object* o) -{ - if (o == 0) return 0; - return length(typeMembers(o)) + typeMemberCount(typeSuper(o)); -} - void writeInitializerDeclarations(Output* out, Object* declarations) { @@ -1888,17 +1820,6 @@ writeEnums(Output* out, Object* declarations) } } -unsigned -memberCount(Object* o) -{ - unsigned c = 0; - for (MemberIterator it(o); it.hasMore();) { - it.next(); - ++c; - } - return c; -} - unsigned methodCount(Object* o) { diff --git a/src/x86.cpp b/src/x86.cpp index 095a567c63..6875449953 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -198,44 +198,12 @@ assert(ArchitectureContext* c, bool v) } #endif // not NDEBUG -void -expect(Context* c, bool v) -{ - expect(c->s, v); -} - ResolvedPromise* resolved(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } -class CodePromise: public Promise { - public: - CodePromise(Context* c, unsigned offset): c(c), offset(offset) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast(c->result + offset); - } - - abort(c); - } - - virtual bool resolved() { - return c->result != 0; - } - - Context* c; - unsigned offset; -}; - -CodePromise* -codePromise(Context* c, unsigned offset) -{ - return new (c->zone) CodePromise(c, offset); -} - class Offset: public Promise { public: Offset(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit): @@ -629,14 +597,6 @@ opcode(Context* c, uint8_t op1, uint8_t op2) c->code.append(op2); } -void -opcode(Context* c, uint8_t op1, uint8_t op2, uint8_t op3) -{ - c->code.append(op1); - c->code.append(op2); - c->code.append(op3); -} - void return_(Context* c) { From bd7ef247345d153c18cabbb5d09d33e7c9c577a6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 1 Jun 2012 17:57:42 -0600 Subject: [PATCH 03/14] pass -std=c++11 to Clang for C++ code --- makefile | 2 +- src/compiler.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index b528fc2fb3..e8626126dd 100755 --- a/makefile +++ b/makefile @@ -139,7 +139,7 @@ endif input = List ifeq ($(use-clang),true) - build-cxx = clang + build-cxx = clang -std=c++11 build-cc = clang else build-cxx = g++ diff --git a/src/compiler.cpp b/src/compiler.cpp index e3e24103c6..812a38a9e9 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1578,7 +1578,7 @@ class ConstantSite: public Site { virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { if (value->resolved()) { return vm::snprintf - (buffer, bufferSize, "constant %"LLD, value->value()); + (buffer, bufferSize, "constant %" LLD, value->value()); } else { return vm::snprintf(buffer, bufferSize, "constant unresolved"); } @@ -1669,7 +1669,7 @@ class AddressSite: public Site { virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { if (address->resolved()) { return vm::snprintf - (buffer, bufferSize, "address %"LLD, address->value()); + (buffer, bufferSize, "address %" LLD, address->value()); } else { return vm::snprintf(buffer, bufferSize, "address unresolved"); } From 5d9f7b2bc33a2a10ef6e773b9b2584970b405585 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 09:06:22 -0600 Subject: [PATCH 04/14] add optional LZMA support for compressing embedded JARs, boot images, and shared objects --- makefile | 94 +++++++++++++++++--- readme.txt | 24 +++++- src/bootimage-fields.cpp | 2 + src/bootimage.cpp | 44 ++++++++-- src/compile.cpp | 8 +- src/compiler.cpp | 23 +++++ src/finder.cpp | 36 +++++++- src/lzma-decode.cpp | 49 +++++++++++ src/lzma-encode.cpp | 71 +++++++++++++++ src/lzma-util.h | 53 ++++++++++++ src/lzma.h | 29 +++++++ src/lzma/load.cpp | 115 +++++++++++++++++++++++++ src/lzma/main.cpp | 182 +++++++++++++++++++++++++++++++++++++++ src/machine.cpp | 62 ++++++++++++- src/machine.h | 2 + 15 files changed, 764 insertions(+), 30 deletions(-) create mode 100644 src/lzma-decode.cpp create mode 100644 src/lzma-encode.cpp create mode 100644 src/lzma-util.h create mode 100644 src/lzma.h create mode 100644 src/lzma/load.cpp create mode 100644 src/lzma/main.cpp diff --git a/makefile b/makefile index e8626126dd..b0af8f8ae8 100755 --- a/makefile +++ b/makefile @@ -33,6 +33,9 @@ endif ifneq ($(mode),fast) options := $(options)-$(mode) endif +ifneq ($(lzma),) + options := $(options)-lzma +endif ifeq ($(bootimage),true) options := $(options)-bootimage endif @@ -532,6 +535,7 @@ ifdef msvc strip = : endif +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))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) @@ -594,7 +598,10 @@ ifeq ($(continuations),true) asmflags += -DAVIAN_CONTINUATIONS endif -bootimage-generator-sources = $(src)/bootimage.cpp +bootimage-generator-sources = $(src)/bootimage.cpp +ifneq ($(lzma),) + bootimage-generator-sources += $(src)/lzma-encode.cpp +endif bootimage-generator-objects = \ $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build)) bootimage-generator = $(build)/bootimage-generator @@ -629,17 +636,62 @@ generator-sources = \ $(src)/type-generator.cpp \ $(src)/$(build-system).cpp \ $(src)/finder.cpp + +ifneq ($(lzma),) + common-cflags += -I$(lzma)/C -DAVIAN_USE_LZMA -D_7ZIP_ST + + vm-sources += \ + $(src)/lzma-decode.cpp + + generator-sources += \ + $(src)/lzma-decode.cpp + + lzma-decode-sources = \ + $(lzma)/C/LzmaDec.c + + lzma-decode-objects = \ + $(call c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) + + lzma-encode-sources = \ + $(lzma)/C/LzmaEnc.c \ + $(lzma)/C/LzFind.c + + lzma-encode-objects = \ + $(call c-objects,$(lzma-encode-sources),$(lzma)/C,$(build)) + + lzma-encoder = $(build)/lzma/lzma + + lzma-encoder-cflags = -D__STDC_CONSTANT_MACROS -fno-rtti -fno-exceptions \ + -I$(lzma)/C + + lzma-encoder-sources = \ + $(src)/lzma/main.cpp + + lzma-encoder-objects = \ + $(call cpp-objects,$(lzma-encoder-sources),$(src),$(build)) + + lzma-encoder-lzma-sources = $(lzma-encode-sources) $(lzma-decode-sources) + + lzma-encoder-lzma-objects = \ + $(call c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) + + lzma-loader = $(build)/lzma/load.o +endif + generator-cpp-objects = \ $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%-build.o,$(x))) +generator-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-build.o,$(x))) generator-objects = \ $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) +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 - converter-sources = \ $(src)/binaryToObject/tools.cpp \ $(src)/binaryToObject/elf.cpp \ @@ -760,7 +812,7 @@ test-flags = -cp $(build)/test test-args = $(test-flags) $(input) .PHONY: build -build: $(static-library) $(executable) $(dynamic-library) \ +build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ $(executable-dynamic) $(classpath-dep) $(test-dep) $(test-extra-dep) $(test-dep): $(classpath-dep) @@ -863,6 +915,9 @@ endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(compile-object) +$(build)/%.o: $(lzma)/C/%.c + $(compile-object) + $(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S $(compile-asm-object) @@ -894,6 +949,16 @@ $(converter-objects) $(converter-tool-objects): $(build)/binaryToObject/%.o: $(s $(converter): $(converter-objects) $(converter-tool-objects) $(build-cc) $(^) -g -o $(@) +$(lzma-encoder-objects): $(build)/lzma/%.o: $(src)/lzma/%.cpp + @mkdir -p $(dir $(@)) + $(build-cxx) $(lzma-encoder-cflags) -c $(<) -o $(@) + +$(lzma-encoder): $(lzma-encoder-objects) $(lzma-encoder-lzma-objects) + $(build-cc) $(^) -g -o $(@) + +$(lzma-loader): $(src)/lzma/load.cpp + $(compile-object) + $(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) @echo "creating $(@)" (wd=$$(pwd) && \ @@ -916,18 +981,25 @@ $(javahome-object): $(build)/javahome.jar $(converter) $(converter) $(<) $(@) _binary_javahome_jar_start \ _binary_javahome_jar_end $(platform) $(arch) -$(generator-objects): $(generator-depends) -$(generator-objects): $(build)/%-build.o: $(src)/%.cpp +define compile-generator-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ -c $(<) -o $(@) +endef + +$(generator-objects): $(generator-depends) +$(generator-objects): $(build)/%-build.o: $(src)/%.cpp + $(compile-generator-object) + +$(generator-lzma-objects): $(build)/%-build.o: $(lzma)/C/%.c + $(compile-generator-object) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(compile-object) $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ - $(javahome-object) $(boot-javahome-object) + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) @echo "creating $(@)" rm -rf $(@) $(ar) cru $(@) $(^) @@ -940,7 +1012,7 @@ $(bootimage-object) $(codeimage-object): $(bootimage-generator) executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ - $(javahome-object) $(boot-javahome-object) + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) $(executable): $(executable-objects) @echo "linking $(@)" @@ -976,7 +1048,8 @@ $(bootimage-generator): $(bootimage-generator-objects) $(build-bootimage-generator): \ $(vm-objects) $(classpath-object) $(classpath-objects) \ - $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) + $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) \ + $(lzma-decode-objects) $(lzma-encode-objects) @echo "linking $(@)" ifeq ($(platform),windows) ifdef msvc @@ -994,7 +1067,8 @@ endif $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ - $(classpath-libraries) $(javahome-object) $(boot-javahome-object) + $(classpath-libraries) $(javahome-object) $(boot-javahome-object) \ + $(lzma-decode-objects) @echo "linking $(@)" ifdef msvc $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ @@ -1020,7 +1094,7 @@ else endif $(strip) $(strip-all) $(@) -$(generator): $(generator-objects) +$(generator): $(generator-objects) $(generator-lzma-objects) @echo "linking $(@)" $(build-ld) $(^) $(build-lflags) -o $(@) diff --git a/readme.txt b/readme.txt index ac54ca700f..ca43b1fa9e 100644 --- a/readme.txt +++ b/readme.txt @@ -79,6 +79,7 @@ certain flags described below, all of which are optional. 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} \ @@ -104,6 +105,13 @@ certain flags described below, all of which are optional. 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 + * 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 @@ -366,8 +374,20 @@ EOF Step 3: Make an object file out of the jar. - $ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar boot-jar.o \ - _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch} + $ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \ + boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch} + +If you've built Avian using the lzma option, you may optionally +compress the jar before generating the object: + + $ ../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma + && ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \ + boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \ + ${platform} ${arch} + +Note that you'll need to specify "-Xbootclasspath:[lzma:bootJar]" +instead of "-Xbootclasspath:[bootJar]" in the next step if you've used +LZMA to compress the jar. Step 4: Write a driver which starts the VM and runs the desired main method. Note the bootJar function, which will be called by the VM to diff --git a/src/bootimage-fields.cpp b/src/bootimage-fields.cpp index 7638830585..a090268de2 100644 --- a/src/bootimage-fields.cpp +++ b/src/bootimage-fields.cpp @@ -5,6 +5,8 @@ FIELD(magic) +FIELD(initialized) + FIELD(heapSize) FIELD(codeSize) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index a4555a9f6e..2affc13f6f 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -17,6 +17,7 @@ #include "assembler.h" #include "target.h" #include "binaryToObject/tools.h" +#include "lzma.h" // since we aren't linking against libstdc++, we must implement this // ourselves: @@ -1275,7 +1276,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp BootImage* image, uint8_t* code, const char* className, const char* methodName, const char* methodSpec, const char* bootimageStart, const char* bootimageEnd, - const char* codeimageStart, const char* codeimageEnd) + const char* codeimageStart, const char* codeimageEnd, + bool useLZMA) { setRoot(t, Machine::OutOfMemoryError, make(t, type(t, Machine::OutOfMemoryErrorType))); @@ -1594,6 +1596,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp heapWalker->dispose(); image->magic = BootImage::Magic; + image->initialized = 0; fprintf(stderr, "class count %d string count %d call count %d\n" "heap size %d code size %d\n", @@ -1656,7 +1659,27 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp SymbolInfo(bootimageData.length, bootimageEnd) }; - platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord); + uint8_t* bootimage; + unsigned bootimageLength; + if (useLZMA) { +#ifdef AVIAN_USE_LZMA + bootimage = encodeLZMA(t->m->system, t->m->heap, bootimageData.data, + bootimageData.length, &bootimageLength); + + fprintf(stderr, "compressed heap size %d\n", bootimageLength); +#else + abort(t); +#endif + } else { + bootimage = bootimageData.data; + bootimageLength = bootimageData.length; + } + + platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimage, bootimageLength), Platform::Writable, TargetBytesPerWord); + + if (useLZMA) { + t->m->heap->free(bootimage, bootimageLength); + } compilationHandler.symbols.add(SymbolInfo(0, codeimageStart)); compilationHandler.symbols.add(SymbolInfo(image->codeSize, codeimageEnd)); @@ -1684,10 +1707,12 @@ writeBootImage(Thread* t, uintptr_t* arguments) const char* bootimageEnd = reinterpret_cast(arguments[8]); const char* codeimageStart = reinterpret_cast(arguments[9]); const char* codeimageEnd = reinterpret_cast(arguments[10]); + bool useLZMA = arguments[11]; writeBootImage2 (t, bootimageOutput, codeOutput, image, code, className, methodName, - methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd); + methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd, + useLZMA); return 1; } @@ -1746,7 +1771,11 @@ bool ArgParser::parse(int ac, const char** av) { } for(Arg* arg = first; arg; arg = arg->next) { if(strcmp(arg->name, &av[i][1]) == 0) { - state = arg; + if (arg->desc == 0) { + arg->value = "true"; + } else { + state = arg; + } } } if(!state) { @@ -1801,6 +1830,8 @@ public: char* codeimageStart; char* codeimageEnd; + bool useLZMA; + bool maybeSplit(const char* src, char*& destA, char*& destB) { if(src) { const char* split = strchr(src, ':'); @@ -1830,6 +1861,7 @@ public: Arg entry(parser, false, "entry", "[.[]]"); Arg bootimageSymbols(parser, false, "bootimage-symbols", ":"); Arg codeimageSymbols(parser, false, "codeimage-symbols", ":"); + Arg useLZMA(parser, false, "use-lzma", 0); if(!parser.parse(ac, av)) { parser.printUsage(av[0]); @@ -1839,6 +1871,7 @@ public: this->classpath = classpath.value; this->bootimage = bootimage.value; this->codeimage = codeimage.value; + this->useLZMA = useLZMA.value != 0; if(entry.value) { if(const char* entryClassEnd = strchr(entry.value, '.')) { @@ -1988,7 +2021,8 @@ main(int ac, const char** av) reinterpret_cast(args.bootimageStart), reinterpret_cast(args.bootimageEnd), reinterpret_cast(args.codeimageStart), - reinterpret_cast(args.codeimageEnd) + reinterpret_cast(args.codeimageEnd), + reinterpret_cast(args.useLZMA) }; run(t, writeBootImage, arguments); diff --git a/src/compile.cpp b/src/compile.cpp index 157f1fd24b..86edcb033e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -9631,9 +9631,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) // fprintf(stderr, "code from %p to %p\n", // code, code + image->codeSize); - static bool fixed = false; - - if (not fixed) { + if (not image->initialized) { fixupHeap(t, heapMap, heapMapSizeInWords, heap); } @@ -9680,7 +9678,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) findThunks(t, image, code); - if (fixed) { + if (image->initialized) { resetRuntimeState (t, classLoaderMap(t, root(t, Machine::BootLoader)), heap, image->heapSize); @@ -9703,7 +9701,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) (t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code); } - fixed = true; + image->initialized = true; setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0)); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 812a38a9e9..213c6e81ae 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -971,6 +971,29 @@ 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) { diff --git a/src/finder.cpp b/src/finder.cpp index 1a08e65008..ba8aef75f4 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -12,6 +12,7 @@ #include "system.h" #include "tokenizer.h" #include "finder.h" +#include "lzma.h" using namespace vm; @@ -173,11 +174,12 @@ class DirectoryElement: public Element { class PointerRegion: public System::Region { public: PointerRegion(System* s, Allocator* allocator, const uint8_t* start, - size_t length): + size_t length, bool freePointer = false): s(s), allocator(allocator), start_(start), - length_(length) + length_(length), + freePointer(freePointer) { } virtual const uint8_t* start() { @@ -189,6 +191,9 @@ class PointerRegion: public System::Region { } virtual void dispose() { + if (freePointer) { + allocator->free(start_, length_); + } allocator->free(this, sizeof(*this)); } @@ -196,6 +201,7 @@ class PointerRegion: public System::Region { Allocator* allocator; const uint8_t* start_; size_t length_; + bool freePointer; }; class DataRegion: public System::Region { @@ -556,7 +562,10 @@ class BuiltinElement: public JarElement { virtual void init() { if (index == 0) { if (s->success(s->load(&library, libraryName))) { - void* p = library->resolve(name); + bool lzma = strncmp("lzma:", name, 5) == 0; + const char* symbolName = lzma ? name + 5 : name; + + void* p = library->resolve(symbolName); if (p) { uint8_t* (*function)(unsigned*); memcpy(&function, &p, BytesPerWord); @@ -564,10 +573,29 @@ class BuiltinElement: public JarElement { unsigned size; uint8_t* data = function(&size); if (data) { + bool freePointer; + if (lzma) { +#ifdef AVIAN_USE_LZMA + unsigned outSize; + data = decodeLZMA(s, allocator, data, size, &outSize); + size = outSize; + freePointer = true; +#else + abort(s); +#endif + } else { + freePointer = false; + } region = new (allocator->allocate(sizeof(PointerRegion))) - PointerRegion(s, allocator, data, size); + PointerRegion(s, allocator, data, size, freePointer); index = JarIndex::open(s, allocator, region); + } else if (DebugFind) { + fprintf(stderr, "%s in %s returned null\n", symbolName, + libraryName); } + } else if (DebugFind) { + fprintf(stderr, "unable to find %s in %s\n", symbolName, + libraryName); } } } diff --git a/src/lzma-decode.cpp b/src/lzma-decode.cpp new file mode 100644 index 0000000000..7710934ddd --- /dev/null +++ b/src/lzma-decode.cpp @@ -0,0 +1,49 @@ +/* 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. */ + +#include "lzma-util.h" +#include "LzmaDec.h" + +using namespace vm; + +namespace vm { + +uint8_t* +decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + int32_t outSize32; + memcpy(&outSize32, in + PropHeaderSize, 4); + expect(s, outSize32 >= 0); + SizeT outSizeT = outSize32; + + uint8_t* out = static_cast(a->allocate(outSize32)); + + SizeT inSizeT = inSize; + LzmaAllocator allocator(a); + + ELzmaStatus status; + int result = LzmaDecode + (out, &outSizeT, in + HeaderSize, &inSizeT, in, PropHeaderSize, + LZMA_FINISH_END, &status, &(allocator.allocator)); + + expect(s, result == SZ_OK); + expect(s, status == LZMA_STATUS_FINISHED_WITH_MARK); + + *outSize = outSize32; + + return out; +} + +} // namespace vm + diff --git a/src/lzma-encode.cpp b/src/lzma-encode.cpp new file mode 100644 index 0000000000..d1b002476a --- /dev/null +++ b/src/lzma-encode.cpp @@ -0,0 +1,71 @@ +/* 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. */ + +#include "lzma-util.h" +#include "LzmaEnc.h" + +using namespace vm; + +namespace { + +SRes +myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +} // namespace + +namespace vm { + +uint8_t* +encodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + unsigned bufferSize = inSize * 2; + + uint8_t* buffer = static_cast(a->allocate(bufferSize)); + + LzmaAllocator allocator(a); + + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = { myProgress }; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(buffer + PropHeaderSize, &inSize32, 4); + + SizeT outSizeT = bufferSize; + int result = LzmaEncode + (buffer + HeaderSize, &outSizeT, in, inSize, &props, buffer, + &propsSize, 1, &progress, &(allocator.allocator), &(allocator.allocator)); + + expect(s, result == SZ_OK); + + *outSize = outSizeT + HeaderSize; + + uint8_t* out = static_cast(a->allocate(*outSize)); + memcpy(out, buffer, *outSize); + + a->free(buffer, bufferSize); + + return out; +} + +} // namespace vm + diff --git a/src/lzma-util.h b/src/lzma-util.h new file mode 100644 index 0000000000..105a9e4077 --- /dev/null +++ b/src/lzma-util.h @@ -0,0 +1,53 @@ +/* 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. */ + +#ifndef LZMA_UTIL_H +#define LZMA_UTIL_H + +#include "lzma.h" +#include "Types.h" +#include "system.h" +#include "allocator.h" + +namespace vm { + +const unsigned Padding = 16; + +class LzmaAllocator { + public: + LzmaAllocator(Allocator* a): a(a) { + allocator.Alloc = allocate; + allocator.Free = free; + } + + ISzAlloc allocator; + Allocator* a; + + static void* allocate(void* allocator, size_t size) { + uint8_t* p = static_cast + (static_cast(allocator)->a->allocate(size + Padding)); + int32_t size32 = size; + memcpy(p, &size32, 4); + return p + Padding; + } + + static void free(void* allocator, void* address) { + if (address) { + void* p = static_cast(address) - Padding; + int32_t size32; + memcpy(&size32, p, 4); + static_cast(allocator)->a->free(p, size32 + Padding); + } + } +}; + +} // namespace vm + +#endif // LZMA_UTIL_H diff --git a/src/lzma.h b/src/lzma.h new file mode 100644 index 0000000000..5e6ba35a82 --- /dev/null +++ b/src/lzma.h @@ -0,0 +1,29 @@ +/* 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. */ + +#ifndef LZMA_H +#define LZMA_H + +#include "system.h" +#include "allocator.h" + +namespace vm { + +uint8_t* +decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize); + +uint8_t* +encodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize); + +} // namespace vm + +#endif // LZMA_H diff --git a/src/lzma/load.cpp b/src/lzma/load.cpp new file mode 100644 index 0000000000..f4fc57965c --- /dev/null +++ b/src/lzma/load.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LzmaDec.h" + +#ifdef __MINGW32__ +# define EXPORT __declspec(dllexport) +#else +# define EXPORT __attribute__ ((visibility("default"))) +#endif + +#if defined __MINGW32__ && ! defined __x86_64__ +# define SYMBOL(x) binary_exe_##x +#else +# define SYMBOL(x) _binary_exe_##x +#endif + +extern "C" { + + extern const uint8_t SYMBOL(start)[]; + extern const uint8_t SYMBOL(end)[]; + +} // extern "C" + +namespace { + +void* +myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void +myFree(void*, void* address) +{ + free(address); +} + +} // namespace + +int +main(int ac, const char** av) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT inSize = SYMBOL(end) - SYMBOL(start); + + int32_t outSize32; + memcpy(&outSize32, SYMBOL(start) + PropHeaderSize, 4); + SizeT outSize = outSize32; + + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + ISzAlloc allocator = { myAllocate, myFree }; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + + if (SZ_OK == LzmaDecode + (out, &outSize, SYMBOL(start) + HeaderSize, &inSize, SYMBOL(start), + PropHeaderSize, LZMA_FINISH_END, &status, &allocator)) + { + char name[L_tmpnam]; + if (tmpnam(name)) { + int file = open(name, O_CREAT | O_EXCL | O_WRONLY, S_IRWXU); + if (file != -1) { + SizeT result = write(file, out, outSize); + free(out); + + if (close(file) == 0 and outSize == result) { + void* library = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); + unlink(name); + + if (library) { + void* main = dlsym(library, "main"); + if (main) { + int (*mainFunction)(int, const char**); + memcpy(&mainFunction, &main, sizeof(void*)); + return mainFunction(ac, av); + } else { + fprintf(stderr, "unable to find main in %s", name); + } + } else { + fprintf(stderr, "unable to dlopen %s: %s\n", name, dlerror()); + } + } else { + unlink(name); + + fprintf(stderr, "close or write failed; tried %d, got %d; %s\n", + static_cast(outSize), static_cast(result), + strerror(errno)); + } + } else { + fprintf(stderr, "unable to open %s\n", name); + } + } else { + fprintf(stderr, "unable to make temporary file name\n"); + } + } else { + fprintf(stderr, "unable to decode LZMA data\n"); + } + } else { + fprintf(stderr, "unable to allocate buffer of size %d\n", + static_cast(outSize)); + } + + return -1; +} diff --git a/src/lzma/main.cpp b/src/lzma/main.cpp new file mode 100644 index 0000000000..a9a558d897 --- /dev/null +++ b/src/lzma/main.cpp @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#include +#endif +#include + +#include "LzmaEnc.h" +#include "LzmaDec.h" + +namespace { + +void* +myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void +myFree(void*, void* address) +{ + free(address); +} + +SRes +myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +void +usageAndExit(const char* program) +{ + fprintf(stderr, + "usage: %s {encode|decode} " + "[]", program); + exit(-1); +} + +} // namespace + +int +main(int argc, const char** argv) +{ + if (argc < 4 or argc > 5) { + usageAndExit(argv[0]); + } + + bool encode = strcmp(argv[1], "encode") == 0; + + uint8_t* data = 0; + unsigned size; + int fd = open(argv[2], O_RDONLY); + if (fd != -1) { + struct stat s; + int r = fstat(fd, &s); + if (r != -1) { +#ifdef WIN32 + HANDLE fm; + HANDLE h = (HANDLE) _get_osfhandle (fd); + + fm = CreateFileMapping( + h, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + data = static_cast(MapViewOfFile( + fm, + FILE_MAP_READ, + 0, + 0, + s.st_size)); + + CloseHandle(fm); +#else + data = static_cast + (mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); +#endif + size = s.st_size; + } + close(fd); + } + + bool success = false; + + if (data) { + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT outSize; + if (encode) { + outSize = size * 2; + } else { + int32_t outSize32; + memcpy(&outSize32, data + PropHeaderSize, 4); + if (outSize32 >= 0) { + outSize = outSize32; + } else if (argc == 5) { + outSize = atoi(argv[4]); + } else { + outSize = -1; + } + } + + if (outSize >= 0) { + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + SizeT inSize = size; + ISzAlloc allocator = { myAllocate, myFree }; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + int result; + if (encode) { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = { myProgress }; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(out + PropHeaderSize, &inSize32, 4); + + result = LzmaEncode + (out + HeaderSize, &outSize, data, inSize, &props, out, + &propsSize, 1, &progress, &allocator, &allocator); + + outSize += HeaderSize; + } else { + result = LzmaDecode + (out, &outSize, data + HeaderSize, &inSize, data, PropHeaderSize, + LZMA_FINISH_END, &status, &allocator); + } + + if (result == SZ_OK) { + FILE* outFile = fopen(argv[3], "wb"); + + if (outFile) { + if (fwrite(out, outSize, 1, outFile) == 1) { + success = true; + } else { + fprintf(stderr, "unable to write to %s\n", argv[3]); + } + + fclose(outFile); + } else { + fprintf(stderr, "unable to open %s\n", argv[3]); + } + } else { + fprintf(stderr, "unable to %s data: result %d status %d\n", + encode ? "encode" : "decode", result, status); + } + + free(out); + } else { + fprintf(stderr, "unable to allocate output buffer\n"); + } + } else { + fprintf(stderr, "unable to determine uncompressed size\n"); + } + +#ifdef WIN32 + UnmapViewOfFile(data); +#else + munmap(data, size); +#endif + } else { + perror(argv[0]); + } + + return (success ? 0 : -1); +} diff --git a/src/machine.cpp b/src/machine.cpp index 53b6a0f66d..6e242dd8b8 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -15,6 +15,7 @@ #include "constants.h" #include "processor.h" #include "arch.h" +#include "lzma.h" using namespace vm; @@ -48,6 +49,40 @@ join(Thread* t, Thread* o) } } +#ifndef NDEBUG + +bool +find(Thread* t, Thread* o) +{ + return (t == o) + or (t->peer and find(t->peer, o)) + or (t->child and find(t->child, o)); +} + +unsigned +count(Thread* t, Thread* o) +{ + unsigned c = 0; + + if (t != o) ++ c; + if (t->peer) c += count(t->peer, o); + if (t->child) c += count(t->child, o); + + return c; +} + +Thread** +fill(Thread* t, Thread* o, Thread** array) +{ + if (t != o) *(array++) = t; + if (t->peer) array = fill(t->peer, o, array); + if (t->child) array = fill(t->child, o, array); + + return array; +} + +#endif // not NDEBUG + void dispose(Thread* t, Thread* o, bool remove) { @@ -203,8 +238,8 @@ turnOffTheLights(Thread* t) Finder* af = m->appFinder; c->dispose(); - m->dispose(); h->disposeFixies(); + m->dispose(); p->dispose(); bf->dispose(); af->dispose(); @@ -2945,6 +2980,10 @@ Machine::dispose() heap->free(heapPool[i], ThreadHeapSizeInBytes); } + if (bootimage) { + heap->free(bootimage, bootimageSize); + } + heap->free(arguments, sizeof(const char*) * argumentCount); heap->free(properties, sizeof(const char*) * propertyCount); @@ -3000,13 +3039,28 @@ Thread::init() uint8_t* code = 0; const char* imageFunctionName = findProperty(m, "avian.bootimage"); if (imageFunctionName) { - void* imagep = m->libraries->resolve(imageFunctionName); + bool lzma = strncmp("lzma:", imageFunctionName, 5) == 0; + const char* symbolName + = lzma ? imageFunctionName + 5 : imageFunctionName; + + void* imagep = m->libraries->resolve(symbolName); if (imagep) { - BootImage* (*imageFunction)(unsigned*); + uint8_t* (*imageFunction)(unsigned*); memcpy(&imageFunction, &imagep, BytesPerWord); unsigned size; - image = imageFunction(&size); + uint8_t* imageBytes = imageFunction(&size); + if (lzma) { +#ifdef AVIAN_USE_LZMA + m->bootimage = image = reinterpret_cast + (decodeLZMA + (m->system, m->heap, imageBytes, size, &(m->bootimageSize))); +#else + abort(this); +#endif + } else { + image = reinterpret_cast(imageBytes); + } const char* codeFunctionName = findProperty(m, "avian.codeimage"); if (codeFunctionName) { diff --git a/src/machine.h b/src/machine.h index 05bc01b1e6..bb3b97a43c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1316,6 +1316,7 @@ class Machine { System::Monitor* shutdownLock; System::Library* libraries; FILE* errorLog; + BootImage* bootimage; object types; object roots; object finalizers; @@ -1332,6 +1333,7 @@ class Machine { JNIEnvVTable jniEnvVTable; uintptr_t* heapPool[ThreadHeapPoolSize]; unsigned heapPoolIndex; + unsigned bootimageSize; }; void From f07a8c7ec48ef494354eb8590c943d899b242223 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 13:23:52 -0600 Subject: [PATCH 05/14] make LZMA encoder by default --- makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index b0af8f8ae8..8ec37fdd50 100755 --- a/makefile +++ b/makefile @@ -813,7 +813,8 @@ test-args = $(test-flags) $(input) .PHONY: build build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ - $(executable-dynamic) $(classpath-dep) $(test-dep) $(test-extra-dep) + $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(test-dep): $(classpath-dep) From d61501453f4cf948ba7981d743fbb6282899dbc5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 15:43:42 -0600 Subject: [PATCH 06/14] add support for LZMA on Windows --- makefile | 20 ++++++--- src/compile.cpp | 2 +- src/lzma-decode.cpp | 2 +- src/lzma-encode.cpp | 2 +- src/lzma-util.h | 2 +- src/lzma/load.cpp | 104 ++++++++++++++++++++++++++++++++++++++------ src/machine.cpp | 1 + 7 files changed, 109 insertions(+), 24 deletions(-) diff --git a/makefile b/makefile index 8ec37fdd50..de21c012b8 100755 --- a/makefile +++ b/makefile @@ -71,6 +71,8 @@ ifeq ($(build-platform),cygwin) native-path = cygpath -m endif +windows-path = echo + path-separator = : ifneq (,$(filter mingw32 cygwin,$(build-platform))) @@ -500,8 +502,9 @@ ld := $(cc) build-ld := $(build-cc) ifdef msvc - windows-java-home := $(shell cygpath -m "$(JAVA_HOME)") - zlib := $(shell cygpath -m "$(win32)/msvc") + 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" @@ -512,6 +515,11 @@ ifdef msvc -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(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 -MANIFEST -debug @@ -638,7 +646,7 @@ generator-sources = \ $(src)/finder.cpp ifneq ($(lzma),) - common-cflags += -I$(lzma)/C -DAVIAN_USE_LZMA -D_7ZIP_ST + common-cflags += -I$(lzma) -DAVIAN_USE_LZMA -D_7ZIP_ST vm-sources += \ $(src)/lzma-decode.cpp @@ -673,7 +681,7 @@ ifneq ($(lzma),) lzma-encoder-lzma-sources = $(lzma-encode-sources) $(lzma-decode-sources) lzma-encoder-lzma-objects = \ - $(call c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) + $(call generator-c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) lzma-loader = $(build)/lzma/load.o endif @@ -904,7 +912,7 @@ $(test-extra-dep): $(test-extra-sources) define compile-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) $(cflags) -c $(<) $(call output,$(@)) + $(cxx) $(cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) endef define compile-asm-object @@ -993,7 +1001,7 @@ $(generator-objects): $(generator-depends) $(generator-objects): $(build)/%-build.o: $(src)/%.cpp $(compile-generator-object) -$(generator-lzma-objects): $(build)/%-build.o: $(lzma)/C/%.c +$(build)/%-build.o: $(lzma)/C/%.c $(compile-generator-object) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp diff --git a/src/compile.cpp b/src/compile.cpp index 86edcb033e..ce67081480 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -10022,7 +10022,7 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size) sprintf(RUNTIME_ARRAY_BODY(virtualThunkName), "%s%d", virtualThunkBaseName, index); - logCompile(t, start, *size, 0, virtualThunkName, 0); + logCompile(t, start, *size, 0, RUNTIME_ARRAY_BODY(virtualThunkName), 0); return reinterpret_cast(start); } diff --git a/src/lzma-decode.cpp b/src/lzma-decode.cpp index 7710934ddd..f51b86af83 100644 --- a/src/lzma-decode.cpp +++ b/src/lzma-decode.cpp @@ -9,7 +9,7 @@ details. */ #include "lzma-util.h" -#include "LzmaDec.h" +#include "C/LzmaDec.h" using namespace vm; diff --git a/src/lzma-encode.cpp b/src/lzma-encode.cpp index d1b002476a..cc7f8ad178 100644 --- a/src/lzma-encode.cpp +++ b/src/lzma-encode.cpp @@ -9,7 +9,7 @@ details. */ #include "lzma-util.h" -#include "LzmaEnc.h" +#include "C/LzmaEnc.h" using namespace vm; diff --git a/src/lzma-util.h b/src/lzma-util.h index 105a9e4077..e7fc3093a0 100644 --- a/src/lzma-util.h +++ b/src/lzma-util.h @@ -12,7 +12,7 @@ #define LZMA_UTIL_H #include "lzma.h" -#include "Types.h" +#include "C/Types.h" #include "system.h" #include "allocator.h" diff --git a/src/lzma/load.cpp b/src/lzma/load.cpp index f4fc57965c..3584c50e6a 100644 --- a/src/lzma/load.cpp +++ b/src/lzma/load.cpp @@ -2,22 +2,31 @@ #include #include #include -#include -#include #include #include #include -#include -#include "LzmaDec.h" +#include "C/LzmaDec.h" -#ifdef __MINGW32__ +#if (defined __MINGW32__) || (defined _MSC_VER) # define EXPORT __declspec(dllexport) +# include +# define open _open +# define write _write +# define close _close +# ifdef _MSC_VER +# define S_IRWXU (_S_IREAD | _S_IWRITE) +# define and && +# endif #else # define EXPORT __attribute__ ((visibility("default"))) +# include +# include +# include +# define O_BINARY 0 #endif -#if defined __MINGW32__ && ! defined __x86_64__ +#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) # define SYMBOL(x) binary_exe_##x #else # define SYMBOL(x) _binary_exe_##x @@ -44,6 +53,70 @@ myFree(void*, void* address) free(address); } +#if (defined __MINGW32__) || (defined _MSC_VER) + +void* +openLibrary(const char* name) +{ + return LoadLibrary(name); +} + +void* +librarySymbol(void* library, const char* name) +{ + void* address; + FARPROC p = GetProcAddress(static_cast(library), name); + memcpy(&address, &p, sizeof(void*)); + return address; +} + +const char* +libraryError(void*) +{ + return "unknown error"; +} + +const char* +temporaryFileName(char* buffer, unsigned size) +{ + unsigned c = GetTempPathA(size, buffer); + if (c) { + if (GetTempFileNameA(buffer, "223", 0, buffer + c)) { + DeleteFileA(buffer + c); + return buffer + c; + } + } + return 0; +} + +#else + +void* +openLibrary(const char* name) +{ + return dlopen(name, RTLD_LAZY | RTLD_LOCAL); +} + +void* +librarySymbol(void* library, const char* name) +{ + return dlsym(library, name); +} + +const char* +libraryError(void*) +{ + return dlerror(); +} + +const char* +temporaryFileName(char* buffer, unsigned) +{ + return tmpnam(buffer); +} + +#endif + } // namespace int @@ -67,28 +140,31 @@ main(int ac, const char** av) (out, &outSize, SYMBOL(start) + HeaderSize, &inSize, SYMBOL(start), PropHeaderSize, LZMA_FINISH_END, &status, &allocator)) { - char name[L_tmpnam]; - if (tmpnam(name)) { - int file = open(name, O_CREAT | O_EXCL | O_WRONLY, S_IRWXU); + const unsigned BufferSize = 1024; + char buffer[BufferSize]; + const char* name = temporaryFileName(buffer, BufferSize); + if (name) { + int file = open(name, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, S_IRWXU); if (file != -1) { SizeT result = write(file, out, outSize); free(out); if (close(file) == 0 and outSize == result) { - void* library = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); + void* library = openLibrary(name); unlink(name); if (library) { - void* main = dlsym(library, "main"); + void* main = librarySymbol(library, "avianMain"); if (main) { - int (*mainFunction)(int, const char**); + int (*mainFunction)(const char*, int, const char**); memcpy(&mainFunction, &main, sizeof(void*)); - return mainFunction(ac, av); + return mainFunction(name, ac, av); } else { fprintf(stderr, "unable to find main in %s", name); } } else { - fprintf(stderr, "unable to dlopen %s: %s\n", name, dlerror()); + fprintf(stderr, "unable to load %s: %s\n", name, + libraryError(library)); } } else { unlink(name); diff --git a/src/machine.cpp b/src/machine.cpp index 6e242dd8b8..67f70196fe 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2925,6 +2925,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, shutdownLock(0), libraries(0), errorLog(0), + bootimage(0), types(0), roots(0), finalizers(0), From 9520b03333764c57ebc8c99ecfb38162089d77cb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 18:56:07 -0600 Subject: [PATCH 07/14] fix OS X build regressions --- makefile | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/makefile b/makefile index de21c012b8..128ce5ffb5 100755 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ MAKEFLAGS = -s name = avian -version = 0.5 +version = 0.6 build-arch := $(shell uname -m \ | sed 's/^i.86$$/i386/' \ @@ -206,7 +206,7 @@ converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject -Isrc/ \ -fno-rtti -fno-exceptions \ -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN \ - -Wall -Wextra -Werror -Wunused-parameter -Winit-self + -Wall -Wextra -Werror -Wunused-parameter -Winit-self -Wno-non-virtual-dtor cflags = $(build-cflags) @@ -457,7 +457,11 @@ ifeq ($(mode),stress-major) strip = : endif ifeq ($(mode),fast) - optimization-cflags = -O4 -g3 -DNDEBUG + ifeq ($(use-clang),true) + optimization-cflags = -O4 -g3 -DNDEBUG + else + optimization-cflags = -O3 -g3 -DNDEBUG + endif use-lto = true endif ifeq ($(mode),small) @@ -925,7 +929,9 @@ $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(compile-object) $(build)/%.o: $(lzma)/C/%.c - $(compile-object) + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -Wno-error -c $$($(windows-path) $(<)) $(call output,$(@)) $(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S $(compile-asm-object) @@ -1002,7 +1008,10 @@ $(generator-objects): $(build)/%-build.o: $(src)/%.cpp $(compile-generator-object) $(build)/%-build.o: $(lzma)/C/%.c - $(compile-generator-object) + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ + -Wno-error -c $(<) -o $(@) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(compile-object) From 84034c00a84b1f54caacee3fe962bd3f6441435c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 18:56:15 -0600 Subject: [PATCH 08/14] use GitHub URL for hello-ios.git link --- readme.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index ca43b1fa9e..e9185b2c85 100644 --- a/readme.txt +++ b/readme.txt @@ -115,8 +115,8 @@ certain flags described below, all of which are optional. * 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 git://oss.readytalk.com/hello-ios.git for an example - of an Xcode project for iOS which uses Avian. + devices. See 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 From 9ea6a283830ae8b6cf0099376971add8cd550697 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Jun 2012 09:51:11 -0600 Subject: [PATCH 09/14] fix MSVC build regression --- makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 128ce5ffb5..49c82a1bcf 100755 --- a/makefile +++ b/makefile @@ -230,6 +230,8 @@ so-suffix = .so shared = -shared +no-error = -Wno-error + openjdk-extra-cflags = -fvisibility=hidden bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) @@ -506,6 +508,7 @@ ld := $(cc) build-ld := $(build-cc) ifdef msvc + no-error = windows-path = $(native-path) windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") zlib := $(shell $(windows-path) "$(win32)/msvc") @@ -931,7 +934,7 @@ $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(build)/%.o: $(lzma)/C/%.c @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) $(cflags) -Wno-error -c $$($(windows-path) $(<)) $(call output,$(@)) + $(cxx) $(cflags) $(no-error) -c $$($(windows-path) $(<)) $(call output,$(@)) $(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S $(compile-asm-object) @@ -1011,7 +1014,7 @@ $(build)/%-build.o: $(lzma)/C/%.c @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ - -Wno-error -c $(<) -o $(@) + $(no-error) -c $(<) -o $(@) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(compile-object) From 7d8def84e0d7d11780786e6792fad3ba145e6dfa Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Jun 2012 09:52:06 -0600 Subject: [PATCH 10/14] fix build on old Xcode versions --- makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 49c82a1bcf..9514d67dcf 100755 --- a/makefile +++ b/makefile @@ -326,8 +326,12 @@ ifeq ($(platform),darwin) endif version-script-flag = - lflags = $(common-lflags) -ldl -framework CoreFoundation \ - -Wl,-compatibility_version,1.0.0 + lflags = $(common-lflags) -ldl -framework CoreFoundation + + ifeq (,$(shell ld -v | grep cctools)) + lflags += -Wl,-compatibility_version,1.0.0 + endif + ifneq ($(arch),arm) lflags += -framework CoreServices -framework SystemConfiguration \ -framework Security From f6299fdfe613a9d24ac709f7170ef511693f1ebc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Jun 2012 13:33:29 -0600 Subject: [PATCH 11/14] fix bootimage build regression --- src/bootimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 2affc13f6f..8d5afff495 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -2022,7 +2022,7 @@ main(int ac, const char** av) reinterpret_cast(args.bootimageEnd), reinterpret_cast(args.codeimageStart), reinterpret_cast(args.codeimageEnd), - reinterpret_cast(args.useLZMA) + static_cast(args.useLZMA) }; run(t, writeBootImage, arguments); From ba6ca031bbe04a226d5a520403622fd84c1be45e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Jun 2012 13:53:13 -0600 Subject: [PATCH 12/14] fix handling of no-argument options in bootimage.cpp --- src/bootimage.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 8d5afff495..8d403d0745 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1769,8 +1769,10 @@ bool ArgParser::parse(int ac, const char** av) { 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 { @@ -1778,7 +1780,7 @@ bool ArgParser::parse(int ac, const char** av) { } } } - if(!state) { + if (not found) { fprintf(stderr, "unrecognized parameter %s\n", av[i]); return false; } @@ -1806,8 +1808,10 @@ void ArgParser::printUsage(const char* exe) { const char* lineEnd = arg->next ? " \\" : ""; if(arg->required) { fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); - } else { + } 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); } } } From 165986841e6c34da8c08d34db01967d1e992e2f8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 6 Jun 2012 12:58:24 -0600 Subject: [PATCH 13/14] fix endianess bug in LZMA decoding --- makefile | 2 +- src/lzma-decode.cpp | 16 ++++++++++++++-- src/lzma/load.cpp | 12 ++++++++++-- src/lzma/main.cpp | 12 ++++++++++-- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/makefile b/makefile index 9514d67dcf..6e5f439d2f 100755 --- a/makefile +++ b/makefile @@ -328,7 +328,7 @@ ifeq ($(platform),darwin) version-script-flag = lflags = $(common-lflags) -ldl -framework CoreFoundation - ifeq (,$(shell ld -v | grep cctools)) + ifeq (,$(shell ld -v 2>&1 | grep cctools)) lflags += -Wl,-compatibility_version,1.0.0 endif diff --git a/src/lzma-decode.cpp b/src/lzma-decode.cpp index f51b86af83..874e6f584d 100644 --- a/src/lzma-decode.cpp +++ b/src/lzma-decode.cpp @@ -13,6 +13,19 @@ using namespace vm; +namespace { + +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + +} // namespace + namespace vm { uint8_t* @@ -22,8 +35,7 @@ decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, const unsigned PropHeaderSize = 5; const unsigned HeaderSize = 13; - int32_t outSize32; - memcpy(&outSize32, in + PropHeaderSize, 4); + int32_t outSize32 = read4(in + PropHeaderSize); expect(s, outSize32 >= 0); SizeT outSizeT = outSize32; diff --git a/src/lzma/load.cpp b/src/lzma/load.cpp index 3584c50e6a..4a68466772 100644 --- a/src/lzma/load.cpp +++ b/src/lzma/load.cpp @@ -41,6 +41,15 @@ extern "C" { namespace { +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + void* myAllocate(void*, size_t size) { @@ -127,8 +136,7 @@ main(int ac, const char** av) SizeT inSize = SYMBOL(end) - SYMBOL(start); - int32_t outSize32; - memcpy(&outSize32, SYMBOL(start) + PropHeaderSize, 4); + int32_t outSize32 = read4(SYMBOL(start) + PropHeaderSize); SizeT outSize = outSize32; uint8_t* out = static_cast(malloc(outSize)); diff --git a/src/lzma/main.cpp b/src/lzma/main.cpp index a9a558d897..f6baa39bb9 100644 --- a/src/lzma/main.cpp +++ b/src/lzma/main.cpp @@ -17,6 +17,15 @@ namespace { +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + void* myAllocate(void*, size_t size) { @@ -100,8 +109,7 @@ main(int argc, const char** argv) if (encode) { outSize = size * 2; } else { - int32_t outSize32; - memcpy(&outSize32, data + PropHeaderSize, 4); + int32_t outSize32 = read4(data + PropHeaderSize); if (outSize32 >= 0) { outSize = outSize32; } else if (argc == 5) { From fa8ba2afc859a764ef38c79a5c5ccaafdb532510 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 11 Jun 2012 23:30:22 +0000 Subject: [PATCH 14/14] fix build for recent versions of OpenJDK 7 As of the latest code from the jdk7u-dev Mercurial repository, java.lang.String no longer has offset or length fields. Instead, the content fits exactly into the backing char array, so offset is implicitly zero and length is the length of the array. The VM previously relied on those fields being present, whereas this commit handles the case where they are not. In addition, I've made some changes to openjdk-src.mk to ensure that we can build against both a stock OpenJDK 7 and an IcedTea-patched version. --- openjdk-src.mk | 15 +++++++-------- src/classpath-openjdk.cpp | 16 ++++++++-------- src/machine.h | 33 +++++++++++++++++++++++++++++++++ src/type-generator.cpp | 5 +++++ 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/openjdk-src.mk b/openjdk-src.mk index 027b6a79b5..fbbce2e5e8 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -239,8 +239,7 @@ ifeq ($(platform),windows) -Ds6_bytes=_s6_bytes else openjdk-sources += \ - $(openjdk-src)/solaris/native/common/jdk_util_md.c \ - $(openjdk-src)/solaris/native/common/jni_util_md.c \ + $(shell find $(openjdk-src)/solaris/native/common -name '*.c') \ $(openjdk-src)/solaris/native/java/io/canonicalize_md.c \ $(openjdk-src)/solaris/native/java/io/Console_md.c \ $(openjdk-src)/solaris/native/java/io/FileDescriptor_md.c \ @@ -305,9 +304,6 @@ else ifeq ($(platform),linux) openjdk-sources += \ $(openjdk-src)/solaris/native/java/net/linux_close.c \ - $(openjdk-src)/solaris/native/common/deps/syscalls_fp.c \ - $(openjdk-src)/solaris/native/common/deps/gconf2/gconf_fp.c \ - $(openjdk-src)/solaris/native/common/deps/glib2/gio_fp.c \ $(openjdk-src)/solaris/native/sun/nio/ch/EPollArrayWrapper.c openjdk-headers-classes += \ @@ -316,6 +312,8 @@ else openjdk-cflags += \ "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ + "-I$(openjdk-src)/solaris/native/common/deps/fontconfig2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gtk2" \ $(shell pkg-config --cflags glib-2.0) \ $(shell pkg-config --cflags gconf-2.0) endif @@ -341,12 +339,13 @@ openjdk-local-sources += \ $(src)/openjdk/my_net_util.c \ $(src)/openjdk/my_management.c -c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-openjdk.o,$(x))) +openjdk-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-openjdk.o,$(x))) openjdk-objects = \ - $(call c-objects,$(openjdk-sources),$(openjdk-src),$(build)/openjdk) + $(call openjdk-c-objects,$(openjdk-sources),$(openjdk-src),$(build)/openjdk) openjdk-local-objects = \ - $(call c-objects,$(openjdk-local-sources),$(src)/openjdk,$(build)/openjdk) + $(call openjdk-c-objects,$(openjdk-local-sources),$(src)/openjdk,$(build)/openjdk) openjdk-headers-dep = $(build)/openjdk/headers.dep diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index fe9dbfdbfb..e05a71260e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -562,6 +562,14 @@ class MyClasspath : public Classpath { expect(t, loadLibrary(t, libraryPath, "java", true, true)); #endif // not AVIAN_OPENJDK_SRC + { object assertionLock = resolveField + (t, type(t, Machine::ClassLoaderType), "assertionLock", + "Ljava/lang/Object;"); + + set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), + root(t, Machine::BootLoader)); + } + { object class_ = resolveClass (t, root(t, Machine::BootLoader), "java/util/Properties", true, Machine::NoClassDefFoundErrorType); @@ -594,14 +602,6 @@ class MyClasspath : public Classpath { root(t, Machine::BootLoader)); } - { object assertionLock = resolveField - (t, type(t, Machine::ClassLoaderType), "assertionLock", - "Ljava/lang/Object;"); - - set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), - root(t, Machine::BootLoader)); - } - { object scl = resolveField (t, type(t, Machine::ClassLoaderType), "scl", "Ljava/lang/ClassLoader;"); diff --git a/src/machine.h b/src/machine.h index bb3b97a43c..9671d6cf7c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2233,6 +2233,39 @@ makeByteArray(Thread* t, const char* format, ...); object makeString(Thread* t, const char* format, ...); +#ifndef HAVE_StringOffset + +inline unsigned +stringLength(Thread* t, object string) +{ + return arrayLength(t, stringData(t, string)); +} + +inline unsigned +stringOffset(Thread*, object) +{ + return 0; +} + +inline object +makeString(Thread* t, object data, unsigned offset, unsigned length, unsigned) +{ + if (offset == 0 and length == arrayLength(t, data)) { + return makeString(t, data, 0, 0); + } else { + PROTECT(t, data); + + object array = makeCharArray(t, length); + + memcpy(&charArrayBody(t, array, 0), &charArrayBody(t, data, offset), + length * 2); + + return makeString(t, array, 0, 0); + } +} + +#endif // not HAVE_StringOffset + int stringUTFLength(Thread* t, object string, unsigned start, unsigned length); diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 813cce7dcd..f31b0f18c8 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1384,6 +1384,11 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false) out->write(" = "); writeOffset(out, offset); out->write(";\n\n"); + + out->write("#define HAVE_"); + out->write(capitalize(local::typeName(memberOwner(member)))); + out->write(capitalize(memberName(member))); + out->write(" 1\n\n"); } out->write("inline ");