diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/ArrayAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/ArrayAttributeNode.java index 7671b2971d04890eee553ae87d73d8522131d786..cfe144c94ac383973b0dd0babfa49227070b4415 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/ArrayAttributeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/ArrayAttributeNode.java @@ -24,23 +24,33 @@ package com.oracle.truffle.r.nodes.attributes; import java.util.List; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributeStorage; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RAttributesLayout.AttrsLayout; import com.oracle.truffle.r.runtime.data.RAttributesLayout.RAttribute; public abstract class ArrayAttributeNode extends AttributeIterativeAccessNode { + private static final RAttribute[] EMPTY = new RAttribute[0]; + + @Child private ArrayAttributeNode recursive; + public static ArrayAttributeNode create() { return ArrayAttributeNodeGen.create(); } - public abstract RAttribute[] execute(DynamicObject attrs); + public abstract RAttribute[] execute(Object attrs); @Specialization(limit = "CACHE_LIMIT", guards = {"attrsLayout != null", "attrsLayout.shape.check(attrs)"}) @ExplodeLoop @@ -69,7 +79,29 @@ public abstract class ArrayAttributeNode extends AttributeIterativeAccessNode { } return result; - } + @Specialization + protected RAttribute[] getArrayFallback(RAttributable x, + @Cached("create()") BranchProfile attrNullProfile, + @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile, + @Cached("createClassProfile()") ValueProfile xTypeProfile) { + DynamicObject attributes; + if (attrStorageProfile.profile(x instanceof RAttributeStorage)) { + attributes = ((RAttributeStorage) x).getAttributes(); + } else { + attributes = xTypeProfile.profile(x).getAttributes(); + } + + if (attributes == null) { + attrNullProfile.enter(); + return EMPTY; + } + if (recursive == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + recursive = insert(create()); + } + + return recursive.execute(attributes); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/IterableAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/IterableAttributeNode.java index 99decfc061953e1c6bc18a7cd0b6d8c317a57870..9032aaefedfbd5b61744a27671cf38dc243df9f7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/IterableAttributeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/IterableAttributeNode.java @@ -22,20 +22,28 @@ */ package com.oracle.truffle.r.nodes.attributes; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributeStorage; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RAttributesLayout.AttrsLayout; public abstract class IterableAttributeNode extends AttributeIterativeAccessNode { + @Child private IterableAttributeNode recursive; + public static IterableAttributeNode create() { return IterableAttributeNodeGen.create(); } - public abstract RAttributesLayout.RAttributeIterable execute(DynamicObject attrs); + public abstract RAttributesLayout.RAttributeIterable execute(Object attr); @Specialization(limit = "CACHE_LIMIT", guards = {"attrsLayout != null", "shapeCheck(attrsLayout.shape, attrs)"}) protected RAttributesLayout.RAttributeIterable getArrayFromConstantLayouts(DynamicObject attrs, @@ -49,4 +57,27 @@ public abstract class IterableAttributeNode extends AttributeIterativeAccessNode return RAttributesLayout.asIterable(attrs); } + @Specialization + protected RAttributesLayout.RAttributeIterable getArrayFallback(RAttributable x, + @Cached("create()") BranchProfile attrNullProfile, + @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile, + @Cached("createClassProfile()") ValueProfile xTypeProfile) { + DynamicObject attributes; + if (attrStorageProfile.profile(x instanceof RAttributeStorage)) { + attributes = ((RAttributeStorage) x).getAttributes(); + } else { + attributes = xTypeProfile.profile(x).getAttributes(); + } + + if (attributes == null) { + attrNullProfile.enter(); + return RAttributesLayout.RAttributeIterable.EMPTY; + } + if (recursive == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + recursive = insert(create()); + } + + return recursive.execute(attributes); + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java index 8f35974969087a286e79230a3b7af3788e483ff2..523100966ba101fd359421ba7c15423cbd3684e2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -257,6 +258,9 @@ public final class RAttributesLayout { } public static final class RAttributeIterable implements Iterable<RAttributesLayout.RAttribute> { + + public static final RAttributeIterable EMPTY = new RAttributeIterable(null, null); + private final DynamicObject attrs; private final List<Property> properties; @@ -267,7 +271,11 @@ public final class RAttributesLayout { @Override public Iterator<RAttributesLayout.RAttribute> iterator() { - return new Iter(attrs, properties.iterator()); + if (attrs == null || properties == null) { + return Collections.emptyIterator(); + } else { + return new Iter(attrs, properties.iterator()); + } } }