/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann - Contributions for
 *     						bug 325755 - [compiler] wrong initialization state after conditional expression
 *     						bug 320170 - [compiler] [null] Whitebox issues in null analysis
 *     						bug 292478 - Report potentially null across variable assignment
 *     						bug 332637 - Dead Code detection removing code that isn't dead
 *     						bug 341499 - [compiler][null] allocate extra bits in all methods of UnconditionalFlowInfo
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
 *							bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
 *							bug 386181 - [compiler][null] wrong transition in UnconditionalFlowInfo.mergedWith()
 *							bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
 *							Bug 453483 - [compiler][null][loop] Improve null analysis for loops
 *							Bug 454031 - [compiler][null][loop] bug in null analysis; wrong "dead code" detection
 *							Bug 421035 - [resource] False alarm of resource leak warning when casting a closeable in its assignment
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;

import java.util.Arrays;

import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallTrackingVariable;

/**
 * OTDT changes:
 *
 * What: special query regarding base-call tracking variable.
 * Why:  don't analyse for dead-end.
 *
 * @version $Id: UnconditionalFlowInfo.java 23404 2010-02-03 14:10:22Z stephan $
 * ====
 * Record initialization status during definite assignment analysis
 *
 * No caching of pre-allocated instances.
 */
public class UnconditionalFlowInfo extends FlowInfo {
	/**
	 * Exception raised when unexpected behavior is detected.
	 */
	public static class AssertionFailedException extends RuntimeException {
		private static final long serialVersionUID = 1827352841030089703L;

	public AssertionFailedException(String message) {
		super(message);
	}
	}

	// Coverage tests need that the code be instrumented. The following flag
	// controls whether the instrumented code is compiled in or not, and whether
	// the coverage tests methods run or not.
	public final static boolean COVERAGE_TEST_FLAG = false;
	// never release with the coverageTestFlag set to true
	public static int CoverageTestId;

	// assignment bits - first segment
	public long definiteInits;
	public long potentialInits;

	// null bits - first segment
	public long
		nullBit1,
		nullBit2,
		nullBit3,
		nullBit4;
/*
		nullBit1
		 nullBit2...
		0000	start
		0001	pot. unknown
		0010	pot. non null
		0011	pot. nn & pot. un
		0100	pot. null
		0101	pot. n & pot. un
		0110	pot. n & pot. nn
		0111    pot. n & pot. nn & pot. un
		1001	def. unknown
		1010	def. non null
		1011	pot. nn & prot. nn
		1100	def. null
		1101	pot. n & prot. n
		1110	prot. null
		1111	prot. non null
 */
	public long 
		iNBit,	// can an incoming null value reach the current point?
		iNNBit;	// can an incoming nonnull value reach the current point?

	// extra segments
	public static final int extraLength = 8;
	public long extra[][];
		// extra bit fields for larger numbers of fields/variables
		// extra[0] holds definiteInits values, extra[1] potentialInits, etc.
		// extra[1+1]... corresponds to nullBits1 ...
		// extra[IN] is iNBit
		// extra[INN] is iNNBit
		// lifecycle is extra == null or else all extra[]'s are allocated
		// arrays which have the same size

	public int maxFieldCount; // limit between fields and locals

	// Constants
	public static final int BitCacheSize = 64; // 64 bits in a long.
	public static final int IN = 6;
	public static final int INN = 7;

/* fakeInitializedFlowInfo: For Lambda expressions tentative analysis during overload resolution. 
   We presume that any and all outer locals touched by the lambda are definitely assigned and 
   effectively final. Whether they are or not is immaterial for overload analysis (errors encountered
   in the body are not supposed to influence the resolution. It is pertinent only for the eventual 
   resolution/analysis post overload resolution. For lambda's the problem is that we start the control/data
   flow analysis abruptly at the start of the lambda, so we need to present a cogent world view and hence 
   all this charade.
*/
public static UnconditionalFlowInfo fakeInitializedFlowInfo(int localsCount, int maxFieldCount) {
		UnconditionalFlowInfo flowInfo = new UnconditionalFlowInfo();
		flowInfo.maxFieldCount = maxFieldCount;
		for (int i = 0; i < localsCount; i++)
			flowInfo.markAsDefinitelyAssigned(i + maxFieldCount);
		return flowInfo;
}

public FlowInfo addInitializationsFrom(FlowInfo inits) {
	return addInfoFrom(inits, true);
}
public FlowInfo addNullInfoFrom(FlowInfo inits) {
	return addInfoFrom(inits, false);
}
private FlowInfo addInfoFrom(FlowInfo inits, boolean handleInits) {
	if (this == DEAD_END)
		return this;
	if (inits == DEAD_END)
		return this;
	UnconditionalFlowInfo otherInits = inits.unconditionalInits();

	if (handleInits) {
		// union of definitely assigned variables,
		this.definiteInits |= otherInits.definiteInits;
		// union of potentially set ones
		this.potentialInits |= otherInits.potentialInits;
	}
	
	// combine null information
	boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0,
		otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0;
//	if ((otherInits.iNNBit | otherInits.iNBit) == 0)
//		thisHadNulls = false; // suppress incoming null info, if none shines through in other
	long
		a1, a2, a3, a4,
		na1, na2, na3, na4,
		b1, b2, b3, b4,
		nb1, nb2, nb3, nb4;
	if (otherHasNulls) {
		if (!thisHadNulls) {
			this.nullBit1 = otherInits.nullBit1;
			this.nullBit2 = otherInits.nullBit2;
			this.nullBit3 = otherInits.nullBit3;
			this.nullBit4 = otherInits.nullBit4;
			this.iNBit = otherInits.iNBit;
			this.iNNBit = otherInits.iNNBit;
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 1) {
				  this.nullBit4 = ~0;
				}
			}
		}
		else {
			a1 = this.nullBit1;
			a2 = this.nullBit2;
			a3 = this.nullBit3;
			a4 = this.nullBit4;

			// state that breaks the correlation between bits and n or nn, used below:
			long protNN1111 = a1&a2&a3&a4;

			// filter 'a' using iNBit,iNNBit from otherInits:
			// this implements that otherInit does not accept certain bits which are known to be superseded by info in otherInits.			
			long acceptNonNull = otherInits.iNNBit;
			long acceptNull = otherInits.iNBit
								| protNN1111; // for 1111 don't bother suppressing incoming null, logic operation would produce wrong result
			long dontResetToStart = ~protNN1111 | acceptNonNull; // for 1111 & ~acceptNonNull we reset all bits to 0000

			a1 &= dontResetToStart;
			a2 = dontResetToStart & acceptNull & a2;
			a3 = dontResetToStart & acceptNonNull & a3;
			a4 &= dontResetToStart;
			a1 &= (a2 | a3 | a4);		// translate 1000 (undefined state) to 0000
			
			this.nullBit1 = (b1 = otherInits.nullBit1)
                				| a1 & (a3
                					& a4 & (nb2 = ~(b2 = otherInits.nullBit2))
                					& (nb4 = ~(b4 = otherInits.nullBit4))
                        		| ((na4 = ~a4) | (na3 = ~a3))
                        			& ((na2 = ~a2) & nb2
                        				| a2 & (nb3 = ~(b3 = otherInits.nullBit3)) & nb4));
			this.nullBit2  = b2 & (nb4 | nb3)
                    			| na3 & na4 & b2
                    			| a2 & (nb3 & nb4
                                			| (nb1 = ~b1) & (na3 | (na1 = ~a1))
                                			| a1 & b2);
			this.nullBit3 = b3 & (nb1 & (b2 | a2 | na1)
                        			| b1 & (b4 | nb2 | a1 & a3)
                         			| na1 & na2 & na4)
                    			| a3 & nb2 & nb4
                    			| nb1 & ((na2 & a4 | na1) & a3
                                			| a1 & na2 & na4 & b2);
			this.nullBit4 = nb1 & (a4 & (na3 & nb3	| (a3 | na2) & nb2)
                      			| a1 & (a3 & nb2 & b4
                              			| a2 & b2 & (b4	| a3 & na4 & nb3)))
                      			| b1 & (a3 & a4 & b4
                          			| na2 & na4 & nb3 & b4
                          			| a2 & ((b3 | a4) & b4
                                  				| na3 & a4 & b2 & b3)
                          			| na1 & (b4	| (a4 | a2) & b2 & b3))
                      			| (na1 & (na3 & nb3 | na2 & nb2)
                      				| a1 & (nb2 & nb3 | a2 & a3)) & b4;

			// unconditional sequence, must shine through both to shine through in the end:
			this.iNBit &= otherInits.iNBit;
			this.iNNBit &= otherInits.iNNBit;
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 2) {
				  this.nullBit4 = ~0;
				}
			}
		}
		this.tagBits |= NULL_FLAG_MASK; // in all cases - avoid forgetting extras
	}
	// treating extra storage
	if (this.extra != null || otherInits.extra != null) {
		int mergeLimit = 0, copyLimit = 0;
		if (this.extra != null) {
			if (otherInits.extra != null) {
				// both sides have extra storage
				int length, otherLength;
				if ((length = this.extra[0].length) <
						(otherLength = otherInits.extra[0].length)) {
					// current storage is shorter -> grow current
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[otherLength]), 0, length);
					}
					mergeLimit = length;
					copyLimit = otherLength;
					if (COVERAGE_TEST_FLAG) {
						if (CoverageTestId == 3) {
							throw new AssertionFailedException("COVERAGE 3"); //$NON-NLS-1$
						}
					}
				} else {
					// current storage is longer
					mergeLimit = otherLength;
					if (COVERAGE_TEST_FLAG) {
						if (CoverageTestId == 4) {
							throw new AssertionFailedException("COVERAGE 4"); //$NON-NLS-1$
						}
					}
				}
			}
		} else if (otherInits.extra != null) {
			// no storage here, but other has extra storage.
			// shortcut regular copy because array copy is better
			int otherLength;
			this.extra = new long[extraLength][];
			System.arraycopy(otherInits.extra[0], 0,
				(this.extra[0] = new long[otherLength =
					otherInits.extra[0].length]), 0, otherLength);
			System.arraycopy(otherInits.extra[1], 0,
				(this.extra[1] = new long[otherLength]), 0, otherLength);
			if (otherHasNulls) {
				for (int j = 2; j < extraLength; j++) {
					System.arraycopy(otherInits.extra[j], 0,
						(this.extra[j] = new long[otherLength]), 0, otherLength);
				}
				if (COVERAGE_TEST_FLAG) {
					if (CoverageTestId == 5) {
						this.extra[5][otherLength - 1] = ~0;
					}
				}
			}
			else {
				for (int j = 2; j < extraLength; j++) {
					this.extra[j] = new long[otherLength];
				}
				System.arraycopy(otherInits.extra[IN], 0, this.extra[IN], 0, otherLength);
				System.arraycopy(otherInits.extra[INN], 0, this.extra[INN], 0, otherLength);
				if (COVERAGE_TEST_FLAG) {
					if (CoverageTestId == 6) {
						throw new AssertionFailedException("COVERAGE 6"); //$NON-NLS-1$
					}
				}
			}
		}
		int i;
		if (handleInits) {
			// manage definite assignment info
			for (i = 0; i < mergeLimit; i++) {
				this.extra[0][i] |= otherInits.extra[0][i];
				this.extra[1][i] |= otherInits.extra[1][i];
			}
			for (; i < copyLimit; i++) {
				this.extra[0][i] = otherInits.extra[0][i];
				this.extra[1][i] = otherInits.extra[1][i];
			
			}
		}
		// tweak limits for nulls
		if (!thisHadNulls) {
		    if (copyLimit < mergeLimit) {
		      	copyLimit = mergeLimit;
		    }
		  	mergeLimit = 0;
		}
		if (!otherHasNulls) {
		  	copyLimit = 0;
		  	mergeLimit = 0;
		}
		for (i = 0; i < mergeLimit; i++) {
			a1 = this.extra[1 + 1][i];
			a2 = this.extra[2 + 1][i];
			a3 = this.extra[3 + 1][i];
			a4 = this.extra[4 + 1][i];
			// state that breaks the correlation between bits and n or nn, used below:
			long protNN1111 = a1&a2&a3&a4;

			// filter 'a' using iNBit,iNNBit from otherInits:
			// this implements that otherInit does not accept certain bits which are known to be superseded by info in otherInits.			
			long acceptNonNull = otherInits.extra[INN][i];
			long acceptNull = otherInits.extra[IN][i]
								| protNN1111; // for 1111 don't bother suppressing incoming null, logic operation would produce wrong result
			long dontResetToStart = ~protNN1111 | acceptNonNull; // for 1111 & ~acceptNonNull we reset all bits to 0000

			a1 &= dontResetToStart;
			a2 = dontResetToStart & acceptNull & a2;
			a3 = dontResetToStart & acceptNonNull & a3;
			a4 &= dontResetToStart;
			a1 &= (a2 | a3 | a4);		// translate 1000 (undefined state) to 0000

			this.extra[1 + 1][i] = (b1 = otherInits.extra[1 + 1][i])
                				| a1 & (a3 
                					& a4 & (nb2 = ~(b2 = otherInits.extra[2 + 1][i]))
                					& (nb4 = ~(b4 = otherInits.extra[4 + 1][i]))
                        		| ((na4 = ~a4) | (na3 = ~a3))
                        			& ((na2 = ~a2) & nb2
                        				| a2 & (nb3 = ~(b3 = otherInits.extra[3 + 1][i])) & nb4));
			this.extra[2 + 1][i] = b2 & (nb4 | nb3)
                    			| na3 & na4 & b2
                    			| a2 & (nb3 & nb4
                                			| (nb1 = ~b1) & (na3 | (na1 = ~a1))
                                			| a1 & b2);
			this.extra[3 + 1][i] = b3 & (nb1 & (b2 | a2 | na1)
                        			| b1 & (b4 | nb2 | a1 & a3)
                         			| na1 & na2 & na4)
                    			| a3 & nb2 & nb4
                    			| nb1 & ((na2 & a4 | na1) & a3
                                			| a1 & na2 & na4 & b2);
			this.extra[4 + 1][i] = nb1 & (a4 & (na3 & nb3	| (a3 | na2) & nb2)
                      			| a1 & (a3 & nb2 & b4
                              			| a2 & b2 & (b4	| a3 & na4 & nb3)))
                      			| b1 & (a3 & a4 & b4
                          			| na2 & na4 & nb3 & b4
                          			| a2 & ((b3 | a4) & b4
                                  				| na3 & a4 & b2 & b3)
                          			| na1 & (b4	| (a4 | a2) & b2 & b3))
                      			| (na1 & (na3 & nb3 | na2 & nb2)
                      				| a1 & (nb2 & nb3 | a2 & a3)) & b4;

			// unconditional sequence, must shine through both to shine through in the end:
			this.extra[IN][i] &= otherInits.extra[IN][i];
			this.extra[INN][i] &= otherInits.extra[INN][i];

			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 7) {
				  this.extra[5][i] = ~0;
				}
			}
		}
		for (; i < copyLimit; i++) {
			for (int j = 2; j < extraLength; j++) {
				this.extra[j][i] = otherInits.extra[j][i];
			}
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 8) {
				  this.extra[5][i] = ~0;
				}
			}
		}
	}
	return this;
}

