@Override public Object execute(VirtualFrame frame) { while (true) { getContext().getSafepointManager().poll(); Object result; try { result = tryPart.execute(frame); } catch (ControlFlowException exception) { controlFlowProfile.enter(); throw exception; } catch (RaiseException exception) { raiseExceptionProfile.enter(); try { return handleException(frame, exception); } catch (RetryException e) { continue; } } finally { clearExceptionVariableNode.execute(frame); } elseProfile.enter(); elsePart.executeVoid(frame); return result; } }
@Specialization public Object step( VirtualFrame frame, RubyRange.IntegerFixnumRange range, int step, RubyProc block) { int count = 0; try { outer: for (int n = range.getBegin(); n < range.getExclusiveEnd(); n += step) { while (true) { if (CompilerDirectives.inInterpreter()) { count++; } try { yield(frame, block, n); continue outer; } catch (BreakException e) { breakProfile.enter(); return e.getResult(); } catch (NextException e) { nextProfile.enter(); continue outer; } catch (RedoException e) { redoProfile.enter(); } } } } finally { if (CompilerDirectives.inInterpreter()) { getRootNode().reportLoopCount(count); } } return range; }
@CompilerDirectives.SlowPath private RubyString formatSlow(RubyString format, Object[] args) { final RubyContext context = getContext(); if (args.length == 1 && args[0] instanceof RubyArray) { singleArrayProfile.enter(); return context.makeString( StringFormatter.format(format.toString(), ((RubyArray) args[0]).asList())); } else { multipleArgumentsProfile.enter(); return context.makeString(StringFormatter.format(format.toString(), Arrays.asList(args))); } }
@Override public Object execute(VirtualFrame frame) { if (CompilerDirectives.injectBranchProbability( getBranchProbability(), condition.executeBoolean(frame))) { if (CompilerDirectives.inInterpreter()) { thenCount++; } thenProfile.enter(); return thenBody.execute(frame); } else { if (CompilerDirectives.inInterpreter()) { elseCount++; } elseProfile.enter(); return elseBody.execute(frame); } }
@Specialization public Object leftShift(DynamicObject a, int b) { if (b >= 0) { return fixnumOrBignum(Layouts.BIGNUM.getValue(a).shiftRight(b)); } else { bLessThanZero.enter(); return fixnumOrBignum(Layouts.BIGNUM.getValue(a).shiftLeft(-b)); } }
@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) { try { assert assertArgumentsShouldBeVisible(frame); final Object result = child.execute(frame); assert shouldObjectBeVisible(result) : "result@" + getEncapsulatingSourceSection().getShortDescription(); return result; } catch (StackOverflowError error) { // TODO: we might want to do sth smarter here to avoid consuming frames when we are almost out // of it. CompilerDirectives.transferToInterpreter(); throw new RaiseException(translate(error)); } catch (TruffleFatalException | ThreadExitException exception) { throw exception; } catch (ControlFlowException exception) { controlProfile.enter(); throw exception; } catch (RaiseException exception) { rethrowProfile.enter(); throw exception; } catch (MainExitException exception) { CompilerDirectives.transferToInterpreter(); throw exception; } catch (ArithmeticException exception) { CompilerDirectives.transferToInterpreter(); throw new RaiseException(translate(exception)); } catch (UnsupportedSpecializationException exception) { CompilerDirectives.transferToInterpreter(); throw new RaiseException(translate(exception)); } catch (org.jruby.exceptions.RaiseException e) { CompilerDirectives.transferToInterpreter(); throw new RaiseException(getContext().toTruffle(e.getException(), this)); } catch (Throwable exception) { CompilerDirectives.transferToInterpreter(); throw new RaiseException(translate(exception)); } }
@Override public Object execute(VirtualFrame frame) { try { return body.execute(frame); } catch (BreakException e) { breakProfile.enter(); if (matchingBreakProfile.profile(e.getBreakID() == breakID)) { return e.getResult(); } else { throw e; } } }
@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); } } }
@Override public RubyBasicObject executeRubyBasicObject(VirtualFrame frame) { final Object object = child.execute(frame); RubyBasicObject boxedObject; if (object instanceof RubyBasicObject) { boxedObject = (RubyBasicObject) object; } else { boxBranch.enter(); boxedObject = getContext().getCoreLibrary().box(object); } return boxedObject; }
@ExplodeLoop @Specialization(guards = {"isPackedHash(hash)", "!isRubyString(key)"}) public Object setPackedArray( VirtualFrame frame, DynamicObject hash, Object key, Object value, boolean byIdentity) { assert HashNodes.verifyStore(hash); final int hashed = hashNode.hash(frame, key); final Object[] store = (Object[]) Layouts.HASH.getStore(hash); final int size = Layouts.HASH.getSize(hash); for (int n = 0; n < PackedArrayStrategy.MAX_ENTRIES; n++) { if (n < size) { if (hashed == PackedArrayStrategy.getHashed(store, n)) { final boolean equal; if (byIdentityProfile.profile(byIdentity)) { equal = equalNode.executeReferenceEqual(frame, key, PackedArrayStrategy.getKey(store, n)); } else { equal = eqlNode.callBoolean(frame, key, "eql?", null, PackedArrayStrategy.getKey(store, n)); } if (equal) { PackedArrayStrategy.setValue(store, n, value); assert HashNodes.verifyStore(hash); return value; } } } } extendProfile.enter(); if (strategyProfile.profile(size + 1 <= PackedArrayStrategy.MAX_ENTRIES)) { PackedArrayStrategy.setHashedKeyValue(store, size, hashed, key, value); Layouts.HASH.setSize(hash, size + 1); return value; } else { PackedArrayStrategy.promoteToBuckets(hash, store, size); BucketsStrategy.addNewEntry(hash, hashed, key, value); } assert HashNodes.verifyStore(hash); return value; }
@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) { while (true) { try { final Object result = tryPart.execute(frame); elsePart.executeVoid(frame); return result; } catch (ControlFlowException exception) { controlFlowProfile.enter(); throw exception; } catch (RuntimeException exception) { CompilerDirectives.transferToInterpreter(); try { return handleException(frame, exception); } catch (RetryException e) { continue; } } } }
@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); }