예제 #1
0
  @Override
  public Object execute(VirtualFrame frame) {
    if (optimizedProfile.profile(RubyArguments.isKwOptimized(frame.getArguments()))) {
      Object kwarg =
          argumentValueProfile.profile(
              RubyArguments.getOptimizedKeywordArgument(frame.getArguments(), kwIndex));

      if (defaultProfile.profile(
          kwarg instanceof OptionalKeywordArgMissingNode.OptionalKeywordArgMissing)) {
        return defaultValue.execute(frame);
      } else {
        return kwarg;
      }
    } else {
      final RubyHash hash = RubyArguments.getUserKeywordsHash(frame.getArguments(), minimum);

      if (defaultProfile.profile(hash == null)) {
        return defaultValue.execute(frame);
      }

      Object value = lookupKeywordInHash(hash);

      if (defaultProfile.profile(value == null)) {
        return defaultValue.execute(frame);
      }

      return value;
    }
  }
 @ExplodeLoop
 private void initFrame(VirtualFrame frame, Page page) {
   for (FrameMapping frameMapping : mapping) {
     frame.setObject(frameMapping.getFrameSlot(), getColumnSlow(page, frameMapping));
   }
   frame.setDouble(reduceNode.getSlot(), 0.0);
 }
예제 #3
0
  @Override
  public Object execute(VirtualFrame frame) {
    final DynamicObject result;

    try {
      result = method.executeDynamicObject(frame);
    } catch (DoNotTaint e) {
      return e.getResult();
    } catch (UnexpectedResultException e) {
      throw new UnsupportedOperationException(e);
    }

    if (result != nil()) {
      if (taintFromSelf) {
        maybeTaint((DynamicObject) RubyArguments.getSelf(frame.getArguments()), result);
      }

      // It's possible the taintFromParameter value was misconfigured by the user, but the far more
      // likely
      // scenario is that the argument at that position is a NotProvided argument, which doesn't
      // take up
      // a space in the frame.
      if (taintFromParameter < RubyArguments.getArgumentsCount(frame.getArguments())) {
        final Object argument = RubyArguments.getArgument(frame.getArguments(), taintFromParameter);

        if (argument instanceof DynamicObject) {
          final DynamicObject taintSource = (DynamicObject) argument;
          maybeTaint(taintSource, result);
        }
      }
    }

    return result;
  }
예제 #4
0
 @Override
 public Object execute(VirtualFrame frame) {
   final int count = RubyArguments.getArgumentsCount(frame.getArguments());
   final int effectiveIndex = count + negativeIndex;
   assert effectiveIndex < count;
   return RubyArguments.getArgument(frame.getArguments(), effectiveIndex);
 }
 @Override
 public Object execute(VirtualFrame frame) {
   if (RubyArguments.getUserArgumentsCount(frame.getArguments()) < minimum) {
     defaultValueProfile.enter();
     return defaultValue.execute(frame);
   } else {
     return RubyArguments.getUserArgument(frame.getArguments(), index);
   }
 }
 @Override
 public Object execute(VirtualFrame frame) {
   final RubyBasicObject binding =
       BindingNodes.createRubyBinding(
           getContext().getCoreLibrary().getBindingClass(),
           RubyArguments.getSelf(frame.getArguments()),
           frame.materialize());
   getContext().getCoreLibrary().getObjectClass().setConstant(this, "TOPLEVEL_BINDING", binding);
   return nil();
 }
예제 #7
0
 @Override
 public Object execute(VirtualFrame frame) {
   return ProcNodes.createRubyProc(
       getContext().getCoreLibrary().getProcClass(),
       type,
       sharedMethodInfo,
       callTargetForBlocks,
       callTargetForProcs,
       callTargetForLambdas,
       frame.materialize(),
       RubyArguments.getMethod(frame.getArguments()),
       RubyArguments.getSelf(frame.getArguments()),
       RubyArguments.getBlock(frame.getArguments()));
 }
