@Specialization(
      guards = {
        "!copyAllAttributes || target != source",
        "containsMetadata(source, attrSourceProfiles)"
      })
  public RAbstractVector copySameLength(
      RAbstractVector target,
      RAbstractVector source, //
      @Cached("create()") CopyOfRegAttributesNode copyOfReg, //
      @Cached("createDim()") RemoveAttributeNode removeDim, //
      @Cached("createDimNames()") RemoveAttributeNode removeDimNames, //
      @Cached("create()") InitAttributesNode initAttributes, //
      @Cached("createNames()") PutAttributeNode putNames, //
      @Cached("createDim()") PutAttributeNode putDim, //
      @Cached("createBinaryProfile()") ConditionProfile noDimensions, //
      @Cached("createBinaryProfile()") ConditionProfile hasNamesSource, //
      @Cached("createBinaryProfile()") ConditionProfile hasDimNames) {
    RVector result = target.materialize();

    if (copyAllAttributes) {
      copyOfReg.execute(source, result);
    }

    int[] newDimensions = source.getDimensions();
    if (noDimensions.profile(newDimensions == null)) {
      RAttributes attributes = result.getAttributes();
      if (attributes != null) {
        removeDim.execute(attributes);
        removeDimNames.execute(attributes);
        result.setInternalDimNames(null);
      }
      result.setInternalDimensions(null);

      RStringVector vecNames = source.getNames(attrSourceProfiles);
      if (hasNamesSource.profile(vecNames != null)) {
        putNames.execute(initAttributes.execute(result), vecNames);
        result.setInternalNames(vecNames);
        return result;
      }
      return result;
    }

    putDim.execute(
        initAttributes.execute(result),
        RDataFactory.createIntVector(newDimensions, RDataFactory.COMPLETE_VECTOR));
    result.setInternalDimensions(newDimensions);

    RList newDimNames = source.getDimNames(attrSourceProfiles);
    if (hasDimNames.profile(newDimNames != null)) {
      result.getAttributes().put(RRuntime.DIMNAMES_ATTR_KEY, newDimNames);
      newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
      result.setInternalDimNames(newDimNames);
      return result;
    }
    return result;
  }
Example #2
0
 @ExplodeLoop
 public boolean getContainsNA(PositionProfile[] profiles) {
   if (positionsCheck.length == 1) {
     return containsNAProfile.profile(profiles[0].containsNA);
   } else {
     boolean containsNA = false;
     for (int i = 0; i < positionsCheck.length; i++) {
       containsNA |= profiles[i].containsNA;
     }
     return containsNAProfile.profile(containsNA);
   }
 }
  private Object tryConvertToHash(
      VirtualFrame frame, final int argumentCount, final Object lastArgument) {
    if (respondsToToHashProfile.profile(respondToToHash(frame, lastArgument))) {
      final Object converted = callToHash(frame, lastArgument);

      if (convertedIsHashProfile.profile(RubyGuards.isRubyHash(converted))) {
        RubyArguments.setArgument(frame, argumentCount - 1, converted);
        return converted;
      }
    }

    return null;
  }
  private static final class WriteSuperFrameVariableConditionalNode
      extends WriteSuperFrameVariableNode {

    @Child private ResolvedWriteSuperFrameVariableNode writeNode;
    @Child private WriteSuperFrameVariableNode nextNode;
    @Child private RNode rhs;

    private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile();
    private final ConditionProfile hasValueProfile = ConditionProfile.createBinaryProfile();
    private final ConditionProfile nullSuperFrameProfile = ConditionProfile.createBinaryProfile();

    WriteSuperFrameVariableConditionalNode(
        ResolvedWriteSuperFrameVariableNode writeNode,
        WriteSuperFrameVariableNode nextNode,
        RNode rhs) {
      this.writeNode = writeNode;
      this.nextNode = nextNode;
      this.rhs = rhs;
    }

    @Override
    public Object getName() {
      return writeNode.getName();
    }

    @Override
    public RNode getRhs() {
      return rhs;
    }

    @Override
    public void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame) {
      MaterializedFrame profiledEnclosingFrame = enclosingFrameProfile.profile(enclosingFrame);
      if (hasValueProfile.profile(writeNode.getFrameSlotNode().hasValue(profiledEnclosingFrame))) {
        writeNode.execute(frame, value, profiledEnclosingFrame);
      } else {
        MaterializedFrame superFrame = RArguments.getEnclosingFrame(profiledEnclosingFrame);
        if (nullSuperFrameProfile.profile(superFrame == null)) {
          // Might be the case if "{ x <<- 42 }": This is in globalEnv!
          superFrame = REnvironment.globalEnv().getFrame();
        }
        nextNode.execute(frame, value, superFrame);
      }
    }

    @Override
    public void execute(VirtualFrame frame, Object value) {
      assert RArguments.getEnclosingFrame(frame) != null;
      execute(frame, value, RArguments.getEnclosingFrame(frame));
    }
  }
 @Override
 public void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame) {
   MaterializedFrame profiledEnclosingFrame = enclosingFrameProfile.profile(enclosingFrame);
   if (hasValueProfile.profile(writeNode.getFrameSlotNode().hasValue(profiledEnclosingFrame))) {
     writeNode.execute(frame, value, profiledEnclosingFrame);
   } else {
     MaterializedFrame superFrame = RArguments.getEnclosingFrame(profiledEnclosingFrame);
     if (nullSuperFrameProfile.profile(superFrame == null)) {
       // Might be the case if "{ x <<- 42 }": This is in globalEnv!
       superFrame = REnvironment.globalEnv().getFrame();
     }
     nextNode.execute(frame, value, superFrame);
   }
 }
  @Specialization(guards = {"!copyAllAttributes || target != source", "containsMetadata(source)"})
  protected RAbstractVector copySameLength(
      RAbstractVector target,
      RAbstractVector source, //
      @Cached("create()") CopyOfRegAttributesNode copyOfReg, //
      @Cached("createDim()") RemoveFixedAttributeNode removeDim, //
      @Cached("createDimNames()") RemoveFixedAttributeNode removeDimNames, //
      @Cached("create()") InitAttributesNode initAttributes, //
      @Cached("createNames()") SetFixedAttributeNode putNames, //
      @Cached("createDim()") SetFixedAttributeNode putDim, //
      @Cached("createDimNames()") SetFixedAttributeNode putDimNames, //
      @Cached("createBinaryProfile()") ConditionProfile noDimensions, //
      @Cached("createBinaryProfile()") ConditionProfile hasNamesSource, //
      @Cached("createBinaryProfile()") ConditionProfile hasDimNames,
      @Cached("create()") GetDimAttributeNode getDimsNode) {
    RVector<?> result = target.materialize();

    if (copyAllAttributes) {
      copyOfReg.execute(source, result);
    }

    int[] newDimensions = getDimsNode.getDimensions(source);
    if (noDimensions.profile(newDimensions == null)) {
      DynamicObject attributes = result.getAttributes();
      if (attributes != null) {
        removeDim.execute(attributes);
        removeDimNames.execute(attributes);
      }

      RStringVector vecNames = getNamesNode.getNames(source);
      if (hasNamesSource.profile(vecNames != null)) {
        putNames.execute(initAttributes.execute(result), vecNames);
        return result;
      }
      return result;
    }

    putDim.execute(
        initAttributes.execute(result),
        RDataFactory.createIntVector(newDimensions, RDataFactory.COMPLETE_VECTOR));

    RList newDimNames = getDimNamesNode.getDimNames(source);
    if (hasDimNames.profile(newDimNames != null)) {
      putDimNames.execute(result.getAttributes(), newDimNames);
      newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
      return result;
    }
    return result;
  }
