1 package gov.nasa.jpf.jvm; 20 21 import gov.nasa.jpf.JPFException; 22 import gov.nasa.jpf.util.Debug; 23 import gov.nasa.jpf.util.HashData; 24 import gov.nasa.jpf.util.HashPool; 25 26 import java.util.HashMap ; 27 import java.util.Vector ; 28 29 36 public abstract class ElementInfo implements Storable, Reference, Cloneable { 37 static final int storingDataLength = 3; 38 39 protected static HashPool fieldsPool = new HashPool(); 40 41 protected static HashPool monitorPool = new HashPool(); 42 43 protected static HashPool racePool = new HashPool(); 44 45 protected Fields fields; 46 47 protected Monitor monitor; 48 49 protected Area area; 50 51 protected int index; 52 53 public static final int ATTR_NONE = 0x0; 55 56 public static final int ATTR_PROP_MASK = 0x0000ffff; 57 58 60 public static final int ATTR_TSHARED = 0x1; 65 public static final int ATTR_IMMUTABLE = 0x2; 73 public static final int ATTR_NO_PROMOTE = 0x4; 75 76 78 public static final int ATTR_SINGLE_WRITER = 0x10000; 81 82 public static final int ATTR_NO_PROPAGATE = 0x20000; 84 85 public static final int ATTR_PROTECTED = 0x40000; 88 89 public static final int ATTR_PINDOWN = 0x80000; 91 92 protected int attributes; 103 104 108 protected int fIndex = -1; 109 110 protected int mIndex = -1; 111 112 static HashMap lockDiscipline = new HashMap (); 113 114 public ElementInfo(Fields f, Monitor m) { 115 fields = f; 116 monitor = m; 117 118 attributes = f.getClassInfo().getElementInfoAttrs(); 119 } 120 121 protected ElementInfo() { 122 } 123 124 public String toString() { 125 return (getClassInfo().getName() + '@' + index); 126 } 127 128 public FieldLockInfo getFieldLockInfo(String fid) { 129 return (FieldLockInfo) lockDiscipline.get(fid); 130 } 131 132 public void setFieldLockInfo(String fid, FieldLockInfo flInfo) { 133 lockDiscipline.put(fid, flInfo); 134 } 135 136 139 boolean hasRefField(int objRef) { 140 return fields.hasRefField(objRef); 141 } 142 143 void setShared() { 144 attributes |= ATTR_TSHARED; 145 } 146 147 150 void setShared(int attrMask) { 151 attributes |= (attrMask & ATTR_TSHARED); 152 } 153 154 164 void markRecursive(int tid, int attrMask) { 165 DynamicArea heap = DynamicArea.getHeap(); 166 int i, n; 167 168 if (isArray()) { 169 if (fields.isReferenceArray()) { 170 n = fields.arrayLength(); 171 for (i = 0; i < n; i++) { 172 heap.markRecursive(fields.getIntValue(i), tid, attributes, attrMask, 173 null); 174 } 175 } 176 } else { 177 ClassInfo ci = getClassInfo(); 178 boolean isWeakRef = ci.isWeakReference(); 179 180 do { 181 n = ci.getNumberOfDeclaredInstanceFields(); 182 boolean isRef = isWeakRef && ci.isRefClass(); 184 for (i = 0; i < n; i++) { 185 FieldInfo fi = ci.getDeclaredInstanceField(i); 186 if (fi.isReference()) { 187 if ((i == 0) && isRef) { 188 heap.registerWeakReference(fields); 192 } else { 193 194 heap.markRecursive(fields 202 .getReferenceValue(fi.getStorageOffset()), tid, attributes, 203 attrMask, fi); 204 } 205 } 206 } 207 ci = ci.getSuperClass(); 208 } while (ci != null); 209 } 210 } 211 212 boolean hasEqualPropagatedAttributes(int refAttrs, int attrMask) { 213 int mask = ATTR_PROP_MASK & attrMask; 214 return ((attributes & mask) == (refAttrs & mask)); 215 } 216 217 void propagateAttributes(int refAttr, int attrMask) { 218 attributes |= ((refAttr & attrMask) & ATTR_PROP_MASK); 219 } 220 221 public boolean isShared() { 222 return ((attributes & ATTR_TSHARED) != 0); 223 } 224 225 public boolean isImmutable() { 226 return ((attributes & ATTR_IMMUTABLE) != 0); 227 } 228 229 public boolean isSchedulingRelevant() { 230 return ((attributes & (ATTR_TSHARED | ATTR_IMMUTABLE)) == ATTR_TSHARED); 232 } 233 234 237 public boolean needsAttributePropagationFrom(ElementInfo ei) { 238 int a = attributes; 239 int o = ei.attributes; 240 241 if (a != o) { 242 if ((o & ATTR_PROP_MASK) > (a & ATTR_PROP_MASK)) 243 return true; 244 245 for (int i = 0; i < 16; i++, o >>= 1, a >>= 1) { 246 if ((o & 0x1) > (a & 0x1)) { 247 return true; 248 } 249 } 250 } 251 252 return false; 253 } 254 255 public void setArea(Area newArea) { 256 area = newArea; 257 } 258 259 public Area getArea() { 260 return area; 261 } 262 263 264 public boolean equals(Object other) { 265 if (getClass() != other.getClass()) 266 return false; 267 268 ElementInfo ei = (ElementInfo) other; 269 return fields.equals(ei.fields); 270 } 271 272 public ClassInfo getClassInfo() { 273 return fields.getClassInfo(); 274 } 275 276 abstract protected FieldInfo getFieldInfo(String clsBase, String fname); 277 278 abstract protected ElementInfo getElementInfo(ClassInfo ci); 279 280 protected FieldInfo getFieldInfo(String fname) { 281 return getFieldInfo(null, fname); 282 } 283 284 public int getIntField(String fname) { 285 return getIntField(fname, null); 286 } 287 288 public long getLongField(String fname) { 289 return getLongField(fname, null); 290 } 291 292 public void setIntField(FieldInfo fi, int value) { 293 ElementInfo ei = getElementInfo(fi.getClassInfo()); 298 if (!fi.isReference()) { 299 ei.cloneFields().setIntValue(fi.getStorageOffset(), value); 300 } else { 301 throw new JPFException("reference field: " + fi.getName()); 302 } 303 } 304 305 public void setIntField(String fname, String clsBase, int value) { 306 setIntField(getFieldInfo(clsBase, fname), value); 307 } 308 309 public void setIntField(String fname, int value) { 310 setIntField(fname, null, value); 311 } 312 313 public void setLongField(String fname, long value) { 314 FieldInfo fi = getFieldInfo(fname); 315 ElementInfo ei = getElementInfo(fi.getClassInfo()); 316 ei.cloneFields().setLongValue(fi.getStorageOffset(), value); 317 } 318 319 void updateReachability(int oldRef, int newRef) { 320 ThreadInfo ti = ThreadInfo.getCurrent(); if ((ti == null) || ti.isInCtor() || !ti.usePor()) { 323 return; 324 } 325 326 if (oldRef != newRef) { 327 DynamicArea heap = DynamicArea.getHeap(); 328 ElementInfo oei, nei; 329 330 if (isShared()) { 331 if (oldRef != -1) { 332 oei = heap.get(oldRef); 333 if (!oei.isImmutable()) { heap.analyzeHeap(false); return; 338 } 339 } 340 341 if (newRef != -1) { 342 nei = heap.get(newRef); 343 if (!nei.isShared() && !nei.isImmutable()) { 344 nei.setShared(); 347 heap.initGc(); nei.markRecursive(ti.getIndex(), ATTR_PROP_MASK); 349 } 350 } 351 } else { if (newRef != -1) { 353 nei = heap.get(newRef); 354 if (nei.isSchedulingRelevant()) { heap.analyzeHeap(false); 357 } 358 } 359 } 360 } 361 362 if (oldRef != -1) { 363 JVM.getVM().getSystemState().activateGC(); } 366 } 367 368 public void setReferenceField(FieldInfo fi, int value) { 369 ElementInfo ei = getElementInfo(fi.getClassInfo()); Fields f = ei.cloneFields(); 372 int off = fi.getStorageOffset(); 373 374 if (fi.isReference()) { 375 int oldValue = f.getReferenceValue(off); 376 f.setReferenceValue(off, value); 377 updateReachability(oldValue, value); 378 } else { 379 throw new JPFException("not a reference field: " + fi.getName()); 380 } 381 } 382 383 public void setReferenceField(String fname, String clsBase, int value) { 384 setReferenceField(getFieldInfo(clsBase, fname), value); 385 } 386 387 public void setReferenceField(String fname, int value) { 388 setReferenceField(fname, null, value); 389 } 390 391 public int getReferenceField(String fname, String clsBase) { 392 FieldInfo fi = getFieldInfo(clsBase, fname); 393 ElementInfo ei = getElementInfo(fi.getClassInfo()); 394 395 if (!fi.isReference()) { 396 throw new JPFException("not a reference field: " + fi.getName()); 397 } 398 return ei.fields.getIntValue(fi.getStorageOffset()); 399 } 400 401 public int getReferenceField(String fname) { 402 return getReferenceField(fname, null); 403 } 404 405 public int getIntField(String fname, String clsBase) { 406 FieldInfo fi = getFieldInfo(clsBase, fname); 409 ElementInfo ei = getElementInfo(fi.getClassInfo()); 410 return ei.fields.getIntValue(fi.getStorageOffset()); 411 } 412 413 public void setLongField(String fname, String clsBase, long value) { 414 FieldInfo fi = getFieldInfo(clsBase, fname); 415 ElementInfo ei = getElementInfo(fi.getClassInfo()); 416 ei.cloneFields().setLongValue(fi.getStorageOffset(), value); 417 } 418 419 public long getLongField(String fname, String clsBase) { 420 FieldInfo fi = getFieldInfo(clsBase, fname); 421 ElementInfo ei = getElementInfo(fi.getClassInfo()); 422 return ei.fields.getLongValue(fi.getStorageOffset()); 423 } 424 425 public boolean getBooleanField(String fname, String refType) { 426 FieldInfo fi = getFieldInfo(refType, fname); 427 ElementInfo ei = getElementInfo(fi.getClassInfo()); 428 return ei.fields.getBooleanValue(fi.getStorageOffset()); 429 } 430 431 public byte getByteField(String fname, String refType) { 432 FieldInfo fi = getFieldInfo(refType, fname); 433 ElementInfo ei = getElementInfo(fi.getClassInfo()); 434 return ei.fields.getByteValue(fi.getStorageOffset()); 435 } 436 437 public char getCharField(String fname, String refType) { 438 FieldInfo fi = getFieldInfo(refType, fname); 439 ElementInfo ei = getElementInfo(fi.getClassInfo()); 440 return ei.fields.getCharValue(fi.getStorageOffset()); 441 } 442 443 public double getDoubleField(String fname, String refType) { 444 FieldInfo fi = getFieldInfo(refType, fname); 445 ElementInfo ei = getElementInfo(fi.getClassInfo()); 446 return ei.fields.getDoubleValue(fi.getStorageOffset()); 447 } 448 449 public float getFloatField(String fname, String refType) { 450 FieldInfo fi = getFieldInfo(refType, fname); 451 ElementInfo ei = getElementInfo(fi.getClassInfo()); 452 return ei.fields.getFloatValue(fi.getStorageOffset()); 453 } 454 455 public short getShortField(String fname, String refType) { 456 FieldInfo fi = getFieldInfo(refType, fname); 457 ElementInfo ei = getElementInfo(fi.getClassInfo()); 458 return ei.fields.getShortValue(fi.getStorageOffset()); 459 } 460 461 private void checkFieldInfo(FieldInfo fi) { 462 if (!getClassInfo().isInstanceOf(fi.getClassInfo())) { 463 throw new JPFException("wrong FieldInfo : " + fi.getName() 464 + " , no such field in " + getClassInfo().getName()); 465 } 466 } 467 468 public int getIntField(FieldInfo fi) { 471 checkFieldInfo(fi); 472 return fields.getIntValue(fi.getStorageOffset()); 473 } 474 475 public long getLongField(FieldInfo fi) { 476 checkFieldInfo(fi); 477 return fields.getLongValue(fi.getStorageOffset()); 478 } 479 480 public void setLongField(FieldInfo fi, long val) { 481 checkFieldInfo(fi); 482 cloneFields().setLongValue(fi.getStorageOffset(), val); 483 } 484 485 private void checkArray(int index) { 486 if (!isArray()) { throw new JPFException( 488 "cannot access non array objects by index"); 489 } 490 if ((index < 0) || (index >= fields.size())) { 491 throw new JPFException("illegal array offset: " + index); 492 } 493 } 494 495 private void checkLongArray(int index) { 496 if (!isArray()) { throw new JPFException( 498 "cannot access non array objects by index"); 499 } 500 if ((index < 0) || (index >= (fields.size() - 1))) { 501 throw new JPFException("illegal long array offset: " + index); 502 } 503 } 504 505 private boolean isReferenceArray() { 506 return getClassInfo().isReferenceArray(); 507 } 508 509 public void setElement(int index, int value) { 511 checkArray(index); 512 if (isReferenceArray()) { 513 cloneFields().setReferenceValue(index, value); 514 } else { 515 cloneFields().setIntValue(index, value); 516 } 517 } 518 519 public void setLongElement(int index, long value) { 520 checkArray(index); 521 cloneFields().setLongValue(index*2, value); 522 } 523 524 public int getElement(int index) { 525 checkArray(index); 526 return fields.getIntValue(index); 527 } 528 529 public long getLongElement(int index) { 530 checkArray(index); 531 return fields.getLongValue(index*2); 532 } 533 534 public void setIndex(int newIndex) { 535 index = newIndex; 536 } 537 538 public int getIndex() { 539 return index; 540 } 541 542 public int getThisReference() { 543 return index; 544 } 545 546 public int getLockCount() { 547 return monitor.getLockCount(); 548 } 549 550 public int getLockingThread() { 551 return monitor.getLockingThread(); 552 } 553 554 public boolean isLocked() { 555 return (monitor.getLockCount() > 0); 556 } 557 558 public boolean isArray() { 559 return fields.isArray(); 560 } 561 562 public String getArrayType() { 563 if (!fields.isArray()) { 564 throw new JPFException("object is not an array"); 565 } 566 567 return Types.getArrayElementType(fields.getType()); 568 } 569 570 public Object getBacktrackData() { 571 return null; 572 } 573 574 public char getCharArrayElement(int index) { 575 return (char) getElement(index); 576 } 577 578 public int getIntArrayElement(int findex) { 579 return getElement(findex); 580 } 581 582 public long getLongArrayElement(int findex) { 583 return getLongElement(findex); 584 } 585 586 public boolean[] asBooleanArray() { 587 return fields.asBooleanArray(); 588 } 589 590 public byte[] asByteArray() { 591 return fields.asByteArray(); 592 } 593 594 public short[] asShortArray() { 595 return fields.asShortArray(); 596 } 597 598 public char[] asCharArray() { 599 return fields.asCharArray(); 600 } 601 602 public int[] asIntArray() { 603 return fields.asIntArray(); 604 } 605 606 public long[] asLongArray() { 607 return fields.asLongArray(); 608 } 609 610 public float[] asFloatArray() { 611 return fields.asFloatArray(); 612 } 613 614 public double[] asDoubleArray() { 615 return fields.asDoubleArray(); 616 } 617 618 public boolean isNull() { 619 return (index == -1); 620 } 621 622 public Reference getObjectField(String fname, String referenceType) { 623 return area.ks.da.get(getIntField(fname, referenceType)); 624 } 625 626 public int[] getStoringData() { 630 int[] data = new int[3]; 631 632 data[0] = getFieldsIndex(); 633 data[1] = getMonitorIndex(); 634 data[2] = attributes; 635 636 return data; 637 } 638 639 643 public int getStoringDataLength() { 644 return 3; 645 } 646 647 652 public int getHeapSize() { 653 return fields.getHeapSize(); 654 } 655 656 public String getStringField(String fname, String referenceType) { 657 int ref = getIntField(fname, referenceType); 658 659 if (ref != -1) { 660 ElementInfo ei = area.ks.da.get(ref); 661 if (ei == null) { 662 System.out.println("OUTCH: " + ref + ", this: " + index); 663 } 664 return ei.asString(); 665 } else { 666 return "null"; 667 } 668 } 669 670 public String getType() { 671 return fields.getType(); 672 } 673 674 public int[] getWaitingThreads() { 675 return monitor.getWaitingThreads(); 676 } 677 678 public int arrayLength() { 679 return fields.arrayLength(); 680 } 681 682 public String asString() { 683 if (!fields.getClassInfo().instanceOf("java.lang.String")) { 684 throw new JPFException("object is not of type java.lang.String"); 685 } 686 687 int value = getIntField("value", "java.lang.String"); 688 int length = getIntField("count", "java.lang.String"); 689 int offset = getIntField("offset", "java.lang.String"); 690 691 ElementInfo e = area.get(value); 692 693 StringBuffer sb = new StringBuffer (); 694 695 for (int i = offset; i < (offset + length); i++) { 696 sb.append((char) e.fields.getIntValue(i)); 697 } 698 699 return sb.toString(); 700 } 701 702 void updateLockingInfo() { 703 int tid = monitor.getLockingThread(); 704 if (tid != -1) { 705 ThreadInfo ti = area.ks.tl.get(tid); 710 ti.addLockedObject(this); 713 } 714 } 715 716 public void backtrackTo(ArrayOffset storing, Object backtrack) { 717 setFieldsIndex(storing.get()); 718 setMonitorIndex(storing.get()); 719 720 attributes = storing.get(); 721 722 updateLockingInfo(); 723 } 724 725 public boolean canLock(ThreadInfo th) { 726 return monitor.canLock(th); 727 } 728 729 public void checkArrayBounds(int index) 730 throws ArrayIndexOutOfBoundsExecutiveException { 731 if (outOfBounds(index)) { 732 throw new ArrayIndexOutOfBoundsExecutiveException(area.ks.ss 733 .getRunningThread().createAndThrowException( 734 "java.lang.ArrayIndexOutOfBoundsException")); 735 } 736 } 737 738 public void checkLongArrayBounds(int index) 739 throws ArrayIndexOutOfBoundsExecutiveException { 740 checkArrayBounds(index); 741 checkArrayBounds(index + 1); 742 } 743 744 public Object clone() { 745 try { 746 ElementInfo ei = (ElementInfo) super.clone(); 747 748 if (ei.fIndex == -1) { 749 ei.fields = (Fields) fields.clone(); 750 } 751 752 if (ei.mIndex == -1) { 753 ei.monitor = (Monitor) monitor.clone(); 754 } 755 756 area = null; 757 index = -1; 758 759 return ei; 760 } catch (CloneNotSupportedException e) { 761 e.printStackTrace(); 762 throw new InternalError ("should not happen"); 763 } 764 } 765 766 public void hash(HashData hd) { 767 fields.hash(hd); 768 monitor.hash(hd); 769 } 770 771 public int hashCode() { 772 HashData hd = new HashData(); 773 774 hash(hd); 775 776 return hd.getValue(); 777 } 778 779 public boolean instanceOf(String type) { 780 return Types.instanceOf(fields.getType(), type); 781 } 782 783 public void interrupt() { 784 area.ks.tl.locate(index).interrupt(); 785 } 786 787 public void lock(ThreadInfo th) { 788 cloneMonitor().lock(th, getRef()); 789 790 if (monitor.getLockCount() == 1) { 793 th.addLockedObject(this); 794 } 795 } 796 797 public void lockNotified(ThreadInfo th) { 798 cloneMonitor().lockNotified(th, getRef()); 799 800 th.addLockedObject(this); } 806 807 abstract public int getNumberOfFields(); 808 809 abstract public FieldInfo getFieldInfo(int i); 810 811 public void log() { 812 if (fIndex == -1) { 813 Debug.println(Debug.MESSAGE, "(fields have changed)"); 814 } 815 816 ClassInfo ci = getClassInfo(); 817 int n = getNumberOfFields(); 818 for (int i = 0; i < n; i++) { 819 FieldInfo fi = getFieldInfo(i); 820 Debug.println(Debug.MESSAGE, fi.getName() + ": " 821 + fi.valueToString(fields)); 822 } 823 824 if (mIndex == -1) { 825 Debug.println(Debug.MESSAGE, "(monitor has changed)"); 826 } 827 828 monitor.log(); 829 } 830 831 public void notifies() { 832 cloneMonitor().notify(area.ks.ss); 833 } 834 835 public void notifiesAll() { 836 cloneMonitor().notifyAll(area.ks.ss); 837 } 838 839 public boolean outOfBounds(int index) { 840 if (!fields.isArray()) { 841 throw new JPFException("object is not an array"); 842 } 843 844 return (index < 0 || index >= fields.size()); 845 } 846 847 853 public void pinDown(boolean keepAlive) { 854 if (keepAlive) { 855 attributes |= ATTR_PINDOWN; 856 } else { 857 attributes &= ~ATTR_PINDOWN; 858 } 859 } 860 861 864 public int storeDataTo(int[] buffer, int idx) { 865 buffer[idx++] = getFieldsIndex(); 866 buffer[idx++] = getMonitorIndex(); 867 buffer[idx] = attributes; 868 869 return 3; 870 } 871 872 public void unlock(ThreadInfo th) { 873 cloneMonitor().unlock(th, getRef()); 874 875 if (monitor.getLockCount() == 0) { 876 th.removeLockedObject(this); 877 } 878 } 879 880 public void wait(ThreadInfo th) { 881 cloneMonitor().wait(th, getRef()); 882 th.removeLockedObject(this); } 884 885 protected void setFieldsIndex(int index) { 886 if (fIndex == index) { 887 return; 888 } 889 890 fIndex = index; 891 fields = (Fields) fieldsPool.getObject(index); 892 } 893 894 protected int getFieldsIndex() { 895 if (fIndex != -1) { 896 return fIndex; 897 } 898 899 HashPool.PoolEntry e = fieldsPool.getEntry(fields); 900 fields = (Fields) e.getObject(); 901 902 return fIndex = e.getIndex(); 903 } 904 905 protected void setMonitorIndex(int index) { 906 if (mIndex == index) { 907 return; 908 } 909 910 mIndex = index; 911 monitor = (Monitor) monitorPool.getObject(index); 912 } 913 914 protected int getMonitorIndex() { 915 if (mIndex != -1) { 916 return mIndex; 917 } 918 919 HashPool.PoolEntry e = monitorPool.getEntry(monitor); 920 monitor = (Monitor) e.getObject(); 921 922 return mIndex = e.getIndex(); 923 } 924 925 932 protected abstract Ref getRef(); 933 934 protected Fields cloneFields() { 935 if (fIndex == -1) { 936 return fields; 937 } 938 939 fIndex = -1; 940 area.ks.data = null; 941 area.hasChanged.set(index); 942 area.anyChanged = true; 943 944 return fields = (Fields) fields.clone(); 945 } 946 947 protected Monitor cloneMonitor() { 948 if (mIndex == -1) { 949 return monitor; 950 } 951 952 mIndex = -1; 953 area.ks.data = null; 954 area.hasChanged.set(index); 955 area.anyChanged = true; 956 957 monitor = (Monitor) monitor.clone(); 958 959 return monitor; 960 } 961 962 boolean isLockedBy(ThreadInfo ti) { 963 return ((monitor != null) && (monitor.getLockingThread() == ti.index)); 964 } 965 966 void _printAttributes(String cls, String msg, int oldAttrs) { 967 if (getClassInfo().getName().equals(cls)) { 968 System.out.println(msg + " " + this + " attributes: " 969 + Integer.toHexString(attributes) + " was: " 970 + Integer.toHexString(oldAttrs)); 971 } 972 } 973 974 977 978 public Vector linearize (Vector result) { 979 DynamicArea heap = DynamicArea.getHeap(); 980 int i, n; 981 982 if (isArray()) { 983 if (fields.isReferenceArray()) { 984 n = fields.arrayLength(); 985 for (i=0; i<n; i++) { 986 result = heap.linearize(fields.getIntValue(i),result); 987 } 988 } 989 } else { 990 ClassInfo ci = getClassInfo(); 991 do { 992 n = ci.getNumberOfDeclaredInstanceFields(); 993 for (i=0; i<n; i++) { 994 FieldInfo fi = ci.getDeclaredInstanceField(i); 995 if (fi.isReference()) { 996 if ((i == 0) && ci.isWeakReference()) { 997 1001 return result; 1003 1004 } else { 1005 result = heap.linearize(fields.getReferenceValue(fi.getStorageOffset()),result); 1010 } 1011 } 1012 } 1013 ci = ci.getSuperClass(); 1014 } while (ci != null); 1015 } 1016 return result; 1017 } 1018} 1019 1020 | Popular Tags |