private void setLanguage(LanguageTranslator translator, CompilerSpecID newCompilerSpecID,
			boolean forceRedisassembly, TaskMonitor monitor) throws LockException {

		checkExclusiveAccess();

		lock.acquire();
		try {
			setEventsEnabled(false);
			try {
				boolean redisassemblyRequired = true;
				LanguageID oldLanguageId = languageID;
				int oldLanguageVersion = languageVersion;
				int oldLanguageMinorVersion = languageMinorVersion;
				if (translator != null) {
					language = translator.getNewLanguage();
					languageID = language.getLanguageID();
					if (newCompilerSpecID == null) {
						newCompilerSpecID = translator.getNewCompilerSpecID(compilerSpecID);
					}
					Msg.info(this, "Setting language for Program " + getName() + ": " + translator);
					Msg.info(this, "Setting compiler spec for Program " + getName() + ": " +
						compilerSpecID + " -> " + newCompilerSpecID);
				}
				else if (!forceRedisassembly && language.getVersion() == languageVersion &&
					language.getMinorVersion() == languageMinorVersion) {
					redisassemblyRequired = false; // compiler spec change only
					Msg.info(this, "Setting compiler spec for Program " + getName() + ": " +
						compilerSpecID + " -> " + newCompilerSpecID);
				}
				else {
					Msg.info(this,
						"Updating language version for Program " + getName() + ": " +
							language.getLanguageDescription() + " (Version " +
							language.getVersion() + "." + language.getMinorVersion() + ")");
				}

				if (newCompilerSpecID != null) {
					compilerSpec = ProgramCompilerSpec.getProgramCompilerSpec(this,
						language.getCompilerSpecByID(newCompilerSpecID));
					if (!oldLanguageId.equals(languageID) ||
						!compilerSpecID.equals(newCompilerSpecID)) {
						if (compilerSpec instanceof ProgramCompilerSpec) {
							((ProgramCompilerSpec) compilerSpec).resetProgramOptions(monitor);
						}
					}
				}
				compilerSpecID = compilerSpec.getCompilerSpecID();
				languageVersion = language.getVersion();
				languageMinorVersion = language.getMinorVersion();

				if (translator != null) {
					addressFactory = new ProgramAddressFactory(language, compilerSpec,
						s -> getDefinedAddressSet(s));

					addrMap.setLanguage(language, addressFactory, translator);
					overlaySpaceAdapter.setLanguage(language, addressFactory, translator);

					memoryManager.setLanguage(language);
					addrMap.memoryMapChanged(memoryManager);

					monitor.setMessage("Updating symbols...");
					getSymbolTable().setLanguage(translator, monitor);
					getFunctionManager().setLanguage(translator, monitor);
				}

				clearCache(true);

				monitor.setMessage("Updating language...");
				monitor.setProgress(0);
				ProgramRegisterContextDB contextMgr =
					(ProgramRegisterContextDB) getProgramContext();

				if (redisassemblyRequired) {
					contextMgr.setLanguage(translator, compilerSpec, memoryManager, monitor);
					repairContext(oldLanguageVersion, oldLanguageMinorVersion, translator, monitor);
					getCodeManager().reDisassembleAllInstructions(monitor);
				}
				else {
					contextMgr.initializeDefaultValues(language, compilerSpec);
				}

				// Update datatype manager data organization
				getDataTypeManager().languageChanged(monitor);

				// Force function manager to reconcile calling conventions
				managers[FUNCTION_MGR].setProgram(this);
				managers[FUNCTION_MGR].programReady(OpenMode.UPDATE, getStoredVersion(), monitor);

				if (translator != null) {
					// allow complex language upgrades to transform instructions/context
					translator.fixupInstructions(this, translator.getOldLanguage(), monitor);
				}

				dataMap.put(LANGUAGE_ID, languageID.getIdAsString());
				dataMap.put(COMPILER_SPEC_ID, compilerSpecID.getIdAsString());
				dataMap.put(LANGUAGE_VERSION, languageVersion + "." + languageMinorVersion);

				setChanged(true);
				clearCache(true);
				invalidate();
			}
			catch (Throwable t) {
				throw new IllegalStateException(
					"Set language aborted - program object is now in an unusable state!", t);
			}
			finally {
				setEventsEnabled(true);
			}
			fireEvent(new DomainObjectChangeRecord(ProgramEvent.LANGUAGE_CHANGED));
		}
		finally {
			lock.release();
		}
	}
Translate language
@param translator language translator, if null only re-disassembly will occur.
@param newCompilerSpecID new compiler specification which corresponds to new language, may be null.
@param forceRedisassembly if true a redisassembly will be forced even if not required
@param monitor task monitor
@throws LockException if exclusive access is missing
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java