Example #7
0
 @Specialization(guards = {"each > 1", "hasNames(x)"})
 protected RAbstractVector repEachNames(
     RAbstractVector x,
     RAbstractIntVector times,
     int lengthOut,
     int each,
     @Cached("create()") InitAttributesNode initAttributes,
     @Cached("createNames()") SetFixedAttributeNode putNames) {
   if (times.getLength() > 1) {
     errorBranch.enter();
     throw invalidTimes();
   }
   RAbstractVector input = handleEach(x, each);
   RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each);
   RVector<?> r;
   if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
     names = (RStringVector) handleLengthOut(names, lengthOut, false);
     r = handleLengthOut(input, lengthOut, false);
   } else {
     names = (RStringVector) handleTimes(names, times, false);
     r = handleTimes(input, times, false);
   }
   putNames.execute(initAttributes.execute(r), names);
   return r;
 }
  private Object lookupRestKeywordArgumentHash(VirtualFrame frame) {
    final Object hash = readUserKeywordsHashNode.execute(frame);

    if (noHash.profile(hash == null)) {
      return Layouts.HASH.createHash(
          coreLibrary().getHashFactory(), null, 0, null, null, null, null, false);
    }

    CompilerDirectives.bailout("Ruby keyword arguments aren't optimized");

    final DynamicObject hashObject = (DynamicObject) hash;

    final List<Map.Entry<Object, Object>> entries = new ArrayList<>();

    outer:
    for (Map.Entry<Object, Object> keyValue : HashOperations.iterableKeyValues(hashObject)) {
      if (!RubyGuards.isRubySymbol(keyValue.getKey())) {
        continue;
      }

      for (String excludedKeyword : excludedKeywords) {
        if (excludedKeyword.equals(keyValue.getKey().toString())) {
          continue outer;
        }
      }

      entries.add(keyValue);
    }

    return BucketsStrategy.create(
        getContext(), entries, Layouts.HASH.getCompareByIdentity(hashObject));
  }
  @Override
  public Object execute(VirtualFrame frame) {
    final int argumentCount = RubyArguments.getArgumentsCount(frame);

    if (notEnoughArgumentsProfile.profile(argumentCount <= minArgumentCount)) {
      return null;
    }

    final Object lastArgument = RubyArguments.getArgument(frame, argumentCount - 1);

    if (lastArgumentIsHashProfile.profile(RubyGuards.isRubyHash(lastArgument))) {
      return lastArgument;
    }

    return tryConvertToHash(frame, argumentCount, lastArgument);
  }
public class AdvanceSourcePositionNode extends FormatNode {

  private final boolean toEnd;

  private final ConditionProfile rangeProfile = ConditionProfile.createBinaryProfile();

  public AdvanceSourcePositionNode(RubyContext context, boolean toEnd) {
    super(context);
    this.toEnd = toEnd;
  }

