public
Description: Cluster Configuration for JRuby, using Terracotta.
Homepage: http://fabiokung.com/2008/11/22/play-with-jmaglev-yourself/
Clone URL: git://github.com/fabiokung/clustered-jruby.git
clustered-jruby / clustering_jruby.patch
d7e19b4f » fabiokung 2008-11-22 including patch to make JRu... 1 Index: src/org/jruby/runtime/ReadonlyGlobalVariable.java
2 ===================================================================
3 --- src/org/jruby/runtime/ReadonlyGlobalVariable.java (revision 8091)
4 +++ src/org/jruby/runtime/ReadonlyGlobalVariable.java (working copy)
5 @@ -34,12 +34,12 @@
6
7 public class ReadonlyGlobalVariable extends GlobalVariable {
8
9 - public ReadonlyGlobalVariable(Ruby runtime, String name, IRubyObject value) {
10 - super(runtime, name, value);
11 + public ReadonlyGlobalVariable(String name, IRubyObject value) {
12 + super(name, value);
13 }
14
15 @Override
16 public IRubyObject set(IRubyObject value) {
17 - throw runtime.newNameError(name() + " is a read-only variable", name());
18 + throw Ruby.getCurrentRuntime().newNameError(name() + " is a read-only variable", name());
19 }
20 }
21 Index: src/org/jruby/runtime/GlobalVariable.java
22 ===================================================================
23 --- src/org/jruby/runtime/GlobalVariable.java (revision 8091)
24 +++ src/org/jruby/runtime/GlobalVariable.java (working copy)
25 @@ -39,7 +39,7 @@
26 private GlobalVariable other;
27
28 public Copy(Ruby runtime, String name, GlobalVariable other) {
29 - super(runtime, name, other.get());
30 + super(name, other.get());
31 this.other = other;
32 }
33
34 @@ -54,8 +54,6 @@
35 }
36 }
37
38 - protected final Ruby runtime;
39 -
40 protected final String name;
41 private IRubyObject value;
42
43 @@ -63,10 +61,8 @@
44 return "$" + name;
45 }
46
47 - public GlobalVariable(Ruby runtime, String name, IRubyObject value) {
48 + public GlobalVariable(String name, IRubyObject value) {
49 assert name.startsWith("$");
50 -
51 - this.runtime = runtime;
52 this.name = name;
53 this.value = value;
54 }
55 Index: src/org/jruby/runtime/GlobalVariableAcessor.java
56 ===================================================================
57 --- src/org/jruby/runtime/GlobalVariableAcessor.java (revision 0)
58 +++ src/org/jruby/runtime/GlobalVariableAcessor.java (revision 0)
59 @@ -0,0 +1,24 @@
60 +package org.jruby.runtime;
61 +
62 +import org.jruby.runtime.IAccessor;
63 +import org.jruby.runtime.GlobalVariable;
64 +import org.jruby.runtime.builtin.IRubyObject;
65 +
66 +/**
67 + * @author Fabio Kung
68 +*/
69 +public class GlobalVariableAcessor implements IAccessor {
70 + private final GlobalVariable variable;
71 +
72 + public GlobalVariableAcessor(GlobalVariable variable) {
73 + this.variable = variable;
74 + }
75 +
76 + public IRubyObject getValue() {
77 + return variable.get();
78 + }
79 +
80 + public IRubyObject setValue(IRubyObject newValue) {
81 + return variable.set(newValue);
82 + }
83 +}
84 Index: src/org/jruby/ext/ffi/io/FileDescriptorIO.java
85 ===================================================================
86 --- src/org/jruby/ext/ffi/io/FileDescriptorIO.java (revision 8091)
87 +++ src/org/jruby/ext/ffi/io/FileDescriptorIO.java (working copy)
88 @@ -68,7 +68,7 @@
89 } catch (InvalidValueException ex) {
90 throw new RuntimeException(ex);
91 }
92 - openFile.setMainStream(new ChannelStream(getRuntime(),
93 + openFile.setMainStream(new ChannelStream(
94 new ChannelDescriptor(Factory.getInstance().newByteChannel(RubyNumeric.fix2int(fd)),
95 getNewFileno(), modes, new java.io.FileDescriptor())));
96 openFile.setPipeStream(openFile.getMainStream());
97 Index: src/org/jruby/ext/socket/RubyUNIXSocket.java
98 ===================================================================
99 --- src/org/jruby/ext/socket/RubyUNIXSocket.java (revision 8091)
100 +++ src/org/jruby/ext/socket/RubyUNIXSocket.java (working copy)
101 @@ -311,7 +311,7 @@
102
103 protected void init_sock(Ruby runtime) throws Exception {
104 ModeFlags modes = new ModeFlags(ModeFlags.RDWR);
105 - openFile.setMainStream(new ChannelStream(runtime, new ChannelDescriptor(new UnixDomainSocketChannel(fd), getNewFileno(), modes, new java.io.FileDescriptor())));
106 + openFile.setMainStream(new ChannelStream(new ChannelDescriptor(new UnixDomainSocketChannel(fd), getNewFileno(), modes, new java.io.FileDescriptor())));
107 openFile.setPipeStream(openFile.getMainStream());
108 openFile.setMode(modes.getOpenFileFlags());
109 openFile.getMainStream().setSync(true);
110 Index: src/org/jruby/internal/runtime/GlobalVariables.java
111 ===================================================================
112 --- src/org/jruby/internal/runtime/GlobalVariables.java (revision 8091)
113 +++ src/org/jruby/internal/runtime/GlobalVariables.java (working copy)
114 @@ -47,13 +47,8 @@
115 * @author jpetersen
116 */
117 public class GlobalVariables {
118 - private Ruby runtime;
119 private Map<String, GlobalVariable> globalVariables = new ConcurrentHashMap<String, GlobalVariable>();
120
121 - public GlobalVariables(Ruby runtime) {
122 - this.runtime = runtime;
123 - }
124 -
125 public void define(String name, IAccessor accessor) {
126 assert name != null;
127 assert accessor != null;
128 @@ -89,15 +84,16 @@
129 assert name.startsWith("$");
130 assert oldName.startsWith("$");
131
132 - if (runtime.getSafeLevel() >= 4) {
133 - throw runtime.newSecurityError("Insecure: can't alias global variable");
134 + if (Ruby.getCurrentRuntime().getSafeLevel() >= 4) {
135 + throw Ruby.getCurrentRuntime().newSecurityError("Insecure: can't alias global variable");
136 }
137
138 GlobalVariable oldVariable = createIfNotDefined(oldName);
139 GlobalVariable variable = (GlobalVariable)globalVariables.get(name);
140
141 if (variable != null && oldVariable != variable && variable.isTracing()) {
142 - throw new RaiseException(runtime, runtime.getRuntimeError(), "can't alias in tracer", false);
143 + throw new RaiseException(Ruby.getCurrentRuntime(), Ruby.getCurrentRuntime().getRuntimeError(),
144 + "can't alias in tracer", false);
145 }
146
147 globalVariables.put(name, oldVariable);
148 @@ -111,16 +107,16 @@
149 if (variable != null) {
150 return variable.getAccessor().getValue();
151 }
152 - runtime.getWarnings().warning(ID.GLOBAL_NOT_INITIALIZED, "global variable `" + name + "' not initialized", name);
153 - return runtime.getNil();
154 + Ruby.getCurrentRuntime().getWarnings().warning(ID.GLOBAL_NOT_INITIALIZED, "global variable `" + name + "' not initialized", name);
155 + return Ruby.getCurrentRuntime().getNil();
156 }
157
158 public IRubyObject set(String name, IRubyObject value) {
159 assert name != null;
160 assert name.startsWith("$");
161
162 - if (runtime.getSafeLevel() >= 4) {
163 - throw runtime.newSecurityError("Insecure: can't change global variable value");
164 + if (Ruby.getCurrentRuntime().getSafeLevel() >= 4) {
165 + throw Ruby.getCurrentRuntime().newSecurityError("Insecure: can't change global variable value");
166 }
167
168 GlobalVariable variable = createIfNotDefined(name);
169 @@ -165,7 +161,7 @@
170 private GlobalVariable createIfNotDefined(String name) {
171 GlobalVariable variable = (GlobalVariable)globalVariables.get(name);
172 if (variable == null) {
173 - variable = GlobalVariable.newUndefined(runtime, name);
174 + variable = GlobalVariable.newUndefined(Ruby.getCurrentRuntime(), name);
175 globalVariables.put(name, variable);
176 }
177 return variable;
178 Index: src/org/jruby/internal/runtime/RuntimeVariableAccessor.java
179 ===================================================================
180 --- src/org/jruby/internal/runtime/RuntimeVariableAccessor.java (revision 0)
181 +++ src/org/jruby/internal/runtime/RuntimeVariableAccessor.java (revision 0)
182 @@ -0,0 +1,32 @@
183 +package org.jruby.internal.runtime;
184 +
185 +import org.jruby.runtime.IAccessor;
186 +import org.jruby.runtime.builtin.IRubyObject;
187 +import org.jruby.Ruby;
188 +
189 +/**
190 + * @author Fabio Kung
191 + */
192 +public class RuntimeVariableAccessor implements IAccessor {
193 + private final String name;
194 +
195 + public RuntimeVariableAccessor(String name) {
196 + this.name = name;
197 + }
198 +
199 + public RuntimeVariableAccessor(String name, IRubyObject value) {
200 + this.name = name;
201 + setValue(value);
202 + }
203 +
204 + public IRubyObject getValue() {
205 + Ruby runtime = Ruby.getCurrentRuntime();
206 + return runtime.getRuntimeVariable(this.name);
207 + }
208 +
209 + public IRubyObject setValue(IRubyObject newValue) {
210 + Ruby runtime = Ruby.getCurrentRuntime();
211 + runtime.setRuntimeVariable(this.name, newValue);
212 + return newValue;
213 + }
214 +}
215 Index: src/org/jruby/RubyArgsFile.java
216 ===================================================================
217 --- src/org/jruby/RubyArgsFile.java (revision 8091)
218 +++ src/org/jruby/RubyArgsFile.java (working copy)
219 @@ -39,6 +39,7 @@
220 import org.jruby.runtime.ThreadContext;
221 import org.jruby.runtime.builtin.IRubyObject;
222 import org.jruby.util.ByteList;
223 +import org.jruby.internal.runtime.RuntimeVariableAccessor;
224
225 public class RubyArgsFile {
226 private static final class ArgsFileData {
227 @@ -106,12 +107,13 @@
228
229 runtime.getEnumerable().extend_object(argsFile);
230
231 - runtime.defineReadonlyVariable("$<", argsFile);
232 + runtime.getGlobalVariables().defineReadonly("$<", new RuntimeVariableAccessor("$<", argsFile));
233 runtime.defineGlobalConstant("ARGF", argsFile);
234
235 RubyClass argfClass = argsFile.getMetaClass();
236 argfClass.defineAnnotatedMethods(RubyArgsFile.class);
237 - runtime.defineReadonlyVariable("$FILENAME", runtime.newString("-"));
238 + runtime.getGlobalVariables().defineReadonly("$FILENAME",
239 + new RuntimeVariableAccessor("$FILENAME", runtime.newString("-")));
240 }
241
242 @JRubyMethod(name = {"fileno", "to_i"})
243 Index: src/org/jruby/RubyFile.java
244 ===================================================================
245 --- src/org/jruby/RubyFile.java (revision 8091)
246 +++ src/org/jruby/RubyFile.java (working copy)
247 @@ -165,7 +165,7 @@
248 super(runtime, runtime.getFile());
249 this.path = path;
250 try {
251 - this.openFile.setMainStream(new ChannelStream(runtime, new ChannelDescriptor(Channels.newChannel(in), getNewFileno(), new FileDescriptor())));
252 + this.openFile.setMainStream(new ChannelStream(new ChannelDescriptor(Channels.newChannel(in), getNewFileno(), new FileDescriptor())));
253 } catch (InvalidValueException ex) {
254 throw runtime.newErrnoEINVALError();
255 }
256 Index: src/org/jruby/Ruby.java
257 ===================================================================
258 --- src/org/jruby/Ruby.java (revision 8091)
259 +++ src/org/jruby/Ruby.java (working copy)
260 @@ -110,6 +110,7 @@
261 import org.jruby.runtime.ObjectSpace;
262 import org.jruby.runtime.RubyEvent;
263 import org.jruby.runtime.ThreadContext;
264 +import org.jruby.runtime.GlobalVariableAcessor;
265 import org.jruby.runtime.builtin.IRubyObject;
266 import org.jruby.runtime.encoding.EncodingService;
267 import org.jruby.runtime.load.Library;
268 @@ -122,6 +123,7 @@
269 import org.jruby.util.JRubyClassLoader;
270 import org.jruby.util.JavaNameMangler;
271 import org.jruby.util.KCode;
272 +import org.jruby.util.RuntimeContainer;
273 import org.jruby.util.SafePropertyAccessor;
274 import org.jruby.util.collections.WeakHashSet;
275 import org.jruby.util.io.ChannelDescriptor;
276 @@ -136,7 +138,7 @@
277 * multiple instances of each class. This means that in multi-runtime mode
278 * (or really, multi-VM mode, where each JRuby instance is a ruby "VM"), objects
279 * generally can't be transported across runtimes without marshaling.
280 - *
281 + *
282 * This class roots everything that makes the JRuby runtime function, and
283 * provides a number of utility methods for constructing global types and
284 * accessing global runtime structures.
285 @@ -183,16 +185,27 @@
286 config.setError(err);
287 return newInstance(config);
288 }
289 -
290 +
291 + public static Ruby getCurrentRuntime() {
292 + JRubyClassLoader loader = (JRubyClassLoader) Thread.currentThread().getContextClassLoader();
293 + while (!(loader instanceof RuntimeContainer)) {
294 + loader = (JRubyClassLoader) loader.getParent();
295 + }
296 + return ((RuntimeContainer) loader).getRuntime();
297 + }
298 +
299 /**
300 * Create and initialize a new JRuby runtime. The properties of the
301 * specified RubyInstanceConfig will be used to determine various JRuby
302 * runtime characteristics.
303 - *
304 + *
305 * @param config The configuration to use for the new instance
306 * @see org.jruby.RubyInstanceConfig
307 */
308 private Ruby(RubyInstanceConfig config) {
309 + Thread currentThread = Thread.currentThread();
310 + currentThread.setContextClassLoader(new RuntimeContainer(currentThread.getContextClassLoader(), this));
311 +
312 this.config = config;
313 this.threadService = new ThreadService(this);
314 if(config.isSamplingEnabled()) {
315 @@ -209,18 +222,18 @@
316 this.beanManager = new BeanManager(this, config.isManagementEnabled());
317 this.jitCompiler = new JITCompiler(this);
318 this.parserStats = new ParserStats(this);
319 -
320 +
321 this.beanManager.register(new Config(this));
322 this.beanManager.register(parserStats);
323 this.beanManager.register(new ClassCache(this));
324 }
325 -
326 +
327 /**
328 * Evaluates a script under the current scope (perhaps the top-level
329 * scope) and returns the result (generally the last value calculated).
330 * This version goes straight into the interpreter, bypassing compilation
331 * and runtime preparation typical to normal script runs.
332 - *
333 + *
334 * @param script The scriptlet to run
335 * @returns The result of the eval
336 */
337 @@ -229,7 +242,7 @@
338 DynamicScope currentScope = context.getCurrentScope();
339 ManyVarsDynamicScope newScope = new ManyVarsDynamicScope(new EvalStaticScope(currentScope.getStaticScope()), currentScope);
340 Node node = parseEval(script, "<script>", newScope, 0);
341 -
342 +
343 try {
344 context.preEvalScriptlet(newScope);
345 return node.interpret(this, context, context.getFrameSelf(), Block.NULL_BLOCK);
346 @@ -243,20 +256,20 @@
347 context.postEvalScriptlet();
348 }
349 }
350 -
351 +
352 /**
353 - * Parse and execute the specified script
354 + * Parse and execute the specified script
355 * This differs from the other methods in that it accepts a string-based script and
356 * parses and runs it as though it were loaded at a command-line. This is the preferred
357 * way to start up a new script when calling directly into the Ruby object (which is
358 * generally *dis*couraged.
359 - *
360 + *
361 * @param script The contents of the script to run as a normal, root script
362 * @return The last value of the script
363 */
364 public IRubyObject executeScript(String script, String filename) {
365 byte[] bytes;
366 -
367 +
368 try {
369 bytes = script.getBytes(KCode.NONE.getKCode());
370 } catch (UnsupportedEncodingException e) {
371 @@ -265,7 +278,7 @@
372
373 Node node = parseInline(new ByteArrayInputStream(bytes), filename, null);
374 ThreadContext context = getCurrentContext();
375 -
376 +
377 String oldFile = context.getFile();
378 int oldLine = context.getLine();
379 try {
380 @@ -277,22 +290,22 @@
381 context.setLine(oldLine);
382 }
383 }
384 -
385 +
386 /**
387 * Run the script contained in the specified input stream, using the
388 * specified filename as the name of the script being executed. The stream
389 * will be read fully before being parsed and executed. The given filename
390 * will be used for the ruby $PROGRAM_NAME and $0 global variables in this
391 * runtime.
392 - *
393 + *
394 * This method is intended to be called once per runtime, generally from
395 * Main or from main-like top-level entry points.
396 - *
397 + *
398 * As part of executing the script loaded from the input stream, various
399 * RubyInstanceConfig properties will be used to determine whether to
400 * compile the script before execution or run with various wrappers (for
401 * looping, printing, and so on, see jruby -help).
402 - *
403 + *
404 * @param inputStream The InputStream from which to read the script contents
405 * @param filename The filename to use when parsing, and for $PROGRAM_NAME
406 * and $0 ruby global variables.
407 @@ -314,7 +327,7 @@
408 getGlobalVariables().set("$" + entry.getKey().toString(), varvalue);
409 }
410
411 -
412 +
413 if(config.isYARVEnabled()) {
414 if (config.isShowBytecode()) System.err.print("error: bytecode printing only works with JVM bytecode");
415 new YARVCompiledRunner(this, inputStream, filename).run();
416 @@ -350,7 +363,7 @@
417 * is used to verify that the script syntax is valid, for jruby -c. The
418 * current scope (generally the top-level scope) is used as the parent
419 * scope for parsing.
420 - *
421 + *
422 * @param inputStream The input stream from which to read the script
423 * @param filename The filename to use for parsing
424 * @returns The root node of the parsed script
425 @@ -362,12 +375,12 @@
426 return parseFile(inputStream, filename, getCurrentContext().getCurrentScope());
427 }
428 }
429 -
430 +
431 /**
432 * Run the given script with a "while gets; end" loop wrapped around it.
433 * This is primarily used for the -n command-line flag, to allow writing
434 * a short script that processes input lines using the specified code.
435 - *
436 + *
437 * @param scriptNode The root node of the script to execute
438 * @param printing Whether $_ should be printed after each loop (as in the
439 * -p command-line flag)
440 @@ -380,7 +393,7 @@
441 */
442 public IRubyObject runWithGetsLoop(Node scriptNode, boolean printing, boolean processLineEnds, boolean split, boolean yarvCompile) {
443 ThreadContext context = getCurrentContext();
444 -
445 +
446 Script script = null;
447 YARVCompiledRunner runner = null;
448 boolean compile = getInstanceConfig().getCompileMode().shouldPrecompileCLI();
449 @@ -393,22 +406,22 @@
450 } else if (yarvCompile) {
451 runner = tryCompileYarv(scriptNode);
452 }
453 -
454 +
455 if (processLineEnds) {
456 getGlobalVariables().set("$\\", getGlobalVariables().get("$/"));
457 }
458 -
459 +
460 while (RubyKernel.gets(context, getTopSelf(), IRubyObject.NULL_ARRAY).isTrue()) {
461 loop: while (true) { // Used for the 'redo' command
462 try {
463 if (processLineEnds) {
464 getGlobalVariables().get("$_").callMethod(context, "chop!");
465 }
466 -
467 +
468 if (split) {
469 getGlobalVariables().set("$F", getGlobalVariables().get("$_").callMethod(context, "split"));
470 }
471 -
472 +
473 if (script != null) {
474 runScript(script);
475 } else if (runner != null) {
476 @@ -416,7 +429,7 @@
477 } else {
478 runInterpreter(scriptNode);
479 }
480 -
481 +
482 if (printing) RubyKernel.print(context, getKernel(), new IRubyObject[] {getGlobalVariables().get("$_")});
483 break loop;
484 } catch (JumpException.RedoJump rj) {
485 @@ -430,14 +443,14 @@
486 }
487 }
488 }
489 -
490 +
491 return getNil();
492 }
493 -
494 +
495 /**
496 * Run the specified script without any of the loop-processing wrapper
497 * code.
498 - *
499 + *
500 * @param scriptNode The root node of the script to be executed
501 * @param yarvCompile Whether to compile the script to YARV (Ruby 1.9)
502 * bytecode before execution
503 @@ -456,7 +469,7 @@
504 return getNil();
505 }
506 }
507 -
508 +
509 if (script != null) {
510 if (config.isShowBytecode()) {
511 return nilObject;
512 @@ -470,11 +483,11 @@
513 return runInterpreter(scriptNode);
514 }
515 }
516 -
517 +
518 private Script tryCompile(Node node) {
519 return tryCompile(node, new JRubyClassLoader(getJRubyClassLoader()));
520 }
521 -
522 +
523 private Script tryCompile(Node node, JRubyClassLoader classLoader) {
524 Script script = null;
525 try {
526 @@ -533,10 +546,10 @@
527 System.err.println("Error, could not compile; pass -d or -J-Djruby.jit.logging.verbose=true for more details");
528 }
529 }
530 -
531 +
532 return script;
533 }
534 -
535 +
536 private YARVCompiledRunner tryCompileYarv(Node node) {
537 try {
538 StandardYARVCompiler compiler = new StandardYARVCompiler(this);
539 @@ -553,17 +566,17 @@
540 return null;
541 }
542 }
543 -
544 +
545 private IRubyObject runScript(Script script) {
546 ThreadContext context = getCurrentContext();
547 -
548 +
549 try {
550 return script.load(context, context.getFrameSelf(), IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
551 } catch (JumpException.ReturnJump rj) {
552 return (IRubyObject) rj.getValue();
553 }
554 }
555 -
556 +
557 private IRubyObject runYarv(YARVCompiledRunner runner) {
558 try {
559 return runner.run();
560 @@ -571,12 +584,12 @@
561 return (IRubyObject) rj.getValue();
562 }
563 }
564 -
565 +
566 private IRubyObject runInterpreter(Node scriptNode) {
567 ThreadContext context = getCurrentContext();
568 -
569 +
570 assert scriptNode != null : "scriptNode is not null";
571 -
572 +
573 try {
574 return scriptNode.interpret(this, context, getTopSelf(), Block.NULL_BLOCK);
575 } catch (JumpException.ReturnJump rj) {
576 @@ -587,11 +600,11 @@
577 public Parser getParser() {
578 return parser;
579 }
580 -
581 +
582 public BeanManager getBeanManager() {
583 return beanManager;
584 }
585 -
586 +
587 public JITCompiler getJITCompiler() {
588 return jitCompiler;
589 }
590 @@ -602,16 +615,16 @@
591 public static Ruby getDefaultInstance() {
592 return newInstance();
593 }
594 -
595 +
596 @Deprecated
597 public static Ruby getCurrentInstance() {
598 return null;
599 }
600 -
601 +
602 @Deprecated
603 public static void setCurrentInstance(Ruby runtime) {
604 }
605 -
606 +
607 public int allocSymbolId() {
608 return symbolLastId.incrementAndGet();
609 }
610 @@ -621,7 +634,7 @@
611
612 /**
613 * Retrieve the module with the given name from the Object namespace.
614 - *
615 + *
616 * @param name The name of the module
617 * @return The module or null if not found
618 */
619 @@ -633,7 +646,7 @@
620 * Retrieve the module with the given name from the Object namespace. The
621 * module name must be an interned string, but this method will be faster
622 * than the non-interned version.
623 - *
624 + *
625 * @param internedName The name of the module; <em>must</em> be an interned String
626 * @return The module or null if not found
627 */
628 @@ -641,7 +654,7 @@
629 return (RubyModule) objectClass.fastGetConstantAt(internedName);
630 }
631
632 - /**
633 + /**
634 * Retrieve the class with the given name from the Object namespace.
635 *
636 * @param name The name of the class
637 @@ -655,7 +668,7 @@
638 * Retrieve the class with the given name from the Object namespace. The
639 * module name must be an interned string, but this method will be faster
640 * than the non-interned version.
641 - *
642 + *
643 * @param internedName the name of the class; <em>must</em> be an interned String!
644 * @return
645 */
646 @@ -663,7 +676,7 @@
647 return objectClass.fastGetClass(internedName);
648 }
649
650 - /**
651 + /**
652 * Define a new class under the Object namespace. Roughly equivalent to
653 * rb_define_class in MRI.
654 *
655 @@ -677,7 +690,7 @@
656 return defineClassUnder(name, superClass, allocator, objectClass);
657 }
658
659 - /**
660 + /**
661 * A variation of defineClass that allows passing in an array of subplementary
662 * call sites for improving dynamic invocation performance.
663 *
664 @@ -694,7 +707,7 @@
665 /**
666 * Define a new class with the given name under the given module or class
667 * namespace. Roughly equivalent to rb_define_class_under in MRI.
668 - *
669 + *
670 * If the name specified is already bound, its value will be returned if:
671 * * It is a class
672 * * No new superclass is being defined
673 @@ -738,23 +751,23 @@
674 }
675 return klazz;
676 }
677 -
678 +
679 boolean parentIsObject = parent == objectClass;
680
681 if (superClass == null) {
682 - String className = parentIsObject ? name : parent.getName() + "::" + name;
683 + String className = parentIsObject ? name : parent.getName() + "::" + name;
684 warnings.warn(ID.NO_SUPER_CLASS, "no super class for `" + className + "', Object assumed", className);
685 -
686 +
687 superClass = objectClass;
688 }
689
690 return RubyClass.newClass(this, superClass, name, allocator, parent, !parentIsObject, callSites);
691 }
692
693 - /**
694 + /**
695 * Define a new module under the Object namespace. Roughly equivalent to
696 * rb_define_module in MRI.
697 - *
698 + *
699 * @param name The name of the new module
700 * @returns The new module
701 */
702 @@ -765,7 +778,7 @@
703 /**
704 * Define a new module with the given name under the given module or
705 * class namespace. Roughly equivalent to rb_define_module_under in MRI.
706 - *
707 + *
708 * @param name The name of the new module
709 * @param parent The class or module namespace under which to define the
710 * module
711 @@ -773,12 +786,12 @@
712 */
713 public RubyModule defineModuleUnder(String name, RubyModule parent) {
714 IRubyObject moduleObj = parent.getConstantAt(name);
715 -
716 +
717 boolean parentIsObject = parent == objectClass;
718
719 if (moduleObj != null ) {
720 if (moduleObj.isModule()) return (RubyModule)moduleObj;
721 -
722 +
723 if (parentIsObject) {
724 throw newTypeError(moduleObj.getMetaClass().getName() + " is not a module");
725 } else {
726 @@ -792,7 +805,7 @@
727 /**
728 * From Object, retrieve the named module. If it doesn't exist a
729 * new module is created.
730 - *
731 + *
732 * @param name The name of the module
733 * @returns The existing or new module
734 */
735 @@ -810,9 +823,9 @@
736 }
737
738
739 - /**
740 + /**
741 * Retrieve the current safe level.
742 - *
743 + *
744 * @see org.jruby.Ruby#setSaveLevel
745 */
746 public int getSafeLevel() {
747 @@ -820,15 +833,15 @@
748 }
749
750
751 - /**
752 + /**
753 * Set the current safe level:
754 - *
755 + *
756 * 0 - strings from streams/environment/ARGV are tainted (default)
757 * 1 - no dangerous operation by tainted value
758 * 2 - process/file operations prohibited
759 * 3 - all generated objects are tainted
760 * 4 - no global (non-tainted) variable modification/no direct output
761 - *
762 + *
763 * The safe level is set using $SAFE in Ruby code. It is not particularly
764 * well supported in JRuby.
765 */
766 @@ -877,7 +890,7 @@
767 public boolean isClassDefined(String name) {
768 return getModule(name) != null;
769 }
770 -
771 +
772 /**
773 * A ThreadFactory for when we're using pooled threads; we want to create
774 * the threads with daemon = true so they don't keep us from shutting down.
775 @@ -886,12 +899,12 @@
776 public Thread newThread(Runnable runnable) {
777 Thread thread = new Thread(runnable);
778 thread.setDaemon(true);
779 -
780 +
781 return thread;
782 }
783 }
784
785 - /**
786 + /**
787 * This method is called immediately after constructing the Ruby instance.
788 * The main thread is prepared for execution, all core classes and libraries
789 * are initialized, and any libraries required on the command line are
790 @@ -902,12 +915,12 @@
791 ThreadContext tc = getCurrentContext();
792
793 safeLevel = config.getSafeLevel();
794 -
795 +
796 // Construct key services
797 loadService = config.createLoadService(this);
798 posix = POSIXFactory.getPOSIX(new JRubyPOSIXHandler(this), RubyInstanceConfig.nativeEnabled);
799 javaSupport = new JavaSupport(this);
800 -
801 +
802 if (RubyInstanceConfig.POOLING_ENABLED) {
803 Executors.newCachedThreadPool();
804 executor = new ThreadPoolExecutor(
805 @@ -918,7 +931,7 @@
806 new SynchronousQueue<Runnable>(),
807 new DaemonThreadFactory());
808 }
809 -
810 +
811 // initialize the root of the class hierarchy completely
812 initRoot();
813
814 @@ -927,11 +940,11 @@
815
816 // Initialize all the core classes
817 bootstrap();
818 -
819 +
820 // Initialize the "dummy" class used as a marker
821 dummyClass = new RubyClass(this, classClass);
822 dummyClass.freeze(tc);
823 -
824 +
825 // Create global constants and variables
826 RubyGlobal.createGlobals(tc, this);
827
828 @@ -940,7 +953,7 @@
829
830 // initialize builtin libraries
831 initBuiltins();
832 -
833 +
834 // Require in all libraries specified on command line
835 for (String scriptName : config.requiredLibraries()) {
836 RubyKernel.require(getTopSelf(), newString(scriptName), Block.NULL_BLOCK);
837 @@ -969,8 +982,8 @@
838
839 RubyObject.createObjectClass(this, objectClass);
840 RubyModule.createModuleClass(this, moduleClass);
841 - RubyClass.createClassClass(this, classClass);
842 -
843 + RubyClass.createClassClass(classClass);
844 +
845 // set constants now that they're initialized
846 objectClass.setConstant("Object", objectClass);
847 objectClass.setConstant("Class", classClass);
848 @@ -1144,10 +1157,10 @@
849 scriptError = defineClassIfAllowed("ScriptError", exceptionClass);
850 rangeError = defineClassIfAllowed("RangeError", standardError);
851 signalException = defineClassIfAllowed("SignalException", exceptionClass);
852 -
853 +
854 if (profile.allowClass("NameError")) {
855 nameError = RubyNameError.createNameErrorClass(this, standardError);
856 - nameErrorMessage = RubyNameError.createNameErrorMessageClass(this, nameError);
857 + nameErrorMessage = RubyNameError.createNameErrorMessageClass(this, nameError);
858 }
859 if (profile.allowClass("NoMethodError")) {
860 noMethodError = RubyNoMethodError.createNoMethodErrorClass(this, nameError);
861 @@ -1185,14 +1198,14 @@
862
863 if (config.getCompatVersion() == CompatVersion.RUBY1_9) {
864 if (profile.allowClass("EncodingError")) {
865 - encodingError = defineClass("EncodingError", standardError, standardError.getAllocator());
866 + encodingError = defineClass("EncodingError", standardError, standardError.getAllocator());
867 encodingCompatibilityError = defineClassUnder("CompatibilityError", encodingError, encodingError.getAllocator(), encodingClass);
868 }
869 }
870
871 initErrno();
872 }
873 -
874 +
875 private RubyClass defineClassIfAllowed(String name, RubyClass superClass) {
876 // TODO: should probably apply the null object pattern for a
877 // non-allowed class, rather than null
878 @@ -1237,9 +1250,9 @@
879 private void initBuiltins() {
880 addLazyBuiltin("java.rb", "java", "org.jruby.javasupport.Java");
881 addLazyBuiltin("jruby.rb", "jruby", "org.jruby.libraries.JRubyLibrary");
882 -
883 +
884 addLazyBuiltin("minijava.rb", "minijava", "org.jruby.java.MiniJava");
885 -
886 +
887 addLazyBuiltin("jruby/ext.rb", "jruby/ext", "org.jruby.RubyJRuby$ExtLibrary");
888 addLazyBuiltin("jruby/core_ext.rb", "jruby/ext", "org.jruby.RubyJRuby$CoreExtLibrary");
889 addLazyBuiltin("jruby/type.rb", "jruby/type", "org.jruby.RubyJRuby$TypeLibrary");
890 @@ -1270,22 +1283,22 @@
891 if(RubyInstanceConfig.NATIVE_NET_PROTOCOL) {
892 addLazyBuiltin("net/protocol.rb", "net/protocol", "org.jruby.libraries.NetProtocolBufferedIOLibrary");
893 }
894 -
895 +
896 if (config.getCompatVersion() == CompatVersion.RUBY1_9) {
897 addLazyBuiltin("fiber.so", "fiber", "org.jruby.libraries.FiberLibrary");
898 }
899 -
900 +
901 addBuiltinIfAllowed("openssl.so", new Library() {
902 public void load(Ruby runtime, boolean wrap) throws IOException {
903 runtime.getLoadService().require("jruby/openssl/stub");
904 }
905 });
906 -
907 +
908 String[] builtins = {"fcntl", "yaml", "yaml/syck", "jsignal" };
909 for (String library : builtins) {
910 addBuiltinIfAllowed(library + ".rb", new BuiltinScript(library));
911 }
912 -
913 +
914 RubyKernel.autoload(topSelf, newSymbol("Java"), newString("java"));
915
916 if (config.getCompatVersion() == CompatVersion.RUBY1_9) {
917 @@ -1334,11 +1347,11 @@
918 public String getCurrentDirectory() {
919 return currentDirectory;
920 }
921 -
922 +
923 public RubyModule getEtc() {
924 return etcModule;
925 }
926 -
927 +
928 public void setEtc(RubyModule etcModule) {
929 this.etcModule = etcModule;
930 }
931 @@ -1354,14 +1367,14 @@
932 public RubyClass getClassClass() {
933 return classClass;
934 }
935 -
936 +
937 public RubyModule getKernel() {
938 return kernelModule;
939 }
940 void setKernel(RubyModule kernelModule) {
941 this.kernelModule = kernelModule;
942 }
943 -
944 +
945 public RubyClass getDummy() {
946 return dummyClass;
947 }
948 @@ -1371,14 +1384,14 @@
949 }
950 void setComparable(RubyModule comparableModule) {
951 this.comparableModule = comparableModule;
952 - }
953 + }
954
955 public RubyClass getNumeric() {
956 return numericClass;
957 }
958 void setNumeric(RubyClass numericClass) {
959 this.numericClass = numericClass;
960 - }
961 + }
962
963 public RubyClass getFloat() {
964 return floatClass;
965 @@ -1386,14 +1399,14 @@
966 void setFloat(RubyClass floatClass) {
967 this.floatClass = floatClass;
968 }
969 -
970 +
971 public RubyClass getInteger() {
972 return integerClass;
973 }
974 void setInteger(RubyClass integerClass) {
975 this.integerClass = integerClass;
976 - }
977 -
978 + }
979 +
980 public RubyClass getFixnum() {
981 return fixnumClass;
982 }
983 @@ -1452,7 +1465,7 @@
984
985 public RubyClass getArray() {
986 return arrayClass;
987 - }
988 + }
989 void setArray(RubyClass arrayClass) {
990 this.arrayClass = arrayClass;
991 }
992 @@ -1532,77 +1545,77 @@
993 }
994 void setMethod(RubyClass methodClass) {
995 this.methodClass = methodClass;
996 - }
997 + }
998
999 public RubyClass getUnboundMethod() {
1000 return unboundMethodClass;
1001 }
1002 void setUnboundMethod(RubyClass unboundMethodClass) {
1003 this.unboundMethodClass = unboundMethodClass;
1004 - }
1005 + }
1006
1007 public RubyClass getMatchData() {
1008 return matchDataClass;
1009 }
1010 void setMatchData(RubyClass matchDataClass) {
1011 this.matchDataClass = matchDataClass;
1012 - }
1013 + }
1014
1015 public RubyClass getRegexp() {
1016 return regexpClass;
1017 }
1018 void setRegexp(RubyClass regexpClass) {
1019 this.regexpClass = regexpClass;
1020 - }
1021 + }
1022
1023 public RubyClass getTime() {
1024 return timeClass;
1025 }
1026 void setTime(RubyClass timeClass) {
1027 this.timeClass = timeClass;
1028 - }
1029 + }
1030
1031 public RubyModule getMath() {
1032 return mathModule;
1033 }
1034 void setMath(RubyModule mathModule) {
1035 this.mathModule = mathModule;
1036 - }
1037 + }
1038
1039 public RubyModule getMarshal() {
1040 return marshalModule;
1041 }
1042 void setMarshal(RubyModule marshalModule) {
1043 this.marshalModule = marshalModule;
1044 - }
1045 + }
1046
1047 public RubyClass getBignum() {
1048 return bignumClass;
1049 }
1050 void setBignum(RubyClass bignumClass) {
1051 this.bignumClass = bignumClass;
1052 - }
1053 + }
1054
1055 public RubyClass getDir() {
1056 return dirClass;
1057 }
1058 void setDir(RubyClass dirClass) {
1059 this.dirClass = dirClass;
1060 - }
1061 + }
1062
1063 public RubyClass getFile() {
1064 return fileClass;
1065 }
1066 void setFile(RubyClass fileClass) {
1067 this.fileClass = fileClass;
1068 - }
1069 + }
1070
1071 public RubyClass getFileStat() {
1072 return fileStatClass;
1073 }
1074 void setFileStat(RubyClass fileStatClass) {
1075 this.fileStatClass = fileStatClass;
1076 - }
1077 + }
1078
1079 public RubyModule getFileTest() {
1080 return fileTestModule;
1081 @@ -1610,20 +1623,20 @@
1082 void setFileTest(RubyModule fileTestModule) {
1083 this.fileTestModule = fileTestModule;
1084 }
1085 -
1086 +
1087 public RubyClass getIO() {
1088 return ioClass;
1089 }
1090 void setIO(RubyClass ioClass) {
1091 this.ioClass = ioClass;
1092 - }
1093 + }
1094
1095 public RubyClass getThread() {
1096 return threadClass;
1097 }
1098 void setThread(RubyClass threadClass) {
1099 this.threadClass = threadClass;
1100 - }
1101 + }
1102
1103 public RubyClass getThreadGroup() {
1104 return threadGroupClass;
1105 @@ -1631,7 +1644,7 @@
1106 void setThreadGroup(RubyClass threadGroupClass) {
1107 this.threadGroupClass = threadGroupClass;
1108 }
1109 -
1110 +
1111 public RubyThreadGroup getDefaultThreadGroup() {
1112 return defaultThreadGroup;
1113 }
1114 @@ -1644,14 +1657,14 @@
1115 }
1116 void setContinuation(RubyClass continuationClass) {
1117 this.continuationClass = continuationClass;
1118 - }
1119 + }
1120
1121 public RubyClass getStructClass() {
1122 return structClass;
1123 }
1124 void setStructClass(RubyClass structClass) {
1125 this.structClass = structClass;
1126 - }
1127 + }
1128
1129 public IRubyObject getTmsStruct() {
1130 return tmsStruct;
1131 @@ -1659,7 +1672,7 @@
1132 void setTmsStruct(RubyClass tmsStruct) {
1133 this.tmsStruct = tmsStruct;
1134 }
1135 -
1136 +
1137 public IRubyObject getPasswdStruct() {
1138 return passwdStruct;
1139 }
1140 @@ -1679,43 +1692,43 @@
1141 }
1142 void setGC(RubyModule gcModule) {
1143 this.gcModule = gcModule;
1144 - }
1145 + }
1146
1147 public RubyModule getObjectSpaceModule() {
1148 return objectSpaceModule;
1149 }
1150 void setObjectSpaceModule(RubyModule objectSpaceModule) {
1151 this.objectSpaceModule = objectSpaceModule;
1152 - }
1153 + }
1154
1155 public RubyModule getProcess() {
1156 return processModule;
1157 }
1158 void setProcess(RubyModule processModule) {
1159 this.processModule = processModule;
1160 - }
1161 + }
1162
1163 public RubyClass getProcStatus() {
1164 - return procStatusClass;
1165 + return procStatusClass;
1166 }
1167 void setProcStatus(RubyClass procStatusClass) {
1168 this.procStatusClass = procStatusClass;
1169 }
1170 -
1171 +
1172 public RubyModule getProcUID() {
1173 return procUIDModule;
1174 }
1175 void setProcUID(RubyModule procUIDModule) {
1176 this.procUIDModule = procUIDModule;
1177 }
1178 -
1179 +
1180 public RubyModule getProcGID() {
1181 return procGIDModule;
1182 }
1183 void setProcGID(RubyModule procGIDModule) {
1184 this.procGIDModule = procGIDModule;
1185 }
1186 -
1187 +
1188 public RubyModule getProcSysModule() {
1189 return procSysModule;
1190 }
1191 @@ -1780,11 +1793,11 @@
1192 public RubyClass getFatal() {
1193 return fatal;
1194 }
1195 -
1196 +
1197 public RubyClass getInterrupt() {
1198 return interrupt;
1199 }
1200 -
1201 +
1202 public RubyClass getTypeError() {
1203 return typeError;
1204 }
1205 @@ -1796,7 +1809,7 @@
1206 public RubyClass getIndexError() {
1207 return indexError;
1208 }
1209 -
1210 +
1211 public RubyClass getSyntaxError() {
1212 return syntaxError;
1213 }
1214 @@ -1804,11 +1817,11 @@
1215 public RubyClass getStandardError() {
1216 return standardError;
1217 }
1218 -
1219 +
1220 public RubyClass getRuntimeError() {
1221 return runtimeError;
1222 }
1223 -
1224 +
1225 public RubyClass getIOError() {
1226 return ioError;
1227 }
1228 @@ -1909,31 +1922,23 @@
1229 if (loader == null) {
1230 loader = ClassLoader.getSystemClassLoader();
1231 }
1232 -
1233 +
1234 return loader;
1235 }
1236
1237 public synchronized JRubyClassLoader getJRubyClassLoader() {
1238 // FIXME: Get rid of laziness and handle restricted access elsewhere
1239 if (!Ruby.isSecurityRestricted() && jrubyClassLoader == null) {
1240 - jrubyClassLoader = new JRubyClassLoader(config.getLoader());
1241 + jrubyClassLoader = new RuntimeContainer(config.getLoader(), this);
1242 }
1243 -
1244 +
1245 return jrubyClassLoader;
1246 }
1247
1248 /** Defines a global variable
1249 */
1250 public void defineVariable(final GlobalVariable variable) {
1251 - globalVariables.define(variable.name(), new IAccessor() {
1252 - public IRubyObject getValue() {
1253 - return variable.get();
1254 - }
1255 -
1256 - public IRubyObject setValue(IRubyObject newValue) {
1257 - return variable.set(newValue);
1258 - }
1259 - });
1260 + globalVariables.define(variable.name(), new GlobalVariableAcessor(variable));
1261 }
1262
1263 /** defines a readonly global variable
1264 @@ -1942,7 +1947,7 @@
1265 public void defineReadonlyVariable(String name, IRubyObject value) {
1266 globalVariables.defineReadonly(name, new ValueAccessor(value));
1267 }
1268 -
1269 +
1270 public Node parseFile(InputStream in, String file, DynamicScope scope) {
1271 if (parserStats != null) parserStats.addLoadParse();
1272 return parser.parse(file, in, scope, new ParserConfiguration(0, false, false, true));
1273 @@ -1955,42 +1960,42 @@
1274
1275 public Node parseEval(String content, String file, DynamicScope scope, int lineNumber) {
1276 byte[] bytes;
1277 -
1278 +
1279 try {
1280 bytes = content.getBytes(KCode.NONE.getKCode());
1281 } catch (UnsupportedEncodingException e) {
1282 bytes = content.getBytes();
1283 }
1284 -
1285 +
1286 if (parserStats != null) parserStats.addEvalParse();
1287 - return parser.parse(file, new ByteArrayInputStream(bytes), scope,
1288 + return parser.parse(file, new ByteArrayInputStream(bytes), scope,
1289 new ParserConfiguration(lineNumber, false));
1290 }
1291
1292 @Deprecated
1293 - public Node parse(String content, String file, DynamicScope scope, int lineNumber,
1294 + public Node parse(String content, String file, DynamicScope scope, int lineNumber,
1295 boolean extraPositionInformation) {
1296 byte[] bytes;
1297 -
1298 +
1299 try {
1300 bytes = content.getBytes(KCode.NONE.getKCode());
1301 } catch (UnsupportedEncodingException e) {
1302 bytes = content.getBytes();
1303 }
1304
1305 - return parser.parse(file, new ByteArrayInputStream(bytes), scope,
1306 + return parser.parse(file, new ByteArrayInputStream(bytes), scope,
1307 new ParserConfiguration(lineNumber, extraPositionInformation, false));
1308 }
1309 -
1310 +
1311 public Node parseEval(ByteList content, String file, DynamicScope scope, int lineNumber) {
1312 if (parserStats != null) parserStats.addEvalParse();
1313 return parser.parse(file, content, scope, new ParserConfiguration(lineNumber, false));
1314 }
1315
1316 - public Node parse(ByteList content, String file, DynamicScope scope, int lineNumber,
1317 + public Node parse(ByteList content, String file, DynamicScope scope, int lineNumber,
1318 boolean extraPositionInformation) {
1319 if (parserStats != null) parserStats.addJRubyModuleParse();
1320 - return parser.parse(file, content, scope,
1321 + return parser.parse(file, content, scope,
1322 new ParserConfiguration(lineNumber, extraPositionInformation, false));
1323 }
1324
1325 @@ -2147,12 +2152,12 @@
1326 }
1327 }
1328 }
1329 -
1330 +
1331 public void loadFile(String scriptName, InputStream in, boolean wrap) {
1332 IRubyObject self = wrap ? TopSelfFactory.createTopSelf(this) : getTopSelf();
1333 ThreadContext context = getCurrentContext();
1334 String file = context.getFile();
1335 -
1336 +
1337 try {
1338 secure(4); /* should alter global state */
1339
1340 @@ -2167,20 +2172,20 @@
1341 context.setFile(file);
1342 }
1343 }
1344 -
1345 +
1346 public void compileAndLoadFile(String filename, InputStream in, boolean wrap) {
1347 IRubyObject self = wrap ? TopSelfFactory.createTopSelf(this) : getTopSelf();
1348 ThreadContext context = getCurrentContext();
1349 String file = context.getFile();
1350 -
1351 +
1352 try {
1353 secure(4); /* should alter global state */
1354
1355 context.setFile(filename);
1356 context.preNodeEval(objectClass, self, filename);
1357 -
1358 +
1359 Node scriptNode = parseFile(in, filename, null);
1360 -
1361 +
1362 Script script = tryCompile(scriptNode, new JRubyClassLoader(jrubyClassLoader));
1363 if (script == null) {
1364 System.err.println("Error, could not compile; pass -J-Djruby.jit.logging.verbose=true for more details");
1365 @@ -2203,7 +2208,7 @@
1366 secure(4); /* should alter global state */
1367
1368 context.preNodeEval(objectClass, self);
1369 -
1370 +
1371 script.load(context, self, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
1372 } catch (JumpException.ReturnJump rj) {
1373 return;
1374 @@ -2214,16 +2219,16 @@
1375
1376 public class CallTraceFuncHook extends EventHook {
1377 private RubyProc traceFunc;
1378 -
1379 +
1380 public void setTraceFunc(RubyProc traceFunc) {
1381 this.traceFunc = traceFunc;
1382 }
1383 -
1384 +
1385 public void eventHandler(ThreadContext context, String eventName, String file, int line, String name, IRubyObject type) {
1386 if (!context.isWithinTrace()) {
1387 if (file == null) file = "(ruby)";
1388 if (type == null) type = getFalse();
1389 -
1390 +
1391 RubyBinding binding = RubyBinding.newBinding(Ruby.this);
1392
1393 context.preTrace();
1394 @@ -2246,14 +2251,14 @@
1395 return true;
1396 }
1397 };
1398 -
1399 +
1400 private final CallTraceFuncHook callTraceFuncHook = new CallTraceFuncHook();
1401 -
1402 +
1403 public void addEventHook(EventHook hook) {
1404 eventHooks.add(hook);
1405 hasEventHooks = true;
1406 }
1407 -
1408 +
1409 public void removeEventHook(EventHook hook) {
1410 eventHooks.remove(hook);
1411 hasEventHooks = !eventHooks.isEmpty();
1412 @@ -2261,15 +2266,15 @@
1413
1414 public void setTraceFunction(RubyProc traceFunction) {
1415 removeEventHook(callTraceFuncHook);
1416 -
1417 +
1418 if (traceFunction == null) {
1419 return;
1420 }
1421 -
1422 +
1423 callTraceFuncHook.setTraceFunc(traceFunction);
1424 addEventHook(callTraceFuncHook);
1425 }
1426 -
1427 +
1428 public void callEventHooks(ThreadContext context, RubyEvent event, String file, int line, String name, IRubyObject type) {
1429 for (EventHook eventHook : eventHooks) {
1430 if (eventHook.isInterestedInEvent(event)) {
1431 @@ -2277,11 +2282,11 @@
1432 }
1433 }
1434 }
1435 -
1436 +
1437 public boolean hasEventHooks() {
1438 return hasEventHooks;
1439 }
1440 -
1441 +
1442 public GlobalVariables getGlobalVariables() {
1443 return globalVariables;
1444 }
1445 @@ -2325,7 +2330,7 @@
1446 finalizers.put(finalizer, null);
1447 }
1448 }
1449 -
1450 +
1451 public void removeInternalFinalizer(Finalizable finalizer) {
1452 synchronized (internalFinalizersMutex) {
1453 if (internalFinalizers != null) {
1454 @@ -2435,15 +2440,15 @@
1455 public RubyArray newArray(IRubyObject[] objects) {
1456 return RubyArray.newArray(this, objects);
1457 }
1458 -
1459 +
1460 public RubyArray newArrayNoCopy(IRubyObject[] objects) {
1461 return RubyArray.newArrayNoCopy(this, objects);
1462 }
1463 -
1464 +
1465 public RubyArray newArrayNoCopyLight(IRubyObject[] objects) {
1466 return RubyArray.newArrayNoCopyLight(this, objects);
1467 }
1468 -
1469 +
1470 public RubyArray newArray(List<IRubyObject> list) {
1471 return RubyArray.newArray(this, list);
1472 }
1473 @@ -2459,7 +2464,7 @@
1474 public RubyFileStat newFileStat(String filename, boolean lstat) {
1475 return RubyFileStat.newFileStat(this, filename, lstat);
1476 }
1477 -
1478 +
1479 public RubyFileStat newFileStat(FileDescriptor descriptor) {
1480 return RubyFileStat.newFileStat(this, descriptor);
1481 }
1482 @@ -2514,7 +2519,7 @@
1483 public RubyString newString(String string) {
1484 return RubyString.newString(this, string);
1485 }
1486 -
1487 +
1488 public RubyString newString(ByteList byteList) {
1489 return RubyString.newString(this, byteList);
1490 }
1491 @@ -2522,7 +2527,7 @@
1492 @Deprecated
1493 public RubyString newStringShared(ByteList byteList) {
1494 return RubyString.newStringShared(this, byteList);
1495 - }
1496 + }
1497
1498 public RubySymbol newSymbol(String name) {
1499 return symbolTable.getSymbol(name);
1500 @@ -2533,7 +2538,7 @@
1501 * name String. Don't intern your string just to call this version - the
1502 * overhead of interning will more than wipe out any benefit from the faster
1503 * lookup.
1504 - *
1505 + *
1506 * @param internedName the symbol name, <em>must</em> be interned! if in
1507 * doubt, call {@link #newSymbol(String)} instead.
1508 * @return the symbol for name
1509 @@ -2550,8 +2555,8 @@
1510
1511 public RaiseException newRuntimeError(String message) {
1512 return newRaiseException(getRuntimeError(), message);
1513 - }
1514 -
1515 + }
1516 +
1517 public RaiseException newArgumentError(String message) {
1518 return newRaiseException(getArgumentError(), message);
1519 }
1520 @@ -2635,14 +2640,14 @@
1521 public RaiseException newErrnoEEXISTError(String message) {
1522 return newRaiseException(getErrno().fastGetClass("EEXIST"), message);
1523 }
1524 -
1525 +
1526 public RaiseException newErrnoEDOMError(String message) {
1527 return newRaiseException(getErrno().fastGetClass("EDOM"), "Domain error - " + message);
1528 - }
1529 -
1530 + }
1531 +
1532 public RaiseException newErrnoECHILDError() {
1533 return newRaiseException(getErrno().fastGetClass("ECHILD"), "No child processes");
1534 - }
1535 + }
1536
1537 public RaiseException newIndexError(String message) {
1538 return newRaiseException(getIndexError(), message);
1539 @@ -2683,7 +2688,7 @@
1540 public RaiseException newNotImplementedError(String message) {
1541 return newRaiseException(getNotImplementedError(), message);
1542 }
1543 -
1544 +
1545 public RaiseException newInvalidEncoding(String message) {
1546 return newRaiseException(fastGetClass("Iconv").fastGetClass("InvalidEncoding"), message);
1547 }
1548 @@ -2803,6 +2808,14 @@
1549 return stackTraces;
1550 }
1551
1552 + public IRubyObject getRuntimeVariable(String name) {
1553 + return this.runtimeVariables.get(name);
1554 + }
1555 +
1556 + public void setRuntimeVariable(String name, IRubyObject value) {
1557 + this.runtimeVariables.put(name, value);
1558 + }
1559 +
1560 public void setRandomSeed(long randomSeed) {
1561 this.randomSeed = randomSeed;
1562 }
1563 @@ -2919,27 +2932,27 @@
1564 public static boolean isSecurityRestricted() {
1565 return securityRestricted;
1566 }
1567 -
1568 +
1569 public static void setSecurityRestricted(boolean restricted) {
1570 securityRestricted = restricted;
1571 }
1572 -
1573 +
1574 public POSIX getPosix() {
1575 return posix;
1576 }
1577 -
1578 +
1579 public void setRecordSeparatorVar(GlobalVariable recordSeparatorVar) {
1580 this.recordSeparatorVar = recordSeparatorVar;
1581 }
1582 -
1583 +
1584 public GlobalVariable getRecordSeparatorVar() {
1585 return recordSeparatorVar;
1586 }
1587 -
1588 +
1589 public Set<Script> getJittedMethods() {
1590 return jittedMethods;
1591 }
1592 -
1593 +
1594 public ExecutorService getExecutor() {
1595 return executor;
1596 }
1597 @@ -2958,7 +2971,7 @@
1598
1599 private volatile int constantGeneration = 1;
1600 private final ThreadService threadService;
1601 -
1602 +
1603 private POSIX posix;
1604
1605 private int stackTraces = 0;
1606 @@ -2972,17 +2985,17 @@
1607 private Random random = new Random();
1608
1609 private List<EventHook> eventHooks = new Vector<EventHook>();
1610 - private boolean hasEventHooks;
1611 + private boolean hasEventHooks;
1612 private boolean globalAbortOnExceptionEnabled = false;
1613 private boolean doNotReverseLookupEnabled = false;
1614 private volatile boolean objectSpaceEnabled;
1615 -
1616 +
1617 private final Set<Script> jittedMethods = Collections.synchronizedSet(new WeakHashSet<Script>());
1618 -
1619 +
1620 private static ThreadLocal<Ruby> currentRuntime = new ThreadLocal<Ruby>();
1621 -
1622 +
1623 private long globalState = 1;
1624 -
1625 +
1626 private int safeLevel = -1;
1627
1628 // Default objects
1629 @@ -2994,7 +3007,7 @@
1630
1631 private IRubyObject verbose;
1632 private IRubyObject debug;
1633 -
1634 +
1635 private RubyThreadGroup defaultThreadGroup;
1636
1637 /**
1638 @@ -3029,7 +3042,7 @@
1639 marshalModule, etcModule, fileTestModule, gcModule,
1640 objectSpaceModule, processModule, procUIDModule, procGIDModule,
1641 procSysModule, precisionModule, errnoModule;
1642 -
1643 +
1644 // record separator var, to speed up io ops that use it
1645 private GlobalVariable recordSeparatorVar;
1646
1647 @@ -3047,13 +3060,13 @@
1648 // Java support
1649 private JavaSupport javaSupport;
1650 private JRubyClassLoader jrubyClassLoader;
1651 -
1652 +
1653 // Management/monitoring
1654 private BeanManager beanManager;
1655
1656 // Parser stats
1657 private ParserStats parserStats;
1658 -
1659 +
1660 // Compilation
1661 private final JITCompiler jitCompiler;
1662
1663 @@ -3081,7 +3094,8 @@
1664
1665 private LoadService loadService;
1666 private EncodingService encodingService;
1667 - private GlobalVariables globalVariables = new GlobalVariables(this);
1668 + private GlobalVariables globalVariables = new GlobalVariables();
1669 + private Map<String, IRubyObject> runtimeVariables = new ConcurrentHashMap<String, IRubyObject>();
1670 private RubyWarnings warnings = new RubyWarnings(this);
1671
1672 // Contains a list of all blocks (as Procs) that should be called when
1673 @@ -3105,7 +3119,7 @@
1674 * weakly referenced, to be executed on tearDown.
1675 */
1676 private Map<Finalizable, Object> finalizers;
1677 -
1678 +
1679 /**
1680 * A list of JRuby-internal finalizers, weakly referenced,
1681 * to be executed on tearDown.
1682 @@ -3117,7 +3131,8 @@
1683
1684 // mutex that controls modifications of internal finalizers
1685 private final Object internalFinalizersMutex = new Object();
1686 -
1687 +
1688 // A thread pool to use for executing this runtime's Ruby threads
1689 private ExecutorService executor;
1690 +
1691 }
1692 Index: src/org/jruby/RubyModule.java
1693 ===================================================================
1694 --- src/org/jruby/RubyModule.java (revision 8091)
1695 +++ src/org/jruby/RubyModule.java (working copy)
1696 @@ -190,13 +190,16 @@
1697 private final Map<String, CacheEntry> cachedMethods = new ConcurrentHashMap<String, CacheEntry>(12, 0.75f, 1);
1698
1699 protected static class Generation {
1700 - public volatile int hash;
1701 + private volatile int hash;
1702 public Generation() {
1703 hash = hashCode();
1704 }
1705 public synchronized void update() {
1706 hash = hash + (hashCode() * 31);
1707 }
1708 + public int hash() {
1709 + return hash;
1710 + }
1711 }
1712 protected final Generation generation;
1713
1714 @@ -946,7 +949,7 @@
1715 }
1716
1717 public final int getSerialNumber() {
1718 - return generation.hash;
1719 + return generation.hash();
1720 }
1721
1722 private CacheEntry cacheHit(String name) {
1723 Index: src/org/jruby/util/RuntimeContainer.java
1724 ===================================================================
1725 --- src/org/jruby/util/RuntimeContainer.java (revision 0)
1726 +++ src/org/jruby/util/RuntimeContainer.java (revision 0)
1727 @@ -0,0 +1,19 @@
1728 +package org.jruby.util;
1729 +
1730 +import org.jruby.Ruby;
1731 +
1732 +/**
1733 + * @author Fabio Kung
1734 + */
1735 +public class RuntimeContainer extends JRubyClassLoader {
1736 + private final Ruby runtime;
1737 +
1738 + public RuntimeContainer(ClassLoader parent, Ruby runtime) {
1739 + super(parent);
1740 + this.runtime = runtime;
1741 + }
1742 +
1743 + public Ruby getRuntime() {
1744 + return runtime;
1745 + }
1746 +}
1747 Index: src/org/jruby/util/io/ChannelDescriptor.java
1748 ===================================================================
1749 --- src/org/jruby/util/io/ChannelDescriptor.java (revision 8091)
1750 +++ src/org/jruby/util/io/ChannelDescriptor.java (working copy)
1751 @@ -94,13 +94,6 @@
1752 private AtomicInteger refCounter;
1753
1754 /**
1755 - * Used to work-around blocking problems with STDIN. In most cases <code>null</code>.
1756 - * See {@link #ChannelDescriptor(InputStream, int, ModeFlags, FileDescriptor)}
1757 - * for more details. You probably should not use it.
1758 - */
1759 - private InputStream baseInputStream;
1760 -
1761 - /**
1762 * Process streams get Channel.newChannel()ed into FileChannel but are not actually
1763 * seekable. So instead of just the isSeekable check doing instanceof FileChannel,
1764 * we must also add this boolean to check, which we set to false when it's known
1765 @@ -148,28 +141,6 @@
1766 }
1767
1768 /**
1769 - * Special constructor to create the ChannelDescriptor out of the stream, file number,
1770 - * mode flags, and file descriptor object. The channel will be created from the
1771 - * provided stream. The channel will be kept open until all ChannelDescriptor
1772 - * references to it have been closed. <b>Note:</b> in most cases, you should not
1773 - * use this constructor, it's reserved mostly for STDIN.
1774 - *
1775 - * @param baseInputStream The stream to create the channel for the new descriptor
1776 - * @param fileno The file number for the new descriptor
1777 - * @param originalModes The mode flags for the new descriptor
1778 - * @param fileDescriptor The java.io.FileDescriptor object for the new descriptor
1779 - */
1780 - public ChannelDescriptor(InputStream baseInputStream, int fileno, ModeFlags originalModes, FileDescriptor fileDescriptor) {
1781 - // The reason why we need the stream is to be able to invoke available() on it.
1782 - // STDIN in Java is non-interruptible, non-selectable, and attempt to read
1783 - // on such stream might lead to thread being blocked without *any* way to unblock it.
1784 - // That's where available() comes it, so at least we could check whether
1785 - // anything is available to be read without blocking.
1786 - this(Channels.newChannel(baseInputStream), fileno, originalModes, fileDescriptor, new AtomicInteger(1), true);
1787 - this.baseInputStream = baseInputStream;
1788 - }
1789 -
1790 - /**
1791 * Construct a new ChannelDescriptor with the given channel, file number,
1792 * and file descriptor object. The channel will be kept open until all ChannelDescriptor
1793 * references to it have been closed. The channel's capabilities will be used
1794 @@ -217,30 +188,20 @@
1795 }
1796
1797 /**
1798 - * This is intentionally non-public, since it should not be really
1799 - * used outside of very limited use case (handling of STDIN).
1800 - * See {@link #ChannelDescriptor(InputStream, int, ModeFlags, FileDescriptor)}
1801 - * for more info.
1802 - */
1803 - /*package-protected*/ InputStream getBaseInputStream() {
1804 - return baseInputStream;
1805 - }
1806 -
1807 - /**
1808 * Whether the channel associated with this descriptor is seekable (i.e.
1809 * whether it is instanceof FileChannel).
1810 *
1811 * @return true if the associated channel is seekable, false otherwise
1812 */
1813 public boolean isSeekable() {
1814 - return canBeSeekable && channel instanceof FileChannel;
1815 + return canBeSeekable && getChannel() instanceof FileChannel;
1816 }
1817
1818 /**
1819 * Set the channel to be explicitly seekable or not, for streams that appear
1820 * to be seekable with the instanceof FileChannel check.
1821 *
1822 - * @param seekable Whether the channel is seekable or not.
1823 + * @param canBeSeekable Whether the channel is seekable or not.
1824 */
1825 public void setCanBeSeekable(boolean canBeSeekable) {
1826 this.canBeSeekable = canBeSeekable;
1827 @@ -251,7 +212,7 @@
1828 * for which many operations are simply noops.
1829 */
1830 public boolean isNull() {
1831 - return channel instanceof NullChannel;
1832 + return getChannel() instanceof NullChannel;
1833 }
1834
1835 /**
1836 @@ -261,7 +222,7 @@
1837 * @return true if the associated channel is writable, false otherwise
1838 */
1839 public boolean isWritable() {
1840 - return channel instanceof WritableByteChannel;
1841 + return getChannel() instanceof WritableByteChannel;
1842 }
1843
1844 /**
1845 @@ -270,7 +231,7 @@
1846 * @return true if the associated channel is open, false otherwise
1847 */
1848 public boolean isOpen() {
1849 - return channel.isOpen();
1850 + return getChannel().isOpen();
1851 }
1852
1853 /**
1854 @@ -321,7 +282,7 @@
1855
1856 if (DEBUG) getLogger("ChannelDescriptor").info("Reopen fileno " + newFileno + ", refs now: " + refCounter.get());
1857
1858 - return new ChannelDescriptor(channel, newFileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
1859 + return new ChannelDescriptor(getChannel(), newFileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
1860 }
1861 }
1862
1863 @@ -338,7 +299,7 @@
1864
1865 if (DEBUG) getLogger("ChannelDescriptor").info("Reopen fileno " + fileno + ", refs now: " + refCounter.get());
1866
1867 - return new ChannelDescriptor(channel, fileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
1868 + return new ChannelDescriptor(getChannel(), fileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
1869 }
1870 }
1871
1872 @@ -386,10 +347,10 @@
1873 * @return the new offset into the FileChannel.
1874 */
1875 public long lseek(long offset, int whence) throws IOException, InvalidValueException, PipeException, BadDescriptorException {
1876 - if (channel instanceof FileChannel) {
1877 + if (getChannel() instanceof FileChannel) {
1878 checkOpen();
1879
1880 - FileChannel fileChannel = (FileChannel)channel;
1881 + FileChannel fileChannel = (FileChannel)getChannel();
1882 try {
1883 long pos;
1884 switch (whence) {
1885 @@ -459,7 +420,7 @@
1886 public int read(ByteBuffer buffer) throws IOException, BadDescriptorException {
1887 checkOpen();
1888
1889 - ReadableByteChannel readChannel = (ReadableByteChannel) channel;
1890 + ReadableByteChannel readChannel = (ReadableByteChannel) getChannel();
1891 int bytesRead = 0;
1892 bytesRead = readChannel.read(buffer);
1893
1894 @@ -478,10 +439,10 @@
1895 public int internalWrite(ByteBuffer buffer) throws IOException, BadDescriptorException {
1896 checkOpen();
1897
1898 - WritableByteChannel writeChannel = (WritableByteChannel)channel;
1899 + WritableByteChannel writeChannel = (WritableByteChannel)getChannel();
1900
1901 if (isSeekable() && originalModes.isAppendable()) {
1902 - FileChannel fileChannel = (FileChannel)channel;
1903 + FileChannel fileChannel = (FileChannel)getChannel();
1904 fileChannel.position(fileChannel.size());
1905 }
1906
1907 @@ -677,7 +638,7 @@
1908 }
1909
1910 // if channel is already closed, we're no longer valid
1911 - if (!channel.isOpen()) {
1912 + if (!getChannel().isOpen()) {
1913 throw new BadDescriptorException();
1914 }
1915
1916 @@ -687,7 +648,7 @@
1917 if (DEBUG) getLogger("ChannelDescriptor").info("Descriptor for fileno " + fileno + " refs: " + count);
1918
1919 if (count <= 0) {
1920 - channel.close();
1921 + getChannel().close();
1922 }
1923 }
1924 }
1925 Index: src/org/jruby/util/io/ChannelStream.java
1926 ===================================================================
1927 --- src/org/jruby/util/io/ChannelStream.java (revision 8091)
1928 +++ src/org/jruby/util/io/ChannelStream.java (working copy)
1929 @@ -87,10 +87,9 @@
1930 private final static int BULK_READ_SIZE = 16 * 1024;
1931 private final static ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
1932
1933 - private Ruby runtime;
1934 protected ModeFlags modes;
1935 protected boolean sync = false;
1936 -
1937 +
1938 protected volatile ByteBuffer buffer; // r/w buffer
1939 protected boolean reading; // are we reading or writing?
1940 private ChannelDescriptor descriptor;
1941 @@ -100,25 +99,23 @@
1942
1943 private boolean eof = false;
1944
1945 - public ChannelStream(Ruby runtime, ChannelDescriptor descriptor, ModeFlags modes, FileDescriptor fileDescriptor) throws InvalidValueException {
1946 + public ChannelStream(ChannelDescriptor descriptor, ModeFlags modes, FileDescriptor fileDescriptor) throws InvalidValueException {
1947 descriptor.checkNewModes(modes);
1948 -
1949 - this.runtime = runtime;
1950 +
1951 this.descriptor = descriptor;
1952 this.modes = modes;
1953 this.buffer = ByteBuffer.allocate(BUFSIZE);
1954 buffer.flip();
1955 this.reading = true;
1956 -
1957 +
1958 // this constructor is used by fdopen, so we don't increment descriptor ref count
1959 }
1960
1961 - public ChannelStream(Ruby runtime, ChannelDescriptor descriptor) {
1962 - this(runtime, descriptor, descriptor.getFileDescriptor());
1963 + public ChannelStream(ChannelDescriptor descriptor) {
1964 + this(descriptor, descriptor.getFileDescriptor());
1965 }
1966
1967 - public ChannelStream(Ruby runtime, ChannelDescriptor descriptor, FileDescriptor fileDescriptor) {
1968 - this.runtime = runtime;
1969 + public ChannelStream(ChannelDescriptor descriptor, FileDescriptor fileDescriptor) {
1970 this.descriptor = descriptor;
1971 this.modes = descriptor.getOriginalModes();
1972 buffer = ByteBuffer.allocate(BUFSIZE);
1973 @@ -126,10 +123,9 @@
1974 this.reading = true;
1975 }
1976
1977 - public ChannelStream(Ruby runtime, ChannelDescriptor descriptor, ModeFlags modes) throws InvalidValueException {
1978 + public ChannelStream(ChannelDescriptor descriptor, ModeFlags modes) throws InvalidValueException {
1979 descriptor.checkNewModes(modes);
1980 -
1981 - this.runtime = runtime;
1982 +
1983 this.descriptor = descriptor;
1984 this.modes = modes;
1985 buffer = ByteBuffer.allocate(BUFSIZE);
1986 @@ -138,9 +134,9 @@
1987 }
1988
1989 public Ruby getRuntime() {
1990 - return runtime;
1991 + return Ruby.getCurrentRuntime();
1992 }
1993 -
1994 +
1995 public void checkReadable() throws IOException {
1996 if (!modes.isReadable()) throw new IOException("not opened for reading");
1997 }
1998 @@ -152,11 +148,11 @@
1999 public void checkPermissionsSubsetOf(ModeFlags subsetModes) {
2000 subsetModes.isSubsetOf(modes);
2001 }
2002 -
2003 +
2004 public ModeFlags getModes() {
2005 return modes;
2006 }
2007 -
2008 +
2009 public boolean isSync() {
2010 return sync;
2011 }
2012 @@ -176,11 +172,11 @@
2013 Thread.sleep(10);
2014 }
2015 }
2016 -
2017 +
2018 public boolean readDataBuffered() {
2019 return reading && buffer.hasRemaining();
2020 }
2021 -
2022 +
2023 public boolean writeDataBuffered() {
2024 return !reading && buffer.position() > 0;
2025 }
2026 @@ -202,22 +198,22 @@
2027 PARAGRAPH_SEPARATOR : separatorString;
2028
2029 descriptor.checkOpen();
2030 -
2031 +
2032 if (feof()) {
2033 return null;
2034 }
2035 -
2036 +
2037 int c = read();
2038 -
2039 +
2040 if (c == -1) {
2041 return null;
2042 }
2043 -
2044 +
2045 // unread back
2046 buffer.position(buffer.position() - 1);
2047
2048 ByteList buf = new ByteList(40);
2049 -
2050 +
2051 byte first = separator.bytes[separator.begin];
2052
2053 LineLoop : while (true) {
2054 @@ -225,7 +221,7 @@
2055 byte[] bytes = buffer.array();
2056 int offset = buffer.position();
2057 int max = buffer.limit();
2058 -
2059 +
2060 // iterate over remainder of buffer until we find a match
2061 for (int i = offset; i < max; i++) {
2062 c = bytes[i];
2063 @@ -240,13 +236,13 @@
2064 break ReadLoop;
2065 }
2066 }
2067 -
2068 +
2069 // no match, append remainder of buffer and continue with next block
2070 buf.append(bytes, offset, buffer.remaining());
2071 int read = refillBuffer();
2072 if (read == -1) break LineLoop;
2073 }
2074 -
2075 +
2076 // found a match above, check if remaining separator characters match, appending as we go
2077 for (int i = 0; i < separator.realSize; i++) {
2078 if (c == -1) {
2079 @@ -272,7 +268,7 @@
2080
2081 return buf;
2082 }
2083 -
2084 +
2085 /**
2086 * An version of read that reads all bytes up to and including a terminator byte.
2087 * <p>
2088 @@ -282,7 +278,7 @@
2089 * @param dst The output buffer.
2090 * @param terminator The byte to terminate reading.
2091 * @return The number of bytes read, or -1 if EOF is reached.
2092 - *
2093 + *
2094 * @throws java.io.IOException
2095 * @throws org.jruby.util.io.BadDescriptorException
2096 */
2097 @@ -290,7 +286,7 @@
2098 checkReadable();
2099 ensureRead();
2100 descriptor.checkOpen();
2101 -
2102 +
2103 int totalRead = 0;
2104 boolean found = false;
2105 if (ungotc != -1) {
2106 @@ -324,7 +320,7 @@
2107 }
2108 return totalRead;
2109 }
2110 -
2111 +
2112 public synchronized ByteList readall() throws IOException, BadDescriptorException {
2113 if (descriptor.isSeekable()) {
2114 invalidateBuffer();
2115 @@ -336,7 +332,7 @@
2116 }
2117 left += ungotc != -1 ? 1 : 0;
2118 ByteList result = new ByteList((int) left);
2119 - ByteBuffer buf = ByteBuffer.wrap(result.unsafeBytes(),
2120 + ByteBuffer buf = ByteBuffer.wrap(result.unsafeBytes(),
2121 result.begin(), (int) left);
2122 if (ungotc != -1) {
2123 buf.put((byte) ungotc);
2124 @@ -358,7 +354,7 @@
2125
2126 ByteList byteList = new ByteList();
2127 ByteList read = fread(BUFSIZE);
2128 -
2129 +
2130 if (read == null) {
2131 eof = true;
2132 return byteList;
2133 @@ -370,14 +366,14 @@
2134 }
2135
2136 return byteList;
2137 - }
2138 + }
2139 }
2140 -
2141 +
2142 /**
2143 * <p>Close IO handler resources.</p>
2144 - * @throws IOException
2145 - * @throws BadDescriptorException
2146 - *
2147 + * @throws IOException
2148 + * @throws BadDescriptorException
2149 + *
2150 * @see org.jruby.util.IOHandler#close()
2151 */
2152 public synchronized void fclose() throws IOException, BadDescriptorException {
2153 @@ -408,7 +404,7 @@
2154 /**
2155 * Internal close, to safely work for finalizing.
2156 * @param finalizing true if this is in a finalizing context
2157 - * @throws IOException
2158 + * @throws IOException
2159 * @throws BadDescriptorException
2160 */
2161 private void closeForFinalize() {
2162 @@ -422,8 +418,8 @@
2163 }
2164
2165 /**
2166 - * @throws IOException
2167 - * @throws BadDescriptorException
2168 + * @throws IOException
2169 + * @throws BadDescriptorException
2170 * @see org.jruby.util.IOHandler#flush()
2171 */
2172 public synchronized int fflush() throws IOException, BadDescriptorException {
2173 @@ -435,14 +431,14 @@
2174 }
2175 return 0;
2176 }
2177 -
2178 +
2179 /**
2180 * Flush the write buffer to the channel (if needed)
2181 * @throws IOException
2182 */
2183 private void flushWrite() throws IOException, BadDescriptorException {
2184 if (reading || !modes.isWritable() || buffer.position() == 0) return; // Don't bother
2185 -
2186 +
2187 int len = buffer.position();
2188 buffer.flip();
2189 int n = descriptor.write(buffer);
2190 @@ -452,7 +448,7 @@
2191 }
2192 buffer.clear();
2193 }
2194 -
2195 +
2196 /**
2197 * Flush the write buffer to the channel (if needed)
2198 * @throws IOException
2199 @@ -494,12 +490,7 @@
2200 * @see org.jruby.util.IOHandler#getInputStream()
2201 */
2202 public InputStream newInputStream() {
2203 - InputStream in = descriptor.getBaseInputStream();
2204 - if (in == null) {
2205 - return new BufferedInputStream(Channels.newInputStream((ReadableByteChannel)descriptor.getChannel()));
2206 - } else {
2207 - return in;
2208 - }
2209 + return new BufferedInputStream(Channels.newInputStream((ReadableByteChannel) descriptor.getChannel()));
2210 }
2211
2212 /**
2213 @@ -508,28 +499,28 @@
2214 public OutputStream newOutputStream() {
2215 return new BufferedOutputStream(Channels.newOutputStream((WritableByteChannel)descriptor.getChannel()));
2216 }
2217 -
2218 +
2219 public void clearerr() {
2220 eof = false;
2221 }
2222 -
2223 +
2224 /**
2225 - * @throws IOException
2226 - * @throws BadDescriptorException
2227 + * @throws IOException
2228 + * @throws BadDescriptorException
2229 * @see org.jruby.util.IOHandler#isEOF()
2230 */
2231 public boolean feof() throws IOException, BadDescriptorException {
2232 checkReadable();
2233 -
2234 +
2235 if (eof) {
2236 return true;
2237 } else {
2238 return false;
2239 }
2240 }
2241 -
2242 +
2243 /**
2244 - * @throws IOException
2245 + * @throws IOException
2246 * @see org.jruby.util.IOHandler#pos()
2247 */
2248 public synchronized long fgetpos() throws IOException, PipeException, InvalidValueException, BadDescriptorException {
2249 @@ -550,14 +541,14 @@
2250 throw new PipeException();
2251 }
2252 }
2253 -
2254 +
2255 /**
2256 * Implementation of libc "lseek", which seeks on seekable streams, raises
2257 * EPIPE if the fd is assocated with a pipe, socket, or FIFO, and doesn't
2258 * do anything for other cases (like stdio).
2259 - *
2260 - * @throws IOException
2261 - * @throws InvalidValueException
2262 + *
2263 + * @throws IOException
2264 + * @throws InvalidValueException
2265 * @see org.jruby.util.IOHandler#seek(long, int)
2266 */
2267 public synchronized void lseek(long offset, int type) throws IOException, InvalidValueException, PipeException, BadDescriptorException {
2268 @@ -636,7 +627,7 @@
2269 reading = true;
2270 }
2271 }
2272 -
2273 +
2274 private void resetForWrite() throws IOException {
2275 if (descriptor.isSeekable()) {
2276 FileChannel fileChannel = (FileChannel)descriptor.getChannel();
2277 @@ -648,7 +639,7 @@
2278 buffer.clear();
2279 reading = false;
2280 }
2281 -
2282 +
2283 /**
2284 * Ensure buffer is ready for writing.
2285 * @throws IOException
2286 @@ -661,25 +652,25 @@
2287 public synchronized ByteList read(int number) throws IOException, BadDescriptorException {
2288 checkReadable();
2289 ensureReadNonBuffered();
2290 -
2291 +
2292 ByteList byteList = new ByteList(number);
2293 -
2294 +
2295 // TODO this should entry into error handling somewhere
2296 int bytesRead = descriptor.read(number, byteList);
2297 -
2298 +
2299 if (bytesRead == -1) {
2300 eof = true;
2301 }
2302 -
2303 +
2304 return byteList;
2305 }
2306
2307 private ByteList bufferedRead(int number) throws IOException, BadDescriptorException {
2308 checkReadable();
2309 ensureRead();
2310 -
2311 +
2312 ByteList result = new ByteList(0);
2313 -
2314 +
2315 int len = -1;
2316 if (buffer.hasRemaining()) { // already have some bytes buffered
2317 len = (number <= buffer.remaining()) ? number : buffer.remaining();
2318 @@ -704,26 +695,26 @@
2319 break;
2320 }
2321 }
2322 -
2323 +
2324 //
2325 // Complete the request by filling the read buffer first
2326 //
2327 while (!done && result.length() != number) {
2328 int read = refillBuffer();
2329 -
2330 +
2331 if (read == -1) {
2332 eof = true;
2333 break;
2334 } else if (read == 0) {
2335 break;
2336 }
2337 -
2338 +
2339 // append what we read into our buffer and allow the loop to continue
2340 int desired = number - result.length();
2341 len = (desired < read) ? desired : read;
2342 result.append(buffer, len);
2343 }
2344 -
2345 +
2346 if (result.length() == 0 && number != 0) {
2347 if (eof) {
2348 throw new EOFException();
2349 @@ -731,10 +722,10 @@
2350 }
2351 return result;
2352 }
2353 -
2354 +
2355 private int bufferedRead() throws IOException, BadDescriptorException {
2356 ensureRead();
2357 -
2358 +
2359 if (!buffer.hasRemaining()) {
2360 int len = refillBuffer();
2361 if (len == -1) {
2362 @@ -746,42 +737,42 @@
2363 }
2364 return buffer.get() & 0xFF;
2365 }
2366 -
2367 +
2368 /**
2369 - * @throws IOException
2370 - * @throws BadDescriptorException
2371 + * @throws IOException
2372 + * @throws BadDescriptorException
2373 * @see org.jruby.util.IOHandler#syswrite(String buf)
2374 */
2375 private int bufferedWrite(ByteList buf) throws IOException, BadDescriptorException {
2376 getRuntime().secure(4);
2377 checkWritable();
2378 ensureWrite();
2379 -
2380 +
2381 // Ruby ignores empty syswrites
2382 if (buf == null || buf.length() == 0) return 0;
2383 -
2384 +
2385 if (buf.length() > buffer.capacity()) { // Doesn't fit in buffer. Write immediately.
2386 flushWrite(); // ensure nothing left to write
2387 -
2388
2389 +
2390 int n = descriptor.write(ByteBuffer.wrap(buf.unsafeBytes(), buf.begin(), buf.length()));
2391 if(n != buf.length()) {
2392 // TODO: check the return value here
2393 }
2394 } else {
2395 if (buf.length() > buffer.remaining()) flushWrite();
2396 -
2397 +
2398 buffer.put(buf.unsafeBytes(), buf.begin(), buf.length());
2399 }
2400 -
2401 +
2402 if (isSync()) sync();
2403 -
2404 +
2405 return buf.realSize;
2406 }
2407 -
2408 +
2409 /**
2410 - * @throws IOException
2411 - * @throws BadDescriptorException
2412 + * @throws IOException
2413 + * @throws BadDescriptorException
2414 * @see org.jruby.util.IOHandler#syswrite(String buf)
2415 */
2416 private int bufferedWrite(int c) throws IOException, BadDescriptorException {
2417 @@ -790,14 +781,14 @@
2418 ensureWrite();
2419
2420 if (!buffer.hasRemaining()) flushWrite();
2421 -
2422 +
2423 buffer.put((byte) c);
2424 -
2425 +
2426 if (isSync()) sync();
2427 -
2428 +
2429 return 1;
2430 }
2431 -
2432 +
2433 public synchronized void ftruncate(long newLength) throws IOException,
2434 BadDescriptorException, InvalidValueException {
2435 Channel ch = descriptor.getChannel();
2436 @@ -810,20 +801,20 @@
2437 // truncate can't lengthen files, so we save position, seek/write, and go back
2438 long position = fileChannel.position();
2439 int difference = (int)(newLength - fileChannel.size());
2440 -
2441 +
2442 fileChannel.position(fileChannel.size());
2443 // FIXME: This worries me a bit, since it could allocate a lot with a large newLength
2444 fileChannel.write(ByteBuffer.allocate(difference));
2445 fileChannel.position(position);
2446 } else {
2447 fileChannel.truncate(newLength);
2448 - }
2449 + }
2450 }
2451 -
2452 +
2453 /**
2454 * Invalidate buffer before a position change has occurred (e.g. seek),
2455 * flushing writes if required, and correcting file position if reading
2456 - * @throws IOException
2457 + * @throws IOException
2458 */
2459 private void invalidateBuffer() throws IOException, BadDescriptorException {
2460 if (!reading) flushWrite();
2461 @@ -862,13 +853,13 @@
2462 if (c == -1) {
2463 return -1;
2464 }
2465 -
2466 +
2467 // putting a bit back, so we're not at EOF anymore
2468 eof = false;
2469
2470 // save the ungot
2471 ungotc = c;
2472 -
2473 +
2474 return c;
2475 }
2476
2477 @@ -876,7 +867,7 @@
2478 if (eof) {
2479 return -1;
2480 }
2481 -
2482 +
2483 checkReadable();
2484
2485 int c = read();
2486 @@ -885,7 +876,7 @@
2487 eof = true;
2488 return c;
2489 }
2490 -
2491 +
2492 return c & 0xff;
2493 }
2494
2495 @@ -896,12 +887,12 @@
2496 getRuntime().secure(4);
2497 checkWritable();
2498 ensureWrite();
2499 -
2500 +
2501 // Ruby ignores empty syswrites
2502 if (buf == null || buf.length() == 0) return 0;
2503 -
2504 +
2505 if (buffer.position() != 0 && !flushWrite(false)) return 0;
2506 -
2507 +
2508 if (descriptor.getChannel() instanceof SelectableChannel) {
2509 SelectableChannel selectableChannel = (SelectableChannel)descriptor.getChannel();
2510 synchronized (selectableChannel.blockingLock()) {
2511 @@ -1002,13 +993,13 @@
2512 } else {
2513 // otherwise, we try an unbuffered read to get whatever's available
2514 return read(number);
2515 - }
2516 + }
2517 }
2518
2519 public synchronized int read() throws IOException, BadDescriptorException {
2520 try {
2521 descriptor.checkOpen();
2522 -
2523 +
2524 if (ungotc >= 0) {
2525 int c = ungotc;
2526 ungotc = -1;
2527 @@ -1021,11 +1012,11 @@
2528 return -1;
2529 }
2530 }
2531 -
2532 +
2533 public ChannelDescriptor getDescriptor() {
2534 return descriptor;
2535 }
2536 -
2537 +
2538 public void setBlocking(boolean block) throws IOException {
2539 if (!(descriptor.getChannel() instanceof SelectableChannel)) {
2540 return;
2541 @@ -1059,7 +1050,7 @@
2542 if (descriptor.isOpen()) {
2543 descriptor.close();
2544 }
2545 -
2546 +
2547 if (path.equals("/dev/null") || path.equalsIgnoreCase("nul:") || path.equalsIgnoreCase("nul")) {
2548 descriptor = new ChannelDescriptor(new NullChannel(), descriptor.getFileno(), modes, new FileDescriptor());
2549 } else {
2550 @@ -1083,27 +1074,27 @@
2551 RandomAccessFile file = new RandomAccessFile(theFile, modes.toJavaModeString());
2552
2553 if (modes.isTruncate()) file.setLength(0L);
2554 -
2555 +
2556 descriptor = new ChannelDescriptor(file.getChannel(), descriptor.getFileno(), modes, file.getFD());
2557 -
2558 +
2559 if (modes.isAppendable()) lseek(0, SEEK_END);
2560 }
2561 }
2562 -
2563 +
2564 public static Stream fopen(Ruby runtime, String path, ModeFlags modes) throws FileNotFoundException, DirectoryAsFileException, FileExistsException, IOException, InvalidValueException, PipeException, BadDescriptorException {
2565 String cwd = runtime.getCurrentDirectory();
2566 -
2567 +
2568 ChannelDescriptor descriptor = ChannelDescriptor.open(cwd, path, modes);
2569 -
2570 +
2571 Stream stream = fdopen(runtime, descriptor, modes);
2572 -
2573 +
2574 if (modes.isAppendable()) stream.lseek(0, Stream.SEEK_END);
2575 -
2576 +
2577 return stream;
2578 }
2579 -
2580 +
2581 public static Stream fdopen(Ruby runtime, ChannelDescriptor descriptor, ModeFlags modes) throws InvalidValueException {
2582 - Stream handler = new ChannelStream(runtime, descriptor, modes, descriptor.getFileDescriptor());
2583 + Stream handler = new ChannelStream(descriptor, modes, descriptor.getFileDescriptor());
2584
2585 return handler;
2586 }
2587 Index: src/org/jruby/RubyGlobal.java
2588 ===================================================================
2589 --- src/org/jruby/RubyGlobal.java (revision 8091)
2590 +++ src/org/jruby/RubyGlobal.java (working copy)
2591 @@ -43,29 +43,28 @@
2592 import org.jruby.common.IRubyWarnings.ID;
2593 import org.jruby.environment.OSEnvironmentReaderExcepton;
2594 import org.jruby.environment.OSEnvironment;
2595 -import org.jruby.internal.runtime.ValueAccessor;
2596 +import org.jruby.internal.runtime.RuntimeVariableAccessor;
2597 import org.jruby.javasupport.JavaUtil;
2598 import org.jruby.javasupport.util.RuntimeHelpers;
2599 import org.jruby.runtime.Constants;
2600 import org.jruby.runtime.GlobalVariable;
2601 -import org.jruby.runtime.IAccessor;
2602 import org.jruby.runtime.ReadonlyGlobalVariable;
2603 import org.jruby.runtime.ThreadContext;
2604 import org.jruby.runtime.builtin.IRubyObject;
2605 import org.jruby.util.KCode;
2606
2607 /** This class initializes global variables and constants.
2608 - *
2609 + *
2610 * @author jpetersen
2611 */
2612 public class RubyGlobal {
2613 -
2614 +
2615 /**
2616 * Obligate string-keyed and string-valued hash, used for ENV and ENV_JAVA
2617 - *
2618 + *
2619 */
2620 public static class StringOnlyRubyHash extends RubyHash {
2621 -
2622 +
2623 public StringOnlyRubyHash(Ruby runtime, Map valueMap, IRubyObject defaultValue) {
2624 super(runtime, valueMap, defaultValue);
2625 }
2626 @@ -95,26 +94,26 @@
2627 if (value.isNil()) {
2628 return super.delete(context, key, org.jruby.runtime.Block.NULL_BLOCK);
2629 }
2630 -
2631 +
2632 //return super.aset(getRuntime().newString("sadfasdF"), getRuntime().newString("sadfasdF"));
2633 return super.op_aset(context, RuntimeHelpers.invoke(context, key, "to_str"),
2634 value.isNil() ? getRuntime().getNil() : RuntimeHelpers.invoke(context, value, "to_str"));
2635 }
2636 -
2637 +
2638 @JRubyMethod
2639 @Override
2640 public IRubyObject to_s(){
2641 return getRuntime().newString("ENV");
2642 }
2643 }
2644 -
2645 +
2646 public static void createGlobals(ThreadContext context, Ruby runtime) {
2647 runtime.defineGlobalConstant("TOPLEVEL_BINDING", runtime.newBinding());
2648 -
2649 +
2650 runtime.defineGlobalConstant("TRUE", runtime.getTrue());
2651 runtime.defineGlobalConstant("FALSE", runtime.getFalse());
2652 runtime.defineGlobalConstant("NIL", runtime.getNil());
2653 -
2654 +
2655 // define ARGV and $* for this runtime
2656 RubyArray argvArray = runtime.newArray();
2657 String[] argv = runtime.getInstanceConfig().getArgv();
2658 @@ -122,12 +121,11 @@
2659 argvArray.append(RubyString.newStringShared(runtime, argv[i].getBytes()));
2660 }
2661 runtime.defineGlobalConstant("ARGV", argvArray);
2662 - runtime.getGlobalVariables().defineReadonly("$*", new ValueAccessor(argvArray));
2663 + runtime.getGlobalVariables().defineReadonly("$*", new RuntimeVariableAccessor("$*", argvArray));
2664
2665 - IAccessor d = new ValueAccessor(runtime.newString(
2666 - runtime.getInstanceConfig().displayedFileName()));
2667 - runtime.getGlobalVariables().define("$PROGRAM_NAME", d);
2668 - runtime.getGlobalVariables().define("$0", d);
2669 + RubyString fileName = runtime.newString(runtime.getInstanceConfig().displayedFileName());
2670 + runtime.getGlobalVariables().define("$PROGRAM_NAME", new RuntimeVariableAccessor("$PROGRAM_NAME", fileName));
2671 + runtime.getGlobalVariables().define("$0", new RuntimeVariableAccessor("$0", fileName));
2672
2673 // Version information:
2674 IRubyObject version = runtime.newString(Constants.RUBY_VERSION).freeze(context);
2675 @@ -144,36 +142,36 @@
2676 runtime.defineGlobalConstant("VERSION", version);
2677 runtime.defineGlobalConstant("RELEASE_DATE", release);
2678 runtime.defineGlobalConstant("PLATFORM", platform);
2679 -
2680 +
2681 IRubyObject jrubyVersion = runtime.newString(Constants.VERSION).freeze(context);
2682 runtime.defineGlobalConstant("JRUBY_VERSION", jrubyVersion);
2683 -
2684 - GlobalVariable kcodeGV = new KCodeGlobalVariable(runtime, "$KCODE", runtime.newString("NONE"));
2685 +
2686 + GlobalVariable kcodeGV = new KCodeGlobalVariable("$KCODE", runtime.newString("NONE"));
2687 runtime.defineVariable(kcodeGV);
2688 runtime.defineVariable(new GlobalVariable.Copy(runtime, "$-K", kcodeGV));
2689 IRubyObject defaultRS = runtime.newString(runtime.getInstanceConfig().getRecordSeparator()).freeze(context);
2690 - GlobalVariable rs = new StringGlobalVariable(runtime, "$/", defaultRS);
2691 + GlobalVariable rs = new StringGlobalVariable("$/", defaultRS);
2692 runtime.defineVariable(rs);
2693 runtime.setRecordSeparatorVar(rs);
2694 runtime.getGlobalVariables().setDefaultSeparator(defaultRS);
2695 - runtime.defineVariable(new StringGlobalVariable(runtime, "$\\", runtime.getNil()));
2696 - runtime.defineVariable(new StringGlobalVariable(runtime, "$,", runtime.getNil()));
2697 + runtime.defineVariable(new StringGlobalVariable("$\\", runtime.getNil()));
2698 + runtime.defineVariable(new StringGlobalVariable("$,", runtime.getNil()));
2699
2700 - runtime.defineVariable(new LineNumberGlobalVariable(runtime, "$.", RubyFixnum.one(runtime)));
2701 - runtime.defineVariable(new LastlineGlobalVariable(runtime, "$_"));
2702 - runtime.defineVariable(new LastExitStatusVariable(runtime, "$?"));
2703 + runtime.defineVariable(new LineNumberGlobalVariable("$.", RubyFixnum.one(runtime)));
2704 + runtime.defineVariable(new LastlineGlobalVariable("$_"));
2705 + runtime.defineVariable(new LastExitStatusVariable("$?"));
2706
2707 - runtime.defineVariable(new ErrorInfoGlobalVariable(runtime, "$!", runtime.getNil()));
2708 - runtime.defineVariable(new NonEffectiveGlobalVariable(runtime, "$=", runtime.getFalse()));
2709 + runtime.defineVariable(new ErrorInfoGlobalVariable("$!", runtime.getNil()));
2710 + runtime.defineVariable(new NonEffectiveGlobalVariable("$=", runtime.getFalse()));
2711
2712 if(runtime.getInstanceConfig().getInputFieldSeparator() == null) {
2713 - runtime.defineVariable(new GlobalVariable(runtime, "$;", runtime.getNil()));
2714 + runtime.defineVariable(new GlobalVariable("$;", runtime.getNil()));
2715 } else {
2716 - runtime.defineVariable(new GlobalVariable(runtime, "$;", RubyRegexp.newRegexp(runtime, runtime.getInstanceConfig().getInputFieldSeparator(), 0)));
2717 + runtime.defineVariable(new GlobalVariable("$;", RubyRegexp.newRegexp(runtime, runtime.getInstanceConfig().getInputFieldSeparator(), 0)));
2718 }
2719 -
2720 +
2721 Boolean verbose = runtime.getInstanceConfig().getVerbose();
2722 - IRubyObject verboseValue = null;
2723 + IRubyObject verboseValue;
2724 if (verbose == null) {
2725 verboseValue = runtime.getNil();
2726 } else if(verbose == Boolean.TRUE) {
2727 @@ -181,68 +179,67 @@
2728 } else {
2729 verboseValue = runtime.getFalse();
2730 }
2731 - runtime.defineVariable(new VerboseGlobalVariable(runtime, "$VERBOSE", verboseValue));
2732 -
2733 + runtime.defineVariable(new VerboseGlobalVariable("$VERBOSE", verboseValue));
2734 +
2735 IRubyObject debug = runtime.newBoolean(runtime.getInstanceConfig().isDebug());
2736 - runtime.defineVariable(new DebugGlobalVariable(runtime, "$DEBUG", debug));
2737 - runtime.defineVariable(new DebugGlobalVariable(runtime, "$-d", debug));
2738 + runtime.defineVariable(new DebugGlobalVariable("$DEBUG", debug));
2739 + runtime.defineVariable(new DebugGlobalVariable("$-d", debug));
2740
2741 - runtime.defineVariable(new SafeGlobalVariable(runtime, "$SAFE"));
2742 + runtime.defineVariable(new SafeGlobalVariable("$SAFE"));
2743
2744 - runtime.defineVariable(new BacktraceGlobalVariable(runtime, "$@"));
2745 + runtime.defineVariable(new BacktraceGlobalVariable("$@"));
2746
2747 IRubyObject stdin = new RubyIO(runtime, STDIO.IN);
2748 IRubyObject stdout = new RubyIO(runtime, STDIO.OUT);
2749 IRubyObject stderr = new RubyIO(runtime, STDIO.ERR);
2750
2751 - runtime.defineVariable(new InputGlobalVariable(runtime, "$stdin", stdin));
2752 + runtime.getGlobalVariables().define("$stdin", new RuntimeVariableAccessor("$stdin", stdin));
2753
2754 - runtime.defineVariable(new OutputGlobalVariable(runtime, "$stdout", stdout));
2755 + runtime.getGlobalVariables().define("$stdout", new RuntimeOutputAccessor("$stdout", stdout));
2756 runtime.getGlobalVariables().alias("$>", "$stdout");
2757 runtime.getGlobalVariables().alias("$defout", "$stdout");
2758
2759 - runtime.defineVariable(new OutputGlobalVariable(runtime, "$stderr", stderr));
2760 + runtime.getGlobalVariables().define("$stderr", new RuntimeOutputAccessor("$stderr", stderr));
2761 runtime.getGlobalVariables().alias("$deferr", "$stderr");
2762
2763 runtime.defineGlobalConstant("STDIN", stdin);
2764 runtime.defineGlobalConstant("STDOUT", stdout);
2765 runtime.defineGlobalConstant("STDERR", stderr);
2766
2767 - runtime.defineVariable(new LoadedFeatures(runtime, "$\""));
2768 - runtime.defineVariable(new LoadedFeatures(runtime, "$LOADED_FEATURES"));
2769 + runtime.defineVariable(new LoadedFeatures("$\""));
2770 + runtime.defineVariable(new LoadedFeatures("$LOADED_FEATURES"));
2771
2772 - runtime.defineVariable(new LoadPath(runtime, "$:"));
2773 - runtime.defineVariable(new LoadPath(runtime, "$-I"));
2774 - runtime.defineVariable(new LoadPath(runtime, "$LOAD_PATH"));
2775 -
2776 - runtime.defineVariable(new MatchMatchGlobalVariable(runtime, "$&"));
2777 - runtime.defineVariable(new PreMatchGlobalVariable(runtime, "$`"));
2778 - runtime.defineVariable(new PostMatchGlobalVariable(runtime, "$'"));
2779 - runtime.defineVariable(new LastMatchGlobalVariable(runtime, "$+"));
2780 - runtime.defineVariable(new BackRefGlobalVariable(runtime, "$~"));
2781 + runtime.defineVariable(new LoadPath("$:"));
2782 + runtime.defineVariable(new LoadPath("$-I"));
2783 + runtime.defineVariable(new LoadPath("$LOAD_PATH"));
2784
2785 - // On platforms without a c-library accessable through JNA, getpid will return hashCode
2786 + runtime.defineVariable(new MatchMatchGlobalVariable("$&"));
2787 + runtime.defineVariable(new PreMatchGlobalVariable("$`"));
2788 + runtime.defineVariable(new PostMatchGlobalVariable("$'"));
2789 + runtime.defineVariable(new LastMatchGlobalVariable("$+"));
2790 + runtime.defineVariable(new BackRefGlobalVariable("$~"));
2791 +
2792 + // On platforms without a c-library accessable through JNA, getpid will return hashCode
2793 // as $$ used to. Using $$ to kill processes could take down many runtimes, but by basing
2794 // $$ on getpid() where available, we have the same semantics as MRI.
2795 - runtime.getGlobalVariables().defineReadonly("$$", new ValueAccessor(runtime.newFixnum(runtime.getPosix().getpid())));
2796 + RubyFixnum pid = runtime.newFixnum(runtime.getPosix().getpid());
2797 + runtime.getGlobalVariables().defineReadonly("$$", new RuntimeVariableAccessor("$$", pid));
2798
2799 // after defn of $stderr as the call may produce warnings
2800 defineGlobalEnvConstants(runtime);
2801 -
2802 - // Fixme: Do we need the check or does Main.java not call this...they should consolidate
2803 - if (runtime.getGlobalVariables().get("$*").isNil()) {
2804 - runtime.getGlobalVariables().defineReadonly("$*", new ValueAccessor(runtime.newArray()));
2805 - }
2806 -
2807 - runtime.getGlobalVariables().defineReadonly("$-p",
2808 - new ValueAccessor(runtime.getInstanceConfig().isAssumePrinting() ? runtime.getTrue() : runtime.getNil()));
2809 - runtime.getGlobalVariables().defineReadonly("$-n",
2810 - new ValueAccessor(runtime.getInstanceConfig().isAssumeLoop() ? runtime.getTrue() : runtime.getNil()));
2811 - runtime.getGlobalVariables().defineReadonly("$-a",
2812 - new ValueAccessor(runtime.getInstanceConfig().isSplit() ? runtime.getTrue() : runtime.getNil()));
2813 - runtime.getGlobalVariables().defineReadonly("$-l",
2814 - new ValueAccessor(runtime.getInstanceConfig().isProcessLineEnds() ? runtime.getTrue() : runtime.getNil()));
2815
2816 + IRubyObject assumePrinting = runtime.getInstanceConfig().isAssumePrinting() ? runtime.getTrue() : runtime.getNil();
2817 + runtime.getGlobalVariables().defineReadonly("$-p", new RuntimeVariableAccessor("$-p", assumePrinting));
2818 +
2819 + IRubyObject assumeLoop = runtime.getInstanceConfig().isAssumeLoop() ? runtime.getTrue() : runtime.getNil();
2820 + runtime.getGlobalVariables().defineReadonly("$-n", new RuntimeVariableAccessor("$-n", assumeLoop));
2821 +
2822 + IRubyObject split = runtime.getInstanceConfig().isSplit() ? runtime.getTrue() : runtime.getNil();
2823 + runtime.getGlobalVariables().defineReadonly("$-a", new RuntimeVariableAccessor("$-a", split));
2824 +
2825 + IRubyObject processLineEnds = runtime.getInstanceConfig().isProcessLineEnds() ? runtime.getTrue() : runtime.getNil();
2826 + runtime.getGlobalVariables().defineReadonly("$-l", new RuntimeVariableAccessor("S-l", processLineEnds));
2827 +
2828 // ARGF, $< object
2829 RubyArgsFile.initArgsFile(runtime);
2830 }
2831 @@ -254,10 +251,10 @@
2832 try {
2833 environmentVariableMap = environment.getEnvironmentVariableMap(runtime);
2834 } catch (OSEnvironmentReaderExcepton e) {
2835 - // If the environment variables are not accessible shouldn't terminate
2836 + // If the environment variables are not accessible shouldn't terminate
2837 runtime.getWarnings().warn(ID.MISCELLANEOUS, e.getMessage());
2838 }
2839 -
2840 +
2841 if (environmentVariableMap == null) {
2842 // if the environment variables can't be obtained, define an empty ENV
2843 environmentVariableMap = new HashMap();
2844 @@ -272,103 +269,109 @@
2845 Map systemProps = environment.getSystemPropertiesMap(runtime);
2846 runtime.defineGlobalConstant("ENV_JAVA", new StringOnlyRubyHash(
2847 runtime, systemProps, runtime.getNil()));
2848 -
2849 +
2850 }
2851
2852 + private static Ruby getRuntime() {
2853 + return Ruby.getCurrentRuntime();
2854 + }
2855 +
2856 private static class NonEffectiveGlobalVariable extends GlobalVariable {
2857 - public NonEffectiveGlobalVariable(Ruby runtime, String name, IRubyObject value) {
2858 - super(runtime, name, value);
2859 + public NonEffectiveGlobalVariable(String name, IRubyObject value) {
2860 + super(name, value);
2861 }
2862
2863 @Override
2864 public IRubyObject set(IRubyObject value) {
2865 - runtime.getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective; ignored", name);
2866 + getRuntime().getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective; ignored", name);
2867 return value;
2868 }
2869
2870 +
2871 @Override
2872 public IRubyObject get() {
2873 - runtime.getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective", name);
2874 - return runtime.getFalse();
2875 + getRuntime().getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective", name);
2876 + return getRuntime().getFalse();
2877 }
2878 +
2879 }
2880
2881 private static class LastExitStatusVariable extends GlobalVariable {
2882 - public LastExitStatusVariable(Ruby runtime, String name) {
2883 - super(runtime, name, runtime.getNil());
2884 + public LastExitStatusVariable(String name) {
2885 + super(name, getRuntime().getNil());
2886 }
2887 -
2888 +
2889 @Override
2890 public IRubyObject get() {
2891 - IRubyObject lastExitStatus = runtime.getCurrentContext().getLastExitStatus();
2892 - return lastExitStatus == null ? runtime.getNil() : lastExitStatus;
2893 + IRubyObject lastExitStatus = getRuntime().getCurrentContext().getLastExitStatus();
2894 + return lastExitStatus == null ? getRuntime().getNil() : lastExitStatus;
2895 }
2896 -
2897 +
2898 @Override
2899 public IRubyObject set(IRubyObject lastExitStatus) {
2900 - runtime.getCurrentContext().setLastExitStatus(lastExitStatus);
2901 -
2902 + getRuntime().getCurrentContext().setLastExitStatus(lastExitStatus);
2903 +
2904 return lastExitStatus;
2905 }
2906 }
2907
2908 private static class MatchMatchGlobalVariable extends GlobalVariable {
2909 - public MatchMatchGlobalVariable(Ruby runtime, String name) {
2910 - super(runtime, name, runtime.getNil());
2911 + public MatchMatchGlobalVariable(String name) {
2912 + super(name, getRuntime().getNil());
2913 }
2914 -
2915 +
2916 @Override
2917 public IRubyObject get() {
2918 - return RubyRegexp.last_match(runtime.getCurrentContext().getCurrentFrame().getBackRef());
2919 + return RubyRegexp.last_match(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
2920 }
2921 }
2922
2923 private static class PreMatchGlobalVariable extends GlobalVariable {
2924 - public PreMatchGlobalVariable(Ruby runtime, String name) {
2925 - super(runtime, name, runtime.getNil());
2926 + public PreMatchGlobalVariable(String name) {
2927 + super(name, getRuntime().getNil());
2928 }
2929 -
2930 +
2931 @Override
2932 public IRubyObject get() {
2933 - return RubyRegexp.match_pre(runtime.getCurrentContext().getCurrentFrame().getBackRef());
2934 + return RubyRegexp.match_pre(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
2935 }
2936 }
2937
2938 private static class PostMatchGlobalVariable extends GlobalVariable {
2939 - public PostMatchGlobalVariable(Ruby runtime, String name) {
2940 - super(runtime, name, runtime.getNil());
2941 + public PostMatchGlobalVariable(String name) {
2942 + super(name, getRuntime().getNil());
2943 }
2944 -
2945 +
2946 @Override
2947 public IRubyObject get() {
2948 - return RubyRegexp.match_post(runtime.getCurrentContext().getCurrentFrame().getBackRef());
2949 + return RubyRegexp.match_post(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
2950 }
2951 }
2952
2953 private static class LastMatchGlobalVariable extends GlobalVariable {
2954 - public LastMatchGlobalVariable(Ruby runtime, String name) {
2955 - super(runtime, name, runtime.getNil());
2956 + public LastMatchGlobalVariable(String name) {
2957 + super(name, getRuntime().getNil());
2958 }
2959 -
2960 +
2961 @Override
2962 public IRubyObject get() {
2963 - return RubyRegexp.match_last(runtime.getCurrentContext().getCurrentFrame().getBackRef());
2964 + return RubyRegexp.match_last(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
2965 }
2966 }
2967
2968 private static class BackRefGlobalVariable extends GlobalVariable {
2969 - public BackRefGlobalVariable(Ruby runtime, String name) {
2970 - super(runtime, name, runtime.getNil());
2971 + public BackRefGlobalVariable(String name) {
2972 + super(name, getRuntime().getNil());
2973 }
2974 -
2975 +
2976 @Override
2977 public IRubyObject get() {
2978 - return RuntimeHelpers.getBackref(runtime, runtime.getCurrentContext());
2979 + return RuntimeHelpers.getBackref(getRuntime(), getRuntime().getCurrentContext());
2980 }
2981
2982 @Override
2983 public IRubyObject set(IRubyObject value) {
2984 - RuntimeHelpers.setBackref(runtime, runtime.getCurrentContext(), value);
2985 + RuntimeHelpers.setBackref(getRuntime(), getRuntime().getCurrentContext(), value);
2986 return value;
2987 }
2988 }
2989 @@ -376,113 +379,113 @@
2990 // Accessor methods.
2991
2992 private static class LineNumberGlobalVariable extends GlobalVariable {
2993 - public LineNumberGlobalVariable(Ruby runtime, String name, RubyFixnum value) {
2994 - super(runtime, name, value);
2995 + public LineNumberGlobalVariable(String name, RubyFixnum value) {
2996 + super(name, value);
2997 }
2998
2999 @Override
3000 public IRubyObject set(IRubyObject value) {
3001 - RubyArgsFile.setCurrentLineNumber(runtime.getGlobalVariables().get("$<"),RubyNumeric.fix2int(value));
3002 + RubyArgsFile.setCurrentLineNumber(getRuntime().getGlobalVariables().get("$<"),RubyNumeric.fix2int(value));
3003 return super.set(value);
3004 }
3005 }
3006
3007 private static class ErrorInfoGlobalVariable extends GlobalVariable {
3008 - public ErrorInfoGlobalVariable(Ruby runtime, String name, IRubyObject value) {
3009 - super(runtime, name, null);
3010 + public ErrorInfoGlobalVariable(String name, IRubyObject value) {
3011 + super(name, null);
3012 set(value);
3013 }
3014
3015 @Override
3016 public IRubyObject set(IRubyObject value) {
3017 if (!value.isNil() &&
3018 - !runtime.getException().isInstance(value) &&
3019 + !getRuntime().getException().isInstance(value) &&
3020 !(JavaUtil.isJavaObject(value) && JavaUtil.unwrapJavaObject(value) instanceof Exception)) {
3021 - throw runtime.newTypeError("assigning non-exception to $!");
3022 + throw getRuntime().newTypeError("assigning non-exception to $!");
3023 }
3024 -
3025 - return runtime.getCurrentContext().setErrorInfo(value);
3026 +
3027 + return getRuntime().getCurrentContext().setErrorInfo(value);
3028 }
3029
3030 @Override
3031 public IRubyObject get() {
3032 - return runtime.getCurrentContext().getErrorInfo();
3033 + return getRuntime().getCurrentContext().getErrorInfo();
3034 }
3035 }
3036
3037 // FIXME: move out of this class!
3038 public static class StringGlobalVariable extends GlobalVariable {
3039 - public StringGlobalVariable(Ruby runtime, String name, IRubyObject value) {
3040 - super(runtime, name, value);
3041 + public StringGlobalVariable(String name, IRubyObject value) {
3042 + super(name, value);
3043 }
3044
3045 @Override
3046 public IRubyObject set(IRubyObject value) {
3047 if (!value.isNil() && ! (value instanceof RubyString)) {
3048 - throw runtime.newTypeError("value of " + name() + " must be a String");
3049 + throw getRuntime().newTypeError("value of " + name() + " must be a String");
3050 }
3051 return super.set(value);
3052 }
3053 }
3054
3055 public static class KCodeGlobalVariable extends GlobalVariable {
3056 - public KCodeGlobalVariable(Ruby runtime, String name, IRubyObject value) {
3057 - super(runtime, name, value);
3058 + public KCodeGlobalVariable(String name, IRubyObject value) {
3059 + super(name, value);
3060 }
3061
3062 @Override
3063 public IRubyObject get() {
3064 - return runtime.getKCode().kcode(runtime);
3065 + return getRuntime().getKCode().kcode(getRuntime());
3066 }
3067
3068 @Override
3069 public IRubyObject set(IRubyObject value) {
3070 - runtime.setKCode(KCode.create(runtime, value.convertToString().toString()));
3071 + getRuntime().setKCode(KCode.create(getRuntime(), value.convertToString().toString()));
3072 return value;
3073 }
3074 }
3075
3076 private static class SafeGlobalVariable extends GlobalVariable {
3077 - public SafeGlobalVariable(Ruby runtime, String name) {
3078 - super(runtime, name, null);
3079 + public SafeGlobalVariable(String name) {
3080 + super(name, null);
3081 }
3082
3083 @Override
3084 public IRubyObject get() {
3085 - return runtime.newFixnum(runtime.getSafeLevel());
3086 + return getRuntime().newFixnum(getRuntime().getSafeLevel());
3087 }
3088
3089 @Override
3090 public IRubyObject set(IRubyObject value) {
3091 // int level = RubyNumeric.fix2int(value);
3092 -// if (level < runtime.getSafeLevel()) {
3093 -// throw runtime.newSecurityError("tried to downgrade safe level from " +
3094 -// runtime.getSafeLevel() + " to " + level);
3095 +// if (level < getRuntime().getSafeLevel()) {
3096 +// throw getRuntime().newSecurityError("tried to downgrade safe level from " +
3097 +// getRuntime().getSafeLevel() + " to " + level);
3098 // }
3099 -// runtime.setSafeLevel(level);
3100 +// getRuntime().setSafeLevel(level);
3101 // thread.setSafeLevel(level);
3102 - runtime.getWarnings().warn(ID.SAFE_NOT_SUPPORTED, "SAFE levels are not supported in JRuby");
3103 - return RubyFixnum.newFixnum(runtime, runtime.getSafeLevel());
3104 + getRuntime().getWarnings().warn(ID.SAFE_NOT_SUPPORTED, "SAFE levels are not supported in JRuby");
3105 + return RubyFixnum.newFixnum(getRuntime(), getRuntime().getSafeLevel());
3106 }
3107 }
3108
3109 private static class VerboseGlobalVariable extends GlobalVariable {
3110 - public VerboseGlobalVariable(Ruby runtime, String name, IRubyObject initialValue) {
3111 - super(runtime, name, initialValue);
3112 + public VerboseGlobalVariable(String name, IRubyObject initialValue) {
3113 + super(name, initialValue);
3114 set(initialValue);
3115 }
3116 -
3117 +
3118 @Override
3119 public IRubyObject get() {
3120 - return runtime.getVerbose();
3121 + return getRuntime().getVerbose();
3122 }
3123
3124 @Override
3125 public IRubyObject set(IRubyObject newValue) {
3126 if (newValue.isNil()) {
3127 - runtime.setVerbose(newValue);
3128 + getRuntime().setVerbose(newValue);
3129 } else {
3130 - runtime.setVerbose(runtime.newBoolean(newValue.isTrue()));
3131 + getRuntime().setVerbose(getRuntime().newBoolean(newValue.isTrue()));
3132 }
3133
3134 return newValue;
3135 @@ -490,22 +493,22 @@
3136 }
3137
3138 private static class DebugGlobalVariable extends GlobalVariable {
3139 - public DebugGlobalVariable(Ruby runtime, String name, IRubyObject initialValue) {
3140 - super(runtime, name, initialValue);
3141 + public DebugGlobalVariable(String name, IRubyObject initialValue) {
3142 + super(name, initialValue);
3143 set(initialValue);
3144 }
3145
3146 @Override
3147 public IRubyObject get() {
3148 - return runtime.getDebug();
3149 + return getRuntime().getDebug();
3150 }
3151
3152 @Override
3153 public IRubyObject set(IRubyObject newValue) {
3154 if (newValue.isNil()) {
3155 - runtime.setDebug(newValue);
3156 + getRuntime().setDebug(newValue);
3157 } else {
3158 - runtime.setDebug(runtime.newBoolean(newValue.isTrue()));
3159 + getRuntime().setDebug(getRuntime().newBoolean(newValue.isTrue()));
3160 }
3161
3162 return newValue;
3163 @@ -513,115 +516,103 @@
3164 }
3165
3166 private static class BacktraceGlobalVariable extends GlobalVariable {
3167 - public BacktraceGlobalVariable(Ruby runtime, String name) {
3168 - super(runtime, name, null);
3169 + public BacktraceGlobalVariable(String name) {
3170 + super(name, null);
3171 }
3172
3173 @Override
3174 public IRubyObject get() {
3175 - IRubyObject errorInfo = runtime.getGlobalVariables().get("$!");
3176 - IRubyObject backtrace = errorInfo.isNil() ? runtime.getNil() : errorInfo.callMethod(errorInfo.getRuntime().getCurrentContext(), "backtrace");
3177 + IRubyObject errorInfo = getRuntime().getGlobalVariables().get("$!");
3178 + IRubyObject backtrace = errorInfo.isNil() ? getRuntime().getNil() : errorInfo.callMethod(errorInfo.getRuntime().getCurrentContext(), "backtrace");
3179 //$@ returns nil if $!.backtrace is not an array
3180 if (!(backtrace instanceof RubyArray)) {
3181 - backtrace = runtime.getNil();
3182 + backtrace = getRuntime().getNil();
3183 }
3184 return backtrace;
3185 }
3186
3187 @Override
3188 public IRubyObject set(IRubyObject value) {
3189 - if (runtime.getGlobalVariables().get("$!").isNil()) {
3190 - throw runtime.newArgumentError("$! not set.");
3191 + if (getRuntime().getGlobalVariables().get("$!").isNil()) {
3192 + throw getRuntime().newArgumentError("$! not set.");
3193 }
3194 - runtime.getGlobalVariables().get("$!").callMethod(value.getRuntime().getCurrentContext(), "set_backtrace", value);
3195 + getRuntime().getGlobalVariables().get("$!").callMethod(value.getRuntime().getCurrentContext(), "set_backtrace", value);
3196 return value;
3197 }
3198 }
3199
3200 private static class LastlineGlobalVariable extends GlobalVariable {
3201 - public LastlineGlobalVariable(Ruby runtime, String name) {
3202 - super(runtime, name, null);
3203 + public LastlineGlobalVariable(String name) {
3204 + super(name, null);
3205 }
3206
3207 @Override
3208 public IRubyObject get() {
3209 - return RuntimeHelpers.getLastLine(runtime, runtime.getCurrentContext());
3210 + return RuntimeHelpers.getLastLine(getRuntime(), getRuntime().getCurrentContext());
3211 }
3212
3213 @Override
3214 public IRubyObject set(IRubyObject value) {
3215 - RuntimeHelpers.setLastLine(runtime, runtime.getCurrentContext(), value);
3216 + RuntimeHelpers.setLastLine(getRuntime(), getRuntime().getCurrentContext(), value);
3217 return value;
3218 }
3219 }
3220
3221 - private static class InputGlobalVariable extends GlobalVariable {
3222 - public InputGlobalVariable(Ruby runtime, String name, IRubyObject value) {
3223 - super(runtime, name, value);
3224 - }
3225 + private static class RuntimeOutputAccessor extends RuntimeVariableAccessor {
3226 + private final String name;
3227
3228 - @Override
3229 - public IRubyObject set(IRubyObject value) {
3230 - if (value == get()) {
3231 - return value;
3232 - }
3233 -
3234 - return super.set(value);
3235 + public RuntimeOutputAccessor(String name, IRubyObject value) {
3236 + super(name, value);
3237 + this.name = name;
3238 }
3239 - }
3240
3241 - private static class OutputGlobalVariable extends GlobalVariable {
3242 - public OutputGlobalVariable(Ruby runtime, String name, IRubyObject value) {
3243 - super(runtime, name, value);
3244 - }
3245 -
3246 @Override
3247 - public IRubyObject set(IRubyObject value) {
3248 - if (value == get()) {
3249 - return value;
3250 + public IRubyObject setValue(IRubyObject newValue) {
3251 + if (newValue == getValue()) {
3252 + return newValue;
3253 }
3254 - if (value instanceof RubyIO) {
3255 - RubyIO io = (RubyIO)value;
3256 -
3257 + if (newValue instanceof RubyIO) {
3258 + RubyIO io = (RubyIO)newValue;
3259 +
3260 // HACK: in order to have stdout/err act like ttys and flush always,
3261 // we set anything assigned to stdout/stderr to sync
3262 io.getHandler().setSync(true);
3263 }
3264
3265 - if (!value.respondsTo("write")) {
3266 - throw runtime.newTypeError(name() + " must have write method, " +
3267 - value.getType().getName() + " given");
3268 + if (!newValue.respondsTo("write")) {
3269 + throw getRuntime().newTypeError(name + " must have write method, " +
3270 + newValue.getType().getName() + " given");
3271 }
3272
3273 - return super.set(value);
3274 + return super.setValue(newValue);
3275 }
3276 }
3277
3278 private static class LoadPath extends ReadonlyGlobalVariable {
3279 - public LoadPath(Ruby runtime, String name) {
3280 - super(runtime, name, null);
3281 + public LoadPath(String name) {
3282 + super(name, null);
3283 }
3284 -
3285 +
3286 /**
3287 * @see org.jruby.runtime.GlobalVariable#get()
3288 */
3289 @Override
3290 public IRubyObject get() {
3291 - return runtime.getLoadService().getLoadPath();
3292 + return getRuntime().getLoadService().getLoadPath();
3293 }
3294 }
3295
3296 private static class LoadedFeatures extends ReadonlyGlobalVariable {
3297 - public LoadedFeatures(Ruby runtime, String name) {
3298 - super(runtime, name, null);
3299 + public LoadedFeatures(String name) {
3300 + super(name, null);
3301 }
3302 -
3303 +
3304 /**
3305 * @see org.jruby.runtime.GlobalVariable#get()
3306 */
3307 @Override
3308 public IRubyObject get() {
3309 - return runtime.getLoadService().getLoadedFeatures();
3310 + return getRuntime().getLoadService().getLoadedFeatures();
3311 }
3312 }
3313 }
3314 Index: src/org/jruby/RubyClass.java
3315 ===================================================================
3316 --- src/org/jruby/RubyClass.java (revision 8091)
3317 +++ src/org/jruby/RubyClass.java (working copy)
3318 @@ -54,6 +54,8 @@
3319 import org.jruby.runtime.marshal.MarshalStream;
3320 import org.jruby.runtime.marshal.UnmarshalStream;
3321 import org.jruby.util.collections.WeakHashSet;
3322 +import org.jruby.util.RuntimeContainer;
3323 +import org.jruby.util.JRubyClassLoader;
3324
3325 /**
3326 *
3327 @@ -74,7 +76,7 @@
3328
3329 private CallSite[] extraCallSites;
3330
3331 - public static void createClassClass(Ruby runtime, RubyClass classClass) {
3332 + public static void createClassClass(RubyClass classClass) {
3333 classClass.index = ClassIndex.CLASS;
3334 classClass.kindOf = new RubyModule.KindOf() {
3335 @Override
3336 @@ -116,9 +118,9 @@
3337
3338 @JRubyMethod(name = "allocate")
3339 public IRubyObject allocate() {
3340 - if (superClass == null) throw runtime.newTypeError("can't instantiate uninitialized class");
3341 - IRubyObject obj = allocator.allocate(runtime, this);
3342 - if (obj.getMetaClass().getRealClass() != getRealClass()) throw runtime.newTypeError("wrong instance allocation");
3343 + if (superClass == null) throw getRuntime().newTypeError("can't instantiate uninitialized class");
3344 + IRubyObject obj = allocator.allocate(getRuntime(), this);
3345 + if (obj.getMetaClass().getRealClass() != getRealClass()) throw getRuntime().newTypeError("wrong instance allocation");
3346 return obj;
3347 }
3348
3349 @@ -171,7 +173,6 @@
3350 return obj;
3351 }
3352
3353 - private final Ruby runtime;
3354 private ObjectAllocator allocator; // the default allocator
3355 protected ObjectMarshal marshal;
3356 private Set<RubyClass> subclasses;
3357 @@ -182,7 +183,6 @@
3358 */
3359 protected RubyClass(Ruby runtime, RubyClass superClass, boolean objectSpace) {
3360 super(runtime, runtime.getClassClass(), objectSpace);
3361 - this.runtime = runtime;
3362 this.superClass = superClass; // this is the only case it might be null here (in MetaClass construction)
3363 }
3364
3365 @@ -192,7 +192,6 @@
3366 */
3367 protected RubyClass(Ruby runtime, RubyClass superClass, Generation generation, boolean objectSpace) {
3368 super(runtime, runtime.getClassClass(), generation, objectSpace);
3369 - this.runtime = runtime;
3370 this.superClass = superClass; // this is the only case it might be null here (in MetaClass construction)
3371 }
3372
3373 @@ -201,7 +200,6 @@
3374 */
3375 protected RubyClass(Ruby runtime) {
3376 super(runtime, runtime.getClassClass());
3377 - this.runtime = runtime;
3378 index = ClassIndex.CLASS;
3379 }
3380
3381 @@ -624,7 +622,7 @@
3382 @JRubyMethod(name = "initialize_copy", required = 1, visibility = Visibility.PRIVATE)
3383 @Override
3384 public IRubyObject initialize_copy(IRubyObject original){
3385 - if (superClass != null) throw runtime.newTypeError("already initialized class");
3386 + if (superClass != null) throw getRuntime().newTypeError("already initialized class");
3387 if (original instanceof MetaClass) throw getRuntime().newTypeError("can't copy singleton class");
3388
3389 super.initialize_copy(original);
3390 @@ -675,7 +673,7 @@
3391 }
3392
3393 public Ruby getClassRuntime() {
3394 - return runtime;
3395 + return Ruby.getCurrentRuntime();
3396 }
3397
3398 public RubyClass getRealClass() {
3399 Index: src/org/jruby/RubyIO.java
3400 ===================================================================
3401 --- src/org/jruby/RubyIO.java (revision 8091)
3402 +++ src/org/jruby/RubyIO.java (working copy)
3403 @@ -85,22 +85,22 @@
3404 import static org.jruby.RubyEnumerator.enumeratorize;
3405
3406 /**
3407 - *
3408 + *
3409 * @author jpetersen
3410 */
3411 @JRubyClass(name="IO", include="Enumerable")
3412 public class RubyIO extends RubyObject {
3413 protected OpenFile openFile;
3414 protected List<RubyThread> blockingThreads;
3415 -
3416 +
3417 public void registerDescriptor(ChannelDescriptor descriptor) {
3418 getRuntime().getDescriptors().put(new Integer(descriptor.getFileno()), new WeakReference<ChannelDescriptor>(descriptor));
3419 }
3420 -
3421 +
3422 public void unregisterDescriptor(int aFileno) {
3423 getRuntime().getDescriptors().remove(new Integer(aFileno));
3424 }
3425 -
3426 +
3427 public ChannelDescriptor getDescriptorByFileno(int aFileno) {
3428 Reference<ChannelDescriptor> reference = getRuntime().getDescriptors().get(new Integer(aFileno));
3429 if (reference == null) {
3430 @@ -108,10 +108,10 @@
3431 }
3432 return reference.get();
3433 }
3434 -
3435 +
3436 // FIXME can't use static; would interfere with other runtimes in the same JVM
3437 protected static AtomicInteger filenoIndex = new AtomicInteger(2);
3438 -
3439 +
3440 public static int getNewFileno() {
3441 return filenoIndex.incrementAndGet();
3442 }
3443 @@ -120,77 +120,77 @@
3444 // It allows this object to be created without a IOHandler.
3445 public RubyIO(Ruby runtime, RubyClass type) {
3446 super(runtime, type);
3447 -
3448 +
3449 openFile = new OpenFile();
3450 }
3451
3452 public RubyIO(Ruby runtime, OutputStream outputStream) {
3453 super(runtime, runtime.getIO());
3454 -
3455 - // We only want IO objects with valid streams (better to error now).
3456 +
3457 + // We only want IO objects with valid streams (better to error now).
3458 if (outputStream == null) {
3459 throw runtime.newRuntimeError("Opening null stream");
3460 }
3461 -
3462 +
3463 openFile = new OpenFile();
3464 -
3465 +
3466 try {
3467 - openFile.setMainStream(new ChannelStream(runtime, new ChannelDescriptor(Channels.newChannel(outputStream), getNewFileno(), new FileDescriptor())));
3468 + openFile.setMainStream(new ChannelStream(new ChannelDescriptor(Channels.newChannel(outputStream), getNewFileno(), new FileDescriptor())));
3469 } catch (InvalidValueException e) {
3470 throw getRuntime().newErrnoEINVALError();
3471 }
3472 -
3473 +
3474 openFile.setMode(OpenFile.WRITABLE | OpenFile.APPEND);
3475 -
3476 +
3477 registerDescriptor(openFile.getMainStream().getDescriptor());
3478 }
3479 -
3480 +
3481 public RubyIO(Ruby runtime, InputStream inputStream) {
3482 super(runtime, runtime.getIO());
3483 -
3484 +
3485 if (inputStream == null) {
3486 throw runtime.newRuntimeError("Opening null stream");
3487 }
3488 -
3489 +
3490 openFile = new OpenFile();
3491 -
3492 +
3493 try {
3494 - openFile.setMainStream(new ChannelStream(runtime, new ChannelDescriptor(Channels.newChannel(inputStream), getNewFileno(), new FileDescriptor())));
3495 + openFile.setMainStream(new ChannelStream(new ChannelDescriptor(Channels.newChannel(inputStream), getNewFileno(), new FileDescriptor())));
3496 } catch (InvalidValueException e) {
3497 throw getRuntime().newErrnoEINVALError();
3498 }
3499 -
3500 +
3501 openFile.setMode(OpenFile.READABLE);
3502 -
3503 +
3504 registerDescriptor(openFile.getMainStream().getDescriptor());
3505 }
3506 -
3507 +
3508 public RubyIO(Ruby runtime, Channel channel) {
3509 super(runtime, runtime.getIO());
3510 -
3511 - // We only want IO objects with valid streams (better to error now).
3512 +
3513 + // We only want IO objects with valid streams (better to error now).
3514 if (channel == null) {
3515 throw runtime.newRuntimeError("Opening null channelpo");
3516 }
3517 -
3518 +
3519 openFile = new OpenFile();
3520 -
3521 +
3522 try {
3523 - openFile.setMainStream(new ChannelStream(runtime, new ChannelDescriptor(channel, getNewFileno(), new FileDescriptor())));
3524 + openFile.setMainStream(new ChannelStream(new ChannelDescriptor(channel, getNewFileno(), new FileDescriptor())));
3525 } catch (InvalidValueException e) {
3526 throw getRuntime().newErrnoEINVALError();
3527 }
3528 -
3529 +
3530 openFile.setMode(openFile.getMainStream().getModes().getOpenFileFlags());
3531 -
3532 +
3533 registerDescriptor(openFile.getMainStream().getDescriptor());
3534 }
3535
3536 public RubyIO(Ruby runtime, ShellLauncher.POpenProcess process, ModeFlags modes) {
3537 super(runtime, runtime.getIO());
3538 -
3539 +
3540 openFile = new OpenFile();
3541 -
3542 +
3543 openFile.setMode(modes.getOpenFileFlags() | OpenFile.SYNC);
3544 openFile.setProcess(process);
3545
3546 @@ -204,17 +204,17 @@
3547 // Stream-based
3548 inChannel = Channels.newChannel(process.getInputStream());
3549 }
3550 -
3551 +
3552 ChannelDescriptor main = new ChannelDescriptor(
3553 inChannel,
3554 getNewFileno(),
3555 new FileDescriptor());
3556 main.setCanBeSeekable(false);
3557 -
3558 - openFile.setMainStream(new ChannelStream(getRuntime(), main));
3559 +
3560 + openFile.setMainStream(new ChannelStream(main));
3561 registerDescriptor(main);
3562 }
3563 -
3564 +
3565 if (openFile.isWritable()) {
3566 Channel outChannel;
3567 if (process.getOutput() != null) {
3568 @@ -229,23 +229,23 @@
3569 getNewFileno(),
3570 new FileDescriptor());
3571 pipe.setCanBeSeekable(false);
3572 -
3573 +
3574 if (openFile.getMainStream() != null) {
3575 - openFile.setPipeStream(new ChannelStream(getRuntime(), pipe));
3576 + openFile.setPipeStream(new ChannelStream(pipe));
3577 } else {
3578 - openFile.setMainStream(new ChannelStream(getRuntime(), pipe));
3579 + openFile.setMainStream(new ChannelStream(pipe));
3580 }
3581 -
3582 +
3583 registerDescriptor(pipe);
3584 }
3585 } catch (InvalidValueException e) {
3586 throw getRuntime().newErrnoEINVALError();
3587 }
3588 }
3589 -
3590 +
3591 public RubyIO(Ruby runtime, STDIO stdio) {
3592 super(runtime, runtime.getIO());
3593 -
3594 +
3595 openFile = new OpenFile();
3596
3597 try {
3598 @@ -253,15 +253,13 @@
3599 case IN:
3600 openFile.setMainStream(
3601 new ChannelStream(
3602 - runtime,
3603 // special constructor that accepts stream, not channel
3604 - new ChannelDescriptor(runtime.getIn(), 0, new ModeFlags(ModeFlags.RDONLY), FileDescriptor.in),
3605 + new ChannelDescriptor(Channels.newChannel(runtime.getIn()), 0, new ModeFlags(ModeFlags.RDONLY), FileDescriptor.in),
3606 FileDescriptor.in));
3607 break;
3608 case OUT:
3609 openFile.setMainStream(
3610 new ChannelStream(
3611 - runtime,
3612 new ChannelDescriptor(Channels.newChannel(runtime.getOut()), 1, new ModeFlags(ModeFlags.WRONLY | ModeFlags.APPEND), FileDescriptor.out),
3613 FileDescriptor.out));
3614 openFile.getMainStream().setSync(true);
3615 @@ -269,8 +267,7 @@
3616 case ERR:
3617 openFile.setMainStream(
3618 new ChannelStream(
3619 - runtime,
3620 - new ChannelDescriptor(Channels.newChannel(runtime.getErr()), 2, new ModeFlags(ModeFlags.WRONLY | ModeFlags.APPEND), FileDescriptor.err),
3621 + new ChannelDescriptor(Channels.newChannel(runtime.getErr()), 2, new ModeFlags(ModeFlags.WRONLY | ModeFlags.APPEND), FileDescriptor.err),
3622 FileDescriptor.err));
3623 openFile.getMainStream().setSync(true);
3624 break;
3625 @@ -278,25 +275,25 @@
3626 } catch (InvalidValueException ex) {
3627 throw getRuntime().newErrnoEINVALError();
3628 }
3629 -
3630 +
3631 openFile.setMode(openFile.getMainStream().getModes().getOpenFileFlags());
3632 -
3633 - registerDescriptor(openFile.getMainStream().getDescriptor());
3634 +
3635 + registerDescriptor(openFile.getMainStream().getDescriptor());
3636 }
3637 -
3638 +
3639 public static RubyIO newIO(Ruby runtime, Channel channel) {
3640 return new RubyIO(runtime, channel);
3641 }
3642 -
3643 +
3644 public OpenFile getOpenFile() {
3645 return openFile;
3646 }
3647 -
3648 +
3649 protected OpenFile getOpenFileChecked() {
3650 openFile.checkClosed(getRuntime());
3651 return openFile;
3652 }
3653 -
3654 +
3655 private static ObjectAllocator IO_ALLOCATOR = new ObjectAllocator() {
3656 public IRubyObject allocate(Ruby runtime, RubyClass klass) {
3657 return new RubyIO(runtime, klass);
3658 @@ -313,12 +310,12 @@
3659 };
3660
3661 ioClass.includeModule(runtime.getEnumerable());
3662 -
3663 +
3664 // TODO: Implement tty? and isatty. We have no real capability to
3665 // determine this from java, but if we could set tty status, then
3666 // we could invoke jruby differently to allow stdin to return true
3667 // on this. This would allow things like cgi.rb to work properly.
3668 -
3669 +
3670 ioClass.defineAnnotatedMethods(RubyIO.class);
3671
3672 // Constants for seek
3673 @@ -344,7 +341,7 @@
3674 return null;
3675 }
3676 }
3677 -
3678 +
3679 public Stream getHandler() {
3680 return getOpenFileChecked().getMainStream();
3681 }
3682 @@ -352,13 +349,13 @@