comparison graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/TraceManager.java @ 13514:0fbee3eb71f0

Ruby: import project.
author Chris Seaton <chris.seaton@oracle.com>
date Mon, 06 Jan 2014 17:12:09 +0000
parents
children
comparison
equal deleted inserted replaced
13513:64a23ce736a0 13514:0fbee3eb71f0
1 /*
2 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
3 * code is released under a tri EPL/GPL/LGPL license. You can use it,
4 * redistribute it and/or modify it under the terms of the:
5 *
6 * Eclipse Public License version 1.0
7 * GNU General Public License version 2
8 * GNU Lesser General Public License version 2.1
9 */
10 package com.oracle.truffle.ruby.runtime.subsystems;
11
12 import com.oracle.truffle.api.*;
13 import com.oracle.truffle.api.utilities.*;
14 import com.oracle.truffle.ruby.runtime.*;
15 import com.oracle.truffle.ruby.runtime.core.*;
16
17 /**
18 * Manages trace events and calls the user's trace method if one is set.
19 * <p>
20 * Once tracing has been enabled via {@link #setTraceProc(RubyProc)}, the underlying instrumentation
21 * remains in effect, along with performance impact.
22 */
23 public final class TraceManager {
24
25 private RubyContext context;
26
27 private final AssumedValue<RubyProc> traceProc = new AssumedValue<>("trace-proc", null);
28 private boolean suspended;
29
30 private String lastFile;
31 private int lastLine;
32
33 private final Assumption notTracingAssumption = Truffle.getRuntime().createAssumption("tracing-disabled");
34
35 public TraceManager(RubyContext context) {
36 this.context = context;
37 }
38
39 /**
40 * Produce a trace; it is a runtime error if {@link #hasTraceProc()}{@code == false}.
41 */
42 @CompilerDirectives.SlowPath
43 public void trace(String event, String file, int line, long objectId, RubyBinding binding, String className) {
44 // If tracing is suspended, stop here
45
46 if (suspended) {
47 return;
48 }
49
50 // If the file and line haven't changed since the last trace, stop here
51
52 if (file.equals(lastFile) && line == lastLine) {
53 return;
54 }
55
56 final RubyClass stringClass = context.getCoreLibrary().getStringClass();
57
58 // Suspend tracing while we run the trace proc
59
60 suspended = true;
61
62 try {
63 // Exceptions from within the proc propagate normally
64
65 traceProc.get().call(null, new RubyString(stringClass, event), //
66 new RubyString(stringClass, file), //
67 line, //
68 GeneralConversions.fixnumOrBignum(objectId), //
69 GeneralConversions.instanceOrNil(binding), //
70 GeneralConversions.instanceOrNil(className));
71 } finally {
72 // Resume tracing
73
74 suspended = false;
75 }
76
77 // Remember the last trace event file and line
78
79 lastFile = file;
80 lastLine = line;
81 }
82
83 /**
84 * Is there a "trace proc" in effect?
85 */
86 public boolean hasTraceProc() {
87 return traceProc.get() != null;
88 }
89
90 /**
91 * Gets the assumption that there has never yet been tracing enabled. Once the assumption is
92 * invalidated, tracing is presumed permanently enabled even if {@link #hasTraceProc()} returns
93 * {@code false}.
94 */
95 public Assumption getNotTracingAssumption() {
96 return notTracingAssumption;
97 }
98
99 public void setTraceProc(RubyProc newTraceProc) {
100 if (!context.getConfiguration().getTrace()) {
101 throw new RuntimeException("You need the --trace option to use tracing");
102 }
103
104 traceProc.set(newTraceProc);
105 lastFile = null;
106 lastLine = -1;
107
108 notTracingAssumption.invalidate();
109 }
110 }