public UnconditionalFlowInfo mitigateNullInfoOf(FlowInfo flowInfo) {
	if ((this.tagBits & NULL_FLAG_MASK) == 0) {
		return flowInfo.unconditionalInits();
	}
	long m, m1, nm1, m2, nm2, m3, a2, a3, a4, s1, s2, ns2, s3, ns3, s4, ns4;
	boolean newCopy = false;
	UnconditionalFlowInfo source = flowInfo.unconditionalInits();
	// clear incompatible protections
	m1 = (s1 = source.nullBit1) & (s3 = source.nullBit3)
				& (s4 = source.nullBit4)
			// prot. non null
		& ((a2 = this.nullBit2) | (a4 = this.nullBit4));
			// null or unknown
	m2 = s1 & (s2 = this.nullBit2) & (s3 ^ s4)
			// prot. null
		& ((a3 = this.nullBit3) | a4);
			// non null or unknown
	// clear incompatible assignments
	// PREMATURE check effect of protected non null (no NPE on call)
	// TODO (maxime) code extensive implementation tests
	m3 = s1	& (s2 & (ns3 = ~s3) & (ns4 = ~s4) & (a3 | a4)
				| (ns2 = ~s2) & s3 & ns4 & (a2 | a4)
				| ns2 & ns3 & s4 & (a2 | a3));
	if ((m = (m1 | m2 | m3)) != 0) {
		newCopy = true;
		source = source.unconditionalCopy();
		source.nullBit1 &= ~m;
		source.nullBit2 &= (nm1 = ~m1) & ((nm2 = ~m2) | a4);
		source.nullBit3 &= (nm1 | a2) & nm2;
		source.nullBit4 &= nm1 & nm2;
	}
	if (this.extra != null && source.extra != null) {
		int length = this.extra[2].length, sourceLength = source.extra[0].length;
		if (sourceLength < length) {
			length = sourceLength;
		}
		for (int i = 0; i < length; i++) {
        	m1 = (s1 = source.extra[1 + 1][i]) & (s3 = source.extra[3 + 1][i])
        				& (s4 = source.extra[4 + 1][i])
        		& ((a2 = this.extra[2 + 1][i]) | (a4 = this.extra[4 + 1][i]));
        	m2 = s1 & (s2 = this.extra[2 + 1][i]) & (s3 ^ s4)
        		& ((a3 = this.extra[3 + 1][i]) | a4);
        	m3 = s1	& (s2 & (ns3 = ~s3) & (ns4 = ~s4) & (a3 | a4)
        				| (ns2 = ~s2) & s3 & ns4 & (a2 | a4)
        				| ns2 & ns3 & s4 & (a2 | a3));
        	if ((m = (m1 | m2 | m3)) != 0) {
        	  	if (! newCopy) {
            		newCopy = true;
            		source = source.unconditionalCopy();
        	  	}
        		source.extra[1 + 1][i] &= ~m;
        		source.extra[2 + 1][i] &= (nm1 = ~m1) & ((nm2 = ~m2) | a4);
        		source.extra[3 + 1][i] &= (nm1 | a2) & nm2;
        		source.extra[4 + 1][i] &= nm1 & nm2;
        	}
		}
	}
	return source;
}