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: 5366c61802f4
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3e3ad2dd5fc3
Choose a head ref
  • 5 commits
  • 19 files changed
  • 1 contributor

Commits on May 30, 2016

  1. Copy the full SHA
    b540e8a View commit details
  2. Copy the full SHA
    7b03b0c View commit details
  3. [Truffle] Remove ReadConstantNode and pass the lookup node explicitly…

    … to GetConstantNode.
    
    * This simplifies drastically all the interactions between constant-related nodes.
    eregon committed May 30, 2016
    Copy the full SHA
    f7d7f7a View commit details
  4. Copy the full SHA
    d5ff29d View commit details
  5. Copy the full SHA
    3e3ad2d View commit details
11 changes: 8 additions & 3 deletions lib/ruby/truffle/cext/ruby.h
Original file line number Diff line number Diff line change
@@ -46,10 +46,12 @@ VALUE get_rb_eException(void);
VALUE get_rb_cObject(void);
VALUE get_rb_cArray(void);
VALUE get_rb_cHash(void);
VALUE get_rb_mKernel(void);

#define rb_cObject get_rb_cObject()
#define rb_cArray get_rb_cArray()
#define rb_cHash get_rb_cHash()
#define rb_mKernel get_rb_mKernel()

VALUE get_rb_eRuntimeError(void);

@@ -152,9 +154,12 @@ VALUE rb_define_class_id_under(VALUE module, ID name, VALUE superclass);
VALUE rb_define_module(const char *name);
VALUE rb_define_module_under(VALUE module, const char *name);

void rb_define_method(VALUE module, const char *name, void *function, int args);
void rb_define_private_method(VALUE module, const char *name, void *function, int args);
void rb_define_module_function(VALUE module, const char *name, void *function, int args);
void rb_define_method(VALUE module, const char *name, void *function, int argc);
void rb_define_private_method(VALUE module, const char *name, void *function, int argc);
void rb_define_protected_method(VALUE module, const char *name, void *function, int argc);
void rb_define_module_function(VALUE module, const char *name, void *function, int argc);
void rb_define_global_function(const char *name, void *function, int argc);
void rb_define_singleton_method(VALUE object, const char *name, void *function, int argc);

#if defined(__cplusplus)
}
Binary file modified lib/ruby/truffle/cext/ruby.su
Binary file not shown.
7 changes: 0 additions & 7 deletions spec/ruby/optional/capi/ext/jruby_truffle.h
Original file line number Diff line number Diff line change
@@ -354,13 +354,6 @@
#undef HAVE_RB_DEFINE_ALIAS
#undef HAVE_RB_DEFINE_CONST
#undef HAVE_RB_DEFINE_GLOBAL_CONST
#undef HAVE_RB_DEFINE_GLOBAL_FUNCTION
#undef HAVE_RB_DEFINE_METHOD
#undef HAVE_RB_DEFINE_MODULE_FUNCTION
#undef HAVE_RB_DEFINE_MODULE_UNDER
#undef HAVE_RB_DEFINE_PRIVATE_METHOD
#undef HAVE_RB_DEFINE_PROTECTED_METHOD
#undef HAVE_RB_DEFINE_SINGLETON_METHOD
#undef HAVE_RB_UNDEF
#undef HAVE_RB_UNDEF_METHOD

2 changes: 1 addition & 1 deletion spec/ruby/optional/capi/module_spec.rb
Original file line number Diff line number Diff line change
@@ -179,7 +179,7 @@ def method_to_be_aliased
end

