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: 25c265de18d7
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7ed20518b159
Choose a head ref
  • 4 commits
  • 4 files changed
  • 1 contributor

Commits on Oct 15, 2015

  1. Copy the full SHA
    e20f54c View commit details
  2. Copy the full SHA
    9383672 View commit details
  3. [Truffle] Cache a Module or Class name even when anonymous as it is r…

    …ather expensive to compute.
    
    * Now the Java String name is truly constant in compiled code.
    eregon committed Oct 15, 2015
    Copy the full SHA
    2a1eb25 View commit details
  4. Copy the full SHA
    7ed2051 View commit details
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ public static DynamicObject createClassClass(RubyContext context) {
model.rubyModuleObject = rubyClass;
Layouts.CLASS.setInstanceFactoryUnsafe(rubyClass, factory);
Layouts.MODULE.setFields(rubyClass, model);
model.name = model.givenBaseName;
model.setFullName(model.givenBaseName);

assert RubyGuards.isRubyModule(rubyClass);
assert RubyGuards.isRubyClass(rubyClass);
@@ -73,7 +73,7 @@ public static DynamicObject createBootClass(RubyContext context, DynamicObject c
model.rubyModuleObject = rubyClass;

if (model.lexicalParent == null) { // bootstrap or anonymous module
Layouts.MODULE.getFields(rubyClass).name = Layouts.MODULE.getFields(rubyClass).givenBaseName;
Layouts.MODULE.getFields(rubyClass).setFullName(Layouts.MODULE.getFields(rubyClass).givenBaseName);
} else {
Layouts.MODULE.getFields(rubyClass).getAdoptedByLexicalParent(context, model.lexicalParent, model.givenBaseName, null);
}
@@ -115,10 +115,10 @@ public static DynamicObject createRubyClass(RubyContext context, DynamicObject c

model.rubyModuleObject = rubyClass;

if (model.lexicalParent == null) { // bootstrap or anonymous module
Layouts.MODULE.getFields(rubyClass).name = Layouts.MODULE.getFields(rubyClass).givenBaseName;
} else {
if (model.lexicalParent != null) {
Layouts.MODULE.getFields(rubyClass).getAdoptedByLexicalParent(context, model.lexicalParent, model.givenBaseName, null);
} else if (Layouts.MODULE.getFields(rubyClass).givenBaseName != null) { // bootstrap module
Layouts.MODULE.getFields(rubyClass).setFullName(Layouts.MODULE.getFields(rubyClass).givenBaseName);
}

if (superclass != null) {
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import com.oracle.truffle.api.utilities.ValueProfile;

import org.jcodings.Encoding;
import org.jcodings.specific.UTF8Encoding;
@@ -75,10 +76,11 @@ public static DynamicObject createRubyModule(RubyContext context, DynamicObject
final ModuleFields model = new ModuleFields(context, lexicalParent, name);
final DynamicObject module = Layouts.MODULE.createModule(Layouts.CLASS.getInstanceFactory(selfClass), model);
model.rubyModuleObject = module;
if (lexicalParent == null) { // bootstrap or anonymous module
Layouts.MODULE.getFields(module).name = Layouts.MODULE.getFields(module).givenBaseName;
} else {

if (lexicalParent != null) {
Layouts.MODULE.getFields(module).getAdoptedByLexicalParent(context, lexicalParent, name, currentNode);
} else if (Layouts.MODULE.getFields(module).givenBaseName != null) { // bootstrap module
Layouts.MODULE.getFields(module).setFullName(Layouts.MODULE.getFields(module).givenBaseName);
}
return module;
}
@@ -1307,14 +1309,16 @@ public NameNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@TruffleBoundary
@Specialization
public Object name(DynamicObject module) {
if (!Layouts.MODULE.getFields(module).hasPartialName()) {
public Object name(DynamicObject module,
@Cached("createIdentityProfile()") ValueProfile fieldsProfile) {
final ModuleFields fields = fieldsProfile.profile(Layouts.MODULE.getFields(module));

if (!fields.hasPartialName()) {
return nil();
}

return createString(StringOperations.encodeByteList(Layouts.MODULE.getFields(module).getName(), UTF8Encoding.INSTANCE));
return createString(StringOperations.encodeByteList(fields.getName(), UTF8Encoding.INSTANCE));
}
}

Original file line number Diff line number Diff line change
@@ -11,9 +11,14 @@

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.utilities.AssumedValue;
import com.oracle.truffle.api.utilities.CyclicAssumption;

import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
@@ -60,10 +65,9 @@ public static void debugModuleChain(DynamicObject module) {

public final DynamicObject lexicalParent;
public final String givenBaseName;
/**
* Full name, including named parent
*/
public String name;

private boolean hasFullName = false;
private String name = null;

private final Map<String, InternalMethod> methods = new ConcurrentHashMap<>();
private final Map<String, RubyConstant> constants = new ConcurrentHashMap<>();
@@ -96,16 +100,16 @@ public void getAdoptedByLexicalParent(RubyContext context, DynamicObject lexical
Layouts.MODULE.getFields(lexicalParent).setConstantInternal(context, currentNode, name, rubyModuleObject, false);
Layouts.MODULE.getFields(lexicalParent).addLexicalDependent(rubyModuleObject);

if (this.name == null) {
if (!hasFullName()) {
// Tricky, we need to compare with the Object class, but we only have a Class at hand.
final DynamicObject classClass = Layouts.BASIC_OBJECT.getLogicalClass(getLogicalClass());
final DynamicObject objectClass = ClassNodes.getSuperClass(ClassNodes.getSuperClass(classClass));

if (lexicalParent == objectClass) {
this.name = name;
this.setFullName(name);
updateAnonymousChildrenModules(context);
} else if (Layouts.MODULE.getFields(lexicalParent).hasName()) {
this.name = Layouts.MODULE.getFields(lexicalParent).getName() + "::" + name;
} else if (Layouts.MODULE.getFields(lexicalParent).hasFullName()) {
this.setFullName(Layouts.MODULE.getFields(lexicalParent).getName() + "::" + name);
updateAnonymousChildrenModules(context);
}
// else: Our lexicalParent is also an anonymous module
@@ -118,7 +122,7 @@ public void updateAnonymousChildrenModules(RubyContext context) {
RubyConstant constant = entry.getValue();
if (RubyGuards.isRubyModule(constant.getValue())) {
DynamicObject module = (DynamicObject) constant.getValue();
if (!Layouts.MODULE.getFields(module).hasName()) {
if (!Layouts.MODULE.getFields(module).hasFullName()) {
Layouts.MODULE.getFields(module).getAdoptedByLexicalParent(context, rubyModuleObject, entry.getKey(), null);
}
}
@@ -418,26 +422,40 @@ public RubyContext getContext() {
}

public String getName() {
if (name != null) {
return name;
final String name = this.name;
if (name == null) {
// Lazily compute the anonymous name because it is expensive
CompilerDirectives.transferToInterpreterAndInvalidate();
final String anonymousName = createAnonymousName();
this.name = anonymousName;
return anonymousName;
}
return name;
}

public void setFullName(String name) {
assert name != null;
hasFullName = true;
this.name = name;
}

@TruffleBoundary
private String createAnonymousName() {
if (givenBaseName != null) {
return Layouts.MODULE.getFields(lexicalParent).getName() + "::" + givenBaseName;
} else if (getLogicalClass() == rubyModuleObject) { // For the case of class Class during initialization
return "#<cyclic>";
} else {
CompilerDirectives.transferToInterpreter();
if (givenBaseName != null) {
return Layouts.MODULE.getFields(lexicalParent).getName() + "::" + givenBaseName;
} else if (getLogicalClass() == rubyModuleObject) { // For the case of class Class during initialization
return "#<cyclic>";
} else {
return "#<" + Layouts.MODULE.getFields(getLogicalClass()).getName() + ":0x" + Long.toHexString(ObjectIDOperations.verySlowGetObjectID(context, rubyModuleObject)) + ">";
}
return "#<" + Layouts.MODULE.getFields(getLogicalClass()).getName() + ":0x" + Long.toHexString(ObjectIDOperations.verySlowGetObjectID(context, rubyModuleObject)) + ">";
}
}

public boolean hasName() {
return name != null;
public boolean hasFullName() {
return hasFullName;
}

public boolean hasPartialName() {
return hasName() || givenBaseName != null;
return hasFullName() || givenBaseName != null;
}

@Override
@@ -616,4 +634,5 @@ public Set<DynamicObject> getAdjacentObjects() {

return adjacent;
}

}
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;

@@ -166,6 +167,7 @@ public static boolean singleByteOptimizable(DynamicObject string) {
return StringSupport.isSingleByteOptimizable(getCodeRangeable(string), EncodingUtils.STR_ENC_GET(getCodeRangeable(string)));
}

@TruffleBoundary
public static ByteList encodeByteList(CharSequence value, Encoding encoding) {
return RubyString.encodeBytelist(value, encoding);
}