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 com.oracle.truffle.api.*;
026import com.oracle.truffle.api.dsl.*;
027import com.oracle.truffle.api.frame.*;
028import com.oracle.truffle.api.nodes.*;
029import com.oracle.truffle.sl.nodes.*;
030import com.oracle.truffle.sl.runtime.*;
031
032/**
033 * Generates a given number of dummy nodes and replaces the root of the current method with them.
034 * This builtin is guaranteed to be executed only once.
035 */
036@NodeInfo(shortName = "generateDummyNodes")
037public abstract class SLGenerateDummyNodesBuiltin extends SLGraalRuntimeBuiltin {
038
039    @Specialization
040    public Object generateNodes(long count) {
041        CompilerAsserts.neverPartOfCompilation("generateNodes should never get optimized.");
042        FrameInstance callerFrame = Truffle.getRuntime().getCallerFrame();
043        SLRootNode root = (SLRootNode) callerFrame.getCallNode().getRootNode();
044        root.getBodyNode().replace(createBinaryTree((int) (count - 1)));
045        return SLNull.SINGLETON;
046    }
047
048    private SLDummyNode createBinaryTree(int nodeCount) {
049        if (nodeCount > 3) {
050            int leftSize = nodeCount / 2;
051            SLDummyNode left = createBinaryTree(leftSize);
052            SLDummyNode right = createBinaryTree(nodeCount - leftSize - 1);
053            return new SLDummyNode(left, right);
054        } else {
055            if (nodeCount <= 0) {
056                return null;
057            }
058            SLDummyNode left = null;
059            SLDummyNode right = null;
060            if (nodeCount > 1) {
061                left = new SLDummyNode(null, null);
062                if (nodeCount > 2) {
063                    right = new SLDummyNode(null, null);
064                }
065            }
066            return new SLDummyNode(left, right);
067        }
068    }
069
070    @NodeInfo(cost = NodeCost.MONOMORPHIC)
071    private static class SLDummyNode extends SLExpressionNode {
072
073        @Child private SLDummyNode left;
074        @Child private SLDummyNode right;
075
076        public SLDummyNode(SLDummyNode left, SLDummyNode right) {
077            super(null);
078            this.left = left;
079            this.right = right;
080        }
081
082        @Override
083        public Object executeGeneric(VirtualFrame frame) {
084            if (left != null) {
085                left.executeGeneric(frame);
086            }
087            if (right != null) {
088                right.executeGeneric(frame);
089            }
090            return null;
091        }
092
093    }
094
095}