langtools/src/share/classes/com/sun/tools/javac/util/Bits.java
changeset 19941 8b91e8eb2d20
parent 17282 c6964ad7df63
child 22689 570f79791f52
equal deleted inserted replaced
19940:d6d6e623f0b4 19941:8b91e8eb2d20
    24  */
    24  */
    25 
    25 
    26 package com.sun.tools.javac.util;
    26 package com.sun.tools.javac.util;
    27 
    27 
    28 import java.util.Arrays;
    28 import java.util.Arrays;
    29 
       
    30 import static com.sun.tools.javac.util.Bits.BitsOpKind.*;
       
    31 
    29 
    32 /** A class for extensible, mutable bit sets.
    30 /** A class for extensible, mutable bit sets.
    33  *
    31  *
    34  *  <p><b>This is NOT part of any supported API.
    32  *  <p><b>This is NOT part of any supported API.
    35  *  If you write code that depends on this, you do so at your own risk.
    33  *  If you write code that depends on this, you do so at your own risk.
    36  *  This code and its internal interfaces are subject to change or
    34  *  This code and its internal interfaces are subject to change or
    37  *  deletion without notice.</b>
    35  *  deletion without notice.</b>
    38  */
    36  */
    39 public class Bits {
    37 public class Bits {
    40 
       
    41     public enum BitsOpKind {
       
    42         INIT,
       
    43         CLEAR,
       
    44         INCL_BIT,
       
    45         EXCL_BIT,
       
    46         ASSIGN,
       
    47         AND_SET,
       
    48         OR_SET,
       
    49         DIFF_SET,
       
    50         XOR_SET,
       
    51         INCL_RANGE,
       
    52         EXCL_RANGE,
       
    53     }
       
    54 
    38 
    55     //       ____________      reset    _________
    39     //       ____________      reset    _________
    56     //      /  UNKNOWN   \   <-------- / UNINIT  \
    40     //      /  UNKNOWN   \   <-------- / UNINIT  \
    57     //      \____________/       |     \_________/
    41     //      \____________/       |     \_________/
    58     //            |              |          |
    42     //            |              |          |
    62     //                    \___________/     |
    46     //                    \___________/     |
    63     //                            |         |
    47     //                            |         |
    64     //                            |         |
    48     //                            |         |
    65     //                            -----------
    49     //                            -----------
    66     //                               any
    50     //                               any
    67     private enum BitsState {
    51     protected enum BitsState {
    68         /*  A Bits instance is in UNKNOWN state if it has been explicitly reset.
    52         /*  A Bits instance is in UNKNOWN state if it has been explicitly reset.
    69          *  It is possible to get to this state from any other by calling the
    53          *  It is possible to get to this state from any other by calling the
    70          *  reset method. An instance in the UNKNOWN state can pass to the
    54          *  reset method. An instance in the UNKNOWN state can pass to the
    71          *  NORMAL state after being assigned another Bits instance.
    55          *  NORMAL state after being assigned another Bits instance.
       
    56          *
       
    57          *  Bits instances are final fields in Flow so the UNKNOWN state models
       
    58          *  the null assignment.
    72          */
    59          */
    73         UNKNOWN,
    60         UNKNOWN,
    74         /*  A Bits instance is in UNINIT when it is created with the default
    61         /*  A Bits instance is in UNINIT when it is created with the default
    75          *  constructor but it isn't explicitly reset. The main objective of this
    62          *  constructor but it isn't explicitly reset. The main objective of this
    76          *  internal state is to save some memory.
    63          *  internal state is to save some memory.
   101     private final static int wordshift = 5;
    88     private final static int wordshift = 5;
   102     private final static int wordmask = wordlen - 1;
    89     private final static int wordmask = wordlen - 1;
   103 
    90 
   104     public int[] bits = null;
    91     public int[] bits = null;
   105     // This field will store last version of bits after every change.
    92     // This field will store last version of bits after every change.
   106     public int[] oldBits = null;
       
   107 
       
   108     public BitsOpKind lastOperation = null;
       
   109 
       
   110     private static final int[] unassignedBits = new int[0];
    93     private static final int[] unassignedBits = new int[0];
   111 
    94 
   112     private BitsState currentState;
    95     protected BitsState currentState;
   113 
    96 
   114     /** Construct an initially empty set.
    97     /** Construct an initially empty set.
   115      */
    98      */
   116     public Bits() {
    99     public Bits() {
   117         this(false);
   100         this(false);
   125         this(unassignedBits, BitsState.getState(unassignedBits, reset));
   108         this(unassignedBits, BitsState.getState(unassignedBits, reset));
   126     }
   109     }
   127 
   110 
   128     /** Construct a set consisting initially of given bit vector.
   111     /** Construct a set consisting initially of given bit vector.
   129      */
   112      */
   130     private Bits(int[] bits, BitsState initState) {
   113     protected Bits(int[] bits, BitsState initState) {
   131         this.bits = bits;
   114         this.bits = bits;
   132         this.currentState = initState;
   115         this.currentState = initState;
   133         switch (initState) {
   116         switch (initState) {
   134             case UNKNOWN:
   117             case UNKNOWN:
   135                 reset(); //this will also set current state;
   118                 this.bits = null;
   136                 break;
   119                 break;
   137             case NORMAL:
   120             case NORMAL:
   138                 Assert.check(bits != unassignedBits);
   121                 Assert.check(bits != unassignedBits);
   139                 lastOperation = INIT;
       
   140                 break;
   122                 break;
   141         }
   123         }
   142     }
   124     }
   143 
   125 
   144     /** This method will be called after any operation that causes a change to
   126     protected void sizeTo(int len) {
   145      *  the bits. Subclasses can thus override it in order to extract information
       
   146      *  from the changes produced to the bits by the given operation.
       
   147      */
       
   148     public void changed() {}
       
   149 
       
   150     private void sizeTo(int len) {
       
   151         if (bits.length < len) {
   127         if (bits.length < len) {
   152             bits = Arrays.copyOf(bits, len);
   128             bits = Arrays.copyOf(bits, len);
   153         }
   129         }
   154     }
   130     }
   155 
   131 
   156     /** This set = {}.
   132     /** This set = {}.
   157      */
   133      */
   158     public void clear() {
   134     public void clear() {
   159         Assert.check(currentState != BitsState.UNKNOWN);
   135         Assert.check(currentState != BitsState.UNKNOWN);
   160         oldBits = bits;
   136         for (int i = 0; i < bits.length; i++) {
   161         lastOperation = CLEAR;
   137             bits[i] = 0;
   162         for (int i = 0; i < bits.length; i++) bits[i] = 0;
   138         }
   163         changed();
       
   164         currentState = BitsState.NORMAL;
   139         currentState = BitsState.NORMAL;
   165     }
   140     }
   166 
   141 
   167     public void reset() {
   142     public void reset() {
       
   143         internalReset();
       
   144     }
       
   145 
       
   146     protected void internalReset() {
   168         bits = null;
   147         bits = null;
   169         oldBits = null;
       
   170         currentState = BitsState.UNKNOWN;
   148         currentState = BitsState.UNKNOWN;
   171     }
   149     }
   172 
   150 
   173     public boolean isReset() {
   151     public boolean isReset() {
   174         return currentState == BitsState.UNKNOWN;
   152         return currentState == BitsState.UNKNOWN;
   175     }
   153     }
   176 
   154 
   177     public Bits assign(Bits someBits) {
   155     public Bits assign(Bits someBits) {
   178         lastOperation = ASSIGN;
       
   179         oldBits = bits;
       
   180         bits = someBits.dup().bits;
   156         bits = someBits.dup().bits;
   181         changed();
       
   182         currentState = BitsState.NORMAL;
   157         currentState = BitsState.NORMAL;
   183         return this;
   158         return this;
   184     }
   159     }
   185 
   160 
   186     /** Return a copy of this set.
   161     /** Return a copy of this set.
   187      */
   162      */
   188     private Bits dup() {
   163     public Bits dup() {
   189         Assert.check(currentState != BitsState.UNKNOWN);
   164         Assert.check(currentState != BitsState.UNKNOWN);
   190         Bits tmp = new Bits();
   165         Bits tmp = new Bits();
       
   166         tmp.bits = dupBits();
       
   167         currentState = BitsState.NORMAL;
       
   168         return tmp;
       
   169     }
       
   170 
       
   171     protected int[] dupBits() {
       
   172         int [] result;
   191         if (currentState != BitsState.NORMAL) {
   173         if (currentState != BitsState.NORMAL) {
   192             tmp.bits = bits;
   174             result = bits;
   193         } else {
   175         } else {
   194             tmp.bits = new int[bits.length];
   176             result = new int[bits.length];
   195             System.arraycopy(bits, 0, tmp.bits, 0, bits.length);
   177             System.arraycopy(bits, 0, result, 0, bits.length);
   196         }
   178         }
   197         currentState = BitsState.NORMAL;
   179         return result;
   198         return tmp;
       
   199     }
   180     }
   200 
   181 
   201     /** Include x in this set.
   182     /** Include x in this set.
   202      */
   183      */
   203     public void incl(int x) {
   184     public void incl(int x) {
   204         Assert.check(currentState != BitsState.UNKNOWN);
   185         Assert.check(currentState != BitsState.UNKNOWN);
   205         Assert.check(x >= 0);
   186         Assert.check(x >= 0, "Value of x " + x);
   206         oldBits = bits;
       
   207         lastOperation = INCL_BIT;
       
   208         sizeTo((x >>> wordshift) + 1);
   187         sizeTo((x >>> wordshift) + 1);
   209         bits[x >>> wordshift] = bits[x >>> wordshift] |
   188         bits[x >>> wordshift] = bits[x >>> wordshift] |
   210             (1 << (x & wordmask));
   189             (1 << (x & wordmask));
   211         changed();
       
   212         currentState = BitsState.NORMAL;
   190         currentState = BitsState.NORMAL;
   213     }
   191     }
   214 
   192 
   215 
   193 
   216     /** Include [start..limit) in this set.
   194     /** Include [start..limit) in this set.
   217      */
   195      */
   218     public void inclRange(int start, int limit) {
   196     public void inclRange(int start, int limit) {
   219         Assert.check(currentState != BitsState.UNKNOWN);
   197         Assert.check(currentState != BitsState.UNKNOWN);
   220         oldBits = bits;
       
   221         lastOperation = INCL_RANGE;
       
   222         sizeTo((limit >>> wordshift) + 1);
   198         sizeTo((limit >>> wordshift) + 1);
   223         for (int x = start; x < limit; x++) {
   199         for (int x = start; x < limit; x++) {
   224             bits[x >>> wordshift] = bits[x >>> wordshift] |
   200             bits[x >>> wordshift] = bits[x >>> wordshift] |
   225                 (1 << (x & wordmask));
   201                 (1 << (x & wordmask));
   226         }
   202         }
   227         changed();
       
   228         currentState = BitsState.NORMAL;
   203         currentState = BitsState.NORMAL;
   229     }
   204     }
   230 
   205 
   231     /** Exclude [start...end] from this set.
   206     /** Exclude [start...end] from this set.
   232      */
   207      */
   233     public void excludeFrom(int start) {
   208     public void excludeFrom(int start) {
   234         Assert.check(currentState != BitsState.UNKNOWN);
   209         Assert.check(currentState != BitsState.UNKNOWN);
   235         oldBits = bits;
       
   236         lastOperation = EXCL_RANGE;
       
   237         Bits temp = new Bits();
   210         Bits temp = new Bits();
   238         temp.sizeTo(bits.length);
   211         temp.sizeTo(bits.length);
   239         temp.inclRange(0, start);
   212         temp.inclRange(0, start);
   240         internalAndSet(temp);
   213         internalAndSet(temp);
   241         changed();
       
   242         currentState = BitsState.NORMAL;
   214         currentState = BitsState.NORMAL;
   243     }
   215     }
   244 
   216 
   245     /** Exclude x from this set.
   217     /** Exclude x from this set.
   246      */
   218      */
   247     public void excl(int x) {
   219     public void excl(int x) {
   248         Assert.check(currentState != BitsState.UNKNOWN);
   220         Assert.check(currentState != BitsState.UNKNOWN);
   249         Assert.check(x >= 0);
   221         Assert.check(x >= 0);
   250         oldBits = bits;
       
   251         lastOperation = EXCL_BIT;
       
   252         sizeTo((x >>> wordshift) + 1);
   222         sizeTo((x >>> wordshift) + 1);
   253         bits[x >>> wordshift] = bits[x >>> wordshift] &
   223         bits[x >>> wordshift] = bits[x >>> wordshift] &
   254             ~(1 << (x & wordmask));
   224             ~(1 << (x & wordmask));
   255         changed();
       
   256         currentState = BitsState.NORMAL;
   225         currentState = BitsState.NORMAL;
   257     }
   226     }
   258 
   227 
   259     /** Is x an element of this set?
   228     /** Is x an element of this set?
   260      */
   229      */
   267 
   236 
   268     /** {@literal this set = this set & xs}.
   237     /** {@literal this set = this set & xs}.
   269      */
   238      */
   270     public Bits andSet(Bits xs) {
   239     public Bits andSet(Bits xs) {
   271         Assert.check(currentState != BitsState.UNKNOWN);
   240         Assert.check(currentState != BitsState.UNKNOWN);
   272         oldBits = bits;
       
   273         lastOperation = AND_SET;
       
   274         internalAndSet(xs);
   241         internalAndSet(xs);
   275         changed();
   242         currentState = BitsState.NORMAL;
   276         currentState = BitsState.NORMAL;
   243         return this;
   277         return this;
   244     }
   278     }
   245 
   279 
   246     protected void internalAndSet(Bits xs) {
   280     private void internalAndSet(Bits xs) {
       
   281         Assert.check(currentState != BitsState.UNKNOWN);
   247         Assert.check(currentState != BitsState.UNKNOWN);
   282         sizeTo(xs.bits.length);
   248         sizeTo(xs.bits.length);
   283         for (int i = 0; i < xs.bits.length; i++) {
   249         for (int i = 0; i < xs.bits.length; i++) {
   284             bits[i] = bits[i] & xs.bits[i];
   250             bits[i] = bits[i] & xs.bits[i];
   285         }
   251         }
   287 
   253 
   288     /** this set = this set | xs.
   254     /** this set = this set | xs.
   289      */
   255      */
   290     public Bits orSet(Bits xs) {
   256     public Bits orSet(Bits xs) {
   291         Assert.check(currentState != BitsState.UNKNOWN);
   257         Assert.check(currentState != BitsState.UNKNOWN);
   292         oldBits = bits;
       
   293         lastOperation = OR_SET;
       
   294         sizeTo(xs.bits.length);
   258         sizeTo(xs.bits.length);
   295         for (int i = 0; i < xs.bits.length; i++) {
   259         for (int i = 0; i < xs.bits.length; i++) {
   296             bits[i] = bits[i] | xs.bits[i];
   260             bits[i] = bits[i] | xs.bits[i];
   297         }
   261         }
   298         changed();
       
   299         currentState = BitsState.NORMAL;
   262         currentState = BitsState.NORMAL;
   300         return this;
   263         return this;
   301     }
   264     }
   302 
   265 
   303     /** this set = this set \ xs.
   266     /** this set = this set \ xs.
   304      */
   267      */
   305     public Bits diffSet(Bits xs) {
   268     public Bits diffSet(Bits xs) {
   306         Assert.check(currentState != BitsState.UNKNOWN);
   269         Assert.check(currentState != BitsState.UNKNOWN);
   307         oldBits = bits;
       
   308         lastOperation = DIFF_SET;
       
   309         for (int i = 0; i < bits.length; i++) {
   270         for (int i = 0; i < bits.length; i++) {
   310             if (i < xs.bits.length) {
   271             if (i < xs.bits.length) {
   311                 bits[i] = bits[i] & ~xs.bits[i];
   272                 bits[i] = bits[i] & ~xs.bits[i];
   312             }
   273             }
   313         }
   274         }
   314         changed();
       
   315         currentState = BitsState.NORMAL;
   275         currentState = BitsState.NORMAL;
   316         return this;
   276         return this;
   317     }
   277     }
   318 
   278 
   319     /** this set = this set ^ xs.
   279     /** this set = this set ^ xs.
   320      */
   280      */
   321     public Bits xorSet(Bits xs) {
   281     public Bits xorSet(Bits xs) {
   322         Assert.check(currentState != BitsState.UNKNOWN);
   282         Assert.check(currentState != BitsState.UNKNOWN);
   323         oldBits = bits;
       
   324         lastOperation = XOR_SET;
       
   325         sizeTo(xs.bits.length);
   283         sizeTo(xs.bits.length);
   326         for (int i = 0; i < xs.bits.length; i++) {
   284         for (int i = 0; i < xs.bits.length; i++) {
   327             bits[i] = bits[i] ^ xs.bits[i];
   285             bits[i] = bits[i] ^ xs.bits[i];
   328         }
   286         }
   329         changed();
       
   330         currentState = BitsState.NORMAL;
   287         currentState = BitsState.NORMAL;
   331         return this;
   288         return this;
   332     }
   289     }
   333 
   290 
   334     /** Count trailing zero bits in an int. Algorithm from "Hacker's
   291     /** Count trailing zero bits in an int. Algorithm from "Hacker's
   335      *  Delight" by Henry S. Warren Jr. (figure 5-13)
   292      *  Delight" by Henry S. Warren Jr. (figure 5-13)
   336      */
   293      */
   337     private static int trailingZeroBits(int x) {
   294     private static int trailingZeroBits(int x) {
   338         Assert.check(wordlen == 32);
   295         Assert.check(wordlen == 32);
   339         if (x == 0) return 32;
   296         if (x == 0) {
       
   297             return 32;
       
   298         }
   340         int n = 1;
   299         int n = 1;
   341         if ((x & 0xffff) == 0) { n += 16; x >>>= 16; }
   300         if ((x & 0xffff) == 0) { n += 16; x >>>= 16; }
   342         if ((x & 0x00ff) == 0) { n +=  8; x >>>=  8; }
   301         if ((x & 0x00ff) == 0) { n +=  8; x >>>=  8; }
   343         if ((x & 0x000f) == 0) { n +=  4; x >>>=  4; }
   302         if ((x & 0x000f) == 0) { n +=  4; x >>>=  4; }
   344         if ((x & 0x0003) == 0) { n +=  2; x >>>=  2; }
   303         if ((x & 0x0003) == 0) { n +=  2; x >>>=  2; }
   353      *  }</pre>
   312      *  }</pre>
   354      */
   313      */
   355     public int nextBit(int x) {
   314     public int nextBit(int x) {
   356         Assert.check(currentState != BitsState.UNKNOWN);
   315         Assert.check(currentState != BitsState.UNKNOWN);
   357         int windex = x >>> wordshift;
   316         int windex = x >>> wordshift;
   358         if (windex >= bits.length) return -1;
   317         if (windex >= bits.length) {
       
   318             return -1;
       
   319         }
   359         int word = bits[windex] & ~((1 << (x & wordmask))-1);
   320         int word = bits[windex] & ~((1 << (x & wordmask))-1);
   360         while (true) {
   321         while (true) {
   361             if (word != 0)
   322             if (word != 0) {
   362                 return (windex << wordshift) + trailingZeroBits(word);
   323                 return (windex << wordshift) + trailingZeroBits(word);
       
   324             }
   363             windex++;
   325             windex++;
   364             if (windex >= bits.length) return -1;
   326             if (windex >= bits.length) {
       
   327                 return -1;
       
   328             }
   365             word = bits[windex];
   329             word = bits[windex];
   366         }
   330         }
   367     }
   331     }
   368 
   332 
   369     /** a string representation of this set.
   333     /** a string representation of this set.
   370      */
   334      */
       
   335     @Override
   371     public String toString() {
   336     public String toString() {
   372         if (bits.length > 0) {
   337         if (bits != null && bits.length > 0) {
   373             char[] digits = new char[bits.length * wordlen];
   338             char[] digits = new char[bits.length * wordlen];
   374             for (int i = 0; i < bits.length * wordlen; i++)
   339             for (int i = 0; i < bits.length * wordlen; i++) {
   375                 digits[i] = isMember(i) ? '1' : '0';
   340                 digits[i] = isMember(i) ? '1' : '0';
       
   341             }
   376             return new String(digits);
   342             return new String(digits);
   377         } else {
   343         } else {
   378             return "[]";
   344             return "[]";
   379         }
   345         }
   380     }
   346     }
   394         int count = 0;
   360         int count = 0;
   395         for (int i = bits.nextBit(0); i >= 0; i = bits.nextBit(i+1)) {
   361         for (int i = bits.nextBit(0); i >= 0; i = bits.nextBit(i+1)) {
   396             System.out.println("found " + i);
   362             System.out.println("found " + i);
   397             count ++;
   363             count ++;
   398         }
   364         }
   399         if (count != 125) throw new Error();
   365         if (count != 125) {
       
   366             throw new Error();
       
   367         }
   400     }
   368     }
   401 }
   369 }