public FlowInfo addPotentialInitializationsFrom(FlowInfo inits) {
	if (this == DEAD_END){
		return this;
	}
	if (inits == DEAD_END){
		return this;
	}
	UnconditionalFlowInfo otherInits = inits.unconditionalInits();
	// union of potentially set ones
	this.potentialInits |= otherInits.potentialInits;
	// treating extra storage
	if (this.extra != null) {
		if (otherInits.extra != null) {
			// both sides have extra storage
			int i = 0, length, otherLength;
			if ((length = this.extra[0].length) < (otherLength = otherInits.extra[0].length)) {
				// current storage is shorter -> grow current
				for (int j = 0; j < extraLength; j++) {
					System.arraycopy(this.extra[j], 0,
						(this.extra[j] = new long[otherLength]), 0, length);
				}
				for (; i < length; i++) {
					this.extra[1][i] |= otherInits.extra[1][i];
				}
				for (; i < otherLength; i++) {
					this.extra[1][i] = otherInits.extra[1][i];
				}
			}
			else {
				// current storage is longer
				for (; i < otherLength; i++) {
					this.extra[1][i] |= otherInits.extra[1][i];
				}
			}
		}
	}
	else if (otherInits.extra != null) {
		// no storage here, but other has extra storage.
		int otherLength = otherInits.extra[0].length;
		createExtraSpace(otherLength);
		System.arraycopy(otherInits.extra[1], 0, this.extra[1], 0,
			otherLength);
	}
	addPotentialNullInfoFrom(otherInits);
	return this;
}

/**
 * Compose other inits over this flow info, then return this. The operation
 * semantics are to wave into this flow info the consequences upon null
 * information of a possible path into the operations that resulted into
 * otherInits. The fact that this path may be left unexecuted under peculiar
 * conditions results into less specific results than
 * {@link #addInitializationsFrom(FlowInfo) addInitializationsFrom}; moreover,
 * only the null information is affected.
 * @param otherInits other null inits to compose over this
 * @return this, modified according to otherInits information
 */
public UnconditionalFlowInfo addPotentialNullInfoFrom(
		UnconditionalFlowInfo otherInits) {
	if ((this.tagBits & UNREACHABLE) != 0 ||
			(otherInits.tagBits & UNREACHABLE) != 0 ||
			(otherInits.tagBits & NULL_FLAG_MASK) == 0) {
		return this;
	}
	// if we get here, otherInits has some null info
	boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0,
		thisHasNulls = false;
	long a1, a2, a3, a4,
		na1, na2, na3, na4,
		b1, b2, b3, b4,
		nb1, nb2, nb3, nb4;
	if (thisHadNulls) {
		this.nullBit1  = (a1 = this.nullBit1)
								& ((a3 = this.nullBit3) & (a4 = this.nullBit4)
									& ((nb2 = ~(b2 = otherInits.nullBit2))
										& (nb4 = ~(b4 = otherInits.nullBit4))
											| (b1 = otherInits.nullBit1) & (b3 = otherInits.nullBit3))
                			| (na2 = ~(a2 = this.nullBit2))
                				& (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2)
                			| a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2)));
		this.nullBit2 = b2 & (nb3 | (nb1 = ~b1))
    			| a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1));
		this.nullBit3 = b3 & (nb1 & b2
            		| a2 & (nb2	| a3)
            		| na1 & nb2
            		| a1 & na2 & na4 & b1)
    			| a3 & (nb2 & nb4 | na2 & a4 | na1)
    			| a1 & na2 & na4 & b2;
		this.nullBit4 = na3 & (nb1 & nb3 & b4
    				| a4 & (nb3 | b1 & b2))
    			| nb2 & (na3 & b1 & nb3	| na2 & (nb1 & b4 | b1 & nb3 | a4))
    			| a3 & (a4 & (nb2 | b1 & b3)
            			| a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3));
		// this and then pot.other: leave iNBit & iNNBit untouched
		if (COVERAGE_TEST_FLAG) {
			if (CoverageTestId == 9) {
			  this.nullBit4 = ~0;
			}
		}
		if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { //  bit1 is redundant
		  	thisHasNulls = true;
		}
	} else {
  		this.nullBit1 = 0;
  		this.nullBit2 = (b2 = otherInits.nullBit2)
  							& ((nb3 = ~(b3 = otherInits.nullBit3)) |
  								(nb1 = ~(b1 = otherInits.nullBit1)));
  		this.nullBit3 = b3 & (nb1 | (nb2 = ~b2));
  		this.nullBit4 = ~b1 & ~b3 & (b4 = otherInits.nullBit4) | ~b2 & (b1 & ~b3 | ~b1 & b4);
		// this and then pot.other: leave iNBit & iNNBit untouched
		if (COVERAGE_TEST_FLAG) {
			if (CoverageTestId == 10) {
			  this.nullBit4 = ~0;
			}
		}
		if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { //  bit1 is redundant
		  	thisHasNulls = true;
		}
	}
	// extra storage management
	if (otherInits.extra != null) {
		int mergeLimit = 0, copyLimit = otherInits.extra[0].length;
		if (this.extra == null) {
			createExtraSpace(copyLimit);
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 11) {
					throw new AssertionFailedException("COVERAGE 11"); //$NON-NLS-1$
				}
			}
		} else {
			mergeLimit = copyLimit;
			if (mergeLimit > this.extra[0].length) {
				mergeLimit = this.extra[0].length;
				for (int j = 0; j < extraLength; j++) {
					System.arraycopy(this.extra[j], 0,
							this.extra[j] = new long[copyLimit], 0,
							mergeLimit);
				}
				if (! thisHadNulls) {
    				mergeLimit = 0;
    				// will do with a copy -- caveat: only valid because definite assignment bits copied above
        			if (COVERAGE_TEST_FLAG) {
        				if (CoverageTestId == 12) {
							throw new AssertionFailedException("COVERAGE 12"); //$NON-NLS-1$
        				}
        			}
				}
			}
		}
		// PREMATURE skip operations for fields
		int i;
		for (i = 0 ; i < mergeLimit ; i++) {
    		this.extra[1 + 1][i]  = (a1 = this.extra[1 + 1][i])
    								& ((a3 = this.extra[3 + 1][i]) & (a4 = this.extra[4 + 1][i])
    									& ((nb2 = ~(b2 = otherInits.extra[2 + 1][i]))
    										& (nb4 = ~(b4 = otherInits.extra[4 + 1][i]))
    											| (b1 = otherInits.extra[1 + 1][i]) & (b3 = otherInits.extra[3 + 1][i]))
                    			| (na2 = ~(a2 = this.extra[2 + 1][i]))
                    				& (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2)
                    			| a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2)));
    		this.extra[2 + 1][i] = b2 & (nb3 | (nb1 = ~b1))
        			| a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1));
    		this.extra[3 + 1][i] = b3 & (nb1 & b2
                		| a2 & (nb2	| a3)
                		| na1 & nb2
                		| a1 & na2 & na4 & b1)
        			| a3 & (nb2 & nb4 | na2 & a4 | na1)
        			| a1 & na2 & na4 & b2;
    		this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4
        				| a4 & (nb3 | b1 & b2))
        			| nb2 & (na3 & b1 & nb3	| na2 & (nb1 & b4 | b1 & nb3 | a4))
        			| a3 & (a4 & (nb2 | b1 & b3)
                			| a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3));
    		// this and then pot.other: leave iNBit & iNNBit untouched
    		if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { //  bit1 is redundant
    		  	thisHasNulls = true;
    		}
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 13) {
				  this.nullBit4 = ~0;
				}
			}
		}
		for (; i < copyLimit; i++) {
    		this.extra[1 + 1][i] = 0;
    		this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i])
    							& ((nb3 = ~(b3 = otherInits.extra[3 + 1][i])) |
    								(nb1 = ~(b1 = otherInits.extra[1 + 1][i])));
    		this.extra[3 + 1][i] = b3 & (nb1 | (nb2 = ~b2));
    		this.extra[4 + 1][i] = ~b1 & ~b3 & (b4 = otherInits.extra[4 + 1][i]) | ~b2 & (b1 & ~b3 | ~b1 & b4);
    		// this and then pot.other: leave iNBit & iNNBit untouched
    		if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { //  bit1 is redundant
    		  	thisHasNulls = true;
    		}
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 14) {
				  this.extra[5][i] = ~0;
				}
			}
		}
	}
	if (thisHasNulls) {
		this.tagBits |= NULL_FLAG_MASK;
	}
	else {
		this.tagBits &= NULL_FLAG_MASK;
	}
	return this;
}

final public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position;
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
		// use bits
		return (
			(~this.nullBit1
					& (this.nullBit2 & this.nullBit3 | this.nullBit4)
				| ~this.nullBit2 & ~this.nullBit3 & this.nullBit4)
			& (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[0].length) {
		return false; // if not enough room in vector, then not initialized
	}
	long a2, a3, a4;
	return (
			(~this.extra[2][vectorIndex]
					& ((a2 = this.extra[3][vectorIndex]) & (a3 = this.extra[4][vectorIndex]) | (a4 = this.extra[5][vectorIndex]))
				| ~a2 & ~a3 & a4)
		    & (1L << (position % BitCacheSize))) != 0;
}

final public boolean cannotBeNull(LocalVariableBinding local) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position;
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
		// use bits
		return (this.nullBit1 & this.nullBit3
			& ((this.nullBit2 & this.nullBit4) | ~this.nullBit2)
			& (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[0].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return (this.extra[2][vectorIndex] & this.extra[4][vectorIndex]
	        & ((this.extra[3][vectorIndex] & this.extra[5][vectorIndex]) |
	        		~this.extra[3][vectorIndex])
		    & (1L << (position % BitCacheSize))) != 0;
}

final public boolean canOnlyBeNull(LocalVariableBinding local) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position;
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
		// use bits
		return (this.nullBit1 & this.nullBit2
			& (~this.nullBit3 | ~this.nullBit4)
			& (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[0].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return (this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
	        & (~this.extra[4][vectorIndex] | ~this.extra[5][vectorIndex])
		    & (1L << (position % BitCacheSize))) != 0;
}

public FlowInfo copy() {
	// do not clone the DeadEnd
	if (this == DEAD_END) {
		return this;
	}
	UnconditionalFlowInfo copy = new UnconditionalFlowInfo();
	// copy slots
	copy.definiteInits = this.definiteInits;
	copy.potentialInits = this.potentialInits;
	boolean hasNullInfo = (this.tagBits & NULL_FLAG_MASK) != 0;
	if (hasNullInfo) {
		copy.nullBit1 = this.nullBit1;
		copy.nullBit2 = this.nullBit2;
		copy.nullBit3 = this.nullBit3;
		copy.nullBit4 = this.nullBit4;
	}
	copy.iNBit = this.iNBit;
	copy.iNNBit = this.iNNBit;
	copy.tagBits = this.tagBits;
	copy.maxFieldCount = this.maxFieldCount;
	if (this.extra != null) {
		int length;
		copy.extra = new long[extraLength][];
		System.arraycopy(this.extra[0], 0,
			(copy.extra[0] = new long[length = this.extra[0].length]), 0,
			length);
		System.arraycopy(this.extra[1], 0,
			(copy.extra[1] = new long[length]), 0, length);
		if (hasNullInfo) {
			for (int j = 2; j < extraLength; j++) {
				System.arraycopy(this.extra[j], 0,
					(copy.extra[j] = new long[length]), 0, length);
			}
		}
		else {
			for (int j = 2; j < extraLength; j++) {
				copy.extra[j] = new long[length];
			}
		}
	}
	return copy;
}

/**
 * Discard definite inits and potential inits from this, then return this.
 * The returned flow info only holds null related information.
 * @return this flow info, minus definite inits and potential inits
 */
public UnconditionalFlowInfo discardInitializationInfo() {
	if (this == DEAD_END) {
		return this;
	}
	this.definiteInits =
		this.potentialInits = 0;
	if (this.extra != null) {
		for (int i = 0, length = this.extra[0].length; i < length; i++) {
			this.extra[0][i] = this.extra[1][i] = 0;
		}
	}
	return this;
}

/**
 * Remove local variables information from this flow info and return this.
 * @return this, deprived from any local variable information
 */
public UnconditionalFlowInfo discardNonFieldInitializations() {
	int limit = this.maxFieldCount;
	if (limit < BitCacheSize) {
		long mask = (1L << limit)-1;
		this.definiteInits &= mask;
		this.potentialInits &= mask;
		this.nullBit1 &= mask;
		this.nullBit2 &= mask;
		this.nullBit3 &= mask;
		this.nullBit4 &= mask;
		this.iNBit &= mask;
		this.iNNBit &= mask;
	}
	// use extra vector
	if (this.extra == null) {
		return this; // if vector not yet allocated, then not initialized
	}
	int vectorIndex, length = this.extra[0].length;
	if ((vectorIndex = (limit / BitCacheSize) - 1) >= length) {
		return this; // not enough room yet
	}
	if (vectorIndex >= 0) {
		// else we only have complete non field array items left
		long mask = (1L << (limit % BitCacheSize))-1;
		for (int j = 0; j < extraLength; j++) {
			this.extra[j][vectorIndex] &= mask;
		}
	}
	for (int i = vectorIndex + 1; i < length; i++) {
		for (int j = 0; j < extraLength; j++) {
			this.extra[j][i] = 0;
		}
	}
	return this;
}

public FlowInfo initsWhenFalse() {
	return this;
}

public FlowInfo initsWhenTrue() {
	return this;
}

/**
 * Check status of definite assignment at a given position.
 * It deals with the dual representation of the InitializationInfo2:
 * bits for the first 64 entries, then an array of booleans.
 */
final private boolean isDefinitelyAssigned(int position) {
	if (position < BitCacheSize) {
		// use bits
		return (this.definiteInits & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null)
		return false; // if vector not yet allocated, then not initialized
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1)
			>= this.extra[0].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[0][vectorIndex]) &
				(1L << (position % BitCacheSize))) != 0;
}

final public boolean isDefinitelyAssigned(FieldBinding field) {
	// Mirrored in CodeStream.isDefinitelyAssigned(..)
	// do not want to complain in unreachable code
	if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0) {
		return true;
	}
//{ObjectTeams: if it is copied don't require definite assignment again
	if (field.copyInheritanceSrc != null)
		return true;
// SH}
	return isDefinitelyAssigned(field.id);
}

final public boolean isDefinitelyAssigned(LocalVariableBinding local) {
	// do not want to complain in unreachable code if local declared in reachable code
	if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0 && (local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0) {
		return true;
	}
	return isDefinitelyAssigned(local.id + this.maxFieldCount);
}

final public boolean isDefinitelyNonNull(LocalVariableBinding local) {
	// do not want to complain in unreachable code
	if ((this.tagBits & UNREACHABLE) != 0 ||
			(this.tagBits & NULL_FLAG_MASK) == 0) {
		return false;
	}
	if ((local.type.tagBits & TagBits.IsBaseType) != 0 ||
			local.constant() != Constant.NotAConstant) { // String instances
		return true;
	}
	int position = local.id + this.maxFieldCount;
	if (position < BitCacheSize) { // use bits
		return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4))
			    & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1)
			>= this.extra[2].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex]
		        & (~this.extra[3][vectorIndex] | this.extra[5][vectorIndex]))
		    & (1L << (position % BitCacheSize))) != 0;
}

final public boolean isDefinitelyNull(LocalVariableBinding local) {
	// do not want to complain in unreachable code
	if ((this.tagBits & UNREACHABLE) != 0 ||
			(this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position = local.id + this.maxFieldCount;
	if (position < BitCacheSize) { // use bits
		return ((this.nullBit1 & this.nullBit2
			        & (~this.nullBit3 | ~this.nullBit4))
			    & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[2].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
		        & (~this.extra[4][vectorIndex] | ~this.extra[5][vectorIndex]))
		    & (1L << (position % BitCacheSize))) != 0;
}

final public boolean isDefinitelyUnknown(LocalVariableBinding local) {
	// do not want to complain in unreachable code
	if ((this.tagBits & UNREACHABLE) != 0 ||
			(this.tagBits & NULL_FLAG_MASK) == 0) {
		return false;
	}
	int position = local.id + this.maxFieldCount;
	if (position < BitCacheSize) { // use bits
		return ((this.nullBit1 & this.nullBit4
				& ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[2].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex]
	    & ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex])
		    & (1L << (position % BitCacheSize))) != 0;
}

//{ObjectTeams: variant for BaseCallTrackingVariable:
      public boolean isDefinitelyAssigned(BaseCallTrackingVariable local) {
              // don't check reachability!
              return isDefinitelyAssigned(local.binding.id + this.maxFieldCount);
      }
//SH}

final public boolean hasNullInfoFor(LocalVariableBinding local) {
	// do not want to complain in unreachable code
	if ((this.tagBits & UNREACHABLE) != 0 ||
			(this.tagBits & NULL_FLAG_MASK) == 0) {
		return false;
	}
	int position = local.id + this.maxFieldCount;
	if (position < BitCacheSize) { // use bits
		return ((this.nullBit1 | this.nullBit2
				| this.nullBit3 | this.nullBit4) & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[2].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[2][vectorIndex] | this.extra[3][vectorIndex]
	    | this.extra[4][vectorIndex] | this.extra[5][vectorIndex])
		    & (1L << (position % BitCacheSize))) != 0;
}

/**
 * Check status of potential assignment at a given position.
 */
final private boolean isPotentiallyAssigned(int position) {
	// id is zero-based
	if (position < BitCacheSize) {
		// use bits
		return (this.potentialInits & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1)
			>= this.extra[0].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[1][vectorIndex]) &
			(1L << (position % BitCacheSize))) != 0;
}

final public boolean isPotentiallyAssigned(FieldBinding field) {
	return isPotentiallyAssigned(field.id);
}

final public boolean isPotentiallyAssigned(LocalVariableBinding local) {
	// final constants are inlined, and thus considered as always initialized
	if (local.constant() != Constant.NotAConstant) {
		return true;
	}
	return isPotentiallyAssigned(local.id + this.maxFieldCount);
}

// TODO (Ayush) Check why this method does not return true for protected non null (1111)
final public boolean isPotentiallyNonNull(LocalVariableBinding local) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position;
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
		// use bits
		return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2))
			    & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[2].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[4][vectorIndex]
		        & (~this.extra[2][vectorIndex] | ~this.extra[3][vectorIndex]))
		    & (1L << (position % BitCacheSize))) != 0;
}

// TODO (Ayush) Check why this method does not return true for protected null
final public boolean isPotentiallyNull(LocalVariableBinding local) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position;
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
		// use bits
		return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3))
			    & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[2].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return ((this.extra[3][vectorIndex]
		        & (~this.extra[2][vectorIndex] | ~this.extra[4][vectorIndex]))
		    & (1L << (position % BitCacheSize))) != 0;
}

final public boolean isPotentiallyUnknown(LocalVariableBinding local) {
	// do not want to complain in unreachable code
	if ((this.tagBits & UNREACHABLE) != 0 ||
			(this.tagBits & NULL_FLAG_MASK) == 0) {
		return false;
	}
	int position = local.id + this.maxFieldCount;
	if (position < BitCacheSize) { // use bits
		return (this.nullBit4
			& (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3)
			& (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[2].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return (this.extra[5][vectorIndex]
	        & (~this.extra[2][vectorIndex]
	            | ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex])
		    & (1L << (position % BitCacheSize))) != 0;
}

final public boolean isProtectedNonNull(LocalVariableBinding local) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position;
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
		// use bits
		return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
		this.extra[0].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return (this.extra[2][vectorIndex]
	            & this.extra[4][vectorIndex]
	            & this.extra[5][vectorIndex]
		    & (1L << (position % BitCacheSize))) != 0;
}

final public boolean isProtectedNull(LocalVariableBinding local) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
		return false;
	}
	int position;
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
		// use bits
		return (this.nullBit1 & this.nullBit2
			& (this.nullBit3 ^ this.nullBit4)
			& (1L << position)) != 0;
	}
	// use extra vector
	if (this.extra == null) {
		return false; // if vector not yet allocated, then not initialized
	}
	int vectorIndex;
	if ((vectorIndex = (position / BitCacheSize) - 1) >=
			this.extra[0].length) {
		return false; // if not enough room in vector, then not initialized
	}
	return (this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
	        & (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex])
		    & (1L << (position % BitCacheSize))) != 0;
}
/** Asserts that the given boolean is <code>true</code>. If this
 * is not the case, some kind of unchecked exception is thrown.
 * The given message is included in that exception, to aid debugging.
 *
 * @param expression the outcome of the check
 * @param message the message to include in the exception
 * @return <code>true</code> if the check passes (does not return
 *    if the check fails)
 */
protected static boolean isTrue(boolean expression, String message) {
	if (!expression)
		throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$
	return expression;
}
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
	// protected from non-object locals in calling methods
	if (this != DEAD_END) {
		this.tagBits |= NULL_FLAG_MASK;
		int position;
		long mask;
		long a1, a2, a3, a4, na2;
		// position is zero-based
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
			// use bits
			if (((mask = 1L << position)
				& (a1 = this.nullBit1)
				& (na2 = ~(a2 = this.nullBit2))
				& ~(a3 = this.nullBit3)
				& (a4 = this.nullBit4))
					!= 0) {
			  	this.nullBit4 &= ~mask;
			} else if ((mask & a1 & na2 & a3) == 0) {
			  	this.nullBit4 |= mask;
			  	if ((mask & a1) == 0) {
			  	  	if ((mask & a2 & (a3 ^ a4)) != 0) {
			  	  	  	this.nullBit2 &= ~mask;
			  	  	}
			  	  	else if ((mask & (a2 | a3 | a4)) == 0) {
			  	  	  	this.nullBit2 |= mask;
			  	  	}
			  	}
			}
			this.nullBit1 |= mask;
			this.nullBit3 |= mask;
			// it was not null;
			this.iNBit &= ~mask;
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 15) {
				  	this.nullBit4 = ~0;
				}
			}
		}
		else {
			// use extra vector
			int vectorIndex = (position / BitCacheSize) - 1;
			if (this.extra == null) {
				int length = vectorIndex + 1;
				createExtraSpace(length);
				if (COVERAGE_TEST_FLAG) {
					if (CoverageTestId == 16) {
						throw new AssertionFailedException("COVERAGE 16"); //$NON-NLS-1$
					}
				}
			}
			else {
				int oldLength;
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
					int newLength = vectorIndex + 1;
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[newLength]), 0,
							oldLength);
					}
					if (COVERAGE_TEST_FLAG) {
						if (CoverageTestId == 17) {
							throw new AssertionFailedException("COVERAGE 17"); //$NON-NLS-1$
						}
					}
				}
			}
			// MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][vectorIndex]/gc
			if (((mask = 1L << (position % BitCacheSize))
  				& (a1 = this.extra[1 + 1][vectorIndex])
  				& (na2 = ~(a2 = this.extra[2 + 1][vectorIndex]))
  				& ~(a3 = this.extra[3 + 1][vectorIndex])
  				& (a4 = this.extra[4 + 1][vectorIndex]))
  					!= 0) {
  			  	this.extra[4 + 1][vectorIndex] &= ~mask;
  			} else if ((mask & a1 & na2 & a3) == 0) {
  			  	this.extra[4 + 1][vectorIndex] |= mask;
  			  	if ((mask & a1) == 0) {
  			  	  	if ((mask & a2 & (a3 ^ a4)) != 0) {
  			  	  	  	this.extra[2 + 1][vectorIndex] &= ~mask;
  			  	  	}
  			  	  	else if ((mask & (a2 | a3 | a4)) == 0) {
  			  	  	  	this.extra[2 + 1][vectorIndex] |= mask;
  			  	  	}
  			  	}
  			}
  			this.extra[1 + 1][vectorIndex] |= mask;
  			this.extra[3 + 1][vectorIndex] |= mask;
			// it was not null;
			this.extra[IN][vectorIndex] &= ~mask;
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 18) {
				  	this.extra[5][vectorIndex] = ~0;
				}
			}
		}
	}
}

