diff --git a/CHANGELOG b/CHANGELOG index 9f757252..627d4739 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,7 +7,7 @@ # | # | C Object System # | -# | Copyright (c) 2007+ Laurent Deniau, laurent.deniau@cern.ch +# | Copyright (c) 2007+ Laurent Deniau, laurent.deniau@gmail.com # | # | For more information, see: # | http://cern.ch/laurent.deniau/cos.html @@ -37,6 +37,8 @@ - docstring system finished and based on Sphinx (Python) for the html/pdf output. - documentation is ongoing + - moved to GitHub + - License moved to Apache ** 0.9 [2009-2010] - "Any" class resurrected. Useful to factorize some "Core" message. No @@ -69,7 +71,7 @@ - all the language feature are there - moving from alpha to beta state - properties added - - gdelete and gautoDelete added (for semi-GC) + - grelease and gautoRelease added (for semi-GC) - more compile-time checks - module support - start of other modules (not provided) diff --git a/CREDITS b/CREDITS index 1439c91c..7b928103 100644 --- a/CREDITS +++ b/CREDITS @@ -1,5 +1,5 @@ Authors: -Laurent Deniau -- laurent.deniau@cern.ch +Laurent Deniau -- laurent dot deniau at gmail dot com Contributors: Any help is welcome. diff --git a/CosBase/examples/README b/CosBase/examples/README index 6f9cb2a5..fd481dce 100644 --- a/CosBase/examples/README +++ b/CosBase/examples/README @@ -55,7 +55,6 @@ TRACE will show the value of important variables Project information: -------------------- - - web page: http:/cern.ch/laurent.deniau/cos.html - - web site: http:/sf.net/projects/cos - - contact : laurent.deniau@cern.ch + - web site: https://github.com/CObjectSystem/COS + - contact : laurent dot deniau at gmail dot com diff --git a/CosBase/examples/ex01/File.c b/CosBase/examples/ex01/File.c index 06975ece..7e587609 100644 --- a/CosBase/examples/ex01/File.c +++ b/CosBase/examples/ex01/File.c @@ -28,12 +28,12 @@ defmethod(OBJ, ginitWithStr, File, (STR)str) self->file = str ? fopen(str,"r+") : stdout; if (!self->file) test_errno(); // THROW - + retmethod(_1); endmethod defmethod(OBJ, gdeinit, File) - if (self->file) + if (self->file && self->file != stdout) fclose(self->file); retmethod(_1); diff --git a/CosBase/examples/ex01/Makefile b/CosBase/examples/ex01/Makefile index 92ebcacd..2f88f24e 100644 --- a/CosBase/examples/ex01/Makefile +++ b/CosBase/examples/ex01/Makefile @@ -1,15 +1,15 @@ # # C Object System # COS Example -# +# # Copyright 2007+ Laurent Deniau -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/CosBase/examples/ex01/String.c b/CosBase/examples/ex01/String.c index d9da5060..ca894f85 100644 --- a/CosBase/examples/ex01/String.c +++ b/CosBase/examples/ex01/String.c @@ -20,15 +20,15 @@ #include "String.h" #include "generics.h" -#include #include +#include makclass(String); static char* str_dup(STR str) { size_t len = strlen(str); - char *s = malloc(len+1); + char *s = cos_malloc(len+1); if (s) memcpy(s, str, len+1); return s; } @@ -39,12 +39,12 @@ defmethod(OBJ, ginitWithStr, String, (STR)str) self->str = str_dup(str); if (!self->str) THROW(ExBadAlloc); - + retmethod(_1); endmethod defmethod(OBJ, gdeinit, String) - free(self->str), self->str = 0; + cos_free(self->str), self->str = 0; retmethod(_1); endmethod diff --git a/CosBase/examples/ex01/main.c b/CosBase/examples/ex01/main.c index 2e4a83e9..d073b155 100644 --- a/CosBase/examples/ex01/main.c +++ b/CosBase/examples/ex01/main.c @@ -17,20 +17,27 @@ * limitations under the License. */ + +/* NOTE-USER: to load the shared libraries + linux: export LD_LIBRARY_PATH="path-to/CosBase/Darwin/lib/" + macos: export DYLD_LIBRARY_PATH="path-to/CosBase/Darwin/lib/" +*/ + #include "generics.h" + #include useclass(Stream, String); int main(void) { - OBJ strm = gnewWithStr(Stream, 0); + OBJ strm = gnewWithStr(Stream, NULL); OBJ str1 = gnewWithStr(String, "string one\n"); OBJ str2 = gnewWithStr(String, "string two\n"); gprint(strm, str1); gprint(strm, str2); - + grelease(str1); grelease(str2); grelease(strm); diff --git a/CosBase/include/cos/cfg/FreeBSD b/CosBase/include/cos/cfg/FreeBSD index 9907c67a..8b91df35 100644 --- a/CosBase/include/cos/cfg/FreeBSD +++ b/CosBase/include/cos/cfg/FreeBSD @@ -100,7 +100,8 @@ SYSLIBS := pthread dl CCFLAGS += -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \ -Wchar-subscripts -Wformat-nonliteral -Wwrite-strings \ -Wpointer-arith -Wbad-function-cast -Wcast-align -Wcast-qual \ - -Wfloat-equal -Wconversion -Wno-conversion -Winline + -Wfloat-equal -Wconversion -Wno-conversion -Winline \ + -Wno-unused-local-typedefs # CCFLAGS += --param large-function-growth=400 --param inline-unit-growth=200 diff --git a/CosBase/include/cos/cfg/Linux b/CosBase/include/cos/cfg/Linux index dc2d0f19..b26eac4f 100644 --- a/CosBase/include/cos/cfg/Linux +++ b/CosBase/include/cos/cfg/Linux @@ -100,7 +100,8 @@ SYSLIBS := pthread dl CCFLAGS += -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \ -Wchar-subscripts -Wformat-nonliteral -Wwrite-strings \ -Wpointer-arith -Wbad-function-cast -Wcast-align -Wcast-qual \ - -Wfloat-equal -Wconversion -Wno-conversion -Winline + -Wfloat-equal -Wconversion -Wno-conversion -Winline \ + -Wno-unused-local-typedefs # CCFLAGS += --param large-function-growth=400 --param inline-unit-growth=200 diff --git a/CosBase/include/cos/cfg/SunOS b/CosBase/include/cos/cfg/SunOS index d19a3e2e..272f6e70 100644 --- a/CosBase/include/cos/cfg/SunOS +++ b/CosBase/include/cos/cfg/SunOS @@ -100,7 +100,8 @@ SYSLIBS := pthread dl CCFLAGS += -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \ -Wchar-subscripts -Wformat-nonliteral -Wwrite-strings \ -Wpointer-arith -Wbad-function-cast -Wcast-align -Wcast-qual \ - -Wfloat-equal -Wconversion -Wno-conversion -Winline + -Wfloat-equal -Wconversion -Wno-conversion -Winline \ + -Wno-unused-local-typedefs # CCFLAGS += --param large-function-growth=400 --param inline-unit-growth=200 diff --git a/CosBase/include/cos/cos/cosapi.h b/CosBase/include/cos/cos/cosapi.h index db0ee275..4016b6e9 100644 --- a/CosBase/include/cos/cos/cosapi.h +++ b/CosBase/include/cos/cos/cosapi.h @@ -41,67 +41,67 @@ struct Class* cos_class_get(U32); struct Class* cos_class_getWithStr(STR); struct Class* cos_property_getWithStr(STR); -BOOL cos_class_isSubclassOf (const struct Class*, const struct Class*); -U32 cos_class_readProperties (const struct Class*,U32,const struct Class**,U32); -U32 cos_class_writeProperties(const struct Class*,U32,const struct Class**,U32); - -IMP1 cos_method_get1(SEL,U32); -IMP2 cos_method_get2(SEL,U32,U32); -IMP3 cos_method_get3(SEL,U32,U32,U32); -IMP4 cos_method_get4(SEL,U32,U32,U32,U32); -IMP5 cos_method_get5(SEL,U32,U32,U32,U32,U32); -IMP1 cos_method_lookup1(SEL,U32); -IMP2 cos_method_lookup2(SEL,U32,U32); -IMP3 cos_method_lookup3(SEL,U32,U32,U32); -IMP4 cos_method_lookup4(SEL,U32,U32,U32,U32); -IMP5 cos_method_lookup5(SEL,U32,U32,U32,U32,U32); +BOOL cos_class_isSubclassOf (const struct Class*, const struct Class*); +U32 cos_class_readProperties (const struct Class*,U32,const struct Class**,U32); +U32 cos_class_writeProperties(const struct Class*,U32,const struct Class**,U32); + +IMP1 cos_method_get1(SEL,U32); +IMP2 cos_method_get2(SEL,U32,U32); +IMP3 cos_method_get3(SEL,U32,U32,U32); +IMP4 cos_method_get4(SEL,U32,U32,U32,U32); +IMP5 cos_method_get5(SEL,U32,U32,U32,U32,U32); +IMP1 cos_method_lookup1(SEL,U32); +IMP2 cos_method_lookup2(SEL,U32,U32); +IMP3 cos_method_lookup3(SEL,U32,U32,U32); +IMP4 cos_method_lookup4(SEL,U32,U32,U32,U32); +IMP5 cos_method_lookup5(SEL,U32,U32,U32,U32,U32); /* inlined functions (see cos/cos/dispatch.h) -IMP1 cos_method_fastLookup1(SEL,U32); -IMP2 cos_method_fastLookup2(SEL,U32,U32); -IMP3 cos_method_fastLookup3(SEL,U32,U32,U32); -IMP4 cos_method_fastLookup4(SEL,U32,U32,U32,U32); -IMP5 cos_method_fastLookup5(SEL,U32,U32,U32,U32,U32); -BOOL cos_method_understand1(SEL,U32); -BOOL cos_method_understand2(SEL,U32,U32); -BOOL cos_method_understand3(SEL,U32,U32,U32); -BOOL cos_method_understand4(SEL,U32,U32,U32,U32); -BOOL cos_method_understand5(SEL,U32,U32,U32,U32,U32); +IMP1 cos_method_fastLookup1(SEL,U32); +IMP2 cos_method_fastLookup2(SEL,U32,U32); +IMP3 cos_method_fastLookup3(SEL,U32,U32,U32); +IMP4 cos_method_fastLookup4(SEL,U32,U32,U32,U32); +IMP5 cos_method_fastLookup5(SEL,U32,U32,U32,U32,U32); +BOOL cos_method_understand1(SEL,U32); +BOOL cos_method_understand2(SEL,U32,U32); +BOOL cos_method_understand3(SEL,U32,U32,U32); +BOOL cos_method_understand4(SEL,U32,U32,U32,U32); +BOOL cos_method_understand5(SEL,U32,U32,U32,U32,U32); */ -char* cos_method_name(const struct Method*,char*,U32); -char* cos_method_call(SEL,OBJ*,char*,U32); -char* cos_method_callName(const struct Method*,OBJ*,char*,U32); -void (*cos_method_trace)(STR,int,BOOL,const struct Method*,OBJ*); -void cos_method_clearCache1(void); -void cos_method_clearCache2(void); -void cos_method_clearCache3(void); -void cos_method_clearCache4(void); -void cos_method_clearCache5(void); -void cos_method_clearCaches(void); - -void cos_contract_invariant1(OBJ,STR,int); -void cos_contract_invariant2(OBJ,OBJ,STR,int); -void cos_contract_invariant3(OBJ,OBJ,OBJ,STR,int); -void cos_contract_invariant4(OBJ,OBJ,OBJ,OBJ,STR,int); -void cos_contract_invariant5(OBJ,OBJ,OBJ,OBJ,OBJ,STR,int); -int cos_contract_setLevel (int lvl); // return previous level - -void cos_exception_assert (STR,STR,int) __attribute__((__noreturn__)); -void cos_exception_errno (int,STR,int) __attribute__((__noreturn__)); -void cos_exception_badcast(OBJ,const struct Class*,STR,int) +char* cos_method_name(const struct Method*,char*,U32); +char* cos_method_call(SEL,OBJ*,char*,U32); +char* cos_method_callName(const struct Method*,OBJ*,char*,U32); +void cos_method_trace(STR,int,BOOL,const struct Method*,OBJ*); +void cos_method_clearCache1(void); +void cos_method_clearCache2(void); +void cos_method_clearCache3(void); +void cos_method_clearCache4(void); +void cos_method_clearCache5(void); +void cos_method_clearCaches(void); + +void cos_contract_invariant1(OBJ,STR,int); +void cos_contract_invariant2(OBJ,OBJ,STR,int); +void cos_contract_invariant3(OBJ,OBJ,OBJ,STR,int); +void cos_contract_invariant4(OBJ,OBJ,OBJ,OBJ,STR,int); +void cos_contract_invariant5(OBJ,OBJ,OBJ,OBJ,OBJ,STR,int); +int cos_contract_setLevel (int lvl); // return previous level + +void cos_exception_assert (STR,STR,int) __attribute__((__noreturn__)); +void cos_exception_errno (int,STR,int) __attribute__((__noreturn__)); +void cos_exception_badcast(OBJ,const struct Class*,STR,int) __attribute__((__noreturn__)); -void cos_exception_throw (OBJ,STR,int) __attribute__((__noreturn__)); -BOOL cos_exception_catch (OBJ,OBJ); -BOOL cos_exception_uncaught(void); -void cos_exception_initContext(struct cos_exception_context*); -void cos_exception_deinitContext(struct cos_exception_context*); +void cos_exception_throw (OBJ,STR,int) __attribute__((__noreturn__)); +BOOL cos_exception_catch (OBJ,OBJ); +BOOL cos_exception_uncaught(void); +void cos_exception_initContext(struct cos_exception_context*); +void cos_exception_deinitContext(struct cos_exception_context*); cos_exception_handler cos_exception_setTerminate(cos_exception_handler); -void cos_functor_overflow(void); -void cos_functor_underflow(void) __attribute__((__noreturn__)); -void cos_functor_clearContext(void); +void cos_functor_overflow(void); +void cos_functor_underflow(void) __attribute__((__noreturn__)); +void cos_functor_clearContext(void); -void cos_module_load(STR*); // null terminated array of module names +void cos_module_load(STR*); // null terminated array of module names /* NOTE-INFO: loggers - prototype: void cos_xxx(STR fmt, ...); diff --git a/CosBase/include/cos/cos/cosmem.h b/CosBase/include/cos/cos/cosmem.h index 85c582f3..1dd21629 100644 --- a/CosBase/include/cos/cos/cosmem.h +++ b/CosBase/include/cos/cos/cosmem.h @@ -35,266 +35,76 @@ Information: - parameters ending with an underscope can be null. - - cos_mem_free does not free the memory, it just returns it to the pool. - - cos_mem_xxx_n are ~50% faster, but objects must have the SAME cos_mem_size. - - cos_mem_alloc_n returns the number of objects effectively allocated. + - cos_free does not free the memory, it just returns it to the pool. - cos_mem_collect does free the unused memory of the thread specific pool. - - cos_mem_collect and cos_mem_unused can be called for a specific cos_mem_size. Errors: - - cos_mem_free_n on objects of different cos_mem_size is undefined. - - cos_mem_free[_n] on objects not allocated by cos_mem_alloc[_n] is undefined. + - cos_free on objects not allocated by cos_malloc is undefined. Compilation: - - set cos_mem_AS_DEFAULT to 1 to activate it for the standard allocator. + - set COS_MEM_STD to 1 to use the standard C allocator instead. */ -// --- interface -------------------------------------------------------------- +#include -// allocator -static void* cos_mem_alloc (size_t size); -static void* cos_mem_calloc (size_t count, size_t size); -static void* cos_mem_realloc (void *ptr_, size_t new_size); -static void cos_mem_free (void *ptr_); -static size_t cos_mem_size (void *ptr_); +// --- interface --------------------------------------------------------------- + +// local buffer (macros) +#define cos_alloc_tmp(type,name,nslot) +#define cos_free_tmp( name) -// allocator, array versions -static int cos_mem_alloc_n (void *ptr_[], int n, size_t size); -static void cos_mem_free_n (void *ptr_[], int n); +// allocator +void* cos_malloc (size_t size); +void* cos_calloc (size_t count, size_t size); +void* cos_realloc (void *ptr_ , size_t size_); +void cos_free (void *ptr_); -// tuning -extern size_t cos_mem_unused (int *count_, size_t *only_); -extern size_t cos_mem_collect (int *percent_, size_t *only_); +// utils +size_t cos_mem_collect (void); +size_t cos_mem_cached (void); +void cos_mem_mdump (FILE*); // --- configuration ----------------------------------------------------------- -// set COS_MEM_AS_DEFAULT to 1 to activate this front-end for the standard allocator. -#ifndef COS_MEM_AS_DEFAULT -#define COS_MEM_AS_DEFAULT 1 +// set COS_MEM_STD to 1 to use the standard C allocator instead. +#ifndef COS_MEM_STD +#define COS_MEM_STD 0 #endif // --- inline implementation --------------------------------------------------- -#include -#include - -// memory node -union cos_mem_node_ { - struct { - union cos_mem_node_ *next; - } free; - - struct { - unsigned slot; - union { - long n, *np; - size_t s, *sp; - double d, *dp; - void (*fp)(void); - } data[1]; - } used; -}; +#undef cos_alloc_tmp +#define cos_alloc_tmp(T,NAME,N) \ + T NAME##_local_tmp__[sizeof(T)*(N) < 8192 ? (N) : 1]; \ + T *NAME = (sizeof(T)*(N) < 8192 ? \ + NAME##_local_tmp__ : cos_malloc(sizeof(T)*(N)) ) -struct cos_mem_slot_ { - union cos_mem_node_ *list; -}; +#undef cos_free_tmp +#define cos_free_tmp(NAME) \ + (NAME != NAME##_local_tmp__ ? cos_free(NAME) : (void)0) -// pool size -enum { - cos_mem_node_size_ = offsetof(union cos_mem_node_, used.data), - cos_mem_slot_size_ = sizeof(struct cos_mem_slot_), - cos_mem_slot_max_ = (1<<16)/cos_mem_slot_size_, // max pool size: ~64kB/thread -}; +// --- global redefinition ----------------------------------------------------- -// memory pool -struct cos_mem_pool_ { - size_t size; - struct cos_mem_slot_ slot[cos_mem_slot_max_]; -}; +#if COS_MEM_STD -// pool (per thread) -extern struct cos_mem_pool_ cos_mem_pool_; -// max unused memory (per thread), default ~32MB -extern size_t cos_mem_pool_max_; +#define cos_malloc( sz ) malloc (sz) +#define cos_calloc( cnt , sz ) calloc (cnt , sz ) +#define cos_realloc(ptr_, sz_) realloc(ptr_, sz_) +#define cos_free( ptr_ ) free (ptr_) -#ifdef _OPENMP -#pragma omp threadprivate (cos_mem_pool_) -#endif - -#if !defined(__GNUC__) && !defined(__attribute__) -#define __attribute__(a) -#endif +#define cos_mem_collect() 0 +#define cos_mem_cached() 0 +#define cos_mem_mdump(f) -#ifdef __cplusplus -# define restrict -# define ATT __attribute__((always_inline)) inline #else -# define ATT __attribute__((always_inline)) static inline -#endif - -// -- utils - -ATT __attribute__((pure)) -union cos_mem_node_* cos_mem_get_base_ (void *ptr) -{ - return (union cos_mem_node_*)((char*)ptr - cos_mem_node_size_); -} - -ATT __attribute__((pure)) -unsigned cos_mem_get_slot_ (size_t size) -{ - return (size + cos_mem_node_size_-1) / cos_mem_node_size_; -} - -ATT __attribute__((pure)) -void* cos_mem_node_init_ (union cos_mem_node_ *ptr, unsigned slot) -{ - ptr->used.slot = slot; - return ptr->used.data; -} - -// -- allocator - -ATT __attribute__((malloc)) -void* cos_mem_alloc (size_t size) -{ - unsigned slot = cos_mem_get_slot_(size); - struct cos_mem_pool_ *restrict pool = &cos_mem_pool_; - struct cos_mem_slot_ *restrict pptr = pool->slot+slot; - union cos_mem_node_ *ptr; - - if (slot < cos_mem_slot_max_ && pptr->list) { - pool->size -= slot*cos_mem_node_size_; - ptr = pptr->list, pptr->list = ptr->free.next; - } - else { - if (pool->size > cos_mem_pool_max_) cos_mem_collect(0,0); - ptr = (union cos_mem_node_*)malloc((slot+1) * cos_mem_node_size_); - if (!ptr) return 0; - } - return cos_mem_node_init_(ptr, slot); -} - -ATT __attribute__((malloc)) -void* cos_mem_calloc (size_t count, size_t size) -{ - size_t sz = count*size; - assert(count < 2 || size < 2 || (sz > count && sz > size)); - - void *ptr = cos_mem_alloc(sz); - if (ptr) memset(ptr, 0, sz); - - return ptr; -} - -ATT __attribute__((malloc)) -void* cos_mem_realloc (void* ptr_, size_t size) -{ - unsigned slot = cos_mem_get_slot_(size); - union cos_mem_node_ *ptr = ptr_ ? cos_mem_get_base_(ptr_) : (union cos_mem_node_*)ptr_; - ptr = (union cos_mem_node_*)realloc(ptr, (slot+1) * cos_mem_node_size_); - if (!ptr) return 0; - - ptr->used.slot = slot; - return ptr->used.data; -} - -ATT -void cos_mem_free (void* ptr_) -{ - if (!ptr_) return; - - union cos_mem_node_ *ptr = cos_mem_get_base_(ptr_); - unsigned slot = ptr->used.slot; - - if (slot < cos_mem_slot_max_) { - struct cos_mem_pool_ *restrict pool = &cos_mem_pool_; - struct cos_mem_slot_ *restrict pptr = pool->slot+slot; - pool->size += slot*cos_mem_node_size_; - ptr->free.next = pptr->list, pptr->list = ptr; - } - else free(ptr); -} - -// -- allocator, array versions - -ATT -int cos_mem_alloc_n (void* ptr_[], int n, size_t size) -{ - unsigned slot = cos_mem_get_slot_(size); - union cos_mem_node_ *ptr; - int i = 0; - - if (slot < cos_mem_slot_max_) { - struct cos_mem_pool_ *restrict pool = &cos_mem_pool_; - struct cos_mem_slot_ *restrict pptr = pool->slot+slot; - - for (; i < n && pptr->list; i++) { - ptr = pptr->list, pptr->list = ptr->free.next; - ptr_[i] = cos_mem_node_init_(ptr, slot); - } - - pool->size -= i*slot*cos_mem_node_size_; - if (i < n && pool->size > cos_mem_pool_max_) cos_mem_collect(0,0); - - for (; i < n; i++) { - ptr = (union cos_mem_node_*)malloc((slot+1) * cos_mem_node_size_); - if (ptr) ptr_[i] = cos_mem_node_init_(ptr, slot); - else break; - } - } else { - for (; i < n; i++) { - ptr = (union cos_mem_node_*)malloc((slot+1) * cos_mem_node_size_); - if (ptr) ptr_[i] = cos_mem_node_init_(ptr, slot); - else break; - } - } - return i; -} - -ATT -void cos_mem_free_n (void* ptr_[], int n) -{ - if (n > 0) { - unsigned slot = cos_mem_get_base_(ptr_[n-1])->used.slot; - - if (slot < cos_mem_slot_max_) { - struct cos_mem_pool_ *restrict pool = &cos_mem_pool_; - struct cos_mem_slot_ *restrict pptr = pool->slot+slot; - int i = n; - - while (n--) { - union cos_mem_node_ *ptr = cos_mem_get_base_(ptr_[n]); - ptr->free.next = pptr->list, pptr->list = ptr; - } - pool->size += i*slot*cos_mem_node_size_; - } - else - while (n--) free(cos_mem_get_base_(ptr_[n])); - } -} - -// -- tuning - -ATT __attribute__((pure)) -size_t cos_mem_size (void* ptr_) -{ - return ptr_ ? cos_mem_get_base_(ptr_)->used.slot * cos_mem_node_size_ : 0; -} - -#undef ATT - -// --- global redefinition ---------------------------------------------------- - -#if COS_MEM_AS_DEFAULT -#define malloc(size) cos_mem_alloc(size) -#define calloc(count,size) cos_mem_calloc(count,size) -#define realloc(ptr,size) cos_mem_realloc(ptr,size) -#define free(ptr) cos_mem_free(ptr) +void* cos_malloc (size_t) __attribute__((hot,malloc(cos_free,1),malloc,returns_nonnull)); +void* cos_calloc (size_t,size_t) __attribute__((hot,malloc(cos_free,1),malloc,returns_nonnull)); +void* cos_realloc(void* ,size_t) __attribute__((hot,malloc(cos_free,1))); +void cos_free (void* ) __attribute__((hot)); #endif -// ---------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- #endif // COS_COS_COSMEM_H diff --git a/CosBase/include/cos/cos/method.h b/CosBase/include/cos/cos/method.h index e201e482..e7a9d174 100644 --- a/CosBase/include/cos/cos/method.h +++ b/CosBase/include/cos/cos/method.h @@ -369,7 +369,7 @@ static void COS_MTH_MNAME(COS_FCT_NAME(NAME,CS),TAG,T) \ /* indirect invocation, normal */ \ _cos_mth_nxt_g(__VA_ARGS__,_cos_mth_nxt_sel,_ret,_cos_mth_nxt_p) : \ /* direct invocation, if GUM */ \ - ((_cos_mth_nxt_d)_cos_mth_nxt_p)(_sel,__VA_ARGS__,_arg,_ret))) + ((_cos_mth_nxt_d)(FCT)_cos_mth_nxt_p)(_sel,__VA_ARGS__,_arg,_ret))) #define COS_MTH_NXT_P \ /* next_method check */ \ diff --git a/CosBase/include/cos/cpp/algos.h b/CosBase/include/cos/cpp/algos.h index c31f7a16..ba55440a 100644 --- a/CosBase/include/cos/cpp/algos.h +++ b/CosBase/include/cos/cpp/algos.h @@ -64,7 +64,7 @@ COS_PP_RES_(COS_PP_EVAL(COS_PP_LEN(T1), \ ((),(COS_PP_ID T1,),(COS_PP_ID T2,),(COS_PP_ID T3,),F),COS_PP_MAP3_0)) -// flatten tuple T to sequence using s as separator, i.e. (a,b,c) -> a b c +// flatten tuple T to sequence using space as separator, i.e. (a,b,c) -> a b c #define COS_PP_SEP(T) \ COS_PP_FOLDL(T,,COS_PP_PAIR) diff --git a/CosBase/include/cos/prologue b/CosBase/include/cos/prologue index 36126cd6..8ad91871 100644 --- a/CosBase/include/cos/prologue +++ b/CosBase/include/cos/prologue @@ -98,7 +98,7 @@ endif # set command echo _ := $(if $(call eq,$(SHOW),yes),,@) -E := $(if $(call eq,$(SHOW),yes),@ \#,@ echo) +E := $(if $(call eq,$(SHOW),yes),@ echo '\#',@ echo) # debug ifneq ($(SHOW),yes) diff --git a/CosBase/src/Any.c b/CosBase/src/Any.c index 5b62c1a2..7d38b1a4 100644 --- a/CosBase/src/Any.c +++ b/CosBase/src/Any.c @@ -42,7 +42,7 @@ endmethod // ----- allocator defmethod(OBJ, galloc, mAny) - struct Any *obj = malloc(self->isz); + struct Any *obj = cos_malloc(self->isz); if (!obj) THROW(ExBadAlloc); // throw the class (no allocation) @@ -60,7 +60,7 @@ defmethod(OBJ, gallocWithSize, mAny, (size_t)extra) if (size - extra != self->isz) THROW(gnewWithStr(ExOverflow, "extra size is too large")); - if (!(obj = malloc(size))) + if (!(obj = cos_malloc(size))) THROW(ExBadAlloc); // throw the class (no allocation) obj->_id = cos_class_id(self); @@ -72,7 +72,7 @@ endmethod // ----- deallocator defmethod(void, gdealloc, Any) - free(_1); + cos_free(_1); endmethod // ----- clone diff --git a/CosBase/src/Exception.c b/CosBase/src/Exception.c index 9c059465..cfe804e3 100644 --- a/CosBase/src/Exception.c +++ b/CosBase/src/Exception.c @@ -62,7 +62,7 @@ str_dup(STR str) { useclass(ExBadAlloc); - char *cpy = malloc(strlen(str)+1); + char *cpy = cos_malloc(strlen(str)+1); if (!cpy) THROW(ExBadAlloc); return strcpy(cpy, str); } @@ -93,7 +93,7 @@ endmethod defmethod(OBJ, gdeinit, Exception) if (self->str) - free(self->str), self->str = 0; + cos_free(self->str), self->str = 0; if (self->obj) grelease(self->obj), self->obj = 0; diff --git a/CosBase/src/cos_memory.c b/CosBase/src/cos_memory.c index 5b1c3230..c33a0c0d 100644 --- a/CosBase/src/cos_memory.c +++ b/CosBase/src/cos_memory.c @@ -17,78 +17,256 @@ * limitations under the License. */ -// --- declarations ----------------------------------------------------------- +// --- declarations ------------------------------------------------------------ #include -// --- definitions ------------------------------------------------------------ +#include +#include +#include +#include +#include -struct cos_mem_pool_ cos_mem_pool_; -size_t cos_mem_pool_max_ = 1<<25; +#define COS_MEM_UTEST 0 // 1 -> run standalone unit tests in main(). +#define DBGMEM(P) // P // uncomment for verbose debugging output +// --- types & constants ------------------------------------------------------- + +// constant sizes enum { - static_assert__node_size_must_be_a_power_of_2 - = 1/!(cos_mem_node_size_&(cos_mem_node_size_-1)) + stp_slot = sizeof(double), // memblk unit of size increment, don't touch + max_slot = 8192, // max 2^16-2, default 8192 slots -> max obj size is 64KB + max_mblk = 2048, // max 2^16-2, default 2048 slots + max_mkch = 2097152, // max 2^32-1, default 2097152 stp_slot -> 16MB +}; + +// memory block +struct memblk { + uint16_t slot; // slot index (i.e. rounded size). + uint16_t next; // index of next memblk (i.e. linked list). + uint32_t mark; // memory boundary marker + union { // alignment of data + ptrdiff_t s, *sp; + size_t u, *up; + double d, *dp; + void *vp; + void (*fp)(void); + } data[1]; }; -size_t __attribute__ ((noinline)) -cos_mem_unused (int *count_, size_t *only_) +// memory pool +struct pool { + uint32_t mkch; // amount of cached memory in stp_slot unit + uint16_t free; // index of first free slot in mblk + uint16_t _dum; // for alignment + uint16_t slot[max_slot]; // index+1 in mblk of first mbp for this size + union { + size_t nxt; // index in mblk of next free slot + struct memblk *mbp; + } mblk[max_mblk]; + char str[128]; // for debug, see pdump() +}; + +// macros +#define BASE(ptr) ((void*)((char*)(ptr)-stp_slot)) // ptr -> mbp +#define SIZE(idx) (((size_t)(idx)+2)*stp_slot) // sizeof(*mbp) +#define CACHED(p) ((size_t)(p)->mkch*stp_slot) +#define IDXMAX 0xFFFF +#define SLTMAX 0xFFFFFFFF +#define MARK 0xACCEDEAD + +// static sanity checks +enum { +//static_assert__max_slot_not_a_power_of_2 = 1/!(max_slot & (max_slot-1)), +//static_assert__max_mblk_not_a_power_of_2 = 1/!(max_mblk & (max_mblk-1)), +//static_assert__max_mkch_not_a_power_of_2 = 1/!(max_mkch & (max_mkch-1)), + static_assert__stp_slot_not_a_power_of_2 = 1/!(stp_slot & (stp_slot-1)), + static_assert__max_slot_not_lt_IDXMAX = 1/ (max_slot < IDXMAX), + static_assert__max_mblk_not_lt_IDXMAX = 1/ (max_mblk < IDXMAX), + static_assert__max_mkch_not_lt_SLTMAX = 1/ (max_mkch < SLTMAX), + static_assert__stp_slot_neq_sizeof = 1/ (stp_slot == sizeof(double)), + static_assert__stp_slot_neq_offsetof = 1/ (stp_slot == offsetof(struct memblk,data)), +}; + +// --- locals ------------------------------------------------------------------ + +typedef int32_t idx_t; + +static struct pool pool = {0,0,0,{0},{{0}},{0}}; + +#ifdef _OPENMP +#pragma omp threadprivate(pool) +#endif + +static inline char* +pdump(struct memblk *mbp) { - if (!count_ && !only_) return cos_mem_pool_.size; + struct pool *p = &pool; + snprintf(p->str, sizeof(p->str), "%p {slot=%4d(%5td), next=%4d, mark=%x}%s", + (void*)mbp, mbp->slot, + mbp->slot == IDXMAX ? -1 : (ptrdiff_t)SIZE(mbp->slot), + mbp->next-1, mbp->mark, mbp->mark == MARK ? "" : " (corrupted!)"); + return p->str; +} + +// --- implementation ---------------------------------------------------------o + +void* +(cos_malloc) (size_t size) +{ + struct pool *p = &pool; + size_t idx = size ? (size-1) / stp_slot : 0; + struct memblk *mbp; // mbp = mblk[slot[idx]-1] - int start = only_ ? cos_mem_get_slot_(*only_) : 0; - int end = only_ ? start+1 : cos_mem_slot_max_; + if (idx < max_slot && p->slot[idx]) { + idx_t slt = p->slot[idx]-1; + DBGMEM( printf("alloc: reuse mblk[[%d]=%d]", (int)idx, slt); ) + mbp = p->mblk[slt].mbp, p->mblk[slt].nxt = p->free; + p->free = p->slot[idx], p->slot[idx] = mbp->next; + p->mkch -= idx+2; + } else { + DBGMEM( printf("alloc: malloc(%2zu)", size); ) + mbp = malloc(SIZE(idx)); + mbp->slot = idx < max_slot ? idx : IDXMAX; + mbp->mark = MARK; + ensure((size_t)mbp > IDXMAX, "unexpected very low address"); // see collect + } - // sanity checks - assert(start < cos_mem_slot_max_); + DBGMEM( printf(" at %s\n", pdump(mbp)); ) + return mbp->data; +} - struct cos_mem_pool_ *restrict pool = &cos_mem_pool_; - struct cos_mem_slot_ *restrict pptr = pool->slot+start; - size_t size = 0; - int count = 0; +void +(cos_free) (void *ptr) +{ + if (!ptr) return; - for (int slot=start; slotslot; - for (union cos_mem_node_ *ptr=pptr->list; ptr; cnt++) - ptr = ptr->free.next; + ensure(mbp->mark == MARK, "invalid or corrupted allocated memory"); - size += slot * cnt * cos_mem_node_size_; - count += cnt; + if (idx == IDXMAX) { + DBGMEM( printf("free : free mblk at %s\n", pdump(mbp)); ) + free(mbp); return; } - if (count_) *count_ = count; - return size; + struct pool *p = &pool; + if (!p->free || p->mkch >= max_mkch) // no free slot (or init) or max cache + cos_mem_collect(); + + idx_t slt = p->free-1; + DBGMEM( printf("free : cache mblk[[%d]=%d]", idx, slt); ) + mbp->next = p->slot[idx], p->slot[idx] = p->free; // update slot + p->free = p->mblk[slt].nxt, p->mblk[slt].mbp = mbp; // store mblk + p->mkch += idx+2; + + DBGMEM( printf(" at %s\n", pdump(mbp)); ) } -size_t __attribute__ ((noinline)) // avoid bug slowing code with openmp -cos_mem_collect (int *percent_, size_t *only_) +void* +(cos_calloc) (size_t ecount, size_t esize) { - int start = only_ ? cos_mem_get_slot_(*only_) : 0; - int end = only_ ? start : cos_mem_slot_max_-1; + size_t size = ecount * esize; + void *ptr = (cos_malloc)(size); + return memset(ptr, 0, size); +} - // sanity checks - assert(start < cos_mem_slot_max_); - assert(!percent_ || (*percent_ >= 0 && *percent_ <= 100)); +void* +(cos_realloc) (void *ptr, size_t size) +{ + if (!size) return (cos_free)(ptr), NULL; + if (!ptr ) return (cos_malloc)(size); - struct cos_mem_pool_ *restrict pool = &cos_mem_pool_; - struct cos_mem_slot_ *restrict pptr = pool->slot+end; - size_t threshold = percent_ && *percent_ < 100 ? pool->size/100.0 * *percent_ : pool->size; - size_t size = 0; + DBGMEM( printf("alloc: realloc(%2zu)", size); ) + struct memblk *mbp = BASE(ptr); - for (int slot=end; slot>=start; slot--, pptr--) { - int cnt = 0; + ensure(mbp->mark == MARK, "invalid or corrupted allocated memory"); - for (union cos_mem_node_ *nxt, *ptr=pptr->list; ptr; ptr=nxt, cnt++) { - nxt = ptr->free.next; - free(ptr); - } + size_t idx = (size-1) / stp_slot; + mbp = realloc(mbp, SIZE(idx)); + mbp->slot = idx < max_slot ? idx : IDXMAX; - pptr->list = 0; - size += slot * cnt * cos_mem_node_size_; - if (size >= threshold) break; + DBGMEM( printf(" at %s\n", pdump(mbp)); ) + return mbp->data; +} + +// -- utils + +size_t +cos_mem_cached (void) +{ + struct pool *p = &pool; + size_t ccached = 0, cached = CACHED(p); + + for (idx_t i=0; i < max_mblk; i++) + if (p->mblk[i].nxt > IDXMAX) // ptr + ccached += SIZE(p->mblk[i].mbp->slot); + + ensure(ccached == cached, "corrupted cache, ccached == cached bytes"); + + return cached; +} + +size_t +cos_mem_collect (void) +{ + struct pool *p = &pool; + size_t cached = CACHED(p); + + DBGMEM(printf("collect/clear/init cache\n");) + DBGMEM(printf("collecting %zu bytes\n", cos_mem_cached()); cos_mem_mdump();) + + p->mkch = 0; + p->free = 1; + + for (idx_t i=0; i < max_slot; i++) + p->slot[i] = 0; + + for (idx_t i=0; i < max_mblk; i++) { + if (p->mblk[i].nxt > IDXMAX) // ptr + free(p->mblk[i].mbp); + p->mblk[i].nxt = i+2; + } + p->mblk[max_mblk-1].nxt = 0; // close linked list + + DBGMEM( printf("status after collect\n"); cos_mem_mdump(); ) + return cached; +} + +// -- debug + +void +cos_mem_mdump (FILE *fp) +{ + struct pool *p = &pool; + + if (!fp) fp = stdout; + + fprintf(fp, "mdump: %zu bytes\n", CACHED(p)); + + // display content of slot[] when used, i.e. link to mblk[] + linked list. + for (idx_t i=0; i < max_slot; i++) { + idx_t slt = p->slot[i]; + if (slt) { // from slot (size) to memblk (object) + fprintf(fp, " slot[%4d] -> mblk[%d]", i, slt-1); + struct memblk *mbp = p->mblk[slt-1].mbp; + while (mbp->next) { // linked list + fprintf(fp, "->[%d]", mbp->next-1); + mbp = p->mblk[mbp->next-1].mbp; + } + fprintf(fp, "\n"); + } } - pool->size -= size; - return size; + // display content of mblk[], i.e. object or not trivial link into mblk[] + for (idx_t i=0; i < max_mblk; i++) + if (p->mblk[i].nxt > IDXMAX) // ptr + fprintf(fp, " mblk[%4d] -> %s\n", i, pdump(p->mblk[i].mbp)); + else if (i+1 == p->free) // free + fprintf(fp, "->mblk[%4d] -> [%d]\n", i, (int)p->mblk[i].nxt-1); + else if (i+2 != (int)p->mblk[i].nxt) // idx + fprintf(fp, " mblk[%4d] -> [%d]\n", i, (int)p->mblk[i].nxt-1); } + +// --- end --------------------------------------------------------------------- diff --git a/CosBase/src/cos_symbol.c b/CosBase/src/cos_symbol.c index 2a552eaf..9f749989 100644 --- a/CosBase/src/cos_symbol.c +++ b/CosBase/src/cos_symbol.c @@ -670,6 +670,7 @@ sym_init(void) case cos_tag_pclass : ++n_pcl; pcl_stinit((void*)tbl_sym[t][s]); break; case cos_tag_generic: ++n_gen; gen_stinit((void*)tbl_sym[t][s]); break; case cos_tag_alias : als_stinit((void*)tbl_sym[t][s]); + /* intentional fall through */ case cos_tag_method : ++n_mth; break; case cos_tag_docstr : ++n_doc; break; default: cos_abort("invalid COS symbol"); @@ -702,12 +703,15 @@ sym_init(void) if (sym.bhv[i]) { switch (bhv->Object.Any._rc) { case cos_tag_class : + /* intentional fall through */ case cos_tag_pclass: + /* intentional fall through */ case cos_tag_mclass: { struct Class *cls = CAST(struct Class*, bhv); cos_abort("class '%s' at (%s,%d) slot %u already assigned", cls_name(cls), cls_file(cls), cls_line(cls), i); } + /* intentional fall through */ case cos_tag_generic: { struct Generic *gen = CAST(struct Generic*, bhv); cos_abort("generic '%s' at (%s,%d) slot %u already assigned", @@ -903,6 +907,7 @@ cos_deinit(void) t1 = clock(); deinit_duration = (t1-t0)/CLOCKS_PER_SEC; + cos_functor_clearContext(); cos_method_clearCaches(); } } @@ -1531,8 +1536,8 @@ cos_method_callName(const struct Method *mth, OBJ obj[], char *str, U32 sz) return str; } -static void -mth_trace(STR file, int line, BOOL enter, const struct Method *mth, OBJ *obj) +void +cos_method_trace(STR file, int line, BOOL enter, const struct Method *mth, OBJ *obj) { char buf[256]; @@ -1542,8 +1547,6 @@ mth_trace(STR file, int line, BOOL enter, const struct Method *mth, OBJ *obj) cos_logmsg(COS_LOGMSG_TRALL,file,line,"<- %s",cos_method_name (mth, buf,sizeof buf)); } -void (*cos_method_trace)(STR,int,BOOL,const struct Method*,OBJ*) = mth_trace; - void cos_symbol_showSummary(FILE *fp) { diff --git a/CosBase/tests/src/st_methods.c b/CosBase/tests/src/st_methods.c index c5aa5f61..1735e727 100644 --- a/CosBase/tests/src/st_methods.c +++ b/CosBase/tests/src/st_methods.c @@ -166,16 +166,16 @@ st_memory(void) // allocator warm up for (i = 0; i < P; i++) - arr[i++] = malloc(sz); + arr[i++] = cos_malloc(sz); for (i = 0; i < P; i++) - free(arr[i++]); + cos_free(arr[i++]); i = 0; - STEST( "malloc", P, arr[i++] = malloc(sz) ); + STEST( "malloc", P, arr[i++] = cos_malloc(sz) ); i = 0; - STEST( "free", P, free(arr[i++]) ); + STEST( "free", P, cos_free(arr[i++]) ); i = 0; STEST( "alloc + init", P, arr[i++] = ginit(galloc(Counter)) ); diff --git a/CosBase/tools/src/coscmt.c b/CosBase/tools/src/coscmt.c index ce204536..0dcd767b 100644 --- a/CosBase/tools/src/coscmt.c +++ b/CosBase/tools/src/coscmt.c @@ -95,6 +95,7 @@ remove_cmt(FILE *in , FILE *out) if (c == '/') { skip_line(in); break; } if (c == '*') { skip_cmt (in); break; } fputc('/', out); + /* intentional fall through */ default : fputc(c , out); } } diff --git a/CosStd/examples/ex01/Makefile b/CosStd/examples/ex01/Makefile index 6bc16e72..d8d53135 100644 --- a/CosStd/examples/ex01/Makefile +++ b/CosStd/examples/ex01/Makefile @@ -1,15 +1,15 @@ # # C Object System # COS example -# +# # Copyright 2007+ Laurent Deniau -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,15 +32,15 @@ targets := release.run # debug.run # files & modules sources := *.c -defgens := +defgens := defprps := # project dependencies (as with -lname) -moddeps := CosStd CosBase +moddeps := CosBase CosStd # project dependencies (as with -Ipath or -Lpath) -incdirs := ../../../CosBase/include ../../include . -libdirs := ../../../CosBase/$(OSNAME)/lib ../../$(OSNAME)/lib +incdirs := $(foreach m,$(moddeps),../../../$(m)/include) . +libdirs := $(foreach m,$(moddeps),../../../$(m)/$(OSNAME)/lib) include $(cos)/epilogue diff --git a/CosStd/examples/ex01/main.c b/CosStd/examples/ex01/main.c index a44a732e..e11a0216 100644 --- a/CosStd/examples/ex01/main.c +++ b/CosStd/examples/ex01/main.c @@ -59,11 +59,11 @@ sum_rep(I32 n) grelease(pool); F64 t3 = clock(); - printf("count [n] = %d [%d]\n" , x, n); - printf("time init = %.2f sec\n", (t1-t0)/CLOCKS_PER_SEC); - printf("time eval = %.2f sec\n", (t2-t1)/CLOCKS_PER_SEC); - printf("time fini = %.2f sec\n", (t3-t2)/CLOCKS_PER_SEC); - printf("time all = %.2f sec\n", (t3-t0)/CLOCKS_PER_SEC); + printf("count [n] = %d [%d]\n" , x, n); + printf("time init = %.2f sec\n", (t1-t0)/CLOCKS_PER_SEC); + printf("time eval = %.2f sec\n", (t2-t1)/CLOCKS_PER_SEC); + printf("time fini = %.2f sec\n", (t3-t2)/CLOCKS_PER_SEC); + printf("time all = %.2f sec\n", (t3-t0)/CLOCKS_PER_SEC); } static void @@ -81,17 +81,17 @@ sum_itr(I32 n) grelease(pool); F64 t3 = clock(); - printf("count [n] = %d [%d]\n" , x, n); - printf("time init = %.2f sec\n", (t1-t0)/CLOCKS_PER_SEC); - printf("time eval = %.2f sec\n", (t2-t1)/CLOCKS_PER_SEC); - printf("time fini = %.2f sec\n", (t3-t2)/CLOCKS_PER_SEC); - printf("time all = %.2f sec\n", (t3-t0)/CLOCKS_PER_SEC); + printf("count [n] = %d [%d]\n" , x, n); + printf("time init = %.2f sec\n", (t1-t0)/CLOCKS_PER_SEC); + printf("time eval = %.2f sec\n", (t2-t1)/CLOCKS_PER_SEC); + printf("time fini = %.2f sec\n", (t3-t2)/CLOCKS_PER_SEC); + printf("time all = %.2f sec\n", (t3-t0)/CLOCKS_PER_SEC); } static void sum_oop(I32 n) { - printf("*** object-oriented sum (repeat + foldl)\n"); + printf("*** object-oriented sum (repeat + foldl)\n"); OBJ pool = gnew(AutoRelease); OBJ ini = gautoRelease(aInt(1)); @@ -103,11 +103,11 @@ sum_oop(I32 n) grelease(pool); F64 t3 = clock(); - printf("count [n] = %d [%d]\n" , x, n); - printf("time init = %.2f sec\n", (t1-t0)/CLOCKS_PER_SEC); - printf("time eval = %.2f sec\n", (t2-t1)/CLOCKS_PER_SEC); - printf("time fini = %.2f sec\n", (t3-t2)/CLOCKS_PER_SEC); - printf("time all = %.2f sec\n", (t3-t0)/CLOCKS_PER_SEC); + printf("count [n] = %d [%d]\n" , x, n); + printf("time init = %.2f sec\n", (t1-t0)/CLOCKS_PER_SEC); + printf("time eval = %.2f sec\n", (t2-t1)/CLOCKS_PER_SEC); + printf("time fini = %.2f sec\n", (t3-t2)/CLOCKS_PER_SEC); + printf("time all = %.2f sec\n", (t3-t0)/CLOCKS_PER_SEC); } int main(int argc, char *argv[]) diff --git a/CosStd/include/cos/Range.h b/CosStd/include/cos/Range.h index 80444c0f..4e42ced4 100644 --- a/CosStd/include/cos/Range.h +++ b/CosStd/include/cos/Range.h @@ -88,7 +88,8 @@ endclass */ static cos_inline U32 Range_index(I32 index, U32 seq_size) { - return index + (index < 0) * seq_size; + // OK because signed=>unsigned cast and unsigned overflow are well defined: + return (U32)index + (index < 0) * seq_size; } /*********************************************************** diff --git a/CosStd/include/cos/Slice.h b/CosStd/include/cos/Slice.h index 7874d4cd..d0d6a140 100644 --- a/CosStd/include/cos/Slice.h +++ b/CosStd/include/cos/Slice.h @@ -184,10 +184,11 @@ Slice_addTo(struct Slice *s1, const struct Slice *s2) { static cos_inline struct Slice* Slice_fromRange(struct Slice *s, const struct Range *r, const U32 *size) { - if (size) // ask for normalization - r = Range_normalize(Range_copy(atRange(0), r), *size); + struct Range *r2 = Range_copy(atRange(0), r); - return Slice_init(s, Range_start(r), Range_size(r), Range_stride(r)); + if (size) r2 = Range_normalize(r2, *size); // ask for normalization + + return Slice_init(s, Range_start(r2), Range_size(r2), Range_stride(r2)); } #endif // COS_SLICE_H diff --git a/CosStd/include/cos/carray.h b/CosStd/include/cos/carray.h deleted file mode 100644 index 18c60135..00000000 --- a/CosStd/include/cos/carray.h +++ /dev/null @@ -1,71 +0,0 @@ -// multiple inclusion allowed - -/** - * C Object System - * COS C Array, C array utils - * - * Copyright 2006+ Laurent Deniau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef COS_CARRAY_H -#define COS_CARRAY_H - -#include - -#include - -/* NOTE-INFO: low level C array - the array is allocated on the stack if its size <= CARRAY_LIMIT - otherwise it is allocated on the heap. - - { - CARRAY_CREATE(OBJ, buf, 1000); - - buf[100] = gnew(Object); - grelease(buf[100]); - - CARRAY_DESTROY(buf); - } -*/ - -#define CARRAY_CREATE(T,name,nelem) \ - CARRAY_CREATE_(T,name,nelem, \ - /* local pointer */ COS_PP_CAT(_cos_tmp_carray_p_,name), \ - /* local array */ COS_PP_CAT(_cos_tmp_carray_a_,name), \ - /* local size */ COS_PP_CAT(_cos_tmp_carray_s_,name)) - -#define CARRAY_CREATE_(T,name,N,P,A,S) \ - U32 S = N; T *P, \ - A[S*sizeof(T) <= CARRAY_LIMIT ? S : 0]; \ - if (S*sizeof(T) <= CARRAY_LIMIT) P = A; \ - else { \ - useclass(ExBadAlloc); \ - if ( !(P = malloc(S * sizeof(T))) ) THROW(ExBadAlloc); \ - } \ - T *const name = P - -#define CARRAY_DESTROY(name) \ - if (name != COS_PP_CAT(_cos_tmp_carray_a_,name)) \ - free(name) - -#endif // COS_CARRAY_H - -// can be redefined between inclusion -#ifndef CARRAY_LIMIT -#define CARRAY_LIMIT (1024 * sizeof(void*)) -#endif - -// multiple inclusion allowed - diff --git a/CosStd/include/cos/gen/floatop.h b/CosStd/include/cos/gen/floatop.h index d420847b..ead99e07 100644 --- a/CosStd/include/cos/gen/floatop.h +++ b/CosStd/include/cos/gen/floatop.h @@ -24,7 +24,7 @@ /* NOTE-USER: operators policy The policy of these messages is to return the operation result in a - new autoDelete object resulting from the promotion/coercion of _1 + new autoRelease object resulting from the promotion/coercion of _1 and _2 which follows the rules of C99 for primitive types. */ defgeneric(OBJ, (G_conj ) gconj , _1); // return _1^* diff --git a/CosStd/include/cos/gen/numop.h b/CosStd/include/cos/gen/numop.h index 1a685ab7..f2dedf00 100644 --- a/CosStd/include/cos/gen/numop.h +++ b/CosStd/include/cos/gen/numop.h @@ -24,7 +24,7 @@ /* NOTE-USER: operators policy The policy of these messages is to return the operation result in a - new autoDelete object resulting from the promotion/coercion of _1 + new autorelease object resulting from the promotion/coercion of _1 and _2 which follows the rules of C99 for primitive types. */ defgeneric(OBJ, (G_abs) gabs, _1); // return |_1| diff --git a/CosStd/src/Array.c b/CosStd/src/Array.c index a02b34bf..b95e0030 100644 --- a/CosStd/src/Array.c +++ b/CosStd/src/Array.c @@ -283,7 +283,7 @@ defmethod(OBJ, ginitWith2 , pmArray, Array, IntVector) // random seque while (dst != end) { U32 i = Range_index(*idx, val_n); ensure( i < val_n, "index out of range" ); - *dst++ = gretain(val[i*val_s]), ++*dst_n; + *dst++ = gretain(val[(ptrdiff_t)i*val_s]), ++*dst_n; idx += idx_s; } @@ -339,7 +339,7 @@ defmethod(void, ginvariant, Array, (STR)file, (int)line) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end && *val) val += val_s; diff --git a/CosStd/src/Array_acc.c b/CosStd/src/Array_acc.c index 1f989e0d..6cc5298d 100644 --- a/CosStd/src/Array_acc.c +++ b/CosStd/src/Array_acc.c @@ -49,10 +49,10 @@ endmethod defmethod(OBJ, ggetAtIdx, Array, (I32)idx) U32 i = Range_index(idx, self->size); - + ensure( i < self->size, "index out of range" ); - retmethod( self->object[i*self->stride] ); + retmethod( self->object[(ptrdiff_t)i*self->stride] ); endmethod defmethod(OBJ, ggetAt, Array, Int) @@ -60,7 +60,7 @@ defmethod(OBJ, ggetAt, Array, Int) ensure( i < self->size, "index out of range" ); - retmethod( self->object[i*self->stride] ); + retmethod( self->object[(ptrdiff_t)i*self->stride] ); endmethod defmethod(OBJ, ggetAt, Array, Slice) @@ -87,7 +87,7 @@ defmethod(OBJ, gputAtIdx, Array, (I32)idx, Object) ensure( i < self->size, "index out of range" ); - OBJ *dst = self->object + i*self->stride; + OBJ *dst = self->object + (ptrdiff_t)i*self->stride; assign(dst, _2); retmethod(_1); @@ -98,7 +98,7 @@ defmethod(OBJ, gputAt, Array, Int, Object) ensure( i < self->size, "index out of range" ); - OBJ *dst = self->object + i*self->stride; + OBJ *dst = self->object + (ptrdiff_t)i*self->stride; assign(dst, _3); retmethod(_1); @@ -112,7 +112,7 @@ BODY U32 dst_n = Slice_size (self2); I32 dst_s = Slice_stride(self2)*self->stride; OBJ *dst = Slice_start (self2)*self->stride + self->object; - OBJ *end = dst + dst_s*dst_n; + OBJ *end = dst + dst_s*(ptrdiff_t)dst_n; while (dst != end) { assign(dst, _3); @@ -136,12 +136,12 @@ defmethod(OBJ, gputAt, Array, IntVector, Object) U32 idx_n = self2->size; I32 idx_s = self2->stride; I32 *idx = self2->value; - I32 *end = idx + idx_s*idx_n; + I32 *end = idx + idx_s*(ptrdiff_t)idx_n; while (idx != end) { U32 i = Range_index(*idx, dst_n); ensure( i < dst_n, "index out of range" ); - assign(dst + i*dst_s, _3); + assign(dst + (ptrdiff_t)i*dst_s, _3); idx += idx_s; } @@ -168,7 +168,7 @@ BODY OBJ *dst = Slice_start (self2)*self->stride + self->object; I32 src_s = self3->stride; OBJ *src = self3->object; - OBJ *end = dst + dst_s*dst_n; + OBJ *end = dst + dst_s*(ptrdiff_t)dst_n; while (dst != end) { assign(dst, *src); @@ -199,12 +199,12 @@ BODY I32 *idx = self2->value; I32 src_s = self3->stride; OBJ *src = self3->object; - I32 *end = idx + idx_s*idx_n; + I32 *end = idx + idx_s*(ptrdiff_t)idx_n; while (idx != end) { U32 i = Range_index(*idx, dst_n); ensure( i < dst_n, "index out of range" ); - assign(dst + i*dst_s, *src); + assign(dst + (ptrdiff_t)i*dst_s, *src); src += src_s; idx += idx_s; } diff --git a/CosStd/src/Array_alg.c b/CosStd/src/Array_alg.c index 8b6be70a..e47bb4b7 100644 --- a/CosStd/src/Array_alg.c +++ b/CosStd/src/Array_alg.c @@ -32,8 +32,6 @@ #include #include -#include - #include "Array_utl.h" #include @@ -54,7 +52,7 @@ defmethod(OBJ, gisEqual, Array, Array) OBJ *val = self->object; I32 val2_s = self2->stride; OBJ *val2 = self2->object; - OBJ *end = val + val_s*val_n; + OBJ *end = val + val_s*(ptrdiff_t)val_n; while (val != end) { if (gisEqual(*val,*val2) != True) @@ -80,7 +78,7 @@ defmethod(OBJ, gcompare, Array, Array) OBJ *val = self->object; I32 val2_s = self2->stride; OBJ *val2 = self2->object; - OBJ *end = val + val_s*val_n; + OBJ *end = val + val_s*(ptrdiff_t)val_n; OBJ res; while (val != end) { @@ -111,7 +109,7 @@ defmethod(OBJ, greverse, Array) U32 val_n = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*(val_n-1); + OBJ *end = val + val_s*(ptrdiff_t)(val_n-1); if (val_s > 0) while (val < end) { @@ -143,8 +141,8 @@ defmethod(OBJ, gpermute, Array, IntVector) I32 idx_s = self2->stride; I32 *idx = self2->value; - CARRAY_CREATE(OBJ,buf,size); // OBJ buf[size]; - CARRAY_CREATE(U8 ,flg,size); // U8 flg[size]; + cos_alloc_tmp(OBJ,buf,size); // OBJ buf[size]; + cos_alloc_tmp(U8 ,flg,size); // U8 flg[size]; memset(flg,1,size); @@ -155,7 +153,7 @@ defmethod(OBJ, gpermute, Array, IntVector) for (cur = buf; cur != end; cur++) { i = Range_index(*idx, size); if ( !(i < size && flg[i]) ) break; - *cur = val[i*val_s], flg[i] = 0; + *cur = val[(ptrdiff_t)i*val_s], flg[i] = 0; idx += idx_s; } @@ -164,8 +162,8 @@ defmethod(OBJ, gpermute, Array, IntVector) for (cur = buf; cur != end; cur++) *val = *cur, val += val_s; - CARRAY_DESTROY(buf); - CARRAY_DESTROY(flg); + cos_free_tmp(buf); + cos_free_tmp(flg); } else { // rollback (error) BOOL iiir = i < size; // last index-is-in-range flag @@ -173,11 +171,11 @@ defmethod(OBJ, gpermute, Array, IntVector) while (cur != buf) { idx -= idx_s; i = Range_index(*idx, size); - val[i*val_s] = *--cur; + val[(ptrdiff_t)i*val_s] = *--cur; } - CARRAY_DESTROY(buf); - CARRAY_DESTROY(flg); + cos_free_tmp(buf); + cos_free_tmp(flg); ensure( iiir, "index out of range" ); ensure( 0, "invalid cyclic permutation" ); } @@ -450,7 +448,7 @@ findVal(OBJ *val, U32 val_n, I32 val_s, OBJ _2) { if (!val_n) return 0; - OBJ *end = val + val_s*val_n; + OBJ *end = val + val_s*(ptrdiff_t)val_n; while (val != end) { if (gisEqual(_2, *val) == True) @@ -488,7 +486,7 @@ endmethod static OBJ* KnuthMorrisPratt(OBJ *val, U32 val_n, I32 val_s, OBJ *pat, I32 pat_n, I32 pat_s) { - CARRAY_CREATE(I32,kmpNext,pat_n); + cos_alloc_tmp(I32,kmpNext,pat_n); { // preprocessing I32 i = 0, j = kmpNext[0] = -1; @@ -515,13 +513,13 @@ KnuthMorrisPratt(OBJ *val, U32 val_n, I32 val_s, OBJ *pat, I32 pat_n, I32 pat_s) i++; j++; if (i >= pat_n) { // found - CARRAY_DESTROY(kmpNext); + cos_free_tmp(kmpNext); return val + (j - i)*val_s; } } } - CARRAY_DESTROY(kmpNext); + cos_free_tmp(kmpNext); return 0; // not found } diff --git a/CosStd/src/Array_dyn.c b/CosStd/src/Array_dyn.c index 92d34768..74054b39 100644 --- a/CosStd/src/Array_dyn.c +++ b/CosStd/src/Array_dyn.c @@ -26,8 +26,6 @@ #include #include -#include - #include "Array_utl.h" #include @@ -53,7 +51,7 @@ defmethod(OBJ, gdeinit, ArrayFix) next_method(self); if (self->_object) { // take care of protection cases - free(self->_object); + cos_free(self->_object); self->Array.object = 0; self->_object = 0; } @@ -95,7 +93,7 @@ defmethod(OBJ, ginitWith, ArrayDyn, Int) THROW(gnewWithStr(ExOverflow, "capacity is too large")); } - arrf->_object = malloc(size); + arrf->_object = cos_malloc(size); if (!arrf->_object && size) THROW(ExBadAlloc); @@ -146,7 +144,7 @@ defmethod(OBJ, genlarge, ArrayDyn, Int) // negative size means enlarge front if (size/sizeof *arrf->_object < capacity) THROW(gnewWithStr(ExOverflow, "extra size is too large")); - OBJ *_object = realloc(arrf->_object, size); + OBJ *_object = cos_realloc(arrf->_object, size); if (!_object && size) THROW(ExBadAlloc); @@ -175,7 +173,7 @@ defmethod(OBJ, gadjust, ArrayDyn) // shrink storage if (arr->size != self->capacity) { - OBJ *_object = realloc(arrf->_object, size); + OBJ *_object = cos_realloc(arrf->_object, size); if (!_object && size) THROW(ExBadAlloc); diff --git a/CosStd/src/Array_fun.c b/CosStd/src/Array_fun.c index ae6d6057..d74cdabc 100644 --- a/CosStd/src/Array_fun.c +++ b/CosStd/src/Array_fun.c @@ -40,7 +40,7 @@ defmethod(void, gforeachWhile, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end && geval(_2, *val) != Nil) val += val_s; @@ -50,7 +50,7 @@ defmethod(void, gforeach, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end) { geval(_2, *val); @@ -64,7 +64,7 @@ defmethod(void, gforeach2, Array, Array, Functor) OBJ *val = self->object; I32 val2_s = self2->stride; OBJ *val2 = self2->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end) { geval(_3, *val, *val2); @@ -82,7 +82,7 @@ defmethod(void, gforeach3, Array, Array, Array, Functor) OBJ *val2 = self2->object; I32 val3_s = self3->stride; OBJ *val3 = self3->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end) { geval(_4, *val, *val2, *val3); @@ -104,7 +104,7 @@ defmethod(void, gforeach4, Array, Array, Array, Array, Functor) OBJ *val3 = self3->object; I32 val4_s = self4->stride; OBJ *val4 = self4->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end) { geval(_5, *val, *val2, *val3, *val4); @@ -121,7 +121,7 @@ defmethod(OBJ, gapplyWhile, Functor, Array) U32 size = self2->size; I32 val_s = self2->stride; OBJ *val = self2->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res, old; while (val != end) { @@ -139,7 +139,7 @@ defmethod(OBJ, gapplyIf, Functor, Array) U32 size = self2->size; I32 val_s = self2->stride; OBJ *val = self2->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res, old; while (val != end) { @@ -156,7 +156,7 @@ defmethod(OBJ, gapply, Functor, Array) U32 size = self2->size; I32 val_s = self2->stride; OBJ *val = self2->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res, old; while (val != end) { @@ -175,7 +175,7 @@ defmethod(OBJ, gapply2, Functor, Array, Array) OBJ *val = self2->object; I32 val2_s = self3->stride; OBJ *val2 = self3->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res, old; while (val != end) { @@ -198,7 +198,7 @@ defmethod(OBJ, gapply3, Functor, Array, Array, Array) OBJ *val2 = self3->object; I32 val3_s = self4->stride; OBJ *val3 = self4->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res, old; while (val != end) { @@ -225,7 +225,7 @@ defmethod(OBJ, gapply4, Functor, Array, Array, Array, Array) OBJ *val3 = self4->object; I32 val4_s = self5->stride; OBJ *val4 = self5->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res, old; while (val != end) { @@ -247,7 +247,7 @@ defmethod(OBJ, gmapWhile, Functor, Array) U32 size = self2->size; I32 val_s = self2->stride; OBJ *val = self2->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res; OBJ _arr = gautoRelease(gnewWith(Array,aInt(size))); @@ -270,7 +270,7 @@ defmethod(OBJ, gmapIf, Functor, Array) U32 size = self2->size; I32 val_s = self2->stride; OBJ *val = self2->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res; OBJ _arr = gautoRelease(gnewWith(Array,aInt(size))); @@ -293,7 +293,7 @@ defmethod(OBJ, gmap, Functor, Array) U32 size = self2->size; I32 val_s = self2->stride; OBJ *val = self2->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res; struct Array* arr = Array_alloc(size); @@ -317,7 +317,7 @@ defmethod(OBJ, gmap2, Functor, Array, Array) OBJ *val = self2->object; I32 val2_s = self3->stride; OBJ *val2 = self3->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res; struct Array* arr = Array_alloc(size); @@ -345,7 +345,7 @@ defmethod(OBJ, gmap3, Functor, Array, Array, Array) OBJ *val2 = self3->object; I32 val3_s = self4->stride; OBJ *val3 = self4->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res; struct Array* arr = Array_alloc(size); @@ -377,7 +377,7 @@ defmethod(OBJ, gmap4, Functor, Array, Array, Array, Array) OBJ *val3 = self4->object; I32 val4_s = self5->stride; OBJ *val4 = self5->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res; struct Array* arr = Array_alloc(size); @@ -404,7 +404,7 @@ defmethod(OBJ, gselect, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ _arr = gautoRelease(gnewWith(Array,aInt(size))); struct Array* arr = dbgcast(Array, _arr); @@ -425,7 +425,7 @@ defmethod(OBJ, greject, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ _arr = gautoRelease(gnewWith(Array,aInt(size))); struct Array* arr = dbgcast(Array, _arr); @@ -446,7 +446,7 @@ defmethod(OBJ, gselectWhile, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ _arr = gautoRelease(gnewWith(Array,aInt(size))); struct Array* arr = dbgcast(Array, _arr); @@ -468,7 +468,7 @@ defmethod(OBJ, grejectWhile, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ _arr = gautoRelease(gnewWith(Array,aInt(size))); struct Array* arr = dbgcast(Array, _arr); @@ -505,7 +505,7 @@ defmethod(OBJ, greduce, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = gautoRelease(gclone(*val)); val += val_s; @@ -522,7 +522,7 @@ defmethod(OBJ, greduce1, Array, Functor, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; while (val != end) { @@ -546,7 +546,7 @@ defmethod(OBJ, greduce2, Array, Functor, Object, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; if (size) { @@ -578,7 +578,7 @@ defmethod(OBJ, grreduce, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = gautoRelease(gclone(*(end-val_s))); end -= val_s; @@ -595,7 +595,7 @@ defmethod(OBJ, grreduce1, Array, Functor, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; while (val != end) { @@ -621,7 +621,7 @@ defmethod(OBJ, grreduce2, Array, Functor, Object, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; if (size) { @@ -662,7 +662,7 @@ defmethod(OBJ, gaccumulate1, Array, Functor, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; struct Array* arr = Array_alloc(size); @@ -693,7 +693,7 @@ defmethod(OBJ, gaccumulate2, Array, Functor, Object, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; struct Array* arr = Array_alloc(size); @@ -740,7 +740,7 @@ defmethod(OBJ, graccumulate1, Array, Functor, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; struct Array* arr = Array_alloc(size); @@ -772,7 +772,7 @@ defmethod(OBJ, graccumulate2, Array, Functor, Object, Object) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res = _3; struct Array* arr = Array_alloc(size); @@ -804,7 +804,7 @@ defmethod(OBJ, gall, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end) { if (geval(_2, *val) != True) @@ -819,7 +819,7 @@ defmethod(OBJ, gany, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; while (val != end) { if (geval(_2, *val) == True) @@ -834,7 +834,7 @@ defmethod(U32, gcount, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; U32 cnt = 0; while (val != end) { @@ -857,7 +857,7 @@ defmethod(OBJ, gunique, Array, Functor) OBJ *val = self->object; U32 *dst_n = &arr->size; OBJ *dst = arr->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; if (val != end) { *dst = gretain(*val), ++*dst_n; @@ -881,7 +881,7 @@ defmethod(OBJ, gsplit, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ *beg = val; while (val != end) { @@ -917,7 +917,7 @@ defmethod(OBJ, ggroup, Array, Functor) U32 size = self->size; I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ res; while (val != end) { @@ -980,7 +980,7 @@ defmethod(OBJ, gdiff, Array, Collection, Functor) OBJ *val = self->object; U32 *dst_n = &arr->size; OBJ *dst = arr->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ fun = aFun(gfind, _2, aFun(geval2, _3, __2, __1)); while (val != end) { @@ -1003,7 +1003,7 @@ defmethod(OBJ, gmatch, Array, Collection, Functor) OBJ *val = self->object; U32 *dst_n = &arr->size; OBJ *dst = arr->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ fun = aLzy(_3); OBJ res; @@ -1029,7 +1029,7 @@ defmethod(OBJ, gintersect, Array, Collection, Functor) OBJ *val = self->object; U32 *dst_n = &arr->size; OBJ *dst = arr->object; - OBJ *end = val + val_s*size; + OBJ *end = val + val_s*(ptrdiff_t)size; OBJ fun = aFun(gfind, _2, aFun(geval2, _3, __2, __1)); while (val != end) { @@ -1055,7 +1055,7 @@ findFun(OBJ *val, U32 val_n, I32 val_s, OBJ _2) // linear search if (res == False) { - OBJ *end = val + val_s*val_n; + OBJ *end = val + val_s*(ptrdiff_t)val_n; val += val_s; while (val != end) { @@ -1073,10 +1073,10 @@ findFun(OBJ *val, U32 val_n, I32 val_s, OBJ _2) while (lo <= hi) { U32 i = (lo + hi) / 2; - res = geval(_2, val[i*val_s]); + res = geval(_2, val[(ptrdiff_t)i*val_s]); if (res == Equal) - return val + i*val_s; // found + return val + (ptrdiff_t)i*val_s; // found if (res == Lesser) hi = i-1; @@ -1389,7 +1389,7 @@ defmethod(OBJ, gisSorted, Array, Functor) I32 val_s = self->stride; OBJ *val = self->object; - OBJ *end = val + val_s*(size-1); + OBJ *end = val + val_s*(ptrdiff_t)(size-1); OBJ res; while (val != end) { diff --git a/CosStd/src/Array_vw.c b/CosStd/src/Array_vw.c index 4c7ec93c..b22e6dc2 100644 --- a/CosStd/src/Array_vw.c +++ b/CosStd/src/Array_vw.c @@ -38,7 +38,7 @@ useclass(ArrayView, ArraySubView, ExBadRange); // ----- initializer (weaker than constructors: no retain) defmethod(OBJ, ginitWith2, ArrayView, Array, Slice) // array view - if ( Slice_first(self3) < self2->size && Slice_last(self3) < self2->size) { + if ( Slice_first(self3) >= self2->size || Slice_last(self3) >= self2->size) { self->ref = 0; THROW( gnewWithStr(ExBadRange, "slice out of range") ); } @@ -58,7 +58,7 @@ defmethod(OBJ, ginitWith2, ArrayView, Array, Range) // array view endmethod defmethod(OBJ, ginitWith2, ArraySubView, Array, Slice) // array subview - if ( Slice_first(self3) < self2->size && Slice_last(self3) < self2->size) { + if ( Slice_first(self3) >= self2->size || Slice_last(self3) >= self2->size) { self->ArrayView.ref = 0; THROW( gnewWithStr(ExBadRange, "slice out of range") ); } diff --git a/CosStd/src/File.c b/CosStd/src/File.c index 30b87032..d641ac1c 100644 --- a/CosStd/src/File.c +++ b/CosStd/src/File.c @@ -41,8 +41,8 @@ makclass(OutputInputFile, OutputFile); // ----- -useclass(InputFile, OutputFile, InputOutputFile, OutputInputFile); -useclass(ExBadStream, ExBadAlloc, AutoRelease, Array, String); +useclass(InputFile, OutputFile); +useclass(ExBadStream); // ----- diff --git a/CosStd/src/String.c b/CosStd/src/String.c index 9f9008ca..dcd2348b 100644 --- a/CosStd/src/String.c +++ b/CosStd/src/String.c @@ -37,7 +37,7 @@ makclass(StringN, String); // ----- -useclass(String, ExBadAlloc, ExOverflow); +useclass(String, ExOverflow); // --- getters diff --git a/CosStd/src/String_alg.c b/CosStd/src/String_alg.c index 5c248280..d1fabeef 100644 --- a/CosStd/src/String_alg.c +++ b/CosStd/src/String_alg.c @@ -29,11 +29,9 @@ #include #include -#include - // ----- -useclass(String, View, Array, ExBadAlloc); +useclass(View, Array); useclass(Lesser,Equal,Greater); // ----- equality @@ -249,7 +247,7 @@ endmethod static U8* KnuthMorrisPratt(U8 *str, U32 str_n, U8 *pat, I32 pat_n) { - CARRAY_CREATE(I32,kmpNext,pat_n); + cos_alloc_tmp(I32,kmpNext,pat_n); { // preprocessing I32 i = 0, j = kmpNext[0] = -1; @@ -276,13 +274,13 @@ KnuthMorrisPratt(U8 *str, U32 str_n, U8 *pat, I32 pat_n) i++; j++; if (i >= pat_n) { // found - CARRAY_DESTROY(kmpNext); + cos_free_tmp(kmpNext); return str + (j - i); } } } - CARRAY_DESTROY(kmpNext); + cos_free_tmp(kmpNext); return 0; } diff --git a/CosStd/src/String_dyn.c b/CosStd/src/String_dyn.c index 012296b4..4fc5c9fb 100644 --- a/CosStd/src/String_dyn.c +++ b/CosStd/src/String_dyn.c @@ -36,7 +36,7 @@ makclass(StringDyn, StringFix); // ----- -useclass(String, StringDyn, ExBadAlloc, ExOverflow); +useclass(StringDyn, ExBadAlloc, ExOverflow); // ----- getter @@ -50,9 +50,9 @@ defmethod(OBJ, gdeinit, StringFix) next_method(self); if (self->_value) { // take care of protection cases - free(self->_value); + cos_free(self->_value); self->String.value = 0; - self->_value = 0; + self->_value = 0; } retmethod(_1); @@ -91,7 +91,7 @@ defmethod(OBJ, ginitWith, StringDyn, Int) THROW(gnewWithStr(ExOverflow, "capacity is too large")); } - strf->_value = malloc(size); + strf->_value = cos_malloc(size); if (!strf->_value && size) THROW(ExBadAlloc); @@ -143,7 +143,7 @@ defmethod(OBJ, genlarge, StringDyn, Int) // negative size means enlarge front if (size/sizeof *strf->_value < capacity+1) THROW(gnewWithStr(ExOverflow, "extra size is too large")); - U8* _value = realloc(strf->_value, size); + U8* _value = cos_realloc(strf->_value, size); if (!_value && size) THROW(ExBadAlloc); @@ -172,7 +172,7 @@ defmethod(OBJ, gadjust, StringDyn) // shrink storage if (str->size != self->capacity) { - U8* _value = realloc(strf->_value, size); + U8* _value = cos_realloc(strf->_value, size); if (!_value && size) THROW(ExBadAlloc); diff --git a/CosStd/src/tmpl/Vector.c b/CosStd/src/tmpl/Vector.c index efec48ce..5f221b3c 100644 --- a/CosStd/src/tmpl/Vector.c +++ b/CosStd/src/tmpl/Vector.c @@ -36,8 +36,6 @@ // #include #include -#include - #include #include diff --git a/CosStd/src/tmpl/Vector_alg.c b/CosStd/src/tmpl/Vector_alg.c index b6725332..63627c56 100644 --- a/CosStd/src/tmpl/Vector_alg.c +++ b/CosStd/src/tmpl/Vector_alg.c @@ -88,8 +88,8 @@ defmethod(OBJ, gpermute, T, IntVector) I32 idx_s = self2->stride; I32 *idx = self2->value; - CARRAY_CREATE(VAL,buf,size); // VAL buf[size]; - CARRAY_CREATE(U8 ,flg,size); // U8 flg[size]; + cos_alloc_tmp(VAL,buf,size); // VAL buf[size]; + cos_alloc_tmp(U8 ,flg,size); // U8 flg[size]; memset(flg,1,size); @@ -109,8 +109,8 @@ defmethod(OBJ, gpermute, T, IntVector) for (cur = buf; cur != end; cur++) *val = *cur, val += val_s; - CARRAY_DESTROY(buf); - CARRAY_DESTROY(flg); + cos_free_tmp(buf); + cos_free_tmp(flg); } else { // rollback (error) BOOL iiir = i < size; // last index-is-in-range flag @@ -121,8 +121,8 @@ defmethod(OBJ, gpermute, T, IntVector) val[i*val_s] = *--cur; } - CARRAY_DESTROY(buf); - CARRAY_DESTROY(flg); + cos_free_tmp(buf); + cos_free_tmp(flg); ensure( iiir, "index out of range" ); ensure( 0, "invalid cyclic permutation" ); } @@ -347,7 +347,7 @@ endmethod static VAL* KnuthMorrisPratt(VAL *val, U32 val_n, I32 val_s, VAL *pat, I32 pat_n, I32 pat_s) { - CARRAY_CREATE(I32,kmpNext,pat_n); + cos_alloc_tmp(I32,kmpNext,pat_n); { // preprocessing I32 i = 0, j = kmpNext[0] = -1; @@ -374,13 +374,13 @@ KnuthMorrisPratt(VAL *val, U32 val_n, I32 val_s, VAL *pat, I32 pat_n, I32 pat_s) i++; j++; if (i >= pat_n) { // found - CARRAY_DESTROY(kmpNext); + cos_free_tmp(kmpNext); return val + (j - i)*val_s; } } } - CARRAY_DESTROY(kmpNext); + cos_free_tmp(kmpNext); return 0; // not found } diff --git a/CosStd/src/tmpl/Vector_dyn.c b/CosStd/src/tmpl/Vector_dyn.c index bc9f78c2..b8b8c9d0 100644 --- a/CosStd/src/tmpl/Vector_dyn.c +++ b/CosStd/src/tmpl/Vector_dyn.c @@ -63,7 +63,7 @@ defmethod(OBJ, ginitWith, TD, Int) ensure(self2->value >= 0, "negative " TS " capacity"); - vecf->_value = malloc(capacity*sizeof *vec->value); + vecf->_value = cos_malloc(capacity*sizeof *vec->value); if (!vecf->_value && capacity) THROW(ExBadAlloc); vec->size = 0; @@ -81,7 +81,7 @@ defmethod(OBJ, gdeinit, TF) next_method(self); if (self->_value) // take care of protection cases - free(self->_value); + cos_free(self->_value); retmethod(_1); endmethod @@ -140,7 +140,7 @@ defmethod(OBJ, genlarge, TD, Int) // negative size means enlarge front capacity += size = extra_size(capacity, size); - VAL *_value = realloc(vecf->_value, capacity*sizeof *vecf->_value); + VAL *_value = cos_realloc(vecf->_value, capacity*sizeof *vecf->_value); if (!_value && capacity) THROW(ExBadAlloc); vec -> value = _value + offset; @@ -166,7 +166,7 @@ defmethod(OBJ, gadjust, TD) // shrink storage if (size != vecf->capacity) { - VAL *_value = realloc(vecf->_value, size*sizeof *vecf->_value); + VAL *_value = cos_realloc(vecf->_value, size*sizeof *vecf->_value); if (!_value && size) THROW(ExBadAlloc); vec -> value = _value; diff --git a/CosStd/src/tmpl/Vector_lzy.c b/CosStd/src/tmpl/Vector_lzy.c index ba0672cb..24d2654f 100644 --- a/CosStd/src/tmpl/Vector_lzy.c +++ b/CosStd/src/tmpl/Vector_lzy.c @@ -92,7 +92,7 @@ defmethod(OBJ, ggetAt, TL, Int) while (vec->size <= i) gappend(_1, geval(self->generator)); - retmethod( gautoDelete(VALOBJ(vec->value[i*vec->stride])) ); + retmethod( gautoRelease(VALOBJ(vec->value[i*vec->stride])) ); endmethod // NOTE-TODO: other getters? diff --git a/CosStd/tests/Makefile b/CosStd/tests/Makefile index 87e58286..f24b3de8 100644 --- a/CosStd/tests/Makefile +++ b/CosStd/tests/Makefile @@ -31,8 +31,8 @@ program := testCosStd targets := debug.run # files and modules -sources := $(wildcard src/*.c) -headers := $(wildcard src/*.h) +sources := src/*.c +headers := src/*.h defgens := $(headers) defprps := $(headers) diff --git a/INSTALL b/INSTALL index 2efcbbfe..d65ad7c9 100644 --- a/INSTALL +++ b/INSTALL @@ -48,11 +48,12 @@ Tested platforms: # System & Architectures Linux Ubuntu 8.04, 8.10, 9.04, 9.10 (Debian) on i386 (32-bit) Core2 Duo Linux Ubuntu 8.04, 8.10, 9.04, 9.10 (Debian) on x86_64 (64-bit) Core2 Duo +Linux Debian 8.11 on x86_64 (64-bit) Intel 8-core Xeon Linux SLC 4.0, 5.0 (RedHat) on x86_64 (64-bit) Quad Xeon Mac OS X Leopard (Darwin) on x86_64 (64-bit) Core2 Duo # Compilers -gcc 3.2.3, 3.4.6, 4.1.2, 4.2.4, 4.3.2, 4.3.3 +gcc 3.2.3, 3.4.6, 4.1.2, 4.2.4, 4.3.2, 4.3.3, 7.2.0, 12.2.0 Other available platforms (untested): ------------------------------------- @@ -73,7 +74,6 @@ or on arXiv.org Project information: -------------------- - - web page: http:/cern.ch/laurent.deniau/cos.html - - web site: http:/sf.net/projects/cos - - contact : laurent.deniau@cern.ch + - web site: https://github.com/CObjectSystem/COS + - contact : laurent dot deniau at gmail dot com diff --git a/Makefile b/Makefile index eaa98c07..53307eb0 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ # | # | C Object System # | -# | Copyright (c) 2007+ Laurent Deniau, laurent.deniau@cern.ch +# | Copyright (c) 2007+ Laurent Deniau, laurent.deniau@gmail.com # | # | For more information, see: # | http://cern.ch/laurent.deniau/cos.html diff --git a/README b/README index 5224bdae..cf6419e2 100644 --- a/README +++ b/README @@ -77,6 +77,9 @@ or on arXiv.org Wiki on CLOS: http://en.wikipedia.org/wiki/Common_Lisp_Object_System +Wiki on multiple dispatch: +http://en.wikipedia.org/wiki/Multiple_dispatch#C + Makefile examples: ------------------ @@ -129,7 +132,7 @@ Mac OSX from Leopard to El Capitan on x86_64 multicore Windows from 7 to 10 on x86_64 multicore using MSys2 (mingw64) # Compilers -gcc from 3.2.3 to 4.8.5 +gcc from 3.2.3 to 4.8.5, 7.2.0, and 8.2.0 Other available platforms (untested): ------------------------------------- diff --git a/README.C89 b/README.C89 index 32caf2cf..7515f2ff 100644 --- a/README.C89 +++ b/README.C89 @@ -25,7 +25,7 @@ COS core generates code conform to ISO C89 but it requires a ISO C99 preprocesso CosBase (core) can be compiled with a standalone C99 preprocessor and a C89 compiler. CosStd and other modules require a C99 compiler or a compiler which supports at least - - compound litterals (automatic constructors) + - compound literals (automatic constructors) - flexible arrays (some class cluster definition like Array) - 64 bits integers on non 64 bits architectures (class Long) - complex numbers (class Complex)