private void initializeSlots(VirtualFrame frame) { Lock lock = getLock(); lock.lock(); try { if (this.inputSlots == null) { if (InstrumentationHandler.TRACE) { InstrumentationHandler.trace("SLOTS: Adding %s save slots for binding %s%n", inputCount, getBinding().getElement()); } FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); FrameSlot[] slots = new FrameSlot[inputCount]; for (int i = 0; i < inputCount; i++) { int slotIndex = inputBaseIndex + i; slots[i] = frameDescriptor.findOrAddFrameSlot(new SavedInputValueID(getBinding(), slotIndex)); } this.sourceFrameDescriptor = frameDescriptor; this.inputSlots = slots; } } finally { lock.unlock(); } }
<T> EventBinding<T> addSourceExecutionBinding(EventBinding.Source<T> binding, boolean notifyLoaded) { if (TRACE) { trace("BEGIN: Adding source execution binding %s, %s%n", binding.getFilter(), binding.getElement()); } this.sourceExecutedBindings.add(binding); this.hasSourceExecutedBindings = true; if (notifyLoaded) { synchronized (sourcesExecuted) { lazyInitializeSourcesExecutedList(); } for (Source source : sourcesExecutedListRef.get()) { notifySourceExecutedBinding(binding, source); } } if (TRACE) { trace("END: Added source execution binding %s, %s%n", binding.getFilter(), binding.getElement()); } return binding; }
/** * 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); }
if (binding.isChildInstrumentedFull(providedTags, rootNode, parentInstrumentable, parentInstrumentableSourceSection, instrumentedNode, sourceSection)) { if (TRACE) { trace(" Found input value binding %s, %s%n", binding.getInputFilter(), System.identityHashCode(binding)); if (binding.isInstrumentedFull(providedTags, rootNode, instrumentedNode, sourceSection)) { if (TRACE) { trace(" Found binding %s, %s%n", binding.getFilter(), binding.getElement());
if (binding.isChildInstrumentedFull(providedTags, rootNode, parentInstrumentable, parentInstrumentableSourceSection, instrumentedNode, sourceSection)) { if (TRACE) { trace(" Found input value binding %s, %s%n", binding.getInputFilter(), System.identityHashCode(binding)); if (binding.isInstrumentedFull(providedTags, rootNode, instrumentedNode, sourceSection)) { if (TRACE) { trace(" Found binding %s, %s%n", binding.getFilter(), binding.getElement());
if (sourceBinding.isExecutionEvent()) { visitRoots(executedRoots, new DisposeWrappersVisitor(sourceBinding));
ProbeNode.EventChainNode createEventChainCallback(VirtualFrame frame, EventBinding.Source<?> binding, RootNode rootNode, Set<Class<?>> providedTags, Node instrumentedNode, SourceSection instrumentedNodeSourceSection) { ProbeNode.EventChainNode next; Object element = binding.getElement(); if (element instanceof ExecutionEventListener) { next = new EventFilterChainNode(binding, (ExecutionEventListener) element); if (binding.getInputFilter() != null) { EventChainNode parent = findParentChain(frame, binding); EventProviderWithInputChainNode parentChain = ((EventProviderWithInputChainNode) parent);
ProbeNode.EventChainNode createEventChainCallback(VirtualFrame frame, EventBinding.Source<?> binding, RootNode rootNode, Set<Class<?>> providedTags, Node instrumentedNode, SourceSection instrumentedNodeSourceSection) { ProbeNode.EventChainNode next; Object element = binding.getElement(); if (element instanceof ExecutionEventListener) { next = new EventFilterChainNode(binding, (ExecutionEventListener) element); if (binding.getInputFilter() != null) { EventChainNode parent = findParentChain(frame, binding); EventProviderWithInputChainNode parentChain = ((EventProviderWithInputChainNode) parent);
if (sourceBinding.isExecutionEvent()) { visitRoots(executedRoots, new DisposeWrappersVisitor(sourceBinding));
private void initializeSlots(VirtualFrame frame) { Lock lock = getLock(); lock.lock(); try { if (this.inputSlots == null) { if (InstrumentationHandler.TRACE) { InstrumentationHandler.trace("SLOTS: Adding %s save slots for binding %s%n", inputCount, getBinding().getElement()); } FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); FrameSlot[] slots = new FrameSlot[inputCount]; for (int i = 0; i < inputCount; i++) { int slotIndex = inputBaseIndex + i; slots[i] = frameDescriptor.findOrAddFrameSlot(new SavedInputValueID(getBinding(), slotIndex)); } this.sourceFrameDescriptor = frameDescriptor; this.inputSlots = slots; } } finally { lock.unlock(); } }
@Override protected final void visitInstrumentable(Node parentInstrumentable, SourceSection parentSourceSection, Node instrumentableNode, SourceSection sourceSection) { // no locking required for these atomic reference arrays for (EventBinding.Source<?> binding : bindings) { if (binding.isInstrumentedFull(providedTags, root, instrumentableNode, sourceSection) || binding.isChildInstrumentedFull(providedTags, root, parentInstrumentable, parentSourceSection, instrumentableNode, sourceSection)) { if (TRACE) { traceFilterCheck("hit", providedTags, binding, instrumentableNode, sourceSection); } visitInstrumented(binding, instrumentableNode, sourceSection); if (!visitForEachBinding) { break; } } else { if (TRACE) { traceFilterCheck("miss", providedTags, binding, instrumentableNode, sourceSection); } } } }
<T> EventBinding<T> addSourceBinding(EventBinding.Source<T> binding, boolean notifyLoaded) { if (TRACE) { trace("BEGIN: Adding source binding %s, %s%n", binding.getFilter(), binding.getElement()); } this.sourceBindings.add(binding); this.hasSourceBindings = true; if (notifyLoaded) { synchronized (sources) { lazyInitializeSourcesList(); } for (Source source : sourcesListRef.get()) { notifySourceBindingLoaded(binding, source); } } if (TRACE) { trace("END: Added source binding %s, %s%n", binding.getFilter(), binding.getElement()); } return binding; }
<T> EventBinding<T> addSourceBinding(EventBinding.Source<T> binding, boolean notifyLoaded) { if (TRACE) { trace("BEGIN: Adding source binding %s, %s%n", binding.getFilter(), binding.getElement()); } this.sourceBindings.add(binding); this.hasSourceBindings = true; if (notifyLoaded) { synchronized (sources) { lazyInitializeSourcesList(); } for (Source source : sourcesListRef.get()) { notifySourceBindingLoaded(binding, source); } } if (TRACE) { trace("END: Added source binding %s, %s%n", binding.getFilter(), binding.getElement()); } return binding; }
@Override protected final void visitInstrumentable(Node parentInstrumentable, SourceSection parentSourceSection, Node instrumentableNode, SourceSection sourceSection) { // no locking required for these atomic reference arrays for (EventBinding.Source<?> binding : bindings) { if (binding.isInstrumentedFull(providedTags, root, instrumentableNode, sourceSection) || binding.isChildInstrumentedFull(providedTags, root, parentInstrumentable, parentSourceSection, instrumentableNode, sourceSection)) { if (TRACE) { traceFilterCheck("hit", providedTags, binding, instrumentableNode, sourceSection); } visitInstrumented(binding, instrumentableNode, sourceSection); if (!visitForEachBinding) { break; } } else { if (TRACE) { traceFilterCheck("miss", providedTags, binding, instrumentableNode, sourceSection); } } } }
/** * 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); }
<T> EventBinding<T> addSourceExecutionBinding(EventBinding.Source<T> binding, boolean notifyLoaded) { if (TRACE) { trace("BEGIN: Adding source execution binding %s, %s%n", binding.getFilter(), binding.getElement()); } this.sourceExecutedBindings.add(binding); this.hasSourceExecutedBindings = true; if (notifyLoaded) { synchronized (sourcesExecuted) { lazyInitializeSourcesExecutedList(); } for (Source source : sourcesExecutedListRef.get()) { notifySourceExecutedBinding(binding, source); } } if (TRACE) { trace("END: Added source execution binding %s, %s%n", binding.getFilter(), binding.getElement()); } return binding; }
AbstractBindingsVisitor(Collection<EventBinding.Source<?>> bindings, boolean visitForEachBinding) { this.bindings = bindings; this.visitForEachBinding = visitForEachBinding; Set<Class<?>> compoundTags = null; // null means all provided tags by the language for (EventBinding.Source<?> sourceBinding : bindings) { Set<Class<?>> limitedTags = sourceBinding.getLimitedTags(); if (limitedTags == null) { compoundTags = null; break; } else { if (compoundTags == null) { compoundTags = new HashSet<>(); } compoundTags.addAll(limitedTags); } } this.materializeLimitedTags = compoundTags != null ? Collections.unmodifiableSet(compoundTags) : null; }
AbstractBindingsVisitor(Collection<EventBinding.Source<?>> bindings, boolean visitForEachBinding) { this.bindings = bindings; this.visitForEachBinding = visitForEachBinding; Set<Class<?>> compoundTags = null; // null means all provided tags by the language for (EventBinding.Source<?> sourceBinding : bindings) { Set<Class<?>> limitedTags = sourceBinding.getLimitedTags(); if (limitedTags == null) { compoundTags = null; break; } else { if (compoundTags == null) { compoundTags = new HashSet<>(); } compoundTags.addAll(limitedTags); } } this.materializeLimitedTags = compoundTags != null ? Collections.unmodifiableSet(compoundTags) : null; }
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); } } }