Skip to content

Commit

Permalink
Showing 7 changed files with 91 additions and 8 deletions.
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -248,6 +248,9 @@ public class Options {
public static final Option<Boolean> TRUFFLE_ROPE_LAZY_SUBSTRINGS = bool(TRUFFLE, "truffle.rope.lazy_substrings", true, "Indicates whether a substring operation on a rope should be performed lazily.");
public static final Option<Boolean> TRUFFLE_ROPE_PRINT_INTERN_STATS = bool(TRUFFLE, "truffle.rope.print_intern_stats", false, "Print interned rope stats at application exit.");

public static final Option<Integer> TRUFFLE_GLOBAL_VARIABLE_MAX_INVALIDATIONS = integer(TRUFFLE, "truffle.global_variable.max_invalidations", 10,
"Maximum number of times a global variable can be changed to be considered constant.");

public static final Option<Integer> TRUFFLE_DEFAULT_CACHE = integer(TRUFFLE, "truffle.default_cache", 8, "Default size for caches.");

public static final Option<Integer> TRUFFLE_METHOD_LOOKUP_CACHE = integer(TRUFFLE, "truffle.method_lookup.cache", TRUFFLE_DEFAULT_CACHE.load(), "Method lookup 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,60 @@

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 org.jruby.util.cli.Options;

public class GlobalVariableStorage {
public volatile Object value;

private static final int GLOBAL_VARIABLE_MAX_INVALIDATIONS = Options.TRUFFLE_GLOBAL_VARIABLE_MAX_INVALIDATIONS.load();

private final CyclicAssumption unchangedAssumption = new CyclicAssumption("global variable unchanged");
private int changes = 0;

// This really means @CompilationFinal for compilation and volatile in interpreter
@CompilationFinal private volatile boolean assumeConstant = true;

private volatile Object value;

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

public Object getValue() {
return value;
}

public Assumption getUnchangedAssumption() {
return unchangedAssumption.getAssumption();
}

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_MAX_INVALIDATIONS) {
changes++;
unchangedAssumption.invalidate();
} else {
unchangedAssumption.getAssumption().invalidate();
assumeConstant = false;
}
}
}
} 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 e04278d

Please sign in to comment.