diff --git a/api/fn.hpp b/api/fn.hpp index 3db522f5d..e1e19423b 100644 --- a/api/fn.hpp +++ b/api/fn.hpp @@ -9,17 +9,9 @@ #include #include -#ifdef OS_WINDOWS -#include -#else -#include -#include -#endif - #include "types.hpp" #include "error.hpp" #include "panic.hpp" -#include "platform.hpp" #include "ptr.hpp" #define __JULE_CO_SPAWN(ROUTINE) \ @@ -35,102 +27,20 @@ namespace jule { - // Anonymous function / closure wrapper of JuleC. - template - struct Fn2 - { - public: - Ret (*f)(jule::Ptr, Args...); - jule::Ptr ctx; // Closure ctx. - void (*ctxHandler)(jule::Ptr &alloc) = nullptr; - - Fn2(void) = default; - Fn2(const Fn2 &) = default; - Fn2(std::nullptr_t) noexcept : Fn2() {} - - Fn2(Ret (*f)(jule::Ptr, Args...)) noexcept - { - this->f = f; - } - - ~Fn2(void) noexcept - { - this->f = nullptr; - if (this->ctxHandler) - { - this->ctxHandler(this->ctx); - this->ctxHandler = nullptr; - this->ctx.ref = nullptr; // Disable GC for allocation. - this->ctx = nullptr; // Assign to nullptr safely. - } - } - - template - Ret call( -#ifndef __JULE_ENABLE__PRODUCTION - const char *file, -#endif - Args... args) - { -#ifndef __JULE_DISABLE__SAFETY - if (this->f == nullptr) -#ifndef __JULE_ENABLE__PRODUCTION - jule::panic((std::string(__JULE_ERROR__INVALID_MEMORY) + "\nfile: ") + file); -#else - jule::panic(__JULE_ERROR__INVALID_MEMORY); -#endif // PRODUCTION -#endif // SAFETY - return this->f(this->ctx, args...); - } - - inline auto operator()(Args... args) - { -#ifndef __JULE_ENABLE__PRODUCTION - return this->call("/api/fn.hpp", args...); -#else - return this->call(args...); -#endif - } - - inline Fn2 &operator=(std::nullptr_t) noexcept - { - this->f = nullptr; - return *this; - } - - constexpr jule::Bool operator==(std::nullptr_t) const noexcept - { - return this->f == nullptr; - } - - constexpr jule::Bool operator!=(std::nullptr_t) const noexcept - { - return !this->operator==(nullptr); - } - - friend std::ostream &operator<<(std::ostream &stream, - const Fn2 &f) noexcept - { - if (f == nullptr) - return (stream << ""); - return (stream << (void *)f.f); - } - }; - // Anonymous function / closure wrapper of JuleC. template struct Fn { public: - Ret (*f)(Args...); + Ret (*f)(jule::Ptr, Args...); jule::Ptr ctx; // Closure ctx. void (*ctxHandler)(jule::Ptr &alloc) = nullptr; Fn(void) = default; Fn(const Fn &) = default; - Fn(std::nullptr_t) : Fn() {} + Fn(std::nullptr_t) noexcept : Fn() {} - Fn(Ret (*f)(Args...)) noexcept + Fn(Ret (*f)(jule::Ptr, Args...)) noexcept { this->f = f; } @@ -143,7 +53,7 @@ namespace jule this->ctxHandler(this->ctx); this->ctxHandler = nullptr; this->ctx.ref = nullptr; // Disable GC for allocation. - this->ctx = nullptr; // Assign as nullptr safely. + this->ctx = nullptr; // Assign to nullptr safely. } } @@ -162,7 +72,7 @@ namespace jule jule::panic(__JULE_ERROR__INVALID_MEMORY); #endif // PRODUCTION #endif // SAFETY - return this->f(args...); + return this->f(this->ctx, args...); } inline auto operator()(Args... args) @@ -199,168 +109,15 @@ namespace jule } }; - template - jule::Fn2 __new_closure2(void *fn, jule::Ptr ctx, void (*ctxHandler)(jule::Ptr &)) noexcept - { - jule::Fn2 fn2((Ret(*)(jule::Ptr, Args...))fn); - fn2.ctx = std::move(ctx); - fn2.ctxHandler = ctxHandler; - return fn2; - } - - static jule::Uint __page_size = __JULE_ASSUMED_PAGE_SIZE; - -#if defined(ARCH_AMD64) - static const char __closure_thunk[] = { - 0xF3, 0x44, 0x0F, 0x7E, 0x3D, 0xF7, 0xBF, 0xFF, 0xFF, // movq xmm15, QWORD PTR [rip - userdata] - 0xFF, 0x25, 0xF9, 0xBF, 0xFF, 0xFF, // jmp QWORD PTR [rip - fn] - }; - static char __closure_get_ctx_bytes[] = { - 0x66, 0x4C, 0x0F, 0x7E, 0xF8, // movq rax, xmm15 - 0xC3, // ret - }; -#elif defined(ARCH_I386) - static char __closure_thunk[] = { - 0xe8, 0x00, 0x00, 0x00, 0x00, // call here - // here: - 0x59, // pop ecx - 0x66, 0x0F, 0x6E, 0xF9, // movd xmm7, ecx - 0xff, 0xA1, 0xff, 0xbf, 0xff, 0xff, // jmp DWORD PTR [ecx - 0x4001] # - }; - static char __closure_get_ctx_bytes[] = { - 0x66, 0x0F, 0x7E, 0xF8, // movd eax, xmm7 - 0x8B, 0x80, 0xFB, 0xBF, 0xFF, 0xFF, // mov eax, DWORD PTR [eax - 0x4005] - 0xc3, // ret - }; -#elif defined(ARCH_ARM64) - static char __closure_thunk[] = { - 0x11, 0x00, 0xFE, 0x58, // ldr x17, userdata - 0x30, 0x00, 0xFE, 0x58, // ldr x16, fn - 0x00, 0x02, 0x1F, 0xD6, // br x16 - }; - static char __closure_get_ctx_bytes[] = { - 0xE0, 0x03, 0x11, 0xAA, // mov x0, x17 - 0xC0, 0x03, 0x5F, 0xD6, // ret - }; -#endif - - static jule::U8 *__closure_ptr = 0; - static jule::Int __closure_cap = 0; - - static void *(*__closure_get_ctx)(void) = nullptr; - -#ifdef OS_WINDOWS - static SRWLOCK __closure_mtx; - inline void __closure_mtx_init(void) noexcept { InitializeSRWLock(&jule::__closure_mtx); } - inline void __closure_mtx_lock(void) noexcept { AcquireSRWLockExclusive(&jule::__closure_mtx); } - inline void __closure_mtx_unlock(void) noexcept { ReleaseSRWLockExclusive(&jule::__closure_mtx); } -#else - static pthread_mutex_t __closure_mtx; - - inline void __closure_mtx_init(void) noexcept - { - if (pthread_mutex_init(&jule::__closure_mtx, 0) != 0) - jule::panic("closure mutex initialization failed"); - } - - inline void __closure_mtx_lock(void) noexcept - { - if (pthread_mutex_lock(&jule::__closure_mtx) != 0) - jule::panic("closure mutex locking failed"); - } - - inline void __closure_mtx_unlock(void) noexcept - { - if (pthread_mutex_unlock(&jule::__closure_mtx) != 0) - jule::panic("closure mutex unlocking failed"); - } -#endif - - static void __closure_alloc(void) noexcept - { -#ifdef OS_WINDOWS - jule::U8 *p = (jule::U8 *)VirtualAlloc(NULL, jule::__page_size << 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if (!p) - jule::panic(__JULE_ERROR__MEMORY_ALLOCATION_FAILED - "\nruntime: heap allocation failed for closure"); -#else - jule::U8 *p = (jule::U8 *)mmap(0, jule::__page_size << 1, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - if (p == MAP_FAILED) - jule::panic(__JULE_ERROR__MEMORY_ALLOCATION_FAILED - "\nruntime: heap allocation failed for closure"); -#endif - jule::U8 *x = p + jule::__page_size; - jule::Uint rem = jule::__page_size / __JULE_CLOSURE_SIZE; - jule::__closure_ptr = x; - jule::__closure_cap = rem; - while (rem > 0) - { - (void)memcpy(x, jule::__closure_thunk, sizeof(jule::__closure_thunk)); - rem--; - x += __JULE_CLOSURE_SIZE; - } -#ifdef OS_WINDOWS - DWORD temp; - VirtualProtect(jule::__closure_ptr, jule::__page_size, PAGE_EXECUTE_READ, &temp); -#else - (void)mprotect(jule::__closure_ptr, jule::__page_size, PROT_READ | PROT_EXEC); -#endif - } - template jule::Fn __new_closure(void *fn, jule::Ptr ctx, void (*ctxHandler)(jule::Ptr &)) noexcept { - jule::__closure_mtx_lock(); - if (jule::__closure_cap < 1) - jule::__closure_alloc(); - jule::__closure_cap--; - jule::U8 *closure = jule::__closure_ptr; - jule::__closure_ptr += __JULE_CLOSURE_SIZE; - void **ptr = __JULE_CLOSURE_PAGE_PTR(closure); - ptr[0] = ctx; - ptr[1] = fn; - jule::__closure_mtx_unlock(); - Ret (*static_closure)(Args...) = (Ret(*)(Args...))closure; - jule::Fn fn2(static_closure); + jule::Fn fn2((Ret(*)(jule::Ptr, Args...))fn); fn2.ctx = std::move(ctx); fn2.ctxHandler = ctxHandler; - ctx = nullptr; return fn2; } -#ifdef OS_WINDOWS - void __closure_init(void) noexcept - { - SYSTEM_INFO si; - GetNativeSystemInfo(&si); - const uint32_t page_size = si.dwPageSize * (((jule::__page_size - 1) / si.dwPageSize) + 1); - jule::__page_size = page_size; - jule::__closure_alloc(); - DWORD temp; - VirtualProtect(jule::__closure_ptr, page_size, PAGE_READWRITE, &temp); - (void)memcpy(jule::__closure_ptr, jule::__closure_get_ctx_bytes, sizeof(jule::__closure_get_ctx_bytes)); - VirtualProtect(jule::__closure_ptr, page_size, PAGE_EXECUTE_READ, &temp); - jule::__closure_get_ctx = (void *(*)(void))jule::__closure_ptr; - jule::__closure_ptr += __JULE_CLOSURE_SIZE; - jule::__closure_cap--; - } -#else - void __closure_init(void) noexcept - { - jule::__closure_mtx_init(); - uint32_t page_size = sysconf(_SC_PAGESIZE); - // page_size must initialized with relevant expression before multiplication. - page_size *= (((__JULE_ASSUMED_PAGE_SIZE - 1) / page_size) + 1); - jule::__page_size = page_size; - jule::__closure_alloc(); - (void)mprotect(jule::__closure_ptr, page_size, PROT_READ | PROT_WRITE); - (void)memcpy(jule::__closure_ptr, jule::__closure_get_ctx_bytes, sizeof(jule::__closure_get_ctx_bytes)); - (void)mprotect(jule::__closure_ptr, page_size, PROT_READ | PROT_EXEC); - jule::__closure_get_ctx = (void *(*)(void))jule::__closure_ptr; - jule::__closure_ptr += __JULE_CLOSURE_SIZE; - jule::__closure_cap--; - } -#endif } // namespace jule #endif // ifndef __JULE_FN_HPP \ No newline at end of file diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule index 5efb42dc8..fbb8cd982 100644 --- a/src/julec/obj/cxx/expr.jule +++ b/src/julec/obj/cxx/expr.jule @@ -938,7 +938,7 @@ impl exprCoder { fn anonFunc(mut &self, mut m: &AnonFnExprModel) { ident := self.oc.pushAnonFn(m) - self.oc.write("jule::__new_closure2<") + self.oc.write("jule::__new_closure<") self.oc.tc.anonFunc(self.oc.Buf, m.Func) self.oc.write(">((void*)") self.oc.write(ident) diff --git a/src/julec/obj/cxx/type.jule b/src/julec/obj/cxx/type.jule index f91a027ca..585aafcc2 100644 --- a/src/julec/obj/cxx/type.jule +++ b/src/julec/obj/cxx/type.jule @@ -59,7 +59,7 @@ impl typeCoder { const Slice = "jule::Slice" const Trait = "jule::Trait" const Array = "jule::Array" - const Fn = "jule::Fn2" + const Fn = "jule::Fn" const Bool = "jule::Bool" const Int = "jule::Int" const Uintptr = "jule::Uintptr"