Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Truffle] Make global variables constants if they are not changed too…
Browse files Browse the repository at this point in the history
… often.
eregon committed Jun 24, 2016
1 parent bc4b492 commit 13ac0ea
Showing 7 changed files with 91 additions and 8 deletions.
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -258,6 +258,7 @@ public class Options {
public static final Option<Integer> TRUFFLE_BIND_CACHE = integer(TRUFFLE, "truffle.bind.cache", TRUFFLE_DEFAULT_CACHE.load(), "Cache size of test for being able to bind a method to a module.");
public static final Option<Integer> TRUFFLE_CONSTANT_CACHE = integer(TRUFFLE, "truffle.constant.cache", TRUFFLE_DEFAULT_CACHE.load(), "Constant cache size.");
public static final Option<Integer> TRUFFLE_INSTANCE_VARIABLE_CACHE = integer(TRUFFLE, "truffle.instance_variable.cache", TRUFFLE_DEFAULT_CACHE.load(), "Instance variable cache size.");
public static final Option<Integer> TRUFFLE_GLOBAL_VARIABLE_CACHE = integer(TRUFFLE, "truffle.global_variable.cache", 10, "Maximum number of times a global variable can be changed to be considered constant.");
public static final Option<Integer> TRUFFLE_BINDING_LOCAL_VARIABLE_CACHE = integer(TRUFFLE, "truffle.binding_local_variable.cache", TRUFFLE_DEFAULT_CACHE.load(), "Binding#local_variable_get/set cache size.");
public static final Option<Integer> TRUFFLE_SYMBOL_TO_PROC_CACHE = integer(TRUFFLE, "truffle.symbol_to_proc.cache", TRUFFLE_DEFAULT_CACHE.load(), "Symbol#to_proc cache size.");
public static final Option<Integer> TRUFFLE_ALLOCATE_CLASS_CACHE = integer(TRUFFLE, "truffle.allocate_class.cache", TRUFFLE_DEFAULT_CACHE.load(), "Allocation size class cache size.");
22 changes: 22 additions & 0 deletions test/truffle/compiler/pe/language/global_pe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) 2014, 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

$stable_global = 42

example "$stable_global", 42

$almost_stable_global = 1
$almost_stable_global = 2

example "$almost_stable_global", 2

100.times { |i|
$unstable_global = i
}

counter example "$unstable_global"
4 changes: 2 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -1315,11 +1315,11 @@ public GlobalVariables getGlobalVariables() {
}

public DynamicObject getLoadPath() {
return (DynamicObject) loadPathStorage.value;
return (DynamicObject) loadPathStorage.getValue();
}

public DynamicObject getLoadedFeatures() {
return (DynamicObject) loadedFeaturesStorage.value;
return (DynamicObject) loadedFeaturesStorage.getValue();
}

public DynamicObject getMainObject() {
Original file line number Diff line number Diff line change
@@ -10,10 +10,62 @@

package org.jruby.truffle.language.globals;

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.utilities.CyclicAssumption;
import com.oracle.truffle.api.utilities.NeverValidAssumption;
import org.jruby.util.cli.Options;

public class GlobalVariableStorage {
public volatile Object value;

private static final int GLOBAL_VARIABLE_CACHE = Options.TRUFFLE_GLOBAL_VARIABLE_CACHE.load();

private final CyclicAssumption unchangedAssumption = new CyclicAssumption("global variable unchanged");
private int changes = 0;
@CompilationFinal private volatile boolean assumeConstant = true;

private volatile Object value;

GlobalVariableStorage(Object value) {
this.value = value;
}

public Object getValue() {
return value;
}

public synchronized Assumption getUnchangedAssumption() {
if (assumeConstant) {
return unchangedAssumption.getAssumption();
} else {
return NeverValidAssumption.INSTANCE;
}
}

public void setValue(Object value) {
if (assumeConstant) {
if (value != this.value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
this.value = value;

synchronized (this) {
if (!assumeConstant) {
// Compiled code didn't see that we do not assumeConstant anymore
return;
}

if (changes <= GLOBAL_VARIABLE_CACHE) {
changes++;
} else {
assumeConstant = false;
}
unchangedAssumption.invalidate();
}
}
} else {
this.value = value;
}
}

}
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ public Object getOrDefault(String key, Object defaultValue) {
}

public Object get(String key) {
return getStorage(key).value;
return getStorage(key).getValue();
}

@TruffleBoundary
@@ -52,7 +52,7 @@ public GlobalVariableStorage getStorage(String key) {

public GlobalVariableStorage put(String key, Object value) {
GlobalVariableStorage storage = getStorage(key);
storage.value = value;
storage.setValue(value);
return storage;
}

@@ -64,7 +64,7 @@ public Collection<DynamicObject> dynamicObjectValues() {
final Collection<GlobalVariableStorage> storages = variables.values();
final ArrayList<DynamicObject> values = new ArrayList<>(storages.size());
for (GlobalVariableStorage storage : storages) {
final Object value = storage.value;
final Object value = storage.getValue();
if (value instanceof DynamicObject) {
values.add((DynamicObject) value);
}
Original file line number Diff line number Diff line change
@@ -25,9 +25,16 @@ public ReadGlobalVariableNode(RubyContext context, SourceSection sourceSection,
this.name = name;
}

@Specialization(assumptions = "storage.getUnchangedAssumption()")
public Object readConstant(
@Cached("getStorage()") GlobalVariableStorage storage,
@Cached("storage.getValue()") Object value) {
return value;
}

@Specialization
public Object read(@Cached("getStorage()") GlobalVariableStorage storage) {
return storage.value;
return storage.getValue();
}

protected GlobalVariableStorage getStorage() {
Original file line number Diff line number Diff line change
@@ -24,7 +24,8 @@ public abstract class WriteGlobalVariableNode extends RubyNode {

@Specialization
public Object write(Object value, @Cached("getStorage()") GlobalVariableStorage storage) {
return storage.value = value;
storage.setValue(value);
return value;
}

protected GlobalVariableStorage getStorage() {

0 comments on commit 13ac0ea

Please sign in to comment.