All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.teavm.backend.c.virtcall.c Maven / Gradle / Ivy

There is a newer version: 0.2.8
Show newest version
#include "virtcall.h"
#include "definitions.h"
#include 
#include 
#include 

typedef struct {
    const char16_t* name;
    int32_t hash;
    int32_t id;
} TeaVM_MethodHashEntry;

static int32_t teavm_vc_hashSize;
static int32_t teavm_vc_hashCapacity;
static int32_t teavm_vc_hashThreshold;
static TeaVM_MethodHashEntry* teavm_vc_hashData = NULL;

static int32_t teavm_vc_classTableSize;
static int32_t teavm_vc_classTableCapacity;
static TeaVM_DynamicClass** teavm_vc_classTable;

static int32_t teavm_vc_computeHash(const char16_t* restrict str) {
     int32_t hash = 0;
     while (true) {
         char16_t c = *str++;
         if (c == 0) {
             break;
         }
         hash = 31 * hash + c;
     }

     hash = (int32_t) (hash << 16 | ((uint32_t) hash >> 16));
     hash ^= INT32_C(0xAAAAAAAA);
     return hash;
}

static bool teavm_vc_streq(const char16_t* restrict a, const char16_t* restrict b) {
    while (true) {
        if (*a != *b) {
            return false;
        }
        if (*a == 0) {
            return true;
        }
        ++a;
        ++b;
    }
}

static size_t teavm_vc_strlen(const char16_t* restrict str) {
    size_t size = 0;
    while (*str++ != 0) {
        ++size;
    }
    return size;
}

static int32_t teavm_vc_insertMethod(const char16_t* restrict name, int32_t hash, int32_t id) {
    uint32_t index = (uint32_t) hash % teavm_vc_hashCapacity;

    TeaVM_MethodHashEntry* entry;
    while (true) {
        entry = &teavm_vc_hashData[index];
        if (entry->name == NULL) {
            break;
        }
        index = (index + 1) % teavm_vc_hashCapacity;
    }

    size_t bytesInName = sizeof(char16_t) * (teavm_vc_strlen(name) + 1);
    entry->name = malloc(bytesInName);
    memcpy((void*) entry->name, name, bytesInName);
    entry->hash = hash;
    entry->id = id;
    teavm_vc_hashSize++;
    return entry->id;
}

static void teavm_vc_rehashMethods() {
    int32_t oldCapacity = teavm_vc_hashCapacity;
    teavm_vc_hashCapacity = teavm_vc_hashCapacity * 2 + 1;
    teavm_vc_hashThreshold = teavm_vc_hashCapacity / 2;
    TeaVM_MethodHashEntry* oldData = teavm_vc_hashData;
    size_t bytesToAllocate = teavm_vc_hashCapacity * sizeof(TeaVM_MethodHashEntry);
    teavm_vc_hashData = malloc(bytesToAllocate);
    memset(teavm_vc_hashData, 0, bytesToAllocate);

    for (int32_t i = 0; i < oldCapacity; ++i) {
        TeaVM_MethodHashEntry* entry = &oldData[i];
        if (entry->name != NULL) {
            teavm_vc_insertMethod(entry->name, entry->hash, entry->id);
        }
    }

    free(oldData);
}

int32_t teavm_vc_getMethodId(const char16_t* restrict name) {
    if (teavm_vc_hashData == NULL) {
        teavm_vc_hashCapacity = 257;
        teavm_vc_hashSize = 0;
        teavm_vc_hashThreshold = teavm_vc_hashCapacity / 2;
        size_t bytesToAllocate = teavm_vc_hashCapacity * sizeof(TeaVM_MethodHashEntry);
        teavm_vc_hashData = malloc(bytesToAllocate);
        memset(teavm_vc_hashData, 0, bytesToAllocate);
    }

    int32_t hash = teavm_vc_computeHash(name);
    uint32_t index = (uint32_t) hash % teavm_vc_hashCapacity;
    TeaVM_MethodHashEntry* entry;

    while (true) {
        entry = &teavm_vc_hashData[index];
        if (entry->name == NULL) {
            break;
        }
        if (entry->hash == hash && teavm_vc_streq(name, entry->name)) {
            return entry->id;
        }
        index = (index + 1) % teavm_vc_hashCapacity;
    }

    if (teavm_vc_hashSize >= teavm_vc_hashThreshold) {
        teavm_vc_rehashMethods();
    }

    int32_t id = (int32_t) ((teavm_vc_hashSize << 16) | ((uint32_t) teavm_vc_hashSize >> 16)) ^ INT32_C(0xAAAAAAAA);
    return teavm_vc_insertMethod(name, hash, id);
}

static void teavm_vc_insertMethodIntoClass(TeaVM_DynamicClass* restrict cls, int32_t id, void* method, bool permanent) {
    uint32_t index = (uint32_t) id % cls->capacity;
    TeaVM_DynamicClassEntry* entry;

    while (true) {
        entry = &cls->data[index];
        if (entry->method == NULL) {
            break;
        }
        entry->hasNext = 1;
        index = (index + 1) % cls->capacity;
    }

    entry->method = method;
    entry->id = id;
    entry->permanent = permanent;
    cls->size++;
}