  @Override
  public Object execute(VirtualFrame frame) {
    if (toEnd) {
      setSourcePosition(frame, getSourceLength(frame));
    } else {
      final int position = getSourcePosition(frame);

      if (rangeProfile.profile(position + 1 > getSourceLength(frame))) {
        throw new OutsideOfStringException();
      }

      setSourcePosition(frame, getSourcePosition(frame) + 1);
    }

    return null;
  }
}
Example #11
0
 /** Replicate the vector a given number of times. */
 private RVector<?> handleTimes(
     RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) {
   if (oneTimeGiven.profile(times.getLength() == 1)) {
     // only one times value is given
     final int howManyTimes = times.getDataAt(0);
     if (howManyTimes < 0) {
       errorBranch.enter();
       throw invalidTimes();
     }
     if (replicateOnce.profile(howManyTimes == 1)) {
       return (RVector<?>) (copyIfSameSize ? x.copy() : x);
     } else {
       return x.copyResized(x.getLength() * howManyTimes, false);
     }
   } else {
     // times is a vector with several elements
     if (x.getLength() != times.getLength()) {
       errorBranch.enter();
       invalidTimes();
     }
     // iterate once over the times vector to determine result vector size
     int resultLength = 0;
     for (int i = 0; i < times.getLength(); i++) {
       int t = times.getDataAt(i);
       if (t < 0) {
         errorBranch.enter();
         throw invalidTimes();
       }
       resultLength += t;
     }
     // create and populate result vector
     RVector<?> r = x.createEmptySameType(resultLength, x.isComplete());
     int wp = 0; // write pointer
     for (int i = 0; i < x.getLength(); i++) {
       for (int j = 0; j < times.getDataAt(i); ++j, ++wp) {
         r.transferElementSameType(wp, x, i);
       }
     }
     return r;
   }
 }
@NodeChild(value = "lexicalParentModule", type = RubyNode.class)
public abstract class DefineModuleNode extends RubyNode {

  private final String name;

  @Child LookupForExistingModuleNode lookupForExistingModuleNode;

  private final ConditionProfile needToDefineProfile = ConditionProfile.createBinaryProfile();
  private final BranchProfile errorProfile = BranchProfile.create();

  public DefineModuleNode(RubyContext context, SourceSection sourceSection, String name) {
    super(context, sourceSection);
    this.name = name;
  }

  @Specialization(guards = "isRubyModule(lexicalParentModule)")
  public Object defineModule(VirtualFrame frame, DynamicObject lexicalParentModule) {
    final RubyConstant constant = lookupForExistingModule(frame, name, lexicalParentModule);

    final DynamicObject definingModule;

    if (needToDefineProfile.profile(constant == null)) {
      definingModule =
          ModuleNodes.createModule(
              getContext(), coreLibrary().getModuleClass(), lexicalParentModule, name, this);
    } else {
      final Object constantValue = constant.getValue();

      if (!RubyGuards.isRubyModule(constantValue) || RubyGuards.isRubyClass(constantValue)) {
        errorProfile.enter();
        throw new RaiseException(coreExceptions().typeErrorIsNotA(name, "module", this));
      }

      definingModule = (DynamicObject) constantValue;
    }

    return definingModule;
  }

  @Specialization(guards = "!isRubyModule(lexicalParentObject)")
  public Object defineModuleWrongParent(VirtualFrame frame, Object lexicalParentObject) {
    throw new RaiseException(coreExceptions().typeErrorIsNotA(lexicalParentObject, "module", this));
  }

  private RubyConstant lookupForExistingModule(
      VirtualFrame frame, String name, DynamicObject lexicalParent) {
    if (lookupForExistingModuleNode == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      lookupForExistingModuleNode = insert(LookupForExistingModuleNodeGen.create(null, null));
    }
    return lookupForExistingModuleNode.executeLookupForExistingModule(frame, name, lexicalParent);
  }
}
public class ReadKeywordRestArgumentNode extends RubyNode {

  private final String[] excludedKeywords;

  @Child private ReadUserKeywordsHashNode readUserKeywordsHashNode;

  private final ConditionProfile noHash = ConditionProfile.createBinaryProfile();

  public ReadKeywordRestArgumentNode(
      RubyContext context, SourceSection sourceSection, int minimum, String[] excludedKeywords) {
    super(context, sourceSection);
    this.excludedKeywords = excludedKeywords;
    readUserKeywordsHashNode = new ReadUserKeywordsHashNode(context, sourceSection, minimum);
  }

  @Override
  public Object execute(VirtualFrame frame) {
    return lookupRestKeywordArgumentHash(frame);
  }

  private Object lookupRestKeywordArgumentHash(VirtualFrame frame) {
    final Object hash = readUserKeywordsHashNode.execute(frame);

    if (noHash.profile(hash == null)) {
      return Layouts.HASH.createHash(
          coreLibrary().getHashFactory(), null, 0, null, null, null, null, false);
    }

    CompilerDirectives.bailout("Ruby keyword arguments aren't optimized");

    final DynamicObject hashObject = (DynamicObject) hash;

    final List<Map.Entry<Object, Object>> entries = new ArrayList<>();

    outer:
    for (Map.Entry<Object, Object> keyValue : HashOperations.iterableKeyValues(hashObject)) {
      if (!RubyGuards.isRubySymbol(keyValue.getKey())) {
        continue;
      }

      for (String excludedKeyword : excludedKeywords) {
        if (excludedKeyword.equals(keyValue.getKey().toString())) {
          continue outer;
        }
      }

      entries.add(keyValue);
    }

    return BucketsStrategy.create(
        getContext(), entries, Layouts.HASH.getCompareByIdentity(hashObject));
  }
}
Example #14
0
 @Specialization(guards = {"each <= 1", "!hasNames(x)"})
 protected RAbstractVector repNoEachNoNames(
     RAbstractVector x,
     RAbstractIntVector times,
     int lengthOut,
     @SuppressWarnings("unused") int each) {
   if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
     return handleLengthOut(x, lengthOut, true);
   } else {
     return handleTimes(x, times, true);
   }
 }
