Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a tier-1 JIT compiler based on x86-64 architecture #289

Merged
merged 2 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ jobs:
- name: gdbstub test
run: |
make distclean ENABLE_GDBSTUB=1 gdbstub-test

- name: JIT test
run: |
make ENABLE_JIT=1 clean check
coding-style:
runs-on: ubuntu-22.04
steps:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ build/path/
tests/**/*.elf
tests/arch-test-target/config.ini
__pycache__/
src/rv32_jit_template.c
17 changes: 16 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ gdbstub-test: $(BIN)
$(Q).ci/gdbstub-test.sh && $(call notice, [OK])
endif

ENABLE_JIT ?= 0
$(call set-feature, JIT)
ifeq ($(call has, JIT), 1)
OBJS_EXT += jit_x64.o
ifneq ($(processor), x86_64)
$(error JIT mode only supports for x64 target currently.)
endif

src/rv32_jit_template.c:
$(Q)tools/gen-jit-template.py $(CFLAGS) > $@

$(OUT)/jit_x64.o: src/jit_x64.c src/rv32_jit_template.c
$(VECHO) " CC\t$@\n"
$(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF [email protected] $<
endif
# For tail-call elimination, we need a specific set of build flags applied.
# FIXME: On macOS + Apple Silicon, -fno-stack-protector might have a negative impact.
$(OUT)/emulate.o: CFLAGS += -foptimize-sibling-calls -fomit-frame-pointer -fno-stack-check -fno-stack-protector
Expand Down Expand Up @@ -214,7 +229,7 @@ endif
endif

clean:
$(RM) $(BIN) $(OBJS) $(HIST_BIN) $(HIST_OBJS) $(deps) $(CACHE_OUT)
$(RM) $(BIN) $(OBJS) $(HIST_BIN) $(HIST_OBJS) $(deps) $(CACHE_OUT) src/rv32_jit_template.c
distclean: clean
-$(RM) $(DOOM_DATA) $(QUAKE_DATA)
$(RM) -r $(OUT)/id1
Expand Down
1 change: 1 addition & 0 deletions mk/tools.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ HIST_BIN := $(OUT)/rv_histogram
# FIXME: riscv.o and map.o are dependencies of 'elf.o', not 'rv_histogram'.
HIST_OBJS := \
riscv.o \
utils.o \
map.o \
elf.o \
decode.o \
Expand Down
68 changes: 65 additions & 3 deletions src/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
#include "mpool.h"
#include "utils.h"

/* THRESHOLD is set to identify hot spots. Once the frequency of use for a block
* exceeds the THRESHOLD, the JIT compiler flow is triggered.
/* Currently, THRESHOLD is set to identify hot spots. Once the using frequency
* for a block exceeds the THRESHOLD, the tier-1 JIT compiler process is
* triggered.
* FIXME: Implement effective profiler to detect hot spots, instead of simply
* relying on THRESHOLD.
*/
#define THRESHOLD 1000
#define THRESHOLD 4096
qwe661234 marked this conversation as resolved.
Show resolved Hide resolved

static uint32_t cache_size, cache_size_bits;
static struct mpool *cache_mp;
Expand Down Expand Up @@ -530,3 +533,62 @@ void cache_free(cache_t *cache)
free(cache->map);
free(cache);
}

#if !RV32_HAS(ARC)
uint32_t cache_freq(struct cache *cache, uint32_t key)
{
if (!cache->capacity ||
hlist_empty(&cache->map->ht_list_head[cache_hash(key)]))
return 0;
lfu_entry_t *entry = NULL;
#ifdef __HAVE_TYPEOF
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list)
#else
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list, lfu_entry_t)
#endif
{
if (entry->key == key)
return entry->frequency;
}
return 0;
}
#endif

#if RV32_HAS(JIT)
bool cache_hot(struct cache *cache, uint32_t key)
{
if (!cache->capacity ||
hlist_empty(&cache->map->ht_list_head[cache_hash(key)]))
return false;
#if RV32_HAS(ARC)
arc_entry_t *entry = NULL;
#ifdef __HAVE_TYPEOF
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list)
#else
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list, arc_entry_t)
#endif
{
if (entry->key == key && entry->frequency == THRESHOLD)
return true;
}
#else
lfu_entry_t *entry = NULL;
#ifdef __HAVE_TYPEOF
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list)
#else
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list, lfu_entry_t)
#endif
{
if (entry->key == key && entry->frequency == THRESHOLD)
return true;
}
#endif
return false;
}
#endif
15 changes: 15 additions & 0 deletions src/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#pragma once

#include <stdbool.h>
#include <stdint.h>

struct cache;
Expand Down Expand Up @@ -38,3 +39,17 @@ void *cache_put(struct cache *cache, uint32_t key, void *value);
* @callback: a function for freeing cache entry completely
*/
void cache_free(struct cache *cache);

#if RV32_HAS(JIT)
/**
* cache_hot - check whether the frequency of the cache entry exceeds the
* threshold or not
* @cache: a pointer points to target cache
* @key: the key of the specified entry
*/
bool cache_hot(struct cache *cache, uint32_t key);
#endif

#if !RV32_HAS(ARC)
uint32_t cache_freq(struct cache *cache, uint32_t key);
#endif
Loading