C: allow to define custom logging functions. Use unified logging function within VM

This commit is contained in:
Alexey Andreev 2020-01-30 18:18:16 +03:00
parent f13a7e6375
commit 374f7c6634
4 changed files with 117 additions and 72 deletions

View File

@ -55,6 +55,10 @@
#define TEAVM_WINDOWS_LOG 0 #define TEAVM_WINDOWS_LOG 0
#endif #endif
#ifndef TEAVM_CUSTOM_LOG
#define TEAVM_CUSTOM_LOG 0
#endif
#ifndef TEAVM_GC_LOG #ifndef TEAVM_GC_LOG
#define TEAVM_GC_LOG 0 #define TEAVM_GC_LOG 0
#endif #endif

View File

@ -1,5 +1,6 @@
#include "heaptrace.h" #include "heaptrace.h"
#include "core.h" #include "core.h"
#include "log.h"
#include "definitions.h" #include "definitions.h"
#include "memory.h" #include "memory.h"
#include "time.h" #include "time.h"
@ -12,23 +13,23 @@
#include <wctype.h> #include <wctype.h>
#include <stdbool.h> #include <stdbool.h>
#define TEAVM_GC_LOG_BUFFER_SIZE 512
#if TEAVM_WINDOWS #if TEAVM_WINDOWS
#include <Windows.h> #include <Windows.h>
#endif #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 #if TEAVM_MEMORY_TRACE
uint8_t* teavm_gc_heapMap = NULL; uint8_t* teavm_gc_heapMap = NULL;
uint8_t* teavm_gc_markMap = NULL; uint8_t* teavm_gc_markMap = NULL;
#endif #endif
static inline void teavm_gc_print(wchar_t* s) {
teavm_printWString(s);
}
void teavm_outOfMemory() { 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(); teavm_gc_writeHeapDump();
abort(); 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*)); uint8_t* map = teavm_gc_heapMap + (((char*) address - (char*) teavm_gc_heapAddress) / sizeof(void*));
if (*map != 0) { 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)); (int) ((char*) address - (char*) teavm_gc_heapAddress));
teavm_gc_print(buffer);
abort(); abort();
} }
*map++ = 1; *map++ = 1;
for (int32_t i = 1; i < size; ++i) { for (int32_t i = 1; i < size; ++i) {
if (*map != 0) { 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)); (int) ((char*) address - (char*) teavm_gc_heapAddress));
teavm_gc_print(buffer);
abort(); abort();
} }
*map++ = 2; *map++ = 2;
@ -104,8 +109,10 @@ void teavm_gc_free(void* address, int32_t size) {
size /= sizeof(void*); size /= sizeof(void*);
for (int32_t i = 0; i < size; ++i) { for (int32_t i = 0; i < size; ++i) {
if (markMap[i] != 0) { 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)); (int) ((char*) address - (char*) teavm_gc_heapAddress));
teavm_gc_print(buffer);
abort(); abort();
} }
} }
@ -130,8 +137,10 @@ void teavm_gc_assertFree(void* address, int32_t size) {
size /= sizeof(void*); size /= sizeof(void*);
for (int32_t i = 0; i < size; ++i) { for (int32_t i = 0; i < size; ++i) {
if (map[i] != 0) { 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)); (int) ((char*) address - (char*) teavm_gc_heapAddress));
teavm_gc_print(buffer);
abort(); abort();
} }
} }
@ -186,8 +195,10 @@ void teavm_gc_mark(void* address) {
size /= sizeof(void*); size /= sizeof(void*);
if (*map++ != 1 || *markMap != 0) { 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)); (int) ((char*) address - (char*) teavm_gc_heapAddress));
teavm_gc_print(buffer);
abort(); abort();
} }
*markMap++ = 1; *markMap++ = 1;
@ -218,8 +229,12 @@ void teavm_gc_move(void* from, void* to, int32_t size) {
if (mapFrom > mapTo) { if (mapFrom > mapTo) {
for (int32_t i = 0; i < size; ++i) { for (int32_t i = 0; i < size; ++i) {
if (mapFrom[i] == 0 || mapTo[i] != 0) { if (mapFrom[i] == 0 || mapTo[i] != 0) {
fprintf(stderr, "[GC] assertion failed moving object from: %d to %d\n", wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE];
(int) ((char*) from - (char*) teavm_gc_heapAddress), (int) ((char*) to - (char*) teavm_gc_heapAddress)); 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(); abort();
} }
mapTo[i] = mapFrom[i]; mapTo[i] = mapFrom[i];
@ -428,17 +443,7 @@ void teavm_gc_defragCompleted() {
#endif #endif
} }
#define TEAVM_GC_LOG_BUFFER_SIZE 512
#if TEAVM_GC_STATS #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() { static void teavm_gc_printStats() {
wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE]; wchar_t buffer[TEAVM_GC_LOG_BUFFER_SIZE];

View File

@ -9,63 +9,96 @@
#include <Windows.h> #include <Windows.h>
#endif #endif
static char16_t* teavm_utf16ToUtf32(char16_t* source, char32_t* target) { #if !TEAVM_CUSTOM_LOG
char16_t c = *source; static char16_t* teavm_utf16ToUtf32(char16_t* source, char32_t* target) {
if ((c & 0xFC00) == 0xD800) { char16_t c = *source;
char16_t n = *(source + 1); if ((c & 0xFC00) == 0xD800) {
if ((n & 0xFC00) == 0xDC00) { char16_t n = *(source + 1);
*target = (((c & ~0xFC00) << 10) | (n & ~0xFC00)) + 0x10000; if ((n & 0xFC00) == 0xDC00) {
return source + 2; *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) { void teavm_printString(char16_t* s) {
#if !TEAVM_WINDOWS_LOG #if !TEAVM_WINDOWS_LOG
#if TEAVM_WINDOWS #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); fprintf(stderr, "%ls", s);
#else #else
int32_t cap = 128; OutputDebugStringW(s);
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 #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 #if !TEAVM_WINDOWS_LOG
fprintf(stderr, "%" PRId32, i); void teavm_logCodePoint(int32_t c) {
putwchar(c);
}
#else #else
wchar_t str[10]; void teavm_logCodePoint(int32_t c) {
swprintf(str, 10, L"%d", i); char16_t buffer[2] = { (char16_t) c, 0 };
OutputDebugStringW(str); OutputDebugStringW(buffer);
}
#endif #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) {
void teavm_logchar(int32_t c) { if (teavm_logCharBufferRemaining > 0) {
putwchar(c); 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

View File

@ -1,7 +1,10 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <uchar.h> #include <uchar.h>
#include <wchar.h>
extern void teavm_printString(char16_t*); extern void teavm_printString(char16_t*);
extern void teavm_printWString(wchar_t*);
extern void teavm_printInt(int32_t); extern void teavm_printInt(int32_t);
extern void teavm_logchar(int32_t); extern void teavm_logchar(int32_t);
extern void teavm_logCodePoint(int32_t);