static void teavm_vc_rehashClass(TeaVM_DynamicClass* restrict cls) {
    int32_t oldCapacity = cls->capacity;
    cls->capacity = cls->capacity * 2 + 1;
    cls->threshold = cls->capacity / 2;
    TeaVM_DynamicClassEntry* oldData = cls->data;
    size_t bytesToAllocate = sizeof(TeaVM_DynamicClassEntry) * cls->capacity;
    cls->data = malloc(bytesToAllocate);
    memset(cls->data, 0, bytesToAllocate);

    for (int32_t i = 0; i < oldCapacity; ++i) {
        TeaVM_DynamicClassEntry* entry = &oldData[i];
        if (entry->method != NULL) {
            teavm_vc_insertMethodIntoClass(cls, entry->id, entry->method, entry->permanent);
        }
    }

    free(oldData);
}

static void teavm_vc_registerMethodImpl(TeaVM_DynamicClass* restrict cls, int32_t id, void* method, bool permanent) {
    if (cls->data == NULL) {
        cls->capacity = 17;
        cls->threshold = cls->capacity / 2;
        cls->size = 0;
        size_t bytesToAllocate = sizeof(TeaVM_DynamicClassEntry) * cls->capacity;
        cls->data = malloc(bytesToAllocate);
        memset(cls->data, 0, bytesToAllocate);
    }

    uint32_t index = (uint32_t) id % cls->capacity;
    TeaVM_DynamicClassEntry* entry;

    while (true) {
        entry = &cls->data[index];
        if (entry->method == NULL) {
            break;
        }
        if (entry->id == id) {
            if (!entry->permanent) {
                entry->method = method;
                entry->permanent = permanent;
            }
            return;
        }
        index = (index + 1) % cls->capacity;
    }

    if (cls->size >= cls->threshold) {
        teavm_vc_rehashClass(cls);
    }

    teavm_vc_insertMethodIntoClass(cls, id, method, permanent);
}

void teavm_vc_registerMethod(TeaVM_DynamicClass* restrict cls, int32_t id, void* method) {
    teavm_vc_registerMethodImpl(cls, id, method, true);
}

static void teavm_vc_addClass(TeaVM_DynamicClass* restrict cls) {
    if (teavm_vc_classTable == NULL) {
        teavm_vc_classTableCapacity = 256;
        teavm_vc_classTableSize = 0;
        teavm_vc_classTable = malloc(sizeof(TeaVM_DynamicClass*) * teavm_vc_classTableCapacity);
    }
    if (teavm_vc_classTableSize == teavm_vc_classTableCapacity) {
        teavm_vc_classTableCapacity *= 2;
        teavm_vc_classTable = realloc(teavm_vc_classTable, sizeof(TeaVM_DynamicClass*) * teavm_vc_classTableCapacity);
    }
    teavm_vc_classTable[teavm_vc_classTableSize++] = cls;
}

void teavm_vc_copyMethods(TeaVM_DynamicClass* restrict from, TeaVM_DynamicClass* restrict to) {
    if (to->copy == NULL) {
        teavm_vc_addClass(to);
        int32_t initialCapacity = 4;
        to->copy = malloc(sizeof(TeaVM_DynamicClassCopy) + sizeof(TeaVM_DynamicClass*) * initialCapacity);
        to->copy->capacity = initialCapacity;
        to->copy->size = 0;
    }
    if (to->copy->size == to->copy->capacity) {
        to->copy->capacity *= 2;
        to->copy = realloc(to->copy, sizeof(TeaVM_DynamicClassCopy) + sizeof(TeaVM_DynamicClass*) * to->copy->capacity);
    }
    to->copy->data[to->copy->size++] = from;
}

void* teavm_vc_lookupMethod(const TeaVM_DynamicClass* restrict cls, int32_t id) {
    if (cls->data == NULL) {
        return NULL;
    }

    uint32_t index = (uint32_t) id % cls->capacity;
    TeaVM_DynamicClassEntry* entry;

    while (true) {
        entry = &cls->data[index];
        if (entry->method == NULL) {
            return NULL;
        }
        if (entry->id == id) {
            return entry->method;
        }
        if (!entry->hasNext) {
            return NULL;
        }

        index = (index + 1) % cls->capacity;
    }
}

static void teavm_vc_cleanupMethodHashtable() {
    if (teavm_vc_hashData == NULL) {
        return;
    }

    for (int32_t i = 0; i < teavm_vc_hashCapacity; ++i) {
        const char16_t* name = teavm_vc_hashData[i].name;
        if (name != NULL) {
            free((void*) name);
        }
    }

    free(teavm_vc_hashData);
}

static void teavm_vc_performCopyOnSingleClass(TeaVM_DynamicClass* restrict cls) {
    if (cls->copy == NULL) {
        return;
    }

    TeaVM_DynamicClassCopy* restrict copy = cls->copy;
    for (int32_t i = 0; i < copy->size; ++i) {
        TeaVM_DynamicClass* restrict from = copy->data[i];
        teavm_vc_performCopyOnSingleClass(from);
        if (from->data != NULL) {
            for (int32_t j = 0; j < from->capacity; ++j) {
                TeaVM_DynamicClassEntry* entry = &from->data[j];
                if (entry->method != NULL) {
                    teavm_vc_registerMethodImpl(cls, entry->id, entry->method, false);
                }
            }
        }
    }

    free(cls->copy);
    cls->copy = NULL;
}

static void teavm_vc_copyClassTables() {
    if (teavm_vc_classTable == NULL) {
        return;
    }

    for (int32_t i = 0; i < teavm_vc_classTableSize; ++i) {
        teavm_vc_performCopyOnSingleClass(teavm_vc_classTable[i]);
    }

    free(teavm_vc_classTable);
}

void teavm_vc_done() {
    teavm_vc_cleanupMethodHashtable();
    teavm_vc_copyClassTables();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy