diff --git a/Makefile-ponyc b/Makefile-ponyc index 9e8cf10822..0839591807 100644 --- a/Makefile-ponyc +++ b/Makefile-ponyc @@ -65,6 +65,15 @@ endif version_str = "$(tag) [$(config)]\ncompiled with: llvm $(llvm_version) \ -- "$(compiler_version) +# build ponyc version md5 +ifneq (,$(filter $(OSTYPE), osx bsd)) + TAG_MD5_CMD = md5 | sed 's/./&,0x/30;s/./&,0x/28;s/./&,0x/26;s/./&,0x/24;s/./&,0x/22;s/./&,0x/20;s/./&,0x/18;s/./&,0x/16;s/./&,0x/14;s/./&,0x/12;s/./&,0x/10;s/./&,0x/8;s/./&,0x/6;s/./&,0x/4;s/./&,0x/2;s/^/0x/' +else + TAG_MD5_CMD = md5sum | sed 's/ -$$//' | sed 's/./&,0x/30;s/./&,0x/28;s/./&,0x/26;s/./&,0x/24;s/./&,0x/22;s/./&,0x/20;s/./&,0x/18;s/./&,0x/16;s/./&,0x/14;s/./&,0x/12;s/./&,0x/10;s/./&,0x/8;s/./&,0x/6;s/./&,0x/4;s/./&,0x/2;s/^/0x/' +endif + +tag_formatted_md5 := $(shell echo $(tag) | $(TAG_MD5_CMD)) + # package_name, _version, and _iteration can be overridden by Travis or AppVeyor package_base_version ?= $(tag) package_iteration ?= "1" @@ -116,6 +125,7 @@ ALL_CFLAGS = -std=gnu11 -fexceptions \ -DBUILD_COMPILER=\"$(compiler_version)\" \ -DPONY_BUILD_CONFIG=\"$(config)\" \ -DPONY_VERSION_STR=\"$(version_str)\" \ + -DPONY_VERSION_FORMATTED_MD5=$(tag_formatted_md5) \ -D_FILE_OFFSET_BITS=64 ALL_CXXFLAGS = -std=gnu++11 -fno-rtti LL_FLAGS = -mcpu=$(cpu) diff --git a/packages/json/_test.pony b/packages/json/_test.pony index 885d326fa9..dc87df2048 100644 --- a/packages/json/_test.pony +++ b/packages/json/_test.pony @@ -552,8 +552,9 @@ class iso _TestPrintObject is UnitTest obj.data("a") = true obj.data("b") = I64(3) let s = doc.string(" ", true) - h.assert_true((s == "{\n \"a\": true,\n \"b\": 3\n}") or - (s == "{\n \"b\": false,\n \"a\": true\n}")) + h.assert_true((s == "{\n \"a\": true,\n \"b\": 3\n}") + or (s == "{\n \"b\": 3,\n \"a\": true\n}") + or (s == "{\n \"b\": false,\n \"a\": true\n}")) // We don't test with more fields in the object because we don't know what // order they will be printed in diff --git a/src/libponyc/ast/ast.c b/src/libponyc/ast/ast.c index 2dd43f8a8f..f2f3c520c9 100644 --- a/src/libponyc/ast/ast.c +++ b/src/libponyc/ast/ast.c @@ -1954,12 +1954,12 @@ static void ast_signature_serialise_trace(pony_ctx_t* ctx, void* object) } static void ast_signature_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; ast_t* ast = (ast_t*)object; - ast_signature_t* dst = (ast_signature_t*)((uintptr_t)buf + offset); + ast_signature_t* dst = (ast_signature_t*)((uintptr_t)buf + (uintptr_t)offset); dst->t = (token_signature_t*)pony_serialise_offset(ctx, ast->t); dst->child = (ast_signature_t*)pony_serialise_offset(ctx, ast->child); @@ -1981,6 +1981,7 @@ static pony_type_t ast_signature_pony = sizeof(ast_signature_t), 0, 0, + 0, NULL, NULL, ast_signature_serialise_trace, @@ -2030,12 +2031,12 @@ static void ast_nominal_pkg_id_signature_serialise_trace(pony_ctx_t* ctx, } static void ast_nominal_pkg_id_signature_serialise(pony_ctx_t* ctx, - void* object, void* buf, size_t offset, int mutability) + void* object, void* buf, uint64_t offset, int mutability) { (void)mutability; ast_t* ast = (ast_t*)object; - ast_signature_t* dst = (ast_signature_t*)((uintptr_t)buf + offset); + ast_signature_t* dst = (ast_signature_t*)((uintptr_t)buf + (uintptr_t)offset); ast_t* def = (ast_t*)ast_data(ast_parent(ast)); pony_assert(def != NULL); @@ -2059,6 +2060,7 @@ static pony_type_t ast_nominal_pkg_id_signature_pony = sizeof(ast_signature_t), 0, 0, + 0, NULL, NULL, ast_nominal_pkg_id_signature_serialise_trace, @@ -2276,12 +2278,12 @@ static void ast_serialise_trace(pony_ctx_t* ctx, void* object) } static void ast_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; ast_t* ast = (ast_t*)object; - ast_t* dst = (ast_t*)((uintptr_t)buf + offset); + ast_t* dst = (ast_t*)((uintptr_t)buf + (uintptr_t)offset); dst->t = (token_t*)pony_serialise_offset(ctx, ast->t); ast_serialise_data(ctx, ast, dst); @@ -2321,6 +2323,7 @@ static pony_type_t ast_pony = sizeof(ast_t), 0, 0, + 0, NULL, NULL, ast_serialise_trace, diff --git a/src/libponyc/ast/source.c b/src/libponyc/ast/source.c index f302198ed6..b344f8e32e 100644 --- a/src/libponyc/ast/source.c +++ b/src/libponyc/ast/source.c @@ -87,12 +87,12 @@ static void source_serialise_trace(pony_ctx_t* ctx, void* object) } static void source_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; source_t* source = (source_t*)object; - source_t* dst = (source_t*)((uintptr_t)buf + offset); + source_t* dst = (source_t*)((uintptr_t)buf + (uintptr_t)offset); dst->file = (const char*)pony_serialise_offset(ctx, (char*)source->file); dst->m = (char*)pony_serialise_offset(ctx, source->m); @@ -114,6 +114,7 @@ static pony_type_t source_pony = sizeof(source_t), 0, 0, + 0, NULL, NULL, source_serialise_trace, diff --git a/src/libponyc/ast/stringtab.c b/src/libponyc/ast/stringtab.c index daa14c2df5..2ee4904698 100644 --- a/src/libponyc/ast/stringtab.c +++ b/src/libponyc/ast/stringtab.c @@ -118,14 +118,15 @@ void stringtab_done() } static void string_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)ctx; (void)mutability; const char* string = (const char*)object; - memcpy((void*)((uintptr_t)buf + offset), object, strlen(string) + 1); + memcpy((void*)((uintptr_t)buf + (uintptr_t)offset), object, + strlen(string) + 1); } static __pony_thread_local struct _pony_type_t string_pony = @@ -134,6 +135,7 @@ static __pony_thread_local struct _pony_type_t string_pony = 0, 0, 0, + 0, NULL, NULL, NULL, @@ -191,12 +193,12 @@ static void strlist_serialise_trace(pony_ctx_t* ctx, void* object) } static void strlist_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; strlist_t* list = (strlist_t*)object; - strlist_t* dst = (strlist_t*)((uintptr_t)buf + offset); + strlist_t* dst = (strlist_t*)((uintptr_t)buf + (uintptr_t)offset); dst->contents.data = (void*)pony_serialise_offset(ctx, list->contents.data); dst->contents.next = (list_t*)pony_serialise_offset(ctx, list->contents.next); @@ -219,6 +221,7 @@ static pony_type_t strlist_pony = sizeof(strlist_t), 0, 0, + 0, NULL, NULL, strlist_serialise_trace, diff --git a/src/libponyc/ast/symtab.c b/src/libponyc/ast/symtab.c index a75427070c..ce5a229b8c 100644 --- a/src/libponyc/ast/symtab.c +++ b/src/libponyc/ast/symtab.c @@ -352,12 +352,12 @@ static void symbol_serialise_trace(pony_ctx_t* ctx, void* object) } static void symbol_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; symbol_t* sym = (symbol_t*)object; - symbol_t* dst = (symbol_t*)((uintptr_t)buf + offset); + symbol_t* dst = (symbol_t*)((uintptr_t)buf + (uintptr_t)offset); dst->name = (const char*)pony_serialise_offset(ctx, (char*)sym->name); dst->def = (ast_t*)pony_serialise_offset(ctx, sym->def); @@ -381,6 +381,7 @@ static pony_type_t symbol_pony = sizeof(symbol_t), 0, 0, + 0, NULL, NULL, symbol_serialise_trace, diff --git a/src/libponyc/ast/token.c b/src/libponyc/ast/token.c index a838532bdf..8ea72bd6c1 100644 --- a/src/libponyc/ast/token.c +++ b/src/libponyc/ast/token.c @@ -364,12 +364,13 @@ static void token_signature_serialise_trace(pony_ctx_t* ctx, void* object) } static void token_signature_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; token_t* token = (token_t*)object; - token_signature_t* dst = (token_signature_t*)((uintptr_t)buf + offset); + token_signature_t* dst = (token_signature_t*)((uintptr_t)buf + + (uintptr_t)offset); memset(dst, 0, sizeof(token_signature_t)); @@ -402,6 +403,7 @@ static pony_type_t token_signature_pony = sizeof(token_signature_t), 0, 0, + 0, NULL, NULL, token_signature_serialise_trace, @@ -435,13 +437,14 @@ static void token_docstring_signature_serialise_trace(pony_ctx_t* ctx, } static void token_docstring_signature_serialise(pony_ctx_t* ctx, void* object, - void* buf, size_t offset, int mutability) + void* buf, uint64_t offset, int mutability) { (void)ctx; (void)object; (void)mutability; - token_signature_t* dst = (token_signature_t*)((uintptr_t)buf + offset); + token_signature_t* dst = (token_signature_t*)((uintptr_t)buf + + (uintptr_t)offset); memset(dst, 0, sizeof(token_signature_t)); @@ -454,6 +457,7 @@ static pony_type_t token_docstring_signature_pony = sizeof(token_signature_t), 0, 0, + 0, NULL, NULL, token_docstring_signature_serialise_trace, @@ -486,12 +490,12 @@ static void token_serialise_trace(pony_ctx_t* ctx, void* object) } static void token_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; token_t* token = (token_t*)object; - token_t* dst = (token_t*)((uintptr_t)buf + offset); + token_t* dst = (token_t*)((uintptr_t)buf + (uintptr_t)offset); dst->id = token->id; @@ -541,6 +545,7 @@ static pony_type_t token_pony = sizeof(token_t), 0, 0, + 0, NULL, NULL, token_serialise_trace, diff --git a/src/libponyc/codegen/codegen.c b/src/libponyc/codegen/codegen.c index 1a69cad813..86b3ee3165 100644 --- a/src/libponyc/codegen/codegen.c +++ b/src/libponyc/codegen/codegen.c @@ -203,6 +203,13 @@ static void init_runtime(compile_t* c) c->msg_ptr = LLVMPointerType(c->msg_type, 0); LLVMStructSetBody(c->msg_type, params, 2, false); + // descriptor_offset_lookup + // uint32_t (*)(i64) + params[0] = c->i64; + c->descriptor_offset_lookup_type = LLVMFunctionType(c->i32, params, 1, false); + c->descriptor_offset_lookup_fn = + LLVMPointerType(c->descriptor_offset_lookup_type, 0); + // trace // void (*)(i8*, __object*) params[0] = c->void_ptr; @@ -211,11 +218,11 @@ static void init_runtime(compile_t* c) c->trace_fn = LLVMPointerType(c->trace_type, 0); // serialise - // void (*)(i8*, __object*, i8*, intptr, i32) + // void (*)(i8*, __object*, i8*, i64, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->void_ptr; - params[3] = c->intptr; + params[3] = c->i64; params[4] = c->i32; c->serialise_type = LLVMFunctionType(c->void_type, params, 5, false); c->serialise_fn = LLVMPointerType(c->serialise_type, 0); diff --git a/src/libponyc/codegen/codegen.h b/src/libponyc/codegen/codegen.h index d0b4b1122a..3995940863 100644 --- a/src/libponyc/codegen/codegen.h +++ b/src/libponyc/codegen/codegen.h @@ -183,6 +183,7 @@ typedef struct compile_t LLVMValueRef primitives_init; LLVMValueRef primitives_final; LLVMValueRef desc_table; + LLVMValueRef desc_table_offset_lookup_fn; LLVMValueRef numeric_sizes; LLVMTypeRef void_type; @@ -199,6 +200,8 @@ typedef struct compile_t LLVMTypeRef void_ptr; LLVMTypeRef descriptor_type; LLVMTypeRef descriptor_ptr; + LLVMTypeRef descriptor_offset_lookup_type; + LLVMTypeRef descriptor_offset_lookup_fn; LLVMTypeRef field_descriptor; LLVMTypeRef object_type; LLVMTypeRef object_ptr; diff --git a/src/libponyc/codegen/gendesc.c b/src/libponyc/codegen/gendesc.c index 18dab986e0..54a06cf2df 100644 --- a/src/libponyc/codegen/gendesc.c +++ b/src/libponyc/codegen/gendesc.c @@ -12,23 +12,24 @@ #define DESC_ID 0 #define DESC_SIZE 1 -#define DESC_FIELD_COUNT 2 -#define DESC_FIELD_OFFSET 3 -#define DESC_INSTANCE 4 -#define DESC_TRACE 5 -#define DESC_SERIALISE_TRACE 6 -#define DESC_SERIALISE 7 -#define DESC_DESERIALISE 8 -#define DESC_CUSTOM_SERIALISE_SPACE 9 -#define DESC_CUSTOM_DESERIALISE 10 -#define DESC_DISPATCH 11 -#define DESC_FINALISE 12 -#define DESC_EVENT_NOTIFY 13 -#define DESC_TRAITS 14 -#define DESC_FIELDS 15 -#define DESC_VTABLE 16 - -#define DESC_LENGTH 17 +#define DESC_SERIALISEID 2 +#define DESC_FIELD_COUNT 3 +#define DESC_FIELD_OFFSET 4 +#define DESC_INSTANCE 5 +#define DESC_TRACE 6 +#define DESC_SERIALISE_TRACE 7 +#define DESC_SERIALISE 8 +#define DESC_DESERIALISE 9 +#define DESC_CUSTOM_SERIALISE_SPACE 10 +#define DESC_CUSTOM_DESERIALISE 11 +#define DESC_DISPATCH 12 +#define DESC_FINALISE 13 +#define DESC_EVENT_NOTIFY 14 +#define DESC_TRAITS 15 +#define DESC_FIELDS 16 +#define DESC_VTABLE 17 + +#define DESC_LENGTH 18 static LLVMValueRef make_unbox_function(compile_t* c, reach_type_t* t, reach_method_t* m) @@ -331,6 +332,7 @@ void gendesc_basetype(compile_t* c, LLVMTypeRef desc_type) params[DESC_ID] = c->i32; params[DESC_SIZE] = c->i32; + params[DESC_SERIALISEID] = c->i64; params[DESC_FIELD_COUNT] = c->i32; params[DESC_FIELD_OFFSET] = c->i32; params[DESC_INSTANCE] = c->object_ptr; @@ -382,6 +384,7 @@ void gendesc_type(compile_t* c, reach_type_t* t) params[DESC_ID] = c->i32; params[DESC_SIZE] = c->i32; + params[DESC_SERIALISEID] = c->i64; params[DESC_FIELD_COUNT] = c->i32; params[DESC_FIELD_OFFSET] = c->i32; params[DESC_INSTANCE] = c->object_ptr; @@ -420,6 +423,7 @@ void gendesc_init(compile_t* c, reach_type_t* t) LLVMValueRef args[DESC_LENGTH]; args[DESC_ID] = LLVMConstInt(c->i32, t->type_id, false); args[DESC_SIZE] = LLVMConstInt(c->i32, c_t->abi_size, false); + args[DESC_SERIALISEID] = LLVMConstInt(c->i64, t->serialise_id, false); args[DESC_FIELD_COUNT] = make_field_count(c, t); args[DESC_FIELD_OFFSET] = make_field_offset(c, t); args[DESC_INSTANCE] = make_desc_ptr(c_t->instance, c->object_ptr); @@ -485,6 +489,59 @@ void gendesc_table(compile_t* c) ponyint_pool_free_size(size, args); } +void gendesc_table_lookup(compile_t* c) +{ + reach_type_t* t; + size_t i = HASHMAP_BEGIN; + + LLVMValueRef desc_lkp_fn = codegen_addfun(c, "__DescOffsetLookupFn", + c->descriptor_offset_lookup_type, false); + LLVMSetFunctionCallConv(desc_lkp_fn, LLVMCCallConv); + LLVMSetLinkage(desc_lkp_fn, LLVMExternalLinkage); + codegen_startfun(c, desc_lkp_fn, NULL, NULL, NULL, false); + + LLVMBasicBlockRef unreachable = codegen_block(c, "unreachable"); + + // Read the serialise ID. + LLVMValueRef serialise_id = LLVMGetParam(desc_lkp_fn, 0); + + // switch based on serialise_id + LLVMValueRef serialise_switch = LLVMBuildSwitch(c->builder, serialise_id, unreachable, 0); + + // the default case is unreachable unless something major has gone wrong + LLVMPositionBuilderAtEnd(c->builder, unreachable); + + LLVMValueRef ret = LLVMConstInt(c->i32, (uint32_t)-1, false); + LLVMBuildRet(c->builder, ret); + + while((t = reach_types_next(&c->reach->types, &i)) != NULL) + { + if(t->is_trait || (t->underlying == TK_STRUCT)) + continue; + + pony_assert(t->serialise_id != (uint64_t)-1); + + LLVMBasicBlockRef type_block = codegen_block(c, + genname_type_with_id("type", t->serialise_id)); + + LLVMAddCase(serialise_switch, LLVMConstInt(c->i64, t->serialise_id, false), + type_block); + + LLVMPositionBuilderAtEnd(c->builder, type_block); + + ret = LLVMConstInt(c->i32, t->type_id, false); + LLVMBuildRet(c->builder, ret); + } + + // Mark the default case as unreachable. + LLVMPositionBuilderAtEnd(c->builder, unreachable); + + codegen_finishfun(c); + + c->desc_table_offset_lookup_fn = make_desc_ptr(desc_lkp_fn, + c->descriptor_offset_lookup_type); +} + static LLVMValueRef desc_field(compile_t* c, LLVMValueRef desc, int index) { LLVMValueRef ptr = LLVMBuildStructGEP(c->builder, desc, index, ""); diff --git a/src/libponyc/codegen/gendesc.h b/src/libponyc/codegen/gendesc.h index 97c76aea27..cd8f7a90a7 100644 --- a/src/libponyc/codegen/gendesc.h +++ b/src/libponyc/codegen/gendesc.h @@ -14,6 +14,8 @@ void gendesc_init(compile_t* c, reach_type_t* t); void gendesc_table(compile_t* c); +void gendesc_table_lookup(compile_t* c); + LLVMValueRef gendesc_fetch(compile_t* c, LLVMValueRef object); LLVMValueRef gendesc_typeid(compile_t* c, LLVMValueRef desc); diff --git a/src/libponyc/codegen/genexe.c b/src/libponyc/codegen/genexe.c index aa8b54d782..55720ed9ba 100644 --- a/src/libponyc/codegen/genexe.c +++ b/src/libponyc/codegen/genexe.c @@ -49,16 +49,18 @@ static LLVMValueRef make_lang_features_init(compile_t* c) boolean = c->i8; LLVMTypeRef desc_ptr_ptr = LLVMPointerType(c->descriptor_ptr, 0); + LLVMValueRef desc_table_lookup_fn = c->desc_table_offset_lookup_fn; uint32_t desc_table_size = reach_max_type_id(c->reach); - LLVMTypeRef f_params[4]; + LLVMTypeRef f_params[5]; f_params[0] = boolean; f_params[1] = boolean; f_params[2] = desc_ptr_ptr; f_params[3] = c->intptr; + f_params[4] = c->descriptor_offset_lookup_fn; - LLVMTypeRef lfi_type = LLVMStructTypeInContext(c->context, f_params, 4, + LLVMTypeRef lfi_type = LLVMStructTypeInContext(c->context, f_params, 5, false); LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder); @@ -88,6 +90,10 @@ static LLVMValueRef make_lang_features_init(compile_t* c) LLVMBuildStore(c->builder, LLVMConstInt(c->intptr, desc_table_size, false), field); + field = LLVMBuildStructGEP(c->builder, lfi_object, 4, ""); + LLVMBuildStore(c->builder, LLVMBuildBitCast(c->builder, desc_table_lookup_fn, + c->descriptor_offset_lookup_fn, ""), field); + return LLVMBuildBitCast(c->builder, lfi_object, c->void_ptr, ""); } diff --git a/src/libponyc/codegen/genname.c b/src/libponyc/codegen/genname.c index a481f31dca..cab07cf70a 100644 --- a/src/libponyc/codegen/genname.c +++ b/src/libponyc/codegen/genname.c @@ -199,3 +199,10 @@ const char* genname_program_fn(const char* program, const char* name) { return stringtab_two(program, name); } + +const char* genname_type_with_id(const char* type, uint64_t type_id) +{ + printbuf_t* buf = printbuf_new(); + printbuf(buf, "%s_%" PRIu64, type, type_id); + return stringtab_buf(buf); +} diff --git a/src/libponyc/codegen/genname.h b/src/libponyc/codegen/genname.h index 13d39ee334..ce160524b0 100644 --- a/src/libponyc/codegen/genname.h +++ b/src/libponyc/codegen/genname.h @@ -42,6 +42,8 @@ const char* genname_unsafe(const char* name); const char* genname_program_fn(const char* program, const char* name); +const char* genname_type_with_id(const char* type, uint64_t type_id); + PONY_EXTERN_C_END #endif diff --git a/src/libponyc/codegen/genprim.c b/src/libponyc/codegen/genprim.c index ca8b8e298e..ae5fcc60bb 100644 --- a/src/libponyc/codegen/genprim.c +++ b/src/libponyc/codegen/genprim.c @@ -821,7 +821,7 @@ void genprim_array_serialise(compile_t* c, reach_type_t* t) LLVMValueRef offset_addr = LLVMBuildInBoundsGEP(c->builder, addr, &offset, 1, ""); - genserialise_typeid(c, t, offset_addr); + genserialise_serialiseid(c, t, offset_addr); // Don't serialise our contents if we are opaque. LLVMBasicBlockRef body_block = codegen_block(c, "body"); @@ -942,7 +942,7 @@ void genprim_array_deserialise(compile_t* c, reach_type_t* t) LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->structure_ptr, ""); - gendeserialise_typeid(c, c_t, object); + gendeserialise_serialiseid(c, c_t, object); // Deserialise the array contents. LLVMValueRef alloc = field_value(c, object, 2); @@ -1065,7 +1065,7 @@ void genprim_string_serialise(compile_t* c, reach_type_t* t) LLVMValueRef offset_addr = LLVMBuildInBoundsGEP(c->builder, addr, &offset, 1, ""); - genserialise_typeid(c, t, offset_addr); + genserialise_serialiseid(c, t, offset_addr); // Don't serialise our contents if we are opaque. LLVMBasicBlockRef body_block = codegen_block(c, "body"); @@ -1129,7 +1129,7 @@ void genprim_string_deserialise(compile_t* c, reach_type_t* t) LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->structure_ptr, ""); - gendeserialise_typeid(c, c_t, object); + gendeserialise_serialiseid(c, c_t, object); // Deserialise the string contents. LLVMValueRef alloc = field_value(c, object, 2); diff --git a/src/libponyc/codegen/genserialise.c b/src/libponyc/codegen/genserialise.c index e150ada7c2..80831e4ecc 100644 --- a/src/libponyc/codegen/genserialise.c +++ b/src/libponyc/codegen/genserialise.c @@ -3,6 +3,7 @@ #include "gendesc.h" #include "genfun.h" #include "genname.h" +#include "genopt.h" #include "genprim.h" #include "ponyassert.h" #include "../../libponyrt/mem/pool.h" @@ -19,7 +20,7 @@ static void serialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, { case TK_PRIMITIVE: { - genserialise_typeid(c, t, offset); + genserialise_serialiseid(c, t, offset); if(c_t->primitive != NULL) { @@ -36,7 +37,7 @@ static void serialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, case TK_CLASS: { - genserialise_typeid(c, t, offset); + genserialise_serialiseid(c, t, offset); extra++; break; } @@ -44,7 +45,7 @@ static void serialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, case TK_ACTOR: { // Skip the actor pad. - genserialise_typeid(c, t, offset); + genserialise_serialiseid(c, t, offset); extra += 2; break; } @@ -54,7 +55,7 @@ static void serialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, // Get the tuple primitive type. if(LLVMTypeOf(object) == c_t->structure_ptr) { - genserialise_typeid(c, t, offset); + genserialise_serialiseid(c, t, offset); object = LLVMBuildStructGEP(c->builder, object, 1, ""); LLVMValueRef size = LLVMConstInt(c->intptr, LLVMOffsetOfElement(c->target_data, structure, 1), false); @@ -101,13 +102,25 @@ static void serialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, } } -void genserialise_typeid(compile_t* c, reach_type_t* t, LLVMValueRef offset) +void genserialise_serialiseid(compile_t* c, reach_type_t* t, LLVMValueRef offset) { - // Write the type id instead of the descriptor. - LLVMValueRef value = LLVMConstInt(c->intptr, t->type_id, false); - LLVMValueRef loc = LLVMBuildBitCast(c->builder, offset, - LLVMPointerType(c->intptr, 0), ""); - LLVMBuildStore(c->builder, value, loc); + // Write the serialise id instead of the descriptor. + if(target_is_ilp32(c->opt->triple)) + { + // TODO: fix this and make 32 bit platforms properly serialise 64 bit + // serialise_ids + LLVMValueRef value = LLVMConstInt(c->intptr, t->serialise_id, false); + LLVMValueRef loc = LLVMBuildBitCast(c->builder, offset, + LLVMPointerType(c->intptr, 0), ""); + LLVMBuildStore(c->builder, value, loc); + } + else + { + LLVMValueRef value = LLVMConstInt(c->i64, t->serialise_id, false); + LLVMValueRef loc = LLVMBuildBitCast(c->builder, offset, + LLVMPointerType(c->i64, 0), ""); + LLVMBuildStore(c->builder, value, loc); + } } static void serialise_bare_interface(compile_t* c, reach_type_t* t, @@ -137,7 +150,7 @@ static void serialise_bare_interface(compile_t* c, reach_type_t* t, LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntEQ, obj, ((compile_type_t*)sub->c_type)->instance, ""); LLVMBuildCondBr(c->builder, test, post_block, next_block); - LLVMValueRef value = LLVMConstInt(c->intptr, sub->type_id, false); + LLVMValueRef value = LLVMConstInt(c->i64, sub->serialise_id, false); LLVMAddIncoming(phi, &value, ¤t_block, 1); LLVMPositionBuilderAtEnd(c->builder, next_block); sub = next; @@ -146,7 +159,7 @@ static void serialise_bare_interface(compile_t* c, reach_type_t* t, } LLVMBuildBr(c->builder, post_block); - LLVMValueRef value = LLVMConstInt(c->intptr, sub->type_id, false); + LLVMValueRef value = LLVMConstInt(c->i64, sub->serialise_id, false); LLVMAddIncoming(phi, &value, ¤t_block, 1); LLVMMoveBasicBlockAfter(post_block, current_block); @@ -173,12 +186,12 @@ void genserialise_element(compile_t* c, reach_type_t* t, bool embed, LLVMPointerType(c_t->mem_type, 0), ""); LLVMBuildStore(c->builder, value, loc); } else if(t->bare_method != NULL) { - // Bare object, either write the type id directly if it is a concrete object - // or compute the type id based on the object value and write it if it isn't. + // Bare object, either write the serialise id directly if it is a concrete object + // or compute the serialise id based on the object value and write it if it isn't. switch(t->underlying) { case TK_PRIMITIVE: - genserialise_typeid(c, t, offset); + genserialise_serialiseid(c, t, offset); break; case TK_INTERFACE: @@ -247,7 +260,7 @@ static void deserialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, case TK_PRIMITIVE: case TK_CLASS: { - gendeserialise_typeid(c, c_t, object); + gendeserialise_serialiseid(c, c_t, object); extra++; break; } @@ -255,7 +268,7 @@ static void deserialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, case TK_ACTOR: { // Skip the actor pad. - gendeserialise_typeid(c, c_t, object); + gendeserialise_serialiseid(c, c_t, object); extra += 2; break; } @@ -265,7 +278,7 @@ static void deserialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, // Get the tuple primitive type. if(LLVMTypeOf(object) == c_t->structure_ptr) { - gendeserialise_typeid(c, c_t, object); + gendeserialise_serialiseid(c, c_t, object); object = LLVMBuildStructGEP(c->builder, object, 1, ""); } break; @@ -282,20 +295,20 @@ static void deserialise(compile_t* c, reach_type_t* t, LLVMValueRef ctx, } } -void gendeserialise_typeid(compile_t* c, compile_type_t* t, LLVMValueRef object) +void gendeserialise_serialiseid(compile_t* c, compile_type_t* t, LLVMValueRef object) { - // Write the descriptor instead of the type id. + // Write the descriptor instead of the serialise id. LLVMValueRef desc_ptr = LLVMBuildStructGEP(c->builder, object, 0, ""); LLVMBuildStore(c->builder, t->desc, desc_ptr); } static void deserialise_bare_interface(compile_t* c, LLVMValueRef ptr) { - LLVMValueRef type_id = LLVMBuildLoad(c->builder, ptr, ""); + LLVMValueRef serialise_id = LLVMBuildLoad(c->builder, ptr, ""); LLVMValueRef args[2]; args[0] = LLVMConstInt(c->i32, 0, false); - args[1] = LLVMBuildPtrToInt(c->builder, type_id, c->intptr, ""); + args[1] = LLVMBuildPtrToInt(c->builder, serialise_id, c->i64, ""); LLVMValueRef desc = LLVMBuildInBoundsGEP(c->builder, c->desc_table, args, 2, ""); diff --git a/src/libponyc/codegen/genserialise.h b/src/libponyc/codegen/genserialise.h index 45743be46e..92d4d9803f 100644 --- a/src/libponyc/codegen/genserialise.h +++ b/src/libponyc/codegen/genserialise.h @@ -11,9 +11,9 @@ typedef struct compile_type_t compile_type_t; void genserialise_element(compile_t* c, reach_type_t* t, bool embed, LLVMValueRef ctx, LLVMValueRef ptr, LLVMValueRef offset); -void genserialise_typeid(compile_t* c, reach_type_t* t, LLVMValueRef offset); +void genserialise_serialiseid(compile_t* c, reach_type_t* t, LLVMValueRef offset); -void gendeserialise_typeid(compile_t* c, compile_type_t* t, LLVMValueRef offset); +void gendeserialise_serialiseid(compile_t* c, compile_type_t* t, LLVMValueRef offset); void gendeserialise_element(compile_t* c, reach_type_t* t, bool embed, LLVMValueRef ctx, LLVMValueRef ptr); diff --git a/src/libponyc/codegen/gentype.c b/src/libponyc/codegen/gentype.c index b098121dae..3e432e3fe3 100644 --- a/src/libponyc/codegen/gentype.c +++ b/src/libponyc/codegen/gentype.c @@ -907,6 +907,7 @@ bool gentypes(compile_t* c) } gendesc_table(c); + gendesc_table_lookup(c); c->numeric_sizes = gen_numeric_size_table(c); diff --git a/src/libponyc/pkg/package.c b/src/libponyc/pkg/package.c index 19132606f9..0d17e3b33b 100644 --- a/src/libponyc/pkg/package.c +++ b/src/libponyc/pkg/package.c @@ -1370,12 +1370,13 @@ static void package_signature_serialise_trace(pony_ctx_t* ctx, static void package_signature_serialise(pony_ctx_t* ctx, void* object, - void* buf, size_t offset, int mutability) + void* buf, uint64_t offset, int mutability) { (void)mutability; package_t* package = (package_t*)object; - package_signature_t* dst = (package_signature_t*)((uintptr_t)buf + offset); + package_signature_t* dst = (package_signature_t*)((uintptr_t)buf + + (uintptr_t)offset); dst->filename = (const char*)pony_serialise_offset(ctx, (char*)package->filename); @@ -1390,6 +1391,7 @@ static pony_type_t package_dep_signature_pony = sizeof(package_signature_t), 0, 0, + 0, NULL, NULL, package_dep_signature_serialise_trace, @@ -1418,6 +1420,7 @@ static pony_type_t package_signature_pony = sizeof(package_signature_t), 0, 0, + 0, NULL, NULL, package_signature_serialise_trace, @@ -1469,13 +1472,13 @@ static void package_group_signature_serialise_trace(pony_ctx_t* ctx, static void package_group_signature_serialise(pony_ctx_t* ctx, void* object, - void* buf, size_t offset, int mutability) + void* buf, uint64_t offset, int mutability) { (void)ctx; (void)mutability; package_group_t* group = (package_group_t*)object; - package_group_t* dst = (package_group_t*)((uintptr_t)buf + offset); + package_group_t* dst = (package_group_t*)((uintptr_t)buf + (uintptr_t)offset); if(group->signature != NULL) { @@ -1495,6 +1498,7 @@ static pony_type_t package_group_dep_signature_pony = sizeof(const char*), 0, 0, + 0, NULL, NULL, package_group_dep_signature_serialise_trace, @@ -1523,6 +1527,7 @@ static pony_type_t package_group_signature_pony = sizeof(const char*), 0, 0, + 0, NULL, NULL, package_group_signature_serialise_trace, @@ -1617,12 +1622,12 @@ static void package_serialise_trace(pony_ctx_t* ctx, void* object) static void package_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; package_t* package = (package_t*)object; - package_t* dst = (package_t*)((uintptr_t)buf + offset); + package_t* dst = (package_t*)((uintptr_t)buf + (uintptr_t)offset); dst->path = (const char*)pony_serialise_offset(ctx, (char*)package->path); dst->qualified_name = (const char*)pony_serialise_offset(ctx, @@ -1671,6 +1676,7 @@ static pony_type_t package_pony = sizeof(package_t), 0, 0, + 0, NULL, NULL, package_serialise_trace, @@ -1705,13 +1711,13 @@ static void package_group_serialise_trace(pony_ctx_t* ctx, void* object) static void package_group_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)ctx; (void)mutability; package_group_t* group = (package_group_t*)object; - package_group_t* dst = (package_group_t*)((uintptr_t)buf + offset); + package_group_t* dst = (package_group_t*)((uintptr_t)buf + (uintptr_t)offset); uintptr_t ptr_offset = pony_serialise_offset(ctx, group->signature); dst->signature = (char*)ptr_offset; @@ -1743,6 +1749,7 @@ static pony_type_t package_group_pony = sizeof(package_group_t), 0, 0, + 0, NULL, NULL, package_group_serialise_trace, diff --git a/src/libponyc/pkg/program.c b/src/libponyc/pkg/program.c index d768147876..4ecdbd82c9 100644 --- a/src/libponyc/pkg/program.c +++ b/src/libponyc/pkg/program.c @@ -358,12 +358,12 @@ static void program_serialise_trace(pony_ctx_t* ctx, void* object) } static void program_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; program_t* program = (program_t*)object; - program_t* dst = (program_t*)((uintptr_t)buf + offset); + program_t* dst = (program_t*)((uintptr_t)buf + (uintptr_t)offset); dst->package_groups = (package_group_list_t*)pony_serialise_offset(ctx, program->package_groups); @@ -416,6 +416,7 @@ static pony_type_t program_pony = sizeof(program_t), 0, 0, + 0, NULL, NULL, program_serialise_trace, diff --git a/src/libponyc/reach/reach.c b/src/libponyc/reach/reach.c index 34ceba4f59..933333230f 100644 --- a/src/libponyc/reach/reach.c +++ b/src/libponyc/reach/reach.c @@ -2,6 +2,7 @@ #include "subtype.h" #include "../ast/astbuild.h" #include "../codegen/genname.h" +#include "../codegen/genopt.h" #include "../pass/expr.h" #include "../type/assemble.h" #include "../type/cap.h" @@ -10,6 +11,7 @@ #include "../../libponyrt/gc/serialise.h" #include "../../libponyrt/mem/pool.h" #include "ponyassert.h" +#include #include #include @@ -738,6 +740,7 @@ static reach_type_t* add_reach_type(reach_t* r, ast_t* type) t->ast = set_cap_and_ephemeral(type, TK_REF, TK_NONE); t->ast_cap = ast_dup(type); t->type_id = (uint32_t)-1; + t->serialise_id = (uint64_t)-1; ast_set_scope(t->ast, NULL); ast_set_scope(t->ast_cap, NULL); @@ -792,6 +795,14 @@ static reach_type_t* add_tuple(reach_t* r, ast_t* type, pass_opt_t* opt) t->type_id = get_new_tuple_id(r); t->can_be_boxed = true; + if(target_is_ilp32(opt->triple)) + t->serialise_id = t->type_id; + else + // TODO: ideally should be hashing AST tree for type and not just name + t->serialise_id = ponyint_hash_str64(t->name); + + pony_assert(t->serialise_id != ((uint64_t)-1)); // -1 is for `Pointer`s + t->field_count = (uint32_t)ast_childcount(t->ast); t->fields = (reach_field_t*)ponyint_pool_alloc_size( t->field_count * sizeof(reach_field_t)); @@ -922,6 +933,14 @@ static reach_type_t* add_nominal(reach_t* r, ast_t* type, pass_opt_t* opt) t->type_id = get_new_numeric_id(r); else if(t->underlying != TK_STRUCT) t->type_id = get_new_object_id(r); + + if(target_is_ilp32(opt->triple)) + t->serialise_id = t->type_id; + else + // TODO: ideally should be hashing AST tree for type and not just name + t->serialise_id = ponyint_hash_str64(t->name); + + pony_assert(t->serialise_id != ((uint64_t)-1)); // -1 is for `Pointer`s } if(ast_id(def) != TK_PRIMITIVE) @@ -1510,6 +1529,10 @@ void reach_dump(reach_t* r) size_t j = HASHMAP_BEGIN; reach_method_name_t* n; + printf(" serialise_id: %" PRIu64 "\n", t->serialise_id); + printf(" is_trait: %s\n", (t->is_trait)?"true":"false"); + printf(" can_be_boxed: %s\n", (t->can_be_boxed)?"true":"false"); + printf(" vtable: %d\n", t->vtable_size); while((n = reach_method_names_next(&t->methods, &j)) != NULL) @@ -1529,6 +1552,8 @@ void reach_dump(reach_t* r) printf(" %s\n", t2->name); } } + + printf(" Total Type Count: %d\n", r->total_type_count); } static void reach_param_serialise_trace(pony_ctx_t* ctx, void* object) @@ -1541,12 +1566,12 @@ static void reach_param_serialise_trace(pony_ctx_t* ctx, void* object) } static void reach_param_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; reach_param_t* p = (reach_param_t*)object; - reach_param_t* dst = (reach_param_t*)((uintptr_t)buf + offset); + reach_param_t* dst = (reach_param_t*)((uintptr_t)buf + (uintptr_t)offset); dst->name = (const char*)pony_serialise_offset(ctx, (char*)p->name); dst->ast = (ast_t*)pony_serialise_offset(ctx, p->ast); @@ -1571,6 +1596,7 @@ static pony_type_t reach_param_pony = sizeof(reach_param_t), 0, 0, + 0, NULL, NULL, reach_param_serialise_trace, @@ -1624,12 +1650,12 @@ static void reach_method_serialise_trace(pony_ctx_t* ctx, void* object) } static void reach_method_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; reach_method_t* m = (reach_method_t*)object; - reach_method_t* dst = (reach_method_t*)((uintptr_t)buf + offset); + reach_method_t* dst = (reach_method_t*)((uintptr_t)buf + (uintptr_t)offset); dst->name = (const char*)pony_serialise_offset(ctx, (char*)m->name); dst->mangled_name = (const char*)pony_serialise_offset(ctx, @@ -1705,6 +1731,7 @@ static pony_type_t reach_method_pony = sizeof(reach_method_t), 0, 0, + 0, NULL, NULL, reach_method_serialise_trace, @@ -1735,12 +1762,13 @@ static void reach_method_name_serialise_trace(pony_ctx_t* ctx, void* object) } static void reach_method_name_serialise(pony_ctx_t* ctx, void* object, - void* buf, size_t offset, int mutability) + void* buf, uint64_t offset, int mutability) { (void)mutability; reach_method_name_t* n = (reach_method_name_t*)object; - reach_method_name_t* dst = (reach_method_name_t*)((uintptr_t)buf + offset); + reach_method_name_t* dst = (reach_method_name_t*)((uintptr_t)buf + + (uintptr_t)offset); dst->id = n->id; dst->cap = n->cap; @@ -1767,6 +1795,7 @@ static pony_type_t reach_method_name_pony = sizeof(reach_method_name_t), 0, 0, + 0, NULL, NULL, reach_method_name_serialise_trace, @@ -1796,12 +1825,12 @@ static void reach_field_serialise_trace(pony_ctx_t* ctx, void* object) } static void reach_field_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; reach_field_t* f = (reach_field_t*)object; - reach_field_t* dst = (reach_field_t*)((uintptr_t)buf + offset); + reach_field_t* dst = (reach_field_t*)((uintptr_t)buf + (uintptr_t)offset); dst->ast = (ast_t*)pony_serialise_offset(ctx, f->ast); dst->type = (reach_type_t*)pony_serialise_offset(ctx, f->type); @@ -1824,6 +1853,7 @@ static pony_type_t reach_field_pony = sizeof(reach_field_t), 0, 0, + 0, NULL, NULL, reach_field_serialise_trace, @@ -1872,12 +1902,12 @@ static void reach_type_serialise_trace(pony_ctx_t* ctx, void* object) } static void reach_type_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; reach_type_t* t = (reach_type_t*)object; - reach_type_t* dst = (reach_type_t*)((uintptr_t)buf + offset); + reach_type_t* dst = (reach_type_t*)((uintptr_t)buf + (uintptr_t)offset); dst->name = (const char*)pony_serialise_offset(ctx, (char*)t->name); dst->mangle = (const char*)pony_serialise_offset(ctx, (char*)t->mangle); @@ -1894,6 +1924,7 @@ static void reach_type_serialise(pony_ctx_t* ctx, void* object, void* buf, dst->vtable_size = t->vtable_size; dst->can_be_boxed = t->can_be_boxed; dst->is_trait = t->is_trait; + dst->serialise_id = t->serialise_id; dst->field_count = t->field_count; dst->fields = (reach_field_t*)pony_serialise_offset(ctx, t->fields); @@ -1947,6 +1978,7 @@ static pony_type_t reach_type_pony = sizeof(reach_type_t), 0, 0, + 0, NULL, NULL, reach_type_serialise_trace, @@ -1975,12 +2007,12 @@ static void reach_serialise_trace(pony_ctx_t* ctx, void* object) } static void reach_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)mutability; reach_t* r = (reach_t*)object; - reach_t* dst = (reach_t*)((uintptr_t)buf + offset); + reach_t* dst = (reach_t*)((uintptr_t)buf + (uintptr_t)offset); reach_types_serialise(ctx, &r->types, buf, offset + offsetof(reach_t, types), PONY_TRACE_MUTABLE); @@ -2005,6 +2037,7 @@ static pony_type_t reach_pony = sizeof(reach_t), 0, 0, + 0, NULL, NULL, reach_serialise_trace, diff --git a/src/libponyc/reach/reach.h b/src/libponyc/reach/reach.h index afd0f79025..eee7f81e25 100644 --- a/src/libponyc/reach/reach.h +++ b/src/libponyc/reach/reach.h @@ -99,6 +99,7 @@ struct reach_type_t reach_type_cache_t subtypes; uint32_t type_id; uint32_t vtable_size; + uint64_t serialise_id; bool can_be_boxed; bool is_trait; diff --git a/src/libponyc/type/reify.c b/src/libponyc/type/reify.c index 3b4b532b3e..5a5ce49ac7 100644 --- a/src/libponyc/type/reify.c +++ b/src/libponyc/type/reify.c @@ -505,13 +505,13 @@ static void deferred_reification_serialise_trace(pony_ctx_t* ctx, void* object) } static void deferred_reification_serialise(pony_ctx_t* ctx, void* object, - void* buf, size_t offset, int mutability) + void* buf, uint64_t offset, int mutability) { (void)mutability; deferred_reification_t* d = (deferred_reification_t*)object; deferred_reification_t* dst = - (deferred_reification_t*)((uintptr_t)buf + offset); + (deferred_reification_t*)((uintptr_t)buf + (uintptr_t)offset); dst->ast = (ast_t*)pony_serialise_offset(ctx, d->ast); dst->type_typeparams = (ast_t*)pony_serialise_offset(ctx, d->type_typeparams); @@ -546,6 +546,7 @@ static pony_type_t deferred_reification_pony = sizeof(deferred_reification_t), 0, 0, + 0, NULL, NULL, deferred_reification_serialise_trace, diff --git a/src/libponyrt/ds/fun.c b/src/libponyrt/ds/fun.c index c41e386428..6fa3499820 100644 --- a/src/libponyrt/ds/fun.c +++ b/src/libponyrt/ds/fun.c @@ -3,11 +3,8 @@ #include -static const unsigned char the_key[16] = { - 0xFE, 0x09, 0xD3, 0x22, 0x6B, 0x9C, 0x10, 0x8A, - 0xE1, 0x35, 0x72, 0xB5, 0xCC, 0x3F, 0x92, 0x9F -}; - +// Use the MD5 of the current pony version for the key +static const unsigned char the_key[16] = { PONY_VERSION_FORMATTED_MD5 }; #ifdef PLATFORM_IS_ILP32 @@ -64,6 +61,7 @@ static uint32_t halfsiphash24(const unsigned char* key, const char* in, return v0 ^ v1 ^ v2 ^ v3; } + #endif #define ROTL64(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) @@ -137,6 +135,11 @@ PONY_API uint64_t ponyint_hash_block64(const void* p, size_t len) return siphash24(the_key, (const char*)p, len); } +uint64_t ponyint_hash_str64(const char* str) +{ + return siphash24(the_key, str, strlen(str)); +} + size_t ponyint_hash_str(const char* str) { #ifdef PLATFORM_IS_ILP32 diff --git a/src/libponyrt/ds/fun.h b/src/libponyrt/ds/fun.h index b19976bc0d..a192548043 100644 --- a/src/libponyrt/ds/fun.h +++ b/src/libponyrt/ds/fun.h @@ -25,6 +25,8 @@ PONY_API size_t ponyint_hash_block(const void* p, size_t len); PONY_API uint64_t ponyint_hash_block64(const void* p, size_t len); +uint64_t ponyint_hash_str64(const char* str); + size_t ponyint_hash_str(const char* str); size_t ponyint_hash_ptr(const void* p); diff --git a/src/libponyrt/ds/hash.c b/src/libponyrt/ds/hash.c index d447e86f18..9b7514c46c 100644 --- a/src/libponyrt/ds/hash.c +++ b/src/libponyrt/ds/hash.c @@ -563,10 +563,10 @@ void ponyint_hashmap_serialise_trace(pony_ctx_t* ctx, void* object, } void ponyint_hashmap_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset) + uint64_t offset) { hashmap_t* map = (hashmap_t*)object; - hashmap_t* dst = (hashmap_t*)((uintptr_t)buf + offset); + hashmap_t* dst = (hashmap_t*)((uintptr_t)((uintptr_t)buf + offset)); uintptr_t bitmap_offset = pony_serialise_offset(ctx, map->item_bitmap); diff --git a/src/libponyrt/ds/hash.h b/src/libponyrt/ds/hash.h index 8361187f83..b75a0f79e0 100644 --- a/src/libponyrt/ds/hash.h +++ b/src/libponyrt/ds/hash.h @@ -114,7 +114,7 @@ void ponyint_hashmap_serialise_trace(pony_ctx_t* ctx, void* object, pony_type_t* elem_type); void ponyint_hashmap_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset); + uint64_t offset); void ponyint_hashmap_deserialise(pony_ctx_t* ctx, void* object, pony_type_t* elem_type); @@ -137,7 +137,7 @@ void ponyint_hashmap_deserialise(pony_ctx_t* ctx, void* object, DECLARE_HASHMAP(name, name_t, type) \ void name##_serialise_trace(pony_ctx_t* ctx, void* object); \ void name##_serialise(pony_ctx_t* ctx, void* object, void* buf, \ - size_t offset, int mutability); \ + uint64_t offset, int mutability); \ void name##_deserialise(pony_ctx_t* ctx, void* object); \ const pony_type_t* name##_pony_type(); \ @@ -210,7 +210,7 @@ void ponyint_hashmap_deserialise(pony_ctx_t* ctx, void* object, ponyint_hashmap_serialise_trace(ctx, object, elem_type); \ } \ void name##_serialise(pony_ctx_t* ctx, void* object, void* buf, \ - size_t offset, int mutability) \ + uint64_t offset, int mutability) \ { \ (void)mutability; \ ponyint_hashmap_serialise(ctx, object, buf, offset); \ @@ -225,6 +225,7 @@ void ponyint_hashmap_deserialise(pony_ctx_t* ctx, void* object, sizeof(name_t), \ 0, \ 0, \ + 0, \ NULL, \ NULL, \ name##_serialise_trace, \ diff --git a/src/libponyrt/ds/list.c b/src/libponyrt/ds/list.c index 4fd6adbd62..509908c7c5 100644 --- a/src/libponyrt/ds/list.c +++ b/src/libponyrt/ds/list.c @@ -192,10 +192,10 @@ void ponyint_list_serialise_trace(pony_ctx_t* ctx, void* object, } void ponyint_list_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset) + uint64_t offset) { list_t* list = (list_t*)object; - list_t* dst = (list_t*)((uintptr_t)buf + offset); + list_t* dst = (list_t*)((uintptr_t)((uintptr_t)buf + offset)); dst->data = (void*)pony_serialise_offset(ctx, list->data); dst->next = (list_t*)pony_serialise_offset(ctx, list->next); diff --git a/src/libponyrt/ds/list.h b/src/libponyrt/ds/list.h index 6d175f41dc..cbbeed060a 100644 --- a/src/libponyrt/ds/list.h +++ b/src/libponyrt/ds/list.h @@ -47,7 +47,7 @@ void ponyint_list_serialise_trace(pony_ctx_t* ctx, void* object, pony_type_t* list_type, pony_type_t* elem_type); void ponyint_list_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset); + uint64_t offset); void ponyint_list_deserialise(pony_ctx_t* ctx, void* object, pony_type_t* list_type, pony_type_t* elem_type); @@ -76,7 +76,7 @@ void ponyint_list_deserialise(pony_ctx_t* ctx, void* object, DECLARE_LIST(name, name_t, type) \ void name##_serialise_trace(pony_ctx_t* ctx, void* object); \ void name##_serialise(pony_ctx_t* ctx, void* object, void* buf, \ - size_t offset, int mutability); \ + uint64_t offset, int mutability); \ void name##_deserialise(pony_ctx_t* ctx, void* object); \ const pony_type_t* name##_pony_type(); \ @@ -152,7 +152,7 @@ void ponyint_list_deserialise(pony_ctx_t* ctx, void* object, ponyint_list_serialise_trace(ctx, object, name##_pony_type(), elem_type); \ } \ void name##_serialise(pony_ctx_t* ctx, void* object, void* buf, \ - size_t offset, int mutability) \ + uint64_t offset, int mutability) \ { \ (void)mutability; \ ponyint_list_serialise(ctx, object, buf, offset); \ @@ -167,6 +167,7 @@ void ponyint_list_deserialise(pony_ctx_t* ctx, void* object, sizeof(name_t), \ 0, \ 0, \ + 0, \ NULL, \ NULL, \ name##_serialise_trace, \ diff --git a/src/libponyrt/gc/cycle.c b/src/libponyrt/gc/cycle.c index b618665c64..c7df2a4b9d 100644 --- a/src/libponyrt/gc/cycle.c +++ b/src/libponyrt/gc/cycle.c @@ -891,6 +891,7 @@ static pony_type_t cycle_type = sizeof(detector_t), 0, 0, + 0, NULL, NULL, NULL, diff --git a/src/libponyrt/gc/serialise.c b/src/libponyrt/gc/serialise.c index 1b5144b7ae..8e74be334d 100644 --- a/src/libponyrt/gc/serialise.c +++ b/src/libponyrt/gc/serialise.c @@ -20,13 +20,14 @@ PONY_EXTERN_C_BEGIN static size_t desc_table_size = 0; static pony_type_t** desc_table = NULL; +static desc_offset_lookup_fn desc_table_offset_lookup_fn = NULL; PONY_EXTERN_C_END struct serialise_t { uintptr_t key; - uintptr_t value; + uint64_t value; pony_type_t* t; int mutability; bool block; @@ -75,13 +76,14 @@ static void custom_deserialise(pony_ctx_t* ctx) { if (s->t != NULL && s->t->custom_deserialise != NULL) { - s->t->custom_deserialise((void *)(s->value), + s->t->custom_deserialise((void *)((uintptr_t)s->value), (void*)((uintptr_t)ctx->serialise_buffer + s->key + s->t->size)); } } } -bool ponyint_serialise_setup(pony_type_t** table, size_t table_size) +bool ponyint_serialise_setup(pony_type_t** table, size_t table_size, + desc_offset_lookup_fn desc_table_offset_lookup) { #ifndef PONY_NDEBUG for(uint32_t i = 0; i < table_size; i++) @@ -93,10 +95,18 @@ bool ponyint_serialise_setup(pony_type_t** table, size_t table_size) desc_table = table; desc_table_size = table_size; + desc_table_offset_lookup_fn = desc_table_offset_lookup; return true; } +static pony_type_t* get_descriptor(uint64_t serialise_id) +{ + uint32_t offset = desc_table_offset_lookup_fn(serialise_id); + pony_assert(offset < desc_table_size); + return desc_table[offset]; +} + void ponyint_serialise_object(pony_ctx_t* ctx, void* p, pony_type_t* t, int mutability) { @@ -186,15 +196,22 @@ PONY_API size_t pony_serialise_offset(pony_ctx_t* ctx, void* p) if(s != NULL) { if(s->block || (s->t != NULL && s->t->serialise != NULL)) - return s->value; + return (uintptr_t)s->value; else return ALL_BITS; } - // If we are not in the map, we are an untraced primitive. Return the type id - // with the high bit set. + // TODO: FIND OUT WHEN/HOW THIS CAN HAPPEN!!!!!! + // If not possible normally, make this into an error/assert! + // If possible, figure out how to handle 64 bit serialise_id's and return types + // since the pointers are no longer able to hold the serialise_id + high bit + // twiddles. + // See TODO in pony_deserialise_offset for related issue + + // If we are not in the map, we are an untraced primitive. Return the + // serialise id with the high bit set. pony_type_t* t = *(pony_type_t**)p; - return (size_t)t->id | HIGH_BIT; + return (size_t)t->serialise_id | HIGH_BIT; } PONY_API void pony_serialise(pony_ctx_t* ctx, void* p, pony_type_t* t, @@ -244,6 +261,9 @@ PONY_API void* pony_deserialise_offset(pony_ctx_t* ctx, pony_type_t* t, // primitive, or an unserialised field in an opaque object. if((offset & HIGH_BIT) != 0) { + // TODO: NOTE: this section needs changing because uintptr_t can't safely + // hold u64 + high bit twiddles + // See TODO in pony_serialise_offset for related issue offset &= ~HIGH_BIT; if(offset > desc_table_size) @@ -263,22 +283,32 @@ PONY_API void* pony_deserialise_offset(pony_ctx_t* ctx, pony_type_t* t, serialise_t* s = ponyint_serialise_get(&ctx->serialise, &k, &index); if(s != NULL) - return (void*)s->value; + return (void*)((uintptr_t)s->value); // If we haven't been passed a type descriptor, read one. if(t == NULL) { - // Make sure we have space to read a type id. + // Make sure we have space to read a serialise id. +#ifdef PLATFORM_IS_ILP32 if((offset + sizeof(uintptr_t)) > ctx->serialise_size) +#else + if((offset + sizeof(uint64_t)) > ctx->serialise_size) +#endif { serialise_cleanup(ctx); ctx->serialise_throw(); abort(); } - // Turn the type id into a descriptor pointer. - uintptr_t id = *(uintptr_t*)((uintptr_t)ctx->serialise_buffer + offset); - t = desc_table[id]; + // Turn the serialise id into a descriptor pointer. +#ifdef PLATFORM_IS_ILP32 + // TODO: remove this ifdef once serialisation of 64 bit serialise_id's works for + // 32 bit platforms + uint64_t id = *(uintptr_t*)((uintptr_t)ctx->serialise_buffer + offset); +#else + uint64_t id = *(uint64_t*)((uintptr_t)ctx->serialise_buffer + offset); +#endif + t = get_descriptor(id); } // If it's a primitive, return the global instance. @@ -348,7 +378,7 @@ PONY_API void* pony_deserialise_raw(pony_ctx_t* ctx, uintptr_t offset, serialise_t* s = ponyint_serialise_get(&ctx->serialise, &k, &index); if(s != NULL) - return (void*)s->value; + return (void*)((uintptr_t)s->value); void* object = ds_fn((void*)((uintptr_t)ctx->serialise_buffer + offset), ctx->serialise_size - offset); diff --git a/src/libponyrt/gc/serialise.h b/src/libponyrt/gc/serialise.h index 4a41da9af9..d31b30ad88 100644 --- a/src/libponyrt/gc/serialise.h +++ b/src/libponyrt/gc/serialise.h @@ -23,7 +23,8 @@ typedef struct serialise_t serialise_t; DECLARE_HASHMAP(ponyint_serialise, ponyint_serialise_t, serialise_t); -bool ponyint_serialise_setup(pony_type_t** table, size_t table_size); +bool ponyint_serialise_setup(pony_type_t** table, size_t table_size, + desc_offset_lookup_fn desc_table_offset_lookup); void ponyint_serialise_object(pony_ctx_t* ctx, void* p, pony_type_t* t, int mutability); diff --git a/src/libponyrt/pony.h b/src/libponyrt/pony.h index 1f1ad853f6..f0c61ea1b5 100644 --- a/src/libponyrt/pony.h +++ b/src/libponyrt/pony.h @@ -82,7 +82,7 @@ typedef void (*pony_trace_fn)(pony_ctx_t* ctx, void* p); * A serialise function must not raise errors. */ typedef void (*pony_serialise_fn)(pony_ctx_t* ctx, void* p, void* addr, - size_t offset, int m); + uint64_t offset, int m); /** Serialise Space function. * @@ -134,6 +134,7 @@ typedef const struct _pony_type_t { uint32_t id; uint32_t size; + uint64_t serialise_id; uint32_t field_count; uint32_t field_offset; void* instance; @@ -151,6 +152,12 @@ typedef const struct _pony_type_t void* vtable; } pony_type_t; +/** Desc table lookup function. + * + * A function to convert `serialise_id`s to offsets in the desc table + */ +typedef uint32_t (*desc_offset_lookup_fn)(uint64_t serialise_id); + /** Language feature initialiser. * * Contains initialisers for the various language features initialised by @@ -177,6 +184,9 @@ typedef struct pony_language_features_init_t /// The total size of the descriptor_table array. size_t descriptor_table_size; + + /// The function to translate `type_id`s to offsets in the desc_table + desc_offset_lookup_fn desc_table_offset_lookup; } pony_language_features_init_t; /** Padding for actor types. diff --git a/src/libponyrt/sched/start.c b/src/libponyrt/sched/start.c index b961e6a497..d83b16b19d 100644 --- a/src/libponyrt/sched/start.c +++ b/src/libponyrt/sched/start.c @@ -183,7 +183,8 @@ PONY_API bool pony_start(bool library, int* exit_code, if(language_init.init_serialisation && !ponyint_serialise_setup(language_init.descriptor_table, - language_init.descriptor_table_size)) + language_init.descriptor_table_size, + language_init.desc_table_offset_lookup)) { atomic_store_explicit(&running, NOT_RUNNING, memory_order_relaxed); return false; diff --git a/test/libponyrt/ds/hash.cc b/test/libponyrt/ds/hash.cc index e635c43277..3eb906d9ad 100644 --- a/test/libponyrt/ds/hash.cc +++ b/test/libponyrt/ds/hash.cc @@ -48,7 +48,7 @@ static void hash_elem_serialise_trace(pony_ctx_t* ctx, void* object) } static void hash_elem_serialise(pony_ctx_t* ctx, void* object, void* buf, - size_t offset, int mutability) + uint64_t offset, int mutability) { (void)ctx; (void)mutability; @@ -72,6 +72,7 @@ static pony_type_t hash_elem_pony = sizeof(hash_elem_t), 0, 0, + 0, NULL, NULL, hash_elem_serialise_trace, diff --git a/wscript b/wscript index 80adfc4e0b..373c8c5a9f 100644 --- a/wscript +++ b/wscript @@ -35,6 +35,11 @@ with open('VERSION') as v: except: pass +# build ponyc version md5 +import hashlib +temp_md5 = hashlib.md5(VERSION).hexdigest() +VERSION_FORMATTED_MD5 = "0x" + ",0x".join([temp_md5[i:i+2] for i in range(0, len(temp_md5), 2)]) + # source and build directories top = '.' out = 'build' @@ -78,6 +83,7 @@ def init(ctx): def configure(ctx): ctx.env.append_value('DEFINES', [ 'PONY_VERSION="' + VERSION + '"', + 'PONY_VERSION_FORMATTED_MD5=' + VERSION_FORMATTED_MD5, 'PONY_USE_BIGINT', ])