public AssemblyMethod parseAssembly()

in core/src/main/java/org/adoptopenjdk/jitwatch/model/assembly/AbstractAssemblyParser.java [56:271]


	public AssemblyMethod parseAssembly(final String assemblyString, boolean isDisassembly)
	{
		final AssemblyLabels labels = new AssemblyLabels();

		String[] lines = assemblyString.split(S_NEWLINE);

		StringBuilder headerBuilder = new StringBuilder();

		AssemblyBlock currentBlock = new AssemblyBlock();

		AssemblyInstruction lastInstruction = null;

		String lastLine = null;

		AssemblyMethod method = new AssemblyMethod(architecture);

		boolean seenInstructions = false;

		for (int i=0; i < lines.length; i++)
		{
			if (DEBUG_LOGGING_ASSEMBLY)
			{
				logger.debug("line: '{}'", lines[i]);
			}

			if (lines[i].trim().startsWith("# {method}"))
			{
				method.setAssemblyMethodSignature(lines[i]);
			}

			String line = lines[i].replace(S_ENTITY_APOS, S_QUOTE);

			line = line.replaceFirst("^ +", "");

			if (line.startsWith(S_HASH))
			{
				if (DEBUG_LOGGING_ASSEMBLY)
				{
					logger.debug("Assembly header: {}", line);
				}

				headerBuilder.append(line).append(S_NEWLINE);
			}
			else if (line.startsWith(S_OPEN_SQUARE_BRACKET))
			{
				if (!"[Constants]".equals(line))
				{
					if (currentBlock.getTitle() != null)
					{
						method.addBlock(currentBlock);

						if (DEBUG_LOGGING_ASSEMBLY)
						{
							logger.debug("stored AssemblyBlock: {} at {}", currentBlock.getTitle(), method.getBlocks().size() - 1);
						}
					}

					currentBlock = new AssemblyBlock();
					currentBlock.setTitle(line);
				}
			}
			else if (line.startsWith(S_SEMICOLON))
			{
				if (DEBUG_LOGGING_ASSEMBLY)
				{
					logger.debug("Extended comment? '{}'", line);
				}

				if (lastInstruction != null)
				{
					lastInstruction.addCommentLine(line);
				}
			}
			else
			{
				if (isDisassembly)
				{
					AssemblyInstruction instr = createInstruction(labels, line);

					if (instr == null && lastLine != null && lastLine.trim().startsWith(S_HASH) && !line.startsWith(S_HEX_PREFIX)
							&& !line.contains(' ' + S_HEX_PREFIX))
					{

						if (headerBuilder.length() > 0)
						{
							// remove last newline
							headerBuilder.setLength(headerBuilder.length() - S_NEWLINE.length());
						}

						headerBuilder.append(line).append(S_NEWLINE);

						// update untrimmedLine since it is used to update
						// lastUntrimmedLine at end of loop
						line = lastLine + line;
					}
					else if (instr == null && lastLine != null && lastLine.trim().startsWith(S_SEMICOLON) && lastInstruction != null)
					{
						lastInstruction.appendToLastCommentLine(line);

						// update untrimmedLine since it is used to update
						// lastUntrimmedLine at end of loop
						line = lastLine + line;
					}
					else
					{
						boolean replaceLast = false;

						if (instr == null && i < lines.length - 1)
						{
							// try appending current and next lines together
							String nextUntrimmedLine = lines[i + 1].replace(S_ENTITY_APOS, S_QUOTE);

							instr = createInstruction(labels, line + nextUntrimmedLine);

							if (instr != null)
							{
								i++;
							}
						}

						if (instr == null && lastInstruction != null)
						{
							// try appending last and current lines together
							instr = createInstruction(labels, lastLine + line);
							if (instr != null)
							{
								replaceLast = true;
							}
						}

						if (instr != null)
						{
							seenInstructions = true;

							if (replaceLast)
							{
								currentBlock.replaceLastInstruction(instr);
							}
							else
							{
								currentBlock.addInstruction(instr);

								if (DEBUG_LOGGING_ASSEMBLY)
								{
									logger.debug("Added instruction {} pos {}", instr.toString(),
											currentBlock.getInstructions().size() - 1);
								}
							}

							if (currentBlock.getTitle() == null)
							{
								currentBlock.setTitle(NATIVE_CODE_ENTRY_POINT);
							}

							lastInstruction = instr;
						}
						else
						{
							if (seenInstructions && !line.trim().startsWith("ImmutableOopMap"))
							{
								logger.error("Could not parse assembly: {}", line);
							}
						}
					}
				}
				else
				{
					AssemblyInstruction instr = createInstructionFromHexaCode(labels, line);

					if (instr != null)
					{
						if (lastInstruction != null && lastInstruction.getAddress() == instr.getAddress())
						{
							if (lastInstruction.getMnemonic().isEmpty())
							{
								lastInstruction.setMnemonic(instr.getMnemonic());
							}
							if (!instr.getCommentLines().isEmpty())
							{
								lastInstruction.getCommentLines().addAll(instr.getCommentLines());
							}
						}
						else
						{
							currentBlock.addInstruction(instr);
							if (DEBUG_LOGGING_ASSEMBLY)
							{
								logger.debug("Added instruction {} pos {}", instr.toString(),
										currentBlock.getInstructions().size() - 1);
							}
							lastInstruction = instr;
						}
					}
					else
					{
						lastInstruction = instr;
					}

				}
			}
			lastLine = line;
		}

		if (DEBUG_LOGGING_ASSEMBLY)
		{
			logger.debug("default AssemblyBlock: {} at {}", currentBlock.getTitle(), method.getBlocks().size());
		}

		method.addBlock(currentBlock);

		method.setHeader(headerBuilder.toString());

		labels.buildLabels();

		return method;
	}