Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Truffle] Reimplemented the :module_mirror primitive in Ruby to simpl…
Browse files Browse the repository at this point in the history
…ify corner cases.
nirvdrum committed Jun 16, 2015
1 parent c6b5cac commit c3065ba
Showing 4 changed files with 46 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -9,49 +9,33 @@
*/
package org.jruby.truffle.nodes.rubinius;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
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.source.SourceSection;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyModule;


public abstract class ModulePrimitiveNodes {

@RubiniusPrimitive(name = "module_mirror")
public abstract static class ModuleMirrorPrimitiveNode extends RubiniusPrimitiveNode {

@Child private CallDispatchHeadNode moduleMirrorNode;

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

@Specialization(guards = "logicalClass == object.getLogicalClass()")
public Object moduleMirrorCached(RubyBasicObject object,
@Cached("object.getLogicalClass()") RubyClass logicalClass,
@Cached("lookupMirror(object)") Object mirror) {
return mirror;
}

@Specialization
public Object moduleMirrorUncached(RubyBasicObject object) {
return lookupMirror(object);
}

@TruffleBoundary
protected Object lookupMirror(RubyBasicObject object) {
final RubyModule rubinius = (RubyModule) getContext().getCoreLibrary().getObjectClass().getConstants().get("Rubinius").getValue();
final RubyModule mirror = (RubyModule) rubinius.getConstants().get("Mirror").getValue();
final RubyConstant objectMirrorConstant = mirror.getConstants().get(object.getLogicalClass().getName());

if (objectMirrorConstant == null) {
return nil();
public Object moduleMirrorCached(VirtualFrame frame, Object reflectee) {
if (moduleMirrorNode == null) {
CompilerDirectives.transferToInterpreter();
moduleMirrorNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), null));
}

return objectMirrorConstant.getValue();
return moduleMirrorNode.call(frame, getContext().getCoreLibrary().getRubiniusMirror(), "module_mirror", null, reflectee);
}

}
Original file line number Diff line number Diff line change
@@ -124,6 +124,7 @@ public class CoreLibrary {
private final RubyModule kernelModule;
private final RubyModule rubiniusModule;
private final RubyModule rubiniusFFIModule;
private final RubyClass rubiniusMirrorModule;
private final RubyModule signalModule;
private final RubyModule truffleModule;
private final RubyClass bigDecimalClass;
@@ -356,6 +357,8 @@ public CoreLibrary(RubyContext context) {
rubiniusFFIModule = defineModule(rubiniusModule, "FFI");
defineModule(defineModule(rubiniusFFIModule, "Platform"), "POSIX");
defineClass(rubiniusFFIModule, objectClass, "Pointer", new PointerPrimitiveNodes.PointerAllocator());

rubiniusMirrorModule = defineClass(rubiniusModule, objectClass, "Mirror");
defineModule(rubiniusModule, "Type");

byteArrayClass = defineClass(rubiniusModule, objectClass, "ByteArray");
@@ -1387,6 +1390,10 @@ public RubyClass getTupleClass() {
return tupleClass;
}

public RubyClass getRubiniusMirror() {
return rubiniusMirrorModule;
}

public RubyBasicObject getRubiniusUndefined() {
return rubiniusUndefined;
}
1 change: 1 addition & 0 deletions truffle/src/main/ruby/core.rb
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@

# Patch rubinius-core-api to make it work for us

require_relative 'core/rubinius/api/shims/mirror'
require_relative 'core/rubinius/api/shims/lookuptable'
require_relative 'core/rubinius/api/shims/array'
require_relative 'core/rubinius/api/shims/rubinius'
27 changes: 27 additions & 0 deletions truffle/src/main/ruby/core/rubinius/api/shims/mirror.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 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

module Rubinius
class Mirror

# Implementation of the :module_mirror Rubinius primitive.
def self.module_mirror(obj)
if obj.is_a?(::Numeric)
Rubinius::Mirror::Numeric
else
begin
Rubinius::Mirror.const_get(obj.class.name.to_sym, false)
rescue NameError
# TODO (nirvdrum 06-Jun-15) Rubinius defaults to Rubinius::Mirror::Object, but we don't have that yet. `nil` is safe based upon current usage.
nil
end
end
end

end
end

0 comments on commit c3065ba

Please sign in to comment.