Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c90b146d0ee5
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4f027fe472ae
Choose a head ref
  • 3 commits
  • 32 files changed
  • 1 contributor

Commits on Aug 5, 2015

  1. Copy the full SHA
    c10afd2 View commit details
  2. [Truffle] Fix LexicalScope to be attached to an InternalMethod.

    * Instead of SharedMethodInfo, which can have multiple LexicalScopes
      in the case of class << self; def meth; end; end.
    * Better separate constant lookup with and without LexicalScope.
    * The LexicalScope stack is saved in the current Fiber and updated
      as we enter/leave a literal class/module body (class/module keywords).
    eregon committed Aug 5, 2015
    Copy the full SHA
    07f7be0 View commit details
  3. Copy the full SHA
    4f027fe View commit details
Showing with 358 additions and 183 deletions.
  1. +0 −3 spec/truffle/tags/language/constants_tags.txt
  2. +32 −0 truffle/src/main/java/org/jruby/truffle/nodes/constants/AbstractLookupConstantNode.java
  3. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/constants/GetConstantNode.java
  4. +5 −17 truffle/src/main/java/org/jruby/truffle/nodes/constants/LookupConstantNode.java
  5. +108 −0 truffle/src/main/java/org/jruby/truffle/nodes/constants/LookupConstantWithLexicalScopeNode.java
  6. +13 −5 truffle/src/main/java/org/jruby/truffle/nodes/constants/ReadConstantNode.java
  7. +3 −3 truffle/src/main/java/org/jruby/truffle/nodes/core/CoreMethodNodeManager.java
  8. +16 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/FiberNodes.java
  9. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  10. +9 −6 truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
  11. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/SymbolNodes.java
  12. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/array/ArrayNodes.java
  13. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/ext/BigDecimalNodes.java
  14. +14 −8 .../org/jruby/truffle/nodes/{objects/LexicalScopeNode.java → lexical/GetLexicalScopeModuleNode.java}
  15. +32 −0 truffle/src/main/java/org/jruby/truffle/nodes/lexical/GetLexicalScopeNode.java
  16. +5 −1 truffle/src/main/java/org/jruby/truffle/nodes/methods/MethodDefinitionNode.java
  17. +19 −12 truffle/src/main/java/org/jruby/truffle/nodes/objects/OpenModuleNode.java
  18. +7 −5 truffle/src/main/java/org/jruby/truffle/nodes/objects/ReadClassVariableNode.java
  19. +4 −3 truffle/src/main/java/org/jruby/truffle/nodes/objects/WriteClassVariableNode.java
  20. +2 −3 truffle/src/main/java/org/jruby/truffle/nodes/time/ReadTimeZoneNode.java
  21. +7 −16 truffle/src/main/java/org/jruby/truffle/runtime/LexicalScope.java
  22. +2 −2 truffle/src/main/java/org/jruby/truffle/runtime/ModuleOperations.java
  23. +2 −2 truffle/src/main/java/org/jruby/truffle/runtime/RubyConstant.java
  24. +19 −1 truffle/src/main/java/org/jruby/truffle/runtime/RubyContext.java
  25. +7 −0 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyFiber.java
  26. +2 −2 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyModuleModel.java
  27. +14 −6 truffle/src/main/java/org/jruby/truffle/runtime/methods/InternalMethod.java
  28. +2 −8 truffle/src/main/java/org/jruby/truffle/runtime/methods/SharedMethodInfo.java
  29. +21 −26 truffle/src/main/java/org/jruby/truffle/translator/BodyTranslator.java
  30. +0 −18 truffle/src/main/java/org/jruby/truffle/translator/ParseEnvironment.java
  31. +4 −15 truffle/src/main/java/org/jruby/truffle/translator/TranslatorDriver.java
  32. +0 −12 truffle/src/main/java/org/jruby/truffle/translator/TranslatorEnvironment.java
3 changes: 0 additions & 3 deletions spec/truffle/tags/language/constants_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2015 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.nodes.constants;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;

import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

@NodeChildren({
@NodeChild(value = "module", type = RubyNode.class),
@NodeChild(value = "name", type = RubyNode.class) })
public abstract class AbstractLookupConstantNode extends RubyNode {

public AbstractLookupConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract RubyConstant executeLookupConstant(VirtualFrame frame, Object module, String name);

}
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@

@NodeChildren({
@NodeChild("module"), @NodeChild("name"),
@NodeChild(value = "lookupConstantNode", type = LookupConstantNode.class, executeWith = { "module", "name" })
@NodeChild(value = "lookupConstantNode", type = AbstractLookupConstantNode.class, executeWith = { "module", "name" })
})
public abstract class GetConstantNode extends RubyNode {

@@ -40,7 +40,7 @@ public GetConstantNode(RubyContext context, SourceSection sourceSection) {
}

public abstract RubyNode getModule();
public abstract LookupConstantNode getLookupConstantNode();
public abstract AbstractLookupConstantNode getLookupConstantNode();

public abstract Object executeGetConstant(VirtualFrame frame, Object module, String name);

Original file line number Diff line number Diff line change
@@ -20,7 +20,6 @@
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ModuleNodes;
import org.jruby.truffle.runtime.LexicalScope;
@@ -29,29 +28,18 @@
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyModule;

/**
* Caches {@link ModuleOperations#lookupConstant}
* and checks visibility.
* The {@link LexicalScope} is constant here.
* No {@link LexicalScope} is considered.
*/
@NodeChildren({ @NodeChild("module"), @NodeChild("name") })
public abstract class LookupConstantNode extends RubyNode {
public abstract class LookupConstantNode extends AbstractLookupConstantNode {

private final LexicalScope lexicalScope;

public LookupConstantNode(RubyContext context, SourceSection sourceSection, LexicalScope lexicalScope) {
public LookupConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.lexicalScope = lexicalScope;
}

public LexicalScope getLexicalScope() {
return lexicalScope;
}

public abstract RubyConstant executeLookupConstant(VirtualFrame frame, Object module, String name);

@Specialization(guards = {
"isRubyModule(module)",
"module == cachedModule",
@@ -103,11 +91,11 @@ protected boolean guardName(String name, String cachedName, ConditionProfile sam
}

protected RubyConstant doLookup(RubyBasicObject module, String name) {
return ModuleOperations.lookupConstant(getContext(), lexicalScope, module, name);
return ModuleOperations.lookupConstant(getContext(), LexicalScope.NONE, module, name);
}

protected boolean isVisible(RubyBasicObject module, RubyConstant constant) {
return constant == null || constant.isVisibleTo(getContext(), lexicalScope, module);
return constant == null || constant.isVisibleTo(getContext(), LexicalScope.NONE, module);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2015 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.nodes.constants;

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ModuleNodes;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;

/**
* Caches {@link ModuleOperations#lookupConstant}
* and checks visibility.
* The {@link LexicalScope} is derived from the current method.
*/
public abstract class LookupConstantWithLexicalScopeNode extends AbstractLookupConstantNode {

public LookupConstantWithLexicalScopeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = {
"isRubyModule(module)",
"module == cachedModule",
"getLexicalScope(frame) == cachedLexicalScope",
"guardName(name, cachedName, sameNameProfile)"
}, assumptions = "getUnmodifiedAssumption(cachedModule)", limit = "getCacheLimit()")
protected RubyConstant lookupConstant(VirtualFrame frame, RubyBasicObject module, String name,
@Cached("module") RubyBasicObject cachedModule,
@Cached("name") String cachedName,
@Cached("getLexicalScope(frame)") LexicalScope cachedLexicalScope,
@Cached("doLookup(cachedModule, cachedName, cachedLexicalScope)") RubyConstant constant,
@Cached("isVisible(cachedModule, constant, cachedLexicalScope)") boolean isVisible,
@Cached("createBinaryProfile()") ConditionProfile sameNameProfile) {
if (!isVisible) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateConstant(module, name, this));
}
return constant;
}

public Assumption getUnmodifiedAssumption(RubyBasicObject module) {
return ModuleNodes.getModel(module).getUnmodifiedAssumption();
}

@Specialization(guards = "isRubyModule(module)")
protected RubyConstant lookupConstantUncached(VirtualFrame frame, RubyBasicObject module, String name) {
LexicalScope lexicalScope = getLexicalScope(frame);
CompilerDirectives.transferToInterpreter();
RubyConstant constant = doLookup(module, name, lexicalScope);
boolean isVisible = isVisible(module, constant, lexicalScope);

if (!isVisible) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateConstant(module, name, this));
}
return constant;
}

@Specialization(guards = "!isRubyModule(module)")
protected RubyConstant lookupNotModule(Object module, String name) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorIsNotA(module.toString(), "class/module", this));
}

protected LexicalScope getLexicalScope(VirtualFrame frame) {
return RubyArguments.getMethod(frame.getArguments()).getLexicalScope();
}

