Package org.adoptopenjdk.jitwatch.util

Source Code of org.adoptopenjdk.jitwatch.util.JournalUtil

/*
* Copyright (c) 2013, 2014 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.util;

import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javafx.scene.paint.Color;

import org.adoptopenjdk.jitwatch.model.AnnotationException;
import org.adoptopenjdk.jitwatch.model.CompilerName;
import org.adoptopenjdk.jitwatch.model.Journal;
import org.adoptopenjdk.jitwatch.model.LineAnnotation;
import org.adoptopenjdk.jitwatch.model.Tag;
import org.adoptopenjdk.jitwatch.model.Task;
import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class JournalUtil
{
  private static final Logger logger = LoggerFactory.getLogger(JournalUtil.class);

  private JournalUtil()
  {
  }

  public static Map<Integer, LineAnnotation> buildBytecodeAnnotations(Journal journal, List<BytecodeInstruction> instructions)
      throws AnnotationException
  {
    Map<Integer, LineAnnotation> result = new HashMap<>();

    if (journal != null)
    {
      CompilerName compilerName = getLastTaskCompiler(journal);

      Tag parsePhase = getParsePhase(journal);

      if (parsePhase != null)
      {
        List<Tag> parseTags = parsePhase.getNamedChildren(TAG_PARSE);

        for (Tag parseTag : parseTags)
        {
          buildParseTagAnnotations(parseTag, result, instructions, compilerName);
        }
      }
    }

    return result;
  }

  private static BytecodeInstruction getInstructionAtIndex(List<BytecodeInstruction> instructions, int index)
  {
    BytecodeInstruction found = null;

    for (BytecodeInstruction instruction : instructions)
    {
      if (instruction.getOffset() == index)
      {
        found = instruction;
        break;
      }
    }

    return found;
  }

  private static void buildParseTagAnnotations(Tag parseTag, Map<Integer, LineAnnotation> result,
      List<BytecodeInstruction> instructions, CompilerName compilerName) throws AnnotationException
  {
    List<Tag> children = parseTag.getChildren();

    int currentBytecode = -1;

    Map<String, String> methodAttrs = new HashMap<>();
    Map<String, String> callAttrs = new HashMap<>();

    boolean isC2 = false;

    if (compilerName == CompilerName.C2)
    {
      isC2 = true;
    }

    boolean inMethod = true;
    BytecodeInstruction currentInstruction = null;

    for (Tag child : children)
    {
      String name = child.getName();
      Map<String, String> tagAttrs = child.getAttrs();

      switch (name)
      {
      case TAG_BC:
      {
        String bciAttr = tagAttrs.get(ATTR_BCI);
        String codeAttr = tagAttrs.get(ATTR_CODE);

        currentBytecode = Integer.parseInt(bciAttr);
        int code = Integer.parseInt(codeAttr);
        callAttrs.clear();

        // we found a LogCompilation bc tag
        // e.g. "<bc code='182' bci='2'/>"
        // Now check in the current class bytecode
        // that the instruction at offset bci
        // has the same opcode as attribute code
        // if not then this is probably a TieredCompilation
        // context change. (TieredCompilation does not use
        // nested parse tags so have to use this heuristic
        // to check if we are still in the same method.

        if (DEBUG_LOGGING_BYTECODE)
        {
          logger.debug("BC Tag {} {}", currentBytecode, code);
        }

        currentInstruction = getInstructionAtIndex(instructions, currentBytecode);

        if (DEBUG_LOGGING_BYTECODE)
        {
          logger.debug("Instruction at {} is {}", currentBytecode, currentInstruction);
        }

        inMethod = false;

        if (currentInstruction != null)
        {
          int opcodeValue = currentInstruction.getOpcode().getValue();

          if (opcodeValue == code)
          {
            inMethod = true;
          }
        }
      }
        break;
      case TAG_CALL:
      {
        callAttrs.clear();
        callAttrs.putAll(tagAttrs);
      }
        break;
      case TAG_METHOD:
      {
        methodAttrs.clear();
        methodAttrs.putAll(tagAttrs);

        String nameAttr = methodAttrs.get(ATTR_NAME);

        inMethod = false;

        if (nameAttr != null && currentInstruction != null && currentInstruction.hasComment())
        {
          String comment = currentInstruction.getComment();

          inMethod = comment.contains(nameAttr);
        }
      }
        break;
      case TAG_INLINE_SUCCESS:
      {

        if (inMethod || isC2)
        {
          if (!sanityCheckInline(currentInstruction))
          {
            throw new AnnotationException("Expected an invoke instruction (in INLINE_SUCCESS)", currentBytecode,
                currentInstruction);
          }

          String reason = tagAttrs.get(ATTR_REASON);
          String annotationText = InlineUtil.buildInlineAnnotationText(true, reason, callAttrs, methodAttrs);

          result.put(currentBytecode, new LineAnnotation(annotationText, Color.GREEN));
        }
      }
        break;
      case TAG_INLINE_FAIL:
      {
        if (inMethod || isC2)
        {
          if (!sanityCheckInline(currentInstruction))
          {
            throw new AnnotationException("Expected an invoke instruction (in INLINE_FAIL)", currentBytecode,
                currentInstruction);
          }

          String reason = tagAttrs.get(ATTR_REASON);
          String annotationText = InlineUtil.buildInlineAnnotationText(false, reason, callAttrs, methodAttrs);

          result.put(currentBytecode, new LineAnnotation(annotationText, Color.RED));
        }
      }
        break;
      case TAG_BRANCH:
      {
        if (!result.containsKey(currentBytecode))
        {
          if (inMethod || isC2)
          {
            if (!sanityCheckBranch(currentInstruction))
            {
              throw new AnnotationException("Expected a branch instruction (in BRANCH)", currentBytecode,
                  currentInstruction);
            }

            String branchAnnotation = buildBranchAnnotation(tagAttrs);

            result.put(currentBytecode, new LineAnnotation(branchAnnotation, Color.BLUE));
          }
        }
      }
        break;
      case TAG_INTRINSIC:
      {
        if (inMethod || isC2)
        {
          if (!sanityCheckIntrinsic(currentInstruction))
          {
            for (BytecodeInstruction ins : instructions)
            {
              logger.info("! instruction: {}", ins);
            }

            throw new AnnotationException("Expected an invoke instruction (IN INTRINSIC)", currentBytecode,
                currentInstruction);
          }

          StringBuilder reason = new StringBuilder();
          reason.append("Intrinsic: ").append(tagAttrs.get(ATTR_ID));

          result.put(currentBytecode, new LineAnnotation(reason.toString(), Color.GREEN));
        }
      }
        break;
       
      case TAG_ELIMINATE_ALLOCATION:
        System.out.println("ELIM");
        break;

      default:
        break;
      }
    }
  }

  private static String buildBranchAnnotation(Map<String, String> tagAttrs)
  {
    String count = tagAttrs.get(ATTR_BRANCH_COUNT);
    String taken = tagAttrs.get(ATTR_BRANCH_TAKEN);
    String notTaken = tagAttrs.get(ATTR_BRANCH_NOT_TAKEN);
    String prob = tagAttrs.get(ATTR_BRANCH_PROB);

    StringBuilder reason = new StringBuilder();

    if (count != null)
    {
      reason.append("Count: ").append(count).append(C_NEWLINE);
    }

    reason.append("Branch taken: ").append(taken).append(C_NEWLINE).append("Branch not taken: ").append(notTaken);

    if (prob != null)
    {
      reason.append(C_NEWLINE).append("Taken Probability: ").append(prob);
    }

    return reason.toString();
  }

  public static Task getLastTask(Journal journal)
  {
    // find the latest task tag
    // this is the most recent compile task for the member
    Task lastTask = null;

    for (Tag tag : journal.getEntryList())
    {
      if (tag instanceof Task)
      {
        lastTask = (Task) tag;
      }
    }

    return lastTask;
  }

  // used to detect if class file matches log file
  // only these bytecode instruction should be at the offset
  // for an inlining log statement
  public static boolean sanityCheckInline(BytecodeInstruction instr)
  {
    return sanityCheckInvoke(instr);
  }

  public static boolean sanityCheckIntrinsic(BytecodeInstruction instr)
  {
    return sanityCheckInvoke(instr);
  }

  private static boolean sanityCheckInvoke(BytecodeInstruction instr)
  {
    boolean sane = false;

    if (instr != null)
    {
      sane = instr.isInvoke();
    }

    return sane;
  }

  public static boolean sanityCheckBranch(BytecodeInstruction instr)
  {
    boolean sane = false;

    if (instr != null)
    {
      sane = instr.getOpcode().getMnemonic().startsWith("if");
    }

    return sane;
  }

  public static CompilerName getLastTaskCompiler(Journal journal)
  {
    Task lastTask = getLastTask(journal);

    CompilerName compilerName = null;

    if (lastTask != null)
    {
      compilerName = lastTask.getCompiler();
    }

    return compilerName;
  }

  public static Tag getParsePhase(Journal journal)
  {
    Tag parsePhase = null;

    Task lastTask = getLastTask(journal);

    if (lastTask != null)
    {
      CompilerName compilerName = lastTask.getCompiler();

      String parseAttributeName = ATTR_PARSE;

      if (compilerName == CompilerName.C1)
      {
        parseAttributeName = ATTR_BUILDIR;
      }

      List<Tag> parsePhases = lastTask.getNamedChildrenWithAttribute(TAG_PHASE, ATTR_NAME, parseAttributeName);

      int count = parsePhases.size();

      if (count != 1)
      {
        logger.warn("Unexpected parse phase count: {}", count);
      }
      else
      {
        parsePhase = parsePhases.get(0);
      }
    }

    return parsePhase;
  }
}
TOP

Related Classes of org.adoptopenjdk.jitwatch.util.JournalUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.