public static boolean maybeSameLocation(Value v1, Value v2) { if (!(v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) && !(v1 instanceof ArrayRef && v2 instanceof ArrayRef)) { return v1.equivTo(v2); } if (v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) { InstanceFieldRef ifr1 = (InstanceFieldRef) v1; InstanceFieldRef ifr2 = (InstanceFieldRef) v2; if (!ifr1.getField().getName().equals(ifr2.getField().getName())) return false; Local base1 = (Local) ifr1.getBase(); Local base2 = (Local) ifr2.getBase(); PointsToAnalysis pta = Scene.v().getPointsToAnalysis(); PointsToSet pts1 = pta.reachingObjects(base1); PointsToSet pts2 = pta.reachingObjects(base2); return pts1.hasNonEmptyIntersection(pts2); } else { // v1 instanceof ArrayRef && v2 instanceof ArrayRef ArrayRef ar1 = (ArrayRef) v1; ArrayRef ar2 = (ArrayRef) v2; Local base1 = (Local) ar1.getBase(); Local base2 = (Local) ar2.getBase(); PointsToAnalysis pta = Scene.v().getPointsToAnalysis(); PointsToSet pts1 = pta.reachingObjects(base1); PointsToSet pts2 = pta.reachingObjects(base2); return pts1.hasNonEmptyIntersection(pts2); } }
// NB: This doesn't just alloc capacity, it also sets bufh.len to the allocated size in advance, // expecting caller to read in that much private static byte[] alloc(ArrayRef<byte[]> bufh, int size) { byte[] buf = null; if (bufh == null) { if (size != 0) buf = new byte[size]; } else { if (bufh.ar_buf.length - bufh.ar_off < size) { bufh.ar_buf = new byte[size]; bufh.ar_off = 0; } bufh.ar_len = size; buf = bufh.ar_buf; } return buf; }
// Read requested number of bytes from stream, and return as byte array. // If bufh is non-null, then it will be used (and grown if necessary) to hold the data and its // backing array is returned. // If reqlen is -1, that means read to end of stream, which we refer to as an unbounded read. // Note that this method does not append to bufh, it will replaces whatever is already there. // // The bounded case is pretty straightforward, but unbounded reads are complicated by the fact // that in the general case, we can't tell how // many bytes are in the URL's content stream in advance. We therefore use a ByteArrayOutputStream // to accumulate its data. // However, the caller may know via other means how large the content is or may be, and therefore // allocate 'bufh' storage which is large // enough to hold it all. Or, the intermediate read buffer we allocate might be enough to hold the // entire content. // In these cases, it seems a shame to go to the wasted expense of allocating a // ByteArrayOutputStream, copying the read buffer into it, // and then allocating another byte array at the end to return its contents. We therefore go to a // moderate amount of trouble to defer // the introduction of the ByteArrayOutputStream until the intermediate read buffer (which might // or might not be based on caller-provider // storage) fills up. public static byte[] read(java.io.InputStream istrm, int reqlen, ArrayRef<byte[]> bufh) throws java.io.IOException { int bufcap = reqlen; if (bufcap == -1) { bufcap = istrm.available(); if (bufcap < RDBUFSIZ) bufcap = RDBUFSIZ; } byte[] rdbuf = alloc( bufh, bufcap); // this is the intermediate read buffer, a staging area between istrm and ostrm int off = (bufh == null ? 0 : bufh.ar_off); java.io.ByteArrayOutputStream ostrm = null; int totaldata = 0; int buflen = 0; while (totaldata != reqlen) { if (buflen == bufcap) { // The intermediate read buffer is full, so flush it to the byte-array-stream. // If reqlen was -1 and InputStream.available() gave us an accurate total, then the creation // of the ByteArrayOutputStream // is a waste as we've already got the whole stream stored in 'rdbuf'. But, there's no way // of knowing for sure as we can't // depend on available()==0 really meaning we're at EOF. if (ostrm == null) ostrm = new java.io.ByteArrayOutputStream(bufcap); ostrm.write(rdbuf, off, buflen); buflen = 0; } int nbytes = istrm.read(rdbuf, off + buflen, bufcap - buflen); if (nbytes == -1) break; // end of input stream // accumulate data in 'buf' if there's space, to avoid copying into the byte-stream on every // single read buflen += nbytes; totaldata += nbytes; } if (ostrm == null) { // NB: This means totaldata == buflen // Either the caller provided enough storage, or we allocated an intermediate read buffer that // was sufficient if (totaldata == 0) return null; // there was no data if (bufh == null && totaldata != bufcap) { // The buffer we initially allocated was too large, and it's length attribute is the only // indication the caller will have // of how much data we did read, so we have to return a smaller buffer that's exactly sized // - allocate it and copy into it. byte[] buf2 = new byte[totaldata]; System.arraycopy(rdbuf, off, buf2, 0, totaldata); rdbuf = buf2; } } else { // the caller didn't provide enough storage (or maybe any storage), so return a copy of the // ByteArrayOutputStream's buffer if (buflen != 0) ostrm.write(rdbuf, off, buflen); // append the final batch of data to the byte stream first rdbuf = ostrm.toByteArray(); } if (bufh != null) { if (bufh.ar_buf != rdbuf) bufh.ar_off = 0; // we allocated a new backing array, and it has no offset bufh.ar_buf = rdbuf; bufh.ar_len = totaldata; } return rdbuf; }