Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Truffle] Separate lexical and ancestor dependent changes.
* Only invalidate lexical dependents for changes on constants.
  • Loading branch information
eregon committed Oct 22, 2014
1 parent 5668504 commit e7d5b03
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 11 deletions.
Expand Up @@ -204,7 +204,7 @@ private Object doRubyBasicObject(
// The module, the "receiver" is an instance of its singleton class.
// But we want to check the module assumption, not its singleton class assumption.
final DispatchNode newDispatch = CachedBoxedDispatchNodeFactory.create(getContext(), methodName, first,
module.getSingletonClass(null), module.getUnmodifiedAssumption(), constant.getValue(),
module.getSingletonClass(null), module.getUnmodifiedAssumption(), constant.getValue(),
null, null, null, null, null, null, null, null);

first.replace(newDispatch);
Expand Down
Expand Up @@ -44,7 +44,7 @@ public Object execute(VirtualFrame frame) {

LexicalScope lexicalScope = definitionMethod.getSharedMethodInfo().getLexicalScope();
lexicalScope.setLiveModule(module);
lexicalScope.getParent().getLiveModule().addDependent(module);
lexicalScope.getParent().getLiveModule().addLexicalDependent(module);

final RubyMethod definition = definitionMethod.executeMethod(frame).withDeclaringModule(module);
return callModuleDefinitionNode.call(frame, definition.getCallTarget(), RubyArguments.pack(definition, definition.getDeclarationFrame(), module, null, new Object[]{}));
Expand Down
40 changes: 31 additions & 9 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyModule.java
Expand Up @@ -113,6 +113,10 @@ public static void debugModuleChain(RubyModule module) {
* include subclasses and modules that include this module.
*/
private final Set<RubyModule> dependents = Collections.newSetFromMap(new WeakHashMap<RubyModule, Boolean>());
/**
* Lexical dependent modules, to take care of changes to a module constants.
*/
private final Set<RubyModule> lexicalDependents = Collections.newSetFromMap(new WeakHashMap<RubyModule, Boolean>());

/**
* The class from which we create the object that is {@code Module}. A subclass of
Expand Down Expand Up @@ -149,7 +153,7 @@ public RubyModule(RubyContext context, RubyClass moduleClass, RubyModule lexical

// Constant invalidation for lexical scope.
if (lexicalParentModule != null) {
lexicalParentModule.addDependent(this);
lexicalParentModule.addLexicalDependent(this);
}
}

Expand Down Expand Up @@ -204,7 +208,7 @@ public void setConstant(RubyNode currentNode, String constantName, Object value)
assert RubyContext.shouldObjectBeVisible(value);
checkFrozen(currentNode);
getConstants().put(constantName, new RubyConstant(value, false));
newVersion();
newLexicalVersion();
// TODO(CS): warn when redefining a constant
}

Expand All @@ -213,7 +217,7 @@ public void removeConstant(RubyNode currentNode, String data) {

checkFrozen(currentNode);
getConstants().remove(data);
newVersion();
newLexicalVersion();
}

public void removeClassVariable(RubyNode currentNode, String variableName) {
Expand Down Expand Up @@ -307,7 +311,7 @@ public void changeConstantVisibility(RubyNode currentNode, RubySymbol constant,
throw new RaiseException(context.getCoreLibrary().nameErrorUninitializedConstant(constant.toString(), currentNode));
}

newVersion();
newLexicalVersion();
}

public void appendFeatures(RubyNode currentNode, RubyModule other) {
Expand Down Expand Up @@ -338,10 +342,16 @@ public int hashCode() {
public void newVersion() {
RubyNode.notDesignedForCompilation();

newVersion(new HashSet<RubyModule>());
newVersion(new HashSet<RubyModule>(), false);
}

public void newLexicalVersion() {
RubyNode.notDesignedForCompilation();

newVersion(new HashSet<RubyModule>(), true);
}

private void newVersion(Set<RubyModule> alreadyInvalidated) {
private void newVersion(Set<RubyModule> alreadyInvalidated, boolean considerLexicalDependents) {
if (alreadyInvalidated.contains(this))
return;

Expand All @@ -350,15 +360,27 @@ private void newVersion(Set<RubyModule> alreadyInvalidated) {

// Make dependents new versions
for (RubyModule dependent : dependents) {
dependent.newVersion(alreadyInvalidated);
dependent.newVersion(alreadyInvalidated, considerLexicalDependents);
}

if (considerLexicalDependents) {
for (RubyModule dependent : lexicalDependents) {
dependent.newVersion(alreadyInvalidated, considerLexicalDependents);
}
}
}

public void addDependent(RubyModule dependent) {
RubyNode.notDesignedForCompilation();

if (dependent != this)
dependents.add(dependent);
dependents.add(dependent);
}

public void addLexicalDependent(RubyModule lexicalChild) {
RubyNode.notDesignedForCompilation();

if (lexicalChild != this)
lexicalDependents.add(lexicalChild);
}

public Assumption getUnmodifiedAssumption() {
Expand Down

0 comments on commit e7d5b03

Please sign in to comment.