public void markAsComparedEqualToNull(LocalVariableBinding local) {
	// protected from non-object locals in calling methods
	if (this != DEAD_END) {
		this.tagBits |= NULL_FLAG_MASK;
		int position;
		long mask;
		// position is zero-based
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
			// use bits
			if (((mask = 1L << position) & this.nullBit1) != 0) {
  			  	if ((mask
  			  		& (~this.nullBit2 | this.nullBit3
  			  			| ~this.nullBit4)) != 0) {
  			  	  	this.nullBit4 &= ~mask;
  			  	}
			} else if ((mask & this.nullBit4) != 0) {
			  	  this.nullBit3 &= ~mask;
			} else {
    			if ((mask & this.nullBit2) != 0) {
    			  	this.nullBit3 &= ~mask;
      			  	this.nullBit4 |= mask;
    			} else {
    			  	this.nullBit3 |= mask;
    			}
			}
			this.nullBit1 |= mask;
			this.nullBit2 |= mask;
			// it was null;
			this.iNNBit &= ~mask;
			if (COVERAGE_TEST_FLAG) {
				if (CoverageTestId == 19) {
				  	this.nullBit4 = ~0;
				}
			}
		}
		else {
			// use extra vector
			int vectorIndex = (position / BitCacheSize) - 1;
			mask = 1L << (position % BitCacheSize);
			if (this.extra == null) {
				int length = vectorIndex + 1;
				createExtraSpace(length);
				if (COVERAGE_TEST_FLAG) {
					if(CoverageTestId == 20) {
						throw new AssertionFailedException("COVERAGE 20"); //$NON-NLS-1$
					}
				}
			}
			else {
				int oldLength;
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
					int newLength = vectorIndex + 1;
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[newLength]), 0,
							oldLength);
					}
					if (COVERAGE_TEST_FLAG) {
						if(CoverageTestId == 21) {
							throw new AssertionFailedException("COVERAGE 21"); //$NON-NLS-1$
						}
					}
				}
			}
			if ((mask & this.extra[1 + 1][vectorIndex]) != 0) {
  			  	if ((mask
  			  		& (~this.extra[2 + 1][vectorIndex] | this.extra[3 + 1][vectorIndex]
  			  			| ~this.extra[4 + 1][vectorIndex])) != 0) {
  			  	  	this.extra[4 + 1][vectorIndex] &= ~mask;
  			  	}
			} else if ((mask & this.extra[4 + 1][vectorIndex]) != 0) {
			  	  this.extra[3 + 1][vectorIndex] &= ~mask;
			} else {
    			if ((mask & this.extra[2 + 1][vectorIndex]) != 0) {
    			  	this.extra[3 + 1][vectorIndex] &= ~mask;
      			  	this.extra[4 + 1][vectorIndex] |= mask;
    			} else {
    			  	this.extra[3 + 1][vectorIndex] |= mask;
    			}
			}
			this.extra[1 + 1][vectorIndex] |= mask;
			this.extra[2 + 1][vectorIndex] |= mask;
			// it was null;
			this.extra[INN][vectorIndex] &= ~mask;
		}
	}
}

/**
 * Record a definite assignment at a given position.
 */
final private void markAsDefinitelyAssigned(int position) {

	if (this != DEAD_END) {
		// position is zero-based
		if (position < BitCacheSize) {
			// use bits
			long mask;
			this.definiteInits |= (mask = 1L << position);
			this.potentialInits |= mask;
		}
		else {
			// use extra vector
			int vectorIndex = (position / BitCacheSize) - 1;
			if (this.extra == null) {
				int length = vectorIndex + 1;
				createExtraSpace(length);
			}
			else {
				int oldLength; // might need to grow the arrays
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[vectorIndex + 1]), 0,
							oldLength);
					}
				}
			}
			long mask;
			this.extra[0][vectorIndex] |=
				(mask = 1L << (position % BitCacheSize));
			this.extra[1][vectorIndex] |= mask;
		}
	}
}

public void markAsDefinitelyAssigned(FieldBinding field) {
	if (this != DEAD_END)
		markAsDefinitelyAssigned(field.id);
}

public void markAsDefinitelyAssigned(LocalVariableBinding local) {
	if (this != DEAD_END)
		markAsDefinitelyAssigned(local.id + this.maxFieldCount);
}

public void markAsDefinitelyNonNull(LocalVariableBinding local) {
	// protected from non-object locals in calling methods
	if (this != DEAD_END) {
    	this.tagBits |= NULL_FLAG_MASK;
    	long mask;
    	int position;
    	// position is zero-based
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
    		// set assigned non null
    		this.nullBit1 |= (mask = 1L << position);
    		this.nullBit3 |= mask;
    		// clear others
    		this.nullBit2 &= (mask = ~mask);
    		this.nullBit4 &= mask;
    		// old value no longer shining through
    		this.iNBit &= mask;
    		this.iNNBit &= mask;
    		if (COVERAGE_TEST_FLAG) {
    			if(CoverageTestId == 22) {
	    		  	this.nullBit1 = 0;
    			}
    		}
    	}
    	else {
    		// use extra vector
    		int vectorIndex = (position / BitCacheSize) - 1;
    		if (this.extra == null) {
    			int length = vectorIndex + 1;
    			createExtraSpace(length);
    		}
    		else {
    			int oldLength; // might need to grow the arrays
    			if (vectorIndex >= (oldLength = this.extra[0].length)) {
    				for (int j = 0; j < extraLength; j++) {
    					System.arraycopy(this.extra[j], 0,
    						(this.extra[j] = new long[vectorIndex + 1]), 0,
    						oldLength);
    				}
    			}
    		}
    		this.extra[2][vectorIndex]
    		    |= (mask = 1L << (position % BitCacheSize));
    		this.extra[4][vectorIndex] |= mask;
    		this.extra[3][vectorIndex] &= (mask = ~mask);
    		this.extra[5][vectorIndex] &= mask;
    		// old value no longer shining through
    		this.extra[IN][vectorIndex] &= mask;
    		this.extra[INN][vectorIndex] &= mask;
    		if (COVERAGE_TEST_FLAG) {
    			if(CoverageTestId == 23) {
	    			this.extra[2][vectorIndex] = 0;
    			}
    		}
    	}
	}
}

public void markAsDefinitelyNull(LocalVariableBinding local) {
	// protected from non-object locals in calling methods
	if (this != DEAD_END) {
    	this.tagBits |= NULL_FLAG_MASK;
    	long mask;
    	int position;
    	// position is zero-based
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
    		// mark assigned null
    		this.nullBit1 |= (mask = 1L << position);
    		this.nullBit2 |= mask;
    		// clear others
    		this.nullBit3 &= (mask = ~mask);
    		this.nullBit4 &= mask;
    		// old value no longer shining through
    		this.iNBit &= mask;
    		this.iNNBit &= mask;
    		if (COVERAGE_TEST_FLAG) {
    			if(CoverageTestId == 24) {
	    		  	this.nullBit4 = ~0;
    			}
    		}
    	}
    	else {
    		// use extra vector
    		int vectorIndex = (position / BitCacheSize) - 1;
    		if (this.extra == null) {
    			int length = vectorIndex + 1;
    			createExtraSpace(length);
    		}
    		else {
    			int oldLength; // might need to grow the arrays
    			if (vectorIndex >= (oldLength = this.extra[0].length)) {
    				for (int j = 0; j < extraLength; j++) {
    					System.arraycopy(this.extra[j], 0,
    						(this.extra[j] = new long[vectorIndex + 1]), 0,
    						oldLength);
    				}
    			}
    		}
    		this.extra[2][vectorIndex]
    		    |= (mask = 1L << (position % BitCacheSize));
    		this.extra[3][vectorIndex] |= mask;
    		this.extra[4][vectorIndex] &= (mask = ~mask);
    		this.extra[5][vectorIndex] &= mask;
    		// old value no longer shining through
    		this.extra[IN][vectorIndex] &= mask;
    		this.extra[INN][vectorIndex] &= mask;
    		if (COVERAGE_TEST_FLAG) {
    			if(CoverageTestId == 25) {
	    			this.extra[5][vectorIndex] = ~0;
    			}
    		}
    	}
	}
}

/**
 * Mark a local as having been assigned to an unknown value.
 * @param local the local to mark
 */
