001/* 002 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot; 024 025import java.util.*; 026 027import jdk.internal.jvmci.code.*; 028import jdk.internal.jvmci.meta.*; 029 030import com.oracle.graal.asm.*; 031import com.oracle.graal.asm.Assembler.*; 032import com.oracle.graal.compiler.common.cfg.*; 033import com.oracle.graal.lir.*; 034import com.oracle.graal.lir.StandardOp.BlockEndOp; 035import com.oracle.graal.lir.StandardOp.LabelOp; 036import com.oracle.graal.lir.asm.*; 037import com.oracle.graal.lir.gen.*; 038import com.oracle.graal.lir.phases.*; 039 040public class HotSpotInstructionProfiling extends PostAllocationOptimizationPhase { 041 public static final String COUNTER_GROUP = "INSTRUCTION_COUNTER"; 042 private final String[] instructionsToProfile; 043 044 public HotSpotInstructionProfiling(String instructionsToProfile) { 045 this.instructionsToProfile = instructionsToProfile.split(","); 046 } 047 048 @Override 049 protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, 050 BenchmarkCounterFactory counterFactory) { 051 new Analyzer(lirGenRes.getCompilationUnitName(), lirGenRes.getLIR(), counterFactory).run(); 052 } 053 054 private class Analyzer { 055 private final LIR lir; 056 private final BenchmarkCounterFactory counterFactory; 057 private final LIRInsertionBuffer buffer; 058 private final String compilationUnitName; 059 060 public Analyzer(String compilationUnitName, LIR lir, BenchmarkCounterFactory counterFactory) { 061 this.lir = lir; 062 this.compilationUnitName = compilationUnitName; 063 this.counterFactory = counterFactory; 064 this.buffer = new LIRInsertionBuffer(); 065 } 066 067 public void run() { 068 for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) { 069 doBlock(block); 070 } 071 } 072 073 public void doBlock(AbstractBlockBase<?> block) { 074 List<LIRInstruction> instructions = lir.getLIRforBlock(block); 075 assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; 076 assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); 077 assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2); 078 assert instructions.get(0) instanceof LabelOp : "Not a LabelOp: " + instructions.get(0); 079 assert !(instructions.get(1) instanceof LabelOp) : "Is a LabelOp: " + instructions.get(1); 080 String[] names = new String[instructionsToProfile.length]; 081 String[] groups = new String[instructionsToProfile.length]; 082 Value[] increments = new Value[instructionsToProfile.length]; 083 for (int i = 0; i < instructionsToProfile.length; i++) { 084 names[i] = compilationUnitName; 085 groups[i] = COUNTER_GROUP + " " + instructionsToProfile[i]; 086 increments[i] = JavaConstant.INT_0; 087 } 088 HotSpotCounterOp op = (HotSpotCounterOp) counterFactory.createMultiBenchmarkCounter(names, groups, increments); 089 LIRInstruction inst = new InstructionCounterOp(op, instructionsToProfile); 090 assert inst != null; 091 buffer.init(instructions); 092 buffer.append(1, inst); 093 buffer.finish(); 094 } 095 } 096 097 /** 098 * After assembly the {@link HotSpotBackend#profileInstructions(LIR, CompilationResultBuilder)} 099 * calls this method for patching the instruction counts into the coutner increment code. 100 */ 101 public static void countInstructions(LIR lir, Assembler asm) { 102 InstructionCounterOp lastOp = null; 103 InstructionCounter counter = asm.getInstructionCounter(); 104 for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) { 105 for (LIRInstruction inst : lir.getLIRforBlock(block)) { 106 if (inst instanceof InstructionCounterOp) { 107 InstructionCounterOp currentOp = (InstructionCounterOp) inst; 108 109 if (lastOp != null) { 110 int beginPc = lastOp.countOffsetEnd; 111 int endPc = currentOp.countOffsetBegin; 112 int[] instructionCounts = counter.countInstructions(lastOp.instructionsToProfile, beginPc, endPc); 113 lastOp.delegate.patchCounterIncrement(asm, instructionCounts); 114 } 115 lastOp = ((InstructionCounterOp) inst); 116 } 117 } 118 } 119 if (lastOp != null) { 120 assert lastOp.countOffsetBegin < asm.position(); 121 int beginPc = lastOp.countOffsetBegin; 122 int endPc = asm.position(); 123 int[] instructionCounts = counter.countInstructions(lastOp.instructionsToProfile, beginPc, endPc); 124 lastOp.delegate.patchCounterIncrement(asm, instructionCounts); 125 } 126 } 127 128 public static class InstructionCounterOp extends LIRInstruction { 129 public static final LIRInstructionClass<InstructionCounterOp> TYPE = LIRInstructionClass.create(InstructionCounterOp.class); 130 private final HotSpotCounterOp delegate; 131 private final String[] instructionsToProfile; 132 private int countOffsetBegin; 133 private int countOffsetEnd; 134 135 public InstructionCounterOp(HotSpotCounterOp delegate, String[] instructionsToProfile) { 136 super(TYPE); 137 this.delegate = delegate; 138 this.instructionsToProfile = instructionsToProfile; 139 } 140 141 @Override 142 public void emitCode(CompilationResultBuilder crb) { 143 countOffsetBegin = crb.asm.position(); 144 this.delegate.emitCode(crb); 145 countOffsetEnd = crb.asm.position(); 146 } 147 148 public String[] getInstructionsToProfile() { 149 return instructionsToProfile; 150 } 151 } 152}