1 /* Copyright (C) 1991, 1992, 1993, 1994, 1999 Aladdin Enterprises. All rights reserved. 2 3 This software is provided AS-IS with no warranty, either express or 4 implied. 5 6 This software is distributed under license and may not be copied, 7 modified or distributed except as expressly authorized under the terms 8 of the license contained in the file LICENSE in this distribution. 9 10 For more information about licensing, please refer to 11 http://www.ghostscript.com/licensing/. For information on 12 commercial licensing, go to http://www.artifex.com/licensing/ or 13 contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14 San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 */ 16 17 /* $Id: ipacked.h,v 1.4 2002/02/21 22:24:53 giles Exp $ */ 18 /* Packed array format for Ghostscript */ 19 20 #ifndef ipacked_INCLUDED 21 # define ipacked_INCLUDED 22 23 /* 24 25 In a packed array, an element may either be a 2-byte ref_packed or a 26 full-size ref (8 or 16 bytes). We carefully arrange the first two bytes, 27 which are either an entire ref_packed or the type_attrs member of a ref, 28 so that we can distinguish the 2 forms. The encoding: 29 30 00tttttt exrwsfnm full-size ref 31 010mjjjj jjjjjjjj executable operator (so bind can work) 32 011mvvvv vvvvvvvv integer (biased by packed_min_intval) 33 100m---- -------- (not used) 34 101m---- -------- (not used) 35 110miiii iiiiiiii literal name 36 111miiii iiiiiiii executable name 37 38 The m bit is the mark bit for the garbage collector. 39 40 ****** Note for the future: We could get packed tokens into the first-level 41 ****** interpreter dispatch by changing to the following representation: 42 43 000ttttt exrwsfnm full-size ref 44 m0100jjj jjjjjjjj executable operator (so bind can work) 45 m0101vvv vvvvvvvv integer (biased by packed_min_intval) 46 m011iiii iiiiiiii literal name 47 m100iiii iiiiiiii executable name 48 m101---- -------- (not used) 49 m11----- -------- (not used) 50 51 ****** We aren't going to do this for a while. 52 53 The jjj index of executable operators is either the index of the operator 54 in the op_def_table, if the index is less than op_def_count, or the index 55 of the definition in the op_array_table (subtracting op_def_count first). 56 57 The iii index of names is the one that the name machinery already 58 maintains. A name whose index is larger than will fit in the packed 59 representation must be represented as a full-size ref. 60 61 There are two packed array types, t_mixedarray and t_shortarray. A 62 t_mixedarray can have a mix of packed and full-size elements; a 63 t_shortarray has all packed elements. The 'size' of a packed array is the 64 number of elements, not the number of bytes it occupies. 65 66 Packed array elements can be distinguished from full-size elements, so we 67 allow the interpreter to simply execute all the different kinds of arrays 68 directly. However, if we really allowed free mixing of packed and 69 full-size elements, this could lead to unaligned placement of full-size 70 refs; some machines can't handle unaligned accesses of this kind. To 71 guarantee that full-size elements in mixed arrays are always properly 72 aligned, if a full-size ref must be aligned at an address which is 0 mod 73 N, we convert up to N/2-1 preceding packed elements into full-size 74 elements, when creating the array, so that the alignment is preserved. 75 The only code this actually affects is in make_packed_array and in the 76 code for compacting refs in the garbage collector. 77 78 Note that code in zpacked.c and interp.c knows more about the 79 representation of packed elements than the definitions in this file would 80 imply. Read the code carefully if you change the representation. 81 82 */ 83 84 #define r_packed_type_shift 13 85 #define r_packed_value_bits 12 86 typedef enum { 87 pt_full_ref = 0, 88 #define pt_min_packed 2 89 pt_executable_operator = 2, 90 pt_integer = 3, 91 pt_unused1 = 4, 92 pt_unused2 = 5, 93 #define pt_min_name 6 94 pt_literal_name = 6, 95 #define pt_min_exec_name 7 96 pt_executable_name = 7 97 } packed_type; 98 99 #define packed_per_ref (sizeof(ref) / sizeof(ref_packed)) 100 #define align_packed_per_ref\ 101 (arch_align_ref_mod / arch_align_short_mod) 102 #define pt_tag(pt) ((ref_packed)(pt) << r_packed_type_shift) 103 #define packed_value_mask ((1 << r_packed_value_bits) - 1) 104 #define packed_max_value packed_value_mask 105 #define r_is_packed(rp) (*(const ref_packed *)(rp) >= pt_tag(pt_min_packed)) 106 /* Names */ 107 #define r_packed_is_name(prp) (*(prp) >= pt_tag(pt_min_name)) 108 #define r_packed_is_exec_name(prp) (*(prp) >= pt_tag(pt_min_exec_name)) 109 #define packed_name_max_index packed_max_value 110 #define packed_name_index(prp) (*(prp) & packed_value_mask) 111 /* Integers */ 112 #define packed_min_intval (-(1 << (r_packed_value_bits - 1))) 113 #define packed_max_intval ((1 << (r_packed_value_bits - 1)) - 1) 114 #define packed_int_mask packed_value_mask 115 116 /* Packed ref marking */ 117 #define lp_mark_shift 12 118 #define lp_mark (1 << lp_mark_shift) 119 #define r_has_pmark(rp) (*(rp) & lp_mark) 120 #define r_set_pmark(rp) (*(rp) |= lp_mark) 121 #define r_clear_pmark(rp) (*(rp) &= ~lp_mark) 122 #define r_store_pmark(rp,pm) (*(rp) = (*(rp) & ~lp_mark) | (pm)) 123 124 /* Advance to the next element in a packed array. */ 125 #define packed_next(prp)\ 126 (r_is_packed(prp) ? prp + 1 : prp + packed_per_ref) 127 128 /* Define the current array packing flag (setpacking/currentpacking) */ 129 /* for operators. */ 130 /* This is a ref so that it can be managed properly by save/restore. */ 131 #define ref_array_packing_container i_ctx_p 132 #define ref_array_packing (ref_array_packing_container->array_packing) 133 134 #endif /* ipacked_INCLUDED */ 135