From 4c77755da0bde8c8405ad54b70469e79a2a311b1 Mon Sep 17 00:00:00 2001 From: luboslenco Date: Fri, 21 Aug 2026 22:35:30 +0200 Subject: [PATCH] base: merge gc remove --- base/assets/licenses/license_gc.md | 23 -- base/project.js | 1 - base/sources/backends/linux_system.c | 3 +- base/sources/backends/metal_gpu.m | 5 +- base/sources/engine.c | 207 +++++++------ base/sources/engine.h | 5 +- base/sources/iron.h | 43 ++- base/sources/iron_alloc.h | 10 + base/sources/iron_armpack.c | 9 +- base/sources/iron_array.c | 110 ++++--- base/sources/iron_array.h | 5 +- base/sources/iron_draw.c | 20 +- base/sources/iron_file.c | 17 +- base/sources/iron_gc.c | 448 --------------------------- base/sources/iron_gc.h | 21 -- base/sources/iron_input.c | 24 +- base/sources/iron_json.c | 69 +++-- base/sources/iron_lz4.c | 8 +- base/sources/iron_map.c | 55 ++-- base/sources/iron_map.h | 1 + base/sources/iron_math.c | 5 +- base/sources/iron_obj.c | 13 +- base/sources/iron_path.c | 195 +++++++----- base/sources/iron_physics.c | 2 +- base/sources/iron_raycast.c | 4 +- base/sources/iron_string.c | 80 ++++- base/sources/iron_string.h | 7 + base/sources/iron_sys.c | 47 +-- base/sources/iron_tween.c | 7 +- base/sources/iron_ui.c | 28 +- base/sources/iron_ui_ext.c | 8 +- base/sources/iron_ui_nodes.c | 16 +- base/sources/libs/minic.c | 26 +- base/tests/cube/sources/main.c | 32 +- base/tests/fall/sources/main.c | 37 +-- base/tests/triangle/main.c | 7 +- base/tools/amake/project.js | 2 - 37 files changed, 635 insertions(+), 965 deletions(-) delete mode 100644 base/assets/licenses/license_gc.md create mode 100644 base/sources/iron_alloc.h delete mode 100644 base/sources/iron_gc.c delete mode 100644 base/sources/iron_gc.h diff --git a/base/assets/licenses/license_gc.md b/base/assets/licenses/license_gc.md deleted file mode 100644 index 26400683..00000000 --- a/base/assets/licenses/license_gc.md +++ /dev/null @@ -1,23 +0,0 @@ -MIT License - -Copyright (c) 2019 Marc Kirchner - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -https://github.com/mkirchner/gc diff --git a/base/project.js b/base/project.js index 674cbedc..b62cd838 100644 --- a/base/project.js +++ b/base/project.js @@ -116,7 +116,6 @@ else if (platform == "wasm") { project.add_cfiles("sources/backends/webgpu_gpu.*"); project.add_define("IRON_WASM"); project.add_define("IRON_WEBGPU"); - project.add_define("NO_GC"); project.add_cfiles("sources/miniclib/**"); project.add_include_dir("sources/miniclib"); project.add_assets("sources/backends/data/wasm/*"); diff --git a/base/sources/backends/linux_system.c b/base/sources/backends/linux_system.c index 4f93b419..440ff934 100644 --- a/base/sources/backends/linux_system.c +++ b/base/sources/backends/linux_system.c @@ -749,10 +749,9 @@ static int xk_to_iron(KeySym symbol) { return KEY_CODE_UNKNOWN; } -void *gc_alloc(size_t size); static char *uri_decode(const char *src) { - char *res = gc_alloc(1024); + char *res = calloc(1, 1024); char *dst = res; char a, b; while (*src) { diff --git a/base/sources/backends/metal_gpu.m b/base/sources/backends/metal_gpu.m index 90182bcd..4835a386 100644 --- a/base/sources/backends/metal_gpu.m +++ b/base/sources/backends/metal_gpu.m @@ -513,6 +513,8 @@ void gpu_shader_destroy(gpu_shader_t *shader) { id function = (__bridge_transfer id)shader->impl.mtl_function; function = nil; shader->impl.mtl_function = NULL; + free(shader->impl.source); + shader->impl.source = NULL; } void gpu_shader_init(gpu_shader_t *shader, const void *data, size_t length, gpu_shader_type_t type) { @@ -527,7 +529,8 @@ void gpu_shader_init(gpu_shader_t *shader, const void *data, size_t length, gpu_ shader->impl.name[i - 3] = source[i]; } - shader->impl.source = data; + shader->impl.source = malloc(length); + memcpy(shader->impl.source, data, length); shader->impl.length = length; } diff --git a/base/sources/engine.c b/base/sources/engine.c index 932b0473..1c872fed 100644 --- a/base/sources/engine.c +++ b/base/sources/engine.c @@ -46,7 +46,7 @@ gpu_shader_t *sys_get_shader(char *name); // ╚═════╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ object_t *object_create(bool is_empty) { - object_t *raw = gc_alloc(sizeof(object_t)); + object_t *raw = calloc(1, sizeof(object_t)); raw->name = ""; raw->children = any_array_create(0); raw->visible = true; @@ -54,7 +54,7 @@ object_t *object_create(bool is_empty) { raw->uid = _object_uid_counter++; raw->transform = transform_create(raw); raw->is_empty = is_empty; - raw->_ = gc_alloc(sizeof(object_runtime_t)); + raw->_ = calloc(1, sizeof(object_runtime_t)); if (raw->is_empty) { any_array_push(scene_empties, raw); } @@ -97,6 +97,17 @@ void object_remove_super(object_t *raw) { } } +void object_free(object_t *raw) { + if (raw->owns_raw && raw->raw != NULL) { + array_delete(raw->raw->dimensions); + free(raw->raw); + } + free(raw->transform); + array_delete(raw->children); + free(raw->_); + free(raw); +} + void object_remove(object_t *raw) { if (string_equals(raw->ext_type, "mesh_object_t")) { mesh_object_remove(raw->ext); @@ -106,6 +117,7 @@ void object_remove(object_t *raw) { } else { object_remove_super(raw); + object_free(raw); } } @@ -131,7 +143,7 @@ object_t *object_get_child(object_t *raw, char *name) { // ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ transform_t *transform_create(object_t *object) { - transform_t *raw = gc_alloc(sizeof(transform_t)); + transform_t *raw = calloc(1, sizeof(transform_t)); raw->scale_world = 1.0; raw->object = object; transform_reset(raw); @@ -225,9 +237,10 @@ void transform_compute_dim(transform_t *raw) { if (raw->object->raw == NULL && string_equals(raw->object->ext_type, "mesh_object_t")) { mesh_object_t *mo = (mesh_object_t *)raw->object->ext; vec4_t aabb = mesh_data_calculate_aabb(mo->data); - obj_t *o_raw = gc_alloc(sizeof(obj_t)); + obj_t *o_raw = calloc(1, sizeof(obj_t)); o_raw->dimensions = f32_array_create_xyz(aabb.x, aabb.y, aabb.z); raw->object->raw = o_raw; + raw->object->owns_raw = true; } if (raw->object->raw == NULL || raw->object->raw->dimensions == NULL) { @@ -310,7 +323,7 @@ world_data_t *world_data_parse(char *name, char *id) { return NULL; } - raw->_ = gc_alloc(sizeof(world_data_runtime_t)); + raw->_ = calloc(1, sizeof(world_data_runtime_t)); raw->_->radiance_mipmaps = any_array_create(0); raw->_->irradiance = world_data_set_irradiance(raw); @@ -349,7 +362,6 @@ world_data_t *world_data_get_raw_by_name(any_array_t *datas, char *name) { f32_array_t *world_data_get_empty_irradiance() { if (_world_data_empty_irr == NULL) { _world_data_empty_irr = f32_array_create(28); - gc_root(_world_data_empty_irr); for (i32 i = 0; i < _world_data_empty_irr->length; ++i) { _world_data_empty_irr->buffer[i] = 0.0; } @@ -386,7 +398,7 @@ void world_data_load_envmap(world_data_t *raw) { i32 _material_data_uid_counter = 0; material_data_t *material_data_create(material_data_t *raw, char *file) { - raw->_ = gc_alloc(sizeof(material_data_runtime_t)); + raw->_ = calloc(1, sizeof(material_data_runtime_t)); raw->_->uid = (float)(++_material_data_uid_counter); // Start from 1 any_array_t *ref = string_split(raw->shader, "/"); @@ -443,7 +455,7 @@ material_context_t *material_data_get_context(material_data_t *raw, char *name) } void material_context_load(material_context_t *raw) { - raw->_ = gc_alloc(sizeof(material_context_runtime_t)); + raw->_ = calloc(1, sizeof(material_context_runtime_t)); if (raw->bind_textures != NULL && raw->bind_textures->length > 0) { raw->_->textures = any_array_create(0); for (i32 i = 0; i < (i32)raw->bind_textures->length; ++i) { @@ -526,7 +538,7 @@ shader_context_t *shader_data_get_context(shader_data_t *raw, char *name) { void shader_context_load(shader_context_t *raw) { if (raw->_ == NULL) { - raw->_ = gc_alloc(sizeof(shader_context_runtime_t)); + raw->_ = calloc(1, sizeof(shader_context_runtime_t)); } shader_context_parse_vertex_struct(raw); shader_context_compile(raw); @@ -630,9 +642,9 @@ void shader_context_compile(shader_context_t *raw) { raw->_->pipe->fragment_shader = sys_get_shader(raw->fragment_shader); raw->_->pipe->vertex_shader = sys_get_shader(raw->vertex_shader); #else - buffer_t *vs_buffer = data_get_blob(string("%s%s", raw->vertex_shader, shader_data_ext())); + buffer_t *vs_buffer = data_get_blob(string_tmp("%s%s", raw->vertex_shader, shader_data_ext())); raw->_->pipe->vertex_shader = gpu_create_shader(vs_buffer, GPU_SHADER_TYPE_VERTEX); - buffer_t *fs_buffer = data_get_blob(string("%s%s", raw->fragment_shader, shader_data_ext())); + buffer_t *fs_buffer = data_get_blob(string_tmp("%s%s", raw->fragment_shader, shader_data_ext())); raw->_->pipe->fragment_shader = gpu_create_shader(fs_buffer, GPU_SHADER_TYPE_FRAGMENT); #endif } @@ -820,7 +832,7 @@ mesh_data_t *mesh_data_get_raw_by_name(any_array_t *datas, char *name) { } mesh_data_t *mesh_data_create(mesh_data_t *raw) { - raw->_ = gc_alloc(sizeof(mesh_data_runtime_t)); + raw->_ = calloc(1, sizeof(mesh_data_runtime_t)); if (raw->scale_pos == 0.0) { raw->scale_pos = 1.0; } @@ -940,6 +952,25 @@ vec4_t mesh_data_calculate_aabb(mesh_data_t *raw) { void mesh_data_delete(mesh_data_t *raw) { gpu_delete_buffer(raw->_->vertex_buffer); gpu_delete_buffer(raw->_->index_buffer); + if (raw->_->owns_arrays) { + // Skip armpack meshes pointing to a decoded blob + for (i32 i = 0; i < raw->vertex_arrays->length; ++i) { + vertex_array_t *va = raw->vertex_arrays->buffer[i]; + if (va->values != NULL) { + array_free(va->values); + free(va->values); + } + free(va); + } + array_free(raw->vertex_arrays); + free(raw->vertex_arrays); + if (raw->index_array != NULL) { + array_free(raw->index_array); + free(raw->index_array); + } + free(raw->_); + free(raw); + } } // ███╗ ███╗███████╗███████╗██╗ ██╗ ██████╗ ██████╗ ██╗███████╗ ██████╗████████╗ @@ -950,7 +981,7 @@ void mesh_data_delete(mesh_data_t *raw) { // ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ mesh_object_t *mesh_object_create(mesh_data_t *data, material_data_t *material) { - mesh_object_t *raw = gc_alloc(sizeof(mesh_object_t)); + mesh_object_t *raw = calloc(1, sizeof(mesh_object_t)); raw->frustum_culling = true; raw->base = object_create(false); raw->base->ext = raw; @@ -970,6 +1001,8 @@ void mesh_object_set_data(mesh_object_t *raw, mesh_data_t *data) { void mesh_object_remove(mesh_object_t *raw) { array_remove(scene_meshes, raw); object_remove_super(raw->base); + object_free(raw->base); + free(raw); } bool mesh_object_cull_material(mesh_object_t *raw, char *context) { @@ -1031,9 +1064,7 @@ void mesh_object_render(mesh_object_t *raw, char *context, string_array_t *bind_ if (scontext->_->pipe != _mesh_object_last_pipeline) { gpu_set_pipeline(scontext->_->pipe); - gc_unroot(_mesh_object_last_pipeline); _mesh_object_last_pipeline = scontext->_->pipe; - gc_root(_mesh_object_last_pipeline); } uniforms_set_context_consts(scontext, bind_params); uniforms_set_obj_consts(scontext, raw->base); @@ -1055,7 +1086,7 @@ bool mesh_object_valid_context(mesh_object_t *raw, material_data_t *mat, char *c // ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ camera_object_t *camera_object_create(camera_data_t *data) { - camera_object_t *raw = gc_alloc(sizeof(camera_object_t)); + camera_object_t *raw = calloc(1, sizeof(camera_object_t)); raw->no_jitter_p = mat4_identity(); raw->frame = 0; raw->base = object_create(false); @@ -1097,6 +1128,14 @@ void camera_object_build_proj(camera_object_t *raw, f32 screen_aspect) { void camera_object_remove(camera_object_t *raw) { array_remove(scene_cameras, raw); object_remove_super(raw->base); + object_free(raw->base); + if (raw->frustum_planes != NULL) { + for (i32 i = 0; i < raw->frustum_planes->length; ++i) { + free(raw->frustum_planes->buffer[i]); + } + array_delete(raw->frustum_planes); + } + free(raw); } void camera_object_proj_jitter(camera_object_t *raw) { @@ -1186,7 +1225,7 @@ bool camera_object_sphere_in_frustum(frustum_plane_array_t *frustum_planes, tran // ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝ frustum_plane_t *frustum_plane_create() { - frustum_plane_t *raw = gc_alloc(sizeof(frustum_plane_t)); + frustum_plane_t *raw = calloc(1, sizeof(frustum_plane_t)); raw->normal = (vec4_t){1.0, 0.0, 0.0, 0.0}; raw->constant = 0.0; return raw; @@ -1526,7 +1565,7 @@ bool uniforms_set_context_const(i32 location, shader_const_t *c) { v.y = (-zfar * znear) / (zfar - znear); } else if (starts_with(c->link, "_size(")) { - char *tex = substring(c->link, 6, string_length(c->link) - 1); + char *tex = string_tmp("%.*s", string_length(c->link) - 7, c->link + 6); gpu_texture_t *image = uniforms_tex_links != NULL ? uniforms_tex_links(NULL, NULL, tex) : NULL; if (image != NULL) { v.x = (f32)image->width; @@ -1854,6 +1893,9 @@ buffer_t *iron_load_blob(char *file); gpu_texture_t *iron_load_texture(char *file); void gpu_delete_texture(gpu_texture_t *texture); void *iron_load_sound(char *file); +#ifdef WITH_EMBED +bool embed_owns(uint8_t *buffer); +#endif char *data_path(void) { #ifdef IRON_ANDROID @@ -1864,11 +1906,11 @@ char *data_path(void) { } bool data_is_abs(char *file) { - return char_at(file, 0)[0] == '/' || char_at(file, 1)[0] == ':' || (char_at(file, 0)[0] == '\\' && char_at(file, 1)[0] == '\\'); + return file[0] == '/' || (file[0] != '\0' && file[1] == ':') || (file[0] == '\\' && file[1] == '\\'); } bool data_is_up(char *file) { - return char_at(file, 0)[0] == '.' && char_at(file, 1)[0] == '.'; + return file[0] == '.' && file[1] == '.'; } char *data_resolve_path(char *file) { @@ -1886,7 +1928,6 @@ char *data_resolve_path(char *file) { mesh_data_t *data_get_mesh(char *file, char *name) { if (data_cached_meshes == NULL) { data_cached_meshes = any_map_create(); - gc_root(data_cached_meshes); } char *handle = string("%s%s", file, name); mesh_data_t *cached = (mesh_data_t *)any_map_get(data_cached_meshes, handle); @@ -1894,7 +1935,7 @@ mesh_data_t *data_get_mesh(char *file, char *name) { return cached; } mesh_data_t *b = mesh_data_parse(file, name); - any_map_set(data_cached_meshes, handle, b); + any_map_set(data_cached_meshes, string_copy(handle), b); b->_->handle = handle; return b; } @@ -1902,7 +1943,6 @@ mesh_data_t *data_get_mesh(char *file, char *name) { camera_data_t *data_get_camera(char *file, char *name) { if (data_cached_cameras == NULL) { data_cached_cameras = any_map_create(); - gc_root(data_cached_cameras); } char *handle = string("%s%s", file, name); camera_data_t *cached = (camera_data_t *)any_map_get(data_cached_cameras, handle); @@ -1910,14 +1950,13 @@ camera_data_t *data_get_camera(char *file, char *name) { return cached; } camera_data_t *b = camera_data_parse(file, name); - any_map_set(data_cached_cameras, handle, b); + any_map_set(data_cached_cameras, string_copy(handle), b); return b; } material_data_t *data_get_material(char *file, char *name) { if (data_cached_materials == NULL) { data_cached_materials = any_map_create(); - gc_root(data_cached_materials); } char *handle = string("%s%s", file, name); material_data_t *cached = (material_data_t *)any_map_get(data_cached_materials, handle); @@ -1925,14 +1964,13 @@ material_data_t *data_get_material(char *file, char *name) { return cached; } material_data_t *b = material_data_parse(file, name); - any_map_set(data_cached_materials, handle, b); + any_map_set(data_cached_materials, string_copy(handle), b); return b; } world_data_t *data_get_world(char *file, char *name) { if (data_cached_worlds == NULL) { data_cached_worlds = any_map_create(); - gc_root(data_cached_worlds); } char *handle = string("%s%s", file, name); world_data_t *cached = (world_data_t *)any_map_get(data_cached_worlds, handle); @@ -1940,14 +1978,13 @@ world_data_t *data_get_world(char *file, char *name) { return cached; } world_data_t *b = world_data_parse(file, name); - any_map_set(data_cached_worlds, handle, b); + any_map_set(data_cached_worlds, string_copy(handle), b); return b; } shader_data_t *data_get_shader(char *file, char *name) { if (data_cached_shaders == NULL) { data_cached_shaders = any_map_create(); - gc_root(data_cached_shaders); } // Only one context override per shader data for now char *handle = name; // Shader must have unique name @@ -1956,14 +1993,13 @@ shader_data_t *data_get_shader(char *file, char *name) { return cached; } shader_data_t *b = shader_data_parse(file, name); - any_map_set(data_cached_shaders, handle, b); + any_map_set(data_cached_shaders, string_copy(handle), b); return b; } scene_t *data_get_scene_raw(char *file) { if (data_cached_scene_raws == NULL) { data_cached_scene_raws = any_map_create(); - gc_root(data_cached_scene_raws); } scene_t *cached = (scene_t *)any_map_get(data_cached_scene_raws, file); if (cached != NULL) { @@ -1973,21 +2009,20 @@ scene_t *data_get_scene_raw(char *file) { char *ext = ends_with(file, ".arm") ? "" : ".arm"; buffer_t *b = data_get_blob(string("%s%s", file, ext)); scene_t *parsed = (scene_t *)armpack_decode(b); - any_map_set(data_cached_scene_raws, file, parsed); + any_map_set(data_cached_scene_raws, string_copy(file), parsed); return parsed; } buffer_t *data_get_blob(char *file) { if (data_cached_blobs == NULL) { data_cached_blobs = any_map_create(); - gc_root(data_cached_blobs); } buffer_t *cached = (buffer_t *)any_map_get(data_cached_blobs, file); if (cached != NULL) { return cached; } buffer_t *b = iron_load_blob(data_resolve_path(file)); - any_map_set(data_cached_blobs, file, b); + any_map_set(data_cached_blobs, string_copy(file), b); data_assets_loaded++; return b; } @@ -1995,7 +2030,6 @@ buffer_t *data_get_blob(char *file) { gpu_texture_t *data_get_texture(char *file) { if (data_cached_textures == NULL) { data_cached_textures = any_map_create(); - gc_root(data_cached_textures); } gpu_texture_t *cached = (gpu_texture_t *)any_map_get(data_cached_textures, file); if (cached != NULL) { @@ -2005,7 +2039,7 @@ gpu_texture_t *data_get_texture(char *file) { if (b == NULL) { return NULL; } - any_map_set(data_cached_textures, file, b); + any_map_set(data_cached_textures, string_copy(file), b); data_assets_loaded++; return b; } @@ -2013,7 +2047,6 @@ gpu_texture_t *data_get_texture(char *file) { video_t *data_get_video(char *file) { if (data_cached_videos == NULL) { data_cached_videos = any_map_create(); - gc_root(data_cached_videos); } // Strip extension and use .webm char *base = substring(file, 0, string_length(file) - 4); @@ -2032,17 +2065,16 @@ video_t *data_get_video(char *file) { draw_font_t *data_get_font(char *file) { if (data_cached_fonts == NULL) { data_cached_fonts = any_map_create(); - gc_root(data_cached_fonts); } draw_font_t *cached = (draw_font_t *)any_map_get(data_cached_fonts, file); if (cached != NULL) { return cached; } buffer_t *blob = iron_load_blob(data_resolve_path(file)); - draw_font_t *b = gc_alloc(sizeof(draw_font_t)); + draw_font_t *b = calloc(1, sizeof(draw_font_t)); b->buf = blob; b->index = 0; - any_map_set(data_cached_fonts, file, b); + any_map_set(data_cached_fonts, string_copy(file), b); data_assets_loaded++; return b; } @@ -2050,14 +2082,13 @@ draw_font_t *data_get_font(char *file) { sound_t *data_get_sound(char *file) { if (data_cached_sounds == NULL) { data_cached_sounds = any_map_create(); - gc_root(data_cached_sounds); } sound_t *cached = (sound_t *)any_map_get(data_cached_sounds, file); if (cached != NULL) { return cached; } sound_t *b = iron_load_sound(data_resolve_path(file)); - any_map_set(data_cached_sounds, file, b); + any_map_set(data_cached_sounds, string_copy(file), b); data_assets_loaded++; return b; } @@ -2097,6 +2128,14 @@ void data_delete_blob(char *handle) { return; } map_delete(data_cached_blobs, handle); +#ifdef WITH_EMBED + if (embed_owns(blob->buffer)) { + free(blob); + return; + } +#endif + free(blob->buffer); + free(blob); } void data_delete_texture(char *handle) { @@ -2158,59 +2197,41 @@ i32 _scene_objects_count = 0; object_t *scene_create(scene_t *format) { _scene_uid = _scene_uid_counter++; - gc_unroot(scene_meshes); scene_meshes = any_array_create(0); - gc_root(scene_meshes); - gc_unroot(scene_cameras); scene_cameras = any_array_create(0); - gc_root(scene_cameras); - gc_unroot(scene_empties); scene_empties = any_array_create(0); - gc_root(scene_empties); - gc_unroot(scene_embedded); scene_embedded = any_map_create(); - gc_root(scene_embedded); - gc_unroot(_scene_root); _scene_root = object_create(true); - gc_root(_scene_root); _scene_root->name = format->name; - gc_unroot(_scene_raw); _scene_raw = format; - gc_root(_scene_raw); - gc_unroot(scene_world); scene_world = data_get_world(format->name, format->world_ref); - gc_root(scene_world); // Startup scene scene_add_scene(format->name); - gc_unroot(scene_camera); scene_camera = (camera_object_t *)scene_cameras->buffer[0]; // format->camera_ref - gc_root(scene_camera); return _scene_root; } void scene_remove(void) { - for (i32 i = 0; i < scene_meshes->length; ++i) { - mesh_object_t *o = (mesh_object_t *)scene_meshes->buffer[i]; - mesh_object_remove(o); + while (scene_meshes->length > 0) { + mesh_object_remove((mesh_object_t *)scene_meshes->buffer[0]); } - for (i32 i = 0; i < scene_cameras->length; ++i) { - camera_object_t *o = (camera_object_t *)scene_cameras->buffer[i]; - camera_object_remove(o); + while (scene_cameras->length > 0) { + camera_object_remove((camera_object_t *)scene_cameras->buffer[0]); } - for (i32 i = 0; i < scene_empties->length; ++i) { - object_t *o = (object_t *)scene_empties->buffer[i]; - object_remove(o); + while (scene_empties->length > 0) { + object_remove((object_t *)scene_empties->buffer[0]); } - object_remove(_scene_root); + _scene_root = NULL; + scene_camera = NULL; } object_t *scene_set_active(char *scene_name) { @@ -2405,6 +2426,11 @@ object_t *scene_return_mesh_object(char *object_file, char *data_ref, material_d object_t *scene_return_object(object_t *object, obj_t *o) { if (object != NULL) { + if (object->owns_raw && object->raw != NULL) { + array_delete(object->raw->dimensions); + free(object->raw); + object->owns_raw = false; + } object->raw = o; object->name = o->name; object->visible = o->visible; @@ -2495,11 +2521,9 @@ void render_path_set_target(char *target, string_array_t *additional, char *dept render_path_end(); } - gc_unroot(_mesh_object_last_pipeline); _mesh_object_last_pipeline = NULL; if (string_equals(target, "")) { // Framebuffer - gc_unroot(_render_path_current_target); _render_path_current_target = NULL; render_path_current_w = sys_w(); render_path_current_h = sys_h(); @@ -2508,40 +2532,34 @@ void render_path_set_target(char *target, string_array_t *additional, char *dept } else { // Render target render_target_t *rt = (render_target_t *)any_map_get(render_path_render_targets, target); - gc_unroot(_render_path_current_target); _render_path_current_target = rt; - gc_root(_render_path_current_target); - any_array_t *additional_images = NULL; + static any_array_t additional_images_scratch = {0}; + any_array_t *additional_images = NULL; if (additional != NULL) { - additional_images = any_array_create(0); + additional_images_scratch.length = 0; for (i32 i = 0; i < additional->length; ++i) { char *s = (char *)additional->buffer[i]; render_target_t *t = (render_target_t *)any_map_get(render_path_render_targets, s); - any_array_push(additional_images, t->_image); + any_array_push(&additional_images_scratch, t->_image); } + additional_images = &additional_images_scratch; } render_path_current_w = rt->_image->width; render_path_current_h = rt->_image->height; render_target_t *db = depth_buffer != NULL ? (render_target_t *)any_map_get(render_path_render_targets, depth_buffer) : NULL; - gc_unroot(_render_path_current_image); _render_path_current_image = rt->_image; - gc_root(_render_path_current_image); _gpu_begin(rt->_image, additional_images, db != NULL ? db->_image : NULL, flags, color, depth); } - gc_unroot(_render_path_bind_params); _render_path_bind_params = NULL; } void render_path_end(void) { gpu_end(); - gc_unroot(_render_path_current_image); _render_path_current_image = NULL; - gc_unroot(_render_path_bind_params); _render_path_bind_params = NULL; } void render_path_draw_meshes(char *context) { - gc_unroot(_mesh_object_last_pipeline); _mesh_object_last_pipeline = NULL; any_array_t *meshes = scene_meshes; for (i32 i = 0; i < meshes->length; ++i) { @@ -2566,17 +2584,13 @@ void render_path_draw_skydome(char *handle) { } void render_path_bind_target(char *target, char *uniform) { - if (_render_path_bind_params != NULL) { - string_array_push(_render_path_bind_params, target); - string_array_push(_render_path_bind_params, uniform); - } - else { - _render_path_bind_params = string_array_create(2); - gc_root(_render_path_bind_params); - _render_path_bind_params->buffer[0] = target; - _render_path_bind_params->buffer[1] = uniform; - _render_path_bind_params->length = 2; + static string_array_t bind_params = {0}; + if (_render_path_bind_params == NULL) { + bind_params.length = 0; + _render_path_bind_params = &bind_params; } + string_array_push(_render_path_bind_params, target); + string_array_push(_render_path_bind_params, uniform); } void render_path_draw_shader(char *handle) { @@ -2599,7 +2613,6 @@ void render_path_load_shader(char *handle) { _render_path_loading++; if (_render_path_cached_shader_contexts == NULL) { _render_path_cached_shader_contexts = any_map_create(); - gc_root(_render_path_cached_shader_contexts); } cached_shader_context_t *cc = (cached_shader_context_t *)any_map_get(_render_path_cached_shader_contexts, handle); if (cc != NULL) { @@ -2607,14 +2620,15 @@ void render_path_load_shader(char *handle) { return; } - cc = gc_alloc(sizeof(cached_shader_context_t)); - any_map_set(_render_path_cached_shader_contexts, handle, cc); + cc = calloc(1, sizeof(cached_shader_context_t)); + any_map_set(_render_path_cached_shader_contexts, string_copy(handle), cc); // Callers may pass frame-temporary handles // file/data_name/context any_array_t *shader_path = string_split(handle, "/"); shader_data_t *res = data_get_shader((char *)shader_path->buffer[0], (char *)shader_path->buffer[1]); cc->context = shader_data_get_context(res, (char *)shader_path->buffer[2]); + string_split_free(shader_path); _render_path_loading--; } @@ -2631,12 +2645,13 @@ void render_path_resize(void) { rt->_image = render_path_create_image(rt); } } + array_free(render_targets_keys); + free(render_targets_keys); } render_target_t *render_path_create_render_target(render_target_t *t) { if (render_path_render_targets == NULL) { render_path_render_targets = any_map_create(); - gc_root(render_path_render_targets); } t->_image = render_path_create_image(t); any_map_set(render_path_render_targets, t->name, t); @@ -2683,7 +2698,7 @@ gpu_texture_format_t render_path_get_tex_format(char *s) { } render_target_t *render_target_create(void) { - render_target_t *raw = gc_alloc(sizeof(render_target_t)); + render_target_t *raw = calloc(1, sizeof(render_target_t)); raw->scale = 1.0; return raw; } diff --git a/base/sources/engine.h b/base/sources/engine.h index 3741eea0..c45e1df9 100644 --- a/base/sources/engine.h +++ b/base/sources/engine.h @@ -4,7 +4,7 @@ #include "iron_array.h" #include "iron_audio.h" #include "iron_draw.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_gpu.h" #include "iron_map.h" #include "iron_math.h" @@ -106,6 +106,7 @@ typedef struct mesh_data_runtime { gpu_vertex_structure_t structure; buffer_t *skin_blob; // Source file bytes i32 skin_frames; + bool owns_arrays; } mesh_data_runtime_t; typedef struct mesh_data { @@ -329,6 +330,7 @@ typedef struct object { bool visible; bool culled; bool is_empty; + bool owns_raw; void *ext; char *ext_type; object_runtime_t *_; @@ -346,6 +348,7 @@ extern i32 _object_uid_counter; object_t *object_create(bool is_empty); void object_set_parent(object_t *raw, object_t *parent_object); void object_remove_super(object_t *raw); +void object_free(object_t *raw); void object_remove(object_t *raw); object_t *object_get_child(object_t *raw, char *name); diff --git a/base/sources/iron.h b/base/sources/iron.h index 5bc81de4..6bb10999 100644 --- a/base/sources/iron.h +++ b/base/sources/iron.h @@ -7,7 +7,7 @@ #include "iron_array.h" #include "iron_draw.h" #include "iron_file.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_gpu.h" #include "iron_json.h" #include "iron_lz4.h" @@ -62,6 +62,15 @@ buffer_t *embed_get(char *key) { } return NULL; } + +bool embed_owns(uint8_t *buffer) { + for (int i = 0; i < embed_count; ++i) { + if (embed_values[i] == buffer) { + return true; + } + } + return false; +} #endif void _kickstart(); @@ -147,13 +156,11 @@ int kickstart(int argc, char **argv) { iron_threads_init(); iron_display_init(); - gc_start(&argc); _kickstart(); #ifdef IRON_AUDIO iron_a2_shutdown(); #endif - gc_stop(); return 0; } @@ -236,11 +243,9 @@ void _update() { #endif return; } - if (paused_frames == 30) { - gc_run(); - } #endif + string_tmp_reset(); iron_net_update(); iron_update(); if (ui_get_current()) @@ -842,6 +847,10 @@ gpu_texture_t *gpu_create_texture_from_encoded_bytes(buffer_t *data, char *forma void gpu_delete_texture(gpu_texture_t *texture) { gpu_texture_destroy(texture); + if (texture->buffer != NULL) { // Cached by gpu_get_texture_pixels + free(texture->buffer->buffer); + free(texture->buffer); + } free(texture); } @@ -862,9 +871,11 @@ gpu_texture_t *iron_load_texture(char *file) { iron_file_reader_read(&reader, data, size); iron_file_reader_close(&reader); buffer_t buf; - buf.buffer = data; - buf.length = size; - return gpu_create_texture_from_encoded_bytes(&buf, file); + buf.buffer = data; + buf.length = size; + gpu_texture_t *texture = gpu_create_texture_from_encoded_bytes(&buf, file); + free(data); // Encoded bytes are decoded into a separate buffer + return texture; } void *iron_load_sound(char *file) { @@ -895,6 +906,20 @@ buffer_t *iron_load_blob(char *file) { return buffer; } +void iron_delete_blob(buffer_t *buffer) { + if (buffer == NULL) { + return; + } +#ifdef WITH_EMBED + if (embed_owns(buffer->buffer)) { + free(buffer); + return; + } +#endif + array_free(buffer); + free(buffer); +} + i32 iron_display_ppi(i32 index) { return iron_display_current_mode(index).pixels_per_inch; } diff --git a/base/sources/iron_alloc.h b/base/sources/iron_alloc.h new file mode 100644 index 00000000..0171ea39 --- /dev/null +++ b/base/sources/iron_alloc.h @@ -0,0 +1,10 @@ +#pragma once + +#include "iron_string.h" +#include +#include + +// point_t *p = ALLOC_INIT(point_t, {x: 1.5, y: 3.5}); +#define ALLOC_INIT(type, ...) (type *)memcpy(malloc(sizeof(type)), (type[]){__VA_ARGS__}, sizeof(type)) + +#define TMP_ALLOC_INIT(type, ...) (type *)memcpy(string_tmp_alloc(sizeof(type)), (type[]){__VA_ARGS__}, sizeof(type)) diff --git a/base/sources/iron_armpack.c b/base/sources/iron_armpack.c index 3c4b1e72..c2b68039 100644 --- a/base/sources/iron_armpack.c +++ b/base/sources/iron_armpack.c @@ -1,7 +1,7 @@ #include "iron_armpack.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_json.h" #include "iron_string.h" #include @@ -251,9 +251,8 @@ static uint8_t flag_to_byte_size(uint8_t flag) { static void store_typed_array(uint8_t flag, uint32_t count) { uint32_t size = flag_to_byte_size(flag) * count; if (size > 4096) { - void *data = gc_alloc(size); + void *data = calloc(1, size); memcpy(data, encoded + ei, size); - gc_leaf(data); *(uintptr_t *)(decoded + di - 4 - 4 - PTR_SIZE) = (uintptr_t)data; // Set buffer ptr *(uint32_t *)(decoded + di - 4) = count; // Set capacity } @@ -406,7 +405,7 @@ void *armpack_decode(buffer_t *b) { encoded = b->buffer; capacity = traverse(0, true); reset(); - decoded = gc_alloc(capacity); + decoded = calloc(1, capacity); read_store(); return decoded; } @@ -592,7 +591,7 @@ uint32_t armpack_size_bool() { static char *read_string_alloc() { char *s = read_string(); - char *allocated = gc_alloc(str_len + 1); + char *allocated = calloc(1, str_len + 1); memcpy(allocated, s, str_len); allocated[str_len] = '\0'; return allocated; diff --git a/base/sources/iron_array.c b/base/sources/iron_array.c index e3db638c..8bb970f6 100644 --- a/base/sources/iron_array.c +++ b/base/sources/iron_array.c @@ -1,6 +1,6 @@ #include "iron_array.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_string.h" #include #include @@ -8,13 +8,22 @@ void array_free(void *a) { u8_array_t *tmp = (u8_array_t *)a; - gc_free(tmp->buffer); + free(tmp->buffer); tmp->buffer = NULL; tmp->length = tmp->capacity = 0; } -static void *gc_realloc_no_free(void *ptr, size_t old_size, size_t new_size) { - void *buffer = gc_alloc(new_size); +void array_delete(void *a) { + if (a == NULL) { + return; + } + array_free(a); + free(a); +} + +// Old buffer may point into an armpack blob +static void *alloc_no_free(void *ptr, size_t old_size, size_t new_size) { + void *buffer = calloc(1, new_size); memcpy(buffer, ptr, old_size); return buffer; } @@ -27,14 +36,11 @@ static void array_alloc(void *a, uint8_t element_size) { tmp->capacity = tmp->length + 1; size_t old_size = tmp->length * element_size; size_t new_size = tmp->capacity * element_size; - tmp->buffer = gc_realloc_no_free(tmp->buffer, old_size, new_size); + tmp->buffer = alloc_no_free(tmp->buffer, old_size, new_size); } else { tmp->capacity *= 2; - tmp->buffer = gc_realloc(tmp->buffer, tmp->capacity * element_size); - } - if (element_size < 8) { - gc_leaf(tmp->buffer); + tmp->buffer = realloc(tmp->buffer, tmp->capacity * element_size); } } } @@ -86,60 +92,52 @@ void string_array_push(string_array_t *a, void *e) { void i8_array_resize(i8_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(int8_t)); - gc_leaf(a->buffer); + a->buffer = realloc(a->buffer, a->capacity * sizeof(int8_t)); } void u8_array_resize(u8_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(uint8_t)); - gc_leaf(a->buffer); + a->buffer = realloc(a->buffer, a->capacity * sizeof(uint8_t)); } void i16_array_resize(i16_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(int16_t)); - gc_leaf(a->buffer); + a->buffer = realloc(a->buffer, a->capacity * sizeof(int16_t)); } void u16_array_resize(u16_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(uint16_t)); - gc_leaf(a->buffer); + a->buffer = realloc(a->buffer, a->capacity * sizeof(uint16_t)); } void i32_array_resize(i32_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(int32_t)); - gc_leaf(a->buffer); + a->buffer = realloc(a->buffer, a->capacity * sizeof(int32_t)); } void u32_array_resize(u32_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(uint32_t)); - gc_leaf(a->buffer); + a->buffer = realloc(a->buffer, a->capacity * sizeof(uint32_t)); } void f32_array_resize(f32_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(float)); - gc_leaf(a->buffer); + a->buffer = realloc(a->buffer, a->capacity * sizeof(float)); } void any_array_resize(any_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(void *)); + a->buffer = realloc(a->buffer, a->capacity * sizeof(void *)); } void string_array_resize(string_array_t *a, uint32_t size) { a->capacity = size; - a->buffer = gc_realloc(a->buffer, a->capacity * sizeof(void *)); + a->buffer = realloc(a->buffer, a->capacity * sizeof(void *)); } void buffer_resize(buffer_t *b, uint32_t size) { b->length = size; - b->buffer = gc_realloc(b->buffer, b->length * sizeof(uint8_t)); - gc_leaf(b->buffer); + b->buffer = realloc(b->buffer, b->length * sizeof(uint8_t)); } static int _array_sort_alpha(const void *a, const void *b) { @@ -208,7 +206,7 @@ void i32_array_splice(i32_array_t *ar, uint32_t start, uint32_t delete_count) { } any_array_t *array_concat(any_array_t *a, any_array_t *b) { - any_array_t *ar = gc_alloc(sizeof(any_array_t)); + any_array_t *ar = calloc(1, sizeof(any_array_t)); ar->length = a->length + b->length; any_array_resize(ar, ar->length); for (uint32_t i = 0; i < a->length; ++i) { @@ -221,7 +219,7 @@ any_array_t *array_concat(any_array_t *a, any_array_t *b) { } any_array_t *array_slice(any_array_t *a, uint32_t begin, uint32_t end) { - any_array_t *ar = gc_alloc(sizeof(any_array_t)); + any_array_t *ar = calloc(1, sizeof(any_array_t)); ar->length = end - begin; any_array_resize(ar, ar->length); for (uint32_t i = 0; i < ar->length; ++i) { @@ -296,7 +294,7 @@ void array_reverse(any_array_t *ar) { } buffer_t *buffer_slice(buffer_t *a, uint32_t begin, uint32_t end) { - buffer_t *b = gc_alloc(sizeof(buffer_t)); + buffer_t *b = calloc(1, sizeof(buffer_t)); buffer_resize(b, end - begin); for (uint32_t i = 0; i < b->length; ++i) { b->buffer[i] = a->buffer[begin + i]; @@ -385,13 +383,13 @@ void buffer_set_f32(buffer_t *b, uint32_t p, float n) { } buffer_t *buffer_create(uint32_t length) { - buffer_t *b = gc_alloc(sizeof(buffer_t)); + buffer_t *b = calloc(1, sizeof(buffer_t)); buffer_resize(b, length); return b; } buffer_t *buffer_create_from_raw(uint8_t *raw, uint32_t length) { - buffer_t *b = gc_alloc(sizeof(buffer_t)); + buffer_t *b = calloc(1, sizeof(buffer_t)); b->buffer = raw; b->length = length; b->capacity = length; @@ -399,7 +397,7 @@ buffer_t *buffer_create_from_raw(uint8_t *raw, uint32_t length) { } f32_array_t *f32_array_create(uint32_t length) { - f32_array_t *a = gc_alloc(sizeof(f32_array_t)); + f32_array_t *a = calloc(1, sizeof(f32_array_t)); if (length > 0) { f32_array_resize(a, length); a->length = length; @@ -408,7 +406,7 @@ f32_array_t *f32_array_create(uint32_t length) { } f32_array_t *f32_array_create_from_buffer(buffer_t *b) { - f32_array_t *a = gc_alloc(sizeof(f32_array_t)); + f32_array_t *a = calloc(1, sizeof(f32_array_t)); a->buffer = b->buffer; a->length = b->length / 4; a->capacity = b->length / 4; @@ -431,6 +429,19 @@ f32_array_t *f32_array_create_from_raw(float *raw, uint32_t length) { return a; } +f32_array_t *f32_array_create_from_raw_tmp(float *raw, uint32_t length) { + f32_array_t *a = (f32_array_t *)string_tmp_alloc(sizeof(f32_array_t)); + a->buffer = (float *)string_tmp_alloc(length * sizeof(float)); + a->length = length; + a->capacity = length; + if (raw != NULL) { + for (uint32_t i = 0; i < length; ++i) { + a->buffer[i] = raw[i]; + } + } + return a; +} + f32_array_t *f32_array_create_x(float x) { f32_array_t *a = f32_array_create(1); a->buffer[0] = x; @@ -472,7 +483,7 @@ f32_array_t *f32_array_create_xyzwv(float x, float y, float z, float w, float v) } u32_array_t *u32_array_create(uint32_t length) { - u32_array_t *a = gc_alloc(sizeof(u32_array_t)); + u32_array_t *a = calloc(1, sizeof(u32_array_t)); if (length > 0) { u32_array_resize(a, length); a->length = length; @@ -497,7 +508,7 @@ u32_array_t *u32_array_create_from_raw(uint32_t *raw, uint32_t length) { } i32_array_t *i32_array_create(uint32_t length) { - i32_array_t *a = gc_alloc(sizeof(i32_array_t)); + i32_array_t *a = calloc(1, sizeof(i32_array_t)); if (length > 0) { i32_array_resize(a, length); a->length = length; @@ -522,7 +533,7 @@ i32_array_t *i32_array_create_from_raw(int32_t *raw, uint32_t length) { } u16_array_t *u16_array_create(uint32_t length) { - u16_array_t *a = gc_alloc(sizeof(u16_array_t)); + u16_array_t *a = calloc(1, sizeof(u16_array_t)); if (length > 0) { u16_array_resize(a, length); a->length = length; @@ -539,7 +550,7 @@ u16_array_t *u16_array_create_from_raw(uint16_t *raw, uint32_t length) { } i16_array_t *i16_array_create(uint32_t length) { - i16_array_t *a = gc_alloc(sizeof(i16_array_t)); + i16_array_t *a = calloc(1, sizeof(i16_array_t)); if (length > 0) { i16_array_resize(a, length); a->length = length; @@ -564,7 +575,7 @@ i16_array_t *i16_array_create_from_raw(int16_t *raw, uint32_t length) { } u8_array_t *u8_array_create(uint32_t length) { - u8_array_t *a = gc_alloc(sizeof(u8_array_t)); + u8_array_t *a = calloc(1, sizeof(u8_array_t)); if (length > 0) { u8_array_resize(a, length); a->length = length; @@ -597,13 +608,13 @@ u8_array_t *u8_array_create_from_string(char *s) { } char *u8_array_to_string(u8_array_t *a) { - char *r = gc_alloc(a->length + 1); + char *r = calloc(1, a->length + 1); memcpy(r, a->buffer, a->length); return r; } i8_array_t *i8_array_create(uint32_t length) { - i8_array_t *a = gc_alloc(sizeof(i8_array_t)); + i8_array_t *a = calloc(1, sizeof(i8_array_t)); if (length > 0) { i8_array_resize(a, length); a->length = length; @@ -620,7 +631,7 @@ i8_array_t *i8_array_create_from_raw(int8_t *raw, uint32_t length) { } any_array_t *any_array_create(uint32_t length) { - any_array_t *a = gc_alloc(sizeof(any_array_t)); + any_array_t *a = calloc(1, sizeof(any_array_t)); if (length > 0) { any_array_resize(a, length); a->length = length; @@ -636,8 +647,21 @@ any_array_t *any_array_create_from_raw(void **raw, uint32_t length) { return a; } +any_array_t *any_array_create_from_raw_tmp(void **raw, uint32_t length) { + any_array_t *a = (any_array_t *)string_tmp_alloc(sizeof(any_array_t)); + a->buffer = (void **)string_tmp_alloc(length * sizeof(void *)); + a->length = length; + a->capacity = length; + if (raw != NULL) { + for (uint32_t i = 0; i < length; ++i) { + a->buffer[i] = raw[i]; + } + } + return a; +} + string_array_t *string_array_create(uint32_t length) { - string_array_t *a = gc_alloc(sizeof(string_array_t)); + string_array_t *a = calloc(1, sizeof(string_array_t)); if (length > 0) { string_array_resize(a, length); a->length = length; diff --git a/base/sources/iron_array.h b/base/sources/iron_array.h index 96973fc9..751b6cce 100644 --- a/base/sources/iron_array.h +++ b/base/sources/iron_array.h @@ -58,7 +58,8 @@ typedef struct string_array { typedef u8_array_t buffer_t; -void array_free(void *a); +void array_free(void *a); // Releases the buffer, keeps the struct +void array_delete(void *a); // Releases the buffer and the struct, not the elements void i8_array_push(i8_array_t *a, int8_t e); void u8_array_push(u8_array_t *a, uint8_t e); void i16_array_push(i16_array_t *a, int16_t e); @@ -123,6 +124,7 @@ f32_array_t *f32_array_create(uint32_t length); f32_array_t *f32_array_create_from_buffer(buffer_t *b); f32_array_t *f32_array_create_from_array(f32_array_t *from); f32_array_t *f32_array_create_from_raw(float *raw, uint32_t length); +f32_array_t *f32_array_create_from_raw_tmp(float *raw, uint32_t length); f32_array_t *f32_array_create_x(float x); f32_array_t *f32_array_create_xy(float x, float y); f32_array_t *f32_array_create_xyz(float x, float y, float z); @@ -148,6 +150,7 @@ i8_array_t *i8_array_create(uint32_t length); i8_array_t *i8_array_create_from_raw(int8_t *raw, uint32_t length); any_array_t *any_array_create(uint32_t length); any_array_t *any_array_create_from_raw(void **raw, uint32_t length); +any_array_t *any_array_create_from_raw_tmp(void **raw, uint32_t length); string_array_t *string_array_create(uint32_t length); uint16_t float_to_half_fast(float value); uint8_t half_to_u8_fast(uint16_t h); diff --git a/base/sources/iron_draw.c b/base/sources/iron_draw.c index 52d99715..73b909f8 100644 --- a/base/sources/iron_draw.c +++ b/base/sources/iron_draw.c @@ -1,7 +1,7 @@ #include "iron_draw.h" #include "const_data.h" #include "iron_file.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_gpu.h" #include "iron_math.h" #include "iron_simd.h" @@ -124,6 +124,9 @@ void draw_init(buffer_t *image_vert, buffer_t *image_frag, buffer_t *rect_vert, draw_pipeline_init(&image_r8_pipeline, &vert_shader, &frag_shader); image_r8_pipeline.color_attachment[0] = GPU_TEXTURE_FORMAT_R8; gpu_pipeline_compile(&image_r8_pipeline); + + gpu_shader_destroy(&vert_shader); + gpu_shader_destroy(&frag_shader); } // Rect painter @@ -133,6 +136,9 @@ void draw_init(buffer_t *image_vert, buffer_t *image_frag, buffer_t *rect_vert, draw_pipeline_init(&rect_pipeline, &vert_shader, &frag_shader); rect_pipeline.blend_source = GPU_BLEND_SOURCE_ALPHA; gpu_pipeline_compile(&rect_pipeline); + + gpu_shader_destroy(&vert_shader); + gpu_shader_destroy(&frag_shader); } // Tris painter @@ -142,6 +148,9 @@ void draw_init(buffer_t *image_vert, buffer_t *image_frag, buffer_t *rect_vert, draw_pipeline_init(&tris_pipeline, &vert_shader, &frag_shader); tris_pipeline.blend_source = GPU_BLEND_SOURCE_ALPHA; gpu_pipeline_compile(&tris_pipeline); + + gpu_shader_destroy(&vert_shader); + gpu_shader_destroy(&frag_shader); } // Text painter @@ -156,6 +165,9 @@ void draw_init(buffer_t *image_vert, buffer_t *image_frag, buffer_t *rect_vert, draw_pipeline_init(&text_rt_pipeline, &vert_shader, &frag_shader); text_rt_pipeline.blend_source = GPU_BLEND_SOURCE_ALPHA; gpu_pipeline_compile(&text_rt_pipeline); + + gpu_shader_destroy(&vert_shader); + gpu_shader_destroy(&frag_shader); } } @@ -672,8 +684,6 @@ void draw_font_13(draw_font_t *font) { } void draw_font_init_glyphs(int from, int to) { - gc_unroot(draw_font_glyphs); - gc_unroot(draw_font_glyph_blocks); draw_font_glyphs = i32_array_create(to - from); for (int i = from; i < to; ++i) { @@ -684,8 +694,6 @@ void draw_font_init_glyphs(int from, int to) { draw_font_glyph_blocks->buffer[1] = to - 1; draw_glyphs_version++; - gc_root(draw_font_glyphs); - gc_root(draw_font_glyph_blocks); } bool draw_font_has_glyph(int glyph) { @@ -709,9 +717,7 @@ void draw_font_build_glyphs() { ++pos; } - gc_unroot(draw_font_glyph_blocks); draw_font_glyph_blocks = i32_array_create(2 * blocks); - gc_root(draw_font_glyph_blocks); draw_font_glyph_blocks->buffer[0] = draw_font_glyphs->buffer[0]; next_char = draw_font_glyphs->buffer[0] + 1; diff --git a/base/sources/iron_file.c b/base/sources/iron_file.c index 1c2dc207..ca57d265 100644 --- a/base/sources/iron_file.c +++ b/base/sources/iron_file.c @@ -1,6 +1,6 @@ #include "iron_file.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_json.h" #include "iron_map.h" #include "iron_net.h" @@ -509,7 +509,7 @@ any_array_t *file_read_directory(char *path) { return files; } else { - return gc_alloc(sizeof(any_array_t)); + return calloc(1, sizeof(any_array_t)); } } @@ -525,7 +525,6 @@ any_array_t *file_read_directory(char *path) { buffer_t *blob = data_get_blob("data_list.json"); char *s = sys_buffer_to_string(blob); file_internal = json_parse_to_map(s); - gc_root(file_internal); } if (any_map_get(file_internal, path) != NULL) { return string_split(any_map_get(file_internal, path), ","); @@ -595,7 +594,6 @@ static void _file_download_to_callback(char *url, buffer_t *ab) { void file_download_to(char *url, char *dst_path, void (*done)(char *url), i32 size) { if (_file_download_map == NULL) { _file_download_map = any_map_create(); - gc_root(_file_download_map); } file_download_data_t *fdd = malloc(sizeof(file_download_data_t)); fdd->done = done; @@ -618,7 +616,6 @@ static void _file_cache_cloud_callback(char *url) { void file_cache_cloud(char *path, void (*done)(char *dest), char *server) { if (_file_cache_cloud_map == NULL) { _file_cache_cloud_map = any_map_create(); - gc_root(_file_cache_cloud_map); } char dest[512]; @@ -658,14 +655,14 @@ void file_cache_cloud(char *path, void (*done)(char *dest), char *server) { static void _file_init_cloud_bytes_callback(char *url, buffer_t *buffer) { if (buffer == NULL) { - any_array_t *empty = gc_alloc(sizeof(any_array_t)); + any_array_t *empty = calloc(1, sizeof(any_array_t)); any_map_set(file_cloud, "cloud", empty); console_error(strings_check_internet_connection()); return; } - any_array_t *files = gc_alloc(sizeof(any_array_t)); - i32_array_t *sizes = gc_alloc(sizeof(i32_array_t)); + any_array_t *files = calloc(1, sizeof(any_array_t)); + i32_array_t *sizes = calloc(1, sizeof(i32_array_t)); char *str = sys_buffer_to_string(buffer); i32 str_len = string_length(str); i32 pos_start = 0; @@ -689,7 +686,7 @@ static void _file_init_cloud_bytes_callback(char *url, buffer_t *buffer) { for (i32 i = 0; i < (i32)files->length; ++i) { char *file = files->buffer[i]; if (path_is_folder(file)) { - any_array_t *empty = gc_alloc(sizeof(any_array_t)); + any_array_t *empty = calloc(1, sizeof(any_array_t)); any_map_set(file_cloud, substring(file, 0, string_length(file) - 1), empty); } } @@ -721,8 +718,6 @@ void file_init_cloud_bytes(void (*done)(void), char *append, char *server) { void file_init_cloud(void (*done)(void), char *server) { file_cloud = any_map_create(); - gc_root(file_cloud); file_cloud_sizes = i32_map_create(); - gc_root(file_cloud_sizes); file_init_cloud_bytes(done, NULL, server); } diff --git a/base/sources/iron_gc.c b/base/sources/iron_gc.c deleted file mode 100644 index 32de075a..00000000 --- a/base/sources/iron_gc.c +++ /dev/null @@ -1,448 +0,0 @@ - -#include "iron_gc.h" - -// A simple mark and sweep garbage collector for C. - -#ifdef NO_GC - -#include - -void *gc_alloc(size_t size) { - return calloc(size, 1); -} - -void gc_leaf(void *ptr) {} -void gc_root(void *ptr) {} -void gc_unroot(void *ptr) {} -void gc_resize(void *ptr, size_t size) {} - -void *gc_realloc(void *ptr, size_t size) { - return realloc(ptr, size); -} - -void gc_free(void *ptr) { - free(ptr); -} - -void gc_pause() {} -void gc_resume() {} -void gc_run() {} -void gc_start(void *bos) {} -void gc_stop() {} - -#else - -#include -#include -#include - -#define PTRSIZE sizeof(char *) - -#define GC_TAG_NONE 0x0 -#define GC_TAG_LEAF 0x1 -#define GC_TAG_MARK 0x2 -#define GC_TAG_ROOT 0x4 - -#if defined(_MSC_VER) && !defined(__clang__) -#define __builtin_frame_address(x) ((void)(x), _AddressOfReturnAddress()) -#endif - -typedef struct gc_allocation { - void *ptr; // mem pointer - size_t size; // allocated size in bytes - char tag; // the tag for mark-and-sweep - char roots; // number of root users - struct gc_allocation *next; // separate chaining -} gc_allocation_t; - -typedef struct gc_allocation_map { - size_t capacity; - size_t min_capacity; - double downsize_factor; - double upsize_factor; - double sweep_factor; - size_t sweep_limit; - size_t size; - gc_allocation_t **allocs; -} gc_allocation_map_t; - -typedef struct garbage_collector { - struct gc_allocation_map *allocs; // allocation map - bool paused; // (temporarily) switch gc on/off - void *bos; // bottom of stack -} garbage_collector_t; - -static garbage_collector_t _gc; -static garbage_collector_t *gc = &_gc; - -static gc_allocation_t *gc_allocation_new(void *ptr, size_t size) { - gc_allocation_t *a = (gc_allocation_t *)malloc(sizeof(gc_allocation_t)); - a->ptr = ptr; - a->size = size; - a->tag = GC_TAG_NONE; - a->roots = 0; - a->next = NULL; - return a; -} - -static void gc_allocation_delete(gc_allocation_t *a) { - free(a); -} - -static gc_allocation_map_t *gc_allocation_map_new(size_t min_capacity, size_t capacity, double sweep_factor, double downsize_factor, double upsize_factor) { - gc_allocation_map_t *am = (gc_allocation_map_t *)malloc(sizeof(gc_allocation_map_t)); - am->min_capacity = min_capacity; - am->capacity = capacity; - am->sweep_factor = sweep_factor; - am->sweep_limit = (int)(sweep_factor * am->capacity); - am->downsize_factor = downsize_factor; - am->upsize_factor = upsize_factor; - am->allocs = (gc_allocation_t **)calloc(am->capacity, sizeof(gc_allocation_t *)); - am->size = 0; - return am; -} - -static void gc_allocation_map_delete(gc_allocation_map_t *am) { - // Iterate over the map - gc_allocation_t *alloc; - gc_allocation_t *tmp; - for (size_t i = 0; i < am->capacity; ++i) { - if ((alloc = am->allocs[i])) { - // Make sure to follow the chain inside a bucket - while (alloc) { - tmp = alloc; - alloc = alloc->next; - // free the management structure - gc_allocation_delete(tmp); - } - } - } - free(am->allocs); - free(am); -} - -static size_t gc_hash(void *ptr) { - return ((uintptr_t)ptr) >> 3; -} - -static void gc_allocation_map_resize(gc_allocation_map_t *am, size_t new_capacity) { - if (new_capacity <= am->min_capacity) { - return; - } - // Replaces the existing items array in the hash table - // with a resized one and pushes items into the new, correct buckets - gc_allocation_t **resized_allocs = calloc(new_capacity, sizeof(gc_allocation_t *)); - - for (size_t i = 0; i < am->capacity; ++i) { - gc_allocation_t *alloc = am->allocs[i]; - while (alloc) { - gc_allocation_t *next_alloc = alloc->next; - size_t new_index = gc_hash(alloc->ptr) & (new_capacity - 1); - alloc->next = resized_allocs[new_index]; - resized_allocs[new_index] = alloc; - alloc = next_alloc; - } - } - free(am->allocs); - am->capacity = new_capacity; - am->allocs = resized_allocs; - am->sweep_limit = am->size + am->sweep_factor * (am->capacity - am->size); -} - -static bool gc_allocation_map_resize_to_fit(gc_allocation_map_t *am) { - double load_factor = (double)am->size / (double)am->capacity; - if (load_factor > am->upsize_factor) { - gc_allocation_map_resize(am, am->capacity * 2); - return true; - } - if (load_factor < am->downsize_factor) { - gc_allocation_map_resize(am, am->capacity / 2); - return true; - } - return false; -} - -static gc_allocation_t *gc_allocation_map_get(gc_allocation_map_t *am, void *ptr) { - size_t index = gc_hash(ptr) & (am->capacity - 1); // % am->capacity - gc_allocation_t *cur = am->allocs[index]; - while (cur) { - if (cur->ptr == ptr) { - return cur; - } - cur = cur->next; - } - return NULL; -} - -static gc_allocation_t *gc_allocation_map_put(gc_allocation_map_t *am, gc_allocation_t *alloc) { - size_t index = gc_hash(alloc->ptr) & (am->capacity - 1); - gc_allocation_t *cur = am->allocs[index]; - gc_allocation_t *prev = NULL; - /* Upsert if ptr is already known */ - while (cur != NULL) { - if (cur->ptr == alloc->ptr) { - // found it - alloc->next = cur->next; - if (!prev) { - // position 0 - am->allocs[index] = alloc; - } - else { - // in the list - prev->next = alloc; - } - gc_allocation_delete(cur); - return alloc; - } - prev = cur; - cur = cur->next; - } - /* Insert at the front of the separate chaining list */ - cur = am->allocs[index]; - alloc->next = cur; - am->allocs[index] = alloc; - am->size++; - void *p = alloc->ptr; - if (gc_allocation_map_resize_to_fit(am)) { - alloc = gc_allocation_map_get(am, p); - } - return alloc; -} - -static void gc_allocation_map_remove(gc_allocation_map_t *am, void *ptr, bool allow_resize) { - // ignores unknown keys - size_t index = gc_hash(ptr) & (am->capacity - 1); - gc_allocation_t *cur = am->allocs[index]; - gc_allocation_t *prev = NULL; - gc_allocation_t *next; - while (cur != NULL) { - next = cur->next; - if (cur->ptr == ptr) { - // found it - if (!prev) { - // first item in list - am->allocs[index] = cur->next; - } - else { - // not the first item in the list - prev->next = cur->next; - } - gc_allocation_delete(cur); - am->size--; - } - else { - // move on - prev = cur; - } - cur = next; - } - if (allow_resize) { - gc_allocation_map_resize_to_fit(am); - } -} - -static void gc_mark_alloc(void *ptr) { - gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr); - /* Mark if alloc exists and is not tagged already, otherwise skip */ - if (alloc && !(alloc->tag & GC_TAG_MARK)) { - alloc->tag |= GC_TAG_MARK; - if (!(alloc->tag & GC_TAG_LEAF)) { // Skip contents - /* Iterate over allocation contents and mark them as well */ - for (void **p = (void **)alloc->ptr; (char *)p <= (char *)alloc->ptr + alloc->size - PTRSIZE; ++p) { - gc_mark_alloc(*p); - } - } - } -} - -static void gc_mark_stack() { - void *tos = __builtin_frame_address(0); - void *bos = gc->bos; - /* The stack grows towards smaller memory addresses, hence we scan tos->bos. - * Stop scanning once the distance between tos & bos is too small to hold a valid pointer */ - for (void **p = (void **)tos; (char *)p <= (char *)bos - PTRSIZE; ++p) { - gc_mark_alloc(*p); - } -} - -static void gc_mark_roots() { - for (size_t i = 0; i < gc->allocs->capacity; ++i) { - gc_allocation_t *chunk = gc->allocs->allocs[i]; - while (chunk) { - if (chunk->tag & GC_TAG_ROOT) { - gc_mark_alloc(chunk->ptr); - } - chunk = chunk->next; - } - } -} - -static void gc_mark() { - /* Note: We only look at the stack and the heap, and ignore BSS. */ - /* Scan the heap for roots */ - gc_mark_roots(); - /* Dump registers onto stack and scan the stack */ - void (*volatile _mark_stack)(void) = gc_mark_stack; - jmp_buf ctx; - memset(&ctx, 0, sizeof(jmp_buf)); - setjmp(ctx); - _mark_stack(); -} - -static size_t gc_sweep() { - size_t total = 0; - for (size_t i = 0; i < gc->allocs->capacity; ++i) { - gc_allocation_t *chunk = gc->allocs->allocs[i]; - gc_allocation_t *next = NULL; - /* Iterate over separate chaining */ - while (chunk) { - if (chunk->tag & GC_TAG_MARK) { - /* unmark */ - chunk->tag &= ~GC_TAG_MARK; - chunk = chunk->next; - } - else { - /* no reference to this chunk, hence delete it */ - total += chunk->size; - free(chunk->ptr); - /* and remove it from the bookkeeping */ - next = chunk->next; - gc_allocation_map_remove(gc->allocs, chunk->ptr, false); - chunk = next; - } - } - } - gc_allocation_map_resize_to_fit(gc->allocs); - return total; -} - -void *gc_alloc(size_t size) { - if (size == 0) { - size = 1; - } - /* Check if we reached the high-water mark and need to clean up */ - if (gc->allocs->size > gc->allocs->sweep_limit && !gc->paused) { - gc_run(); - } - /* With cleanup out of the way, attempt to allocate memory */ - void *ptr = calloc(size, sizeof(uint8_t)); - /* If allocation fails, force an out-of-policy run to free some memory and try again. */ - if (!ptr && !gc->paused) { - gc_run(); - ptr = calloc(size, sizeof(uint8_t)); - } - /* Start managing the memory we received from the system */ - if (ptr) { - gc_allocation_t *alloc = gc_allocation_map_put(gc->allocs, gc_allocation_new(ptr, size)); - /* Deal with metadata allocation failure */ - if (alloc) { - ptr = alloc->ptr; - } - else { - /* We failed to allocate the metadata, fail cleanly. */ - free(ptr); - ptr = NULL; - } - } - return ptr; -} - -void gc_leaf(void *ptr) { - gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr); - if (alloc) { - alloc->tag |= GC_TAG_LEAF; - } -} - -void gc_root(void *ptr) { - gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr); - if (alloc) { - alloc->roots++; - alloc->tag |= GC_TAG_ROOT; - } -} - -void gc_unroot(void *ptr) { - gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr); - if (alloc) { - alloc->roots--; - if (alloc->roots == 0) { - alloc->tag &= ~GC_TAG_ROOT; - } - } -} - -void gc_resize(void *ptr, size_t size) { - // Narrows the range gc_mark_alloc walks - gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr); - if (alloc) { - alloc->size = size; - } -} - -void *gc_realloc(void *ptr, size_t size) { - if (ptr == NULL) { - return gc_alloc(size); - } - gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr); - if (!alloc) { - // the user passed an unknown pointer - return NULL; - } - void *q = realloc(ptr, size); - if (!q) { - // realloc failed but ptr is still valid - return NULL; - } - if (ptr == q) { - // successful reallocation w/o copy - alloc->size = size; - } - else { - // successful reallocation w/ copy - gc_allocation_map_remove(gc->allocs, ptr, true); - gc_allocation_map_put(gc->allocs, gc_allocation_new(q, size)); - } - return q; -} - -void gc_free(void *ptr) { - if (ptr == NULL) { - return; - } - gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr); - if (alloc) { - free(ptr); - gc_allocation_map_remove(gc->allocs, ptr, true); - } -} - -void gc_pause() { - gc->paused = true; -} - -void gc_resume() { - gc->paused = false; -} - -void gc_run() { - // double t = iron_time(); - gc_mark(); - gc_sweep(); - // iron_log("gc took %fms, freed %db.\n", (iron_time() - t) * 1000, collected); -} - -void gc_start(void *bos) { - gc->paused = false; - gc->bos = bos; - // Create allocation map with no downsizing - // Capacity must be a power of two - gc->allocs = gc_allocation_map_new(1024 * 1024, 1024 * 1024, 0.5, 0.0, 0.8); -} - -void gc_stop() { - gc_sweep(); - gc_allocation_map_delete(gc->allocs); -} - -#endif diff --git a/base/sources/iron_gc.h b/base/sources/iron_gc.h deleted file mode 100644 index d8df09ed..00000000 --- a/base/sources/iron_gc.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include -#include - -// point_t *p = GC_ALLOC_INIT(point_t, {x: 1.5, y: 3.5}); -#define GC_ALLOC_INIT(type, ...) (type *)memcpy(gc_alloc(sizeof(type)), (type[]){__VA_ARGS__}, sizeof(type)) - -void *gc_alloc(size_t size); -void gc_leaf(void *ptr); -void gc_root(void *ptr); -void gc_unroot(void *ptr); -void gc_resize(void *ptr, size_t size); -void *gc_realloc(void *ptr, size_t size); -void gc_free(void *ptr); -void gc_pause(); -void gc_resume(); -void gc_run(); -void gc_start(void *bos); -void gc_stop(); diff --git a/base/sources/iron_input.c b/base/sources/iron_input.c index f7d385a2..e5cbceae 100644 --- a/base/sources/iron_input.c +++ b/base/sources/iron_input.c @@ -1,6 +1,6 @@ #include "iron_input.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_string.h" #include "iron_system.h" #include @@ -105,7 +105,6 @@ void input_register(void) { _input_occupied = false; _mouse_buttons = string_array_create(0); - gc_root(_mouse_buttons); string_array_push(_mouse_buttons, "left"); string_array_push(_mouse_buttons, "right"); string_array_push(_mouse_buttons, "middle"); @@ -113,11 +112,8 @@ void input_register(void) { string_array_push(_mouse_buttons, "side2"); _mouse_buttons_down = u8_array_create(0); - gc_root(_mouse_buttons_down); _mouse_buttons_started = u8_array_create(0); - gc_root(_mouse_buttons_started); _mouse_buttons_released = u8_array_create(0); - gc_root(_mouse_buttons_released); for (i32 i = 0; i < 5; ++i) { u8_array_push(_mouse_buttons_down, 0); u8_array_push(_mouse_buttons_started, 0); @@ -140,15 +136,11 @@ void input_register(void) { #endif pen_buttons = string_array_create(0); - gc_root(pen_buttons); string_array_push(pen_buttons, "tip"); pen_buttons_down = u8_array_create(0); - gc_root(pen_buttons_down); pen_buttons_started = u8_array_create(0); - gc_root(pen_buttons_started); pen_buttons_released = u8_array_create(0); - gc_root(pen_buttons_released); u8_array_push(pen_buttons_down, 0); u8_array_push(pen_buttons_started, 0); u8_array_push(pen_buttons_released, 0); @@ -165,7 +157,6 @@ void input_register(void) { pen_last_y = -1.0f; keyboard_keys = string_array_create(0); - gc_root(keyboard_keys); string_array_push(keyboard_keys, "a"); string_array_push(keyboard_keys, "b"); string_array_push(keyboard_keys, "c"); @@ -261,21 +252,16 @@ void input_register(void) { string_array_push(keyboard_keys, "f12"); keyboard_keys_down = i32_map_create(); - gc_root(keyboard_keys_down); keyboard_keys_started = i32_map_create(); - gc_root(keyboard_keys_started); keyboard_keys_released = i32_map_create(); - gc_root(keyboard_keys_released); keyboard_keys_frame = string_array_create(0); - gc_root(keyboard_keys_frame); keyboard_repeat_key = false; keyboard_repeat_time = 0.0f; #ifdef WITH_GAMEPAD gamepad_buttons_ps = string_array_create(0); - gc_root(gamepad_buttons_ps); string_array_push(gamepad_buttons_ps, "cross"); string_array_push(gamepad_buttons_ps, "circle"); string_array_push(gamepad_buttons_ps, "square"); @@ -296,7 +282,6 @@ void input_register(void) { string_array_push(gamepad_buttons_ps, "touchpad"); gamepad_buttons_xbox = string_array_create(0); - gc_root(gamepad_buttons_xbox); string_array_push(gamepad_buttons_xbox, "a"); string_array_push(gamepad_buttons_xbox, "b"); string_array_push(gamepad_buttons_xbox, "x"); @@ -319,7 +304,6 @@ void input_register(void) { gamepad_buttons = gamepad_buttons_ps; gamepad_raws = any_array_create(0); - gc_root(gamepad_raws); #endif keyboard_reset(); @@ -892,7 +876,7 @@ void keyboard_up_listener(i32 code) { void gamepad_end_frame(void) {} gamepad_stick_t *gamepad_stick_create(void) { - gamepad_stick_t *raw = gc_alloc(sizeof(gamepad_stick_t)); + gamepad_stick_t *raw = calloc(1, sizeof(gamepad_stick_t)); raw->x = 0.0f; raw->y = 0.0f; raw->last_x = 0.0f; @@ -904,7 +888,7 @@ gamepad_stick_t *gamepad_stick_create(void) { } gamepad_t *gamepad_create(void) { - gamepad_t *raw = gc_alloc(sizeof(gamepad_t)); + gamepad_t *raw = calloc(1, sizeof(gamepad_t)); raw->buttons_down = f32_array_create(0); raw->buttons_started = u8_array_create(0); raw->buttons_released = u8_array_create(0); @@ -915,9 +899,7 @@ gamepad_t *gamepad_create(void) { } void gamepad_reset(void) { - gc_unroot(gamepad_raws); gamepad_raws = any_array_create(0); - gc_root(gamepad_raws); for (i32 i = 0; i < 4; ++i) { gamepad_t *g = gamepad_create(); any_array_push(gamepad_raws, g); diff --git a/base/sources/iron_json.c b/base/sources/iron_json.c index 98a290ce..b90fd5c9 100644 --- a/base/sources/iron_json.c +++ b/base/sources/iron_json.c @@ -7,7 +7,6 @@ #include #include -void *gc_alloc(size_t size); #ifdef IRON_WASM #define PTR_SIZE 4 @@ -286,7 +285,7 @@ void *json_parse(char *s) { load_tokens(s); uint32_t out_size = strlen(s) * 2; - decoded = gc_alloc(out_size); + decoded = calloc(1, out_size); wi = 0; bottom = 0; array_count = 1; @@ -331,36 +330,48 @@ any_map_t *json_parse_to_map(char *s) { return m; } -static char *encoded; -static int keys; -static int array_nest = -1; -static int array_length[16]; +static buffer_t encoded; +static int keys; +static int array_nest = -1; +static int array_length[16]; + +static void enc(char *s) { + string_buffer_append(&encoded, s); +} void json_encode_begin() { - encoded = "{"; - keys = 0; + if (encoded.buffer == NULL) { + string_buffer_init(&encoded); + } + string_buffer_reset(&encoded); + enc("{"); + keys = 0; } char *json_encode_end() { - encoded = string("%s}", encoded); - return encoded; + enc("}"); + return string_copy(string_buffer_get(&encoded)); } void json_encode_key(char *k) { if (keys > 0) { - encoded = string("%s,", encoded); + enc(","); } - encoded = string("%s\"%s\":", encoded, k); + enc("\""); + enc(k); + enc("\":"); keys++; } void json_encode_null(char *k) { json_encode_key(k); - encoded = string("%snull", encoded); + enc("null"); } void json_encode_string_value(char *v) { - encoded = string("%s\"%s\"", encoded, v); + enc("\""); + enc(v); + enc("\""); } void json_encode_string(char *k, char *v) { @@ -376,7 +387,7 @@ void json_encode_string_array(char *k, string_array_t *a) { json_encode_begin_array(k); for (uint32_t i = 0; i < a->length; ++i) { if (i > 0) { - encoded = string("%s,", encoded); + enc(","); } json_encode_string_value(a->buffer[i]); } @@ -385,12 +396,12 @@ void json_encode_string_array(char *k, string_array_t *a) { void json_encode_f32(char *k, float f) { json_encode_key(k); - encoded = string("%s%s", encoded, f32_to_string_with_zeros(f)); + enc(f32_to_string_with_zeros(f)); } void json_encode_i32(char *k, int i) { json_encode_key(k); - encoded = string("%s%s", encoded, i32_to_string(i)); + enc(i32_to_string(i)); } void json_encode_f32_array(char *k, f32_array_t *a) { @@ -401,9 +412,9 @@ void json_encode_f32_array(char *k, f32_array_t *a) { json_encode_begin_array(k); for (uint32_t i = 0; i < a->length; ++i) { if (i > 0) { - encoded = string("%s,", encoded); + enc(","); } - encoded = string("%s%s", encoded, f32_to_string_with_zeros(a->buffer[i])); + enc(f32_to_string_with_zeros(a->buffer[i])); } json_encode_end_array(); } @@ -416,43 +427,43 @@ void json_encode_i32_array(char *k, i32_array_t *a) { json_encode_begin_array(k); for (uint32_t i = 0; i < a->length; ++i) { if (i > 0) { - encoded = string("%s,", encoded); + enc(","); } - encoded = string("%s%s", encoded, i32_to_string(a->buffer[i])); + enc(i32_to_string(a->buffer[i])); } json_encode_end_array(); } void json_encode_bool(char *k, bool b) { json_encode_key(k); - encoded = string("%s%s", encoded, b ? "true" : "false"); + enc(b ? "true" : "false"); } void json_encode_begin_array(char *k) { array_nest++; array_length[array_nest] = 0; json_encode_key(k); - encoded = string("%s[", encoded); + enc("["); } void json_encode_end_array() { array_nest--; - encoded = string("%s]", encoded); + enc("]"); } void json_encode_begin_object() { if (array_nest > -1) { if (array_length[array_nest] > 0) { - encoded = string("%s,", encoded); + enc(","); } array_length[array_nest]++; } - keys = 0; - encoded = string("%s{", encoded); + keys = 0; + enc("{"); } void json_encode_end_object() { - encoded = string("%s}", encoded); + enc("}"); } void json_encode_map(any_map_t *m) { @@ -460,6 +471,8 @@ void json_encode_map(any_map_t *m) { for (uint32_t i = 0; i < keys->length; i++) { json_encode_string(keys->buffer[i], any_map_get(m, keys->buffer[i])); } + array_free(keys); + free(keys); } static char *jenc_src; diff --git a/base/sources/iron_lz4.c b/base/sources/iron_lz4.c index d9f811e5..9c6b2c3a 100644 --- a/base/sources/iron_lz4.c +++ b/base/sources/iron_lz4.c @@ -3,7 +3,7 @@ // armorpaint/base/assets/licenses/license_lz4-wasm.md #include "iron_lz4.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_system.h" #include #include @@ -28,7 +28,6 @@ buffer_t *lz4_encode(buffer_t *b) { if (_lz4_hash_table == NULL) { _lz4_hash_table = i32_array_create(65536); - gc_root(_lz4_hash_table); } for (uint32_t i = 0; i < _lz4_hash_table->length; ++i) { _lz4_hash_table->buffer[i] = -65536; @@ -136,7 +135,10 @@ buffer_t *lz4_encode(buffer_t *b) { obuf->buffer[opos++] = ibuf->buffer[anchor_pos++]; } - return buffer_slice(obuf, 0, opos); + buffer_t *result = buffer_slice(obuf, 0, opos); + array_free(obuf); + free(obuf); + return result; } buffer_t *lz4_decode(buffer_t *b, uint32_t olen) { diff --git a/base/sources/iron_map.c b/base/sources/iron_map.c index 18b3e105..d9a87070 100644 --- a/base/sources/iron_map.c +++ b/base/sources/iron_map.c @@ -1,6 +1,6 @@ #include "iron_map.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_string.h" static size_t hash(const char *k) { @@ -56,12 +56,9 @@ static void resize(any_map_t *m, int elem_size) { int cap = m->keys->capacity == 0 ? 16 : m->keys->capacity * 2; any_map_t *tmp = any_map_create(); tmp->keys->capacity = cap; - tmp->keys->buffer = gc_alloc(cap * sizeof(void *)); + tmp->keys->buffer = calloc(1, cap * sizeof(void *)); tmp->values->capacity = cap; - tmp->values->buffer = gc_alloc(cap * elem_size); - if (elem_size < 8) { - gc_leaf(tmp->values->buffer); - } + tmp->values->buffer = calloc(1, cap * elem_size); any_array_t *old_keys = map_keys(m); for (int i = 0; i < old_keys->length; ++i) { @@ -78,8 +75,16 @@ static void resize(any_map_t *m, int elem_size) { } } + array_free(old_keys); + free(old_keys); + + array_free(m->keys); + free(m->keys); + array_free(m->values); + free(m->values); m->keys = tmp->keys; m->values = tmp->values; + free(tmp); } void i32_map_set(i32_map_t *m, char *k, int v) { @@ -144,7 +149,7 @@ void map_delete(any_map_t *m, char *k) { } any_array_t *map_keys(any_map_t *m) { - string_array_t *keys = gc_alloc(sizeof(string_array_t)); + string_array_t *keys = calloc(1, sizeof(string_array_t)); string_array_resize(keys, m->keys->length); for (int i = 0; i < m->keys->capacity; ++i) { if (m->keys->buffer[i] != NULL) { @@ -154,17 +159,29 @@ any_array_t *map_keys(any_map_t *m) { return keys; } +// Stored keys and values are not owned by the map +void map_free(any_map_t *m) { + if (m == NULL) { + return; + } + array_free(m->keys); + free(m->keys); + array_free(m->values); + free(m->values); + free(m); +} + i32_map_t *i32_map_create() { - i32_map_t *r = gc_alloc(sizeof(i32_map_t)); - r->keys = gc_alloc(sizeof(string_array_t)); - r->values = gc_alloc(sizeof(i32_array_t)); + i32_map_t *r = calloc(1, sizeof(i32_map_t)); + r->keys = calloc(1, sizeof(string_array_t)); + r->values = calloc(1, sizeof(i32_array_t)); return r; } any_map_t *any_map_create() { - any_map_t *r = gc_alloc(sizeof(any_map_t)); - r->keys = gc_alloc(sizeof(string_array_t)); - r->values = gc_alloc(sizeof(any_array_t)); + any_map_t *r = calloc(1, sizeof(any_map_t)); + r->keys = calloc(1, sizeof(string_array_t)); + r->values = calloc(1, sizeof(any_array_t)); return r; } @@ -223,15 +240,15 @@ i32_array_t *imap_keys(any_imap_t *m) { } i32_imap_t *i32_imap_create() { - i32_imap_t *r = gc_alloc(sizeof(i32_imap_t)); - r->keys = gc_alloc(sizeof(i32_array_t)); - r->values = gc_alloc(sizeof(i32_array_t)); + i32_imap_t *r = calloc(1, sizeof(i32_imap_t)); + r->keys = calloc(1, sizeof(i32_array_t)); + r->values = calloc(1, sizeof(i32_array_t)); return r; } any_imap_t *any_imap_create() { - any_imap_t *r = gc_alloc(sizeof(any_imap_t)); - r->keys = gc_alloc(sizeof(i32_array_t)); - r->values = gc_alloc(sizeof(any_array_t)); + any_imap_t *r = calloc(1, sizeof(any_imap_t)); + r->keys = calloc(1, sizeof(i32_array_t)); + r->values = calloc(1, sizeof(any_array_t)); return r; } diff --git a/base/sources/iron_map.h b/base/sources/iron_map.h index 085f6574..3028be49 100644 --- a/base/sources/iron_map.h +++ b/base/sources/iron_map.h @@ -28,6 +28,7 @@ void *any_map_get(any_map_t *m, char *k); void map_delete(any_map_t *m, char *k); any_array_t *map_keys(any_map_t *m); +void map_free(any_map_t *m); i32_map_t *i32_map_create(); any_map_t *any_map_create(); diff --git a/base/sources/iron_math.c b/base/sources/iron_math.c index 0b913f68..f041af34 100644 --- a/base/sources/iron_math.c +++ b/base/sources/iron_math.c @@ -1,6 +1,6 @@ #include "iron_math.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include #include #include @@ -646,7 +646,8 @@ mat4_decomposed_t *mat4_decompose(mat4_t m) { m.m[10] *= invs; rot = quat_from_rot_mat(m); - mat4_decomposed_t *dec = gc_alloc(sizeof(mat4_decomposed_t)); + // Frame temporary.. + mat4_decomposed_t *dec = (mat4_decomposed_t *)string_tmp_alloc(sizeof(mat4_decomposed_t)); dec->loc = loc; dec->rot = rot; dec->scl = scl; diff --git a/base/sources/iron_obj.c b/base/sources/iron_obj.c index 3e62db6a..f9edf107 100644 --- a/base/sources/iron_obj.c +++ b/base/sources/iron_obj.c @@ -1,7 +1,7 @@ #include "iron_obj.h" #include "iron_array.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_math.h" #include "iron_string.h" #include @@ -220,7 +220,7 @@ raw_mesh_t *obj_parse(buffer_t *file_bytes, char split_code, uint64_t start_pos, bytes = file_bytes->buffer; bytes_length = file_bytes->length; - part = gc_alloc(sizeof(raw_mesh_t)); + part = calloc(1, sizeof(raw_mesh_t)); part->scale_pos = 1.0; part->scale_tex = 1.0; part->pos = start_pos; @@ -247,9 +247,9 @@ raw_mesh_t *obj_parse(buffer_t *file_bytes, char split_code, uint64_t start_pos, uv_temp = *uv_first; } else { - memset(&pos_temp, 0, sizeof(pos_temp)); - memset(&uv_temp, 0, sizeof(uv_temp)); - memset(&nor_temp, 0, sizeof(nor_temp)); + array_free(&pos_temp); + array_free(&uv_temp); + array_free(&nor_temp); } while (part->pos < bytes_length) { @@ -446,6 +446,7 @@ raw_mesh_t *obj_parse(buffer_t *file_bytes, char split_code, uint64_t start_pos, if (!udim) { reading_object = true; } + free(part->name); part->name = string_copy(read_string()); } else if (c0 == '\n') { // Empty line @@ -650,5 +651,5 @@ void obj_destroy(raw_mesh_t *part) { free(part->nora); free(part->texa); free(part->inda); - gc_free(part); + free(part); } diff --git a/base/sources/iron_path.c b/base/sources/iron_path.c index 0221b594..0e1ceeaa 100644 --- a/base/sources/iron_path.c +++ b/base/sources/iron_path.c @@ -1,10 +1,11 @@ #include "iron_path.h" +#include #include #include "iron_array.h" #include "iron_file.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_map.h" #include "iron_string.h" @@ -27,7 +28,6 @@ static string_array_t *_path_displacement_ext = NULL; string_array_t *path_mesh_formats(void) { if (_path_mesh_formats == NULL) { _path_mesh_formats = string_array_create(0); - gc_root(_path_mesh_formats); string_array_push(_path_mesh_formats, "obj"); string_array_push(_path_mesh_formats, "blend"); } @@ -37,7 +37,6 @@ string_array_t *path_mesh_formats(void) { string_array_t *path_texture_formats(void) { if (_path_texture_formats == NULL) { _path_texture_formats = string_array_create(0); - gc_root(_path_texture_formats); string_array_push(_path_texture_formats, "jpg"); string_array_push(_path_texture_formats, "jpeg"); string_array_push(_path_texture_formats, "png"); @@ -54,7 +53,6 @@ string_array_t *path_texture_formats(void) { string_array_t *path_sound_formats(void) { if (_path_sound_formats == NULL) { _path_sound_formats = string_array_create(0); - gc_root(_path_sound_formats); string_array_push(_path_sound_formats, "wav"); string_array_push(_path_sound_formats, "ogg"); } @@ -64,7 +62,6 @@ string_array_t *path_sound_formats(void) { string_array_t *path_text_formats(void) { if (_path_text_formats == NULL) { _path_text_formats = string_array_create(0); - gc_root(_path_text_formats); string_array_push(_path_text_formats, "txt"); string_array_push(_path_text_formats, "json"); } @@ -74,7 +71,6 @@ string_array_t *path_text_formats(void) { string_array_t *path_base_color_ext(void) { if (_path_base_color_ext == NULL) { _path_base_color_ext = string_array_create(0); - gc_root(_path_base_color_ext); string_array_push(_path_base_color_ext, "albedo"); string_array_push(_path_base_color_ext, "alb"); string_array_push(_path_base_color_ext, "basecol"); @@ -93,7 +89,6 @@ string_array_t *path_base_color_ext(void) { string_array_t *path_opacity_ext(void) { if (_path_opacity_ext == NULL) { _path_opacity_ext = string_array_create(0); - gc_root(_path_opacity_ext); string_array_push(_path_opacity_ext, "opac"); string_array_push(_path_opacity_ext, "opacity"); string_array_push(_path_opacity_ext, "alpha"); @@ -104,7 +99,6 @@ string_array_t *path_opacity_ext(void) { string_array_t *path_normal_map_ext(void) { if (_path_normal_map_ext == NULL) { _path_normal_map_ext = string_array_create(0); - gc_root(_path_normal_map_ext); string_array_push(_path_normal_map_ext, "normal"); string_array_push(_path_normal_map_ext, "normals"); string_array_push(_path_normal_map_ext, "nor"); @@ -118,7 +112,6 @@ string_array_t *path_normal_map_ext(void) { string_array_t *path_occlusion_ext(void) { if (_path_occlusion_ext == NULL) { _path_occlusion_ext = string_array_create(0); - gc_root(_path_occlusion_ext); string_array_push(_path_occlusion_ext, "ao"); string_array_push(_path_occlusion_ext, "occlusion"); string_array_push(_path_occlusion_ext, "ambientOcclusion"); @@ -131,7 +124,6 @@ string_array_t *path_occlusion_ext(void) { string_array_t *path_roughness_ext(void) { if (_path_roughness_ext == NULL) { _path_roughness_ext = string_array_create(0); - gc_root(_path_roughness_ext); string_array_push(_path_roughness_ext, "roughness"); string_array_push(_path_roughness_ext, "rough"); string_array_push(_path_roughness_ext, "r"); @@ -143,7 +135,6 @@ string_array_t *path_roughness_ext(void) { string_array_t *path_metallic_ext(void) { if (_path_metallic_ext == NULL) { _path_metallic_ext = string_array_create(0); - gc_root(_path_metallic_ext); string_array_push(_path_metallic_ext, "metallic"); string_array_push(_path_metallic_ext, "metal"); string_array_push(_path_metallic_ext, "metalness"); @@ -156,7 +147,6 @@ string_array_t *path_metallic_ext(void) { string_array_t *path_displacement_ext(void) { if (_path_displacement_ext == NULL) { _path_displacement_ext = string_array_create(0); - gc_root(_path_displacement_ext); string_array_push(_path_displacement_ext, "displacement"); string_array_push(_path_displacement_ext, "height"); string_array_push(_path_displacement_ext, "h"); @@ -165,6 +155,21 @@ string_array_t *path_displacement_ext(void) { return _path_displacement_ext; } +static bool has_ext(char *path, char *ext) { + size_t len_path = strlen(path); + size_t len_ext = strlen(ext); + if (len_path < len_ext + 1 || path[len_path - len_ext - 1] != '.') { + return false; + } + char *tail = path + len_path - len_ext; + for (size_t i = 0; i < len_ext; ++i) { + if (tolower((unsigned char)tail[i]) != tolower((unsigned char)ext[i])) { + return false; + } + } + return true; +} + static char *data_path(void) { #ifdef IRON_ANDROID return "data" PATH_SEP; @@ -181,7 +186,7 @@ char *path_to_relative(char *from, char *to) { any_array_t *a = string_split(from, PATH_SEP); any_array_t *b = string_split(to, PATH_SEP); if (a->length > 0 && !path_is_folder(from)) { - array_pop(a); + free(array_pop(a)); } while (a->length > 0 && b->length > 0) { char *a0 = a->buffer[0]; @@ -189,23 +194,36 @@ char *path_to_relative(char *from, char *to) { if (string_equals(a0, b0)) { array_shift(a); array_shift(b); + free(a0); + free(b0); } else { break; } } - char *p = ""; + + buffer_t sb; + string_buffer_init(&sb); for (uint32_t i = 0; i < a->length; ++i) { - p = string("%s.." PATH_SEP, p); + string_buffer_append(&sb, ".." PATH_SEP); } - p = string("%s%s", p, string_array_join(b, PATH_SEP)); + char *joined = string_array_join(b, PATH_SEP); + string_buffer_append(&sb, joined); + free(joined); + + char *p = string_copy(string_buffer_get(&sb)); + string_buffer_free(&sb); + string_split_free(a); + string_split_free(b); return p; } char *path_normalize(char *path) { - size_t path_len = strlen(path); + size_t path_len = strlen(path); + char *trimmed = NULL; if (path_len > 0 && ends_with(path, PATH_SEP)) { - path = substring(path, 0, path_len - 1); + trimmed = substring(path, 0, path_len - 1); + path = trimmed; } any_array_t *ar = string_split(path, PATH_SEP); uint32_t i = 0; @@ -214,6 +232,8 @@ char *path_normalize(char *path) { char *ar_i = ar->buffer[i]; char *ar_i_1 = ar->buffer[i - 1]; if (string_equals(ar_i, "..") && !string_equals(ar_i_1, "..")) { + free(ar_i); + free(ar_i_1); array_splice(ar, i - 1, 2); i--; } @@ -225,7 +245,10 @@ char *path_normalize(char *path) { i++; } } - return string_array_join(ar, PATH_SEP); + char *r = string_array_join(ar, PATH_SEP); + string_split_free(ar); + free(trimmed); + return r; } char *path_base_dir(char *path) { @@ -239,86 +262,53 @@ char *path_base_name(char *path) { return substring(path, last_sep + 1, last_dot); } -bool path_is_mesh(char *path) { - char *p = to_lower_case(path); - string_array_t *formats = path_mesh_formats(); +static bool path_has_format(char *path, string_array_t *formats) { for (uint32_t i = 0; i < formats->length; ++i) { - char *s = formats->buffer[i]; - char *ext = string(".%s", s); - if (ends_with(p, ext)) { + if (has_ext(path, formats->buffer[i])) { return true; } } return false; } +bool path_is_mesh(char *path) { + return path_has_format(path, path_mesh_formats()); +} + bool path_is_texture(char *path) { - char *p = to_lower_case(path); - string_array_t *formats = path_texture_formats(); - for (uint32_t i = 0; i < formats->length; ++i) { - char *s = formats->buffer[i]; - char *ext = string(".%s", s); - if (ends_with(p, ext)) { - return true; - } - } - return false; + return path_has_format(path, path_texture_formats()); } bool path_is_sound(char *path) { - char *p = to_lower_case(path); - string_array_t *formats = path_sound_formats(); - for (uint32_t i = 0; i < formats->length; ++i) { - char *s = formats->buffer[i]; - char *ext = string(".%s", s); - if (ends_with(p, ext)) { - return true; - } - } - return false; + return path_has_format(path, path_sound_formats()); } bool path_is_font(char *path) { - char *p = to_lower_case(path); - return ends_with(p, ".ttf") || ends_with(p, ".ttc") || ends_with(p, ".otf"); + return has_ext(path, "ttf") || has_ext(path, "ttc") || has_ext(path, "otf"); } bool path_is_project(char *path) { - char *p = to_lower_case(path); - return ends_with(p, ".arm"); + return has_ext(path, "arm"); } bool path_is_plugin(char *path) { - char *p = to_lower_case(path); - return ends_with(p, ".c"); + return has_ext(path, "c"); } bool path_is_json(char *path) { - char *p = to_lower_case(path); - return ends_with(p, ".json"); + return has_ext(path, "json"); } bool path_is_text(char *path) { - char *p = to_lower_case(path); - string_array_t *formats = path_text_formats(); - for (uint32_t i = 0; i < formats->length; ++i) { - char *s = formats->buffer[i]; - char *ext = string(".%s", s); - if (ends_with(p, ext)) { - return true; - } - } - return false; + return path_has_format(path, path_text_formats()); } bool path_is_ext_format(char *path) { - char *p = to_lower_case(path); - return ends_with(p, ".stl") || ends_with(p, ".svg"); + return has_ext(path, "stl") || has_ext(path, "svg"); } bool path_is_lut(char *path) { - char *p = to_lower_case(path); - return ends_with(p, ".cube"); + return has_ext(path, "cube"); } bool path_is_known(char *path) { @@ -326,16 +316,52 @@ bool path_is_known(char *path) { path_is_text(path) || path_is_ext_format(path) || path_is_lut(path); } -bool path_check_ext(char *p, string_array_t *exts) { - p = string_replace_all(p, "-", "_"); - for (uint32_t i = 0; i < exts->length; ++i) { - char *ext = exts->buffer[i]; - char *ext_underscore = string("_%s", ext); - if (ends_with(p, ext_underscore)) { +static char tag_char(char c) { + return c == '-' ? '_' : c; +} + +static bool ends_with_tag(char *p, char *tag) { + size_t len_p = strlen(p); + size_t len_tag = strlen(tag); + if (len_p < len_tag + 1) { + return false; + } + char *tail = p + len_p - len_tag; + if (tag_char(tail[-1]) != '_') { + return false; + } + for (size_t i = 0; i < len_tag; ++i) { + if (tag_char(tail[i]) != tag[i]) { + return false; + } + } + return true; +} + +static bool contains_tag(char *p, char *tag) { + size_t len_tag = strlen(tag); + for (char *s = p; *s != '\0'; ++s) { + if (tag_char(*s) != '_') { + continue; + } + size_t i = 0; + while (i < len_tag && tag_char(s[1 + i]) == tag[i]) { + ++i; + } + if (i == len_tag && tag_char(s[1 + len_tag]) == '_') { return true; } - char *ext_underscore_mid = string("_%s_", ext); - if (string_index_of(p, ext_underscore_mid) >= 0 && !ends_with(p, "_preview") && !ends_with(p, "_icon")) { + } + return false; +} + +bool path_check_ext(char *p, string_array_t *exts) { + for (uint32_t i = 0; i < exts->length; ++i) { + char *ext = exts->buffer[i]; + if (ends_with_tag(p, ext)) { + return true; + } + if (contains_tag(p, ext) && !ends_with_tag(p, "preview") && !ends_with_tag(p, "icon")) { return true; } } @@ -371,10 +397,13 @@ bool path_is_displacement_tex(char *p) { } bool path_is_folder(char *p) { - char *p_slash = string_replace_all(p, "\\", "/"); - any_array_t *split = string_split(p_slash, "/"); - char *last = array_pop(split); - return string_index_of(last, ".") < 0; + char *last = p; + for (char *s = p; *s != '\0'; ++s) { + if (*s == '/' || *s == '\\') { + last = s + 1; + } + } + return strchr(last, '.') == NULL; } bool path_is_protected(void) { @@ -392,10 +421,8 @@ bool path_is_protected(void) { } char *path_join(char *a, char *b) { - char *path = a; - if (!ends_with(path, PATH_SEP)) { - path = string("%s" PATH_SEP, path); + if (ends_with(a, PATH_SEP)) { + return string("%s%s", a, b); } - path = string("%s%s", path, b); - return path; + return string("%s" PATH_SEP "%s", a, b); } diff --git a/base/sources/iron_physics.c b/base/sources/iron_physics.c index 09716806..ad8b6cb0 100644 --- a/base/sources/iron_physics.c +++ b/base/sources/iron_physics.c @@ -1326,7 +1326,7 @@ static bool mesh_bounds(object_t *obj, vec4_t *center, vec4_t *extent) { } physics_body_t *physics_body_create(object_t *obj, physics_shape_t shape, float mass) { - physics_body_t *body = GC_ALLOC_INIT(physics_body_t, {0}); + physics_body_t *body = ALLOC_INIT(physics_body_t, {0}); body->shape = shape; body->mass = mass; body->obj = obj; diff --git a/base/sources/iron_raycast.c b/base/sources/iron_raycast.c index c3f7bb5e..42fc69f6 100644 --- a/base/sources/iron_raycast.c +++ b/base/sources/iron_raycast.c @@ -1,6 +1,6 @@ #include "iron_raycast.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_math.h" #include @@ -87,7 +87,7 @@ vec4_t raycast_plane_intersect(vec4_t normal, vec4_t a, f32 input_x, f32 input_y } ray_t *ray_create(vec4_t origin, vec4_t dir) { - ray_t *raw = gc_alloc(sizeof(ray_t)); + ray_t *raw = calloc(1, sizeof(ray_t)); raw->origin = origin; raw->dir = dir; return raw; diff --git a/base/sources/iron_string.c b/base/sources/iron_string.c index 8eab7caa..780b5904 100644 --- a/base/sources/iron_string.c +++ b/base/sources/iron_string.c @@ -6,15 +6,47 @@ #include #include -void *gc_alloc(size_t size); -void gc_leaf(void *ptr); - char *string_alloc(int size) { - char *r = gc_alloc(size); - gc_leaf(r); + char *r = calloc(1, size); return r; } +#define STRING_TMP_BUFFER_SIZE (4 * 1024 * 1024) +static char *string_tmp_buffer = NULL; +static size_t string_tmp_pos = 0; + +char *string_tmp_alloc(int size) { + if (string_tmp_buffer == NULL) { + string_tmp_buffer = malloc(STRING_TMP_BUFFER_SIZE); + } + if (string_tmp_pos + size > STRING_TMP_BUFFER_SIZE) { + return string_alloc(size); + } + char *r = string_tmp_buffer + string_tmp_pos; + string_tmp_pos += ((size_t)size + 7) & ~(size_t)7; + memset(r, 0, size); + return r; +} + +void string_tmp_reset() { + string_tmp_pos = 0; +} + +char *string_tmp(char *fmt, ...) { + va_list args; + va_start(args, fmt); + + va_list args_copy; + va_copy(args_copy, args); + int len = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + char *str = string_tmp_alloc(len + 1); + vsnprintf(str, len + 1, fmt, args); + va_end(args); + return str; +} + char *string(char *fmt, ...) { va_list args; va_start(args, fmt); @@ -52,14 +84,14 @@ bool string_equals(char *a, char *b) { char *i32_to_string(int32_t i) { int l = snprintf(NULL, 0, "%d", i); - char *r = string_alloc(l + 1); + char *r = string_tmp_alloc(l + 1); sprintf(r, "%d", i); return r; } char *i32_to_string_hex(int32_t i) { int l = snprintf(NULL, 0, "%X", i); - char *r = string_alloc(l + 1); + char *r = string_tmp_alloc(l + 1); sprintf(r, "%X", i); return r; } @@ -74,21 +106,21 @@ char *i32_to_string_hex(int32_t i) { char *i64_to_string(int64_t i) { int l = snprintf(NULL, 0, PERCENT_LD, i); - char *r = string_alloc(l + 1); + char *r = string_tmp_alloc(l + 1); sprintf(r, PERCENT_LD, i); return r; } char *u64_to_string(uint64_t i) { int l = snprintf(NULL, 0, PERCENT_LU, i); - char *r = string_alloc(l + 1); + char *r = string_tmp_alloc(l + 1); sprintf(r, PERCENT_LU, i); return r; } char *f32_to_string_with_zeros(float f) { int l = snprintf(NULL, 0, "%f", f); - char *r = string_alloc(l + 1); + char *r = string_tmp_alloc(l + 1); sprintf(r, "%f", f); return r; } @@ -139,7 +171,7 @@ int32_t string_last_index_of(char *str, char *search) { } any_array_t *string_split(char *s, char *sep) { - any_array_t *a = gc_alloc(sizeof(any_array_t)); + any_array_t *a = calloc(1, sizeof(any_array_t)); int sep_len = strlen(sep); char *pos = s; while (true) { @@ -158,6 +190,17 @@ any_array_t *string_split(char *s, char *sep) { return a; } +void string_split_free(any_array_t *a) { + if (a == NULL) { + return; + } + for (int i = 0; i < a->length; ++i) { + free(a->buffer[i]); + } + array_free(a); + free(a); +} + char *string_array_join(any_array_t *a, char *separator) { int len = 0; int len_sep = strlen(separator); @@ -178,7 +221,7 @@ char *string_array_join(any_array_t *a, char *separator) { return r; } -char *string_replace_all(char *s, char *search, char *replace) { +static char *string_replace_all_impl(char *s, char *search, char *replace, bool use_tmp) { size_t search_len = strlen(search); size_t replace_len = strlen(replace); size_t buffer_size = strlen(s) + 1; @@ -192,7 +235,7 @@ char *string_replace_all(char *s, char *search, char *replace) { buffer_size += count * (replace_len - search_len); } - char *buffer = string_alloc(buffer_size); + char *buffer = use_tmp ? string_tmp_alloc(buffer_size) : string_alloc(buffer_size); char *buffer_pos = buffer; while (1) { char *p = strstr(s, search); @@ -209,6 +252,14 @@ char *string_replace_all(char *s, char *search, char *replace) { return buffer; } +char *string_replace_all(char *s, char *search, char *replace) { + return string_replace_all_impl(s, search, replace, false); +} + +char *string_replace_all_tmp(char *s, char *search, char *replace) { + return string_replace_all_impl(s, search, replace, true); +} + char *substring(char *s, int32_t start, int32_t end) { char *buffer = string_alloc(end - start + 1); for (int i = 0; i < end - start; ++i) { @@ -242,6 +293,9 @@ bool starts_with(char *s, char *start) { bool ends_with(char *s, char *end) { size_t len_s = strlen(s); size_t len_end = strlen(end); + if (len_end > len_s) { + return false; + } return strncmp(s + len_s - len_end, end, len_end) == 0; } diff --git a/base/sources/iron_string.h b/base/sources/iron_string.h index 5523dbf8..a7a0fb98 100644 --- a/base/sources/iron_string.h +++ b/base/sources/iron_string.h @@ -8,6 +8,12 @@ char *string_alloc(int size); char *string(char *fmt, ...); char *string_copy(char *a); + +// Frame temporary +char *string_tmp_alloc(int size); +char *string_tmp(char *fmt, ...); +char *string_replace_all_tmp(char *s, char *search, char *replace); +void string_tmp_reset(); int string_length(char *str); bool string_equals(char *a, char *b); char *i32_to_string(int32_t i); @@ -22,6 +28,7 @@ int32_t string_index_of(char *s, char *search); int32_t string_index_of_pos(char *s, char *search, int pos); int32_t string_last_index_of(char *s, char *search); any_array_t *string_split(char *s, char *sep); +void string_split_free(any_array_t *a); char *string_array_join(any_array_t *a, char *separator); char *string_replace_all(char *s, char *search, char *replace); char *substring(char *s, int32_t start, int32_t end); diff --git a/base/sources/iron_sys.c b/base/sources/iron_sys.c index 8c1c183e..e8c92725 100644 --- a/base/sources/iron_sys.c +++ b/base/sources/iron_sys.c @@ -2,7 +2,7 @@ #include "iron_array.h" #include "iron_draw.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_input.h" #include "iron_map.h" #include "iron_string.h" @@ -33,6 +33,7 @@ i32 iron_display_frequency(i32 index); i32 iron_display_ppi(i32 index); bool iron_display_is_primary(i32 index); gpu_shader_t *gpu_create_shader(buffer_t *data, i32 shader_type); +void iron_delete_blob(buffer_t *buffer); char *data_path(void); #ifdef WITH_GAMEPAD @@ -66,13 +67,13 @@ static f32 _sys_time_real_delta = 0.0f; static i32 _sys_time_frequency = -1; static sys_callback_t *_sys_callback_create(void (*f)(void)) { - sys_callback_t *cb = gc_alloc(sizeof(sys_callback_t)); + sys_callback_t *cb = calloc(1, sizeof(sys_callback_t)); cb->f = f; return cb; } static callback_t *_callback_create(void (*f)(void *data), void *data) { - callback_t *cb = gc_alloc(sizeof(callback_t)); + callback_t *cb = calloc(1, sizeof(callback_t)); cb->f = f; cb->data = data; return cb; @@ -80,21 +81,13 @@ static callback_t *_callback_create(void (*f)(void *data), void *data) { void sys_start(iron_window_options_t *ops) { _sys_foreground_listeners = any_array_create(0); - gc_root(_sys_foreground_listeners); _sys_background_listeners = any_array_create(0); - gc_root(_sys_background_listeners); _sys_shutdown_listeners = any_array_create(0); - gc_root(_sys_shutdown_listeners); _sys_drop_files_listeners = any_array_create(0); - gc_root(_sys_drop_files_listeners); _sys_on_next_frames = any_array_create(0); - gc_root(_sys_on_next_frames); _sys_on_end_frames = any_array_create(0); - gc_root(_sys_on_end_frames); _sys_on_updates = any_array_create(0); - gc_root(_sys_on_updates); _sys_shaders = any_map_create(); - gc_root(_sys_shaders); _iron_init(ops); @@ -137,8 +130,13 @@ void sys_start(iron_window_options_t *ops) { strcat(path_text_frag, "draw_text.frag"); strcat(path_text_frag, ext); - draw_init(iron_load_blob(path_image_vert), iron_load_blob(path_image_frag), iron_load_blob(path_rect_vert), iron_load_blob(path_rect_frag), - iron_load_blob(path_tris_vert), iron_load_blob(path_tris_frag), iron_load_blob(path_text_vert), iron_load_blob(path_text_frag)); + buffer_t *draw_blobs[8] = {iron_load_blob(path_image_vert), iron_load_blob(path_image_frag), iron_load_blob(path_rect_vert), + iron_load_blob(path_rect_frag), iron_load_blob(path_tris_vert), iron_load_blob(path_tris_frag), + iron_load_blob(path_text_vert), iron_load_blob(path_text_frag)}; + draw_init(draw_blobs[0], draw_blobs[1], draw_blobs[2], draw_blobs[3], draw_blobs[4], draw_blobs[5], draw_blobs[6], draw_blobs[7]); + for (int i = 0; i < 8; ++i) { + iron_delete_blob(draw_blobs[i]); + } _iron_set_update_callback(sys_render); _iron_set_drop_files_callback(sys_drop_files_callback); @@ -175,7 +173,7 @@ void sys_notify_on_app_state(void (*on_foreground)(void), void (*on_background)( } void sys_notify_on_drop_files(void (*drop_files_listener)(char *s)) { - sys_string_callback_t *cb = gc_alloc(sizeof(sys_string_callback_t)); + sys_string_callback_t *cb = calloc(1, sizeof(sys_string_callback_t)); cb->f = drop_files_listener; any_array_push(_sys_drop_files_listeners, cb); } @@ -349,7 +347,9 @@ gpu_shader_t *sys_get_shader(char *name) { strcat(path, name); strcat(path, ext); gpu_shader_type_t shader_type = ends_with(name, ".frag") ? GPU_SHADER_TYPE_FRAGMENT : GPU_SHADER_TYPE_VERTEX; - shader = gpu_create_shader(iron_load_blob(path), (i32)shader_type); + buffer_t *blob = iron_load_blob(path); + shader = gpu_create_shader(blob, (i32)shader_type); + iron_delete_blob(blob); any_map_set(_sys_shaders, name, shader); } return shader; @@ -403,17 +403,26 @@ static void _sys_run_callbacks(any_array_t *cbs, i32 len) { } } +static void _sys_run_callbacks_once(any_array_t *cbs, i32 len) { + for (i32 i = 0; i < len; ++i) { + callback_t *cb = cbs->buffer[i]; + if (cb != NULL) { + cb->f(cb->data); + free(cb); + } + } + array_splice(cbs, 0, len); +} + void sys_render(void) { i32 len = _sys_on_next_frames->length; - _sys_run_callbacks(_sys_on_next_frames, len); - array_splice(_sys_on_next_frames, 0, len); + _sys_run_callbacks_once(_sys_on_next_frames, len); scene_render_frame(); _sys_run_callbacks(_sys_on_updates, _sys_on_updates->length); len = _sys_on_end_frames->length; - _sys_run_callbacks(_sys_on_end_frames, len); - array_splice(_sys_on_end_frames, 0, len); + _sys_run_callbacks_once(_sys_on_end_frames, len); input_end_frame(); diff --git a/base/sources/iron_tween.c b/base/sources/iron_tween.c index be30caa2..2b55fdf8 100644 --- a/base/sources/iron_tween.c +++ b/base/sources/iron_tween.c @@ -1,7 +1,7 @@ #include "iron_tween.h" #include "iron_array.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include #include @@ -14,7 +14,6 @@ void sys_notify_on_update(void (*f)(void *data), void *data); static void _tween_register(void) { _tween_registered = true; _tween_anims = any_array_create(0); - gc_root(_tween_anims); sys_notify_on_update(tween_update, NULL); } @@ -30,7 +29,7 @@ tween_anim_t *tween_to(tween_anim_t *anim) { } tween_anim_t *tween_timer(f32 delay, void (*done)(void *data), void *data) { - tween_anim_t *a = gc_alloc(sizeof(tween_anim_t)); + tween_anim_t *a = calloc(1, sizeof(tween_anim_t)); a->target = NULL; a->to = 0.0f; a->duration = 0.0f; @@ -49,9 +48,7 @@ void tween_stop(tween_anim_t *anim) { } void tween_reset(void) { - gc_unroot(_tween_anims); _tween_anims = any_array_create(0); - gc_root(_tween_anims); } static f32 _tween_ease_linear(f32 k) { diff --git a/base/sources/iron_ui.c b/base/sources/iron_ui.c index 5db81e45..cc5c1d64 100644 --- a/base/sources/iron_ui.c +++ b/base/sources/iron_ui.c @@ -1,7 +1,7 @@ #include "iron_ui.h" #include "iron_draw.h" #include "iron_file.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_gpu.h" #include "iron_string.h" #include "iron_system.h" @@ -114,7 +114,7 @@ void ui_set_current(ui_t *_current) { } ui_handle_t *ui_handle_create() { - ui_handle_t *h = (ui_handle_t *)gc_alloc(sizeof(ui_handle_t)); + ui_handle_t *h = (ui_handle_t *)calloc(1, sizeof(ui_handle_t)); memset(h, 0, sizeof(ui_handle_t)); h->redraws = 2; h->color = 0xffffffff; @@ -1703,7 +1703,6 @@ void ui_init(ui_t *ui, ui_options_t *ops) { current->input_y = -1; if (ui_combo_search_handle == NULL) { ui_combo_search_handle = ui_handle_create(); - gc_root(ui_combo_search_handle); } if (_ui_row2 == NULL) { _ui_row2 = f32_array_create_from_raw((float[]){1.0 / 2.0, 1.0 / 2.0}, 2); @@ -1712,12 +1711,6 @@ void ui_init(ui_t *ui, ui_options_t *ops) { _ui_row5 = f32_array_create_from_raw((float[]){1.0 / 5.0, 1.0 / 5.0, 1.0 / 5.0, 1.0 / 5.0, 1.0 / 5.0}, 5); _ui_row6 = f32_array_create_from_raw((float[]){1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0}, 6); _ui_row7 = f32_array_create_from_raw((float[]){1.0 / 7.0, 1.0 / 7.0, 1.0 / 7.0, 1.0 / 7.0, 1.0 / 7.0, 1.0 / 7.0, 1.0 / 7.0}, 7); - gc_root(_ui_row2); - gc_root(_ui_row3); - gc_root(_ui_row4); - gc_root(_ui_row5); - gc_root(_ui_row6); - gc_root(_ui_row7); } } @@ -2262,13 +2255,26 @@ int ui_combo(ui_handle_t *handle, string_array_t *texts, char *label, bool show_ } if (ui_get_released(UI_ELEMENT_H())) { if (current->combo_selected_handle == NULL) { + static string_array_t texts_copy = {0}; + static char label_copy[256]; + for (int i = 0; i < texts_copy.length; ++i) { + free(texts_copy.buffer[i]); + } + texts_copy.length = 0; + for (int i = 0; i < texts->length; ++i) { + string_array_push(&texts_copy, string_copy(texts->buffer[i])); + } + if (label != NULL) { + strncpy(label_copy, label, sizeof(label_copy) - 1); + label_copy[sizeof(label_copy) - 1] = '\0'; + } current->input_enabled = false; current->combo_selected_handle = handle; current->combo_selected_window = current->current_window; current->combo_selected_align = align; - current->combo_selected_texts = texts; + current->combo_selected_texts = &texts_copy; current->combo_selected_images = NULL; - current->combo_selected_label = label; + current->combo_selected_label = label != NULL ? label_copy : NULL; current->combo_selected_x = current->_x + current->_window_x; current->combo_selected_y = current->_y + current->_window_y + UI_ELEMENT_H(); current->combo_selected_w = current->_w; diff --git a/base/sources/iron_ui_ext.c b/base/sources/iron_ui_ext.c index 71b1fc11..1ae49c12 100644 --- a/base/sources/iron_ui_ext.c +++ b/base/sources/iron_ui_ext.c @@ -1,5 +1,5 @@ #include "iron_draw.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_string.h" #include "iron_system.h" #include "iron_ui.h" @@ -1014,7 +1014,7 @@ ui_handle_t *ui_handle(char *s) { ui_handle_t *h = any_map_get(ui_children, s); if (h == NULL) { h = ui_handle_create(); - any_map_set(ui_children, s, h); + any_map_set(ui_children, string_copy(s), h); return h; } h->init = false; @@ -1022,13 +1022,13 @@ ui_handle_t *ui_handle(char *s) { } ui_t *ui_create(ui_options_t *ops) { - ui_t *raw = GC_ALLOC_INIT(ui_t, {0}); + ui_t *raw = ALLOC_INIT(ui_t, {0}); ui_init(raw, ops); return raw; } ui_theme_t *ui_theme_create() { - ui_theme_t *raw = GC_ALLOC_INIT(ui_theme_t, {0}); + ui_theme_t *raw = ALLOC_INIT(ui_theme_t, {0}); ui_theme_default(raw); return raw; } diff --git a/base/sources/iron_ui_nodes.c b/base/sources/iron_ui_nodes.c index 94ccf01c..340e9007 100644 --- a/base/sources/iron_ui_nodes.c +++ b/base/sources/iron_ui_nodes.c @@ -3,7 +3,7 @@ #include "iron_armpack.h" #include "iron_array.h" #include "iron_draw.h" -#include "iron_gc.h" +#include "iron_alloc.h" #include "iron_gpu.h" #include "iron_json.h" #include "iron_string.h" @@ -66,7 +66,7 @@ void ui_nodes_init(ui_nodes_t *nodes) { nodes->snap_from_id = -1; nodes->snap_to_id = -1; nodes->link_drag_id = -1; - nodes->nodes_selected_id = gc_alloc(sizeof(i32_array_t)); + nodes->nodes_selected_id = calloc(1, sizeof(i32_array_t)); nodes->handle = ui_handle_create(); } @@ -561,9 +561,7 @@ void ui_node_draw_body(ui_node_t *node, ui_node_canvas_t *canvas, float nx, floa ar->length = texts_count; } else { - gc_unroot(ar); ar = (*ui_nodes_enum_texts)(node->type); - gc_root(ar); } strcpy(label, ui_tr(but->name)); @@ -842,8 +840,7 @@ void ui_node_canvas(ui_nodes_t *nodes, ui_node_canvas_t *canvas) { draw_begin(current, false, 0); } if (ui_nodes_exclude_remove == NULL) { - ui_nodes_exclude_remove = gc_alloc(sizeof(string_array_t)); - gc_root(ui_nodes_exclude_remove); + ui_nodes_exclude_remove = calloc(1, sizeof(string_array_t)); } float wx = current->_window_x; @@ -1271,9 +1268,7 @@ void ui_node_canvas(ui_nodes_t *nodes, ui_node_canvas_t *canvas) { ui_node_link_array_t links = {.buffer = copy_links, .length = copy_links_count}; copy_canvas.nodes = &nodes; copy_canvas.links = &links; - gc_unroot(ui_clipboard); ui_clipboard = ui_node_canvas_to_json(©_canvas); - gc_root(ui_clipboard); iron_copy_to_clipboard(ui_clipboard); } cut_selected = ui_is_cut; @@ -1288,7 +1283,6 @@ void ui_node_canvas(ui_nodes_t *nodes, ui_node_canvas_t *canvas) { if (is_json) { ui_node_canvas_t *paste_canvas = json_parse(ui_clipboard); - gc_root(paste_canvas); // TODO // Convert button data from string to u8 array for (int i = 0; i < paste_canvas->nodes->length; ++i) { @@ -1758,9 +1752,8 @@ void nodes_on_custom_button(i32 node_id, char *button_name) { } ui_nodes_t *ui_nodes_create() { - ui_nodes_t *raw = GC_ALLOC_INIT(ui_nodes_t, {0}); + ui_nodes_t *raw = ALLOC_INIT(ui_nodes_t, {0}); ui_nodes_init(raw); - gc_unroot(ui_nodes_exclude_remove); ui_nodes_exclude_remove = any_array_create_from_raw( (void *[]){ "OUTPUT_MATERIAL_PBR", @@ -1769,7 +1762,6 @@ ui_nodes_t *ui_nodes_create() { "brush_output_node", }, 4); - gc_root(ui_nodes_exclude_remove); ui_nodes_on_custom_button = nodes_on_custom_button; return raw; } diff --git a/base/sources/libs/minic.c b/base/sources/libs/minic.c index c9b015c9..151605cc 100644 --- a/base/sources/libs/minic.c +++ b/base/sources/libs/minic.c @@ -63,19 +63,10 @@ typedef struct { minic_token_t cur; } minic_lexer_t; -void *gc_alloc(size_t size); -void gc_root(void *ptr); -void gc_unroot(void *ptr); -void gc_free(void *ptr); -void gc_resize(void *ptr, size_t size); static minic_u8 *minic_active_mem = NULL; static int *minic_active_mem_used = NULL; -static void minic_mem_sync(void) { - gc_resize(minic_active_mem, (size_t)*minic_active_mem_used); -} - static const struct { const char *kw; minic_tok_type_t tok; @@ -222,7 +213,6 @@ static void minic_lex_next(minic_lexer_t *l) { } minic_active_mem[wi++] = '\0'; *minic_active_mem_used = (wi + 7) & ~7; - minic_mem_sync(); if (l->src[l->pos] == '"') { l->pos++; // Consume closing '"' } @@ -298,7 +288,6 @@ void *minic_alloc(int size) { // Align to 8 bytes int aligned = (*minic_active_mem_used + 7) & ~7; *minic_active_mem_used = aligned + size; - minic_mem_sync(); return &minic_active_mem[aligned]; } @@ -853,7 +842,6 @@ static minic_val_t minic_call_in_ctx(minic_ctx_t *ctx, minic_func_t *fn, minic_v int saved_used = ctx->mem_used; minic_val_t r = minic_call(&ctx->e, fn, args, argc); ctx->mem_used = saved_used; - minic_mem_sync(); minic_active_mem = prev_mem; minic_active_mem_used = prev_mem_used; return r; @@ -2049,12 +2037,8 @@ static void minic_register_funcs(minic_env_t *e) { minic_ctx_t *minic_eval_named(const char *src, const char *filename) { minic_register_builtins(); - // The arena stores every script variable, including pointers to GC-managed host objects - minic_ctx_t *ctx = (minic_ctx_t *)gc_alloc(sizeof(minic_ctx_t)); - gc_root(ctx); - ctx->mem = (minic_u8 *)gc_alloc(MINIC_MEM_SIZE); - gc_root(ctx->mem); - gc_resize(ctx->mem, 0); + minic_ctx_t *ctx = (minic_ctx_t *)calloc(1, sizeof(minic_ctx_t)); + ctx->mem = (minic_u8 *)calloc(1, MINIC_MEM_SIZE); // Copy the source so the context stays valid after the caller frees its buffer int src_len = (int)strlen(src); ctx->src_copy = (char *)malloc(src_len + 1); @@ -2113,11 +2097,9 @@ minic_ctx_t *minic_eval(const char *src) { void minic_ctx_free(minic_ctx_t *ctx) { if (ctx != NULL) { - gc_unroot(ctx->mem); - gc_free(ctx->mem); + free(ctx->mem); free(ctx->src_copy); - gc_unroot(ctx); - gc_free(ctx); + free(ctx); } } diff --git a/base/tests/cube/sources/main.c b/base/tests/cube/sources/main.c index d3a6078d..a37964e7 100644 --- a/base/tests/cube/sources/main.c +++ b/base/tests/cube/sources/main.c @@ -25,37 +25,36 @@ void scene_ready() { void ready() { render_path_commands = render_commands; - gc_root(render_path_commands); - scene_t *scene = GC_ALLOC_INIT( + scene_t *scene = ALLOC_INIT( scene_t, {.name = "Scene", .objects = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT( + ALLOC_INIT( obj_t, {.name = "Cube", .type = "mesh_object", .data_ref = "cube.arm/Cube", .material_ref = "MyMaterial", .visible = true, .spawn = true}), - GC_ALLOC_INIT(obj_t, {.name = "Camera", .type = "camera_object", .data_ref = "MyCamera", .visible = true, .spawn = true}), + ALLOC_INIT(obj_t, {.name = "Camera", .type = "camera_object", .data_ref = "MyCamera", .visible = true, .spawn = true}), }, 2), .camera_datas = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(camera_data_t, {.name = "MyCamera", .near_plane = 0.1, .far_plane = 100.0, .fov = 0.85}), + ALLOC_INIT(camera_data_t, {.name = "MyCamera", .near_plane = 0.1, .far_plane = 100.0, .fov = 0.85}), }, 1), .camera_ref = "Camera", .world_ref = "MyWorld", - .world_datas = any_array_create_from_raw((void *[]){GC_ALLOC_INIT(world_data_t, {.name = "MyWorld", .color = 0xff000000})}, 1), + .world_datas = any_array_create_from_raw((void *[]){ALLOC_INIT(world_data_t, {.name = "MyWorld", .color = 0xff000000})}, 1), .material_datas = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(material_data_t, + ALLOC_INIT(material_data_t, {.name = "MyMaterial", .shader = "MyShader", .contexts = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(material_context_t, {.name = "mesh", + ALLOC_INIT(material_context_t, {.name = "mesh", .bind_textures = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(bind_tex_t, {.name = "my_texture", .file = "texture.k"}), + ALLOC_INIT(bind_tex_t, {.name = "my_texture", .file = "texture.k"}), }, 1)}), }, @@ -64,10 +63,10 @@ void ready() { 1), .shader_datas = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(shader_data_t, {.name = "MyShader", + ALLOC_INIT(shader_data_t, {.name = "MyShader", .contexts = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(shader_context_t, + ALLOC_INIT(shader_context_t, {.name = "mesh", .vertex_shader = "mesh.vert", .fragment_shader = "mesh.frag", @@ -76,19 +75,19 @@ void ready() { .depth_write = true, .vertex_elements = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(vertex_element_t, {.name = "pos", .data = "short4norm"}), - GC_ALLOC_INIT(vertex_element_t, {.name = "tex", .data = "short2norm"}), + ALLOC_INIT(vertex_element_t, {.name = "pos", .data = "short4norm"}), + ALLOC_INIT(vertex_element_t, {.name = "tex", .data = "short2norm"}), }, 2), .constants = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(shader_const_t, + ALLOC_INIT(shader_const_t, {.name = "WVP", .type = "float4x4", .link = "_world_view_proj_matrix"}), }, 1), .texture_units = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(tex_unit_t, {.name = "my_texture"}), + ALLOC_INIT(tex_unit_t, {.name = "my_texture"}), }, 1), .depth_attachment = "D32"}), @@ -98,7 +97,6 @@ void ready() { 1)}); data_cached_scene_raws = any_map_create(); - gc_root(data_cached_scene_raws); any_map_set(data_cached_scene_raws, scene->name, scene); // Instantiate scene @@ -108,7 +106,7 @@ void ready() { void _kickstart() { iron_window_options_t *ops = - GC_ALLOC_INIT(iron_window_options_t, {.title = "Empty", + ALLOC_INIT(iron_window_options_t, {.title = "Empty", .width = 1280, .height = 720, .x = -1, diff --git a/base/tests/fall/sources/main.c b/base/tests/fall/sources/main.c index 0e65c7a5..b32472a2 100644 --- a/base/tests/fall/sources/main.c +++ b/base/tests/fall/sources/main.c @@ -45,41 +45,39 @@ void scene_ready() { } void ready() { - gc_unroot(render_path_commands); render_path_commands = render_commands; - gc_root(render_path_commands); - scene_t *scene = GC_ALLOC_INIT( + scene_t *scene = ALLOC_INIT( scene_t, {.name = "Scene", .objects = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT( + ALLOC_INIT( obj_t, {.name = "Cube", .type = "mesh_object", .data_ref = "cube.arm/Cube", .material_ref = "MyMaterial", .visible = true, .spawn = true}), - GC_ALLOC_INIT( + ALLOC_INIT( obj_t, {.name = "Sphere", .type = "mesh_object", .data_ref = "sphere.arm/Sphere", .material_ref = "MyMaterial", .visible = true, .spawn = true}), - GC_ALLOC_INIT(obj_t, {.name = "Camera", .type = "camera_object", .data_ref = "MyCamera", .visible = true, .spawn = true}), + ALLOC_INIT(obj_t, {.name = "Camera", .type = "camera_object", .data_ref = "MyCamera", .visible = true, .spawn = true}), }, 3), .camera_datas = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(camera_data_t, {.name = "MyCamera", .near_plane = 0.1, .far_plane = 100.0, .fov = 0.85}), + ALLOC_INIT(camera_data_t, {.name = "MyCamera", .near_plane = 0.1, .far_plane = 100.0, .fov = 0.85}), }, 1), .camera_ref = "Camera", .world_ref = "MyWorld", - .world_datas = any_array_create_from_raw((void *[]){GC_ALLOC_INIT(world_data_t, {.name = "MyWorld", .color = 0xff000000})}, 1), + .world_datas = any_array_create_from_raw((void *[]){ALLOC_INIT(world_data_t, {.name = "MyWorld", .color = 0xff000000})}, 1), .material_datas = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(material_data_t, + ALLOC_INIT(material_data_t, {.name = "MyMaterial", .shader = "MyShader", .contexts = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(material_context_t, {.name = "mesh", + ALLOC_INIT(material_context_t, {.name = "mesh", .bind_textures = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(bind_tex_t, {.name = "my_texture", .file = "texture.k"}), + ALLOC_INIT(bind_tex_t, {.name = "my_texture", .file = "texture.k"}), }, 1)}), }, @@ -88,12 +86,12 @@ void ready() { 1), .shader_datas = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT( + ALLOC_INIT( shader_data_t, {.name = "MyShader", .contexts = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(shader_context_t, + ALLOC_INIT(shader_context_t, {.name = "mesh", .vertex_shader = "mesh.vert", .fragment_shader = "mesh.frag", @@ -102,19 +100,19 @@ void ready() { .depth_write = true, .vertex_elements = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(vertex_element_t, {.name = "pos", .data = "short4norm"}), - GC_ALLOC_INIT(vertex_element_t, {.name = "nor", .data = "short2norm"}), - GC_ALLOC_INIT(vertex_element_t, {.name = "tex", .data = "short2norm"}), + ALLOC_INIT(vertex_element_t, {.name = "pos", .data = "short4norm"}), + ALLOC_INIT(vertex_element_t, {.name = "nor", .data = "short2norm"}), + ALLOC_INIT(vertex_element_t, {.name = "tex", .data = "short2norm"}), }, 3), .constants = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(shader_const_t, {.name = "WVP", .type = "float4x4", .link = "_world_view_proj_matrix"}), + ALLOC_INIT(shader_const_t, {.name = "WVP", .type = "float4x4", .link = "_world_view_proj_matrix"}), }, 1), .texture_units = any_array_create_from_raw( (void *[]){ - GC_ALLOC_INIT(tex_unit_t, {.name = "my_texture"}), + ALLOC_INIT(tex_unit_t, {.name = "my_texture"}), }, 1), .depth_attachment = "D32"}), @@ -124,7 +122,6 @@ void ready() { 1)}); data_cached_scene_raws = any_map_create(); - gc_root(data_cached_scene_raws); any_map_set(data_cached_scene_raws, scene->name, scene); // Instantiate scene @@ -134,7 +131,7 @@ void ready() { void _kickstart() { iron_window_options_t *ops = - GC_ALLOC_INIT(iron_window_options_t, {.title = "Empty", + ALLOC_INIT(iron_window_options_t, {.title = "Empty", .width = 1280, .height = 720, .x = -1, diff --git a/base/tests/triangle/main.c b/base/tests/triangle/main.c index 5778b5c4..6c2bfec0 100644 --- a/base/tests/triangle/main.c +++ b/base/tests/triangle/main.c @@ -18,7 +18,7 @@ void render() { void _kickstart() { iron_window_options_t *ops = - GC_ALLOC_INIT(iron_window_options_t, {.title = "Iron", + ALLOC_INIT(iron_window_options_t, {.title = "Iron", .width = 640, .height = 480, .x = -1, @@ -31,9 +31,8 @@ void _kickstart() { _iron_init(ops); pipeline = gpu_create_pipeline(); - gc_root(pipeline); - gpu_vertex_structure_t *vs = GC_ALLOC_INIT(gpu_vertex_structure_t, {0}); + gpu_vertex_structure_t *vs = ALLOC_INIT(gpu_vertex_structure_t, {0}); gpu_vertex_structure_add(vs, "pos", GPU_VERTEX_DATA_F32_3X); buffer_t *vs_buffer = iron_load_blob(string("./data/test.vert%s", sys_shader_ext())); buffer_t *fs_buffer = iron_load_blob(string("./data/test.frag%s", sys_shader_ext())); @@ -68,7 +67,6 @@ void _kickstart() { 3); vb = gpu_create_vertex_buffer(vertices->length / (float)3, vs->elements); - gc_root(vb); float *vb_data = gpu_vertex_buffer_lock(vb); for (i32 i = 0; i < vertices->length; i++) { @@ -77,7 +75,6 @@ void _kickstart() { gpu_vertex_buffer_unlock(vb); ib = gpu_create_index_buffer(indices->length); - gc_root(ib); uint32_t *ib_data = gpu_index_buffer_lock(ib); for (i32 i = 0; i < indices->length; i++) { diff --git a/base/tools/amake/project.js b/base/tools/amake/project.js index 2c9ed1c8..919165b7 100644 --- a/base/tools/amake/project.js +++ b/base/tools/amake/project.js @@ -5,8 +5,6 @@ project.add_define('AMAKE'); project.add_include_dir("../../sources"); project.add_cfiles("../../sources/iron_string.c"); project.add_cfiles("../../sources/iron_array.c"); -project.add_cfiles("../../sources/iron_gc.c"); -project.add_define("NO_GC"); project.add_cfiles("quickjs-amalgam.c"); project.add_define("JS_DEFAULT_STACK_SIZE=8388608"); // 8 * 1024 * 1024