describe "rb_define_global_function" do
it "defines a method on Object" do
it "defines a method on Kernel" do
@m.rb_define_global_function("module_specs_global_function")
Kernel.should have_method(:module_specs_global_function)
module_specs_global_function.should == :test_method
1 change: 0 additions & 1 deletion spec/truffle/tags/optional/capi/class_tags.txt
Original file line number Diff line number Diff line change
@@ -41,5 +41,4 @@ fails:C-API Class function rb_class_real returns the class of an object ignoring
fails:C-API Class function rb_class_real returns the class of an object ignoring included modules
fails:C-API Class function rb_class_real returns 0 if passed 0
fails:C-API Class function rb_cv_get raises a NameError if the class variable is not defined
fails:C-API Class function rb_define_class_under raises a NameError when given a mismatched class to superclass
fails:C-API Class function rb_cvar_get raises a NameError if the class variable is not defined
13 changes: 0 additions & 13 deletions spec/truffle/tags/optional/capi/module_tags.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
fails:CApiModule rb_define_global_const defines a constant on Object
fails:CApiModule rb_const_set given a symbol name and a value sets a new constant on a module
fails:CApiModule rb_const_set given a symbol name and a value sets an existing constant's value
fails:CApiModule rb_define_module_under creates a new module inside the inner class
fails:CApiModule rb_define_module_under sets the module name
fails:CApiModule rb_define_module_under defines a module for an existing Autoload with an extension
fails:CApiModule rb_define_const given a String name and a value defines a new constant on a module
fails:CApiModule rb_define_const given a String name and a value sets an existing constant's value
fails:CApiModule rb_const_defined returns C non-zero if a constant is defined
@@ -27,19 +24,9 @@ fails:CApiModule rb_const_get_at calls #const_missing if the constant is not def
fails:CApiModule rb_define_alias defines an alias for an existing method
fails:CApiModule rb_alias defines an alias for an existing method
fails:CApiModule rb_define_global_function defines a method on Object
fails:CApiModule rb_define_method defines a method on a class
fails:CApiModule rb_define_method defines a method on a module
fails:CApiModule rb_define_module_function defines a module function
fails:CApiModule rb_define_module_function defines a private instance method
fails:CApiModule rb_define_private_method defines a private method on a class
fails:CApiModule rb_define_private_method defines a private method on a module
fails:CApiModule rb_define_protected_method defines a protected method on a class
fails:CApiModule rb_define_protected_method defines a protected method on a module
fails:CApiModule rb_define_singleton_method defines a method on the singleton class
fails:CApiModule rb_undef_method undef'ines a method on a class
fails:CApiModule rb_undef_method does not raise exceptions when passed a missing name
fails:CApiModule rb_undef_method when given a frozen Class raises a RuntimeError when passed a name
fails:CApiModule rb_undef_method when given a frozen Class raises a RuntimeError when passed a missing name
fails:CApiModule rb_undef undef'ines a method on a class
fails:CApiModule rb_class2name returns the module name
fails:CApiModule rb_define_module_under defines a module for an existing Autoload with a ruby object
32 changes: 24 additions & 8 deletions truffle/src/main/c/cext/ruby.c
Original file line number Diff line number Diff line change
@@ -40,6 +40,10 @@ VALUE get_rb_cHash() {
return (VALUE) truffle_read(RUBY_CEXT, "rb_cHash");
}

VALUE get_rb_mKernel() {
return (VALUE) truffle_read(RUBY_CEXT, "rb_mKernel");
}

VALUE get_rb_eRuntimeError() {
return (VALUE) truffle_read(RUBY_CEXT, "rb_eRuntimeError");
}
@@ -268,21 +272,33 @@ VALUE rb_define_class_id_under(VALUE module, ID name, VALUE superclass) {
}

VALUE rb_define_module(const char *name) {
return truffle_invoke(RUBY_CEXT, "rb_define_module", rb_str_new_cstr(name));
return rb_define_module_under(rb_cObject, name);
}

VALUE rb_define_module_under(VALUE module, const char *name) {
return truffle_invoke(RUBY_CEXT, "rb_define_module_under", module, name);
return truffle_invoke(RUBY_CEXT, "rb_define_module_under", module, rb_str_new_cstr(name));
}

void rb_define_method(VALUE module, const char *name, void *function, int argc) {
truffle_invoke(RUBY_CEXT, "rb_define_method", module, rb_str_new_cstr(name), truffle_address_to_function(function), argc);
}

void rb_define_private_method(VALUE module, const char *name, void *function, int argc) {
truffle_invoke(RUBY_CEXT, "rb_define_private_method", module, rb_str_new_cstr(name), truffle_address_to_function(function), argc);
}

void rb_define_protected_method(VALUE module, const char *name, void *function, int argc) {
truffle_invoke(RUBY_CEXT, "rb_define_protected_method", module, rb_str_new_cstr(name), truffle_address_to_function(function), argc);
}

