Mercurial > hg > graal-compiler
annotate graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java @ 13735:2c1c805153e6
Ruby: refactor low level instrumentation services
author | Michael Van De Vanter <michael.van.de.vanter@oracle.com> |
---|---|
date | Wed, 22 Jan 2014 21:02:06 -0800 |
parents | fbf448929260 |
children | 64fa70319890 |
rev | line source |
---|---|
13514 | 1 /* |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
2 * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This |
13514 | 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; | |
11 | |
12 import java.math.*; | |
13 import java.util.concurrent.atomic.*; | |
14 | |
15 import jnr.posix.*; | |
16 | |
17 import com.oracle.truffle.api.*; | |
18 import com.oracle.truffle.api.frame.*; | |
13732
fbf448929260
Ruby: remove some prototyping code no longer needed
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13658
diff
changeset
|
19 import com.oracle.truffle.api.impl.*; |
13514 | 20 import com.oracle.truffle.api.nodes.*; |
21 import com.oracle.truffle.api.source.*; | |
22 import com.oracle.truffle.ruby.runtime.configuration.*; | |
23 import com.oracle.truffle.ruby.runtime.control.*; | |
24 import com.oracle.truffle.ruby.runtime.core.*; | |
25 import com.oracle.truffle.ruby.runtime.methods.*; | |
26 import com.oracle.truffle.ruby.runtime.objects.*; | |
27 import com.oracle.truffle.ruby.runtime.subsystems.*; | |
28 | |
29 /** | |
30 * The global state of a running Ruby system. | |
31 */ | |
32 public class RubyContext implements ExecutionContext { | |
33 | |
34 private final Configuration configuration; | |
35 private final RubyParser parser; | |
36 private final CoreLibrary coreLibrary; | |
37 private final FeatureManager featureManager; | |
38 private final ObjectSpaceManager objectSpaceManager; | |
39 private final TraceManager traceManager; | |
40 private final ThreadManager threadManager; | |
41 private final FiberManager fiberManager; | |
42 private final AtExitManager atExitManager; | |
13732
fbf448929260
Ruby: remove some prototyping code no longer needed
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13658
diff
changeset
|
43 private final DebugManager debugManager; |
13514 | 44 private final SourceManager sourceManager; |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
45 private final ASTPrinter astPrinter; |
13514 | 46 |
47 private AtomicLong nextObjectID = new AtomicLong(0); | |
48 | |
49 private String currentDirectory = System.getProperty("user.dir"); | |
50 | |
51 private POSIX posix = POSIXFactory.getPOSIX(); | |
52 | |
53 public RubyContext(RubyParser parser) { | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
54 this(new Configuration(new ConfigurationBuilder()), parser, null); |
13514 | 55 } |
56 | |
57 public RubyContext(Configuration configuration, RubyParser parser) { | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
58 this(configuration, parser, null); |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
59 } |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
60 |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
61 public RubyContext(Configuration configuration, RubyParser parser, ASTPrinter astPrinter) { |
13514 | 62 assert configuration != null; |
63 | |
64 this.configuration = configuration; | |
65 this.parser = parser; | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
66 this.astPrinter = astPrinter; |
13514 | 67 |
68 objectSpaceManager = new ObjectSpaceManager(this); | |
69 traceManager = new TraceManager(this); | |
70 | |
71 // See note in CoreLibrary#initialize to see why we need to break this into two statements | |
72 coreLibrary = new CoreLibrary(this); | |
73 coreLibrary.initialize(); | |
74 | |
75 featureManager = new FeatureManager(this); | |
76 atExitManager = new AtExitManager(); | |
77 sourceManager = new SourceManager(); | |
78 | |
13735
2c1c805153e6
Ruby: refactor low level instrumentation services
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13732
diff
changeset
|
79 debugManager = new DefaultDebugManager(this); |
13514 | 80 |
81 // Must initialize threads before fibers | |
82 | |
83 threadManager = new ThreadManager(this); | |
13645
497fada09efb
Ruby: remove versioning.
Chris Seaton <chris.seaton@oracle.com>
parents:
13563
diff
changeset
|
84 fiberManager = new FiberManager(this); |
13514 | 85 } |
86 | |
13735
2c1c805153e6
Ruby: refactor low level instrumentation services
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13732
diff
changeset
|
87 public final String getLanguageShortName() { |
2c1c805153e6
Ruby: refactor low level instrumentation services
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13732
diff
changeset
|
88 return "Ruby " + CoreLibrary.RUBY_VERSION; |
13514 | 89 } |
90 | |
13732
fbf448929260
Ruby: remove some prototyping code no longer needed
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13658
diff
changeset
|
91 public DebugManager getDebugManager() { |
13514 | 92 return debugManager; |
93 } | |
94 | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
95 public ASTPrinter getASTPrinter() { |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
96 return astPrinter; |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
97 } |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
98 |
13514 | 99 public void implementationMessage(String format, Object... arguments) { |
100 System.err.println("rubytruffle: " + String.format(format, arguments)); | |
101 } | |
102 | |
103 public void load(Source source) { | |
104 execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); | |
105 } | |
106 | |
107 public void loadFile(String fileName) { | |
108 final Source source = sourceManager.get(fileName); | |
109 final String code = source.getCode(); | |
110 if (code == null) { | |
111 throw new RuntimeException("Can't read file " + fileName); | |
112 } | |
113 execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); | |
114 } | |
115 | |
116 /** | |
117 * Receives runtime notification that execution has halted. | |
118 */ | |
119 public void haltedAt(Node node, MaterializedFrame frame) { | |
120 runShell(node, frame); | |
121 } | |
122 | |
123 public Object eval(String code) { | |
124 final Source source = sourceManager.get("(eval)", code); | |
125 return execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); | |
126 } | |
127 | |
128 public Object eval(String code, RubyModule module) { | |
129 final Source source = sourceManager.get("(eval)", code); | |
130 return execute(this, source, RubyParser.ParserContext.MODULE, module, null); | |
131 } | |
132 | |
133 public Object eval(String code, RubyBinding binding) { | |
134 final Source source = sourceManager.get("(eval)", code); | |
135 return execute(this, source, RubyParser.ParserContext.TOP_LEVEL, binding.getSelf(), binding.getFrame()); | |
136 } | |
137 | |
138 public void runShell(Node node, MaterializedFrame frame) { | |
139 MaterializedFrame existingLocals = frame; | |
140 | |
141 String prompt = "Ruby> "; | |
142 if (node != null) { | |
143 final SourceSection src = node.getSourceSection(); | |
144 if (src != null) { | |
145 prompt = (src.getSource().getName() + ":" + src.getStartLine() + "> "); | |
146 } | |
147 } | |
148 | |
149 while (true) { | |
150 try { | |
151 final String line = configuration.getInputReader().readLine(prompt); | |
152 | |
153 final ShellResult result = evalShell(line, existingLocals); | |
154 | |
155 configuration.getStandardOut().println("=> " + result.getResult()); | |
156 | |
157 existingLocals = result.getFrame(); | |
158 } catch (BreakShellException e) { | |
159 return; | |
160 } catch (Exception e) { | |
161 e.printStackTrace(); | |
162 } | |
163 } | |
164 } | |
165 | |
166 public ShellResult evalShell(String code, MaterializedFrame existingLocals) { | |
167 final Source source = sourceManager.get("(shell)", code); | |
168 return (ShellResult) execute(this, source, RubyParser.ParserContext.SHELL, coreLibrary.getMainObject(), existingLocals); | |
169 } | |
170 | |
171 public Object execute(RubyContext context, Source source, RubyParser.ParserContext parserContext, Object self, MaterializedFrame parentFrame) { | |
172 try { | |
173 final RubyParserResult parseResult = parser.parse(context, source, parserContext, parentFrame); | |
174 final RubyArguments arguments = new RubyArguments(parentFrame, self, null); | |
175 final CallTarget callTarget = Truffle.getRuntime().createCallTarget(parseResult.getRootNode(), parseResult.getFrameDescriptor()); | |
176 | |
177 return callTarget.call(null, arguments); | |
178 } catch (RaiseException e) { | |
179 throw e; | |
180 } catch (ThrowException e) { | |
13645
497fada09efb
Ruby: remove versioning.
Chris Seaton <chris.seaton@oracle.com>
parents:
13563
diff
changeset
|
181 throw new RaiseException(context.getCoreLibrary().argumentErrorUncaughtThrow(e.getTag())); |
13514 | 182 } catch (BreakShellException | QuitException e) { |
183 throw e; | |
184 } catch (Throwable e) { | |
185 throw new RaiseException(ExceptionTranslator.translateException(this, e)); | |
186 } | |
187 } | |
188 | |
189 public long getNextObjectID() { | |
190 // TODO(CS): We can theoretically run out of long values | |
191 | |
192 final long id = nextObjectID.getAndIncrement(); | |
193 | |
194 if (id < 0) { | |
195 nextObjectID.set(Long.MIN_VALUE); | |
196 throw new RuntimeException("Object IDs exhausted"); | |
197 } | |
198 | |
199 return id; | |
200 } | |
201 | |
202 public void shutdown() { | |
203 atExitManager.run(); | |
204 | |
205 threadManager.leaveGlobalLock(); | |
206 | |
207 objectSpaceManager.shutdown(); | |
208 | |
209 if (fiberManager != null) { | |
210 fiberManager.shutdown(); | |
211 } | |
212 } | |
213 | |
214 public RubyString makeString(String string) { | |
215 return new RubyString(coreLibrary.getStringClass(), string); | |
216 } | |
217 | |
218 public RubyString makeString(char string) { | |
219 return makeString(Character.toString(string)); | |
220 } | |
221 | |
222 public Configuration getConfiguration() { | |
223 return configuration; | |
224 } | |
225 | |
226 public CoreLibrary getCoreLibrary() { | |
227 return coreLibrary; | |
228 } | |
229 | |
230 public FeatureManager getFeatureManager() { | |
231 return featureManager; | |
232 } | |
233 | |
234 public ObjectSpaceManager getObjectSpaceManager() { | |
235 return objectSpaceManager; | |
236 } | |
237 | |
238 public TraceManager getTraceManager() { | |
239 return traceManager; | |
240 } | |
241 | |
242 public FiberManager getFiberManager() { | |
243 return fiberManager; | |
244 } | |
245 | |
246 public ThreadManager getThreadManager() { | |
247 return threadManager; | |
248 } | |
249 | |
250 public RubyParser getParser() { | |
251 return parser; | |
252 } | |
253 | |
254 /** | |
255 * Utility method to check if an object should be visible in a Ruby program. Used in assertions | |
256 * at method boundaries to check that only values we want to be visible to the programmer become | |
257 * so. | |
258 */ | |
259 public static boolean shouldObjectBeVisible(Object object) { | |
260 // TODO(cs): RubyMethod should never be visible | |
261 | |
262 return object instanceof UndefinedPlaceholder || // | |
263 object instanceof Boolean || // | |
264 object instanceof Integer || // | |
265 object instanceof BigInteger || // | |
266 object instanceof Double || // | |
267 object instanceof RubyBasicObject || // | |
268 object instanceof RubyMethod || // | |
269 object instanceof NilPlaceholder || // | |
270 object instanceof RubyMethod; | |
271 } | |
272 | |
273 public static boolean shouldObjectsBeVisible(Object... objects) { | |
274 for (Object object : objects) { | |
275 if (!shouldObjectBeVisible(object)) { | |
276 return false; | |
277 } | |
278 } | |
279 | |
280 return true; | |
281 } | |
282 | |
283 public void setCurrentDirectory(String currentDirectory) { | |
284 this.currentDirectory = currentDirectory; | |
285 } | |
286 | |
287 public String getCurrentDirectory() { | |
288 return currentDirectory; | |
289 } | |
290 | |
291 public POSIX getPOSIX() { | |
292 return posix; | |
293 } | |
294 | |
295 public AtExitManager getAtExitManager() { | |
296 return atExitManager; | |
297 } | |
298 | |
299 public SourceManager getSourceManager() { | |
300 return sourceManager; | |
301 } | |
302 | |
303 } |