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

org.jruby.truffle.language.objects.shared.SharedObjects Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2015, 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.language.objects.shared;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.language.objects.ObjectGraph;
import org.jruby.truffle.options.OptionsBuilder;
import org.jruby.truffle.options.OptionsCatalog;

import java.util.ArrayDeque;
import java.util.Deque;

public class SharedObjects {

    // TODO CS 3-Dec-16 these shouldn't be static
    public static final boolean ENABLED = OptionsBuilder.readSystemProperty(OptionsCatalog.SHARED_OBJECTS_ENABLED);
    public static final boolean SHARE_ALL = OptionsBuilder.readSystemProperty(OptionsCatalog.SHARED_OBJECTS_SHARE_ALL);
    public static final boolean DEBUG = OptionsBuilder.readSystemProperty(OptionsCatalog.SHARED_OBJECTS_DEBUG);

    private final RubyContext context;
    // No need for volatile since we change this before starting the 2nd Thread
    private boolean sharing = false;

    public SharedObjects(RubyContext context) {
        this.context = context;
    }

    public boolean isSharing() {
        return sharing;
    }

    public void startSharing() {
        sharing = true;
        shareContextRoots(context);
    }

    private static void shareContextRoots(RubyContext context) {
        final Deque stack = new ArrayDeque<>();

        // Share global variables (including new ones)
        for (DynamicObject object : context.getCoreLibrary().getGlobalVariables().dynamicObjectValues()) {
            stack.push(object);
        }

        // Share all named modules and constants (including the shared TOPLEVEL_BINDING)
        stack.push(context.getCoreLibrary().getObjectClass());

        // Share all threads since they are accessible via Thread.list
        for (DynamicObject thread : context.getThreadManager().iterateThreads()) {
            stack.push(thread);
        }

        long t0 = System.currentTimeMillis();
        shareObjects(stack);
        if (context.getOptions().SHARED_OBJECTS_DEBUG) {
            System.err.println("Sharing roots took " + (System.currentTimeMillis() - t0) + " ms");
        }
    }

    public static void shareDeclarationFrame(DynamicObject block) {
        final Deque stack = new ArrayDeque<>();

        if (DEBUG) {
            final SourceSection sourceSection = Layouts.PROC.getSharedMethodInfo(block).getSourceSection();
            System.err.println("Sharing decl frame of " + RubyLanguage.fileLine(sourceSection));
        }

        final MaterializedFrame declarationFrame = Layouts.PROC.getDeclarationFrame(block);
        stack.addAll(ObjectGraph.getObjectsInFrame(declarationFrame));

        shareObjects(stack);
    }

    private static void shareObjects(Deque stack) {
        while (!stack.isEmpty()) {
            final DynamicObject object = stack.pop();

            if (share(object)) {
                stack.addAll(ObjectGraph.getAdjacentObjects(object));
            }
        }
    }

    @TruffleBoundary
    private static void shareObject(Object value) {
        final Deque stack = new ArrayDeque<>();
        stack.add((DynamicObject) value);
        shareObjects(stack);
    }

    public static boolean isShared(DynamicObject object) {
        return isShared(object.getShape());
    }

    public static boolean isShared(Shape shape) {
        return ENABLED && (SHARE_ALL || shape.isShared());
    }

    public static void writeBarrier(Object value) {
        if (ENABLED && value instanceof DynamicObject && !isShared((DynamicObject) value)) {
            shareObject(value);
        }
    }

    public static void propagate(DynamicObject source, Object value) {
        if (isShared(source)) {
            writeBarrier(value);
        }
    }

    private static boolean share(DynamicObject object) {
        if (isShared(object)) {
            return false;
        }

        object.updateShape();
        final Shape oldShape = object.getShape();
        final Shape newShape = oldShape.makeSharedShape();
        object.setShapeAndGrow(oldShape, newShape);
        return true;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy