Changeset 12690
- Timestamp:
- 05/16/10 15:06:32 (13 years ago)
- Location:
- trunk/abcl/src/org/armedbear/lisp
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/compiler-pass2.lisp
r12683 r12690 1 ;;; compiler-pass2.lisp1 ;;; compiler-pass2.lisp 2 2 ;;; 3 3 ;;; Copyright (C) 2003-2008 Peter Graves … … 2066 2066 ,item-var)) 2067 2067 2068 ;; The protocol of the serialize-* functions is to serialize 2069 ;; the type to which they apply and emit code which leaves the 2070 ;; restored object on the stack. 2071 2072 ;; The functions may generate only Java code, or decide to defer 2073 ;; some of the process of restoring the object to the reader. The 2074 ;; latter is generally applicable to more complex structures. 2075 2076 ;; This way, the serialize-* functions can be used to depend on 2077 ;; each other to serialize nested constructs. They are also the 2078 ;; building blocks of the EXTERNALIZE-OBJECT function, which is 2079 ;; called from the compiler. 2080 2081 (defun serialize-integer (n) 2082 "Generates code to restore a serialized integer." 2083 (cond((<= 0 n 255) 2084 (emit 'getstatic +lisp-fixnum-class+ "constants" +lisp-fixnum-array+) 2085 (emit-push-constant-int n) 2086 (emit 'aaload)) 2087 ((<= most-negative-fixnum n most-positive-fixnum) 2088 (emit-push-constant-int n) 2089 (emit-invokestatic +lisp-fixnum-class+ "getInstance" 2090 '("I") +lisp-fixnum+)) 2091 ((<= most-negative-java-long n most-positive-java-long) 2092 (emit-push-constant-long n) 2093 (emit-invokestatic +lisp-bignum-class+ "getInstance" 2094 '("J") +lisp-integer+)) 2095 (t 2096 (let* ((*print-base* 10) 2097 (s (with-output-to-string (stream) (dump-form n stream)))) 2098 (emit 'ldc (pool-string s)) 2099 (emit-push-constant-int 10) 2100 (emit-invokestatic +lisp-bignum-class+ "getInstance" 2101 (list +java-string+ "I") +lisp-integer+))))) 2102 2103 (defun serialize-character (c) 2104 "Generates code to restore a serialized character." 2105 (emit-push-constant-int (char-code c)) 2106 (emit-invokestatic +lisp-character-class+ "getInstance" '("C") 2107 +lisp-character+)) 2108 2109 (defun serialize-float (s) 2110 "Generates code to restore a serialized single-float." 2111 (emit 'new +lisp-single-float-class+) 2112 (emit 'dup) 2113 (emit 'ldc (pool-float s)) 2114 (emit-invokespecial-init +lisp-single-float-class+ '("F"))) 2115 2116 (defun serialize-double (d) 2117 "Generates code to restore a serialized double-float." 2118 (emit 'new +lisp-double-float-class+) 2119 (emit 'dup) 2120 (emit 'ldc2_w (pool-double d)) 2121 (emit-invokespecial-init +lisp-double-float-class+ '("D"))) 2122 2123 (defun serialize-string (string) 2124 "Generate code to restore a serialized string." 2125 (emit 'new +lisp-simple-string-class+) 2126 (emit 'dup) 2127 (emit 'ldc (pool-string string)) 2128 (emit-invokespecial-init +lisp-simple-string-class+ (list +java-string+))) 2129 2130 (defun serialize-package (pkg) 2131 "Generate code to restore a serialized package." 2132 (emit 'ldc (pool-string (concatenate 'string "#.(FIND-PACKAGE \"" 2133 (package-name pkg) "\")"))) 2134 (emit-invokestatic +lisp-class+ "readObjectFromString" 2135 (list +java-string+) +lisp-object+)) 2136 2137 (defun serialize-object (object) 2138 "Generate code to restore a serialized object which is not of any 2139 of the other types." 2140 (let ((s (with-output-to-string (stream) 2141 (dump-form object stream)))) 2142 (emit 'ldc (pool-string s)) 2143 (emit-invokestatic +lisp-class+ "readObjectFromString" 2144 (list +java-string+) +lisp-object+))) 2145 2146 (defun serialize-symbol (symbol) 2147 "Generate code to restore a serialized symbol." 2148 (cond 2149 ((null (symbol-package symbol)) 2150 ;; we need to read the #?<n> syntax for uninterned symbols 2151 2152 ;; TODO: we could use the byte code variant of 2153 ;; Load._FASL_UNINTERNED_SYMBOLS_.symbolValue(LispThread.currentThread()) 2154 ;; .aref(<index) 2155 ;; to eliminate the reader dependency 2156 (serialize-object symbol) 2157 (emit 'checkcast +lisp-symbol-class+)) 2158 ((keywordp symbol) 2159 (emit 'ldc (pool-string (symbol-name symbol))) 2160 (emit-invokestatic +lisp-class+ "internKeyword" 2161 (list +java-string+) +lisp-symbol+)) 2162 (t 2163 (emit 'ldc (pool-string (symbol-name symbol))) 2164 (emit 'ldc (pool-string (package-name (symbol-package symbol)))) 2165 (emit-invokestatic +lisp-class+ "internInPackage" 2166 (list +java-string+ +java-string+) 2167 +lisp-symbol+)))) 2168 2169 (defvar serialization-table 2170 `((integer "INT" ,#'eql ,#'serialize-integer ,+lisp-integer+) 2171 (character "CHR" ,#'eql ,#'serialize-character ,+lisp-character+) 2172 (single-float "FLT" ,#'eql ,#'serialize-float ,+lisp-single-float+) 2173 (double-float "DBL" ,#'eql ,#'serialize-double ,+lisp-double-float+) 2174 (string "STR" ,#'equal ,#'serialize-string ,+lisp-simple-string+) 2175 (package "PKG" ,#'eq ,#'serialize-package ,+lisp-object+) 2176 (symbol "SYM" ,#'eq ,#'serialize-symbol ,+lisp-symbol+) 2177 (T "OBJ" ,#'eq ,#'serialize-object ,+lisp-object+)) 2178 "A list of 5-element lists. The elements of the sublists mean: 2179 2180 1. The type of the value to be serialized 2181 2. The string to be used as a field prefix 2182 3. The function to be used to determine equality (coalescing or not) 2183 4. The function to dispatch serialization to 2184 5. The type of the field to save the serialized result to") 2185 2186 (defknown externalize-object (t) string) 2187 (defun externalize-object (object) 2188 "Externalizes `object' for use in a FASL. 2189 2190 Returns the name of the field (in `*this-class*') from which 2191 the value of the object can be loaded. Objects may be coalesced based 2192 on the equality indicator in the `serialization-table'. 2193 2194 Code to restore the serialized object is inserted into `*code' or 2195 `*static-code*' if `*declare-inline*' is non-nil. 2196 " 2197 ;; TODO: rewrite to become EMIT-LOAD-EXTERNALIZED-OBJECT which 2198 ;; - instead of returning the name of the field - returns the type 2199 ;; of the field it just loaded (to allow casting and what not). 2200 ;; The function should still do what it does today: de-serialize the 2201 ;; object and storing its value. 2202 2203 (destructuring-bind 2204 (type prefix similarity-fn dispatch-fn field-type) 2205 (assoc-if #'(lambda (x) 2206 (typep object x)) 2207 serialization-table) 2208 (declare (ignore type)) ;; the type has been used in the selection process 2209 (let ((existing (assoc object *externalized-objects* :test similarity-fn))) 2210 (when existing 2211 (return-from externalize-object (cdr existing)))) 2212 2213 ;; We need to set up the serialized value 2214 (let ((field-name (symbol-name (gensym prefix)))) 2215 (declare-field field-name field-type +field-access-private+) 2216 (push (cons object field-name) *externalized-objects*) 2217 2218 (if *declare-inline* 2219 (progn 2220 (funcall dispatch-fn object) 2221 (emit 'putstatic *this-class* field-name field-type)) 2222 (let ((*code* *static-code*)) 2223 (funcall dispatch-fn object) 2224 (emit 'putstatic *this-class* field-name field-type) 2225 (setf *static-code* *code*))) 2226 2227 field-name))) 2068 2228 2069 2229 (defknown declare-symbol (symbol) string) 2070 2230 (defun declare-symbol (symbol) 2071 (declare (type symbol symbol)) 2072 (declare-with-hashtable 2073 symbol *declared-symbols* ht g 2074 (cond ((null (symbol-package symbol)) 2075 (setf g (if *file-compilation* 2076 (declare-object-as-string symbol +lisp-symbol+ 2077 +lisp-symbol-class+) 2078 (declare-object symbol +lisp-symbol+ 2079 +lisp-symbol-class+)) 2080 (gethash symbol ht) g)) 2081 (t 2082 (let (saved-code) 2083 (let ((*code* (if *declare-inline* *code* *static-code*)) 2084 (s (sanitize symbol))) 2085 ;; *declare-inline*, because the code below assumes the 2086 ;; package to exist, which can be in a previous statement; 2087 ;; thus we can't create the symbol out-of-band. 2088 (setf g (symbol-name (gensym "SYM"))) 2089 (when s 2090 (setf g (concatenate 'string g "_" s))) 2091 (declare-field g +lisp-symbol+ +field-access-private+) 2092 (emit 'ldc (pool-string (symbol-name symbol))) 2093 (emit 'ldc (pool-string (package-name (symbol-package symbol)))) 2094 (emit-invokestatic +lisp-class+ "internInPackage" 2095 (list +java-string+ +java-string+) 2096 +lisp-symbol+) 2097 (emit 'putstatic *this-class* g +lisp-symbol+) 2098 (if *declare-inline* 2099 (setf saved-code *code*) 2100 (setf *static-code* *code*)) 2101 (setf (gethash symbol ht) g)) 2102 (when *declare-inline* 2103 (setf *code* saved-code))))))) 2231 (cond 2232 ((and (not *file-compilation*) 2233 (null (symbol-package symbol))) 2234 (declare-object symbol +lisp-symbol+ +lisp-symbol-class+)) 2235 (t (externalize-object symbol)))) 2104 2236 2105 2237 (defun lookup-or-declare-symbol (symbol) … … 2112 2244 (values name class) 2113 2245 (values (declare-symbol symbol) *this-class*)))) 2114 2115 (defknown declare-keyword (symbol) string)2116 (defun declare-keyword (symbol)2117 (declare (type symbol symbol))2118 (declare-with-hashtable2119 symbol *declared-symbols* ht g2120 (let ((*code* *static-code*))2121 ;; there's no requirement to declare-inline here:2122 ;; keywords are constants, so they can be created any time,2123 ;; if early enough2124 (setf g (symbol-name (gensym "KEY")))2125 (declare-field g +lisp-symbol+ +field-access-private+)2126 (emit 'ldc (pool-string (symbol-name symbol)))2127 (emit-invokestatic +lisp-class+ "internKeyword"2128 (list +java-string+) +lisp-symbol+)2129 (emit 'putstatic *this-class* g +lisp-symbol+)2130 (setf *static-code* *code*)2131 (setf (gethash symbol ht) g))))2132 2246 2133 2247 (defknown declare-function (symbol &optional setf) string) … … 2186 2300 (setf (gethash local-function ht) g)))) 2187 2301 2188 (defknown declare-integer (integer) string) 2189 (defun declare-integer (n) 2190 (declare-with-hashtable 2191 n *declared-integers* ht g 2192 (setf g (concatenate 'string "INT_" (symbol-name (gensym)))) 2193 (let ((*code* *static-code*)) 2194 ;; no need to *declare-inline*: constants 2195 (declare-field g +lisp-integer+ +field-access-private+) 2196 (cond((<= 0 n 255) 2197 (emit 'getstatic +lisp-fixnum-class+ "constants" +lisp-fixnum-array+) 2198 (emit-push-constant-int n) 2199 (emit 'aaload)) 2200 ((<= most-negative-fixnum n most-positive-fixnum) 2201 (emit-push-constant-int n) 2202 (emit-invokestatic +lisp-fixnum-class+ "getInstance" 2203 '("I") +lisp-fixnum+)) 2204 ((<= most-negative-java-long n most-positive-java-long) 2205 (emit-push-constant-long n) 2206 (emit-invokestatic +lisp-bignum-class+ "getInstance" 2207 '("J") +lisp-integer+)) 2208 (t 2209 (let* ((*print-base* 10) 2210 (s (with-output-to-string (stream) (dump-form n stream)))) 2211 (emit 'ldc (pool-string s)) 2212 (emit-push-constant-int 10) 2213 (emit-invokestatic +lisp-bignum-class+ "getInstance" 2214 (list +java-string+ "I") +lisp-integer+)))) 2215 (emit 'putstatic *this-class* g +lisp-integer+) 2216 (setf *static-code* *code*)) 2217 (setf (gethash n ht) g))) 2218 2219 (defknown declare-float (single-float) string) 2220 (defun declare-float (s) 2221 (declare-with-hashtable 2222 s *declared-floats* ht g 2223 (let* ((*code* *static-code*)) 2224 ;; no need to *declare-inline*: constants 2225 (setf g (concatenate 'string "FLOAT_" (symbol-name (gensym)))) 2226 (declare-field g +lisp-single-float+ +field-access-private+) 2227 (emit 'new +lisp-single-float-class+) 2228 (emit 'dup) 2229 (emit 'ldc (pool-float s)) 2230 (emit-invokespecial-init +lisp-single-float-class+ '("F")) 2231 (emit 'putstatic *this-class* g +lisp-single-float+) 2232 (setf *static-code* *code*)) 2233 (setf (gethash s ht) g))) 2234 2235 (defknown declare-double (double-float) string) 2236 (defun declare-double (d) 2237 (declare-with-hashtable 2238 d *declared-doubles* ht g 2239 (let ((*code* *static-code*)) 2240 ;; no need to *declare-inline*: constants 2241 (setf g (concatenate 'string "DOUBLE_" (symbol-name (gensym)))) 2242 (declare-field g +lisp-double-float+ +field-access-private+) 2243 (emit 'new +lisp-double-float-class+) 2244 (emit 'dup) 2245 (emit 'ldc2_w (pool-double d)) 2246 (emit-invokespecial-init +lisp-double-float-class+ '("D")) 2247 (emit 'putstatic *this-class* g +lisp-double-float+) 2248 (setf *static-code* *code*)) 2249 (setf (gethash d ht) g))) 2250 2251 (defknown declare-character (t) string) 2252 (defun declare-character (c) 2253 (let ((g (symbol-name (gensym "CHAR"))) 2254 (n (char-code c)) 2255 (*code* *static-code*)) 2256 ;; no need to *declare-inline*: constants 2257 (declare-field g +lisp-character+ +field-access-private+) 2258 (emit-push-constant-int n) 2259 (emit-invokestatic +lisp-character-class+ "getInstance" '("C") 2260 +lisp-character+) 2261 (emit 'putstatic *this-class* g +lisp-character+) 2262 (setf *static-code* *code*) 2263 g)) 2264 2265 (defknown declare-object-as-string (t &optional t) string) 2266 (defun declare-object-as-string (obj &optional (obj-ref +lisp-object+) 2267 obj-class) 2302 2303 (defknown declare-object-as-string (t) string) 2304 (defun declare-object-as-string (obj) 2305 ;; TODO: replace with externalize-object 2306 ;; just replacing won't work however: 2307 ;; field identification in Java includes the field type 2308 ;; and we're not letting the caller know about the type of 2309 ;; field we're creating in externalize-object. 2310 ;; The solution is te rewrite externalize-object to 2311 ;; EMIT-LOAD-EXTERNALIZED-OBJECT, which serializes *and* 2312 ;; emits the right loading code (not just de-serialization anymore) 2268 2313 (let (saved-code 2269 2314 (g (symbol-name (gensym "OBJSTR")))) … … 2272 2317 ;; strings may contain evaluated bits which may depend on 2273 2318 ;; previous statements 2274 (declare-field g obj-ref+field-access-private+)2319 (declare-field g +lisp-object+ +field-access-private+) 2275 2320 (emit 'ldc (pool-string s)) 2276 2321 (emit-invokestatic +lisp-class+ "readObjectFromString" 2277 2322 (list +java-string+) +lisp-object+) 2278 (when (and obj-class (string/= obj-class +lisp-object+)) 2279 (emit 'checkcast obj-class)) 2280 (emit 'putstatic *this-class* g obj-ref) 2323 (emit 'putstatic *this-class* g +lisp-object+) 2281 2324 (if *declare-inline* 2282 2325 (setf saved-code *code*) … … 2334 2377 g)) 2335 2378 2336 (defun declare-package (obj)2337 (let (saved-code2338 (g (symbol-name (gensym "PKG"))))2339 (let* ((*print-level* nil)2340 (*print-length* nil)2341 (s (format nil "#.(FIND-PACKAGE ~S)" (package-name obj)))2342 (*code* (if *declare-inline* *code* *static-code*)))2343 (declare-field g +lisp-object+ +field-access-private+)2344 (emit 'ldc (pool-string s))2345 (emit-invokestatic +lisp-class+ "readObjectFromString"2346 (list +java-string+) +lisp-object+)2347 (emit 'putstatic *this-class* g +lisp-object+)2348 (if *declare-inline*2349 (setf saved-code *code*)2350 (setf *static-code* *code*)))2351 (when *declare-inline*2352 (setf *code* saved-code))2353 g))2354 2355 2379 (declaim (ftype (function (t &optional t) string) declare-object)) 2356 2380 (defun declare-object (obj &optional (obj-ref +lisp-object+) … … 2396 2420 g)) 2397 2421 2398 (defun declare-string (string)2399 (declare-with-hashtable2400 string *declared-strings* ht g2401 (let ((*code* *static-code*))2402 ;; constant: no need to *declare-inline*2403 (setf g (symbol-name (gensym "STR")))2404 (declare-field g +lisp-simple-string+ +field-access-private+)2405 (emit 'new +lisp-simple-string-class+)2406 (emit 'dup)2407 (emit 'ldc (pool-string string))2408 (emit-invokespecial-init +lisp-simple-string-class+ (list +java-string+))2409 (emit 'putstatic *this-class* g +lisp-simple-string+)2410 (setf *static-code* *code*)2411 (setf (gethash string ht) g))))2412 2413 2422 (defknown compile-constant (t t t) t) 2414 2423 (defun compile-constant (form target representation) … … 2420 2429 (emit-push-constant-int form)) 2421 2430 ((integerp form) 2422 (emit 'getstatic *this-class* (declare-integer form) +lisp-integer+) 2431 (emit 'getstatic *this-class* (externalize-object form) 2432 +lisp-integer+) 2423 2433 (emit-invokevirtual +lisp-object-class+ "intValue" nil "I")) 2424 2434 (t … … 2431 2441 (emit-push-constant-long form)) 2432 2442 ((integerp form) 2433 (emit 'getstatic *this-class* (declare-integer form) +lisp-integer+) 2443 (emit 'getstatic *this-class* (externalize-object form) 2444 +lisp-integer+) 2434 2445 (emit-invokevirtual +lisp-object-class+ "longValue" nil "J")) 2435 2446 (t … … 2476 2487 ((NIL))) 2477 2488 (cond ((integerp form) 2478 (emit 'getstatic *this-class* (declare-integer form) +lisp-integer+)) 2489 (emit 'getstatic *this-class* (externalize-object form) 2490 +lisp-integer+)) 2479 2491 ((typep form 'single-float) 2480 2492 (emit 'getstatic *this-class* 2481 ( declare-float form) +lisp-single-float+))2493 (externalize-object form) +lisp-single-float+)) 2482 2494 ((typep form 'double-float) 2483 2495 (emit 'getstatic *this-class* 2484 ( declare-doubleform) +lisp-double-float+))2496 (externalize-object form) +lisp-double-float+)) 2485 2497 ((numberp form) 2486 2498 ;; A number, but not a fixnum. … … 2490 2502 (if *file-compilation* 2491 2503 (emit 'getstatic *this-class* 2492 ( declare-stringform) +lisp-simple-string+)2504 (externalize-object form) +lisp-simple-string+) 2493 2505 (emit 'getstatic *this-class* 2494 2506 (declare-object form) +lisp-object+))) … … 2501 2513 ((characterp form) 2502 2514 (emit 'getstatic *this-class* 2503 ( declare-characterform) +lisp-character+))2515 (externalize-object form) +lisp-character+)) 2504 2516 ((or (hash-table-p form) (typep form 'generic-function)) 2505 2517 (emit 'getstatic *this-class* … … 2512 2524 ((packagep form) 2513 2525 (let ((g (if *file-compilation* 2514 ( declare-packageform)2526 (externalize-object form) 2515 2527 (declare-object form)))) 2516 2528 (emit 'getstatic *this-class* g +lisp-object+))) -
trunk/abcl/src/org/armedbear/lisp/jvm.lisp
r12421 r12690 83 83 (defvar *static-code* ()) 84 84 85 (defvar * declared-symbols* nil)85 (defvar *externalized-objects* nil) 86 86 (defvar *declared-functions* nil) 87 (defvar *declared-strings* nil)88 (defvar *declared-integers* nil)89 (defvar *declared-floats* nil)90 (defvar *declared-doubles* nil)91 87 92 88 (defstruct (abcl-class-file (:constructor %make-abcl-class-file)) … … 102 98 methods 103 99 static-code 104 (symbols (make-hash-table :test 'eq)) 105 (functions (make-hash-table :test 'equal)) 106 (strings (make-hash-table :test 'eq)) 107 (integers (make-hash-table :test 'eql)) 108 (floats (make-hash-table :test 'eql)) 109 (doubles (make-hash-table :test 'eql))) 100 objects ;; an alist of externalized objects and their field names 101 (functions (make-hash-table :test 'equal)) ;; because of (SETF ...) functions 102 ) 110 103 111 104 (defun class-name-from-filespec (filespec) … … 144 137 (let ((var (gensym))) 145 138 `(let* ((,var ,class-file) 146 (*pool* (abcl-class-file-pool ,var)) 147 (*pool-count* (abcl-class-file-pool-count ,var)) 148 (*pool-entries* (abcl-class-file-pool-entries ,var)) 149 (*fields* (abcl-class-file-fields ,var)) 150 (*static-code* (abcl-class-file-static-code ,var)) 151 (*declared-symbols* (abcl-class-file-symbols ,var)) 152 (*declared-functions* (abcl-class-file-functions ,var)) 153 (*declared-strings* (abcl-class-file-strings ,var)) 154 (*declared-integers* (abcl-class-file-integers ,var)) 155 (*declared-floats* (abcl-class-file-floats ,var)) 156 (*declared-doubles* (abcl-class-file-doubles ,var))) 139 (*pool* (abcl-class-file-pool ,var)) 140 (*pool-count* (abcl-class-file-pool-count ,var)) 141 (*pool-entries* (abcl-class-file-pool-entries ,var)) 142 (*fields* (abcl-class-file-fields ,var)) 143 (*static-code* (abcl-class-file-static-code ,var)) 144 (*externalized-objects* (abcl-class-file-objects ,var)) 145 (*declared-functions* (abcl-class-file-functions ,var))) 157 146 (progn ,@body) 158 147 (setf (abcl-class-file-pool ,var) *pool* … … 161 150 (abcl-class-file-fields ,var) *fields* 162 151 (abcl-class-file-static-code ,var) *static-code* 163 (abcl-class-file-symbols ,var) *declared-symbols* 164 (abcl-class-file-functions ,var) *declared-functions* 165 (abcl-class-file-strings ,var) *declared-strings* 166 (abcl-class-file-integers ,var) *declared-integers* 167 (abcl-class-file-floats ,var) *declared-floats* 168 (abcl-class-file-doubles ,var) *declared-doubles*)))) 152 (abcl-class-file-objects ,var) *externalized-objects* 153 (abcl-class-file-functions ,var) *declared-functions*)))) 169 154 170 155 (defstruct compiland
Note: See TracChangeset
for help on using the changeset viewer.