11/*
2- * Copyright (c) 2013, 2018 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2013, 2019 , 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
3030
3131import java .util .Arrays ;
3232
33- import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
3433import com .oracle .truffle .api .dsl .Cached ;
3534import com .oracle .truffle .api .dsl .Specialization ;
35+ import com .oracle .truffle .api .nodes .ControlFlowException ;
3636import com .oracle .truffle .api .profiles .BranchProfile ;
3737import com .oracle .truffle .api .profiles .ConditionProfile ;
3838import com .oracle .truffle .api .profiles .ValueProfile ;
4242import com .oracle .truffle .r .nodes .builtin .CastBuilder .Predef ;
4343import com .oracle .truffle .r .nodes .builtin .RBuiltinNode ;
4444import com .oracle .truffle .r .runtime .RError ;
45+ import com .oracle .truffle .r .runtime .RError .Message ;
4546import com .oracle .truffle .r .runtime .RRuntime ;
4647import com .oracle .truffle .r .runtime .RType ;
4748import com .oracle .truffle .r .runtime .builtins .RBuiltin ;
@@ -65,6 +66,7 @@ public abstract static class Log extends RBuiltinNode.Arg2 {
6566
6667 private final NAProfile naX = NAProfile .create ();
6768 private final BranchProfile nanProfile = BranchProfile .create ();
69+ private final BranchProfile warningProfile = BranchProfile .create ();
6870
6971 @ Override
7072 public Object [] getDefaultParameterValues () {
@@ -206,13 +208,22 @@ private RDoubleVector logInternal(RAbstractDoubleVector vector, double base, Cop
206208 Arrays .fill (resultVector , 0 , resultVector .length , Double .NaN );
207209 } else {
208210 xNACheck .enable (vector );
209- RBaseNode [] warningCtx = new RBaseNode [ 1 ] ;
211+ ShowWarningException showWarning = null ;
210212 for (int i = 0 ; i < vector .getLength (); i ++) {
211213 double value = vector .getDataAt (i );
212- resultVector [i ] = xNACheck .check (value ) ? RRuntime .DOUBLE_NA : logb (value , base , warningCtx );
214+ if (xNACheck .check (value )) {
215+ resultVector [i ] = RRuntime .DOUBLE_NA ;
216+ } else {
217+ try {
218+ resultVector [i ] = logb (value , base );
219+ } catch (ShowWarningException ex ) {
220+ showWarning = ex ;
221+ resultVector [i ] = ex .result ;
222+ }
223+ }
213224 }
214- if (warningCtx [ 0 ] != null ) {
215- RError .warning (warningCtx [ 0 ], RError . Message . NAN_PRODUCED );
225+ if (showWarning != null ) {
226+ RError .warning (showWarning . context , showWarning . message );
216227 }
217228 }
218229 boolean complete = xNACheck .neverSeenNA () && baseNACheck .neverSeenNA ();
@@ -228,32 +239,50 @@ private double logb(double x, double base, NAProfile naBase) {
228239 nanProfile .enter ();
229240 return base ;
230241 }
231- RBaseNode [] warningCtx = new RBaseNode [1 ];
232- double ret = logb (x , base , warningCtx );
233- if (warningCtx [0 ] != null ) {
234- RError .warning (warningCtx [0 ], RError .Message .NAN_PRODUCED );
242+ try {
243+ return logb (x , base );
244+ } catch (ShowWarningException showWarn ) {
245+ RError .warning (showWarn .context , showWarn .message );
246+ return showWarn .result ;
235247 }
236- return ret ;
237248 }
238249
239- @ TruffleBoundary
240- private double logb (double x , double base , RBaseNode [] warningCtx ) {
250+ private double logb (double x , double base ) throws ShowWarningException {
241251 double logx = Math .log (x );
252+ RBaseNode warningCtx = null ;
242253 if (!Double .isNaN (x ) && Double .isNaN (logx )) {
243- warningCtx [0 ] = this ;
254+ warningProfile .enter ();
255+ warningCtx = this ;
244256 }
257+ double result ;
245258 if (base == Math .E ) {
246- return logx ;
259+ result = logx ;
260+ } else {
261+ result = logx / Math .log (base );
262+ if (warningCtx == null && Double .isNaN (result )) {
263+ warningProfile .enter ();
264+ warningCtx = RError .SHOW_CALLER ;
265+ }
247266 }
248-
249- double result = logx / Math .log (base );
250- if (warningCtx [0 ] == null && Double .isNaN (result )) {
251- warningCtx [0 ] = RError .SHOW_CALLER ;
267+ if (warningCtx != null ) {
268+ throw new ShowWarningException (result , warningCtx , RError .Message .NAN_PRODUCED );
252269 }
253-
254270 return result ;
255271 }
256272
273+ private static final class ShowWarningException extends ControlFlowException {
274+ private static final long serialVersionUID = -5922014313815330744L ;
275+ final RBaseNode context ;
276+ final RError .Message message ;
277+ final double result ;
278+
279+ ShowWarningException (double result , RBaseNode context , Message message ) {
280+ this .result = result ;
281+ this .context = context ;
282+ this .message = message ;
283+ }
284+ }
285+
257286 private RComplexVector logInternal (RAbstractComplexVector vector , RComplex base , BinaryMapArithmeticFunctionNode divNode ,
258287 InitDimsNamesDimNamesNode initDimsNamesDimNames , CopyOfRegAttributesNode copyAttrsNode , NACheck xNACheck , NACheck baseNACheck ) {
259288 baseNACheck .enable (base );
0 commit comments