11/*
2- * Copyright (c) 2018, 2019 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2018, 2020 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2323package com .oracle .truffle .r .nodes .function ;
2424
2525import com .oracle .truffle .api .CompilerDirectives ;
26+ import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
2627import com .oracle .truffle .api .frame .FrameDescriptor ;
2728import com .oracle .truffle .api .frame .FrameSlot ;
2829import com .oracle .truffle .api .frame .FrameSlotKind ;
2930import com .oracle .truffle .api .frame .VirtualFrame ;
3031import com .oracle .truffle .api .nodes .Node ;
3132import com .oracle .truffle .api .profiles .BranchProfile ;
33+ import com .oracle .truffle .api .profiles .ConditionProfile ;
3234import com .oracle .truffle .api .source .SourceSection ;
3335import com .oracle .truffle .r .runtime .RArguments ;
3436import com .oracle .truffle .r .runtime .RArguments .DispatchArgs ;
3537import com .oracle .truffle .r .runtime .RArguments .S3Args ;
3638import com .oracle .truffle .r .runtime .RArguments .S4Args ;
39+ import com .oracle .truffle .r .runtime .RInternalError ;
3740import com .oracle .truffle .r .runtime .RRuntime ;
41+ import com .oracle .truffle .r .runtime .ReturnException ;
3842import com .oracle .truffle .r .runtime .RootBodyNode ;
3943import com .oracle .truffle .r .runtime .env .frame .FrameSlotChangeMonitor ;
4044import com .oracle .truffle .r .runtime .nodes .RNode ;
@@ -46,16 +50,34 @@ public final class FunctionBodyNode extends Node implements RootBodyNode {
4650 @ Child private SetupS3ArgsNode setupS3Args ;
4751 @ Child private SetupS4ArgsNode setupS4Args ;
4852
53+ // Profiling for catching ReturnException
54+ private final BranchProfile returnExceptionProfile = BranchProfile .create ();
55+ @ CompilationFinal private ConditionProfile returnTopLevelProfile ;
56+
4957 public FunctionBodyNode (SaveArgumentsNode saveArguments , RNode body ) {
5058 this .body = body ;
5159 this .saveArguments = saveArguments ;
5260 }
5361
5462 @ Override
5563 public Object visibleExecute (VirtualFrame frame ) {
56- setupDispatchSlots (frame );
57- saveArguments .execute (frame );
58- return body .visibleExecute (frame );
64+ try {
65+ setupDispatchSlots (frame );
66+ saveArguments .execute (frame );
67+ return body .visibleExecute (frame );
68+ } catch (ReturnException ex ) {
69+ returnExceptionProfile .enter ();
70+ if (profileReturnToTopLevel (ex .getTarget () == RArguments .getCall (frame ))) {
71+ Object result = ex .getResult ();
72+ if (CompilerDirectives .inInterpreter () && result == null ) {
73+ throw RInternalError .shouldNotReachHere ("invalid null from ReturnException.getResult() of " + this );
74+ }
75+ return result ;
76+ } else {
77+ // re-thrown until it reaches its target
78+ throw ex ;
79+ }
80+ }
5981 }
6082
6183 @ Override
@@ -68,6 +90,14 @@ public SourceSection getSourceSection() {
6890 return body .getSourceSection ();
6991 }
7092
93+ public boolean profileReturnToTopLevel (boolean condition ) {
94+ if (returnTopLevelProfile == null ) {
95+ CompilerDirectives .transferToInterpreterAndInvalidate ();
96+ returnTopLevelProfile = ConditionProfile .createBinaryProfile ();
97+ }
98+ return returnTopLevelProfile .profile (condition );
99+ }
100+
71101 private void setupDispatchSlots (VirtualFrame frame ) {
72102 DispatchArgs dispatchArgs = RArguments .getDispatchArgs (frame );
73103 if (dispatchArgs == null ) {
0 commit comments