예제 #8
0
  @Override
  public Object execute(VirtualFrame frame) {
    if (RubyArguments.isKwOptimized(frame.getArguments())) {
      Object restHash = RubyArguments.getOptimizedKeywordArgument(frame.getArguments(), kwIndex);

      if (restHash instanceof MarkerNode.Marker) {
        // no rest keyword args hash passed
        return HashLiteralNode.create(getContext(), null, new RubyNode[0]).execute(frame);
      } else {
        return restHash;
      }
    } else {
      return lookupRestKeywordArgumentHash(frame);
    }
  }
예제 #9
0
  @Override
  public void enter(Node node, VirtualFrame frame) {
    try {
      traceAssumption.check();
    } catch (InvalidAssumptionException e) {

      traceAssumption = context.getTraceManager().getTraceAssumption();
      traceFunc = context.getTraceManager().getTraceFunc();

      if (traceFunc != null) {
        callNode = insert(Truffle.getRuntime().createDirectCallNode(traceFunc.getCallTarget()));
      } else {
        callNode = null;
      }
    }

    if (traceFunc != null) {
      if (!context.getTraceManager().isInTraceFunc()) {
        context.getTraceManager().setInTraceFunc(true);

        final Object[] args =
            new Object[] {
              event,
              file,
              line,
              NilPlaceholder.INSTANCE,
              new RubyBinding(
                  context.getCoreLibrary().getBindingClass(),
                  RubyArguments.getSelf(frame.getArguments()),
                  frame.materialize()),
              NilPlaceholder.INSTANCE
            };

        try {
          callNode.call(
              frame,
              RubyArguments.pack(
                  traceFunc,
                  traceFunc.getDeclarationFrame(),
                  traceFunc.getSelfCapturedInScope(),
                  traceFunc.getBlockCapturedInScope(),
                  args));
        } finally {
          context.getTraceManager().setInTraceFunc(false);
        }
      }
    }
  }
예제 #10
0
  private Object lookupRestKeywordArgumentHash(VirtualFrame frame) {
    CompilerDirectives.transferToInterpreter();

    final DynamicObject hash = RubyArguments.getUserKeywordsHash(frame.getArguments(), minimum);

    if (hash == null) {
      return Layouts.HASH.createHash(
          getContext().getCoreLibrary().getHashFactory(), null, null, null, 0, null, null, false);
    }

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

    outer:
    for (Map.Entry<Object, Object> keyValue : HashOperations.iterableKeyValues(hash)) {
      for (String excludedKeyword : excludedKeywords) {
        if (excludedKeyword.equals(keyValue.getKey().toString())) {
          continue outer;
        }
      }

      entries.add(keyValue);
    }

    return BucketsStrategy.create(getContext(), entries, Layouts.HASH.getCompareByIdentity(hash));
  }
예제 #11
0
 @Override
 public Object isDefined(VirtualFrame frame) {
   if (RubyArguments.getBlock(frame.getArguments()) == null) {
     return nil();
   } else {
     return createString("yield");
   }
 }
예제 #12
0
  @ExplodeLoop
  @Override
  public final Object execute(VirtualFrame frame) {
    final Object self = RubyArguments.getSelf(frame.getArguments());

    // Execute the arguments

    final Object[] argumentsObjects = new Object[arguments.length];

    CompilerAsserts.compilationConstant(arguments.length);
    for (int i = 0; i < arguments.length; i++) {
      argumentsObjects[i] = arguments[i].execute(frame);
    }

    // Execute the block

    RubyProc blockObject;

    if (block != null) {
      final Object blockTempObject = block.execute(frame);

      if (blockTempObject instanceof RubyNilClass) {
        blockObject = null;
      } else {
        blockObject = (RubyProc) blockTempObject;
      }
    } else {
      blockObject = null;
    }

    // Check we have a method and the module is unmodified

    if (!guard(frame, self)) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      lookup(frame);
    }

    // Call the method

    if (isSplatted) {
      // TODO(CS): need something better to splat the arguments array
      notDesignedForCompilation();
      final RubyArray argumentsArray = (RubyArray) argumentsObjects[0];
      return callNode.call(
          frame,
          RubyArguments.pack(
              superMethod,
              superMethod.getDeclarationFrame(),
              self,
              blockObject,
              argumentsArray.slowToArray()));
    } else {
      return callNode.call(
          frame,
          RubyArguments.pack(
              superMethod, superMethod.getDeclarationFrame(), self, blockObject, argumentsObjects));
    }
  }
