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

Add the first JIT #23

Merged
merged 18 commits into from
Nov 17, 2024
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
8 changes: 7 additions & 1 deletion .github/workflows/microcontroller_core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,10 @@ jobs:
run: gcc -DTEST64 float-test.c -o float-test -lm

- name: Run float-test
run: ./float-test
run: ./float-test

- name: Build profiler-test
run: gcc -DTEST64 profiler-test.c -o profiler-test -lm

- name: Run profiler-test
run: ./profiler-test
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
.DS_Store
.DS_Store
.vscode
8 changes: 6 additions & 2 deletions microcontroller/core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
idf_component_register(SRCS "src/c-runtime.c"
INCLUDE_DIRS "include")
idf_component_register(SRCS "src/c-runtime.c" "src/profiler.c"
INCLUDE_DIRS "include"
LDFRAGMENTS linker.lf
WHOLE_ARCHIVE)

target_compile_options(${COMPONENT_LIB} PRIVATE -mtext-section-literals)
7 changes: 6 additions & 1 deletion microcontroller/core/include/c-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ extern bool CR_SECTION value_to_truefalse(value_t v);

inline value_t bool_to_value(bool b) { return b ? VALUE_TRUE : VALUE_FALSE; }
inline bool value_to_bool(value_t v) { return value_to_truefalse(v); }
inline bool is_bool_value(value_t v) { return (v & 3) == 2; }

inline bool safe_value_to_bool(value_t v) {
// any value can be a boolean value.
Expand Down Expand Up @@ -166,7 +167,7 @@ extern void CR_SECTION interrupt_handler_end();

extern void CR_SECTION gc_initialize();
extern class_object* CR_SECTION gc_get_class_of(value_t value);
extern bool gc_is_instance_of(const class_object* clazz, value_t obj);
extern bool CR_SECTION gc_is_instance_of(const class_object* clazz, value_t obj);
extern void* CR_SECTION method_lookup(value_t obj, uint32_t index);

extern pointer_t CR_SECTION gc_allocate_object(const class_object* clazz);
Expand Down Expand Up @@ -224,18 +225,21 @@ extern value_t CR_SECTION gc_new_intarray(int32_t n, int32_t init_value);
extern value_t CR_SECTION gc_make_intarray(int32_t n, ...);
extern int32_t CR_SECTION gc_intarray_length(value_t obj);
extern int32_t* CR_SECTION gc_intarray_get(value_t obj, int32_t index);
extern bool CR_SECTION gc_is_intarray(value_t v);

extern value_t CR_SECTION safe_value_to_floatarray(value_t v);
extern value_t CR_SECTION gc_new_floatarray(int32_t n, float init_value);
extern value_t CR_SECTION gc_make_floatarray(int32_t n, ...);
extern int32_t CR_SECTION gc_floatarray_length(value_t obj);
extern float* CR_SECTION gc_floatarray_get(value_t obj, int32_t index);
extern bool CR_SECTION gc_is_floatarray(value_t v);

extern value_t CR_SECTION safe_value_to_boolarray(value_t v);
extern value_t CR_SECTION gc_new_bytearray(bool is_boolean, int32_t n, int32_t init_value);
extern value_t CR_SECTION gc_make_bytearray(bool is_boolean, int32_t n, ...);
extern int32_t CR_SECTION gc_bytearray_length(value_t obj);
extern uint8_t* CR_SECTION gc_bytearray_get(value_t obj, int32_t index);
extern bool CR_SECTION gc_is_boolarray(value_t v);

extern value_t CR_SECTION safe_value_to_vector(value_t v);
extern value_t CR_SECTION gc_new_vector(int32_t n, value_t init_value);
Expand All @@ -251,6 +255,7 @@ extern value_t CR_SECTION gc_make_array(int32_t is_any, int32_t n, ...);
extern int32_t CR_SECTION gc_array_length(value_t obj);
extern value_t* CR_SECTION gc_array_get(value_t obj, int32_t index);
extern value_t CR_SECTION gc_array_set(value_t obj, int32_t index, value_t new_value);
extern bool CR_SECTION gc_is_anyarray(value_t v);

extern int32_t CR_SECTION get_all_array_length(value_t obj);
extern value_t CR_SECTION get_anyobj_length_property(value_t obj, int property);
Expand Down
25 changes: 25 additions & 0 deletions microcontroller/core/include/profiler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef __BS_PROFILER__
#define __BS_PROFILER__

#include <stdint.h>
#include "c-runtime.h"

#ifdef TEST64
typedef uint64_t typeint_t;
#define CORE_TEXT_SECTION
#define CORE_DATA_SECTION
#else
typedef uint32_t typeint_t;
#define CORE_TEXT_SECTION __attribute__((section(".core_text")))
#define CORE_DATA_SECTION __attribute__((section(".core_data")))
#endif


void CORE_TEXT_SECTION bs_profiler_profile(uint8_t fid, uint8_t* call_count, typeint_t** type_profile, value_t p1, value_t p2, value_t p3, value_t p4);

#ifndef TEST64
extern void bs_logger_push_profile(uint8_t fid, char *profile_str);
#endif

#endif /* __BS_PROFILER__ */

24 changes: 24 additions & 0 deletions microcontroller/core/linker.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[sections:core_text]
entries:
.core_text

[sections:core_data]
entries:
.core_data

[scheme:core_text_default]
entries:
core_text -> flash_text

[scheme:core_data_default]
entries:
core_data -> flash_rodata


[mapping:core_text]
archive: *
entries:
* (core_text_default);
core_text -> flash_text KEEP()
* (core_data_default);
core_data -> flash_rodata KEEP()
20 changes: 20 additions & 0 deletions microcontroller/core/src/c-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,11 @@ int32_t* gc_intarray_get(value_t obj, int32_t index) {
}
}