Example #15
0
 @Specialization(guards = {"each > 1", "!hasNames(x)"})
 protected RAbstractVector repEachNoNames(
     RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) {
   if (times.getLength() > 1) {
     errorBranch.enter();
     throw invalidTimes();
   }
   RAbstractVector input = handleEach(x, each);
   if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
     return handleLengthOut(input, lengthOut, false);
   } else {
     return handleTimes(input, times, false);
   }
 }
  @Specialization(guards = "strategy.matches(array)", limit = "ARRAY_STRATEGIES")
  public boolean ensureCapacity(
      DynamicObject array,
      int requiredCapacity,
      @Cached("of(array)") ArrayStrategy strategy,
      @Cached("createCountingProfile()") ConditionProfile extendProfile) {
    final ArrayMirror mirror = strategy.newMirror(array);

    if (extendProfile.profile(mirror.getLength() < requiredCapacity)) {
      final int capacity = ArrayUtils.capacity(getContext(), mirror.getLength(), requiredCapacity);
      Layouts.ARRAY.setStore(array, mirror.copyArrayAndMirror(capacity).getArray());
      return true;
    } else {
      return false;
    }
  }
  @Override
  public Object execute(VirtualFrame frame) {
    if (toEnd) {
      setSourcePosition(frame, getSourceLength(frame));
    } else {
      final int position = getSourcePosition(frame);

      if (rangeProfile.profile(position + 1 > getSourceLength(frame))) {
        throw new OutsideOfStringException();
      }

      setSourcePosition(frame, getSourcePosition(frame) + 1);
    }

    return null;
  }
Example #18
0
 @Specialization
 protected Object getDimNames(RAbstractContainer container) {
   controlVisibility();
   RList names;
   if (container instanceof RDataFrame) {
     dataframeProfile.enter();
     names = ((RDataFrame) container).getVector().getDimNames();
   } else if (container instanceof RFactor) {
     factorProfile.enter();
     names = ((RFactor) container).getVector().getDimNames();
   } else {
     otherProfile.enter();
     names = container.getDimNames(attrProfiles);
   }
   return nullProfile.profile(names == null) ? RNull.instance : names;
 }
Example #19
0
 @Specialization(
     guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
 protected RAbstractVector repNoEachNoNamesSimple(
     RAbstractDoubleVector x,
     RAbstractIntVector times,
     int lengthOut,
     @SuppressWarnings("unused") int each) {
   int t = times.getDataAt(0);
   if (t < 0) {
     errorBranch.enter();
     throw invalidTimes();
   }
   int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
   double[] data = new double[length];
   Arrays.fill(data, x.getDataAt(0));
   return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0)));
 }
Example #20
0
 @Specialization(guards = {"each <= 1", "hasNames(x)"})
 protected RAbstractVector repNoEachNames(
     RAbstractVector x,
     RAbstractIntVector times,
     int lengthOut,
     @SuppressWarnings("unused") int each,
     @Cached("create()") InitAttributesNode initAttributes,
     @Cached("createNames()") SetFixedAttributeNode putNames) {
   RStringVector names;
   RVector<?> r;
   if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
     names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true);
     r = handleLengthOut(x, lengthOut, true);
   } else {
     names = (RStringVector) handleTimes(getNames.getNames(x), times, true);
     r = handleTimes(x, times, true);
   }
   putNames.execute(initAttributes.execute(r), names);
   return r;
 }
Example #21
0
 private void checkSlotAssign(VirtualFrame frame, Object object, String name, Object value) {
   // TODO: optimize using a mechanism similar to overrides?
   if (checkSlotAssignFunction == null) {
     CompilerDirectives.transferToInterpreterAndInvalidate();
     checkSlotAssignFunction = (RFunction) checkAtAssignmentFind.execute(frame);
     checkAtAssignmentCall = insert(CallRFunctionNode.create(checkSlotAssignFunction.getTarget()));
     assert objClassHierarchy == null && valClassHierarchy == null;
     objClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
     valClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
   }
   RStringVector objClass = objClassHierarchy.execute(object);
   RStringVector valClass = objClassHierarchy.execute(value);
   RFunction currentFunction = (RFunction) checkAtAssignmentFind.execute(frame);
   if (cached.profile(currentFunction == checkSlotAssignFunction)) {
     // TODO: technically, someone could override checkAtAssignment function and access the
     // caller, but it's rather unlikely
     checkAtAssignmentCall.execute(
         frame,
         checkSlotAssignFunction,
         RCaller.create(frame, getOriginalCall()),
         null,
         new Object[] {objClass, name, valClass},
         SIGNATURE,
         checkSlotAssignFunction.getEnclosingFrame(),
         null);
   } else {
     // slow path
     RContext.getEngine()
         .evalFunction(
             currentFunction,
             frame.materialize(),
             RCaller.create(frame, getOriginalCall()),
             null,
             objClass,
             name,
             valClass);
   }
 }
  @Specialization(guards = "isRubyModule(lexicalParentModule)")
  public Object defineModule(VirtualFrame frame, DynamicObject lexicalParentModule) {
    final RubyConstant constant = lookupForExistingModule(frame, name, lexicalParentModule);

    final DynamicObject definingModule;

    if (needToDefineProfile.profile(constant == null)) {
      definingModule =
          ModuleNodes.createModule(
              getContext(), coreLibrary().getModuleClass(), lexicalParentModule, name, this);
    } else {
      final Object constantValue = constant.getValue();

      if (!RubyGuards.isRubyModule(constantValue) || RubyGuards.isRubyClass(constantValue)) {
        errorProfile.enter();
        throw new RaiseException(coreExceptions().typeErrorIsNotA(name, "module", this));
      }

      definingModule = (DynamicObject) constantValue;
    }

    return definingModule;
  }
