[vmkit-commits] [vmkit] r199010 - Transparent trampoline for the stack (important for libunwind)

Gael Thomas gael.thomas at lip6.fr
Sat Jan 11 07:22:13 PST 2014


Author: gthomas
Date: Sat Jan 11 09:22:13 2014
New Revision: 199010

URL: http://llvm.org/viewvc/llvm-project?rev=199010&view=rev
Log:
Transparent trampoline for the stack (important for libunwind)

Modified:
    vmkit/branches/mcjit/include/j3/j3arch-dep.h
    vmkit/branches/mcjit/include/j3/j3thread.h
    vmkit/branches/mcjit/include/j3/j3trampoline.h
    vmkit/branches/mcjit/include/vmkit/allocator.h
    vmkit/branches/mcjit/lib/j3/vm/j3.cc
    vmkit/branches/mcjit/lib/j3/vm/j3arch-dep.s
    vmkit/branches/mcjit/lib/j3/vm/j3trampoline.cc
    vmkit/branches/mcjit/lib/vmkit/allocator.cc
    vmkit/branches/mcjit/lib/vmkit/thread.cc

Modified: vmkit/branches/mcjit/include/j3/j3arch-dep.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3arch-dep.h?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3arch-dep.h (original)
+++ vmkit/branches/mcjit/include/j3/j3arch-dep.h Sat Jan 11 09:22:13 2014
@@ -1,6 +1,13 @@
 #ifndef _J3_ARCH_DEP_H_
 #define _J3_ARCH_DEP_H_
 
-#define TRAMPOLINE_SAVE_ZONE (8*16 + 6*8 + 2*8)
+namespace j3 {
+	class J3Method;
+
+	class J3TrampolineArg {
+		uint64_t  savee[8*2 + 6 + 2]; 
+		/* xmm0 - xmm7 + %rdi/%rsi/%rdx/%rcx/%r8/%r9 + %rbp, %rsp */
+	};
+}
 
 #endif

