| /* |
| * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package org.graalvm.compiler.nodes.spi; |
| |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_100; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_15; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_20; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_30; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_40; |
| import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_80; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_10; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_100; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_15; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_200; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_30; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; |
| import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_80; |
| |
| import org.graalvm.compiler.graph.Node; |
| import org.graalvm.compiler.nodeinfo.NodeCycles; |
| import org.graalvm.compiler.nodeinfo.NodeSize; |
| import org.graalvm.compiler.nodes.CallTargetNode; |
| import org.graalvm.compiler.nodes.Invoke; |
| import org.graalvm.compiler.nodes.LoopEndNode; |
| import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; |
| import org.graalvm.compiler.nodes.extended.SwitchNode; |
| import org.graalvm.compiler.nodes.java.AccessFieldNode; |
| import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; |
| |
| /* |
| * Certain node costs can not, based on the meta information encoded in the node properties, |
| * be computed before a real node is instantiated. E.g. the type of a call in Java heavily |
| * influences the cost of an invocation and thus must be decided dynamically. |
| */ |
| public abstract class DefaultNodeCostProvider implements NodeCostProvider { |
| |
| @Override |
| public final int getEstimatedCodeSize(Node n) { |
| return size(n).estimatedCodeSize; |
| } |
| |
| @Override |
| public final int getEstimatedCPUCycles(Node n) { |
| return cycles(n).estimatedCPUCycles; |
| } |
| |
| @Override |
| public NodeSize size(Node n) { |
| if (n instanceof Invoke) { |
| /* |
| * Code size for the invoke itself is a very weak approximation. |
| */ |
| Invoke ivk = (Invoke) n; |
| CallTargetNode mct = ivk.callTarget(); |
| switch (mct.invokeKind()) { |
| case Interface: |
| return SIZE_50; |
| case Special: |
| case Static: |
| return SIZE_2; |
| case Virtual: |
| return SIZE_4; |
| default: |
| break; |
| } |
| } else if (n instanceof CommitAllocationNode) { |
| CommitAllocationNode commit = (CommitAllocationNode) n; |
| /* |
| * very weak approximation, current problem is node size is an enum and we cannot |
| * dynamically instantiate a new case like nrOfAllocs*allocationCodeSize |
| */ |
| int nrOfAllocs = commit.getVirtualObjects().size(); |
| if (nrOfAllocs < 5) { |
| return SIZE_80; |
| } else if (nrOfAllocs < 10) { |
| return SIZE_100; |
| } else { |
| return SIZE_200; |
| } |
| } else if (n instanceof AccessFieldNode) { |
| if (((AccessFieldNode) n).field().isVolatile()) { |
| // membar size is added |
| return SIZE_10; |
| } |
| } else if (n instanceof LoopEndNode) { |
| if (((LoopEndNode) n).canSafepoint()) { |
| return SIZE_6; |
| } |
| } else if (n instanceof SwitchNode) { |
| SwitchNode x = (SwitchNode) n; |
| int keyCount = x.keyCount(); |
| if (keyCount == 0) { |
| return SIZE_1; |
| } else { |
| if (keyCount == 1) { |
| // if |
| return SIZE_2; |
| } else if (x instanceof IntegerSwitchNode && x.isSorted()) { |
| // good heuristic |
| return SIZE_15; |
| } else { |
| // not so good |
| return SIZE_30; |
| } |
| } |
| } |
| |
| return n.getNodeClass().size(); |
| } |
| |
| @Override |
| public NodeCycles cycles(Node n) { |
| if (n instanceof Invoke) { |
| Invoke ivk = (Invoke) n; |
| CallTargetNode mct = ivk.callTarget(); |
| switch (mct.invokeKind()) { |
| case Interface: |
| return CYCLES_100; |
| case Special: |
| case Static: |
| return CYCLES_2; |
| case Virtual: |
| return CYCLES_4; |
| default: |
| break; |
| } |
| } else if (n instanceof CommitAllocationNode) { |
| CommitAllocationNode commit = (CommitAllocationNode) n; |
| /* |
| * very weak approximation, current problem is node cycles is an enum and we cannot |
| * dynamically instantiate a new case like nrOfAllocs*allocationCost |
| */ |
| int nrOfAllocs = commit.getVirtualObjects().size(); |
| if (nrOfAllocs < 5) { |
| return CYCLES_20; |
| } else if (nrOfAllocs < 10) { |
| return CYCLES_40; |
| } else { |
| return CYCLES_80; |
| } |
| } else if (n instanceof AccessFieldNode) { |
| if (((AccessFieldNode) n).field().isVolatile()) { |
| // membar cycles is added |
| return CYCLES_30; |
| } |
| } else if (n instanceof SwitchNode) { |
| SwitchNode x = (SwitchNode) n; |
| int keyCount = x.keyCount(); |
| if (keyCount == 0) { |
| return CYCLES_1; |
| } else { |
| if (keyCount == 1) { |
| // if |
| return CYCLES_2; |
| } else if (x instanceof IntegerSwitchNode && x.isSorted()) { |
| // good heuristic |
| return CYCLES_15; |
| } else { |
| // not so good |
| return CYCLES_30; |
| } |
| } |
| } |
| |
| return n.getNodeClass().cycles(); |
| } |
| |
| } |