001/*
002 * Copyright (c) 2014, 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.truffle.test.builtins;
024
025import java.util.*;
026
027import com.oracle.graal.truffle.*;
028import com.oracle.truffle.api.*;
029import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
030import com.oracle.truffle.api.frame.*;
031import com.oracle.truffle.api.nodes.*;
032import com.oracle.truffle.api.source.*;
033import com.oracle.truffle.sl.builtins.*;
034import com.oracle.truffle.sl.runtime.*;
035
036public abstract class SLGraalRuntimeBuiltin extends SLBuiltinNode {
037
038    public SLGraalRuntimeBuiltin() {
039        super(null);
040        assignSourceSection(SourceSection.createUnavailable("SL Builtin", SLContext.lookupNodeInfo(getClass()).shortName()));
041        if (!(Truffle.getRuntime() instanceof GraalTruffleRuntime)) {
042            throw new AssertionError("Graal runtime builtins can only be used inside of a Graal runtime.");
043        }
044    }
045
046    /**
047     * Finds all call targets available for the same original call target. This might be useful if a
048     * {@link CallTarget} got duplicated due to splitting.
049     */
050    @TruffleBoundary
051    protected static final Set<OptimizedCallTarget> findDuplicateCallTargets(OptimizedCallTarget originalCallTarget) {
052        final Set<OptimizedCallTarget> allCallTargets = new HashSet<>();
053        allCallTargets.add(originalCallTarget);
054        for (RootCallTarget target : Truffle.getRuntime().getCallTargets()) {
055            if (target instanceof OptimizedCallTarget) {
056                OptimizedCallTarget oct = (OptimizedCallTarget) target;
057                if (oct.getSourceCallTarget() == originalCallTarget) {
058                    allCallTargets.add(oct);
059                }
060            }
061        }
062        return allCallTargets;
063    }
064
065    /**
066     * Finds all {@link DirectCallNode} instances calling a certain original {@link CallTarget} in
067     * the caller function.
068     */
069    @TruffleBoundary
070    protected static final Set<DirectCallNode> findCallsTo(OptimizedCallTarget originalCallTarget) {
071        FrameInstance frame = Truffle.getRuntime().getCallerFrame();
072        RootNode root = frame.getCallNode().getRootNode();
073        return findCallsTo(root, originalCallTarget);
074    }
075
076    /**
077     * Finds all {@link DirectCallNode} instances calling a certain original {@link CallTarget} in a
078     * given {@link RootNode}.
079     */
080    @TruffleBoundary
081    protected static final Set<DirectCallNode> findCallsTo(RootNode root, OptimizedCallTarget originalCallTarget) {
082        final Set<DirectCallNode> allCallNodes = new HashSet<>();
083        root.accept(new NodeVisitor() {
084            public boolean visit(Node node) {
085                if (node instanceof DirectCallNode) {
086                    DirectCallNode callNode = (DirectCallNode) node;
087                    if (callNode.getCallTarget() == originalCallTarget || callNode.getClonedCallTarget() == originalCallTarget) {
088                        allCallNodes.add(callNode);
089                    }
090                }
091                return true;
092            }
093        });
094        return allCallNodes;
095    }
096}