private static boolean checkInteropType(Object value, EventBinding.Source<?> binding) { if (value != null && value != UNWIND_ACTION_REENTER && !InstrumentationHandler.ACCESSOR.isTruffleObject(value)) { Class<?> clazz = value.getClass(); if (!(clazz == Byte.class || clazz == Short.class || clazz == Integer.class || clazz == Long.class || clazz == Float.class || clazz == Double.class || clazz == Character.class || clazz == Boolean.class || clazz == String.class)) { CompilerDirectives.transferToInterpreter(); ClassCastException ccex = new ClassCastException(clazz.getName() + " isn't allowed Truffle interop type!"); if (binding.isLanguageBinding()) { throw ccex; } else { exceptionEventForClientInstrument(binding, "onUnwind", ccex); return false; } } } return true; }
/** * Handles exceptions from non-language instrumentation code that must not be allowed to alter * guest language execution semantics. Normal response is to log and continue. */ @TruffleBoundary static void exceptionEventForClientInstrument(EventBinding.Source<?> b, String eventName, Throwable t) { assert !b.isLanguageBinding(); if (t instanceof ThreadDeath) { // Terminates guest language execution immediately throw (ThreadDeath) t; } // Exception is a failure in (non-language) instrumentation code; log and continue InstrumentClientInstrumenter instrumenter = (InstrumentClientInstrumenter) b.getInstrumenter(); Class<?> instrumentClass = instrumenter.getInstrumentClass(); String message = String.format("Event %s failed for instrument class %s and listener/factory %s.", // eventName, instrumentClass.getName(), b.getElement()); Exception exception = new Exception(message, t); PrintStream stream = new PrintStream(instrumenter.getEnv().err()); exception.printStackTrace(stream); }
private static boolean checkInteropType(Object value, EventBinding.Source<?> binding) { if (value != null && value != UNWIND_ACTION_REENTER && value != UNWIND_ACTION_IGNORED && !InstrumentationHandler.ACCESSOR.isTruffleObject(value)) { Class<?> clazz = value.getClass(); if (!(clazz == Byte.class || clazz == Short.class || clazz == Integer.class || clazz == Long.class || clazz == Float.class || clazz == Double.class || clazz == Character.class || clazz == Boolean.class || clazz == String.class)) { CompilerDirectives.transferToInterpreter(); ClassCastException ccex = new ClassCastException(clazz.getName() + " isn't allowed Truffle interop type!"); if (binding.isLanguageBinding()) { throw ccex; } else { exceptionEventForClientInstrument(binding, "onUnwind", ccex); return false; } } } return true; }
setSeenException(); if (binding.isLanguageBinding()) { throw t; } else {
setSeenException(); if (binding.isLanguageBinding()) { throw t; } else {
setSeenException(); if (binding.isLanguageBinding()) { throw t; } else {
final Object onUnwind(EventContext context, VirtualFrame frame, UnwindException unwind) { Object ret = null; if (containsBinding(unwind)) { try { ret = innerOnUnwind(context, frame, getInfo(unwind)); } catch (Throwable t) { if (!isSeenException()) { CompilerDirectives.transferToInterpreterAndInvalidate(); setSeenException(); } if (binding.isLanguageBinding()) { throw t; } else { CompilerDirectives.transferToInterpreter(); exceptionEventForClientInstrument(binding, "onUnwind", t); } } if (ret != null) { assert checkInteropType(ret, binding); reset(unwind); } } else { ret = UNWIND_ACTION_IGNORED; } if (next != null) { Object nextRet = next.onUnwind(context, frame, unwind); ret = mergePostUnwindReturns(ret, nextRet); } return ret; }
final Object onUnwind(EventContext context, VirtualFrame frame, UnwindException unwind) { Object ret = null; if (containsBinding(unwind)) { try { ret = innerOnUnwind(context, frame, getInfo(unwind)); } catch (Throwable t) { if (!isSeenException()) { CompilerDirectives.transferToInterpreterAndInvalidate(); setSeenException(); } if (binding.isLanguageBinding()) { throw t; } else { CompilerDirectives.transferToInterpreter(); exceptionEventForClientInstrument(binding, "onUnwind", t); } } if (ret != null) { assert checkInteropType(ret, binding); reset(unwind); } } else { ret = UNWIND_ACTION_IGNORED; } if (next != null) { Object nextRet = next.onUnwind(context, frame, unwind); ret = mergePostUnwindReturns(ret, nextRet); } return ret; }
/** * Handles exceptions from non-language instrumentation code that must not be allowed to alter * guest language execution semantics. Normal response is to log and continue. */ @TruffleBoundary static void exceptionEventForClientInstrument(EventBinding.Source<?> b, String eventName, Throwable t) { assert !b.isLanguageBinding(); if (t instanceof ThreadDeath) { // Terminates guest language execution immediately throw (ThreadDeath) t; } final Object currentVm = AccessorInstrumentHandler.engineAccess().getCurrentVM(); if (b.getInstrumenter() instanceof EngineInstrumenter || (currentVm != null && AccessorInstrumentHandler.engineAccess().isInstrumentExceptionsAreThrown(currentVm))) { throw sthrow(RuntimeException.class, t); } // Exception is a failure in (non-language) instrumentation code; log and continue InstrumentClientInstrumenter instrumenter = (InstrumentClientInstrumenter) b.getInstrumenter(); Class<?> instrumentClass = instrumenter.getInstrumentClass(); String message = String.format("Event %s failed for instrument class %s and listener/factory %s.", // eventName, instrumentClass.getName(), b.getElement()); Exception exception = new Exception(message, t); PrintStream stream = new PrintStream(instrumenter.getEnv().err()); exception.printStackTrace(stream); }
private ExecutionEventNode createEventNode(EventBinding.Source<?> binding, Object element) { ExecutionEventNode eventNode; try { eventNode = ((ExecutionEventNodeFactory) element).create(context); if (eventNode != null && eventNode.getParent() != null) { throw new IllegalStateException(String.format("Returned EventNode %s was already adopted by another AST.", eventNode)); } } catch (Throwable t) { if (binding.isLanguageBinding()) { /* Language bindings can just throw exceptions directly into the AST. */ throw t; } else { /* * Client Instruments are not allowed to disrupt program execution by throwing * exceptions into the AST. */ exceptionEventForClientInstrument(binding, "ProbeNodeFactory.create", t); return null; } } return eventNode; }
private ExecutionEventNode createEventNode(EventBinding.Source<?> binding, Object element) { ExecutionEventNode eventNode; try { eventNode = ((ExecutionEventNodeFactory) element).create(context); if (eventNode.getParent() != null) { throw new IllegalStateException(String.format("Returned EventNode %s was already adopted by another AST.", eventNode)); } } catch (Throwable t) { if (binding.isLanguageBinding()) { /* Language bindings can just throw exceptions directly into the AST. */ throw t; } else { /* * Client Instruments are not allowed to disrupt program execution by throwing * exceptions into the AST. */ exceptionEventForClientInstrument(binding, "ProbeNodeFactory.create", t); return null; } } return eventNode; }
final void onInputValue(EventContext context, VirtualFrame frame, EventBinding<?> inputBinding, EventContext inputContext, int inputIndex, Object inputValue) { if (next != null) { next.onInputValue(context, frame, inputBinding, inputContext, inputIndex, inputValue); } try { if (binding == inputBinding) { innerOnInputValue(context, frame, binding, inputContext, inputIndex, inputValue); } } catch (Throwable t) { if (!isSeenException()) { CompilerDirectives.transferToInterpreterAndInvalidate(); setSeenException(); } if (binding.isLanguageBinding()) { throw t; } else { CompilerDirectives.transferToInterpreter(); exceptionEventForClientInstrument(binding, "onInputValue", t); } } }
final void onDispose(EventContext context, VirtualFrame frame) { try { innerOnDispose(context, frame); } catch (Throwable t) { if (!isSeenException()) { CompilerDirectives.transferToInterpreterAndInvalidate(); setSeenException(); } if (binding.isLanguageBinding()) { throw t; } else { exceptionEventForClientInstrument(binding, "onEnter", t); } } if (next != null) { next.onDispose(context, frame); } }
final void onDispose(EventContext context, VirtualFrame frame) { try { innerOnDispose(context, frame); } catch (Throwable t) { if (!isSeenException()) { CompilerDirectives.transferToInterpreterAndInvalidate(); setSeenException(); } if (binding.isLanguageBinding()) { throw t; } else { exceptionEventForClientInstrument(binding, "onEnter", t); } } if (next != null) { next.onDispose(context, frame); } }
static void notifySourceSectionLoaded(EventBinding.Source<?> binding, Node node, SourceSection section) { if (section == null) { // Do not report null source sections to keep compatibility with the past behavior. return; } LoadSourceSectionListener listener = (LoadSourceSectionListener) binding.getElement(); try { listener.onLoad(new LoadSourceSectionEvent(section, node)); } catch (Throwable t) { if (binding.isLanguageBinding()) { throw t; } else { ProbeNode.exceptionEventForClientInstrument(binding, "onLoad", t); } } }
static void notifySourceSectionLoaded(EventBinding.Source<?> binding, Node node, SourceSection section) { if (section == null) { // Do not report null source sections to keep compatibility with the past behavior. return; } LoadSourceSectionListener listener = (LoadSourceSectionListener) binding.getElement(); try { listener.onLoad(new LoadSourceSectionEvent(section, node)); } catch (Throwable t) { if (binding.isLanguageBinding()) { throw t; } else { ProbeNode.exceptionEventForClientInstrument(binding, "onLoad", t); } } }
private static void notifySourceExecutedBinding(EventBinding.Source<?> binding, Source source) { if (!binding.isDisposed() && binding.isInstrumentedSource(source)) { try { ((ExecuteSourceListener) binding.getElement()).onExecute(new ExecuteSourceEvent(source)); } catch (Throwable t) { if (binding.isLanguageBinding()) { throw t; } else { ProbeNode.exceptionEventForClientInstrument(binding, "onExecute", t); } } } }
private static void notifySourceBindingLoaded(EventBinding.Source<?> binding, Source source) { if (!binding.isDisposed() && binding.isInstrumentedSource(source)) { try { ((LoadSourceListener) binding.getElement()).onLoad(new LoadSourceEvent(source)); } catch (Throwable t) { if (binding.isLanguageBinding()) { throw t; } else { ProbeNode.exceptionEventForClientInstrument(binding, "onLoad", t); } } } }
private static void notifySourceExecutedBinding(EventBinding.Source<?> binding, Source source) { if (!binding.isDisposed() && binding.isInstrumentedSource(source)) { try { ((ExecuteSourceListener) binding.getElement()).onExecute(new ExecuteSourceEvent(source)); } catch (Throwable t) { if (binding.isLanguageBinding()) { throw t; } else { ProbeNode.exceptionEventForClientInstrument(binding, "onExecute", t); } } } }
private static void notifySourceBindingLoaded(EventBinding.Source<?> binding, Source source) { if (!binding.isDisposed() && binding.isInstrumentedSource(source)) { try { ((LoadSourceListener) binding.getElement()).onLoad(new LoadSourceEvent(source)); } catch (Throwable t) { if (binding.isLanguageBinding()) { throw t; } else { ProbeNode.exceptionEventForClientInstrument(binding, "onLoad", t); } } } }