From 374f7c6634142f9692688184f3cc24e144aee98d Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 30 Jan 2020 18:18:16 +0300 Subject: [PATCH] C: allow to define custom logging functions. Use unified logging function within VM --- .../org/teavm/backend/c/definitions.h | 4 + .../resources/org/teavm/backend/c/heaptrace.c | 53 ++++---- .../main/resources/org/teavm/backend/c/log.c | 127 +++++++++++------- .../main/resources/org/teavm/backend/c/log.h | 5 +- 4 files changed, 117 insertions(+), 72 deletions(-) diff --git a/core/src/main/resources/org/teavm/backend/c/definitions.h b/core/src/main/resources/org/teavm/backend/c/definitions.h index b4a485f75..50546b5c3 100644 --- a/core/src/main/resources/org/teavm/backend/c/definitions.h +++ b/core/src/main/resources/org/teavm/backend/c/definitions.h @@ -55,6 +55,10 @@ #define TEAVM_WINDOWS_LOG 0 #endif +#ifndef TEAVM_CUSTOM_LOG + #define TEAVM_CUSTOM_LOG 0 +#endif + #ifndef TEAVM_GC_LOG #define TEAVM_GC_LOG 0 #endif diff --git a/core/src/main/resources/org/teavm/backend/c/heaptrace.c b/core/src/main/resources/org/teavm/backend/c/heaptrace.c index 47cfd6fb3..fcf8107d9 100644 --- a/core/src/main/resources/org/teavm/backend/c/heaptrace.c +++ b/core/src/main/resources/org/teavm/backend/c/heaptrace.c @@ -1,5 +1,6 @@ #include "heaptrace.h" #include "core.h" +#include "log.h" #include "definitions.h" #include "memory.h" #include "time.h" @@ -12,23 +13,23 @@ #include #include +#define TEAVM_GC_LOG_BUFFER_SIZE 512 + #if TEAVM_WINDOWS #include #endif -#if !TEAVM_WINDOWS_LOG - #define TEAVM_OUTPUT_STRING(s) fprintf(stderr, s) -#else - #define TEAVM_OUTPUT_STRING(s) OutputDebugStringW(L##s) -#endif - #if TEAVM_MEMORY_TRACE uint8_t* teavm_gc_heapMap = NULL; uint8_t* teavm_gc_markMap = NULL; #endif +static inline void teavm_gc_print(wchar_t* s) { + teavm_printWString(s); +} + void teavm_outOfMemory() { - TEAVM_OUTPUT_STRING("Application crashed due to lack of free memory\n"); + teavm_gc_print(L"Application crashed due to lack of free memory\n"); teavm_gc_writeHeapDump(); abort(); } @@ -73,16 +74,20 @@ void teavm_gc_allocate(void* address, int32_t size) { uint8_t* map = teavm_gc_heapMap + (((char*) address - (char*) teavm_gc_heapAddress) / sizeof(void*)); if (*map != 0) { - fprintf(stderr, "[GC] trying allocate at memory in use at: %d\n", + wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; + swprintf(buffer, TEAVM_GC_LOG_BUFFER_SIZE, L"[GC] trying allocate at memory in use at: %d\n", (int) ((char*) address - (char*) teavm_gc_heapAddress)); + teavm_gc_print(buffer); abort(); } *map++ = 1; for (int32_t i = 1; i < size; ++i) { if (*map != 0) { - fprintf(stderr, "[GC] trying allocate at memory in use at: %d\n", + wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; + swprintf(buffer, TEAVM_GC_LOG_BUFFER_SIZE, L"[GC] trying allocate at memory in use at: %d\n", (int) ((char*) address - (char*) teavm_gc_heapAddress)); + teavm_gc_print(buffer); abort(); } *map++ = 2; @@ -104,8 +109,10 @@ void teavm_gc_free(void* address, int32_t size) { size /= sizeof(void*); for (int32_t i = 0; i < size; ++i) { if (markMap[i] != 0) { - fprintf(stderr, "[GC] trying to release reachable object at: %d\n", + wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; + swprintf(buffer, TEAVM_GC_LOG_BUFFER_SIZE, L"[GC] trying to release reachable object at: %d\n", (int) ((char*) address - (char*) teavm_gc_heapAddress)); + teavm_gc_print(buffer); abort(); } } @@ -130,8 +137,10 @@ void teavm_gc_assertFree(void* address, int32_t size) { size /= sizeof(void*); for (int32_t i = 0; i < size; ++i) { if (map[i] != 0) { - fprintf(stderr, "[GC] memory supposed to be free at: %d\n", + wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; + swprintf(buffer, TEAVM_GC_LOG_BUFFER_SIZE, L"[GC] memory supposed to be free at: %d\n", (int) ((char*) address - (char*) teavm_gc_heapAddress)); + teavm_gc_print(buffer); abort(); } } @@ -186,8 +195,10 @@ void teavm_gc_mark(void* address) { size /= sizeof(void*); if (*map++ != 1 || *markMap != 0) { - fprintf(stderr, "[GC] assertion failed marking object at: %d\n", + wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; + swprintf(buffer, TEAVM_GC_LOG_BUFFER_SIZE, L"[GC] assertion failed marking object at: %d\n", (int) ((char*) address - (char*) teavm_gc_heapAddress)); + teavm_gc_print(buffer); abort(); } *markMap++ = 1; @@ -218,8 +229,12 @@ void teavm_gc_move(void* from, void* to, int32_t size) { if (mapFrom > mapTo) { for (int32_t i = 0; i < size; ++i) { if (mapFrom[i] == 0 || mapTo[i] != 0) { - fprintf(stderr, "[GC] assertion failed moving object from: %d to %d\n", - (int) ((char*) from - (char*) teavm_gc_heapAddress), (int) ((char*) to - (char*) teavm_gc_heapAddress)); + wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; + swprintf(buffer, TEAVM_GC_LOG_BUFFER_SIZE, + L"[GC] assertion failed moving object from: %d to %d\n", + (int) ((char*) from - (char*) teavm_gc_heapAddress), + (int) ((char*) to - (char*) teavm_gc_heapAddress)); + teavm_gc_print(buffer); abort(); } mapTo[i] = mapFrom[i]; @@ -428,17 +443,7 @@ void teavm_gc_defragCompleted() { #endif } -#define TEAVM_GC_LOG_BUFFER_SIZE 512 - #if TEAVM_GC_STATS - static void teavm_gc_print(wchar_t* s) { - #if TEAVM_WINDOWS_LOG - OutputDebugStringW(s); - #else - fprintf(stderr, "%ls", s); - #endif - } - static void teavm_gc_printStats() { wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; diff --git a/core/src/main/resources/org/teavm/backend/c/log.c b/core/src/main/resources/org/teavm/backend/c/log.c index deb574f11..ff5e227a8 100644 --- a/core/src/main/resources/org/teavm/backend/c/log.c +++ b/core/src/main/resources/org/teavm/backend/c/log.c @@ -9,63 +9,96 @@ #include #endif -static char16_t* teavm_utf16ToUtf32(char16_t* source, char32_t* target) { - char16_t c = *source; - if ((c & 0xFC00) == 0xD800) { - char16_t n = *(source + 1); - if ((n & 0xFC00) == 0xDC00) { - *target = (((c & ~0xFC00) << 10) | (n & ~0xFC00)) + 0x10000; - return source + 2; +#if !TEAVM_CUSTOM_LOG + static char16_t* teavm_utf16ToUtf32(char16_t* source, char32_t* target) { + char16_t c = *source; + if ((c & 0xFC00) == 0xD800) { + char16_t n = *(source + 1); + if ((n & 0xFC00) == 0xDC00) { + *target = (((c & ~0xFC00) << 10) | (n & ~0xFC00)) + 0x10000; + return source + 2; + } } + *target = c; + return source + 1; } - *target = c; - return source + 1; -} -void teavm_printString(char16_t* s) { - #if !TEAVM_WINDOWS_LOG - #if TEAVM_WINDOWS + void teavm_printString(char16_t* s) { + #if !TEAVM_WINDOWS_LOG + #if TEAVM_WINDOWS + fprintf(stderr, "%ls", s); + #else + int32_t cap = 128; + wchar_t* buf = malloc(sizeof(wchar_t) * cap); + wchar_t* out = buf; + int32_t sz = 0; + while (*s != '\0') { + s = teavm_utf16ToUtf32(s, out++); + if (++sz == cap) { + cap *= 2; + buf = realloc(buf, sizeof(wchar_t) * cap); + out = buf + sz; + } + } + *out = '\0'; + fprintf(stderr, "%ls", buf); + free(buf); + #endif + #else + OutputDebugStringW(s); + #endif + } + + void teavm_printWString(wchar_t* s) { + #if !TEAVM_WINDOWS_LOG fprintf(stderr, "%ls", s); #else - int32_t cap = 128; - wchar_t* buf = malloc(sizeof(wchar_t) * cap); - wchar_t* out = buf; - int32_t sz = 0; - while (*s != '\0') { - s = teavm_utf16ToUtf32(s, out++); - if (++sz == cap) { - cap *= 2; - buf = realloc(buf, sizeof(wchar_t) * cap); - out = buf + sz; - } - } - *out = '\0'; - fprintf(stderr, "%ls", buf); - free(buf); + OutputDebugStringW(s); #endif - #else - OutputDebugStringW(s); - #endif -} + } + + void teavm_printInt(int32_t i) { + #if !TEAVM_WINDOWS_LOG + fprintf(stderr, "%" PRId32, i); + #else + wchar_t str[10]; + swprintf(str, 10, L"%d", i); + OutputDebugStringW(str); + #endif + } -void teavm_printInt(int32_t i) { #if !TEAVM_WINDOWS_LOG - fprintf(stderr, "%" PRId32, i); + void teavm_logCodePoint(int32_t c) { + putwchar(c); + } #else - wchar_t str[10]; - swprintf(str, 10, L"%d", i); - OutputDebugStringW(str); + void teavm_logCodePoint(int32_t c) { + char16_t buffer[2] = { (char16_t) c, 0 }; + OutputDebugStringW(buffer); + } #endif -} +#endif +static int32_t teavm_logCharBuffer; +static int teavm_logCharBufferRemaining; +static int teavm_logCharBufferSize; -#if !TEAVM_WINDOWS_LOG - void teavm_logchar(int32_t c) { - putwchar(c); +void teavm_logchar(int32_t c) { + if (teavm_logCharBufferRemaining > 0) { + teavm_logCharBuffer = teavm_logCharBuffer << 6 | (c & 0x3F); + if (--teavm_logCharBufferRemaining == 0) { + teavm_logCodePoint(teavm_logCharBuffer); + } + } else if ((c & 0x80) == 0) { + teavm_logCodePoint(c); + } else if ((c & 0xE0) == 0xC0) { + teavm_logCharBuffer = c & 0x1F; + teavm_logCharBufferRemaining = 1; + } else if ((c & 0xF0) == 0xE0) { + teavm_logCharBuffer = c & 0x0F; + teavm_logCharBufferRemaining = 2; + } else if ((c & 0xF8) == 0xF0) { + teavm_logCharBuffer = c & 0x07; + teavm_logCharBufferRemaining = 3; } -#else - void teavm_logchar(int32_t c) { - char16_t buffer[2] = { (char16_t) c, 0 }; - OutputDebugStringW(buffer); - } -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/core/src/main/resources/org/teavm/backend/c/log.h b/core/src/main/resources/org/teavm/backend/c/log.h index e9f36e772..9ff921d29 100644 --- a/core/src/main/resources/org/teavm/backend/c/log.h +++ b/core/src/main/resources/org/teavm/backend/c/log.h @@ -1,7 +1,10 @@ #pragma once #include #include +#include extern void teavm_printString(char16_t*); +extern void teavm_printWString(wchar_t*); extern void teavm_printInt(int32_t); -extern void teavm_logchar(int32_t); \ No newline at end of file +extern void teavm_logchar(int32_t); +extern void teavm_logCodePoint(int32_t); \ No newline at end of file