All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jruby.truffle.tools.callgraph.CallGraph Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
 * code is released under a tri EPL/GPL/LGPL license. You can use it,
 * redistribute it and/or modify it under the terms of the:
 *
 * Eclipse Public License version 1.0
 * GNU General Public License version 2
 * GNU Lesser General Public License version 2.1
 */
package org.jruby.truffle.tools.callgraph;

import com.oracle.truffle.api.TruffleOptions;
import org.jruby.truffle.language.RubyRootNode;
import org.jruby.truffle.language.methods.SharedMethodInfo;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class CallGraph {

    private final Map sharedMethodInfoToMethod = new HashMap<>();
    private final Map rootNodeToMethodVersion = new HashMap<>();
    private final Map>> localTypes = new HashMap<>();

    public synchronized void registerRootNode(RubyRootNode rootNode) {
        rootNodeToMethodVersion(rootNode);
    }

    public synchronized void recordLocalWrite(RubyRootNode rootNode, String name, String type) {
        if (name.equals("foo_a") && type.equals("Object")) {
            throw new UnsupportedOperationException();
        }

        final Map> rootNodeLocalTypes = localTypes.computeIfAbsent(rootNode,
                (k) -> new HashMap<>());

        final Set rootNodeLocalTypeSet = rootNodeLocalTypes.computeIfAbsent(name,
                (k) -> new HashSet<>());

        rootNodeLocalTypeSet.add(type);
    }

    public Method sharedMethodInfoToMethod(SharedMethodInfo sharedMethodInfo) {
        Method method = sharedMethodInfoToMethod.get(sharedMethodInfo);

        if (method == null) {
            method = new Method(this, sharedMethodInfo);
            sharedMethodInfoToMethod.put(sharedMethodInfo, method);
        }

        return method;
    }

    public MethodVersion rootNodeToMethodVersion(RubyRootNode rootNode) {
        MethodVersion methodVersion = rootNodeToMethodVersion.get(rootNode);

        if (methodVersion == null) {
            methodVersion = new MethodVersion(sharedMethodInfoToMethod(rootNode.getSharedMethodInfo()), rootNode);
            rootNodeToMethodVersion.put(rootNode, methodVersion);
        }

        return methodVersion;
    }

    public Collection getMethods() {
        return Collections.unmodifiableCollection(sharedMethodInfoToMethod.values());
    }

    public Map> getLocalTypes(RubyRootNode rootNode) {
        final Map> rootNodeLocalTypes = localTypes.get(rootNode);

        if (rootNodeLocalTypes == null) {
            return Collections.>emptyMap();
        } else {
            return rootNodeLocalTypes;
        }
    }

    public void resolve() {
        // Call graph currently doesn't work with AOT due to runtime reflection.
        if (!TruffleOptions.AOT) {
            rootNodeToMethodVersion.values().forEach(MethodVersion::resolve);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy