1 /* Copyright (C) 2001-2019 Artifex Software, Inc. 2 All Rights Reserved. 3 4 This software is provided AS-IS with no warranty, either express or 5 implied. 6 7 This software is distributed under license and may not be copied, 8 modified or distributed except as expressly authorized under the terms 9 of the license contained in the file LICENSE in this distribution. 10 11 Refer to licensing information at http://www.artifex.com or contact 12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, 13 CA 94945, U.S.A., +1(415)492-9861, for further information. 14 */ 15 16 17 /* Local/global space management */ 18 /* Requires iref.h */ 19 20 #ifndef ivmspace_INCLUDED 21 # define ivmspace_INCLUDED 22 23 #include "gsgc.h" 24 #include "iref.h" 25 26 /* 27 * r_space_bits and r_space_shift, which define the bits in a ref 28 * that carry VM space information, are defined in iref.h. 29 * r_space_bits must be at least 2. 30 */ 31 #define a_space (((1 << r_space_bits) - 1) << r_space_shift) 32 /* 33 * The i_vm_xxx values are defined in gsgc.h. 34 */ 35 typedef enum { 36 avm_foreign = (i_vm_foreign << r_space_shift), 37 avm_system = (i_vm_system << r_space_shift), 38 avm_global = (i_vm_global << r_space_shift), 39 avm_local = (i_vm_local << r_space_shift), 40 avm_max = avm_local 41 } avm_space; 42 43 #define r_space(rp) (avm_space)(r_type_attrs(rp) & a_space) 44 #define r_space_index(rp) ((int)r_space(rp) >> r_space_shift) 45 #define r_set_space(rp,space) r_store_attrs(rp, a_space, (uint)space) 46 47 /* 48 * According to the PostScript language specification, attempting to store 49 * a reference to a local object into a global object must produce an 50 * invalidaccess error. However, systemdict must be able to refer to 51 * a number of local dictionaries such as userdict and errordict. 52 * Therefore, we implement a special hack in 'def' that allows such stores 53 * if the dictionary being stored into is systemdict (which is normally 54 * only writable during initialization) or a dictionary that appears 55 * in systemdict (such as level2dict), and the current save level is zero 56 * (to guarantee that we can't get dangling pointers). 57 * We could allow this for any global dictionary, except that the garbage 58 * collector must treat any such dictionaries as roots when collecting 59 * local VM without collecting global VM. 60 * We make a similar exception for .makeglobaloperator; this requires 61 * treating the operator table as a GC root as well. 62 * 63 * We extend the local-into-global store check because we have four VM 64 * spaces (local, global, system, and foreign), and we allow PostScript 65 * programs to create objects in any of the first three. If we define 66 * the "generation" of an object as foreign = 0, system = 1, global = 2, 67 * and local = 3, then a store is legal iff the generation of the object 68 * into which a pointer is being stored is greater than or equal to 69 * the generation of the object into which the store is occurring. 70 * 71 * We must check for local-into-global stores in three categories of places: 72 * 73 * - The scanner, when it encounters a //name inside {}. 74 * 75 * - All operators that allocate ref-containing objects and also 76 * store into them: 77 * packedarray gstate makepattern? 78 * makefont scalefont definefont filter 79 * 80 * - All operators that store refs into existing objects 81 * ("operators" marked with * are actually PostScript procedures): 82 * put(array) putinterval(array) astore copy(to array) 83 * def store* put(dict) copy(dict) 84 * dictstack execstack .make(global)operator 85 * currentgstate defineusername 86 */ 87 88 /* Test whether an object is in local space, */ 89 /* which implies that we need not check when storing into it. */ 90 #define r_is_local(rp) (r_space(rp) == avm_local) 91 /* Test whether an object is foreign, i.e., outside known space. */ 92 #define r_is_foreign(rp) (r_space(rp) == avm_foreign) 93 /* Check whether a store is allowed. */ 94 #define store_check_space(destspace,rpnew)\ 95 if ( r_space(rpnew) > (destspace) )\ 96 return_error(gs_error_invalidaccess) 97 #define store_check_dest(rpdest,rpnew)\ 98 store_check_space(r_space(rpdest), rpnew) 99 /* BACKWARD COMPATIBILITY (not used by any Ghostscript code per se) */ 100 #define check_store_space(rdest,rnewcont)\ 101 store_check_dest(&(rdest),&(rnewcont)) 102 103 #endif /* ivmspace_INCLUDED */ 104