src/vs/workbench/contrib/debug/browser/disassemblyView.ts/DisassemblyView/createEditor
class DisassemblyView:	protected createEditor(parent: HTMLElement): void {
		this._enableSourceCodeRender = this._configurationService.getValue<IDebugConfiguration>('debug').disassemblyView.showSourceCode;
		const lineHeight = this.fontInfo.lineHeight;
		const thisOM = this;
		const delegate = new class implements ITableVirtualDelegate<IDisassembledInstructionEntry>{
			headerRowHeight: number = 0; // No header
			getHeight(row: IDisassembledInstructionEntry): number {
				if (thisOM.isSourceCodeRender && row.instruction.location?.path && row.instruction.line) {
					// instruction line + source lines
					if (row.instruction.endLine) {
						return lineHeight * (row.instruction.endLine - row.instruction.line + 2);
					} else {
						// source is only a single line.
						return lineHeight * 2;
					}
				}

				// just instruction line
				return lineHeight;
			}
		};

		const instructionRenderer = this._register(this._instantiationService.createInstance(InstructionRenderer, this));

		this._disassembledInstructions = this._register(this._instantiationService.createInstance(WorkbenchTable,
			'DisassemblyView', parent, delegate,
			[
				{
					label: '',
					tooltip: '',
					weight: 0,
					minimumWidth: this.fontInfo.lineHeight,
					maximumWidth: this.fontInfo.lineHeight,
					templateId: BreakpointRenderer.TEMPLATE_ID,
					project(row: IDisassembledInstructionEntry): IDisassembledInstructionEntry { return row; }
				},
				{
					label: localize('disassemblyTableColumnLabel', "instructions"),
					tooltip: '',
					weight: 0.3,
					templateId: InstructionRenderer.TEMPLATE_ID,
					project(row: IDisassembledInstructionEntry): IDisassembledInstructionEntry { return row; }
				},
			],
			[
				this._instantiationService.createInstance(BreakpointRenderer, this),
				instructionRenderer,
			],
			{
				identityProvider: { getId: (e: IDisassembledInstructionEntry) => e.instruction.address },
				horizontalScrolling: false,
				overrideStyles: {
					listBackground: editorBackground
				},
				multipleSelectionSupport: false,
				setRowLineHeight: false,
				openOnSingleClick: false,
				accessibilityProvider: new AccessibilityProvider(),
				mouseSupport: false
			}
		)) as WorkbenchTable<IDisassembledInstructionEntry>;

		this.reloadDisassembly();

		this._register(this._disassembledInstructions.onDidScroll(e => {
			if (this._loadingLock) {
				return;
			}

			if (e.oldScrollTop > e.scrollTop && e.scrollTop < e.height) {
				this._loadingLock = true;
				const topElement = Math.floor(e.scrollTop / this.fontInfo.lineHeight) + DisassemblyView.NUM_INSTRUCTIONS_TO_LOAD;
				this.scrollUp_LoadDisassembledInstructions(DisassemblyView.NUM_INSTRUCTIONS_TO_LOAD).then((success) => {
					if (success) {
						this._disassembledInstructions!.reveal(topElement, 0);
					}
					this._loadingLock = false;
				});
			} else if (e.oldScrollTop < e.scrollTop && e.scrollTop + e.height > e.scrollHeight - e.height) {
				this._loadingLock = true;
				this.scrollDown_LoadDisassembledInstructions(DisassemblyView.NUM_INSTRUCTIONS_TO_LOAD).then(() => { this._loadingLock = false; });
			}
		}));

		this._register(this._debugService.getViewModel().onDidFocusStackFrame((stackFrame) => {
			if (this._disassembledInstructions) {
				this.goToAddress();
				this._onDidChangeStackFrame.fire();
			}
		}));

		// refresh breakpoints view
		this._register(this._debugService.getModel().onDidChangeBreakpoints(bpEvent => {
			if (bpEvent && this._disassembledInstructions) {
				// draw viewable BP
				let changed = false;
				bpEvent.added?.forEach((bp) => {
					if (bp instanceof InstructionBreakpoint) {
						const index = this.getIndexFromAddress(bp.instructionReference);
						if (index >= 0) {
							this._disassembledInstructions!.row(index).isBreakpointSet = true;
							this._disassembledInstructions!.row(index).isBreakpointEnabled = bp.enabled;
							changed = true;
						}
					}
				});

				bpEvent.removed?.forEach((bp) => {
					if (bp instanceof InstructionBreakpoint) {
						const index = this.getIndexFromAddress(bp.instructionReference);
						if (index >= 0) {
							this._disassembledInstructions!.row(index).isBreakpointSet = false;
							changed = true;
						}
					}
				});

				bpEvent.changed?.forEach((bp) => {
					if (bp instanceof InstructionBreakpoint) {
						const index = this.getIndexFromAddress(bp.instructionReference);
						if (index >= 0) {
							if (this._disassembledInstructions!.row(index).isBreakpointEnabled !== bp.enabled) {
								this._disassembledInstructions!.row(index).isBreakpointEnabled = bp.enabled;
								changed = true;
							}
						}
					}
				});

				// get an updated list so that items beyond the current range would render when reached.
				this._instructionBpList = this._debugService.getModel().getInstructionBreakpoints();

				if (changed) {
					this._onDidChangeStackFrame.fire();
				}
			}
		}));

		this._register(this._debugService.onDidChangeState(e => {
			if ((e === State.Running || e === State.Stopped) &&
				(this._previousDebuggingState !== State.Running && this._previousDebuggingState !== State.Stopped)) {
				// Just started debugging, clear the view
				this._disassembledInstructions?.splice(0, this._disassembledInstructions.length, [disassemblyNotAvailable]);
				this._enableSourceCodeRender = this._configurationService.getValue<IDebugConfiguration>('debug').disassemblyView.showSourceCode;
			}
			this._previousDebuggingState = e;
		}));
	}