Example #23
0
@RBuiltin(
    name = "dimnames",
    kind = PRIMITIVE,
    parameterNames = {"x"},
    dispatch = INTERNAL_GENERIC)
public abstract class DimNames extends RBuiltinNode {

  private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
  private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile();
  private final BranchProfile dataframeProfile = BranchProfile.create();
  private final BranchProfile factorProfile = BranchProfile.create();
  private final BranchProfile otherProfile = BranchProfile.create();

  @Specialization
  protected RNull getDimNames(@SuppressWarnings("unused") RNull operand) {
    controlVisibility();
    return RNull.instance;
  }

  @Specialization
  protected Object getDimNames(RAbstractContainer container) {
    controlVisibility();
    RList names;
    if (container instanceof RDataFrame) {
      dataframeProfile.enter();
      names = ((RDataFrame) container).getVector().getDimNames();
    } else if (container instanceof RFactor) {
      factorProfile.enter();
      names = ((RFactor) container).getVector().getDimNames();
    } else {
      otherProfile.enter();
      names = container.getDimNames(attrProfiles);
    }
    return nullProfile.profile(names == null) ? RNull.instance : names;
  }
}
Example #24
0
final class PositionsCheckNode extends Node {

  @Children private final PositionCheckNode[] positionsCheck;

  private final ElementAccessMode mode;
  private final BranchProfile errorBranch = BranchProfile.create();
  private final VectorLengthProfile selectedPositionsCountProfile = VectorLengthProfile.create();
  private final VectorLengthProfile maxOutOfBoundsProfile = VectorLengthProfile.create();
  private final ConditionProfile containsNAProfile = ConditionProfile.createBinaryProfile();
  private final BranchProfile unsupportedProfile = BranchProfile.create();
  private final boolean replace;
  private final int positionsLength;

  PositionsCheckNode(
      ElementAccessMode mode,
      RType containerType,
      Object[] positions,
      boolean exact,
      boolean replace,
      boolean recursive) {
    this.mode = mode;
    this.replace = replace;
    this.positionsCheck = new PositionCheckNode[positions.length];
    for (int i = 0; i < positions.length; i++) {
      positionsCheck[i] =
          PositionCheckNode.createNode(
              mode, containerType, positions[i], i, positions.length, exact, replace, recursive);
    }
    this.positionsLength = positions.length;
  }

  public PositionCheckNode getPositionCheckAt(int index) {
    return positionsCheck[index];
  }

  @ExplodeLoop
  public boolean isSupported(Object[] positions) {
    if (positionsCheck.length != positions.length) {
      unsupportedProfile.enter();
      return false;
    }
    for (int i = 0; i < positionsCheck.length; i++) {
      if (!positionsCheck[i].isSupported(positions[i])) {
        unsupportedProfile.enter();
        return false;
      }
    }
    return true;
  }

  public int getDimensions() {
    return positionsCheck.length;
  }

  public boolean isSingleDimension() {
    return positionsCheck.length == 1;
  }

  public boolean isMultiDimension() {
    return positionsCheck.length > 1;
  }

  @ExplodeLoop
  public PositionProfile[] executeCheck(
      RAbstractContainer vector, int[] vectorDimensions, int vectorLength, Object[] positions) {
    assert isSupported(positions);
    verifyDimensions(vectorDimensions);

    PositionProfile[] statistics = new PositionProfile[positionsLength];
    for (int i = 0; i < positionsLength; i++) {
      Object position = positions[i];
      PositionProfile profile = new PositionProfile();
      positions[i] =
          positionsCheck[i].execute(profile, vector, vectorDimensions, vectorLength, position);
      statistics[i] = profile;
    }
    return statistics;
  }

  @TruffleBoundary
  private void print() {
    System.out.println(positionsCheck.length);
  }

  private void verifyDimensions(int[] vectorDimensions) {
    if (vectorDimensions == null) {
      if (isMultiDimension()) {
        errorBranch.enter();
        throw dimensionsError();
      }
    } else {
      if (getDimensions() > vectorDimensions.length || getDimensions() < vectorDimensions.length) {
        errorBranch.enter();
        throw dimensionsError();
      }
    }
  }