예제 #13
0
 @Specialization
 public Object match(VirtualFrame frame, RubyString string, RubyString regexpString) {
   final RubyRegexp regexp =
       new RubyRegexp(
           getContext().getCoreLibrary().getRegexpClass(),
           regexpString.toString(),
           Option.DEFAULT);
   return regexp.match(frame.getCaller().unpack(), string.toString());
 }
예제 #14
0
  private boolean moduleFunctionFlag(VirtualFrame frame) {
    final FrameSlot moduleFunctionFlagSlot =
        frame.getFrameDescriptor().findFrameSlot(RubyModule.MODULE_FUNCTION_FLAG_FRAME_SLOT_ID);

    if (moduleFunctionFlagSlot == null) {
      return false;
    } else {
      Object moduleFunctionObject;

      try {
        moduleFunctionObject = frame.getObject(moduleFunctionFlagSlot);
      } catch (FrameSlotTypeException e) {
        throw new RuntimeException(e);
      }

      return (moduleFunctionObject instanceof Boolean) && (boolean) moduleFunctionObject;
    }
  }
예제 #15
0
  @Override
  public Object execute(VirtualFrame frame) {
    if (index >= RubyArguments.getUserArgumentsCount(frame.getArguments())) {
      outOfRangeProfile.enter();

      switch (missingArgumentBehaviour) {
        case RUNTIME_ERROR:
          break;

        case UNDEFINED:
          return UndefinedPlaceholder.INSTANCE;

        case NIL:
          return nil();
      }
    }

    return argumentValueProfile.profile(RubyArguments.getUserArgument(frame.getArguments(), index));
  }
  @Override
  public Object execute(VirtualFrame frame) {
    Page page = PageArguments.get(frame);
    initFrame(frame, page);

    for (int row = 0; row < page.getRowCount(); row++) {
      frame.setInt(rowSlot, row);
      try {
        if (filterNode.executeBoolean(frame)) {
          reduceNode.execute(frame);
        }
      } catch (UnexpectedResultException e) {
        throw new IllegalStateException("not implemented yet: rewrite in reduce node");
      }
    }

    try {
      return frame.getDouble(reduceNode.getSlot());
    } catch (FrameSlotTypeException e) {
      throw new IllegalStateException("should not reach here");
    }
  }
예제 #17
0
파일: HashNodes.java 프로젝트: phs/jruby
    @Specialization
    public Object construct(VirtualFrame frame, RubyHash hash, Object index) {
      final Object value = hash.get(index);

      if (value == null) {
        if (hash.defaultBlock == null) {
          return NilPlaceholder.INSTANCE;
        } else {
          return hash.defaultBlock.call(frame.pack(), hash, index);
        }
      } else {
        return value;
      }
    }
예제 #18
0
  @Override
  public boolean executeBoolean(VirtualFrame frame) {
    // TODO(CS): express this using normal nodes?

    // If we don't accept any arguments, there's never any need to destructure
    // TODO(CS): is this guaranteed by the translator anyway?

    if (!arity.allowsMore() && arity.getRequired() == 0 && arity.getOptional() == 0) {
      return false;
    }

    // If we only accept one argument, there's never any need to destructure

    if (!arity.allowsMore() && arity.getRequired() == 1 && arity.getOptional() == 0) {
      return false;
    }

    // If the caller supplied no arguments, or more than one argument, there's no need to
    // destructure this time

    if (RubyArguments.getUserArgumentsCount(frame.getArguments()) != 1) {
      return false;
    }

    // If the single argument is a RubyArray, destructure
    // TODO(CS): can we not just reply on the respondToCheck? Should experiment.

    if (RubyGuards.isRubyArray(RubyArguments.getUserArgument(frame.getArguments(), 0))) {
      return true;
    }

    // If the single argument responds to #to_ary, then destructure

    checkRespondProfile.enter();

    return respondToCheck.executeBoolean(frame);
  }
