123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- /* Copyright (C) 1992, 1993, 1994, 1996, 1997 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
- /*$Id: ivmspace.h,v 1.2 2000/09/19 19:00:47 lpd Exp $ */
- /* Local/global space management */
- /* Requires iref.h */
- #ifndef ivmspace_INCLUDED
- # define ivmspace_INCLUDED
- #include "gsgc.h"
- /*
- * r_space_bits and r_space_shift, which define the bits in a ref
- * that carry VM space information, are defined in iref.h.
- * r_space_bits must be at least 2.
- */
- #define a_space (((1 << r_space_bits) - 1) << r_space_shift)
- /*
- * The i_vm_xxx values are defined in gsgc.h.
- */
- typedef enum {
- avm_foreign = (i_vm_foreign << r_space_shift),
- avm_system = (i_vm_system << r_space_shift),
- avm_global = (i_vm_global << r_space_shift),
- avm_local = (i_vm_local << r_space_shift),
- avm_max = avm_local
- } avm_space;
- #define r_space(rp) (avm_space)(r_type_attrs(rp) & a_space)
- #define r_space_index(rp) ((int)r_space(rp) >> r_space_shift)
- #define r_set_space(rp,space) r_store_attrs(rp, a_space, (uint)space)
- /*
- * According to the PostScript language specification, attempting to store
- * a reference to a local object into a global object must produce an
- * invalidaccess error. However, systemdict must be able to refer to
- * a number of local dictionaries such as userdict and errordict.
- * Therefore, we implement a special hack in 'def' that allows such stores
- * if the dictionary being stored into is systemdict (which is normally
- * only writable during initialization) or a dictionary that appears
- * in systemdict (such as level2dict), and the current save level is zero
- * (to guarantee that we can't get dangling pointers).
- * We could allow this for any global dictionary, except that the garbage
- * collector must treat any such dictionaries as roots when collecting
- * local VM without collecting global VM.
- * We make a similar exception for .makeglobaloperator; this requires
- * treating the operator table as a GC root as well.
- *
- * We extend the local-into-global store check because we have four VM
- * spaces (local, global, system, and foreign), and we allow PostScript
- * programs to create objects in any of the first three. If we define
- * the "generation" of an object as foreign = 0, system = 1, global = 2,
- * and local = 3, then a store is legal iff the generation of the object
- * into which a pointer is being stored is greater than or equal to
- * the generation of the object into which the store is occurring.
- *
- * We must check for local-into-global stores in three categories of places:
- *
- * - The scanner, when it encounters a //name inside {}.
- *
- * - All operators that allocate ref-containing objects and also
- * store into them:
- * packedarray gstate makepattern?
- * makefont scalefont definefont filter
- *
- * - All operators that store refs into existing objects
- * ("operators" marked with * are actually PostScript procedures):
- * put(array) putinterval(array) astore copy(to array)
- * def store* put(dict) copy(dict)
- * dictstack execstack .make(global)operator
- * currentgstate defineusername
- */
- /* Test whether an object is in local space, */
- /* which implies that we need not check when storing into it. */
- #define r_is_local(rp) (r_space(rp) == avm_local)
- /* Test whether an object is foreign, i.e., outside known space. */
- #define r_is_foreign(rp) (r_space(rp) == avm_foreign)
- /* Check whether a store is allowed. */
- #define store_check_space(destspace,rpnew)\
- if ( r_space(rpnew) > (destspace) )\
- return_error(e_invalidaccess)
- #define store_check_dest(rpdest,rpnew)\
- store_check_space(r_space(rpdest), rpnew)
- /* BACKWARD COMPATIBILITY (not used by any Ghostscript code per se) */
- #define check_store_space(rdest,rnewcont)\
- store_check_dest(&(rdest),&(rnewcont))
- #endif /* ivmspace_INCLUDED */
|