protected DFAState addDFAState(DFA dfa, DFAState D) {
		if (D == ERROR) {
			return D;
		}

		synchronized (dfa.states) {
			DFAState existing = dfa.states.get(D);

			if ( existing!=null ) {
				if ( trace_atn_sim ) System.out.println("addDFAState " + D + " exists");
				return existing;
			}

			D.stateNumber = dfa.states.size();

			if (!D.configs.isReadonly()) {
				D.configs.optimizeConfigs(this);
				D.configs.setReadonly(true);
			}

			if ( trace_atn_sim ) System.out.println("addDFAState new "+D);

			dfa.states.put(D, D);
			return D;
		}
	}
Add state {@code D} to the DFA if it is not already present, and return
the actual instance stored in the DFA. If a state equivalent to {@code D}
is already in the DFA, the existing state is returned. Otherwise this
method returns {@code D} after adding it to the DFA.

<p>If {@code D} is {@link #ERROR}, this method returns {@link #ERROR} and
does not change the DFA.</p>

@param dfa The dfa
@param D The DFA state to add
@return The state stored in the DFA. This will be either the existing
state if {@code D} is already in the DFA, or {@code D} itself if the
state was not already present.
runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java