예제 #19
0
  @Override
  public Object execute(VirtualFrame frame) {
    final RubyClass arrayClass = getContext().getCoreLibrary().getArrayClass();

    int count = RubyArguments.getUserArgumentsCount(frame.getArguments());

    int endIndex = count + negativeEndIndex;

    if (keywordArguments) {
      final Object lastArgument =
          RubyArguments.getUserArgument(
              frame.getArguments(), RubyArguments.getUserArgumentsCount(frame.getArguments()) - 1);

      if (lastArgument instanceof RubyHash) {
        endIndex -= 1;
      }
    }

    final int length = endIndex - startIndex;

    if (startIndex == 0) {
      final Object[] arguments = RubyArguments.extractUserArguments(frame.getArguments());
      return new RubyArray(arrayClass, arguments, length);
    } else {
      if (startIndex >= endIndex) {
        noArgumentsLeftProfile.enter();
        return new RubyArray(arrayClass);
      } else {
        subsetOfArgumentsProfile.enter();
        final Object[] arguments = RubyArguments.extractUserArguments(frame.getArguments());
        // TODO(CS): risk here of widening types too much - always going to be Object[] - does seem
        // to be something that does happen
        return new RubyArray(
            arrayClass, ArrayUtils.extractRange(arguments, startIndex, endIndex), length);
      }
    }
  }
예제 #20
0
  private boolean assertArgumentsShouldBeVisible(VirtualFrame frame) {
    final Object self = RubyArguments.getSelf(frame.getArguments());

    assert shouldObjectBeVisible(self)
        : "self="
            + (self == null ? "null" : self.getClass())
            + "@"
            + getEncapsulatingSourceSection().getShortDescription();

    final Object[] arguments = RubyArguments.extractUserArguments(frame.getArguments());

    for (int n = 0; n < arguments.length; n++) {
      final Object argument = arguments[n];
      assert shouldObjectBeVisible(argument)
          : "arg["
              + n
              + "]="
              + (argument == null ? "null" : argument.getClass() + "=" + toString(argument))
              + "@"
              + getEncapsulatingSourceSection().getShortDescription();
    }

    return true;
  }
예제 #21
0
  @Override
  public boolean doesRespondTo(VirtualFrame frame, RubyBasicObject receiverObject) {
    // TODO(CS): copy-and-paste of the above - needs to be factored out

    MethodCacheEntry entry = lookupInCache(receiverObject.getLookupNode());

    if (entry == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();

      final RubyBasicObject boxedCallingSelf =
          getContext().getCoreLibrary().box(RubyArguments.getSelf(frame.getArguments()));

      try {
        entry = new MethodCacheEntry(lookup(boxedCallingSelf, receiverObject, name), false);
      } catch (UseMethodMissingException e) {
        try {
          entry =
              new MethodCacheEntry(
                  lookup(boxedCallingSelf, receiverObject, "method_missing"), true);
        } catch (UseMethodMissingException e2) {
          throw new RaiseException(
              getContext()
                  .getCoreLibrary()
                  .runtimeError(receiverObject.toString() + " didn't have a #method_missing"));
        }
      }

      if (entry.isMethodMissing()) {
        hasAnyMethodsMissing = true;
      }

      cache.put(receiverObject.getLookupNode(), entry);

      if (cache.size() > RubyContext.GENERAL_DISPATCH_SIZE_WARNING_THRESHOLD) {
        getContext()
            .getRuntime()
            .getWarnings()
            .warn(
                IRubyWarnings.ID.TRUFFLE,
                getEncapsulatingSourceSection().getSource().getName(),
                getEncapsulatingSourceSection().getStartLine(),
                "general call node cache has " + cache.size() + " entries");
      }
    }

    return !entry.isMethodMissing();
  }