bool gc_is_intarray(value_t v) {
const class_object* type = gc_get_class_of(v);
return type == &intarray_object.clazz;
}

// A float array

static CLASS_OBJECT(floatarray_object, 1) = {
Expand Down Expand Up @@ -851,6 +856,11 @@ float* gc_floatarray_get(value_t obj, int32_t index) {
}
}

bool gc_is_floatarray(value_t v) {
const class_object* type = gc_get_class_of(v);
return type == &floatarray_object.clazz;
}

// A byte array and a boolean array

CLASS_OBJECT(class_Uint8Array, 1) = {
Expand Down Expand Up @@ -934,6 +944,11 @@ uint8_t* gc_bytearray_get(value_t obj, int32_t idx) {
}
}

bool gc_is_boolarray(value_t v) {
const class_object* type = gc_get_class_of(v);
return type == &boolarray_object.clazz;
}

// A fixed-length array

static CLASS_OBJECT(vector_object, 1) = {
Expand Down Expand Up @@ -1184,6 +1199,11 @@ value_t gc_safe_array_acc(value_t obj, int32_t index, char op, value_t value) {
return gc_safe_array_set(obj, index, new_value);
}

bool gc_is_anyarray(value_t v) {
const class_object* type = gc_get_class_of(v);
return type == &anyarray_object.clazz;
}

// Compute an object size. It is always an even number.
//
// length: length of object_type.body[]
Expand Down
121 changes: 121 additions & 0 deletions microcontroller/core/src/profiler.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "../include/profiler.h"
#include "../include/c-runtime.h"


#define BS_PROFILER_TAG "BS_PROFILER"

#define TYPEINT_SIZE sizeof(typeint_t)
#define PARAMS_NUM 4
#define TYPE_PROFILE_COLUMN (PARAMS_NUM + 1)
#define TYPE_PROFILE_ROW 5
#define TYPE_PROFILE_SIZE TYPEINT_SIZE * TYPE_PROFILE_COLUMN * TYPE_PROFILE_ROW
#define TYPE_COUNT_THRESHOLD 5
#define CALL_COUNT_THRESHOLD 5

char types_str[128];

static typeint_t value_to_typeint(value_t p) {
uint32_t last_2bit = p & 3;
if (last_2bit == 3 && p != VALUE_UNDEF) {
class_object* obj_class = gc_get_class_of(p);
return obj_class == NULL ? VALUE_UNDEF : (typeint_t)obj_class;
} else {
return last_2bit;
}
}

static const char* typeint_to_str(typeint_t typeint) {
if (typeint == 0b00) {
return "integer";
} else if (typeint == 0b01) {
return "float";
} else if (typeint == 0b10) {
return "boolean";
} else if (typeint == 0b11) {
return "undefined";
} else {
return ((class_object*)typeint)->name;
}
}

static inline bool row_is_empty(typeint_t* type_profile_row) {
return *type_profile_row == 0;
}

static inline void increment_row_count(typeint_t* type_profile_row) {
*type_profile_row += 1;
}

static void set_initial_row(typeint_t* type_profile_row, value_t p1, value_t p2, value_t p3, value_t p4) {
*type_profile_row = 1;
*(type_profile_row + 1) = value_to_typeint(p1);
*(type_profile_row + 2) = value_to_typeint(p2);
*(type_profile_row + 3) = value_to_typeint(p3);
*(type_profile_row + 4) = value_to_typeint(p4);
}

static bool row_match_param_types(typeint_t* type_profile_row, value_t p1, value_t p2, value_t p3, value_t p4) {
bool p1_match = value_to_typeint(p1) == *(type_profile_row + 1);
bool p2_match = value_to_typeint(p2) == *(type_profile_row + 2);
bool p3_match = value_to_typeint(p3) == *(type_profile_row + 3);
bool p4_match = value_to_typeint(p4) == *(type_profile_row + 4);
return p1_match && p2_match && p3_match && p4_match;
}

static char* row_to_str(typeint_t* type_profile_row) {
const char* p1_str = typeint_to_str(*(type_profile_row + 1));
const char* p2_str = typeint_to_str(*(type_profile_row + 2));
const char* p3_str = typeint_to_str(*(type_profile_row + 3));
const char* p4_str = typeint_to_str(*(type_profile_row + 4));
snprintf(types_str, sizeof(types_str), "%s, %s, %s, %s", p1_str, p2_str, p3_str, p4_str);
return types_str;
}

static void send_row(uint8_t fid, typeint_t* type_profile_row) {
char* s = row_to_str(type_profile_row);
#ifdef TEST64
printf("%s\n", s);
#else
bs_logger_push_profile(fid, s);
#endif
}

static typeint_t* get_row_on_threshold(uint8_t fid, typeint_t* type_profile, value_t p1, value_t p2, value_t p3, value_t p4) {
for (int i = 0; i < TYPE_PROFILE_ROW; i++) {
typeint_t* row = type_profile + TYPE_PROFILE_COLUMN * i;
if(row_is_empty(row)) {
set_initial_row(row, p1, p2, p3, p4);
return NULL;
} else if (row_match_param_types(row, p1, p2, p3, p4)) {
increment_row_count(row);
return *row == TYPE_COUNT_THRESHOLD ? row : NULL;
}
}
return NULL;
}

void bs_profiler_profile(uint8_t fid, uint8_t* call_count, typeint_t** type_profile, value_t p1, value_t p2, value_t p3, value_t p4) {
if (*call_count < CALL_COUNT_THRESHOLD) {
*call_count += 1;
return;
} else if (*call_count == CALL_COUNT_THRESHOLD) {
*call_count += 1;
*type_profile = malloc(TYPE_PROFILE_SIZE);
memset(*type_profile, 0, TYPE_PROFILE_SIZE);
return;
} else if (*type_profile) {
typeint_t* result_row = get_row_on_threshold(fid, *type_profile, p1, p2, p3, p4);
if (result_row != NULL) {
send_row(fid, result_row);
free(*type_profile);
*type_profile = NULL;
}
return;
}
return;
}

Loading