protected boolean guardName(String name, String cachedName, ConditionProfile sameNameProfile) {
// This is likely as for literal constant lookup the name does not change and Symbols always return the same String.
if (sameNameProfile.profile(name == cachedName)) {
return true;
} else {
return name.equals(cachedName);
}
}

protected RubyConstant doLookup(RubyBasicObject module, String name, LexicalScope lexicalScope) {
return ModuleOperations.lookupConstant(getContext(), lexicalScope, module, name);
}

protected boolean isVisible(RubyBasicObject module, RubyConstant constant, LexicalScope lexicalScope) {
return constant == null || constant.isVisibleTo(getContext(), lexicalScope, module);
}

}
Original file line number Diff line number Diff line change
@@ -12,10 +12,10 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.literal.LiteralNode;
import org.jruby.truffle.runtime.ConstantReplacer;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
@@ -26,13 +26,21 @@ public class ReadConstantNode extends RubyNode {
private final String name;
@Child private GetConstantNode getConstantNode;

public ReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, LexicalScope lexicalScope) {
public ReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver) {
this(context, sourceSection, name, receiver, false);
}

public ReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, boolean considerLexicalScope) {
super(context, sourceSection);

this.name = ConstantReplacer.replacementName(sourceSection, name);
this.getConstantNode =
GetConstantNodeGen.create(context, sourceSection, receiver, new LiteralNode(context, sourceSection, this.name),
LookupConstantNodeGen.create(context, sourceSection, lexicalScope, null, null));
final AbstractLookupConstantNode lookupConstantNode;
if (considerLexicalScope) {
lookupConstantNode = LookupConstantWithLexicalScopeNodeGen.create(context, sourceSection, null, null);
} else {
lookupConstantNode = LookupConstantNodeGen.create(context, sourceSection, null, null);
}
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, receiver, new LiteralNode(context, sourceSection, this.name), lookupConstantNode);
}

@Override
Original file line number Diff line number Diff line change
@@ -139,8 +139,8 @@ private static void addMethod(RubyBasicObject module, RubyRootNode rootNode, Lis
visibility = Visibility.PRIVATE;
}

final InternalMethod method = new InternalMethod(rootNodeCopy.getSharedMethodInfo(), name, module, visibility, false,
Truffle.getRuntime().createCallTarget(rootNodeCopy), null);
final InternalMethod method = new InternalMethod(rootNodeCopy.getSharedMethodInfo(), name, module, visibility, LexicalScope.NONE,
false, Truffle.getRuntime().createCallTarget(rootNodeCopy), null);

ModuleNodes.getModel(module).addMethod(null, method.withVisibility(visibility).withName(name));
}
@@ -156,7 +156,7 @@ private static RubyRootNode makeGenericMethod(RubyContext context, MethodDetails

final Arity arity = new Arity(required, optional, method.rest());

final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, LexicalScope.NONE, arity, methodDetails.getIndicativeName(), false, null, true);
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, arity, methodDetails.getIndicativeName(), false, null, true);

final List<RubyNode> argumentsNodes = new ArrayList<>();

16 changes: 16 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/FiberNodes.java
Original file line number Diff line number Diff line change
@@ -9,19 +9,23 @@
*/
package org.jruby.truffle.nodes.core;

import java.util.Deque;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ControlFlowException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.cast.SingleValueCastNode;
import org.jruby.truffle.nodes.cast.SingleValueCastNodeGen;
import org.jruby.truffle.nodes.core.FiberNodesFactory.FiberTransferNodeFactory;
import org.jruby.truffle.nodes.methods.UnsupportedOperationBehavior;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.control.ReturnException;
@@ -38,6 +42,18 @@ public static RubyFiber.FiberFields getFields(RubyBasicObject fiber) {
return getFields(((RubyFiber) fiber));
}

public static LexicalScope getLexicalScopeStack(RubyContext context) {
final RubyBasicObject currentThread = context.getThreadManager().getCurrentThread();
final RubyBasicObject currentFiber = ThreadNodes.getFiberManager(currentThread).getCurrentFiber();
return FiberNodes.getFields(currentFiber).lexicalScopeStack;
}

public static void setLexicalScopeStack(RubyContext context, LexicalScope lexicalScope) {
final RubyBasicObject currentThread = context.getThreadManager().getCurrentThread();
final RubyBasicObject currentFiber = ThreadNodes.getFiberManager(currentThread).getCurrentFiber();
FiberNodes.getFields(currentFiber).lexicalScopeStack = lexicalScope;
}