Modified: vmkit/branches/mcjit/include/j3/j3thread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3thread.h?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3thread.h (original)
+++ vmkit/branches/mcjit/include/j3/j3thread.h Sat Jan 11 09:22:13 2014
@@ -17,7 +17,6 @@ namespace j3 {
 	class J3Thread : public vmkit::Thread {
 		friend class J3Monitor;
 		friend class J3CodeGen;
-		friend class J3Trampoline;
 
 		static const uint32_t gepInterfaceMethodIndex = 1;
 		uint32_t              _interfaceMethodIndex;
@@ -28,7 +27,9 @@ namespace j3 {
 		J3LocalReferences          _localReferences;
 		J3ObjectHandle*            _pendingException;
 		J3ObjectHandle             _javaThread;
-		char                       _trampolineSaveZone[TRAMPOLINE_SAVE_ZONE];
+	public:
+		J3TrampolineArg            _trampolineArg;
+	private:
 
 		virtual void run();
 		static void doRun();

Modified: vmkit/branches/mcjit/include/j3/j3trampoline.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3trampoline.h?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3trampoline.h (original)
+++ vmkit/branches/mcjit/include/j3/j3trampoline.h Sat Jan 11 09:22:13 2014
@@ -3,13 +3,10 @@
 
 #include <stdint.h>
 
-extern "C" uintptr_t  trampoline_mask;
-extern "C" uintptr_t  trampoline_offset;
 extern "C" char       trampoline_generic;
 extern "C" char       trampoline_generic_method;
 extern "C" char       trampoline_generic_resolver; 
 extern "C" char       trampoline_generic_end;
-extern "C" char       trampoline_save;
 extern "C" void       trampoline_restart(void* ptr, void* saveZone);
 
 namespace vmkit {
@@ -21,9 +18,9 @@ namespace j3 {
 	class J3Object;
 
 	class J3Trampoline {
-		static void* interfaceTrampoline(J3Object* obj);
-		static void* staticTrampoline(J3Object* obj, J3Method* ref);
-		static void* virtualTrampoline(J3Object* obj, J3Method* ref);
+		static void  interfaceTrampoline(J3Object* obj);
+		static void  staticTrampoline(J3Object* obj, J3Method* ref);
+		static void  virtualTrampoline(J3Object* obj, J3Method* ref);
 
 		static void* buildTrampoline(vmkit::BumpAllocator* allocator, J3Method* method, void* tra);
 	public:

Modified: vmkit/branches/mcjit/include/vmkit/allocator.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/vmkit/allocator.h?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/vmkit/allocator.h (original)
+++ vmkit/branches/mcjit/include/vmkit/allocator.h Sat Jan 11 09:22:13 2014
@@ -119,29 +119,26 @@ namespace vmkit {
 	class ThreadAllocator {
 		static const uint32_t refill = 128;
 
-		static ThreadAllocator* _allocator;
+		static pthread_mutex_t     mutex;
+		static uintptr_t           baseStack;
+		static uintptr_t           topStack;
+		static uintptr_t           _magic;
+		static std::vector<void*>* spaces;
+		static std::vector<void*>* freeThreads;
 
-		pthread_mutex_t       mutex;
-		std::vector<void*>    spaces;
-		std::vector<void*>    freeThreads;
-		uintptr_t             baseStack;
-		uintptr_t             topStack;
-
-		ThreadAllocator(uintptr_t minThreadStruct, uintptr_t minFullSize);
 	public:
 		static void initialize(uintptr_t minThreadStruct, uintptr_t minFullSize);
-		static ThreadAllocator* allocator() { return _allocator; }
 
-		void* allocate();
-		void  release(void* thread);
+		static void* allocate();
+		static void  release(void* thread);
 
-		void*     alternateStackAddr(void* thread);
-		size_t    alternateStackSize(void* thread); 
+		static void*     alternateStackAddr(void* thread);
+		static size_t    alternateStackSize(void* thread); 
 
-		void*     stackAddr(void* thread);
-		size_t    stackSize(void* thread); 
+		static void*     stackAddr(void* thread);
+		static size_t    stackSize(void* thread); 
 
-		uintptr_t magic() { return -topStack; }
+		static uintptr_t magic() { return _magic; }
 	};
 } // end namespace vmkit
 

Modified: vmkit/branches/mcjit/lib/j3/vm/j3.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3.cc?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3.cc Sat Jan 11 09:22:13 2014
@@ -70,7 +70,6 @@ void J3::start(int argc, char** argv) {
 	_options.process(argc, argv);
 
 	vmkit::ThreadAllocator::initialize(sizeof(J3Thread), options()->stackSize);
-	J3Trampoline::initialize(vmkit::Thread::getThreadMask());
 
 	J3Thread* thread = new J3ThreadBootstrap(this);
 

Modified: vmkit/branches/mcjit/lib/j3/vm/j3arch-dep.s
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3arch-dep.s?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3arch-dep.s (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3arch-dep.s Sat Jan 11 09:22:13 2014
@@ -1,44 +1,27 @@
 	.section	__DATA,__data
-	.globl	_trampoline_mask, _trampoline_offset
+	.globl _trampoline_offset, __ZN5vmkit15ThreadAllocator6_magicE
 	.globl _trampoline_generic, _trampoline_generic_method, _trampoline_generic_resolver, _trampoline_generic_end
 	
-_trampoline_mask:
-	.quad	0
-_trampoline_offset:
-	.quad 0
-	
 _trampoline_generic:
-	.byte  0x48, 0xb8     			/* mov _trampoline_save, %rax (absolute adressing, what is the mnemonic?) */
-	.quad  _trampoline_save
+	movabsq $_trampoline_save, %rax   /* absolute to avoid any problem of relocation */
 	callq		*%rax
-	mov			%rsp,  184(%rax)
-	.byte 0x48, 0xbe  					/* mov _trampoline_generic_method, %rsi */
+	.byte 0x48, 0xbe  					      /* movabsq _trampoline_generic_method, %rsi (i.e., replace second arg) */
 _trampoline_generic_method:
 	.quad 0
-	.byte 0x48, 0xb8  					/* mov _trampoline_generic_resolver, %rax */
+	.byte 0x48, 0xb8  					      /* movabsq _trampoline_generic_resolver, %rax */
 _trampoline_generic_resolver:	
 	.quad 0
 	jmpq *%rax
 _trampoline_generic_end:	
 
 	.section	__TEXT,__text,regular,pure_instructions
-	.globl _trampoline_save, _trampoline_restart
+	.globl _trampoline_restart
 	.align	4
 	
-	/* compute the adress of the save zone area */
-	/* and return the adress in %rax */
-_trampoline_get_save_zone:	
-	push 		%rbx
-	mov 		%rsp, %rax
-	movq 		_trampoline_mask(%rip), %rbx
-	and 		%rbx, %rax
-	movq 		_trampoline_offset(%rip), %rbx
-	add			%rbx, %rax
-	pop			%rbx
-	ret
-	
 _trampoline_save:
-	call    _trampoline_get_save_zone
+	mov 		%rsp, %rax
+	and 		__ZN5vmkit15ThreadAllocator6_magicE(%rip), %rax
+	add 		_trampoline_offset(%rip), %rax
 
 	mov 		%xmm0, 0(%rax)
 	mov 		%xmm1, 16(%rax)
@@ -55,11 +38,14 @@ _trampoline_save:
 	mov 		%r8,   160(%rax)
 	mov 		%r9,   168(%rax)
 	mov 		%rbp,  176(%rax)
-
+	mov     %rsp,  184(%rax)
+	addq		$8, 184(%rax)    /* my own call :) */
+	
 	ret
 
-	/* %rdi contains the function */
-	/* %rsi contains the save zone area */
+	/* void trampoline_restart(void* ptr, void* saveZone); */
+	/* %rsi: saveZone */
+	/* %rdi: pointer to function */
 _trampoline_restart:
 	mov     %rdi, %rax
 

Modified: vmkit/branches/mcjit/lib/j3/vm/j3trampoline.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3trampoline.cc?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3trampoline.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3trampoline.cc Sat Jan 11 09:22:13 2014
@@ -8,8 +8,10 @@
 
 using namespace j3;
 
-void* J3Trampoline::interfaceTrampoline(J3Object* obj) {
-	J3::internalError("implement me it");
+extern "C" uintptr_t trampoline_offset = (uint64_t)&((J3Thread*)0)->_trampolineArg;
+
+void J3Trampoline::interfaceTrampoline(J3Object* obj) {
+	J3TrampolineArg arg = J3Thread::get()->_trampolineArg;
 	J3ObjectHandle* prev = J3Thread::get()->tell();
 	J3ObjectHandle* handle = J3Thread::get()->push(obj);
 	J3ObjectType* type = obj->vt()->type()->asObjectType();
@@ -30,20 +32,17 @@ void* J3Trampoline::interfaceTrampoline(
 
 	J3Thread::get()->restore(prev);
 
-	return res;
+	trampoline_restart(res, &arg);
 }
 
-void* J3Trampoline::staticTrampoline(J3Object* obj, J3Method* target) {
-	char saveZone[TRAMPOLINE_SAVE_ZONE];
-	memcpy(saveZone, J3Thread::get()->_trampolineSaveZone, TRAMPOLINE_SAVE_ZONE);
+void J3Trampoline::staticTrampoline(J3Object* obj, J3Method* target) {
+	J3TrampolineArg arg = J3Thread::get()->_trampolineArg;
 	target->ensureCompiled(0);
-	//return target->fnPtr();
-	trampoline_restart(target->fnPtr(), saveZone);
-	return 0;
+	trampoline_restart(target->fnPtr(), &arg);
 }
 	
-void* J3Trampoline::virtualTrampoline(J3Object* obj, J3Method* target) {
-	J3::internalError("implement me vt");
+void J3Trampoline::virtualTrampoline(J3Object* obj, J3Method* target) {
+	J3TrampolineArg arg = J3Thread::get()->_trampolineArg;
 	J3ObjectHandle* prev = J3Thread::get()->tell();
 	J3ObjectHandle* handle = J3Thread::get()->push(obj);
 	J3ObjectType* cl = handle->vt()->type()->asObjectType();
@@ -55,7 +54,7 @@ void* J3Trampoline::virtualTrampoline(J3
 
 	J3Thread::get()->restore(prev);
 
-	return res;
+	trampoline_restart(res, &arg);
 }
 
 void* J3Trampoline::buildTrampoline(vmkit::BumpAllocator* allocator, J3Method* m, void* tra) {	
@@ -82,9 +81,3 @@ void* J3Trampoline::buildInterfaceTrampo
 	return buildTrampoline(allocator, 0, (void*)interfaceTrampoline);
 }
 
-void J3Trampoline::initialize(uintptr_t mask) {
-	J3Thread* thread = J3Thread::get();
-	trampoline_mask = mask;
-	trampoline_offset = (uintptr_t)&thread->_trampolineSaveZone - (uintptr_t)thread;
-}
-

Modified: vmkit/branches/mcjit/lib/vmkit/allocator.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/vmkit/allocator.cc?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/vmkit/allocator.cc (original)
+++ vmkit/branches/mcjit/lib/vmkit/allocator.cc Sat Jan 11 09:22:13 2014
@@ -8,7 +8,12 @@
 
 using namespace vmkit;
 
-ThreadAllocator* ThreadAllocator::_allocator = 0;
+pthread_mutex_t     ThreadAllocator::mutex;
+uintptr_t           ThreadAllocator::baseStack = 0;
+uintptr_t           ThreadAllocator::topStack = 0;
+uintptr_t           ThreadAllocator::_magic = 0;
+std::vector<void*>* ThreadAllocator::spaces = 0;
+std::vector<void*>* ThreadAllocator::freeThreads = 0;
 
 void* BumpAllocator::operator new(size_t n) {
 	return (void*)((uintptr_t)map(bucketSize) + sizeof(BumpAllocatorNode));
@@ -89,10 +94,15 @@ void PermanentObject::operator delete[](
 	Thread::get()->vm()->internalError("should not happen");
 }
 
-ThreadAllocator::ThreadAllocator(uintptr_t minThreadStruct, uintptr_t minFullSize) {
+void ThreadAllocator::initialize(uintptr_t minThreadStruct, uintptr_t minFullSize) {
+	if(spaces)
+		VMKit::internalError("thread allocation system is already initialized");
+	spaces = new std::vector<void*>();
+	freeThreads = new std::vector<void*>();
+
 	pthread_mutex_init(&mutex, 0);
-	spaces.reserve(1);
-	freeThreads.reserve(refill);
+	spaces->reserve(1);
+	freeThreads->reserve(refill);
 
 	minThreadStruct = ((minThreadStruct - 1) & -PAGE_SIZE) + PAGE_SIZE;
 	baseStack = minThreadStruct + PAGE_SIZE;
@@ -102,19 +112,12 @@ ThreadAllocator::ThreadAllocator(uintptr
 		minFullSize = min;
 
 	topStack = 1L << (__builtin_clzl(0) - __builtin_clzl(minFullSize-1));
-}
-
-void ThreadAllocator::initialize(uintptr_t minThreadStruct, uintptr_t minFullSize) {
-	if(_allocator) {
-		fprintf(stderr, "Never try to modify the thread structure layout dynamically\n");
-		abort();
-	}
-	_allocator = new ThreadAllocator(minThreadStruct, minFullSize);
+	_magic = -topStack;
 }
 
 void* ThreadAllocator::allocate() {
 	pthread_mutex_lock(&mutex);
-	if(!freeThreads.size()) {
+	if(!freeThreads->size()) {
 		void* space = mmap(0, topStack*refill, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
 
 		if(space == MAP_FAILED) {
@@ -122,27 +125,27 @@ void* ThreadAllocator::allocate() {
 			abort();
 		}
 
-		spaces.push_back(space);
+		spaces->push_back(space);
 
 		uintptr_t base = (((uintptr_t)space - 1) & -topStack) + topStack;
 		uint32_t n = (base == (uintptr_t)space) ? refill : (refill - 1);
 
 		for(uint32_t i=0; i<n; i++) {
 			mprotect((void*)(base + baseStack), PROT_NONE, PAGE_SIZE);
-			freeThreads.push_back((void*)base);
+			freeThreads->push_back((void*)base);
 			base += topStack;
 		}
 	}
 
-	void* res = freeThreads.back();
-	freeThreads.pop_back();
+	void* res = freeThreads->back();
+	freeThreads->pop_back();
 	pthread_mutex_unlock(&mutex);
 	return res;
 }
 
 void ThreadAllocator::release(void* thread) {
 	pthread_mutex_lock(&mutex);
-	freeThreads.push_back(thread);
+	freeThreads->push_back(thread);
 	pthread_mutex_unlock(&mutex);
 }
 

Modified: vmkit/branches/mcjit/lib/vmkit/thread.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/vmkit/thread.cc?rev=199010&r1=199009&r2=199010&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/vmkit/thread.cc (original)
+++ vmkit/branches/mcjit/lib/vmkit/thread.cc Sat Jan 11 09:22:13 2014
@@ -13,11 +13,11 @@ void Thread::sigsegvHandler(int n, sigin
 }
 
 void* Thread::operator new(size_t n) {
-	return ThreadAllocator::allocator()->allocate();
+	return ThreadAllocator::allocate();
 }
 
 void Thread::operator delete(void* p) {
-	ThreadAllocator::allocator()->release(p);
+	ThreadAllocator::release(p);
 }
 
 Thread* Thread::get() {
@@ -29,7 +29,7 @@ Thread* Thread::get(void* ptr) {
 }
 
 uintptr_t Thread::getThreadMask() {
-	return ThreadAllocator::allocator()->magic();
+	return ThreadAllocator::magic();
 }
 
 void Thread::registerSignalInternal(int n, sa_action_t handler, bool altStack) {
@@ -58,9 +58,9 @@ void* Thread::doRun(void* _thread) {
   // Set the alternate stack as the second page of the thread's
   // stack.
   stack_t st;
-  st.ss_sp = ThreadAllocator::allocator()->alternateStackAddr(thread);
+  st.ss_sp = ThreadAllocator::alternateStackAddr(thread);
   st.ss_flags = 0;
-  st.ss_size = ThreadAllocator::allocator()->alternateStackSize(thread);
+  st.ss_size = ThreadAllocator::alternateStackSize(thread);
   sigaltstack(&st, NULL);
 
 	thread->registerSignalInternal(SIGSEGV, sigsegvHandler, 1);
@@ -74,7 +74,7 @@ void Thread::start() {
 	pthread_attr_t attr;
 
 	pthread_attr_init(&attr);
-	pthread_attr_setstack(&attr, ThreadAllocator::allocator()->stackAddr(this), ThreadAllocator::allocator()->stackSize(this));
+	pthread_attr_setstack(&attr, ThreadAllocator::stackAddr(this), ThreadAllocator::stackSize(this));
 
 	pthread_create(&_tid, &attr, doRun, this);
 





More information about the vmkit-commits mailing list