/* types.h * Copyright 1984-2017 Cisco Systems, Inc. * * 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. */ /* C datatypes (mostly defined in equates.h or scheme.h) * ptr: scheme object: (void *) on most platforms * uptr: unsigned integer sizeof(uptr) == sizeof(ptr): typically unsigned long * iptr: signed integer sizeof(uptr) == sizeof(ptr): typically long * I8: 8-bit signed integer: typically char * I16: 16-bit signed integer: typically short * I32: 32-bit signed integer: typically int * U32: 32-bit unsigned integer: typically unsigned int * I64: 64-bit signed integer: typically long long * U64: 64-bit unsigned integer: typically unsigned long long * bigit: unsigned integer sizeof(bigit)*8 == bigit_bits * bigit: unsigned integer sizeof(bigit)*8 == bigit_bits */ #if (bigit_bits == 32) typedef U32 bigit; typedef U64 bigitbigit; typedef I32 ibigit; typedef I64 ibigitbigit; #endif /* C signed/unsigned conventions: * signed/unsigned distinction is felt in comparisons with zero, right * shifts, multiplies, and divides. * * general philosophy is to avoid surprises by using signed quantities, * with a few exceptions. * * use unsigned whenever shifting right. ANSI C >> is undefined for * negative numbers. if arithmetic shift is desired, divide by the * appropriate power of two and hope that the C compiler generates a * shift instruction. * * cast to uptr for ptr address computations. this is really necessary * only when shifting addresses, but we do it all the time since * addresses are inherently unsigned values. * * however, use signed (usually iptr) for lengths and array indices. * this allows base cases like i < 0 when working backward from the end * to the front of an array. using uptr would give a slightly larger * range in theory, but not in practice. */ /* documentary names for ints and unsigned ints */ typedef int INT; /* honest-to-goodness C int */ typedef unsigned int UINT; /* honest-to-goodness C unsigned int */ typedef int ITYPE; /* ptr types */ typedef int ISPC; /* storage manager spaces */ typedef int IGEN; /* storage manager generations */ typedef int IDIRTYBYTE; /* storage manager dirty bytes */ typedef int IBOOL; /* int used exclusively as a boolean */ typedef int ICHAR; /* int used exclusively as a character */ typedef int IFASLCODE; /* fasl type codes */ #if (BUFSIZ < 4096) #define SBUFSIZ 4096 #else #define SBUFSIZ BUFSIZ #endif /* inline allocation --- mutex required */ /* find room allocates n bytes in space s and generation g into * destination x, tagged with ty, punting to find_more_room if * no space is left in the current segment. n is assumed to be * an integral multiple of the object alignment. */ #define find_room(s, g, t, n, x) {\ ptr X = S_G.next_loc[g][s];\ S_G.next_loc[g][s] = (ptr)((uptr)X + (n));\ if ((S_G.bytes_left[g][s] -= (n)) < 0) X = S_find_more_room(s, g, n, X);\ (x) = TYPE(X, t);\ } /* thread-local inline allocation --- no mutex required */ /* thread_find_room allocates n bytes in the local allocation area of * the thread (hence space new, generation zero) into destination x, tagged * with type t, punting to find_more_room if no space is left in the current * allocation area. n is assumed to be an integral multiple of the object * alignment. */ #define thread_find_room(tc, t, n, x) {\ ptr _tc = tc;\ uptr _ap = (uptr)AP(_tc);\ if ((uptr)n > ((uptr)EAP(_tc) - _ap)) {\ (x) = S_get_more_room_help(_tc, _ap, t, n);\ } else {\ (x) = TYPE(_ap,t);\ AP(_tc) = (ptr)(_ap + n);\ }\ } /* size of protected array used to store roots for the garbage collector */ #define max_protected 100 #define build_ptr(s,o) ((ptr)(((uptr)(s) << segment_offset_bits) | (uptr)(o))) #define addr_get_segment(p) ((uptr)(p) >> segment_offset_bits) #define ptr_get_segment(p) (((uptr)(p) + typemod - 1) >> segment_offset_bits) #define SPACE(p) SegmentSpace(ptr_get_segment(p)) #define GENERATION(p) SegmentGeneration(ptr_get_segment(p)) #define ptr_align(size) (((size)+byte_alignment-1) & ~(byte_alignment-1)) typedef struct _seginfo { unsigned char space; /* space the segment is in */ unsigned char generation; /* generation the segment is in */ unsigned char sorted; /* sorted indicator---possibly to be incorporated into space flags? */ octet min_dirty_byte; /* dirty byte for full segment, effectively min(dirty_bytes) */ uptr number; /* the segment number */ struct _chunkinfo *chunk; /* the chunk this segment belongs to */ struct _seginfo *next; /* pointer to the next seginfo (used in occupied_segments and unused_segs */ struct _seginfo **dirty_prev; /* pointer to the next pointer on the previous seginfo in the DirtySegments list */ struct _seginfo *dirty_next; /* pointer to the next seginfo on the DirtySegments list */ ptr trigger_ephemerons; /* ephemerons to re-check if object in segment is copied out */ octet dirty_bytes[cards_per_segment]; /* one dirty byte per card */ } seginfo; typedef struct _chunkinfo { void *addr; /* chunk starting address */ iptr base; /* first segment */ iptr bytes; /* size in bytes */ iptr segs; /* size in segments */ iptr nused_segs; /* number of segments currently in used use */ struct _chunkinfo **prev; /* pointer to previous chunk's next */ struct _chunkinfo *next; /* next chunk */ struct _seginfo *unused_segs; /* list of unused segments */ struct _seginfo sis[0]; /* one seginfo per segment */ } chunkinfo; #ifdef segment_t2_bits typedef struct _t1table { seginfo *t1[1<>1)+to_g) #define DIRTY_SEGMENT_LISTS DIRTY_SEGMENT_INDEX(static_generation, static_generation) #define DirtySegments(from_g, to_g) S_G.dirty_segments[DIRTY_SEGMENT_INDEX(from_g, to_g)] /* oblist */ typedef struct _bucket { ptr sym; struct _bucket *next; } bucket; typedef struct _bucket_list { struct _bucket *car; struct _bucket_list *cdr; } bucket_list; typedef struct _bucket_pointer_list { struct _bucket **car; struct _bucket_pointer_list *cdr; } bucket_pointer_list; /* size macros for variable-sized objects */ #define size_vector(n) ptr_align(header_size_vector + (n)*ptr_bytes) #define size_closure(n) ptr_align(header_size_closure + (n)*ptr_bytes) #define size_string(n) ptr_align(header_size_string + (n)*string_char_bytes) #define size_fxvector(n) ptr_align(header_size_fxvector + (n)*ptr_bytes) #define size_bytevector(n) ptr_align(header_size_bytevector + (n)) #define size_bignum(n) ptr_align(header_size_bignum + (n)*bigit_bytes) #define size_code(n) ptr_align(header_size_code + (n)) #define size_reloc_table(n) ptr_align(header_size_reloc_table + (n)*ptr_bytes) #define size_record_inst(n) ptr_align(n) #define unaligned_size_record_inst(n) (n) /* type tagging macros */ #define TYPE(x,type) ((ptr)((iptr)(x) - typemod + (type))) #define UNTYPE(x,type) ((ptr)((iptr)(x) + typemod - (type))) #define UNTYPE_ANY(x) ((ptr)(((iptr)(x) + (typemod - 1)) & ~(typemod - 1))) #define TYPEBITS(x) ((iptr)(x) & (typemod - 1)) #define TYPEFIELD(x) (*(ptr *)UNTYPE(x, type_typed_object)) #define FIX(x) Sfixnum(x) #define UNFIX(x) Sfixnum_value(x) #define TYPEP(x,mask,type) (((iptr)(x) & (mask)) == (type)) /* reloc fields */ #define RELOC_EXTENDED_FORMAT(x) ((x)&reloc_extended_format) #define RELOC_TYPE(x) (((x)>>reloc_type_offset)&reloc_type_mask) #define RELOC_CODE_OFFSET(x) (((x)>>reloc_code_offset_offset)&reloc_code_offset_mask) #define RELOC_ITEM_OFFSET(x) (((x)>>reloc_item_offset_offset)&reloc_item_offset_mask) #define MAKE_SHORT_RELOC(ty,co,io) (((ty)<