public static RubyBasicObject newRootFiber(RubyBasicObject thread, FiberManager fiberManager, ThreadManager threadManager) {
assert RubyGuards.isRubyThread(thread);
RubyContext context = thread.getContext();
Original file line number Diff line number Diff line change
@@ -539,9 +539,9 @@ public Object evalNoBindingCached(
cachedRootNode.getRootNode().getSharedMethodInfo().getName(),
getContext().getCoreLibrary().getObjectClass(),
Visibility.PUBLIC,
RubyArguments.getMethod(frame.getArguments()).getLexicalScope(),
false,
cachedCallTarget,
parentFrame);
cachedCallTarget, parentFrame);

return callNode.call(frame, RubyArguments.pack(
method,
Original file line number Diff line number Diff line change
@@ -406,7 +406,7 @@ public RubyBasicObject generateAccessor(VirtualFrame frame, RubyBasicObject modu
final String indicativeName = name + "(attr_" + (isGetter ? "reader" : "writer") + ")";

final CheckArityNode checkArity = new CheckArityNode(getContext(), sourceSection, arity);
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, LexicalScope.NONE, arity, indicativeName, false, null, false);
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, arity, indicativeName, false, null, false);

final SelfNode self = new SelfNode(getContext(), sourceSection);
final RubyNode accessInstanceVariable;
@@ -419,7 +419,7 @@ public RubyBasicObject generateAccessor(VirtualFrame frame, RubyBasicObject modu
final RubyNode sequence = SequenceNode.sequence(getContext(), sourceSection, checkArity, accessInstanceVariable);
final RubyRootNode rootNode = new RubyRootNode(getContext(), sourceSection, null, sharedMethodInfo, sequence);
final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
final InternalMethod method = new InternalMethod(sharedMethodInfo, accessorName, module, visibility, false, callTarget, null);
final InternalMethod method = new InternalMethod(sharedMethodInfo, accessorName, module, visibility, LexicalScope.NONE, false, callTarget, null);

getModel(module).addMethod(this, method);
return nil();
@@ -897,7 +897,7 @@ public abstract static class ConstGetNode extends CoreMethodNode {
public ConstGetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, null, null,
LookupConstantNodeGen.create(context, sourceSection, LexicalScope.NONE, null, null));
LookupConstantNodeGen.create(context, sourceSection, null, null));
}

@CreateCast("name")
@@ -1104,7 +1104,10 @@ private RubyBasicObject defineMethod(RubyBasicObject module, String name, RubyBa

final CallTarget modifiedCallTarget = ProcNodes.getCallTargetForLambdas(proc);
final SharedMethodInfo info = ProcNodes.getSharedMethodInfo(proc).withName(name);
final InternalMethod modifiedMethod = new InternalMethod(info, name, module, Visibility.PUBLIC, false, modifiedCallTarget, ProcNodes.getDeclarationFrame(proc));
final InternalMethod modifiedMethod = new InternalMethod(info, name, module, Visibility.PUBLIC,
ProcNodes.getMethod(proc).getLexicalScope(),
false, modifiedCallTarget,
ProcNodes.getDeclarationFrame(proc));

return addMethod(module, name, modifiedMethod);
}
@@ -1342,11 +1345,11 @@ public RubyBasicObject nesting() {
final List<RubyBasicObject> modules = new ArrayList<>();

InternalMethod method = RubyCallStack.getCallingMethod(getContext());
LexicalScope lexicalScope = method == null ? null : method.getSharedMethodInfo().getLexicalScope();
LexicalScope lexicalScope = method == null ? null : method.getLexicalScope();
RubyBasicObject object = getContext().getCoreLibrary().getObjectClass();

while (lexicalScope != null) {
final RubyBasicObject enclosing = lexicalScope.getLiveModule();
final RubyBasicObject enclosing = lexicalScope.getModule();
if (enclosing == object)
break;
modules.add(enclosing);
Original file line number Diff line number Diff line change
@@ -227,8 +227,8 @@ protected RubyBasicObject createProc(RubyBasicObject symbol) {
.getCallNode().getEncapsulatingSourceSection();

final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(
sourceSection, null, Arity.NO_ARGUMENTS, getString(symbol),
true, null, false);
sourceSection, Arity.NO_ARGUMENTS, getString(symbol), true,
null, false);

final RubyRootNode rootNode = new RubyRootNode(
getContext(), sourceSection,
Loading