예제 #22
0
  @Override
  public Object execute(VirtualFrame frame) {
    final RubyArguments rubyArguments = frame.getArguments(RubyArguments.class);

    final Object[] arguments = rubyArguments.getArguments();

    final RubyClass arrayClass = getContext().getCoreLibrary().getArrayClass();

    if (arguments.length <= index) {
      return new RubyArray(arrayClass);
    } else if (index == 0) {
      return new RubyArray(arrayClass, new ObjectArrayStore(arguments));
    } else {
      return new RubyArray(
          arrayClass, new ObjectArrayStore(Arrays.copyOfRange(arguments, index, arguments.length)));
    }
  }
예제 #23
0
  @Override
  public Object execute(VirtualFrame frame) {
    CompilerDirectives.bailout("blocks with kwargs are not optimized yet");

    final Object array = readArrayNode.executeRead(frame);

    final Object remainingArray =
        ruby(
            frame,
            "Truffle::Primitive.load_arguments_from_array_kw_helper(array, kwrest_name, binding)",
            "array",
            array,
            "kwrest_name",
            kwrestName,
            "binding",
            Layouts.BINDING.createBinding(
                getContext().getCoreLibrary().getBindingFactory(), frame.materialize()));

    writeArrayNode.executeWrite(frame, remainingArray);

    return nil();
  }
예제 #24
0
  @ExplodeLoop
  @Override
  public final Object execute(VirtualFrame frame) {
    Object[] argumentsObjects = new Object[arguments.length];

    for (int i = 0; i < arguments.length; i++) {
      argumentsObjects[i] = arguments[i].execute(frame);
    }

    final RubyProc block = RubyArguments.getBlock(frame.getArguments());

    if (block == null) {
      CompilerDirectives.transferToInterpreter();
      throw new RaiseException(getContext().getCoreLibrary().noBlockToYieldTo(this));
    }

    if (unsplat) {
      argumentsObjects = unsplat(argumentsObjects);
    }

    return dispatch.dispatch(frame, block, argumentsObjects);
  }
예제 #25
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);
   }
 }
  public InternalMethod executeMethod(VirtualFrame frame) {
    final DynamicObject dummyModule = getContext().getCoreLibrary().getObjectClass();
    final Visibility dummyVisibility = Visibility.PUBLIC;

    final DynamicObject capturedBlock;

    if (captureBlock) {
      capturedBlock = RubyArguments.getBlock(frame.getArguments());
    } else {
      capturedBlock = null;
    }

    return new InternalMethod(
        sharedMethodInfo,
        name,
        dummyModule,
        dummyVisibility,
        false,
        null,
        callTarget,
        capturedBlock,
        null);
  }
예제 #27
0
 @Specialization
 public Object match(VirtualFrame frame, RubyString string, RubyRegexp regexp) {
   return regexp.match(frame.getCaller().unpack(), string.toString());
 }
예제 #28
0
 protected InternalMethod getCurrentMethod(VirtualFrame frame) {
   return RubyArguments.getMethod(frame.getArguments());
 }
