comparison src/main/gov/nasa/jpf/vm/serialize/DynamicAbstractionSerializer.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:61d41facf527
1 /*
2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
4 * All rights reserved.
5 *
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0.
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package gov.nasa.jpf.vm.serialize;
19
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPF;
22 import gov.nasa.jpf.ListenerAdapter;
23 import gov.nasa.jpf.util.FieldSpec;
24 import gov.nasa.jpf.util.FinalBitSet;
25 import gov.nasa.jpf.util.JPFLogger;
26 import gov.nasa.jpf.util.StringSetMatcher;
27 import gov.nasa.jpf.vm.ArrayFields;
28 import gov.nasa.jpf.vm.ClassInfo;
29 import gov.nasa.jpf.vm.ClassLoaderInfo;
30 import gov.nasa.jpf.vm.ElementInfo;
31 import gov.nasa.jpf.vm.FieldInfo;
32 import gov.nasa.jpf.vm.Fields;
33 import gov.nasa.jpf.vm.MJIEnv;
34 import gov.nasa.jpf.vm.VM;
35 import gov.nasa.jpf.vm.MethodInfo;
36 import gov.nasa.jpf.vm.ReferenceArrayFields;
37 import gov.nasa.jpf.vm.StackFrame;
38 import gov.nasa.jpf.vm.StaticElementInfo;
39 import gov.nasa.jpf.vm.Statics;
40
41 import java.util.LinkedList;
42 import java.util.List;
43
44 /**
45 * a serializer that uses Abstraction objects stored as field attributes to
46 * obtain the values to hash.
47 */
48 public class DynamicAbstractionSerializer extends FilteringSerializer {
49
50 static JPFLogger logger = JPF.getLogger("gov.nasa.jpf.vm.serialize.DynamicAbstractionSerializer");
51
52 static class FieldAbstraction {
53 FieldSpec fspec;
54 Abstraction abstraction;
55
56 FieldAbstraction(FieldSpec f, Abstraction a) {
57 fspec = f;
58 abstraction = a;
59 }
60 }
61
62 public class Attributor extends ListenerAdapter {
63
64 @Override
65 public void classLoaded(VM vm, ClassInfo loadedClass) {
66
67 if (!loadedClass.isArray() && !loadedClass.isPrimitive()) {
68
69 if (!fieldAbstractions.isEmpty()) {
70 for (FieldInfo fi : loadedClass.getDeclaredInstanceFields()) {
71 for (FieldAbstraction fabs : fieldAbstractions) {
72 if (fabs.fspec.matches(fi)) {
73 logger.info("setting instance field abstraction ", fabs.abstraction.getClass().getName(),
74 " for field ", fi.getFullName());
75 fi.addAttr(fabs.abstraction);
76 }
77 }
78 }
79
80 for (FieldInfo fi : loadedClass.getDeclaredStaticFields()) {
81 for (FieldAbstraction fabs : fieldAbstractions) {
82 if (fabs.fspec.matches(fi)) {
83 logger.info("setting static field abstraction ", fabs.abstraction.getClass().getName(),
84 " for field ", fi.getFullName());
85 fi.addAttr(fabs.abstraction);
86 }
87 }
88 }
89 }
90 }
91 }
92 }
93
94 protected StringSetMatcher includeClasses = null; // means all
95 protected StringSetMatcher excludeClasses = null; // means none
96 protected StringSetMatcher includeMethods = null;
97 protected StringSetMatcher excludeMethods = null;
98
99 List<FieldAbstraction> fieldAbstractions;
100
101 protected boolean processAllObjects;
102 protected boolean declaredFieldsOnly;
103
104
105 public DynamicAbstractionSerializer(Config conf) {
106 processAllObjects = conf.getBoolean("das.all_objects", true);
107 declaredFieldsOnly = conf.getBoolean("das.declared_fields", false);
108
109 includeClasses = StringSetMatcher.getNonEmpty(conf.getStringArray("das.classes.include"));
110 excludeClasses = StringSetMatcher.getNonEmpty(conf.getStringArray("das.classes.exclude"));
111
112 includeMethods = StringSetMatcher.getNonEmpty(conf.getStringArray("das.methods.include"));
113 excludeMethods = StringSetMatcher.getNonEmpty(conf.getStringArray("das.methods.exclude"));
114
115 fieldAbstractions = getFieldAbstractions(conf);
116 }
117
118
119 protected List<FieldAbstraction> getFieldAbstractions(Config conf){
120 List<FieldAbstraction> list = null;
121
122 String[] fids = conf.getCompactTrimmedStringArray("das.fields");
123 for (String id : fids) {
124 String keyPrefix = "das." + id;
125 String fs = conf.getString(keyPrefix + ".field");
126 if (fs != null) {
127 FieldSpec fspec = FieldSpec.createFieldSpec(fs);
128 if (fspec != null) {
129 String aKey = keyPrefix + ".abstraction";
130 Abstraction abstraction = conf.getInstance(aKey, Abstraction.class);
131
132 logger.info("found field abstraction for ", fspec, " = ", abstraction.getClass().getName());
133
134 if (list == null){
135 list = new LinkedList<FieldAbstraction>();
136 }
137
138 list.add(new FieldAbstraction(fspec, abstraction));
139 }
140 } else {
141 logger.warning("no field spec for id: " + id);
142 }
143 }
144
145 return list;
146 }
147
148 @Override
149 public void attach (VM vm){
150 super.attach(vm);
151
152 if (fieldAbstractions != null){
153 Attributor attributor = new Attributor();
154 vm.addListener(attributor);
155 }
156 }
157
158
159 // note that we don't add the reference value here
160 @Override
161 public void processReference(int objref) {
162 if (objref != MJIEnv.NULL) {
163 ElementInfo ei = heap.get(objref);
164 if (!ei.isMarked()) { // only add objects once
165 ei.setMarked();
166 refQueue.add(ei);
167 }
168 }
169
170 // we DON'T add the reference value to the buffer here
171 }
172
173 protected void processField(Fields fields, int[] slotValues, FieldInfo fi, FinalBitSet filtered) {
174 int off = fi.getStorageOffset();
175 if (!filtered.get(off)) {
176 Abstraction a = fi.getAttr(Abstraction.class);
177 if (a != null) {
178 if (fi.is1SlotField()) {
179 if (fi.isReference()) {
180 int ref = fields.getReferenceValue(off);
181 buf.add(a.getAbstractObject(ref));
182
183 if (a.traverseObject(ref)) {
184 processReference(ref);
185 }
186
187 } else if (fi.isFloatField()) {
188 buf.add(a.getAbstractValue(fields.getFloatValue(off)));
189 } else {
190 buf.add(a.getAbstractValue(fields.getIntValue(off)));
191 }
192 } else { // double or long
193 if (fi.isLongField()) {
194 buf.add(a.getAbstractValue(fields.getLongValue(off)));
195 } else { // got to be double
196 buf.add(a.getAbstractValue(fields.getDoubleValue(off)));
197 }
198 }
199
200 } else { // no abstraction, fall back to concrete values
201 if (fi.is1SlotField()) {
202 if (fi.isReference()) {
203 int ref = slotValues[off];
204 buf.add(ref);
205 processReference(ref);
206
207 } else {
208 buf.add(slotValues[off]);
209 }
210
211 } else { // double or long
212 buf.add(slotValues[off]);
213 buf.add(slotValues[off + 1]);
214 }
215 }
216 }
217 }
218
219 // non-ignored class
220 @Override
221 protected void processArrayFields(ArrayFields fields) {
222 buf.add(fields.arrayLength());
223
224 if (fields.isReferenceArray()) {
225 int[] values = fields.asReferenceArray();
226 for (int i = 0; i < values.length; i++) {
227 processReference(values[i]);
228 buf.add(values[i]);
229 }
230 } else {
231 fields.appendTo(buf);
232 }
233 }
234
235 // for ignored class, to get all live objects
236 protected void processNamedInstanceReferenceFields(ClassInfo ci, Fields fields) {
237 FinalBitSet filtered = getInstanceFilterMask(ci);
238 FinalBitSet refs = getInstanceRefMask(ci);
239 int[] slotValues = fields.asFieldSlots(); // for non-attributed fields
240
241 for (int i = 0; i < slotValues.length; i++) {
242 if (!filtered.get(i)) {
243 if (refs.get(i)) {
244 processReference(slotValues[i]);
245 }
246 }
247 }
248 }
249
250 // for ignored class, to get all live objects
251 protected void processNamedStaticReferenceFields(ClassInfo ci, Fields fields) {
252 FinalBitSet filtered = getStaticFilterMask(ci);
253 FinalBitSet refs = getStaticRefMask(ci);
254 int[] slotValues = fields.asFieldSlots(); // for non-attributed fields
255
256 for (int i = 0; i < slotValues.length; i++) {
257 if (!filtered.get(i)) {
258 if (refs.get(i)) {
259 processReference(slotValues[i]);
260 }
261 }
262 }
263 }
264
265 // for ignored class, to get all live objects
266 protected void processReferenceArray(ReferenceArrayFields fields) {
267 int[] slotValues = fields.asReferenceArray();
268 for (int i = 0; i < slotValues.length; i++) {
269 processReference(slotValues[i]);
270 }
271 }
272
273 // non-ignored class
274 @Override
275 protected void processNamedFields(ClassInfo ci, Fields fields) {
276 FinalBitSet filtered = getInstanceFilterMask(ci);
277 int nFields = ci.getNumberOfInstanceFields();
278 int[] slotValues = fields.asFieldSlots(); // for non-attributed fields
279
280 for (int i = 0; i < nFields; i++) {
281 FieldInfo fi = ci.getInstanceField(i);
282
283 if (declaredFieldsOnly && fi.getClassInfo() != ci) {
284 continue;
285 }
286
287 processField(fields, slotValues, fi, filtered);
288 }
289 }
290
291 // <2do> this should also allow abstraction of whole objects, so that
292 // we can hash combinations/relations of field values
293 @Override
294 public void process (ElementInfo ei) {
295 Fields fields = ei.getFields();
296 ClassInfo ci = ei.getClassInfo();
297
298 if (StringSetMatcher.isMatch(ci.getName(), includeClasses, excludeClasses)) {
299 buf.add(ci.getUniqueId());
300
301 if (fields instanceof ArrayFields) { // not filtered
302 processArrayFields((ArrayFields) fields);
303 } else { // named fields, potentially filtered & abstracted via attributes
304 processNamedFields(ci, fields);
305 }
306
307 } else { // ignored class
308 // we check for live non-ignored objects along all stack frames, so we should do the same for all objects
309 if (fields instanceof ArrayFields) {
310 if (fields instanceof ReferenceArrayFields) {
311 processReferenceArray((ReferenceArrayFields) fields);
312 }
313 } else {
314 processNamedInstanceReferenceFields(ci, fields);
315 }
316 }
317 }
318
319 @Override
320 protected void serializeFrame (StackFrame frame) {
321 MethodInfo mi = frame.getMethodInfo();
322
323 if (StringSetMatcher.isMatch(mi.getFullName(), includeMethods, excludeMethods)){
324 // <2do> should do frame abstraction here
325 super.serializeFrame(frame);
326
327 } else {
328 if (processAllObjects) {
329 frame.visitReferenceSlots(this);
330 }
331 }
332 }
333
334 @Override
335 protected void serializeClass (StaticElementInfo sei) {
336 ClassInfo ci = sei.getClassInfo();
337 Fields fields = sei.getFields();
338
339 if (StringSetMatcher.isMatch(ci.getName(), includeClasses, excludeClasses)) {
340 buf.add(sei.getStatus());
341
342 FinalBitSet filtered = getStaticFilterMask(ci);
343 int[] slotValues = fields.asFieldSlots();
344
345 for (FieldInfo fi : ci.getDeclaredStaticFields()) {
346 processField(fields, slotValues, fi, filtered);
347 }
348
349 } else {
350 // ignored class, but still process references to extract live objects
351 processNamedStaticReferenceFields(ci, fields);
352 }
353 }
354
355 @Override
356 protected void serializeClassLoaders(){
357 // we don't care about the number of classloaders
358
359 for (ClassLoaderInfo cl : ks.classLoaders) {
360 if(cl.isAlive()) {
361 serializeStatics( cl.getStatics());
362 }
363 }
364 }
365
366 @Override
367 protected void serializeStatics(Statics statics){
368 // we don't care about the number of statics entries
369
370 for (StaticElementInfo sei : statics.liveStatics()) {
371 serializeClass(sei);
372 }
373 }
374 }