00001 package gov.nasa.arc.ase.jpf.jvm;
00002
00003 import de.fub.bytecode.*;
00004 import de.fub.bytecode.classfile.*;
00005 import gov.nasa.arc.ase.util.PoolObject;
00006 import de.fub.bytecode.generic.*;
00007 import gov.nasa.arc.ase.jpf.*;
00008 import gov.nasa.arc.ase.jpf.jvm.reflection.Reflection;
00009 import gov.nasa.arc.ase.util.Debug;
00010 import gov.nasa.arc.ase.util.HashData;
00011 import gov.nasa.arc.ase.util.HashPool;
00012 import java.io.*;
00013 import java.util.*;
00014
00015 import gov.nasa.arc.ase.jpf.jvm.runtime.*;
00016
00017
00018 public class DynamicArea {
00019 static BitSet ZERO = new BitSet();
00020 Vector objects;
00021 Vector objinfo;
00022
00023
00024
00025
00026 BitSet objectChanged;
00027 BitSet objinfoChanged;
00028 private boolean anyObjectChanged;
00029 private boolean anyObjectInfoChanged;
00030
00031
00032
00033 int[] objectData;
00034 int[] objinfoData;
00035
00036
00037
00038
00039
00040
00041
00042 public BitSet isUsed = null;
00043
00044
00045
00046
00047 public DynamicArea() {
00048 objects = new Vector();
00049 objinfo = new Vector();
00050
00051
00052
00053 objectChanged = new BitSet();
00054 objinfoChanged = new BitSet();
00055 anyObjectChanged = false;
00056 anyObjectInfoChanged = false;
00057
00058
00059
00060
00061 objectData = new int[0];
00062 objinfoData = new int[0];
00063
00064 }
00065
00066
00067 public int arraylength(int objref) {
00068 return ((Fields)objects.get(objref)).getVariables().length;
00069 }
00070
00071
00072
00073
00074
00075 private void cloneObject(int index) {
00076
00077 if(!objectChanged.get(index)) {
00078 Object o = ((Fields)objects.get(index)).clone();
00079 objects.setElementAt(o, index);
00080
00081
00082
00083 objectChanged.set(index);
00084 anyObjectChanged = true;
00085 }
00086 }
00087
00088 private void cloneObjectInfo(int index) {
00089
00090 if(!objinfoChanged.get(index)) {
00091 Object o = ((ObjectInfo)objinfo.get(index)).clone();
00092 objinfo.setElementAt(o, index);
00093
00094
00095 objinfoChanged.set(index);
00096 anyObjectInfoChanged = true;
00097 }
00098 }
00099
00100 public long[] convert2Array(int objref) {
00101
00102 int length = arraylength(objref);
00103
00104
00105
00106
00107
00108
00109 long[] result = new long[length];
00110 for(int i = 0; i < length; i++) {
00111 result[i] = getValue(objref, i);
00112
00113
00114
00115 }
00116
00117
00118 return result;
00119 }
00120
00121
00122
00123 public String convert2String(int objref) {
00124
00125 int value = (int)getValue(objref, "value");
00126
00127
00128 int length = (int)getValue(objref, "count");
00129
00130
00131
00132
00133
00134
00135 StringBuffer sb = new StringBuffer();
00136
00137 for(int i = 0; i < length; i++)
00138 sb.append((char)getValue(value, i));
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 return sb.toString();
00149 }
00150 public void gc(KernelState ks) {
00151 List o = objects;
00152
00153 int length = o.size() - 1;
00154 while(length > 0 && o.get(length) == null)
00155 length--;
00156 length++;
00157
00158 isUsed = new BitSet(length);
00159
00160 List threads = ks.threads;
00161 int nthreads = threads.size();
00162
00163
00164
00165
00166 for(int i = 0; i < nthreads; i++) {
00167 ThreadInfo th = (ThreadInfo)threads.get(i);
00168 th.mark(this);
00169 }
00170 ks.static_area.mark(this);
00171
00172
00173
00174
00175
00176 int count = 0;
00177
00178 for(int i = 0; i < length; i++)
00179 if(!isUsed.get(i)) {
00180 if(objects.get(i) != null) {
00181 count++;
00182
00183
00184
00185
00186 objects.setElementAt(null, i);
00187 objinfo.setElementAt(null, i);
00188 anyObjectChanged = true;
00189 anyObjectInfoChanged = true;
00190 objectChanged.set(i);
00191 objinfoChanged.set(i);
00192 }
00193
00194
00195
00196
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206 Runner.GCs += count;
00207
00208 isUsed = null;
00209 }
00210
00211 public ClassInfo getClass(int objref) {
00212 return ((Fields)objects.get(objref)).getClassInfo();
00213 }
00214 public LockStatus getLockStatus(int objref) {
00215 return ((Fields)objects.get(objref)).getLockStatus();
00216 }
00217
00218
00219 public LockStatus getLockStatus(int objref, String fieldname) {
00220 return ((Fields)objects.get(objref)).getLockStatus(fieldname);
00221 }
00222
00223
00224 public Reflection getReflection(int objref) {
00225 Reflection r = (Reflection)getClass(objref).reflection.clone();
00226 r.setObjectReference(objref);
00227
00228 return r;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 public int[] getStoringData() {
00259
00260
00261 update();
00262
00263
00264 int ol = objectData.length;
00265 int il = objinfoData.length;
00266
00267
00268
00269
00270
00271 int[] data = new int[ol + il];
00272
00273
00274 System.arraycopy(objectData, 0, data, 0, ol);
00275 System.arraycopy(objinfoData, 0, data, ol, il);
00276
00277 return data;
00278 }
00279 public long getValue(int objref, int index) {
00280 return ((Fields)objects.get(objref)).getValue(index);
00281 }
00282
00283
00284
00285
00286 public long getValue(int objref, String fieldname) {
00287 return ((Fields)objects.get(objref)).getValue(fieldname);
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 public int getVariableType(int objref, int index) {
00303 return ((Fields)objects.get(objref)).getClassInfo().getFieldType(index);
00304 }
00305 public int getVariableType(int objref, String fname) {
00306 return ((Fields)objects.get(objref)).getClassInfo().getFieldType(fname);
00307 }
00308 public void hash(HashData hd) {
00309 for(int i = 0, l = objects.size(); i < l; i++) {
00310 Object o = objects.get(i);
00311 if(o != null) hd.add(o.hashCode());
00312 }
00313
00314 for(int i = 0, l = objinfo.size(); i < l; i++) {
00315 Object o = objinfo.get(i);
00316 if(o != null) hd.add(o.hashCode());
00317 }
00318 }
00319 public int hashCode() {
00320 HashData hd = new HashData();
00321
00322 for(int i = 0, l = objects.size(); i < l; i++) {
00323 Object o = objects.get(i);
00324 if(o != null) hd.add(o.hashCode());
00325 }
00326
00327 for(int i = 0, l = objinfo.size(); i < l; i++) {
00328 Object o = objinfo.get(i);
00329 if(o != null) hd.add(o.hashCode());
00330 }
00331
00332 return hd.getValue();
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 private int indexFor(ThreadInfo th) {
00448
00449
00450
00451
00452
00453
00454
00455
00456 DynamicMapIndex i = new DynamicMapIndex(th.getPC(),
00457
00458
00459
00460 0);
00461
00462 if(!DynamicMap.hasEntry(i)) return DynamicMap.addEntry(i);
00463
00464 int index = DynamicMap.getEntry(i);
00465
00466 if(index < objects.size())
00467 while(objects.get(index) != null) {
00468 i.next();
00469
00470 if(!DynamicMap.hasEntry(i)) return DynamicMap.addEntry(i);
00471 index = DynamicMap.getEntry(i);
00472 if(index >= objects.size()) return index;
00473 }
00474
00475 return index;
00476
00477 }
00478
00479 public boolean instanceOfClass(int objref, String classname) {
00480 Fields f = (Fields)objects.get(objref);
00481 if(f == null) return false;
00482
00483
00484 ClassInfo ci = f.getClassInfo();
00485
00486 if (ci == null) {
00487 Debug.println(Debug.ERROR, "ci field for object " + objref + " is null");
00488 System.exit(0);
00489 }
00490
00491
00492 while (ci != null)
00493
00494 if (ci.getClassName().equals(classname))
00495 return true;
00496 else
00497
00498 ci = ci.getSuperClassInfo();
00499
00500
00501 return false;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 public boolean isFieldRef(int objref, String fieldname) {
00585 return ((Fields)objects.get(objref)).isRef(fieldname);
00586 }
00587
00588
00589 public void log() {
00590 Debug.println(Debug.MESSAGE, "DA");
00591 for(int i = 0; i < objects.size(); i++) {
00592 Fields f = (Fields)objects.get(i);
00593 if(f != null) {
00594
00595
00596
00597 Debug.println(Debug.MESSAGE, " #" + i);
00598
00599 f.log(i, true);
00600 }
00601 }
00602 }
00603 public void mark(int objref) {
00604
00605
00606
00607 if(objref == -1) return;
00608
00609 if(isUsed.get(objref)) return;
00610 isUsed.set(objref);
00611
00612 ((Fields)objects.get(objref)).mark(this);
00613 }
00614
00615
00616
00617 public boolean monitorCheckLock(int objref, ThreadInfo th) {
00618 return ((ObjectInfo)objinfo.get(objref)).getMonitor().checkLock(th);
00619 }
00620 public boolean monitorCheckLockAfterNotified(int objref, ThreadInfo th) {
00621 return ((ObjectInfo)objinfo.get(objref)).getMonitor().checkLockAfterNotified(th);
00622 }
00623 public boolean monitorLock(int objref, ThreadInfo th) {
00624
00625
00626 cloneObjectInfo(objref);
00627
00628
00629 return ((ObjectInfo)objinfo.get(objref)).getMonitor().lock(th, new ObjRef(objref));
00630 }
00631 public boolean monitorLockAfterNotified(int objref, ThreadInfo th) {
00632
00633
00634 cloneObjectInfo(objref);
00635
00636
00637 return ((ObjectInfo)objinfo.get(objref)).getMonitor().lockAfterNotified(th, new ObjRef(objref));
00638 }
00639 public int monitorLockCount(int objref) {
00640 return ((ObjectInfo)objinfo.get(objref)).getMonitor().getLockCount();
00641 }
00642 public int monitorLockingThread(int objref) {
00643 return ((ObjectInfo)objinfo.get(objref)).getMonitor().getLockingThread();
00644 }
00645 public void monitorNotify(int objref, KernelState ks, Scheduler sch) {
00646
00647
00648 cloneObjectInfo(objref);
00649
00650
00651 ((ObjectInfo)objinfo.get(objref)).getMonitor().notify(ks, sch);
00652 }
00653 public void monitorNotifyAll(int objref, KernelState ks) {
00654
00655
00656 cloneObjectInfo(objref);
00657
00658
00659 ((ObjectInfo)objinfo.get(objref)).getMonitor().notifyAll(ks);
00660 }
00661 public void monitorUnlock(int objref, ThreadInfo th) {
00662
00663
00664 cloneObjectInfo(objref);
00665
00666
00667 ((ObjectInfo)objinfo.get(objref)).getMonitor().unlock(th, new ObjRef(objref));
00668 }
00669 public void monitorWait(int objref, ThreadInfo th) {
00670
00671
00672 cloneObjectInfo(objref);
00673
00674
00675 ((ObjectInfo)objinfo.get(objref)).getMonitor().wait(th, new ObjRef(objref));
00676 }
00677 public List monitorWaitingThreads(int objref) {
00678 return (List)((ArrayList)((ObjectInfo)objinfo.get(objref)).getMonitor().getWaitingThreads()).clone();
00679 }
00680
00681
00682 public int newArrayObject(String type, int size, ThreadInfo th) {
00683 Fields fields = new Fields(null, size);
00684 ObjectInfo oi;
00685
00686
00687 oi = new ObjectInfo();
00688
00689
00690
00691
00692
00693 int index = indexFor(th);
00694
00695
00696
00697 if (index >= objects.size()) {
00698 objects.setSize(index+10);
00699 objinfo.setSize(index+10);
00700 }
00701
00702
00703
00704 objects.setElementAt(fields, index);
00705 objinfo.setElementAt(oi, index);
00706
00707
00708
00709 objectChanged.set(index);
00710 objinfoChanged.set(index);
00711 anyObjectChanged= true;
00712 anyObjectInfoChanged = true;
00713
00714
00715
00716 for(int i = 0; i < size; i++) {
00717 fields.setValue(i, Types.newValue(type));
00718
00719 if(Types.isReference(type))
00720 fields.setValueRef(i);
00721
00722 }
00723
00724
00725 return index;
00726 }
00727
00728
00729 public int newClassObject(String str, ThreadInfo th) {
00730 JPFVM jpfvm = JPFVM.getJPFVM();
00731
00732
00733 ClassInfo ci = jpfvm.getClass("java.lang.Class");
00734
00735
00736 int objref = newObject(ci, th);
00737
00738
00739
00740
00741 return objref;
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 public int newObject(ClassInfo ci, ThreadInfo th) {
00776
00777
00778
00779
00780
00781
00782 Fields fs = ci.createFields();
00783 ObjectInfo oi;
00784
00785
00786 oi = new ObjectInfo();
00787
00788
00789 int index = indexFor(th);
00790
00791
00792
00793 if (index >= objects.size()) {
00794 objects.setSize(index+10);
00795 objinfo.setSize(index+10);
00796 }
00797
00798
00799
00800 objects.setElementAt(fs, index);
00801 objinfo.setElementAt(oi, index);
00802
00803
00804
00805 objectChanged.set(index);
00806 objinfoChanged.set(index);
00807 anyObjectChanged= true;
00808 anyObjectInfoChanged = true;
00809
00810
00811
00812
00813
00814
00815
00816 return index;
00817 }
00818
00819
00820
00821
00822 public int newStringObject(String str, ThreadInfo th) {
00823 JPFVM jpfvm = JPFVM.getJPFVM();
00824
00825
00826 ClassInfo ci = jpfvm.getClass("java.lang.String");
00827
00828
00829 int objref = newObject(ci, th);
00830
00831
00832 int value = newArrayObject("C", str.length(), th);
00833
00834
00835 setValue(objref, "value", value);
00836 for(int i = 0, s = str.length(); i < s; i++)
00837 setValue(value, i, str.charAt(i));
00838 setValue(objref, "offset", 0);
00839 setValue(objref, "count", str.length());
00840
00841
00842 return objref;
00843 }
00844
00845 public void revertTo(int[] data) {
00846 int len = data.length / 2;
00847
00848 int[] nObjectData = new int[len];
00849 int[] nObjinfoData = new int[len];
00850
00851 System.arraycopy(data, 0, nObjectData, 0, len);
00852 System.arraycopy(data, len, nObjinfoData, 0, len);
00853
00854 int s = objectData.length;
00855
00856 if (s >= len) {
00857 for (int idx = 0; idx < len; idx++) {
00858 if(nObjectData[idx] != objectData[idx])
00859 objects.setElementAt(
00860 VirtualMachine.fieldsPool.getObject(nObjectData[idx]),
00861 idx);
00862 if(nObjinfoData[idx] != objinfoData[idx])
00863 objinfo.setElementAt(
00864 VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00865 idx);
00866 }
00867 objects.setSize(len);
00868 objinfo.setSize(len);
00869 } else {
00870 for (int idx = 0; idx < s; idx++) {
00871 if(nObjectData[idx] != objectData[idx])
00872 objects.setElementAt(
00873 VirtualMachine.fieldsPool.getObject(nObjectData[idx]),
00874 idx);
00875 if(nObjinfoData[idx] != objinfoData[idx])
00876 objinfo.setElementAt(
00877 VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00878 idx);
00879 }
00880 objects.setSize(len);
00881 objinfo.setSize(len);
00882 for (int idx = s; idx < len; idx++) {
00883 objects.setElementAt(
00884 VirtualMachine.fieldsPool.getObject(nObjectData[idx]),
00885 idx);
00886 objinfo.setElementAt(
00887 VirtualMachine.objectInfoPool.getObject(nObjinfoData[idx]),
00888 idx);
00889 }
00890 }
00891 objectData = nObjectData;
00892 objinfoData = nObjinfoData;
00893 }
00894 public void setValue(int objref, int index, long value) {
00895
00896 cloneObject(objref);
00897
00898 ((Fields)objects.get(objref)).setValue(index, value);
00899 }
00900 public void setValue(int objref, String fieldname, long value) {
00901
00902 cloneObject(objref);
00903
00904 ((Fields)objects.get(objref)).setValue(fieldname, value);
00905 }
00906
00907
00908
00909 private void update() {
00910 if (anyObjectChanged) {
00911
00912 updateObjects();
00913
00914
00915 objectChanged.and(ZERO);
00916 anyObjectChanged = false;
00917 }
00918
00919 if (anyObjectInfoChanged) {
00920
00921 updateObjectInfos();
00922
00923
00924 objinfoChanged.and(ZERO);
00925 anyObjectInfoChanged = false;
00926 }
00927 }
00928
00929 private void updateObjectInfos() {
00930
00931
00932 int size = objinfo.size();
00933 int old_size = objinfoData.length;
00934 int actual_size = -1;
00935
00936
00937
00938
00939
00940
00941
00942 int[] data = new int[size];
00943 for(int i = 0; i < size; i++) {
00944
00945 ObjectInfo o = (ObjectInfo)objinfo.get(i);
00946 if(o != null) {
00947
00948
00949 actual_size = i;
00950
00951 if (objinfoChanged.get(i)) {
00952
00953 HashPool.PoolEntry e = VirtualMachine.objectInfoPool.getEntry(o);
00954
00955
00956 objinfo.setElementAt(e.getObject(), i);
00957
00958 data[i] = e.getIndex();
00959 } else {
00960
00961
00962
00963
00964
00965 data[i] = objinfoData[i];
00966 }
00967 } else {
00968
00969 data[i] = 0;
00970 }
00971 }
00972
00973
00974
00975 objinfoData = new int[++actual_size];
00976 System.arraycopy(data, 0, objinfoData, 0, actual_size);
00977 }
00978
00979 private void updateObjects() {
00980
00981
00982 int size = objects.size();
00983 int old_size = objectData.length;
00984 int actual_size = -1;
00985
00986
00987
00988
00989
00990
00991
00992 int[] data = new int[size];
00993 for(int i = 0; i < size; i++) {
00994
00995 Fields o = (Fields)objects.get(i);
00996 if(o != null) {
00997
00998
00999 actual_size = i;
01000
01001 if (objectChanged.get(i)) {
01002
01003 HashPool.PoolEntry e = VirtualMachine.fieldsPool.getEntry(o);
01004
01005
01006 objects.setElementAt(e.getObject(), i);
01007
01008 data[i] = e.getIndex();
01009 } else {
01010
01011
01012
01013
01014
01015 data[i] = objectData[i];
01016 }
01017 } else {
01018
01019 data[i] = 0;
01020 }
01021 }
01022
01023
01024
01025 objectData = new int[++actual_size];
01026 System.arraycopy(data, 0, objectData, 0, actual_size);
01027 }
01028 }