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