From 522545287ee3c20c103d29f5dae9f041de7b1fbf Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 20 Jun 2019 12:37:57 -0400 Subject: [PATCH] Add janet_abstract_begin and janet_abstract_end This will allow some one constructing an abstract to only make it visible to the garbage collector after it is in a valid state. If code in the constructing cfunction panics before janet_abstract_end is called, the GC will not try to mark the incomplete abstract type. This is often not needed through careful programming, but should work well. --- src/core/abstract.c | 13 +++++++++++-- src/core/peg.c | 5 +++++ src/include/janet.h | 4 +++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/core/abstract.c b/src/core/abstract.c index 1132c470..0536fc98 100644 --- a/src/core/abstract.c +++ b/src/core/abstract.c @@ -26,10 +26,19 @@ #endif /* Create new userdata */ -void *janet_abstract(const JanetAbstractType *atype, size_t size) { - JanetAbstractHead *header = janet_gcalloc(JANET_MEMORY_ABSTRACT, +void *janet_abstract_begin(const JanetAbstractType *atype, size_t size) { + JanetAbstractHead *header = janet_gcalloc(JANET_MEMORY_NONE, sizeof(JanetAbstractHead) + size); header->size = size; header->type = atype; return (void *) & (header->data); } + +void *janet_abstract_end(void *x) { + janet_gc_settype((void *)(janet_gc_header(x)), JANET_MEMORY_ABSTRACT); + return x; +} + +void *janet_abstract(const JanetAbstractType *atype, size_t size) { + return janet_abstract_end(janet_abstract_begin(atype, size)); +} diff --git a/src/core/peg.c b/src/core/peg.c index 85b907e3..924ea665 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -990,6 +990,11 @@ static void peg_unmarshal(void *p, JanetMarshalContext *ctx) { peg->bytecode = NULL; peg->constants = NULL; + /* Ensure not too large */ + if (constants_start + sizeof(Janet) * peg->num_constants > janet_abstract_size(p)) { + janet_panic("size mismatch"); + } + for (size_t i = 0; i < peg->bytecode_len; i++) bytecode[i] = (uint32_t) janet_unmarshal_int(ctx); for (uint32_t j = 0; j < peg->num_constants; j++) diff --git a/src/include/janet.h b/src/include/janet.h index 335b909f..e92700fd 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1219,7 +1219,9 @@ JANET_API const JanetKV *janet_dictionary_next(const JanetKV *kvs, int32_t cap, #define janet_abstract_head(u) ((JanetAbstractHead *)((char *)u - offsetof(JanetAbstractHead, data))) #define janet_abstract_type(u) (janet_abstract_head(u)->type) #define janet_abstract_size(u) (janet_abstract_head(u)->size) -JANET_API void *janet_abstract(const JanetAbstractType *type, size_t size); +JANET_API void *janet_abstract_begin(const JanetAbstractType *type, size_t size); +JANET_API void *janet_abstract_end(void *); +JANET_API void *janet_abstract(const JanetAbstractType *type, size_t size); /* begin and end in one call */ /* Native */ typedef void (*JanetModule)(JanetTable *);