  private RError dimensionsError() {
    if (replace) {
      if (mode.isSubset()) {
        if (getDimensions() == 2) {
          return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX);
        } else {
          return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS);
        }
      } else {
        return RError.error(this, RError.Message.IMPROPER_SUBSCRIPT);
      }
    } else {
      return RError.error(this, RError.Message.INCORRECT_DIMENSIONS);
    }
  }

  @ExplodeLoop
  public int getSelectedPositionsCount(PositionProfile[] profiles) {
    if (positionsCheck.length == 1) {
      return selectedPositionsCountProfile.profile(profiles[0].selectedPositionsCount);
    } else {
      int newSize = 1;
      for (int i = 0; i < positionsCheck.length; i++) {
        newSize *= profiles[i].selectedPositionsCount;
      }
      return selectedPositionsCountProfile.profile(newSize);
    }
  }

  public int getCachedSelectedPositionsCount() {
    return selectedPositionsCountProfile.getCachedLength();
  }

  @ExplodeLoop
  public boolean getContainsNA(PositionProfile[] profiles) {
    if (positionsCheck.length == 1) {
      return containsNAProfile.profile(profiles[0].containsNA);
    } else {
      boolean containsNA = false;
      for (int i = 0; i < positionsCheck.length; i++) {
        containsNA |= profiles[i].containsNA;
      }
      return containsNAProfile.profile(containsNA);
    }
  }

  @ExplodeLoop
  public int getMaxOutOfBounds(PositionProfile[] replacementStatistics) {
    if (positionsCheck.length == 1) {
      return maxOutOfBoundsProfile.profile(replacementStatistics[0].maxOutOfBoundsIndex);
    } else {
      // impossible to be relevant as position check will throw an error in this case.
      return 0;
    }
  }

  public boolean isMissing() {
    return positionsCheck.length == 1
        && //
        (positionsCheck[0].getPositionClass() == RMissing.class
            || positionsCheck[0].getPositionClass() == REmpty.class
            || //
            positionsCheck[0].getPositionClass() == RSymbol.class);
  }

  final class PositionProfile {

    int selectedPositionsCount;

    int maxOutOfBoundsIndex;

    boolean containsNA;
  }
}
Example #25
0
/**
 * The {@code rep} builtin works as follows.
 *
 * <ol>
 *   <li>If {@code each} is greater than one, all elements of {@code x} are first replicated {@code
 *       each} times.
 *   <li>If {@code length.out} is given, the result of the first step is truncated or extended as
 *       required. In this case, {@code times} is ignored.
 *   <li>If {@code length.out} is not given, {@code times} is regarded:
 *       <ul>
 *         <li>If {@code times} is a one-element vector, the result of the first step is replicated
 *             {@code times} times.
 *         <li>If {@code times} is a vector longer than one, and {@code each} is greater than one,
 *             an error is issued.
 *         <li>If {@code times} is a vector longer than one, and {@code each} is one, and {@code
 *             times} is as long as {@code x}, each element of {@code x} is given the number of
 *             times indicated by the value at the same index of {@code times}. If {@code times} has
 *             a different length, an error is issued.
 *       </ul>
 * </ol>
 */
@RBuiltin(
    name = "rep",
    kind = PRIMITIVE,
    parameterNames = {"x", "times", "length.out", "each"},
    dispatch = INTERNAL_GENERIC,
    behavior = PURE)
public abstract class Repeat extends RBuiltinNode {

  protected abstract Object execute(
      RAbstractVector x, RAbstractIntVector times, int lengthOut, int each);

  private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile();
  private final BranchProfile errorBranch = BranchProfile.create();
  private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile();
  private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile();
  @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();

  @Override
  public Object[] getDefaultParameterValues() {
    return new Object[] {RMissing.instance, 1, RRuntime.INT_NA, 1};
  }

  private String argType(Object arg) {
    return ((RTypedValue) arg).getRType().getName();
  }

