From f34741467585fa7da6b6a193aefbf2263c2500b2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 22 Sep 2014 11:10:35 -0600 Subject: [PATCH] abort if JIT triggered when AVIAN_AOT_ONLY is defined If AVIAN_AOT_ONLY is defined and the VM is asked to compile a method anyway, we should abort immediately rather than let it crash later (e.g. due to an access violation on a non-jailbroken iPhone). This makes debugging such issues a bit easier since the failure will come earlier and with a more obvious cause. --- src/compile.cpp | 154 ++++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 72 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 9f34ebcf59..b64d06f1c5 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -62,10 +62,13 @@ const bool DebugCompile = false; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; -const bool DebugFrameMaps = false; const bool DebugInstructions = false; +#ifndef AVIAN_AOT_ONLY +const bool DebugFrameMaps = false; const bool CheckArrayBounds = true; +const unsigned ExecutableAreaSizeInBytes = 30 * 1024 * 1024; +#endif #ifdef AVIAN_CONTINUATIONS const bool Continuations = true; @@ -77,8 +80,6 @@ const unsigned MaxNativeCallFootprint = TargetBytesPerWord == 8 ? 4 : 5; const unsigned InitialZoneCapacityInBytes = 64 * 1024; -const unsigned ExecutableAreaSizeInBytes = 30 * 1024 * 1024; - enum ThunkIndex { compileMethodIndex, compileVirtualMethodIndex, @@ -2012,8 +2013,6 @@ unsigned savedTargetIndex(MyThread* t UNUSED, GcMethod* method) GcCallNode* findCallNode(MyThread* t, void* address); -void insertCallNode(MyThread* t, GcCallNode* node); - void* findExceptionHandler(Thread* t, GcMethod* method, void* ip) { if (t->exception) { @@ -2289,10 +2288,6 @@ uintptr_t nativeThunk(MyThread* t); uintptr_t bootNativeThunk(MyThread* t); -uintptr_t aioobThunk(MyThread* t); - -uintptr_t stackOverflowThunk(MyThread* t); - uintptr_t virtualThunk(MyThread* t, unsigned index); bool unresolved(MyThread* t, uintptr_t methodAddress); @@ -2401,18 +2396,6 @@ void checkMethod(Thread* t, GcMethod* method, bool shouldBeStatic) } } -void checkField(Thread* t, GcField* field, bool shouldBeStatic) -{ - if (((field->flags() & ACC_STATIC) == 0) == shouldBeStatic) { - throwNew(t, - GcIncompatibleClassChangeError::Type, - "expected %s.%s to be %s", - field->class_()->name()->body().begin(), - field->name()->body().begin(), - shouldBeStatic ? "static" : "non-static"); - } -} - int64_t findSpecialMethodFromReference(MyThread* t, GcPair* pair) { PROTECT(t, pair); @@ -3018,6 +3001,35 @@ void idleIfNecessary(MyThread* t) } } +bool useLongJump(MyThread* t, uintptr_t target) +{ + uintptr_t reach = t->arch->maximumImmediateJump(); + FixedAllocator* a = codeAllocator(t); + uintptr_t start = reinterpret_cast(a->memory.begin()); + uintptr_t end = reinterpret_cast(a->memory.begin()) + + a->memory.count; + assertT(t, end - start < reach); + + return (target > end && (target - start) > reach) + or (target < start && (end - target) > reach); +} + +FILE* compileLog = 0; + +void logCompile(MyThread* t, + const void* code, + unsigned size, + const char* class_, + const char* name, + const char* spec); + +unsigned simpleFrameMapTableSize(MyThread* t, GcMethod* method, GcIntArray* map) +{ + int size = frameMapSizeInBits(t, method); + return ceilingDivide(map->length() * size, 32 + size); +} + +#ifndef AVIAN_AOT_ONLY unsigned resultSize(MyThread* t, unsigned code) { switch (code) { @@ -3069,19 +3081,6 @@ ir::Value* popField(MyThread* t, Frame* frame, int code) } } -bool useLongJump(MyThread* t, uintptr_t target) -{ - uintptr_t reach = t->arch->maximumImmediateJump(); - FixedAllocator* a = codeAllocator(t); - uintptr_t start = reinterpret_cast(a->memory.begin()); - uintptr_t end = reinterpret_cast(a->memory.begin()) - + a->memory.count; - assertT(t, end - start < reach); - - return (target > end && (target - start) > reach) - or (target < start && (end - target) > reach); -} - void compileSafePoint(MyThread* t, Compiler* c, Frame* frame) { c->nativeCall( @@ -3878,6 +3877,22 @@ lir::TernaryOperation toCompilerBinaryOp(MyThread* t, unsigned instruction) } } +uintptr_t aioobThunk(MyThread* t); + +uintptr_t stackOverflowThunk(MyThread* t); + +void checkField(Thread* t, GcField* field, bool shouldBeStatic) +{ + if (((field->flags() & ACC_STATIC) == 0) == shouldBeStatic) { + throwNew(t, + GcIncompatibleClassChangeError::Type, + "expected %s.%s to be %s", + field->class_()->name()->body().begin(), + field->name()->body().begin(), + shouldBeStatic ? "static" : "non-static"); + } +} + void compile(MyThread* t, Frame* initialFrame, unsigned initialIp, @@ -6167,15 +6182,6 @@ branch: goto start; } -FILE* compileLog = 0; - -void logCompile(MyThread* t, - const void* code, - unsigned size, - const char* class_, - const char* name, - const char* spec); - int resolveIpForwards(Context* context, int start, int end) { if (start < 0) { @@ -6621,12 +6627,6 @@ int compareTraceElementPointers(const void* va, const void* vb) } } -unsigned simpleFrameMapTableSize(MyThread* t, GcMethod* method, GcIntArray* map) -{ - int size = frameMapSizeInBits(t, method); - return ceilingDivide(map->length() * size, 32 + size); -} - uint8_t* finish(MyThread* t, FixedAllocator* allocator, avian::codegen::Assembler* a, @@ -6754,6 +6754,8 @@ GcIntArray* makeSimpleFrameMapTable(MyThread* t, return table; } +void insertCallNode(MyThread* t, GcCallNode* node); + void finish(MyThread* t, FixedAllocator* allocator, Context* context) { avian::codegen::Compiler* c = context->compiler; @@ -6919,9 +6921,7 @@ void finish(MyThread* t, FixedAllocator* allocator, Context* context) "") == 0) { trap(); } -#if !defined(AVIAN_AOT_ONLY) syncInstructionCache(start, codeSize); -#endif } void compile(MyThread* t, Context* context) @@ -7063,6 +7063,7 @@ void compile(MyThread* t, Context* context) } free(stackMap); } +#endif // not AVIAN_AOT_ONLY void updateCall(MyThread* t, avian::codegen::lir::UnaryOperation op, @@ -8249,7 +8250,9 @@ class MyProcessor; MyProcessor* processor(MyThread* t); +#ifndef AVIAN_AOT_ONLY void compileThunks(MyThread* t, FixedAllocator* allocator); +#endif class CompilationHandlerList { public: @@ -8794,7 +8797,7 @@ class MyProcessor : public Processor { virtual void dispose() { if (codeAllocator.memory.begin()) { -#if !defined(AVIAN_AOT_ONLY) +#ifndef AVIAN_AOT_ONLY Memory::free(codeAllocator.memory); #endif } @@ -8973,7 +8976,7 @@ class MyProcessor : public Processor { virtual void boot(Thread* t, BootImage* image, uint8_t* code) { -#if !defined(AVIAN_AOT_ONLY) +#ifndef AVIAN_AOT_ONLY if (codeAllocator.memory.begin() == 0) { codeAllocator.memory = Memory::allocate(ExecutableAreaSizeInBytes, Memory::ReadWriteExecute); @@ -9370,14 +9373,6 @@ GcArray* insertCallNode(MyThread* t, return table; } -void insertCallNode(MyThread* t, GcCallNode* node) -{ - GcArray* newArray = insertCallNode( - t, compileRoots(t)->callTable(), &(processor(t)->callTableSize), node); - // sequence point, for gc (don't recombine statements) - compileRoots(t)->setCallTable(t, newArray); -} - GcHashMap* makeClassMap(Thread* t, unsigned* table, unsigned count, @@ -9764,6 +9759,15 @@ intptr_t getThunk(MyThread* t, Thunk thunk) + (thunk * p->thunks.table.length)); } +#ifndef AVIAN_AOT_ONLY +void insertCallNode(MyThread* t, GcCallNode* node) +{ + GcArray* newArray = insertCallNode( + t, compileRoots(t)->callTable(), &(processor(t)->callTableSize), node); + // sequence point, for gc (don't recombine statements) + compileRoots(t)->setCallTable(t, newArray); +} + BootImage::Thunk thunkToThunk(const MyProcessor::Thunk& thunk, uint8_t* base) { return BootImage::Thunk( @@ -10000,6 +10004,17 @@ void compileThunks(MyThread* t, FixedAllocator* allocator) } } +uintptr_t aioobThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.aioob.start); +} + +uintptr_t stackOverflowThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.stackOverflow.start); +} +#endif // not AVIAN_AOT_ONLY + MyProcessor* processor(MyThread* t) { return static_cast(t->m->processor); @@ -10030,16 +10045,6 @@ uintptr_t bootNativeThunk(MyThread* t) return reinterpret_cast(processor(t)->bootThunks.native.start); } -uintptr_t aioobThunk(MyThread* t) -{ - return reinterpret_cast(processor(t)->thunks.aioob.start); -} - -uintptr_t stackOverflowThunk(MyThread* t) -{ - return reinterpret_cast(processor(t)->thunks.stackOverflow.start); -} - bool unresolved(MyThread* t, uintptr_t methodAddress) { return methodAddress == defaultThunk(t) @@ -10119,7 +10124,7 @@ uintptr_t virtualThunk(MyThread* t, unsigned index) } void compile(MyThread* t, - FixedAllocator* allocator, + FixedAllocator* allocator UNUSED, BootContext* bootContext, GcMethod* method) { @@ -10135,6 +10140,10 @@ void compile(MyThread* t, assertT(t, (method->flags() & ACC_NATIVE) == 0); +#ifdef AVIAN_AOT_ONLY + abort(t); +#else + // We must avoid acquiring any locks until after the first pass of // compilation, since this pass may trigger classloading operations // involving application classloaders and thus the potential for @@ -10227,6 +10236,7 @@ void compile(MyThread* t, method, compileRoots(t)->methodTreeSentinal(), compareIpToMethodBounds); +#endif // not AVIAN_AOT_ONLY } GcCompileRoots* compileRoots(Thread* t)