// PREMATURE may try to get closer to markAsDefinitelyAssigned, but not
//			 obvious
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
	// protected from non-object locals in calling methods
	if (this != DEAD_END) {
		this.tagBits |= NULL_FLAG_MASK;
		long mask;
		int position;
		// position is zero-based
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
			// use bits
			// mark assigned null
			this.nullBit1 |= (mask = 1L << position);
			this.nullBit4 |= mask;
			// clear others
			this.nullBit2 &= (mask = ~mask);
			this.nullBit3 &= mask;
    		// old value no longer shining through
    		this.iNBit &= mask;
    		this.iNNBit &= mask;
			if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 26) {
				  	this.nullBit4 = 0;
				}
			}
		}
		else {
			// use extra vector
			int vectorIndex = (position / BitCacheSize) - 1;
			if (this.extra == null) {
				int length = vectorIndex + 1;
				createExtraSpace(length);
			}
			else {
				int oldLength; // might need to grow the arrays
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[vectorIndex + 1]), 0,
							oldLength);
					}
				}
			}
			this.extra[2][vectorIndex]
			    |= (mask = 1L << (position % BitCacheSize));
			this.extra[5][vectorIndex] |= mask;
			this.extra[3][vectorIndex] &= (mask = ~mask);
			this.extra[4][vectorIndex] &= mask;
    		// old value no longer shining through
    		this.extra[IN][vectorIndex] &= mask;
    		this.extra[INN][vectorIndex] &= mask;
			if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 27) {
					this.extra[5][vectorIndex] = 0;
				}
			}
		}
	}
}

public void resetNullInfo(LocalVariableBinding local) {
	if (this != DEAD_END) {
		this.tagBits |= NULL_FLAG_MASK;
        int position;
        long mask;
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
            // use bits
            this.nullBit1 &= (mask = ~(1L << position));
            this.nullBit2 &= mask;
            this.nullBit3 &= mask;
            this.nullBit4 &= mask;
            this.iNBit &= mask;
            this.iNNBit &= mask;
        } else {
    		// use extra vector
    		int vectorIndex = (position / BitCacheSize) - 1;
    		if (this.extra == null || vectorIndex >= this.extra[2].length) {
    			// in case we attempt to reset the null info of a variable that has not been encountered
    			// before and for which no null bits exist.
    			return;
    		}
    		this.extra[2][vectorIndex]
    		    &= (mask = ~(1L << (position % BitCacheSize)));
    		this.extra[3][vectorIndex] &= mask;
    		this.extra[4][vectorIndex] &= mask;
    		this.extra[5][vectorIndex] &= mask;
    		this.extra[IN][vectorIndex] &= mask;
    		this.extra[INN][vectorIndex] &= mask;
    	}
	}
}

/**
 * Mark a local as potentially having been assigned to an unknown value.
 * @param local the local to mark
 */
public void markPotentiallyUnknownBit(LocalVariableBinding local) {
	// protected from non-object locals in calling methods
	if (this != DEAD_END) {
		this.tagBits |= NULL_FLAG_MASK;
        int position;
        long mask;
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
            // use bits
        	mask = 1L << position;
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
            this.nullBit4 |= mask;
            if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 44) {
				  	this.nullBit4 = 0;
				}
			}
        } else {
    		// use extra vector
    		int vectorIndex = (position / BitCacheSize) - 1;
    		if (this.extra == null) {
				int length = vectorIndex + 1;
				createExtraSpace(length);
			}
			else {
				int oldLength; // might need to grow the arrays
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[vectorIndex + 1]), 0,
							oldLength);
					}
				}
			}
    		mask = 1L << (position % BitCacheSize);
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
    		this.extra[5][vectorIndex] |= mask;
    		if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 45) {
					this.extra[2][vectorIndex] = ~0;
					this.extra[3][vectorIndex] = ~0;
					this.extra[4][vectorIndex] = 0;
					this.extra[5][vectorIndex] = 0;
				}
			}
    	}
	}
}

public void markPotentiallyNullBit(LocalVariableBinding local) {
	if (this != DEAD_END) {
		this.tagBits |= NULL_FLAG_MASK;
        int position;
        long mask;
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
            // use bits
        	mask = 1L << position;
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
            this.nullBit2 |= mask;
            if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 40) {
				  	this.nullBit2 = 0;
				}
			}
        } else {
    		// use extra vector
    		int vectorIndex = (position / BitCacheSize) - 1;
    		if (this.extra == null) {
				int length = vectorIndex + 1;
				createExtraSpace(length);
			}
			else {
				int oldLength; // might need to grow the arrays
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[vectorIndex + 1]), 0,
							oldLength);
					}
				}
			}
    		mask = 1L << (position % BitCacheSize);
    		this.extra[3][vectorIndex] |= mask;
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
    		if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 41) {
					this.extra[3][vectorIndex] = 0;
				}
			}
    	}
	}
}

public void markPotentiallyNonNullBit(LocalVariableBinding local) {
	if (this != DEAD_END) {
		this.tagBits |= NULL_FLAG_MASK;
        int position;
        long mask;
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
            // use bits
        	mask = 1L << position;
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
            this.nullBit3 |= mask;
            if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 42) {
				  	this.nullBit1 = ~0;
				  	this.nullBit2 = 0;
				  	this.nullBit3 = ~0;
				  	this.nullBit4 = 0;
				}
			}
        } else {
    		// use extra vector
    		int vectorIndex  = (position / BitCacheSize) - 1;
    		if (this.extra == null) {
				int length = vectorIndex + 1;
				createExtraSpace(length);
			}
			else {
				int oldLength; // might need to grow the arrays
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[vectorIndex + 1]), 0,
							oldLength);
					}
				}
			}
    		mask = 1L << (position % BitCacheSize);
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
    		this.extra[4][vectorIndex] |= mask;
    		if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 43) {
					this.extra[2][vectorIndex] = ~0;
					this.extra[3][vectorIndex] = 0;
					this.extra[4][vectorIndex] = ~0;
					this.extra[5][vectorIndex] = 0;
				}
			}
    	}
	}
}