  @Override
  protected void createCasts(CastBuilder casts) {
    Function<Object, Object> argType = this::argType;
    casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, argType);
    casts
        .arg("times")
        .defaultError(RError.Message.INVALID_ARGUMENT, "times")
        .mustNotBeNull()
        .asIntegerVector();
    casts
        .arg("length.out")
        .mustNotBeNull()
        .asIntegerVector()
        .shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out")
        .findFirst(RRuntime.INT_NA, RError.Message.FIRST_ELEMENT_USED, "length.out")
        .mustBe(intNA().or(gte(0)));
    casts
        .arg("each")
        .asIntegerVector()
        .shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each")
        .findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each")
        .notNA(1)
        .mustBe(gte(0));
  }

  protected boolean hasNames(RAbstractVector x) {
    return getNames.getNames(x) != null;
  }

  private RError invalidTimes() {
    throw RError.error(this, RError.Message.INVALID_ARGUMENT, "times");
  }

  @Specialization(
      guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
  protected RAbstractVector repNoEachNoNamesSimple(
      RAbstractDoubleVector x,
      RAbstractIntVector times,
      int lengthOut,
      @SuppressWarnings("unused") int each) {
    int t = times.getDataAt(0);
    if (t < 0) {
      errorBranch.enter();
      throw invalidTimes();
    }
    int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
    double[] data = new double[length];
    Arrays.fill(data, x.getDataAt(0));
    return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0)));
  }

  @Specialization(guards = {"each > 1", "!hasNames(x)"})
  protected RAbstractVector repEachNoNames(
      RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) {
    if (times.getLength() > 1) {
      errorBranch.enter();
      throw invalidTimes();
    }
    RAbstractVector input = handleEach(x, each);
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      return handleLengthOut(input, lengthOut, false);
    } else {
      return handleTimes(input, times, false);
    }
  }

  @Specialization(guards = {"each <= 1", "!hasNames(x)"})
  protected RAbstractVector repNoEachNoNames(
      RAbstractVector x,
      RAbstractIntVector times,
      int lengthOut,
      @SuppressWarnings("unused") int each) {
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      return handleLengthOut(x, lengthOut, true);
    } else {
      return handleTimes(x, times, true);
    }
  }

  @Specialization(guards = {"each > 1", "hasNames(x)"})
  protected RAbstractVector repEachNames(
      RAbstractVector x,
      RAbstractIntVector times,
      int lengthOut,
      int each,
      @Cached("create()") InitAttributesNode initAttributes,
      @Cached("createNames()") SetFixedAttributeNode putNames) {
    if (times.getLength() > 1) {
      errorBranch.enter();
      throw invalidTimes();
    }
    RAbstractVector input = handleEach(x, each);
    RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each);
    RVector<?> r;
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      names = (RStringVector) handleLengthOut(names, lengthOut, false);
      r = handleLengthOut(input, lengthOut, false);
    } else {
      names = (RStringVector) handleTimes(names, times, false);
      r = handleTimes(input, times, false);
    }
    putNames.execute(initAttributes.execute(r), names);
    return r;
  }

  @Specialization(guards = {"each <= 1", "hasNames(x)"})
  protected RAbstractVector repNoEachNames(
      RAbstractVector x,
      RAbstractIntVector times,
      int lengthOut,
      @SuppressWarnings("unused") int each,
      @Cached("create()") InitAttributesNode initAttributes,
      @Cached("createNames()") SetFixedAttributeNode putNames) {
    RStringVector names;
    RVector<?> r;
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true);
      r = handleLengthOut(x, lengthOut, true);
    } else {
      names = (RStringVector) handleTimes(getNames.getNames(x), times, true);
      r = handleTimes(x, times, true);
    }
    putNames.execute(initAttributes.execute(r), names);
    return r;
  }

  /** Prepare the input vector by replicating its elements. */
  private static RVector<?> handleEach(RAbstractVector x, int each) {
    RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete());
    for (int i = 0; i < x.getLength(); i++) {
      for (int j = i * each; j < (i + 1) * each; j++) {
        r.transferElementSameType(j, x, i);
      }
    }
    return r;
  }

  /** Extend or truncate the vector to a specified length. */
  private static RVector<?> handleLengthOut(
      RAbstractVector x, int lengthOut, boolean copyIfSameSize) {
    if (x.getLength() == lengthOut) {
      return (RVector<?>) (copyIfSameSize ? x.copy() : x);
    }
    return x.copyResized(lengthOut, false);
  }

  /** Replicate the vector a given number of times. */
  private RVector<?> handleTimes(
      RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) {
    if (oneTimeGiven.profile(times.getLength() == 1)) {
      // only one times value is given
      final int howManyTimes = times.getDataAt(0);
      if (howManyTimes < 0) {
        errorBranch.enter();
        throw invalidTimes();
      }
      if (replicateOnce.profile(howManyTimes == 1)) {
        return (RVector<?>) (copyIfSameSize ? x.copy() : x);
      } else {
        return x.copyResized(x.getLength() * howManyTimes, false);
      }
    } else {
      // times is a vector with several elements
      if (x.getLength() != times.getLength()) {
        errorBranch.enter();
        invalidTimes();
      }
      // iterate once over the times vector to determine result vector size
      int resultLength = 0;
      for (int i = 0; i < times.getLength(); i++) {
        int t = times.getDataAt(i);
        if (t < 0) {
          errorBranch.enter();
          throw invalidTimes();
        }
        resultLength += t;
      }
      // create and populate result vector
      RVector<?> r = x.createEmptySameType(resultLength, x.isComplete());
      int wp = 0; // write pointer
      for (int i = 0; i < x.getLength(); i++) {
        for (int j = 0; j < times.getDataAt(i); ++j, ++wp) {
          r.transferElementSameType(wp, x, i);
        }
      }
      return r;
    }
  }
}
Example #26
0
@RBuiltin(
    name = "@<-",
    kind = PRIMITIVE,
    parameterNames = {"", "", "value"},
    nonEvalArgs = 1,
    behavior = COMPLEX)
public abstract class UpdateSlot extends RBuiltinNode {

  private static final ArgumentsSignature SIGNATURE =
      ArgumentsSignature.get("cl", "name", "valueClass");

  @CompilationFinal private RFunction checkSlotAssignFunction;
  @Child private ClassHierarchyNode objClassHierarchy;
  @Child private ClassHierarchyNode valClassHierarchy;

  @Child
  private UpdateSlotNode updateSlotNode =
      com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen.create(null, null, null);