예제 #29
0
  @Override
  public Object dispatch(
      VirtualFrame frame,
      RubyBasicObject receiverObject,
      RubyProc blockObject,
      Object[] argumentsObjects) {
    MethodCacheEntry entry = lookupInCache(receiverObject.getLookupNode());

    if (entry == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();

      final RubyBasicObject boxedCallingSelf =
          getContext().getCoreLibrary().box(RubyArguments.getSelf(frame.getArguments()));

      try {
        entry = new MethodCacheEntry(lookup(boxedCallingSelf, receiverObject, name), false);
      } catch (UseMethodMissingException e) {
        try {
          entry =
              new MethodCacheEntry(
                  lookup(boxedCallingSelf, receiverObject, "method_missing"), true);
        } catch (UseMethodMissingException e2) {
          throw new RaiseException(
              getContext()
                  .getCoreLibrary()
                  .runtimeError(receiverObject.toString() + " didn't have a #method_missing"));
        }
      }

      if (entry.isMethodMissing()) {
        hasAnyMethodsMissing = true;
      }

      cache.put(receiverObject.getLookupNode(), entry);

      if (cache.size() > RubyContext.GENERAL_DISPATCH_SIZE_WARNING_THRESHOLD) {
        getContext()
            .getRuntime()
            .getWarnings()
            .warn(
                IRubyWarnings.ID.TRUFFLE,
                getEncapsulatingSourceSection().getSource().getName(),
                getEncapsulatingSourceSection().getStartLine(),
                "general call node cache has " + cache.size() + " entries");
      }
    }

    final Object[] argumentsToUse;

    if (hasAnyMethodsMissing && entry.isMethodMissing()) {
      final Object[] modifiedArgumentsObjects = new Object[1 + argumentsObjects.length];
      modifiedArgumentsObjects[0] = getContext().newSymbol(name);
      System.arraycopy(argumentsObjects, 0, modifiedArgumentsObjects, 1, argumentsObjects.length);
      argumentsToUse = modifiedArgumentsObjects;
    } else {
      argumentsToUse = argumentsObjects;
    }

    return callNode.call(
        frame,
        entry.getMethod().getCallTarget(),
        RubyArguments.pack(
            entry.getMethod().getDeclarationFrame(), receiverObject, blockObject, argumentsToUse));
  }
예제 #30
0
  @Override
  public Object execute(VirtualFrame frame) {
    frame.setObject(FormatFrameDescriptor.SOURCE_SLOT, frame.getArguments()[0]);
    frame.setInt(FormatFrameDescriptor.SOURCE_LENGTH_SLOT, (int) frame.getArguments()[1]);
    frame.setInt(FormatFrameDescriptor.SOURCE_POSITION_SLOT, 0);
    frame.setObject(FormatFrameDescriptor.OUTPUT_SLOT, new byte[expectedLength]);
    frame.setInt(FormatFrameDescriptor.OUTPUT_POSITION_SLOT, 0);
    frame.setInt(FormatFrameDescriptor.STRING_LENGTH_SLOT, 0);
    frame.setInt(FormatFrameDescriptor.STRING_CODE_RANGE_SLOT, CodeRange.CR_UNKNOWN.toInt());
    frame.setBoolean(FormatFrameDescriptor.TAINT_SLOT, false);

    child.execute(frame);

    final int outputLength;

    try {
      outputLength = frame.getInt(FormatFrameDescriptor.OUTPUT_POSITION_SLOT);
    } catch (FrameSlotTypeException e) {
      throw new IllegalStateException(e);
    }

    if (outputLength > expectedLength) {
      CompilerDirectives.transferToInterpreterAndInvalidate();

      /*
       * Don't over-compensate and allocate 2x or something like that for next time, as we have to copy the
       * byte[] at the end if it's too big to make it fit its contents. In the ideal case the byte[] is exactly
       * the right size. If we have to keep making it bigger in the slow-path, we can live with that.
       */

      expectedLength = outputLength;
    }

    final byte[] output;

    try {
      output = (byte[]) frame.getObject(FormatFrameDescriptor.OUTPUT_SLOT);
    } catch (FrameSlotTypeException e) {
      throw new IllegalStateException(e);
    }

    final boolean taint;

    try {
      taint = frame.getBoolean(FormatFrameDescriptor.TAINT_SLOT);
    } catch (FrameSlotTypeException e) {
      throw new IllegalStateException(e);
    }

    final int stringLength;

    if (encoding == FormatEncoding.UTF_8) {
      try {
        stringLength = frame.getInt(FormatFrameDescriptor.STRING_LENGTH_SLOT);
      } catch (FrameSlotTypeException e) {
        throw new IllegalStateException(e);
      }
    } else {
      stringLength = outputLength;
    }

    final CodeRange stringCodeRange;

    try {
      stringCodeRange =
          CodeRange.fromInt(frame.getInt(FormatFrameDescriptor.STRING_CODE_RANGE_SLOT));
    } catch (FrameSlotTypeException e) {
      throw new IllegalStateException(e);
    }

    return new BytesResult(output, outputLength, stringLength, stringCodeRange, taint, encoding);
  }