Merge pull request #171 from joshuawarner32/master

Flatten "vm" dir and split signal handling out of vm::System
This commit is contained in:
Joel Dice 2014-02-25 14:11:09 -07:00
commit 3912f2c0e4
67 changed files with 818 additions and 479 deletions

View File

@ -11,11 +11,11 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_H
#define AVIAN_CODEGEN_ASSEMBLER_H
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/zone.h"
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/promise.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/promise.h>
namespace avian {
namespace codegen {

View File

@ -11,7 +11,7 @@
#ifndef AVIAN_CODEGEN_COMPILER_H
#define AVIAN_CODEGEN_COMPILER_H
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/zone.h"
#include "assembler.h"

View File

@ -11,7 +11,7 @@
#ifndef HEAP_H
#define HEAP_H
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/allocator.h"
namespace vm {

View File

@ -0,0 +1,82 @@
/* 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
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_SYSTEM_SIGNAL_H
#define AVIAN_SYSTEM_SIGNAL_H
#include <avian/common.h>
namespace avian {
namespace system {
// Crash the process.
// On posix, the just calls abort. On windows, we dereference a null pointer in
// order to trigger the crash dump logic.
NO_RETURN void crash();
// Registrar for unix-like "signals" (implemented with structured exceptions on windows).
// TODO: remove dependence on generated code having a well-known "thread"
// register. Use a thread-local variable instead.
class SignalRegistrar {
public:
class Handler {
public:
// This function receives state information about the paused thread.
// Returns whether to resume execution after the failure point.
virtual bool handleSignal(void** ip,
void** frame,
void** stack,
void** thread) = 0;
};
enum Signal {
// "Segmentation fault" exceptions (mostly null pointer dereference, but
// generally access to any non-mapped memory)
SegFault,
DivideByZero,
};
SignalRegistrar();
~SignalRegistrar();
// Register a handler for the given signal.
// After this method call, anytime the given signal is raised, it will be
// handled by the given handler.
// Returns true upon success, false upon failure
bool registerHandler(Signal signal, Handler* handler);
// Unregister a handler for the given signal.
// After this method call, the given signal will no longer be handled (or,
// rather, it go back to being handled by whatever was registered to handle it
// before us).
// Returns true upon success, false upon failure
bool unregisterHandler(Signal signal);
// Set the directory that a crash dump will be written to should an unhandled
// exception be thrown.
// Note: this only currently does anything on windows.
// TODO: move this out of this class, into a separate "CrashDumper" class or
// somesuch.
void setCrashDumpDirectory(const char* crashDumpDirectory);
// This is internal, implementation-specific data. It's declared in the
// specific implementation.
struct Data;
private:
Data* data;
};
} // namespace system
} // namespace avian
#endif

View File

@ -98,12 +98,6 @@ class System : public avian::util::Aborter {
virtual void disposeAll() = 0;
};
class SignalHandler {
public:
virtual bool handleSignal(void** ip, void** frame, void** stack,
void** thread) = 0;
};
class MonitorResource {
public:
MonitorResource(System::Thread* t, System::Monitor* m): t(t), m(m) {
@ -131,8 +125,7 @@ class System : public avian::util::Aborter {
virtual Status make(Mutex**) = 0;
virtual Status make(Monitor**) = 0;
virtual Status make(Local**) = 0;
virtual Status handleSegFault(SignalHandler* handler) = 0;
virtual Status handleDivideByZero(SignalHandler* handler) = 0;
virtual Status visit(Thread* thread, Thread* target,
ThreadVisitor* visitor) = 0;
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
@ -193,7 +186,7 @@ sysAbort(System* s)
// #endif // not NDEBUG
AVIAN_EXPORT System*
makeSystem(const char* crashDumpDirectory);
makeSystem();
} // namespace vm

View File

@ -90,6 +90,12 @@ ifneq (,$(filter mingw32 cygwin,$(build-platform)))
path-separator = ;
endif
target-path-separator = :
ifeq ($(platform),windows)
target-path-separator = ;
endif
library-path-variable = LD_LIBRARY_PATH
ifeq ($(build-platform),darwin)
@ -1108,7 +1114,8 @@ vm-depends := $(generated-code) \
$(shell find src include -name '*.h' -or -name '*.inc.cpp')
vm-sources = \
$(src)/vm/system/$(system).cpp \
$(src)/system/$(system).cpp \
$(src)/system/$(system)/signal.cpp \
$(src)/finder.cpp \
$(src)/machine.cpp \
$(src)/util.cpp \
@ -1239,7 +1246,8 @@ boot-object = $(build)/boot.o
generator-depends := $(wildcard $(src)/*.h)
generator-sources = \
$(src)/tools/type-generator/main.cpp \
$(src)/vm/system/$(build-system).cpp \
$(src)/system/$(build-system).cpp \
$(src)/system/$(build-system)/signal.cpp \
$(src)/finder.cpp
ifneq ($(lzma),)
@ -1525,7 +1533,7 @@ endif
$(build)/run-tests.sh: $(test-classes) makefile $(build)/extra-dir/multi-classpath-test.txt $(build)/test/multi-classpath-test.txt
echo 'cd $$(dirname $$0)' > $(@)
echo "sh ./test.sh 2>/dev/null \\" >> $(@)
echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test$(path-separator)extra-dir\" \\" >> $(@)
echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test$(target-path-separator)extra-dir\" \\" >> $(@)
echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@)
echo "$(continuation-tests) $(tail-tests)" >> $(@)

View File

@ -11,7 +11,7 @@
#ifndef VECTOR_H
#define VECTOR_H
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/target.h"
#include <avian/util/math.h>

View File

@ -12,7 +12,7 @@
#define FINDER_H
#include "avian/common.h"
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/allocator.h"
namespace vm {

View File

@ -13,7 +13,7 @@
#include "avian/lzma.h"
#include "C/Types.h"
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/allocator.h"
namespace vm {

View File

@ -11,7 +11,7 @@
#ifndef LZMA_H
#define LZMA_H
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/allocator.h"
namespace vm {

View File

@ -13,8 +13,9 @@
#include "avian/common.h"
#include "java-common.h"
#include <avian/vm/system/system.h>
#include <avian/vm/heap/heap.h>
#include <avian/system/system.h>
#include <avian/system/signal.h>
#include <avian/heap/heap.h>
#include "avian/finder.h"
#include "avian/processor.h"
#include "avian/constants.h"

View File

@ -12,7 +12,7 @@
#define PROCESS_H
#include "avian/common.h"
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/machine.h"
#include "avian/constants.h"

View File

@ -12,8 +12,8 @@
#define PROCESSOR_H
#include "avian/common.h"
#include <avian/vm/system/system.h>
#include <avian/vm/heap/heap.h>
#include <avian/system/system.h>
#include <avian/heap/heap.h>
#include "bootimage.h"
#include "avian/heapwalk.h"
#include "avian/zone.h"
@ -208,8 +208,10 @@ class Processor {
}
};
Processor*
makeProcessor(System* system, Allocator* allocator, bool useNativeFeatures);
Processor* makeProcessor(System* system,
Allocator* allocator,
const char* crashDumpDirectory,
bool useNativeFeatures);
} // namespace vm

View File

@ -11,7 +11,7 @@
#ifndef ZONE_H
#define ZONE_H
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/allocator.h"
#include <avian/util/math.h>

View File

@ -12,10 +12,10 @@
#include <avian/util/runtime-array.h>
#include <avian/vm/codegen/compiler.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/architecture.h>
#include <avian/vm/codegen/promise.h>
#include <avian/codegen/compiler.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/architecture.h>
#include <avian/codegen/promise.h>
#include "codegen/compiler/regalloc.h"
#include "codegen/compiler/context.h"

View File

@ -11,7 +11,7 @@
#include "codegen/compiler/context.h"
#include "codegen/compiler/resource.h"
#include <avian/vm/codegen/architecture.h>
#include <avian/codegen/architecture.h>
namespace avian {
namespace codegen {

View File

@ -11,8 +11,8 @@
#ifndef AVIAN_CODEGEN_COMPILER_CONTEXT_H
#define AVIAN_CODEGEN_COMPILER_CONTEXT_H
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/compiler.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/compiler.h>
#include <avian/util/list.h>
#include "regalloc.h"

View File

@ -13,7 +13,7 @@
#include "codegen/compiler/context.h"
#include "codegen/compiler/frame.h"
#include <avian/vm/codegen/architecture.h>
#include <avian/codegen/architecture.h>
namespace avian {
namespace codegen {

View File

@ -13,8 +13,8 @@
#include "avian/common.h"
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/registers.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/registers.h>
namespace avian {
@ -108,4 +108,4 @@ pickTarget(Context* c, Read* read, bool intersectRead,
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H

View File

@ -11,7 +11,7 @@
#ifndef AVIAN_CODEGEN_COMPILER_SITE_H
#define AVIAN_CODEGEN_COMPILER_SITE_H
#include <avian/vm/codegen/architecture.h>
#include <avian/codegen/architecture.h>
#include "codegen/compiler/value.h"
#include "codegen/compiler/context.h"

View File

@ -11,8 +11,8 @@
#ifndef AVIAN_CODEGEN_COMPILER_VALUE_H
#define AVIAN_CODEGEN_COMPILER_VALUE_H
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/compiler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/compiler.h>
namespace avian {
namespace codegen {
@ -81,4 +81,4 @@ Value* value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0);
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H

View File

@ -8,7 +8,7 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include <avian/vm/codegen/registers.h>
#include <avian/codegen/registers.h>
namespace avian {
namespace codegen {

View File

@ -10,9 +10,9 @@
#include <avian/util/runtime-array.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/architecture.h>
#include <avian/vm/codegen/registers.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/architecture.h>
#include <avian/codegen/registers.h>
#include "context.h"
#include "block.h"

View File

@ -11,8 +11,8 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H
#define AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
namespace avian {
namespace codegen {

View File

@ -11,8 +11,8 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H
#define AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
#include "avian/alloc-vector.h"
namespace vm {

View File

@ -11,8 +11,8 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H
#define AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
namespace avian {
namespace codegen {

View File

@ -13,8 +13,8 @@
#include "avian/target.h"
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
#include "avian/alloc-vector.h"
namespace vm {

View File

@ -11,8 +11,8 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H
#define AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)

View File

@ -11,8 +11,8 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H
#define AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
namespace avian {
namespace codegen {

View File

@ -8,9 +8,9 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/architecture.h>
#include <avian/vm/codegen/registers.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/architecture.h>
#include <avian/codegen/registers.h>
#include "avian/alloc-vector.h"
#include <avian/util/abort.h>

View File

@ -11,7 +11,7 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_CONTEXT_H
#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_CONTEXT_H
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/assembler.h>
#include "avian/alloc-vector.h"
#ifdef powerpc

View File

@ -22,13 +22,13 @@
#include <avian/util/abort.h>
#include <avian/util/math.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/architecture.h>
#include <avian/vm/codegen/registers.h>
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/promise.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/architecture.h>
#include <avian/codegen/registers.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/promise.h>
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "context.h"
#include "block.h"

View File

@ -10,7 +10,7 @@
#include "block.h"
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/assembler.h>
namespace avian {
namespace codegen {

View File

@ -11,7 +11,7 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H
#define AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/assembler.h>
namespace avian {
namespace codegen {

View File

@ -19,10 +19,10 @@
#include "avian/alloc-vector.h"
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
namespace vm {
class System;

View File

@ -11,7 +11,7 @@
#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H
#define AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H
#include <avian/vm/codegen/assembler.h>
#include <avian/codegen/assembler.h>
namespace avian {
namespace codegen {

View File

@ -14,8 +14,8 @@
#include <avian/util/abort.h>
#include <avian/util/math.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/promise.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/promise.h>
#include "context.h"
#include "encode.h"

View File

@ -15,7 +15,7 @@
#include "avian/common.h"
#include <avian/vm/codegen/lir.h>
#include <avian/codegen/lir.h>
#include "registers.h"

View File

@ -16,7 +16,7 @@
#include "avian/zone.h"
#include <avian/util/abort.h>
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "context.h"
#include "fixup.h"

View File

@ -13,7 +13,7 @@
#include <stdint.h>
#include <avian/vm/codegen/promise.h>
#include <avian/codegen/promise.h>
namespace vm {
class System;

View File

@ -12,7 +12,7 @@
#include <avian/util/abort.h>
#include <avian/vm/codegen/lir.h>
#include <avian/codegen/lir.h>
#include "context.h"
#include "operations.h"

View File

@ -13,7 +13,7 @@
#include "avian/common.h"
#include <avian/vm/codegen/lir.h>
#include <avian/codegen/lir.h>
namespace avian {
namespace codegen {

View File

@ -15,8 +15,8 @@
#include <avian/util/abort.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/promise.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/promise.h>
#include "context.h"
#include "encode.h"

View File

@ -13,7 +13,7 @@
#include "avian/common.h"
#include <avian/vm/codegen/lir.h>
#include <avian/codegen/lir.h>
#include "context.h"

View File

@ -10,7 +10,7 @@
#include "avian/common.h"
#include <avian/vm/codegen/targets.h>
#include <avian/codegen/targets.h>
#include "avian/environment.h"

View File

@ -15,12 +15,12 @@
#include "avian/target.h"
#include "avian/arch.h"
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/architecture.h>
#include <avian/vm/codegen/compiler.h>
#include <avian/vm/codegen/targets.h>
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/runtime.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/architecture.h>
#include <avian/codegen/compiler.h>
#include <avian/codegen/targets.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/runtime.h>
#include <avian/util/runtime-array.h>
#include <avian/util/list.h>
@ -43,6 +43,7 @@ vmJumpAndInvoke(void* thread, void* function, void* stack,
unsigned frameSize);
using namespace avian::codegen;
using namespace avian::system;
namespace {
@ -8366,7 +8367,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
return r;
}
class SignalHandler: public System::SignalHandler {
class SignalHandler: public SignalRegistrar::Handler {
public:
SignalHandler(Machine::Type type, Machine::Root root, unsigned fixedSize):
m(0), type(type), root(root), fixedSize(fixedSize) { }
@ -8501,24 +8502,27 @@ class MyProcessor: public Processor {
Thunk table;
};
MyProcessor(System* s, Allocator* allocator, bool useNativeFeatures):
s(s),
allocator(allocator),
roots(0),
bootImage(0),
heapImage(0),
codeImage(0),
codeImageSize(0),
segFaultHandler(Machine::NullPointerExceptionType,
Machine::NullPointerException,
FixedSizeOfNullPointerException),
divideByZeroHandler(Machine::ArithmeticExceptionType,
Machine::ArithmeticException,
FixedSizeOfArithmeticException),
codeAllocator(s, 0, 0),
callTableSize(0),
useNativeFeatures(useNativeFeatures),
compilationHandlers(0)
MyProcessor(System* s,
Allocator* allocator,
const char* crashDumpDirectory,
bool useNativeFeatures)
: s(s),
allocator(allocator),
roots(0),
bootImage(0),
heapImage(0),
codeImage(0),
codeImageSize(0),
segFaultHandler(Machine::NullPointerExceptionType,
Machine::NullPointerException,
FixedSizeOfNullPointerException),
divideByZeroHandler(Machine::ArithmeticExceptionType,
Machine::ArithmeticException,
FixedSizeOfArithmeticException),
codeAllocator(s, 0, 0),
callTableSize(0),
useNativeFeatures(useNativeFeatures),
compilationHandlers(0)
{
thunkTable[compileMethodIndex] = voidPointer(local::compileMethod);
thunkTable[compileVirtualMethodIndex] = voidPointer(compileVirtualMethod);
@ -8540,6 +8544,8 @@ class MyProcessor: public Processor {
// table.
thunkTable[dummyIndex] = reinterpret_cast<void*>
(static_cast<uintptr_t>(UINT64_C(0x5555555555555555)));
signals.setCrashDumpDirectory(crashDumpDirectory);
}
virtual Thread*
@ -8924,7 +8930,9 @@ class MyProcessor: public Processor {
compilationHandlers->dispose(allocator);
s->handleSegFault(0);
signals.unregisterHandler(SignalRegistrar::SegFault);
signals.unregisterHandler(SignalRegistrar::DivideByZero);
signals.setCrashDumpDirectory(0);
allocator->free(this, sizeof(*this));
}
@ -9116,12 +9124,10 @@ class MyProcessor: public Processor {
#endif
segFaultHandler.m = t->m;
expect(t, t->m->system->success
(t->m->system->handleSegFault(&segFaultHandler)));
expect(t, signals.registerHandler(SignalRegistrar::SegFault, &segFaultHandler));
divideByZeroHandler.m = t->m;
expect(t, t->m->system->success
(t->m->system->handleDivideByZero(&divideByZeroHandler)));
expect(t, signals.registerHandler(SignalRegistrar::DivideByZero, &divideByZeroHandler));
}
virtual void callWithCurrentContinuation(Thread* t, object receiver) {
@ -9173,6 +9179,7 @@ class MyProcessor: public Processor {
}
System* s;
SignalRegistrar signals;
Allocator* allocator;
object roots;
BootImage* bootImage;
@ -10285,11 +10292,13 @@ codeAllocator(MyThread* t)
namespace vm {
Processor*
makeProcessor(System* system, Allocator* allocator, bool useNativeFeatures)
Processor* makeProcessor(System* system,
Allocator* allocator,
const char* crashDumpDirectory,
bool useNativeFeatures)
{
return new (allocator->allocate(sizeof(local::MyProcessor)))
local::MyProcessor(system, allocator, useNativeFeatures);
local::MyProcessor(system, allocator, crashDumpDirectory, useNativeFeatures);
}
} // namespace vm

View File

@ -8,7 +8,7 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include <avian/util/string.h>
#include <avian/util/runtime-array.h>
#include <avian/util/list.h>

View File

@ -8,8 +8,8 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include <avian/vm/heap/heap.h>
#include <avian/vm/system/system.h>
#include <avian/heap/heap.h>
#include <avian/system/system.h>
#include "avian/common.h"
#include "avian/arch.h"

View File

@ -9,7 +9,8 @@
details. */
#include "avian/common.h"
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include <avian/system/signal.h>
#include "avian/constants.h"
#include "avian/machine.h"
#include "avian/processor.h"
@ -20,6 +21,7 @@
#include <avian/util/list.h>
using namespace vm;
using namespace avian::system;
namespace local {
@ -2959,9 +2961,11 @@ invoke(Thread* t, object method)
class MyProcessor: public Processor {
public:
MyProcessor(System* s, Allocator* allocator):
s(s), allocator(allocator)
{ }
MyProcessor(System* s, Allocator* allocator, const char* crashDumpDirectory)
: s(s), allocator(allocator)
{
signals.setCrashDumpDirectory(crashDumpDirectory);
}
virtual vm::Thread*
makeThread(Machine* m, object javaThread, vm::Thread* parent)
@ -3260,21 +3264,25 @@ class MyProcessor: public Processor {
virtual void dispose() {
allocator->free(this, sizeof(*this));
signals.setCrashDumpDirectory(0);
}
System* s;
Allocator* allocator;
SignalRegistrar signals;
};
} // namespace
namespace vm {
Processor*
makeProcessor(System* system, Allocator* allocator, bool)
Processor* makeProcessor(System* system,
Allocator* allocator,
const char* crashDumpDirectory,
bool)
{
return new (allocator->allocate(sizeof(local::MyProcessor)))
local::MyProcessor(system, allocator);
local::MyProcessor(system, allocator, crashDumpDirectory);
}
} // namespace vm

View File

@ -3878,7 +3878,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
if (classpath == 0) classpath = ".";
System* s = makeSystem(crashDumpDirectory);
System* s = makeSystem();
Heap* h = makeHeap(s, heapLimit);
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
@ -3913,7 +3913,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
Finder* af = makeFinder(s, h, classpath, bootLibrary);
if(bootLibrary)
free(bootLibrary);
Processor* p = makeProcessor(s, h, true);
Processor* p = makeProcessor(s, h, crashDumpDirectory, true);
const char** properties = static_cast<const char**>
(h->allocate(sizeof(const char*) * propertyCount));

View File

@ -13,7 +13,7 @@
#include "string.h"
#include "jni.h"
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include "avian/finder.h"
#include <avian/util/runtime-array.h>
@ -59,7 +59,7 @@ mainClass(const char* jar)
{
using namespace vm;
System* system = makeSystem(0);
System* system = makeSystem();
class MyAllocator: public Allocator {
public:

View File

@ -49,8 +49,9 @@
#include "dirent.h"
#include "sched.h"
#include "avian/arch.h"
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include <avian/system/signal.h>
#include <avian/util/math.h>
@ -78,29 +79,14 @@ class MutexResource {
const int InvalidSignal = -1;
const int VisitSignal = SIGUSR1;
const unsigned VisitSignalIndex = 0;
const int SegFaultSignal = SIGSEGV;
const unsigned SegFaultSignalIndex = 1;
const int InterruptSignal = SIGUSR2;
const unsigned InterruptSignalIndex = 2;
#ifdef __APPLE__
const int AltSegFaultSignal = SIGBUS;
#else
const int AltSegFaultSignal = InvalidSignal;
#endif
const unsigned AltSegFaultSignalIndex = 3;
const unsigned InterruptSignalIndex = 1;
const int PipeSignal = SIGPIPE;
const unsigned PipeSignalIndex = 4;
const int DivideByZeroSignal = SIGFPE;
const unsigned DivideByZeroSignalIndex = 5;
const unsigned PipeSignalIndex = 2;
const int signals[] = { VisitSignal,
SegFaultSignal,
InterruptSignal,
AltSegFaultSignal,
PipeSignal,
DivideByZeroSignal };
const int signals[] = {VisitSignal, InterruptSignal, PipeSignal};
const unsigned SignalCount = 6;
const unsigned SignalCount = 3;
class MySystem;
MySystem* system;
@ -123,7 +109,7 @@ pathOfExecutable(System* s, const char** retBuf, unsigned* size)
CFURLRef url = CFBundleCopyExecutableURL(bundle);
CFStringRef path = CFURLCopyPath(url);
path = CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault,
path, CFSTR(""));
path, CFSTR(""));
CFIndex pathSize = CFStringGetMaximumSizeOfFileSystemRepresentation(path);
char* buffer = reinterpret_cast<char*>(allocate(s, pathSize));
if (CFStringGetFileSystemRepresentation(path, buffer, pathSize)) {
@ -606,32 +592,27 @@ class MySystem: public System {
expect(this, system == 0);
system = this;
memset(handlers, 0, sizeof(handlers));
registerHandler(&nullHandler, InterruptSignalIndex);
registerHandler(&nullHandler, PipeSignalIndex);
registerHandler(&nullHandler, VisitSignalIndex);
expect(this, registerHandler(InterruptSignalIndex));
expect(this, registerHandler(VisitSignalIndex));
expect(this, registerHandler(PipeSignalIndex));
expect(this, make(&visitLock) == 0);
}
int registerHandler(System::SignalHandler* handler, int index) {
if (handler) {
handlers[index] = handler;
// Returns true on success, false on failure
bool unregisterHandler(int index) {
return sigaction(signals[index], oldHandlers + index, 0) == 0;
}
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&(sa.sa_mask));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handleSignal;
return sigaction(signals[index], &sa, oldHandlers + index);
} else if (handlers[index]) {
handlers[index] = 0;
return sigaction(signals[index], oldHandlers + index, 0);
} else {
return 1;
}
// Returns true on success, false on failure
bool registerHandler(int index) {
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&(sa.sa_mask));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handleSignal;
return sigaction(signals[index], &sa, oldHandlers + index) == 0;
}
virtual void* tryAllocate(unsigned sizeInBytes) {
@ -701,18 +682,6 @@ class MySystem: public System {
return 0;
}
virtual Status handleSegFault(SignalHandler* handler) {
Status s = registerHandler(handler, SegFaultSignalIndex);
if (s == 0 and AltSegFaultSignal != InvalidSignal) {
return registerHandler(handler, AltSegFaultSignalIndex);
}
return s;
}
virtual Status handleDivideByZero(SignalHandler* handler) {
return registerHandler(handler, DivideByZeroSignalIndex);
}
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
ThreadVisitor* visitor)
{
@ -931,25 +900,20 @@ class MySystem: public System {
}
virtual void abort() {
::abort();
avian::system::crash();
}
virtual void dispose() {
visitLock->dispose();
registerHandler(0, InterruptSignalIndex);
registerHandler(0, VisitSignalIndex);
registerHandler(0, PipeSignalIndex);
expect(this, unregisterHandler(InterruptSignalIndex));
expect(this, unregisterHandler(VisitSignalIndex));
expect(this, unregisterHandler(PipeSignalIndex));
system = 0;
::free(this);
}
class NullSignalHandler: public SignalHandler {
virtual bool handleSignal(void**, void**, void**, void**) { return false; }
} nullHandler;
SignalHandler* handlers[SignalCount];
struct sigaction oldHandlers[SignalCount];
ThreadVisitor* threadVisitor;
@ -957,27 +921,16 @@ class MySystem: public System {
System::Monitor* visitLock;
};
void
handleSignal(int signal, siginfo_t*, void* context)
void handleSignal(int signal, siginfo_t*, void* context)
{
ucontext_t* c = static_cast<ucontext_t*>(context);
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
void* link = reinterpret_cast<void*>(LINK_REGISTER(c));
#ifdef FRAME_REGISTER
void* frame = reinterpret_cast<void*>(FRAME_REGISTER(c));
#else
void* frame = 0;
#endif
unsigned index;
switch (signal) {
case VisitSignal: {
index = VisitSignalIndex;
system->threadVisitor->visit(ip, stack, link);
System::Thread* t = system->visitTarget;
@ -987,57 +940,6 @@ handleSignal(int signal, siginfo_t*, void* context)
system->visitLock->notifyAll(t);
} break;
case SegFaultSignal:
case AltSegFaultSignal:
case DivideByZeroSignal: {
switch (signal) {
case SegFaultSignal:
index = SegFaultSignalIndex;
break;
case AltSegFaultSignal:
index = AltSegFaultSignalIndex;
break;
case DivideByZeroSignal:
index = DivideByZeroSignalIndex;
break;
default:
abort();
}
bool jump = system->handlers[index]->handleSignal
(&ip, &frame, &stack, &thread);
if (jump) {
// I'd like to use setcontext here (and get rid of the
// sigprocmask call), but it doesn't work on my Linux x86_64
// system, and I can't tell from the documentation if it's even
// supposed to work.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, signal);
pthread_sigmask(SIG_UNBLOCK, &set, 0);
vmJump(ip, frame, stack, thread, 0, 0);
}
} break;
case InterruptSignal: {
index = InterruptSignalIndex;
} break;
case PipeSignal: {
index = PipeSignalIndex;
} break;
default: abort();
}
switch (signal) {
case VisitSignal:
case InterruptSignal:
case PipeSignal:
break;
@ -1052,7 +954,7 @@ handleSignal(int signal, siginfo_t*, void* context)
namespace vm {
AVIAN_EXPORT System*
makeSystem(const char*)
makeSystem()
{
return new (malloc(sizeof(MySystem))) MySystem();
}

233
src/system/posix/signal.cpp Normal file
View File

@ -0,0 +1,233 @@
/* 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
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 "signal.h"
#include "sys/types.h"
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#include "sys/ucontext.h"
#undef assert
#elif defined(__ANDROID__)
#include <asm/sigcontext.h> /* for sigcontext */
#include <asm/signal.h> /* 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"
#endif
#include "ucontext.h"
#endif
#include "avian/arch.h"
#include <avian/system/system.h>
#include <avian/system/signal.h>
namespace avian {
namespace system {
namespace posix {
const int InvalidSignal = -1;
const int SegFaultSignal = SIGSEGV;
const unsigned SegFaultSignalIndex = 0;
#ifdef __APPLE__
const int AltSegFaultSignal = SIGBUS;
#else
const int AltSegFaultSignal = InvalidSignal;
#endif
const unsigned AltSegFaultSignalIndex = 1;
const int DivideByZeroSignal = SIGFPE;
const unsigned DivideByZeroSignalIndex = 2;
const int signals[]
= {SegFaultSignal, AltSegFaultSignal, DivideByZeroSignal};
const unsigned SignalCount = 3;
}
struct SignalRegistrar::Data {
Handler* handlers[posix::SignalCount];
struct sigaction oldHandlers[posix::SignalCount];
bool registerHandler(Handler* handler, int index);
Data()
{
if(instance) {
crash();
}
instance = this;
}
~Data()
{
instance = 0;
}
static SignalRegistrar::Data* instance;
};
SignalRegistrar::Data* SignalRegistrar::Data::instance = 0;
namespace posix {
using namespace vm;
void handleSignal(int signal, siginfo_t*, void* context)
{
ucontext_t* c = static_cast<ucontext_t*>(context);
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
#ifdef FRAME_REGISTER
void* frame = reinterpret_cast<void*>(FRAME_REGISTER(c));
#else
void* frame = 0;
#endif
unsigned index;
switch (signal) {
case SegFaultSignal:
case AltSegFaultSignal:
case DivideByZeroSignal: {
switch (signal) {
case SegFaultSignal:
index = SegFaultSignalIndex;
break;
case AltSegFaultSignal:
index = AltSegFaultSignalIndex;
break;
case DivideByZeroSignal:
index = DivideByZeroSignalIndex;
break;
default:
crash();
}
bool jump
= SignalRegistrar::Data::instance->handlers[index]->handleSignal(&ip, &frame, &stack, &thread);
if (jump) {
// I'd like to use setcontext here (and get rid of the
// sigprocmask call), but it doesn't work on my Linux x86_64
// system, and I can't tell from the documentation if it's even
// supposed to work.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, signal);
pthread_sigmask(SIG_UNBLOCK, &set, 0);
vmJump(ip, frame, stack, thread, 0, 0);
}
} break;
default:
crash();
}
}
} // namespace posix
NO_RETURN void crash()
{
abort();
}
SignalRegistrar::SignalRegistrar()
{
data = new (malloc(sizeof(Data))) Data();
}
SignalRegistrar::~SignalRegistrar()
{
data->~Data();
free(data);
}
bool SignalRegistrar::Data::registerHandler(Handler* handler, int index)
{
if (handler) {
handlers[index] = handler;
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&(sa.sa_mask));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = posix::handleSignal;
return sigaction(posix::signals[index], &sa, oldHandlers + index) == 0;
} else if (handlers[index]) {
handlers[index] = 0;
return sigaction(posix::signals[index], oldHandlers + index, 0) == 0;
} else {
return false;
}
}
bool SignalRegistrar::registerHandler(Signal signal, Handler* handler)
{
switch(signal) {
case SegFault:
if(!data->registerHandler(handler, posix::SegFaultSignalIndex)) {
return false;
}
if (posix::AltSegFaultSignal != posix::InvalidSignal) {
return data->registerHandler(handler, posix::AltSegFaultSignalIndex);
} else {
return true;
}
case DivideByZero:
return data->registerHandler(handler, posix::DivideByZeroSignalIndex);
default:
crash();
}
}
bool SignalRegistrar::unregisterHandler(Signal signal)
{
switch(signal) {
case SegFault:
if(!data->registerHandler(0, posix::SegFaultSignalIndex)) {
return false;
}
if (posix::AltSegFaultSignal != posix::InvalidSignal) {
return data->registerHandler(0, posix::AltSegFaultSignalIndex);
} else {
return true;
}
case DivideByZero:
return data->registerHandler(0, posix::DivideByZeroSignalIndex);
default:
crash();
}
}
void SignalRegistrar::setCrashDumpDirectory(const char*)
{
// Do nothing, not currently supported on posix
}
} // namespace system
} // namespace avian

View File

@ -10,7 +10,6 @@
#include "sys/stat.h"
#include "windows.h"
#include "sys/timeb.h"
#ifdef _MSC_VER
# define S_ISREG(x) ((x) & _S_IFREG)
@ -24,7 +23,8 @@
#undef min
#include "avian/arch.h"
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include <avian/system/signal.h>
#include <avian/util/runtime-array.h>
#if defined(WINAPI_FAMILY)
@ -115,11 +115,6 @@ class MutexResource {
HANDLE m;
};
const unsigned SegFaultIndex = 0;
const unsigned DivideByZeroIndex = 1;
const unsigned HandlerCount = 2;
class MySystem;
MySystem* system;
@ -626,68 +621,15 @@ class MySystem: public System {
System::Library* next_;
};
MySystem(const char* crashDumpDirectory):
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
oldHandler(0),
#endif
crashDumpDirectory(crashDumpDirectory)
MySystem()
{
expect(this, system == 0);
system = this;
memset(handlers, 0, sizeof(handlers));
mutex = CreateMutex(0, false, 0);
assert(this, mutex);
}
bool findHandler() {
for (unsigned i = 0; i < HandlerCount; ++i) {
if (handlers[i]) return true;
}
return false;
}
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
oldHandler = SetUnhandledExceptionFilter(handleException);
# elif defined ARCH_x86_64
AddVectoredExceptionHandler(1, handleException);
oldHandler = reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(1);
# 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()) {
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# ifdef ARCH_x86_32
SetUnhandledExceptionFilter(oldHandler);
oldHandler = 0;
# elif defined ARCH_x86_64
// do nothing, handlers are never "unregistered" anyway
# 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 {
return 1;
}
}
virtual void* tryAllocate(unsigned sizeInBytes) {
return malloc(sizeInBytes);
}
@ -746,14 +688,6 @@ class MySystem: public System {
return 0;
}
virtual Status handleSegFault(SignalHandler* handler) {
return registerHandler(handler, SegFaultIndex);
}
virtual Status handleDivideByZero(SignalHandler* handler) {
return registerHandler(handler, DivideByZeroIndex);
}
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
ThreadVisitor* visitor)
{
@ -1008,9 +942,7 @@ class MySystem: public System {
}
virtual void abort() {
// trigger an EXCEPTION_ACCESS_VIOLATION, which we will catch and
// generate a debug dump for
*static_cast<volatile int*>(0) = 0;
avian::system::crash();
}
virtual void dispose() {
@ -1020,139 +952,16 @@ class MySystem: public System {
}
HANDLE mutex;
SignalHandler* handlers[HandlerCount];
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
LPTOP_LEVEL_EXCEPTION_FILTER oldHandler;
#endif
const char* crashDumpDirectory;
};
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#pragma pack(push,4)
struct MINIDUMP_EXCEPTION_INFORMATION {
DWORD thread;
LPEXCEPTION_POINTERS exception;
BOOL exceptionInCurrentAddressSpace;
};
#pragma pack(pop)
struct MINIDUMP_USER_STREAM_INFORMATION;
struct MINIDUMP_CALLBACK_INFORMATION;
enum MINIDUMP_TYPE {
MiniDumpNormal = 0,
MiniDumpWithFullMemory = 2
};
typedef BOOL (*MiniDumpWriteDumpType)
(HANDLE processHandle,
DWORD processId,
HANDLE file,
MINIDUMP_TYPE type,
const MINIDUMP_EXCEPTION_INFORMATION* exception,
const MINIDUMP_USER_STREAM_INFORMATION* userStream,
const MINIDUMP_CALLBACK_INFORMATION* callback);
void
dump(LPEXCEPTION_POINTERS e, const char* directory)
{
HINSTANCE dbghelp = LoadLibrary("dbghelp.dll");
if (dbghelp) {
MiniDumpWriteDumpType MiniDumpWriteDump = reinterpret_cast
<MiniDumpWriteDumpType>(GetProcAddress(dbghelp, "MiniDumpWriteDump"));
if (MiniDumpWriteDump) {
char name[MAX_PATH];
_timeb tb;
FTIME(&tb);
vm::snprintf(name, MAX_PATH, "%s\\crash-%" LLD ".mdmp", directory,
(static_cast<int64_t>(tb.time) * 1000)
+ static_cast<int64_t>(tb.millitm));
HANDLE file = CreateFile
(name, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, 0, 0);
if (file != INVALID_HANDLE_VALUE) {
MINIDUMP_EXCEPTION_INFORMATION exception
= { GetCurrentThreadId(), e, true };
MiniDumpWriteDump
(GetCurrentProcess(),
GetCurrentProcessId(),
file,
MiniDumpWithFullMemory,
&exception,
0,
0);
CloseHandle(file);
}
}
FreeLibrary(dbghelp);
}
}
LONG CALLBACK
handleException(LPEXCEPTION_POINTERS e)
{
System::SignalHandler* handler = 0;
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
handler = system->handlers[SegFaultIndex];
} else if (e->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
{
handler = system->handlers[DivideByZeroIndex];
}
if (handler) {
#ifdef ARCH_x86_32
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
void* stack = reinterpret_cast<void*>(e->ContextRecord->Esp);
void* thread = reinterpret_cast<void*>(e->ContextRecord->Ebx);
#elif defined ARCH_x86_64
void* ip = reinterpret_cast<void*>(e->ContextRecord->Rip);
void* base = reinterpret_cast<void*>(e->ContextRecord->Rbp);
void* stack = reinterpret_cast<void*>(e->ContextRecord->Rsp);
void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx);
#endif
bool jump = handler->handleSignal(&ip, &base, &stack, &thread);
#ifdef ARCH_x86_32
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
e->ContextRecord->Esp = reinterpret_cast<DWORD>(stack);
e->ContextRecord->Ebx = reinterpret_cast<DWORD>(thread);
#elif defined ARCH_x86_64
e->ContextRecord->Rip = reinterpret_cast<DWORD64>(ip);
e->ContextRecord->Rbp = reinterpret_cast<DWORD64>(base);
e->ContextRecord->Rsp = reinterpret_cast<DWORD64>(stack);
e->ContextRecord->Rbx = reinterpret_cast<DWORD64>(thread);
#endif
if (jump) {
return EXCEPTION_CONTINUE_EXECUTION;
} else if (system->crashDumpDirectory) {
dump(e, system->crashDumpDirectory);
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
} // namespace
namespace vm {
AVIAN_EXPORT System*
makeSystem(const char* crashDumpDirectory)
makeSystem()
{
return new (malloc(sizeof(MySystem))) MySystem(crashDumpDirectory);
return new (malloc(sizeof(MySystem))) MySystem();
}
} // namespace vm

View File

@ -0,0 +1,292 @@
/* 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
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 "windows.h"
#include "sys/timeb.h"
#ifdef _MSC_VER
#define FTIME _ftime_s
#else
#define FTIME _ftime
#endif
#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
#include <avian/system/signal.h>
#include <avian/common.h>
namespace avian {
namespace system {
namespace windows {
const unsigned HandlerCount = 2;
} // namespace windows
struct SignalRegistrar::Data {
Handler* handlers[windows::HandlerCount];
const char* crashDumpDirectory;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
LPTOP_LEVEL_EXCEPTION_FILTER oldHandler;
#endif
Data() : crashDumpDirectory(0),
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
oldHandler(0)
#endif
{
if (instance) {
crash();
}
instance = this;
memset(handlers, 0, sizeof(handlers));
}
~Data()
{
instance = 0;
}
bool registerHandler(Handler* handler, int index);
bool findHandler() {
for (unsigned i = 0; i < windows::HandlerCount; ++i) {
if (handlers[i]) return true;
}
return false;
}
static SignalRegistrar::Data* instance;
};
SignalRegistrar::Data* SignalRegistrar::Data::instance = 0;
namespace windows {
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#pragma pack(push, 4)
struct MINIDUMP_EXCEPTION_INFORMATION {
DWORD thread;
LPEXCEPTION_POINTERS exception;
BOOL exceptionInCurrentAddressSpace;
};
#pragma pack(pop)
struct MINIDUMP_USER_STREAM_INFORMATION;
struct MINIDUMP_CALLBACK_INFORMATION;
enum MINIDUMP_TYPE {
MiniDumpNormal = 0,
MiniDumpWithFullMemory = 2
};
typedef BOOL (*MiniDumpWriteDumpType)(HANDLE processHandle,
DWORD processId,
HANDLE file,
MINIDUMP_TYPE type,
const MINIDUMP_EXCEPTION_INFORMATION
* exception,
const MINIDUMP_USER_STREAM_INFORMATION
* userStream,
const MINIDUMP_CALLBACK_INFORMATION
* callback);
#endif
void dump(LPEXCEPTION_POINTERS e, const char* directory)
{
HINSTANCE dbghelp = LoadLibrary("dbghelp.dll");
if (dbghelp) {
MiniDumpWriteDumpType MiniDumpWriteDump = reinterpret_cast
<MiniDumpWriteDumpType>(GetProcAddress(dbghelp, "MiniDumpWriteDump"));
if (MiniDumpWriteDump) {
char name[MAX_PATH];
_timeb tb;
FTIME(&tb);
vm::snprintf(name,
MAX_PATH,
"%s\\crash-%" LLD ".mdmp",
directory,
(static_cast<int64_t>(tb.time) * 1000) + static_cast
<int64_t>(tb.millitm));
HANDLE file
= CreateFile(name, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, 0, 0);
if (file != INVALID_HANDLE_VALUE) {
MINIDUMP_EXCEPTION_INFORMATION exception
= {GetCurrentThreadId(), e, true};
MiniDumpWriteDump(GetCurrentProcess(),
GetCurrentProcessId(),
file,
MiniDumpWithFullMemory,
&exception,
0,
0);
CloseHandle(file);
}
}
FreeLibrary(dbghelp);
}
}
LONG CALLBACK handleException(LPEXCEPTION_POINTERS e)
{
SignalRegistrar::Handler* handler = 0;
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
handler = SignalRegistrar::Data::instance->handlers[SignalRegistrar::SegFault];
} else if (e->ExceptionRecord->ExceptionCode
== EXCEPTION_INT_DIVIDE_BY_ZERO) {
handler = SignalRegistrar::Data::instance->handlers[SignalRegistrar::DivideByZero];
}
if (handler) {
#ifdef ARCH_x86_32
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
void* stack = reinterpret_cast<void*>(e->ContextRecord->Esp);
void* thread = reinterpret_cast<void*>(e->ContextRecord->Ebx);
#elif defined ARCH_x86_64
void* ip = reinterpret_cast<void*>(e->ContextRecord->Rip);
void* base = reinterpret_cast<void*>(e->ContextRecord->Rbp);
void* stack = reinterpret_cast<void*>(e->ContextRecord->Rsp);
void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx);
#endif
bool jump = handler->handleSignal(&ip, &base, &stack, &thread);
#ifdef ARCH_x86_32
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
e->ContextRecord->Esp = reinterpret_cast<DWORD>(stack);
e->ContextRecord->Ebx = reinterpret_cast<DWORD>(thread);
#elif defined ARCH_x86_64
e->ContextRecord->Rip = reinterpret_cast<DWORD64>(ip);
e->ContextRecord->Rbp = reinterpret_cast<DWORD64>(base);
e->ContextRecord->Rsp = reinterpret_cast<DWORD64>(stack);
e->ContextRecord->Rbx = reinterpret_cast<DWORD64>(thread);
#endif
if (jump) {
return EXCEPTION_CONTINUE_EXECUTION;
} else if (SignalRegistrar::Data::instance->crashDumpDirectory) {
dump(e, SignalRegistrar::Data::instance->crashDumpDirectory);
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
} // namespace windows
SignalRegistrar::SignalRegistrar()
{
data = new (malloc(sizeof(Data))) Data();
}
SignalRegistrar::~SignalRegistrar()
{
data->~Data();
free(data);
}
bool SignalRegistrar::Data::registerHandler(Handler* handler, int index)
{
if(index != SegFault && index != DivideByZero) {
crash();
}
if (handler) {
handlers[index] = handler;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
if (oldHandler == 0) {
#ifdef ARCH_x86_32
oldHandler = SetUnhandledExceptionFilter(windows::handleException);
#elif defined ARCH_x86_64
AddVectoredExceptionHandler(1, windows::handleException);
oldHandler = reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(1);
#endif
}
#else
#pragma message( \
"TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx")
#endif
return true;
} else if (handlers[index]) {
handlers[index] = 0;
if (not findHandler()) {
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#ifdef ARCH_x86_32
SetUnhandledExceptionFilter(oldHandler);
oldHandler = 0;
#elif defined ARCH_x86_64
// do nothing, handlers are never "unregistered" anyway
#endif
#else
#pragma message( \
"TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx")
#endif
}
return true;
} else {
return false;
}
}
NO_RETURN void crash()
{
// trigger an EXCEPTION_ACCESS_VIOLATION, which we will catch and
// generate a debug dump for
*static_cast<volatile int*>(0) = 0;
// Some (all?) compilers don't realize that we can't possibly continue past
// the above statement.
abort();
}
bool SignalRegistrar::registerHandler(Signal signal, Handler* handler)
{
return data->registerHandler(handler, signal);
}
bool SignalRegistrar::unregisterHandler(Signal signal)
{
return data->registerHandler(0, signal);
}
void SignalRegistrar::setCrashDumpDirectory(const char* crashDumpDirectory)
{
data->crashDumpDirectory = crashDumpDirectory;
}
} // namespace system
} // namespace avian

View File

@ -8,16 +8,16 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include <avian/vm/system/system.h>
#include <avian/system/system.h>
#include <avian/util/arg-parser.h>
#include <avian/vm/codegen/lir.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/targets.h>
#include <avian/vm/codegen/registers.h>
#include <avian/codegen/lir.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/targets.h>
#include <avian/codegen/registers.h>
#include <avian/vm/heap/heap.h>
#include <avian/heap/heap.h>
// since we aren't linking against libstdc++, we must implement this
// ourselves:
@ -34,7 +34,7 @@ public:
Architecture* arch;
BasicEnv():
s(makeSystem(0)),
s(makeSystem()),
heap(makeHeap(s, 32 * 1024)),
arch(makeArchitectureNative(s, true))
{

View File

@ -8,14 +8,14 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include <avian/vm/heap/heap.h>
#include <avian/heap/heap.h>
#include "avian/heapwalk.h"
#include "avian/common.h"
#include "avian/machine.h"
#include "avian/util.h"
#include <avian/util/stream.h>
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/promise.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/promise.h>
#include "avian/target.h"
#include <avian/tools/object-writer/tools.h>
#include <avian/util/runtime-array.h>
@ -1899,11 +1899,11 @@ main(int ac, const char** av)
Arguments args(ac, av);
// args.dump();
System* s = makeSystem(0);
System* s = makeSystem();
Heap* h = makeHeap(s, HeapCapacity * 2);
Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX);
Finder* f = makeFinder(s, h, args.classpath, 0);
Processor* p = makeProcessor(s, h, false);
Processor* p = makeProcessor(s, h, 0, false);
// todo: currently, the compiler cannot compile code with jumps or
// calls spanning more than the maximum size of an immediate value

View File

@ -1941,7 +1941,7 @@ main(int ac, char** av)
local::usageAndExit(av[0]);
}
System* system = makeSystem(0);
System* system = makeSystem();
class MyAllocator: public Allocator {
public:

View File

@ -11,14 +11,14 @@
#include <stdio.h>
#include "avian/common.h"
#include <avian/vm/heap/heap.h>
#include <avian/vm/system/system.h>
#include <avian/heap/heap.h>
#include <avian/system/system.h>
#include "avian/target.h"
#include <avian/vm/codegen/assembler.h>
#include <avian/vm/codegen/architecture.h>
#include <avian/vm/codegen/targets.h>
#include <avian/vm/codegen/lir.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/architecture.h>
#include <avian/codegen/targets.h>
#include <avian/codegen/lir.h>
#include "test-harness.h"
@ -33,7 +33,7 @@ public:
Architecture* arch;
BasicEnv():
s(makeSystem(0)),
s(makeSystem()),
heap(makeHeap(s, 32 * 1024)),
arch(makeArchitectureNative(s, true))
{

View File

@ -10,7 +10,7 @@
#include <stdio.h>
#include <avian/vm/codegen/registers.h>
#include <avian/codegen/registers.h>
#include "test-harness.h"