  @Child
  private ReadVariableNode checkAtAssignmentFind =
      ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "checkAtAssignment");

  @Child private CallRFunctionNode checkAtAssignmentCall;
  private final ConditionProfile cached = ConditionProfile.createBinaryProfile();

  @Override
  protected void createCasts(CastBuilder casts) {
    casts.arg(0).allowNull().asAttributable(true, true, true);
  }

  protected String getName(Object nameObj) {
    assert nameObj instanceof RPromise;
    Object rep = ((RPromise) nameObj).getRep();
    if (rep instanceof WrapArgumentNode) {
      rep = ((WrapArgumentNode) rep).getOperand();
    }
    if (rep instanceof ConstantNode) {
      Object val = ((ConstantNode) rep).getValue();
      if (val instanceof String) {
        return (String) val;
      }
      if (val instanceof RSymbol) {
        return ((RSymbol) val).getName();
      }
    } else if (rep instanceof ReadVariableNode) {
      return ((ReadVariableNode) rep).getIdentifier();
    } else if (rep instanceof RCallNode) {
      throw RError.error(this, RError.Message.SLOT_INVALID_TYPE, "language");
    }
    // TODO: this is not quite correct, but I wonder if we even reach here (can also be
    // augmented on demand)
    throw RError.error(this, RError.Message.SLOT_INVALID_TYPE, nameObj.getClass().toString());
  }

  private void checkSlotAssign(VirtualFrame frame, Object object, String name, Object value) {
    // TODO: optimize using a mechanism similar to overrides?
    if (checkSlotAssignFunction == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      checkSlotAssignFunction = (RFunction) checkAtAssignmentFind.execute(frame);
      checkAtAssignmentCall = insert(CallRFunctionNode.create(checkSlotAssignFunction.getTarget()));
      assert objClassHierarchy == null && valClassHierarchy == null;
      objClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
      valClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
    }
    RStringVector objClass = objClassHierarchy.execute(object);
    RStringVector valClass = objClassHierarchy.execute(value);
    RFunction currentFunction = (RFunction) checkAtAssignmentFind.execute(frame);
    if (cached.profile(currentFunction == checkSlotAssignFunction)) {
      // TODO: technically, someone could override checkAtAssignment function and access the
      // caller, but it's rather unlikely
      checkAtAssignmentCall.execute(
          frame,
          checkSlotAssignFunction,
          RCaller.create(frame, getOriginalCall()),
          null,
          new Object[] {objClass, name, valClass},
          SIGNATURE,
          checkSlotAssignFunction.getEnclosingFrame(),
          null);
    } else {
      // slow path
      RContext.getEngine()
          .evalFunction(
              currentFunction,
              frame.materialize(),
              RCaller.create(frame, getOriginalCall()),
              null,
              objClass,
              name,
              valClass);
    }
  }

  /*
   * Motivation for cached version is that in the operator form (foo@bar<-baz), the name is an
   * interned string which allows us to avoid longer lookup
   */
  @Specialization(guards = "sameName(nameObj, nameObjCached)")
  protected Object updateSlotCached(
      VirtualFrame frame,
      Object object,
      @SuppressWarnings("unused") Object nameObj,
      Object value,
      @SuppressWarnings("unused") @Cached("nameObj") Object nameObjCached,
      @Cached("getName(nameObjCached)") String name) {
    checkSlotAssign(frame, object, name, value);
    return updateSlotNode.executeUpdate(object, name, value);
  }

  @Specialization(contains = "updateSlotCached")
  protected Object updateSlot(VirtualFrame frame, Object object, Object nameObj, Object value) {
    String name = getName(nameObj);
    checkSlotAssign(frame, object, name, value);
    return updateSlotNode.executeUpdate(object, name, value);
  }

  protected boolean sameName(Object nameObj, Object nameObjCached) {
    assert nameObj instanceof RPromise;
    assert nameObjCached instanceof RPromise;
    return ((RPromise) nameObj).getRep() == ((RPromise) nameObjCached).getRep();
  }
}
public class ReadUserKeywordsHashNode extends RubyNode {

  private final int minArgumentCount;

  @Child private DoesRespondDispatchHeadNode respondToToHashNode;
  @Child private CallDispatchHeadNode callToHashNode;

  private final ConditionProfile notEnoughArgumentsProfile = ConditionProfile.createBinaryProfile();
  private final ConditionProfile lastArgumentIsHashProfile = ConditionProfile.createBinaryProfile();
  private final ConditionProfile respondsToToHashProfile = ConditionProfile.createBinaryProfile();
  private final ConditionProfile convertedIsHashProfile = ConditionProfile.createBinaryProfile();

  public ReadUserKeywordsHashNode(int minArgumentCount) {
    this.minArgumentCount = minArgumentCount;
  }

  @Override
  public Object execute(VirtualFrame frame) {
    final int argumentCount = RubyArguments.getArgumentsCount(frame);

    if (notEnoughArgumentsProfile.profile(argumentCount <= minArgumentCount)) {
      return null;
    }

    final Object lastArgument = RubyArguments.getArgument(frame, argumentCount - 1);

    if (lastArgumentIsHashProfile.profile(RubyGuards.isRubyHash(lastArgument))) {
      return lastArgument;
    }

    return tryConvertToHash(frame, argumentCount, lastArgument);
  }

  private Object tryConvertToHash(
      VirtualFrame frame, final int argumentCount, final Object lastArgument) {
    if (respondsToToHashProfile.profile(respondToToHash(frame, lastArgument))) {
      final Object converted = callToHash(frame, lastArgument);

      if (convertedIsHashProfile.profile(RubyGuards.isRubyHash(converted))) {
        RubyArguments.setArgument(frame, argumentCount - 1, converted);
        return converted;
      }
    }

    return null;
  }

  private boolean respondToToHash(VirtualFrame frame, final Object lastArgument) {
    if (respondToToHashNode == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      respondToToHashNode = insert(new DoesRespondDispatchHeadNode(getContext(), false));
    }
    return respondToToHashNode.doesRespondTo(frame, "to_hash", lastArgument);
  }

  private Object callToHash(VirtualFrame frame, final Object lastArgument) {
    if (callToHashNode == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      callToHashNode = insert(CallDispatchHeadNode.createMethodCall());
    }
    return callToHashNode.call(frame, lastArgument, "to_hash");
  }
}