cemu
载入中...
搜索中...
未找到
obj.h
浏览该文件的文档.
1
59#ifndef __OBJ_H_
60#define __OBJ_H_
61
62#ifdef __cplusplus
63 #error "C++ header is not supported, please use native OOP instead!"
64#endif
65
66#include <stdint.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70
71#ifndef __EXPAND
72#define __EXPAND(x) x
73#endif
74
75#if defined(__unix__) || defined(__unix) || defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
76#include <sys/mman.h>
77#include <sys/user.h>
78#define __OBJ_ACTIV(ptr, size) \
79 (mprotect((void *)(((size_t)ptr >> PAGE_SHIFT) << PAGE_SHIFT), size, PROT_READ | PROT_EXEC | PROT_WRITE) == 0)
80#elif defined(_WIN32)
81#if defined (_MSC_VER)
82#pragma warning(disable : 4996)
83#pragma comment(lib, "kernel32.lib")
84#if ((defined(DEBUG) || defined(_DEBUG)) && _MSC_VER >= 1915)
85#pragma message ("warning: On Visual Studio 2017 15.8+, please disable Just My Code debugging!")
86#endif
87#endif
88#if !(defined(_WINDOWS_) || defined(_INC_WINDOWS) || defined(_WINDOWS_H) || defined(_MEMORYAPI_H_))
89extern int __stdcall VirtualProtect(void *addr, size_t size, unsigned long newprot, unsigned long *oldprot);
90#endif
91#ifndef PAGE_EXECUTE_READWRITE
92#define PAGE_EXECUTE_READWRITE 0x40
93#endif
94#define __OBJ_ACTIV(ptr, size) \
95 (VirtualProtect(ptr, size, PAGE_EXECUTE_READWRITE, &((unsigned long){ 0 })) != 0)
96#else
97#error "This OS is not supported!"
98#endif
99
100#if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
101#define __OBJ_X64 1
102#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
103#define __OBJ_X86 1
104#else
105#error This architecture is not supported!
106#endif
107
108#define __OBJ_ERR(...) \
109 do { \
110 fprintf(stderr, "[obj.h] error: "); \
111 fprintf(stderr, __VA_ARGS__); \
112 fprintf(stderr, "\n"); \
113 } while (0)
114
115#define __OBJ_MAXPHSIZE 1024
116#if __OBJ_X64
117#define __OBJ_CLOFNNUM 0x58ffffbffdffffafULL
118#elif __OBJ_X86
119#define __OBJ_CLOFNNUM 0x58ffffbfU
120#endif
121
122static void *__OBJ_clofn(void *prototype, size_t *phsize, void *data) {
123
124 uint8_t *code;
125 size_t offset;
126 size_t ihsize;
127
128 offset = *phsize;
129 if (offset == 0) {
130 for (; offset < __OBJ_MAXPHSIZE; offset++) {
131 if (*(size_t *)((uintptr_t)prototype + offset) == (size_t)__OBJ_CLOFNNUM) {
132 if (*phsize == 0) *phsize = offset;
133 goto _mk;
134 }
135 }
136
137 fprintf(stderr, "could't find closure declaration at prototype function (%p)!", prototype);
138 return NULL;
139 }
140
141_mk:;
142#pragma pack(push, 1)
143#if __OBJ_X64
144 // push rax
145 // mov rax, addr
146 // jmp rax
147 static struct {
148 uintptr_t data;
149 uint8_t push_rax;
150 uint8_t mov_rax[2];
151 uintptr_t addr;
152 uint8_t jmp_rax[2];
153 } asmc = {
154 .push_rax = 0x50,
155 .mov_rax = { 0x48, 0xB8 },
156 .jmp_rax = { 0xFF, 0xE0 }
157 };
158 //ihsize = offset + sizeof(void *) * 2 + 5;
159#elif __OBJ_X86
160 // jmp addr
161 static struct {
162 uintptr_t data;
163 uint8_t jmp;
164 uintptr_t addr;
165 } asmc = {
166 .jmp = 0xE9
167 };
168 //ihsize = offset + sizeof(void *) * 2 + 1;
169#endif
170#pragma pack(pop)
171
172 ihsize = offset + sizeof(asmc);
173 code = (uint8_t *)malloc(ihsize);
174
175 if (!__OBJ_ACTIV(code, ihsize)) {
176 __OBJ_ERR("could't change memory type of C.malloc allocated!");
177 free(code);
178 return NULL;
179 }
180
181#if __OBJ_X64
182 asmc.addr = (uintptr_t)prototype + offset + sizeof(uintptr_t) - 1;
183#elif __OBJ_X86
184 asmc.addr = ((uintptr_t)prototype + offset + sizeof(uintptr_t)) - ((uintptr_t)code + ihsize);
185#endif
186
187 asmc.data = (uintptr_t)data;
188 memcpy(code, prototype, offset);
189 memcpy(code + offset, &asmc, sizeof(asmc));
190
191 return (void *)code;
192}
193
194#if defined(class)
195#undef class
196#endif
197
198#if defined(classdef)
199#undef classdef
200#endif
201
202#if defined(public)
203#undef public
204#endif
205
206#if defined(private)
207#undef private
208#endif
209
210#if defined(new)
211#undef new
212#endif
213
214#if defined(extend)
215#undef extend
216#endif
217
218#if defined(ctor)
219#undef ctor
220#endif
221
222#if defined(dtor)
223#undef dtor
224#endif
225
226// Set root name, default is "self"
227// For "this", #define obj_use this
228#if defined(obj_use)
229#define __OBJ_ROOT obj_use
230#else
231#define __OBJ_ROOT self
232#endif
233
235 void *ptr;
236 char sub;
237};
238
240 int count;
241 int space;
242 struct __OBJ_entry *entries;
243};
244
245// Class base
247 void *(*alloc)(size_t);
248 void *(*realloc)(void *, size_t);
249 void (*free)(void *);
250 void (*release)();
251 struct {
252 struct __OBJ_pool *p;
253 void *(*d)(void *);
254 } reserved;
255};
256
257static struct __OBJ_pool *__OBJ_pool_create() {
258 struct __OBJ_pool *p = malloc(sizeof(struct __OBJ_pool));
259 p->count = 0;
260 p->space = 0;
261 p->entries = NULL;
262 return p;
263}
264
265static void __OBJ_pool_destroy(struct __OBJ_pool *p) {
266 if (p == NULL) return;
267 if (p->space > 0) {
268 for (int i = 0; i < p->space; i++) {
269 free(p->entries[i].ptr);
270 }
271 free(p->entries);
272 }
273 free(p);
274}
275
276static struct __OBJ_entry *__OBJ_pool_find(struct __OBJ_entry entries[], int space, void *ptr) {
277 size_t index = (uintptr_t)ptr % (space - 1);
278 struct __OBJ_entry *tombstone = NULL;
279
280 for (;;) {
281 struct __OBJ_entry *entry = &entries[index];
282
283 if (entry->ptr == NULL) {
284 if (!entry->sub) {
285 return tombstone != NULL ? tombstone : entry;
286 }
287 else {
288 if (tombstone == NULL) tombstone = entry;
289 }
290 }
291 else if (entry->ptr == ptr) {
292 return entry;
293 }
294
295 index = (index + 1) % space;
296 }
297}
298
299static void __OBJ_pool_resize(struct __OBJ_pool *p, int space) {
300 struct __OBJ_entry *entries = malloc(space * sizeof(struct __OBJ_entry));
301 memset(entries, '\0', space * sizeof(struct __OBJ_entry));
302
303 p->count = 0;
304 for (int i = 0; i < p->space; i++) {
305 struct __OBJ_entry *entry = &p->entries[i];
306 if (entry->ptr == NULL) continue;
307
308 *__OBJ_pool_find(entries, space, entry->ptr) = *entry;
309 p->count++;
310 }
311
312 free(p->entries);
313 p->space = space;
314 p->entries = entries;
315}
316
317static void *__OBJ_pool_add(struct __OBJ_pool *p, void *ptr) {
318 if (ptr == NULL) return NULL;
319
320 int space = p->space;
321 if (p->count >= space * 0.75) {
322 __OBJ_pool_resize(p, space < 8 ? 8 : space * 2);
323 }
324
325 struct __OBJ_entry *entry = __OBJ_pool_find(p->entries, p->space, ptr);
326 if (entry->ptr == NULL) {
327 p->count++;
328 }
329
330 return entry->ptr = ptr;
331}
332
333static int __OBJ_pool_remove(struct __OBJ_pool *p, void *ptr) {
334 if (p->count == 0 || ptr == NULL) return 0;
335 int space = p->space;
336
337 if (space > 8 && p->count < space / 2) {
338 __OBJ_pool_resize(p, space /= 2);
339 }
340
341 struct __OBJ_entry *entry = __OBJ_pool_find(p->entries, space, ptr);
342 if (entry->ptr == NULL) return 0;
343
344 entry->sub = 1;
345 entry->ptr = NULL;
346 p->count--;
347 return 1;
348}
349
350static void *__OBJ_pool_alloc(struct __OBJ_pool *p, size_t size) {
351 void *ptr = malloc(size);
352 return __OBJ_pool_add(p, ptr);
353}
354
355static void *__OBJ_pool_realloc(struct __OBJ_pool *p, void *ptr, size_t size) {
356 __OBJ_pool_remove(p, ptr);
357 ptr = realloc(ptr, size);
358 return __OBJ_pool_add(p, ptr);
359}
360
361static void __OBJ_pool_free(struct __OBJ_pool *p, void *ptr) {
362 if (__OBJ_pool_remove(p, ptr)) free(ptr);
363}
364
365static void __OBJ_freebase(struct __OBJ_base *base) {
366 free(base->alloc);
367 free(base->realloc);
368 free(base->free);
369 free(base->release);
370 __OBJ_pool_destroy(base->reserved.p);
371 free(base);
372}
373
374// base::alloc(size_t)
375static size_t __OBJ_alloc_s = 0;
376static void *__OBJ_alloc(size_t size) {
377 volatile size_t closn = __OBJ_CLOFNNUM;
378 struct __OBJ_base *base = (struct __OBJ_base *)closn;
379
380 return __OBJ_pool_alloc(base->reserved.p, size);
381}
382
383// base::realloc(void *, size_t)
384static size_t __OBJ_realloc_s = 0;
385static void *__OBJ_realloc(void *ptr, size_t size) {
386 volatile size_t closn = __OBJ_CLOFNNUM;
387 struct __OBJ_base *base = (struct __OBJ_base *)closn;
388
389 return __OBJ_pool_realloc(base->reserved.p, ptr, size);
390}
391
392// base::free(void *)
393static size_t __OBJ_free_s = 0;
394static void __OBJ_free(void *ptr) {
395 volatile size_t closn = __OBJ_CLOFNNUM;
396 struct __OBJ_base *base = (struct __OBJ_base *)closn;
397
398 __OBJ_pool_free(base->reserved.p, ptr);
399}
400
401// base::release()
402static size_t __OBJ_release_s = 0;
403static void __OBJ_release() {
404 volatile size_t closn = __OBJ_CLOFNNUM;
405 struct __OBJ_base *base = (struct __OBJ_base *)closn;
406
407 void (*release)() = base->release;
408 base->release = NULL;
409
410 if (base->reserved.d != NULL) {
411 base->reserved.d(base);
412 }
413
414 base->release = release;
415 __OBJ_freebase(base);
416}
417
418// Some private macros
419#define __OBJ_PUB(n) struct __OBJ__##n
420#define __OBJ_PRV(n) struct __OBJ_PRV_##n
421#define __OBJ_INF(n) struct __OBJ_INF_##n
422
423#define __OBJ_M(n, f) __OBJ__##n##_##f
424#define __OBJ_S(n, f) __OBJ_S_##n##_##f
425#define __OBJ_H(n, f) __OBJ_H_##n##_##f
426
427#define __OBJ_CON(n) __OBJ_C_##n
428#define __OBJ_DES(n) __OBJ_D_##n
429
430// Public fields
431#define public(...) __VA_ARGS__
432// Private fields
433#define private(...) __VA_ARGS__
434
435// Extend a class
436#define extend(super_name) \
437 __OBJ_PUB(super_name) super_name
438
439// Class declaration
440#define classdef(name) \
441 typedef __OBJ_PUB(name) *name
442
443// Class definition
444#define class(name, public_members, ...) \
445 __OBJ_PUB(name) { \
446 struct __OBJ_base base; \
447 struct { char : 0; public_members }; \
448 }; \
449 __OBJ_PRV(name) { \
450 struct __OBJ_base base; \
451 struct { char : 0; public_members }; \
452 struct { char : 0; __VA_ARGS__ }; \
453 }
454
455// Constructor declaration
456#define ctor(class_name) \
457 __OBJ_PUB(class_name) *class_name##_new
458
459// Destructor declaration
460#define dtor(class_name) \
461 void __OBJ_DES(class_name)(__OBJ_PRV(class_name) *__OBJ_ROOT)
462
463// Method declaration
464#define method(class_name, return_type, name) \
465 static size_t __OBJ_S(class_name, name); \
466 static return_type __OBJ_M(class_name, name)
467
468// New instance
469#define new(class_name) \
470 class_name##_new
471
472// Prepare self
473#define obj_prepare(class_name) \
474 volatile size_t __closn = (size_t)__OBJ_CLOFNNUM; \
475 __OBJ_PRV(class_name) *__OBJ_ROOT = (__OBJ_PRV(class_name)*)__closn
476
477#define __OBJ_IMPL(class_name, method_name) \
478 do { \
479 void *__pf = __OBJ_clofn(__OBJ_M(class_name, method_name), \
480 &__OBJ_S(class_name, method_name), (void*)__OBJ_ROOT); \
481 if (__pf) { \
482 __OBJ_ROOT->method_name = __OBJ_pool_add(__OBJ_ROOT->base.reserved.p, __pf); \
483 } \
484 else { \
485 __OBJ_ERR("could't implement the method '%s'!", #method_name); \
486 goto __err__; \
487 } \
488 } while (0)
489
490#define __OBJ_S2(n, _1) \
491 __OBJ_IMPL(n, _1)
492#define __OBJ_S3(n, _1, _2) \
493 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2)
494#define __OBJ_S4(n, _1, _2, _3) \
495 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3)
496#define __OBJ_S5(n, _1, _2, _3, _4) \
497 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
498 __OBJ_IMPL(n, _4)
499#define __OBJ_S6(n, _1, _2, _3, _4, _5) \
500 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
501 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5)
502#define __OBJ_S7(n, _1, _2, _3, _4, _5, _6) \
503 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
504 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6)
505#define __OBJ_S8(n, _1, _2, _3, _4, _5, _6, _7) \
506 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
507 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6); \
508 __OBJ_IMPL(n, _7)
509#define __OBJ_S9(n, _1, _2, _3, _4, _5, _6, _7, _8) \
510 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
511 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6), \
512 __OBJ_IMPL(n, _7); __OBJ_IMPL(n, _8)
513#define __OBJ_S10(n, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
514 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
515 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6); \
516 __OBJ_IMPL(n, _7); __OBJ_IMPL(n, _8); __OBJ_IMPL(n, _9)
517#define __OBJ_S11(n, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
518 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
519 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6); \
520 __OBJ_IMPL(n, _7); __OBJ_IMPL(n, _8); __OBJ_IMPL(n, _9); \
521 __OBJ_IMPL(n, _10)
522#define __OBJ_S12(n, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
523 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
524 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6); \
525 __OBJ_IMPL(n, _7); __OBJ_IMPL(n, _8); __OBJ_IMPL(n, _9); \
526 __OBJ_IMPL(n, _10); __OBJ_IMPL(n, _11)
527#define __OBJ_S13(n, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
528 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
529 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6); \
530 __OBJ_IMPL(n, _7); __OBJ_IMPL(n, _8); __OBJ_IMPL(n, _9); \
531 __OBJ_IMPL(n, _10); __OBJ_IMPL(n, _11); __OBJ_IMPL(n, _12)
532#define __OBJ_S14(n, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
533 __OBJ_IMPL(n, _1); __OBJ_IMPL(n, _2); __OBJ_IMPL(n, _3); \
534 __OBJ_IMPL(n, _4); __OBJ_IMPL(n, _5); __OBJ_IMPL(n, _6); \
535 __OBJ_IMPL(n, _7); __OBJ_IMPL(n, _8); __OBJ_IMPL(n, _9); \
536 __OBJ_IMPL(n, _10); __OBJ_IMPL(n, _11); __OBJ_IMPL(n, _12); \
537 __OBJ_IMPL(n, _13)
538
539#define __OBJ_FC(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
540#define __OBJ_FR(args) __OBJ_FC args
541#define __OBJ_CFA(...) __OBJ_FR((__VA_ARGS__, \
542 __OBJ_S14, __OBJ_S13, __OBJ_S12, \
543 __OBJ_S11, __OBJ_S10, __OBJ_S9, __OBJ_S8, \
544 __OBJ_S7, __OBJ_S6, __OBJ_S5, __OBJ_S4, \
545 __OBJ_S3, __OBJ_S2, , ))
546#define __OBJ_MC(...) __OBJ_CFA(__VA_ARGS__ ())
547
548// Bind methods
549#define obj_bind(class_name, ...) __EXPAND(__OBJ_MC(class_name, __VA_ARGS__)(class_name, __VA_ARGS__))
550
551// Constructor setup instance
552#define obj_setup(class_name) \
553 __OBJ_PRV(class_name) *__OBJ_ROOT = (__OBJ_PRV(class_name) *)malloc(sizeof(__OBJ_PRV(class_name))); \
554 do { \
555 if (!__OBJ_ROOT) { \
556 __OBJ_ERR("could't create new class '%s' instance!", #class_name); \
557 return NULL; \
558 } \
559 __OBJ_ROOT->base.reserved.d = NULL; \
560 __OBJ_ROOT->base.reserved.p = __OBJ_pool_create(); \
561 __OBJ_ROOT->base.alloc = __OBJ_clofn((void *)__OBJ_alloc, &__OBJ_alloc_s, (void *)__OBJ_ROOT); \
562 __OBJ_ROOT->base.realloc = __OBJ_clofn((void *)__OBJ_realloc, &__OBJ_realloc_s, (void *)__OBJ_ROOT); \
563 __OBJ_ROOT->base.free = __OBJ_clofn((void *)__OBJ_free, &__OBJ_free_s, (void *)__OBJ_ROOT); \
564 __OBJ_ROOT->base.release = __OBJ_clofn((void *)__OBJ_release, &__OBJ_release_s, (void *)__OBJ_ROOT); \
565 } while (0)
566
567// Constructor raiserror
568#define obj_error() \
569 goto __err__
570
571// Constructor error handing
572#define obj_done(class_name) \
573 return (class_name)__OBJ_ROOT; \
574 __err__:; \
575 __OBJ_freebase(&__OBJ_ROOT->base); \
576 return NULL
577
578// Bind deconstructor
579#define obj_dtor(class_name) \
580 __OBJ_ROOT->base.reserved.d = (void *)__OBJ_DES(class_name)
581
582// Override super's method
583#define obj_override(class_name, super_name, method_name) \
584 do { \
585 void *__pf = __OBJ_clofn(__OBJ_M(class_name, method_name), &__OBJ_S(class_name, method_name), (void*)__OBJ_ROOT); \
586 if (__pf) { __OBJ_ROOT->super_name.method_name = __OBJ_pool_add(__OBJ_ROOT->base.reserved.p, __pf); } \
587 else { __OBJ_ERR("could't override the method '%s.%s'!", #super_name, #method_name); goto __err__; } \
588 } while (0)
589
590// Const cast
591#define const_cast(type, prop) \
592 *(type *)&__OBJ_ROOT->prop
593
594#endif
#define NULL
Definition list.h:22
Definition obj.h:246
Definition obj.h:234
Definition obj.h:239