void rb_define_method(VALUE module, const char *name, void *function, int args) {
truffle_invoke(RUBY_CEXT, "rb_define_method", module, rb_str_new_cstr(name), truffle_address_to_function(function), args);
void rb_define_module_function(VALUE module, const char *name, void *function, int argc) {
truffle_invoke(RUBY_CEXT, "rb_define_module_function", module, rb_str_new_cstr(name), truffle_address_to_function(function), argc);
}

void rb_define_private_method(VALUE module, const char *name, void *function, int args) {
truffle_invoke(RUBY_CEXT, "rb_define_private_method", module, rb_str_new_cstr(name), truffle_address_to_function(function), args);
void rb_define_global_function(const char *name, void *function, int argc) {
rb_define_module_function(rb_mKernel, name, function, argc);
}

void rb_define_module_function(VALUE module, const char *name, void *function, int args) {
truffle_invoke(RUBY_CEXT, "rb_define_module_function", module, rb_str_new_cstr(name), truffle_address_to_function(function), args);
void rb_define_singleton_method(VALUE object, const char *name, void *function, int argc) {
truffle_invoke(RUBY_CEXT, "rb_define_singleton_method", object, rb_str_new_cstr(name), truffle_address_to_function(function), argc);
}
Original file line number Diff line number Diff line change
@@ -68,7 +68,8 @@
import org.jruby.truffle.language.arguments.MissingArgumentBehavior;
import org.jruby.truffle.language.arguments.ReadPreArgumentNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.constants.ReadConstantNode;
import org.jruby.truffle.language.constants.GetConstantNode;
import org.jruby.truffle.language.constants.LookupConstantNode;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
@@ -96,7 +97,6 @@
import org.jruby.truffle.language.yield.YieldNode;
import org.jruby.truffle.platform.UnsafeGroup;
import org.jruby.util.IdUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -837,14 +837,11 @@ public boolean isConstDefined(DynamicObject module, String fullName, boolean inh
})
public abstract static class ConstGetNode extends CoreMethodNode {

@Child private ReadConstantNode readConstantNode;
@Child private KernelNodes.RequireNode requireNode;
@Child private IndirectCallNode indirectCallNode;

public ConstGetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.readConstantNode = new ReadConstantNode(context, sourceSection, true, true, null, null);
}
@Child LookupConstantNode lookupConstantNode = LookupConstantNode.create(true, true);
@Child GetConstantNode getConstantNode = GetConstantNode.create();

@CreateCast("name")
public RubyNode coerceToSymbolOrString(RubyNode name) {
@@ -859,7 +856,7 @@ public RubyNode coerceToBoolean(RubyNode inherit) {
// Symbol
@Specialization(guards = { "inherit", "isRubySymbol(name)" })
public Object getConstant(VirtualFrame frame, DynamicObject module, DynamicObject name, boolean inherit) {
return readConstantNode.readConstant(frame, module, Layouts.SYMBOL.getString(name));
return getConstant(frame, module, Layouts.SYMBOL.getString(name));
}

@Specialization(guards = { "!inherit", "isRubySymbol(name)" })
@@ -870,7 +867,7 @@ public Object getConstantNoInherit(VirtualFrame frame, DynamicObject module, Dyn
// String
@Specialization(guards = { "inherit", "isRubyString(name)", "!isScoped(name)" })
public Object getConstantString(VirtualFrame frame, DynamicObject module, DynamicObject name, boolean inherit) {
return readConstantNode.readConstant(frame, module, name.toString());
return getConstant(frame, module, name.toString());
}

@Specialization(guards = { "!inherit", "isRubyString(name)", "!isScoped(name)" })
@@ -884,12 +881,18 @@ public Object getConstantScoped(DynamicObject module, DynamicObject fullName, bo
return getConstantScoped(module, fullName.toString(), inherit);
}

private Object getConstant(VirtualFrame frame, Object module, String name) {
final RubyConstant constant = lookupConstantNode.lookupConstant(frame, module, name);
return getConstantNode.executeGetConstant(frame, module, name, constant, lookupConstantNode);
}

private Object getConstantNoInherit(VirtualFrame frame, DynamicObject module, String name, Node currentNode) {
CompilerDirectives.transferToInterpreter();

RubyConstant constant = ModuleOperations.lookupConstantWithInherit(getContext(), module, name, false, currentNode);
if (constant == null) {
throw new RaiseException(coreExceptions().nameErrorUninitializedConstant(module, name, this));
// Call const_missing
return getConstantNode.executeGetConstant(frame, module, name, null, lookupConstantNode);
} else {
if (constant.isAutoload()) {
loadAutoloadedConstant(frame, constant);
Original file line number Diff line number Diff line change
@@ -18,9 +18,7 @@
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.kernel.KernelNodes.RequireNode;
import org.jruby.truffle.core.kernel.KernelNodesFactory;
import org.jruby.truffle.language.RubyConstant;
@@ -30,47 +28,39 @@
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.util.IdUtil;

@NodeChildren({ @NodeChild("module"), @NodeChild("name"), @NodeChild("constant") })
@NodeChildren({ @NodeChild("module"), @NodeChild("name"), @NodeChild("constant"), @NodeChild("lookupConstantNode") })
public abstract class GetConstantNode extends RubyNode {

private final RestartableReadConstantNode readConstantNode;
private @Child CallDispatchHeadNode constMissingNode;

public GetConstantNode(
RubyContext context,
SourceSection sourceSection,
RestartableReadConstantNode readConstantNode) {
super(context, sourceSection);
this.readConstantNode = readConstantNode;
public static GetConstantNode create() {
return GetConstantNodeGen.create(null, null, null, null);
}

private @Child CallDispatchHeadNode constMissingNode;

public abstract Object executeGetConstant(
VirtualFrame frame, Object module, String name, RubyConstant constant);
VirtualFrame frame, Object module, String name, RubyConstant constant, LookupConstantInterface lookupConstantNode);

@Specialization(guards = { "constant != null", "!constant.isAutoload()" })
protected Object getConstant(DynamicObject module, String name, RubyConstant constant) {
protected Object getConstant(DynamicObject module, String name, RubyConstant constant, LookupConstantInterface lookupConstantNode) {
return constant.getValue();
}

@Specialization(guards = { "constant != null", "constant.isAutoload()" })
protected Object autoloadConstant(VirtualFrame frame, DynamicObject module, String name, RubyConstant constant,
protected Object autoloadConstant(VirtualFrame frame, DynamicObject module, String name, RubyConstant constant, LookupConstantInterface lookupConstantNode,
@Cached("createRequireNode()") RequireNode requireNode,
@Cached("deepCopyReadConstantNode()") RestartableReadConstantNode readConstantNode,
@Cached("create()") IndirectCallNode callNode) {

final DynamicObject path = (DynamicObject) constant.getValue();

// The autoload constant must only be removed if everything succeeds.
// We remove it first to allow lookup to ignore it and add it back if there was a failure.
Layouts.MODULE.getFields(constant.getDeclaringModule()).removeConstant(getContext(),
this,
name);
Layouts.MODULE.getFields(constant.getDeclaringModule()).removeConstant(getContext(), this, name);
try {
requireNode.require(frame, path, callNode);
return readConstantNode.readConstant(frame, module, name);
final RubyConstant resolvedConstant = lookupConstantNode.lookupConstant(frame, module, name);
return executeGetConstant(frame, module, name, resolvedConstant, lookupConstantNode);
} catch (RaiseException e) {
Layouts.MODULE.getFields(constant.getDeclaringModule()).
setAutoloadConstant(getContext(), this, name, path);
Layouts.MODULE.getFields(constant.getDeclaringModule()).setAutoloadConstant(getContext(), this, name, path);
throw e;
}
}
@@ -83,6 +73,7 @@ protected Object missingConstantCached(
DynamicObject module,
String name,
Object constant,
LookupConstantInterface lookupConstantNode,
@Cached("name") String cachedName,
@Cached("isValidConstantName(name)") boolean isValidConstantName,
@Cached("getSymbol(name)") DynamicObject symbolName,
@@ -91,8 +82,7 @@ protected Object missingConstantCached(
}

@Specialization(guards = "constant == null")
protected Object missingConstantUncached(
VirtualFrame frame, DynamicObject module, String name, Object constant) {
protected Object missingConstantUncached(VirtualFrame frame, DynamicObject module, String name, Object constant, LookupConstantInterface lookupConstantNode) {
final boolean isValidConstantName = isValidConstantName(name);
return doMissingConstant(frame, module, name, isValidConstantName, getSymbol(name));
}
@@ -124,10 +114,6 @@ protected RequireNode createRequireNode() {
return KernelNodesFactory.RequireNodeFactory.create(null);
}

protected RestartableReadConstantNode deepCopyReadConstantNode() {
return (RestartableReadConstantNode) readConstantNode.deepCopy();
}

protected boolean isValidConstantName(String name) {
return IdUtil.isValidConstantName19(name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.jruby.truffle.language.constants;

import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.truffle.language.RubyConstant;

public interface LookupConstantInterface {

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

}
Original file line number Diff line number Diff line change
@@ -18,9 +18,7 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.module.ModuleOperations;
import org.jruby.truffle.language.CheckLayoutNode;
import org.jruby.truffle.language.LexicalScope;
@@ -36,19 +34,18 @@
@NodeChild(value = "module", type = RubyNode.class),
@NodeChild(value = "name", type = RubyNode.class)
})
public abstract class LookupConstantNode extends RubyNode {
public abstract class LookupConstantNode extends RubyNode implements LookupConstantInterface {

private final boolean ignoreVisibility;
private final boolean lookInObject;

public static LookupConstantNode create(boolean ignoreVisibility, boolean lookInObject) {
return LookupConstantNodeGen.create(ignoreVisibility, lookInObject, null, null);
}

@Child CheckLayoutNode checkLayoutNode = new CheckLayoutNode();

public LookupConstantNode(
RubyContext context,
SourceSection sourceSection,
boolean ignoreVisibility,
boolean lookInObject) {
super(context, sourceSection);
public LookupConstantNode(boolean ignoreVisibility, boolean lookInObject) {
this.ignoreVisibility = ignoreVisibility;
this.lookInObject = lookInObject;
}
@@ -58,6 +55,11 @@ public abstract RubyConstant executeLookupConstant(
Object module,
String name);

@Override
public RubyConstant lookupConstant(VirtualFrame frame, Object module, String name) {
return executeLookupConstant(frame, module, name);
}

@Specialization(
guards = {
"module == cachedModule",
Loading