public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
	if ((otherInits.tagBits & UNREACHABLE_OR_DEAD) != 0 && this != DEAD_END) {
		if (COVERAGE_TEST_FLAG) {
			if(CoverageTestId == 28) {
				throw new AssertionFailedException("COVERAGE 28"); //$NON-NLS-1$
			}
		}
		return this;
	}
	if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0) {
		if (COVERAGE_TEST_FLAG) {
			if(CoverageTestId == 29) {
				throw new AssertionFailedException("COVERAGE 29"); //$NON-NLS-1$
			}
		}
		return (UnconditionalFlowInfo) otherInits.copy(); // make sure otherInits won't be affected
	}

	// intersection of definitely assigned variables,
	this.definiteInits &= otherInits.definiteInits;
	// union of potentially set ones
	this.potentialInits |= otherInits.potentialInits;

	// null combinations
	boolean
		thisHasNulls = (this.tagBits & NULL_FLAG_MASK) != 0,
		otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0,
		thisHadNulls = thisHasNulls;
	long
		a1, a2, a3, a4,
		na1, na2, na3, na4,
		nb1, nb2, nb3, nb4,
		b1, b2, b3, b4;
	if ((otherInits.tagBits & FlowInfo.UNREACHABLE_BY_NULLANALYSIS) != 0) {
		otherHasNulls = false; // skip merging, otherInits is unreachable by null analysis
	} else if ((this.tagBits & FlowInfo.UNREACHABLE_BY_NULLANALYSIS) != 0) { // directly copy if this is unreachable by null analysis
		this.nullBit1 = otherInits.nullBit1;
		this.nullBit2 = otherInits.nullBit2;
		this.nullBit3 = otherInits.nullBit3;
		this.nullBit4 = otherInits.nullBit4;
		this.iNBit = otherInits.iNBit;
		this.iNNBit = otherInits.iNNBit;
		thisHadNulls = false;
		thisHasNulls = otherHasNulls;
		this.tagBits = otherInits.tagBits;
	} else if (thisHadNulls) {
    	if (otherHasNulls) {
    		this.nullBit1 = (a1 = this.nullBit1) & (b1 = otherInits.nullBit1) & (
    				((a2 = this.nullBit2) & (((b2 = otherInits.nullBit2) & 
    											~(((a3=this.nullBit3) & (a4=this.nullBit4)) ^ ((b3=otherInits.nullBit3) & (b4=otherInits.nullBit4))))
    										|(a3 & a4 & (nb2 = ~b2))))
    				|((na2 = ~a2) & ((b2 & b3 & b4)
    								|(nb2 & ((na3 = ~a3) ^ b3)))));
    		this.nullBit2 = b2 & ((nb3 = ~b3) | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & (nb4 = ~b4))
        			| a2 & (b2 | (na4 = ~a4) & b3 & (b4 | nb1) | na3 | na1);
    		this.nullBit3 =   a3 & (na1 | a1 & na2 | b3 & (na4 ^ b4))
    						| b3 & (nb1 | b1 & nb2);
    		this.nullBit4 = na3 & (nb1 & nb3 & b4
              			| b1 & (nb2 & nb3 | a4 & b2 & nb4)
              			| na1 & a4 & (nb3 | b1 & b2))
        			| a3 & a4 & (b3 & b4 | b1 & nb2 | na1 & a2)
        			| na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2
        			| a1 & (na3 & (nb3 & b4
                        			| b1 & b2 & b3 & nb4
                        			| na2 & (nb3 | nb2))
                			| na2 & b3 & b4
                			| a2 & (nb1 & b4 | a3 & na4 & b1) & nb3)
                	|nb1 & b2 & b3 & b4;

    		if (COVERAGE_TEST_FLAG) {
    			if(CoverageTestId == 30) {
	    		  	this.nullBit4 = ~0;
    			}
    		}
    	} else { // other has no null info
    		a1 = this.nullBit1;
      		this.nullBit1 = 0;
      		this.nullBit2 = (a2 = this.nullBit2) & (na3 = ~(a3 = this.nullBit3) | (na1 = ~a1));
      		this.nullBit3 = a3 & ((na2 = ~a2) & (a4 = this.nullBit4) | na1) | a1 & na2 & ~a4;
      		this.nullBit4 = (na3 | na2) & na1 & a4	| a1 & na3 & na2;
    		if (COVERAGE_TEST_FLAG) {
    			if(CoverageTestId == 31) {
	    		  	this.nullBit4 = ~0;
    			}
    		}
    	}
    	this.iNBit |= otherInits.iNBit;
    	this.iNNBit |= otherInits.iNNBit;
	} else if (otherHasNulls) { // only other had nulls
  		this.nullBit1 = 0;
  		this.nullBit2 = (b2 = otherInits.nullBit2) & (nb3 = ~(b3 = otherInits.nullBit3) | (nb1 = ~(b1 = otherInits.nullBit1)));
  		this.nullBit3 = b3 & ((nb2 = ~b2) & (b4 = otherInits.nullBit4) | nb1) | b1 & nb2 & ~b4;
  		this.nullBit4 = (nb3 | nb2) & nb1 & b4	| b1 & nb3 & nb2;
  		this.iNBit |= otherInits.iNBit;
  		this.iNNBit |= otherInits.iNNBit;
  		if (COVERAGE_TEST_FLAG) {
  			if(CoverageTestId == 32) {
	  		  	this.nullBit4 = ~0;
  			}
  		}
    	thisHasNulls =
    		// redundant with the three following ones
    		this.nullBit2 != 0 ||
    		this.nullBit3 != 0 ||
    		this.nullBit4 != 0;
	}

	// treating extra storage
	if (this.extra != null || otherInits.extra != null) {
		int mergeLimit = 0, copyLimit = 0, resetLimit = 0;
		int i;
		if (this.extra != null) {
			if (otherInits.extra != null) {
				// both sides have extra storage
				int length, otherLength;
				if ((length = this.extra[0].length) <
						(otherLength = otherInits.extra[0].length)) {
					// current storage is shorter -> grow current
					for (int j = 0; j < extraLength; j++) {
						System.arraycopy(this.extra[j], 0,
							(this.extra[j] = new long[otherLength]), 0, length);
					}
					mergeLimit = length;
					copyLimit = otherLength;
					if (COVERAGE_TEST_FLAG) {
						if(CoverageTestId == 33) {
							throw new AssertionFailedException("COVERAGE 33"); //$NON-NLS-1$
						}
					}
				}
				else {
					// current storage is longer
					mergeLimit = otherLength;
					resetLimit = length;
					if (COVERAGE_TEST_FLAG) {
						if(CoverageTestId == 34) {
							throw new AssertionFailedException("COVERAGE 34"); //$NON-NLS-1$
						}
					}
				}
			}
			else {
				resetLimit = this.extra[0].length;
				if (COVERAGE_TEST_FLAG) {
					if(CoverageTestId == 35) {
						throw new AssertionFailedException("COVERAGE 35"); //$NON-NLS-1$
					}
				}
			}
		}
		else if (otherInits.extra != null) {
			// no storage here, but other has extra storage.
			int otherLength = otherInits.extra[0].length;
			this.extra = new long[extraLength][];
			for (int j = 0; j < extraLength; j++) {
				this.extra[j] = new long[otherLength];
			}
			System.arraycopy(otherInits.extra[1], 0,
				this.extra[1], 0, otherLength);
			System.arraycopy(otherInits.extra[IN], 0, this.extra[IN], 0, otherLength);
			System.arraycopy(otherInits.extra[INN], 0, this.extra[INN], 0, otherLength);
			copyLimit = otherLength;
			if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 36) {
					throw new AssertionFailedException("COVERAGE 36"); //$NON-NLS-1$
				}
			}
		}
        // MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][i]/g
		// manage definite assignment
		for (i = 0; i < mergeLimit; i++) {
	  		this.extra[0][i] &= otherInits.extra[0][i];
	  		this.extra[1][i] |= otherInits.extra[1][i];
		}
		for (; i < copyLimit; i++) {
		  	this.extra[1][i] = otherInits.extra[1][i];
		}
		for (; i < resetLimit; i++) {
		  	this.extra[0][i] = 0;
		}
		// refine null bits requirements
		if (!otherHasNulls) {
		  if (resetLimit < mergeLimit) {
			resetLimit = mergeLimit;
		  }
		  copyLimit = 0; // no need to carry inexisting nulls
		  mergeLimit = 0;
		}
		if (!thisHadNulls) {
		  resetLimit = 0; // no need to reset anything
		}
		// compose nulls
		for (i = 0; i < mergeLimit; i++) {
    		this.extra[1 + 1][i] = (a1=this.extra[1+1][i]) & (b1=otherInits.extra[1+1][i]) & (
    				((a2=this.extra[2+1][i]) & (((b2=otherInits.extra[2+1][i]) & 
    												~(((a3=this.extra[3+1][i]) & (a4=this.extra[4+1][i])) ^ ((b3=otherInits.extra[3+1][i]) & (b4=otherInits.extra[4+1][i]))))
    											|(a3 & a4 & (nb2=~b2))))
    				|((na2=~a2) & ((b2 & b3 & b4)
    						|(nb2 & ((na3=~a3) ^ b3)))));
    		this.extra[2 + 1][i] = b2 & ((nb3=~b3) | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & (nb4=~b4))
        			| a2 & (b2 | (na4=~a4) & b3 & (b4 | nb1) | na3 | na1);
    		this.extra[3 + 1][i] =   a3 & (na1 | a1 & na2 | b3 & (na4 ^ b4))
								   | b3 & (nb1 | b1 & nb2);
    		this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4
              			| b1 & (nb2 & nb3 | a4 & b2 & nb4)
              			| na1 & a4 & (nb3 | b1 & b2))
        			| a3 & a4 & (b3 & b4 | b1 & nb2 | na1 & a2)
        			| na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2
        			| a1 & (na3 & (nb3 & b4
                        			| b1 & b2 & b3 & nb4
                        			| na2 & (nb3 | nb2))
                			| na2 & b3 & b4
                			| a2 & (nb1 & b4 | a3 & na4 & b1) & nb3)
                	|nb1 & b2 & b3 & b4;
    		this.extra[IN][i] |= otherInits.extra[IN][i];
    		this.extra[INN][i] |= otherInits.extra[INN][i];
			thisHasNulls = thisHasNulls ||
				this.extra[3][i] != 0 ||
				this.extra[4][i] != 0 ||
				this.extra[5][i] != 0 ;
			if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 37) {
					this.extra[5][i] = ~0;
				}
			}
		}
		for (; i < copyLimit; i++) {
    		this.extra[1 + 1][i] = 0;
    		this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i]) & (nb3 = ~(b3 = otherInits.extra[3 + 1][i]) | (nb1 = ~(b1 = otherInits.extra[1 + 1][i])));
    		this.extra[3 + 1][i] = b3 & ((nb2 = ~b2) & (b4 = otherInits.extra[4 + 1][i]) | nb1) | b1 & nb2 & ~b4;
    		this.extra[4 + 1][i] = (nb3 | nb2) & nb1 & b4	| b1 & nb3 & nb2;
    		this.extra[IN][i] |= otherInits.extra[IN][i];
    		this.extra[INN][i] |= otherInits.extra[INN][i];
			thisHasNulls = thisHasNulls ||
				this.extra[3][i] != 0 ||
				this.extra[4][i] != 0 ||
				this.extra[5][i] != 0;
			if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 38) {
					this.extra[5][i] = ~0;
				}
			}
		}
		for (; i < resetLimit; i++) {
    		a1 = this.extra[1 + 1][i];
      		this.extra[1 + 1][i] = 0;
      		this.extra[2 + 1][i] = (a2 = this.extra[2 + 1][i]) & (na3 = ~(a3 = this.extra[3 + 1][i]) | (na1 = ~a1));
      		this.extra[3 + 1][i] = a3 & ((na2 = ~a2) & (a4 = this.extra[4 + 1][i]) | na1) | a1 & na2 & ~a4;
      		this.extra[4 + 1][i] = (na3 | na2) & na1 & a4	| a1 & na3 & na2;
			thisHasNulls = thisHasNulls ||
				this.extra[3][i] != 0 ||
				this.extra[4][i] != 0 ||
				this.extra[5][i] != 0;
			if (COVERAGE_TEST_FLAG) {
				if(CoverageTestId == 39) {
					this.extra[5][i] = ~0;
				}
			}
		}
	}
	if (thisHasNulls) {
		this.tagBits |= NULL_FLAG_MASK;
	}
	else {
		this.tagBits &= ~NULL_FLAG_MASK;
	}
	return this;
}

/*
 * Answer the total number of fields in enclosing types of a given type
 */
static int numberOfEnclosingFields(ReferenceBinding type){
	int count = 0;
	type = type.enclosingType();
	while(type != null) {
		count += type.fieldCount();
		type = type.enclosingType();
	}
	return count;
}

public UnconditionalFlowInfo nullInfoLessUnconditionalCopy() {
	if (this == DEAD_END) {
		return this;
	}
	UnconditionalFlowInfo copy = new UnconditionalFlowInfo();
	copy.definiteInits = this.definiteInits;
	copy.potentialInits = this.potentialInits;
	// no nullness known means: any previous nullness could shine through:
	copy.iNBit = -1L;
	copy.iNNBit = -1L;
	copy.tagBits = this.tagBits & ~NULL_FLAG_MASK;
	copy.tagBits |= UNROOTED;
	copy.maxFieldCount = this.maxFieldCount;
	if (this.extra != null) {
		int length;
		copy.extra = new long[extraLength][];
		System.arraycopy(this.extra[0], 0,
			(copy.extra[0] =
				new long[length = this.extra[0].length]), 0, length);
		System.arraycopy(this.extra[1], 0,
			(copy.extra[1] = new long[length]), 0, length);
		for (int j = 2; j < extraLength; j++) {
			copy.extra[j] = new long[length];
		}
		// no nullness known means: any previous nullness could shine through:
		Arrays.fill(copy.extra[IN], -1L);
		Arrays.fill(copy.extra[INN], -1L);
	}
	return copy;
}

public FlowInfo safeInitsWhenTrue() {
	return copy();
}

public FlowInfo setReachMode(int reachMode) {
	if (this == DEAD_END) {// cannot modify DEAD_END
		return this;
	}	
	if (reachMode == REACHABLE ) {
		this.tagBits &= ~UNREACHABLE;
	} else if (reachMode == UNREACHABLE_BY_NULLANALYSIS ) {
		this.tagBits |= UNREACHABLE_BY_NULLANALYSIS;	// do not interfere with definite assignment analysis
	} else {
		if ((this.tagBits & UNREACHABLE) == 0) {
			// reset optional inits when becoming unreachable
			// see InitializationTest#test090 (and others)
			this.potentialInits = 0;
			if (this.extra != null) {
				for (int i = 0, length = this.extra[0].length;
						i < length; i++) {
					this.extra[1][i] = 0;
				}
			}
		}
		this.tagBits |= reachMode;
	}
	return this;
}

public String toString(){
	// PREMATURE consider printing bit fields as 0001 0001 1000 0001...
	if (this == DEAD_END){
		return "FlowInfo.DEAD_END"; //$NON-NLS-1$
	}
	if ((this.tagBits & NULL_FLAG_MASK) != 0) {
		if (this.extra == null) {
			return "FlowInfo<def: " + this.definiteInits //$NON-NLS-1$
				+", pot: " + this.potentialInits  //$NON-NLS-1$
				+ ", reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
				+", null: " + this.nullBit1 //$NON-NLS-1$
					+ this.nullBit2 + this.nullBit3 + this.nullBit4
				+", incoming: " + this.iNBit + this.iNNBit //$NON-NLS-1$
				+">"; //$NON-NLS-1$
		}
		else {
			String def = "FlowInfo<def:[" + this.definiteInits, //$NON-NLS-1$
				pot = "], pot:[" + this.potentialInits, //$NON-NLS-1$
				nullS = ", null:[" + this.nullBit1 //$NON-NLS-1$
					+ this.nullBit2 + this.nullBit3 + this.nullBit4;
			int i, ceil;
			for (i = 0, ceil = this.extra[0].length > 3 ?
								3 :
								this.extra[0].length;
				i < ceil; i++) {
				def += "," + this.extra[0][i]; //$NON-NLS-1$
				pot += "," + this.extra[1][i]; //$NON-NLS-1$
				nullS += "," + this.extra[2][i] //$NON-NLS-1$
				    + this.extra[3][i] + this.extra[4][i] + this.extra[5][i]
					+", incoming: " + this.extra[IN][i] + this.extra[INN]; //$NON-NLS-1$
			}
			if (ceil < this.extra[0].length) {
				def += ",..."; //$NON-NLS-1$
				pot += ",..."; //$NON-NLS-1$
				nullS += ",..."; //$NON-NLS-1$
			}
			return def + pot
				+ "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
				+ nullS
				+ "]>"; //$NON-NLS-1$
		}
	}
	else {
		if (this.extra == null) {
			return "FlowInfo<def: " + this.definiteInits //$NON-NLS-1$
				+", pot: " + this.potentialInits  //$NON-NLS-1$
				+ ", reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
				+", no null info>"; //$NON-NLS-1$
		}
		else {
			String def = "FlowInfo<def:[" + this.definiteInits, //$NON-NLS-1$
				pot = "], pot:[" + this.potentialInits; //$NON-NLS-1$
			int i, ceil;
			for (i = 0, ceil = this.extra[0].length > 3 ?
								3 :
								this.extra[0].length;
				i < ceil; i++) {
				def += "," + this.extra[0][i]; //$NON-NLS-1$
				pot += "," + this.extra[1][i]; //$NON-NLS-1$
			}
			if (ceil < this.extra[0].length) {
				def += ",..."; //$NON-NLS-1$
				pot += ",..."; //$NON-NLS-1$
			}
			return def + pot
				+ "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
				+ ", no null info>"; //$NON-NLS-1$
		}
	}
}

public UnconditionalFlowInfo unconditionalCopy() {
	return (UnconditionalFlowInfo) copy();
}

public UnconditionalFlowInfo unconditionalFieldLessCopy() {
	// TODO (maxime) may consider leveraging null contribution verification as it is done in copy
	UnconditionalFlowInfo copy = new UnconditionalFlowInfo();
	copy.tagBits = this.tagBits;
	copy.maxFieldCount = this.maxFieldCount;
	int limit = this.maxFieldCount;
	if (limit < BitCacheSize) {
		long mask;
		copy.definiteInits = this.definiteInits & (mask = ~((1L << limit)-1));
		copy.potentialInits = this.potentialInits & mask;
		copy.nullBit1 = this.nullBit1 & mask;
		copy.nullBit2 = this.nullBit2 & mask;
		copy.nullBit3 = this.nullBit3 & mask;
		copy.nullBit4 = this.nullBit4 & mask;
		copy.iNBit = this.iNBit & mask;
		copy.iNNBit = this.iNNBit & mask;
	}
	// use extra vector
	if (this.extra == null) {
		return copy; // if vector not yet allocated, then not initialized
	}
	int vectorIndex, length, copyStart;
	if ((vectorIndex = (limit / BitCacheSize) - 1) >=
			(length = this.extra[0].length)) {
		return copy; // not enough room yet
	}
	long mask;
	copy.extra = new long[extraLength][];
	if ((copyStart = vectorIndex + 1) < length) {
		int copyLength = length - copyStart;
		for (int j = 0; j < extraLength; j++) {
			System.arraycopy(this.extra[j], copyStart,
				(copy.extra[j] = new long[length]), copyStart,
				copyLength);
		}
	}
	else if (vectorIndex >= 0) {
		copy.createExtraSpace(length);
	}
	if (vectorIndex >= 0) {
		mask = ~((1L << (limit % BitCacheSize))-1);
		for (int j = 0; j < extraLength; j++) {
			copy.extra[j][vectorIndex] =
				this.extra[j][vectorIndex] & mask;
		}
	}
	return copy;
}

public UnconditionalFlowInfo unconditionalInits() {
	// also see conditional inits, where it requests them to merge
	return this;
}

public UnconditionalFlowInfo unconditionalInitsWithoutSideEffect() {
	return this;
}
public UnconditionalFlowInfo mergeDefiniteInitsWith(UnconditionalFlowInfo otherInits) {
	if ((otherInits.tagBits & UNREACHABLE_OR_DEAD) != 0 && this != DEAD_END) {
		return this;
	}
	if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0) {
		return (UnconditionalFlowInfo) otherInits.copy(); // make sure otherInits won't be affected
	}

	// intersection of definitely assigned variables,
	this.definiteInits &= otherInits.definiteInits;
	if (this.extra != null) {
		if (otherInits.extra != null) {
			// both sides have extra storage
			int i = 0, length, otherLength;
			if ((length = this.extra[0].length) < (otherLength = otherInits.extra[0].length)) {
				// current storage is shorter -> grow current
				for (int j = 0; j < extraLength; j++) {
					System.arraycopy(this.extra[j], 0,
						(this.extra[j] = new long[otherLength]), 0, length);
				}
				for (; i < length; i++) {
					this.extra[0][i] &= otherInits.extra[0][i];
				}
				for (; i < otherLength; i++) {
					this.extra[0][i] = otherInits.extra[0][i];
				}
			}
			else {
				// current storage is longer
				for (; i < otherLength; i++) {
					this.extra[0][i] &= otherInits.extra[0][i];
				}
			}
		} else {
			for (int i = 0; i < this.extra[0].length; i++) {
				this.extra[0][i] = 0;
			}
		}
	}
	else if (otherInits.extra != null) {
		// no storage here, but other has extra storage.
		int otherLength = otherInits.extra[0].length;
		createExtraSpace(otherLength);
		System.arraycopy(otherInits.extra[0], 0, this.extra[0], 0,
				otherLength);
	}
	return this;
}
public void resetAssignmentInfo(LocalVariableBinding local) {
	resetAssignmentInfo(local.id + this.maxFieldCount);
}

public void resetAssignmentInfo(int position) {
	if (this != DEAD_END) {
		// position is zero-based
		if (position < BitCacheSize) {
			// use bits
			long mask;
			this.definiteInits &= (mask = ~(1L << position));
			this.potentialInits &= mask;
		} else {
			// use extra vector
			int vectorIndex = (position / BitCacheSize) - 1;
			if (this.extra == null || vectorIndex >= this.extra[0].length) return;	// variable doesnt exist in flow info
			long mask;
			this.extra[0][vectorIndex] &=
				(mask = ~(1L << (position % BitCacheSize)));
			this.extra[1][vectorIndex] &= mask;
		}
	}
}

private void createExtraSpace(int length) {
	this.extra = new long[extraLength][];
	for (int j = 0; j < extraLength; j++) {
		this.extra[j] = new long[length];
	}
	if ((this.tagBits & UNROOTED) != 0) {
		Arrays.fill(this.extra[IN], -1L);
		Arrays.fill(this.extra[INN], -1L);
	}
}
}

