Index: src/org/jruby/runtime/ReadonlyGlobalVariable.java
===================================================================
--- src/org/jruby/runtime/ReadonlyGlobalVariable.java (revision 8091)
+++ src/org/jruby/runtime/ReadonlyGlobalVariable.java (working copy)
@@ -34,12 +34,12 @@
public class ReadonlyGlobalVariable extends GlobalVariable {
- public ReadonlyGlobalVariable(Ruby runtime, String name, IRubyObject value) {
- super(runtime, name, value);
+ public ReadonlyGlobalVariable(String name, IRubyObject value) {
+ super(name, value);
}
@Override
public IRubyObject set(IRubyObject value) {
- throw runtime.newNameError(name() + " is a read-only variable", name());
+ throw Ruby.getCurrentRuntime().newNameError(name() + " is a read-only variable", name());
}
}
Index: src/org/jruby/runtime/GlobalVariable.java
===================================================================
--- src/org/jruby/runtime/GlobalVariable.java (revision 8091)
+++ src/org/jruby/runtime/GlobalVariable.java (working copy)
@@ -39,7 +39,7 @@
private GlobalVariable other;
public Copy(Ruby runtime, String name, GlobalVariable other) {
- super(runtime, name, other.get());
+ super(name, other.get());
this.other = other;
}
@@ -54,8 +54,6 @@
}
}
- protected final Ruby runtime;
-
protected final String name;
private IRubyObject value;
@@ -63,10 +61,8 @@
return "$" + name;
}
- public GlobalVariable(Ruby runtime, String name, IRubyObject value) {
+ public GlobalVariable(String name, IRubyObject value) {
assert name.startsWith("$");
-
- this.runtime = runtime;
this.name = name;
this.value = value;
}
Index: src/org/jruby/runtime/GlobalVariableAcessor.java
===================================================================
--- src/org/jruby/runtime/GlobalVariableAcessor.java (revision 0)
+++ src/org/jruby/runtime/GlobalVariableAcessor.java (revision 0)
@@ -0,0 +1,24 @@
+package org.jruby.runtime;
+
+import org.jruby.runtime.IAccessor;
+import org.jruby.runtime.GlobalVariable;
+import org.jruby.runtime.builtin.IRubyObject;
+
+/**
+ * @author Fabio Kung
+*/
+public class GlobalVariableAcessor implements IAccessor {
+ private final GlobalVariable variable;
+
+ public GlobalVariableAcessor(GlobalVariable variable) {
+ this.variable = variable;
+ }
+
+ public IRubyObject getValue() {
+ return variable.get();
+ }
+
+ public IRubyObject setValue(IRubyObject newValue) {
+ return variable.set(newValue);
+ }
+}
Index: src/org/jruby/ext/ffi/io/FileDescriptorIO.java
===================================================================
--- src/org/jruby/ext/ffi/io/FileDescriptorIO.java (revision 8091)
+++ src/org/jruby/ext/ffi/io/FileDescriptorIO.java (working copy)
@@ -68,7 +68,7 @@
} catch (InvalidValueException ex) {
throw new RuntimeException(ex);
}
- openFile.setMainStream(new ChannelStream(getRuntime(),
+ openFile.setMainStream(new ChannelStream(
new ChannelDescriptor(Factory.getInstance().newByteChannel(RubyNumeric.fix2int(fd)),
getNewFileno(), modes, new java.io.FileDescriptor())));
openFile.setPipeStream(openFile.getMainStream());
Index: src/org/jruby/ext/socket/RubyUNIXSocket.java
===================================================================
--- src/org/jruby/ext/socket/RubyUNIXSocket.java (revision 8091)
+++ src/org/jruby/ext/socket/RubyUNIXSocket.java (working copy)
@@ -311,7 +311,7 @@
protected void init_sock(Ruby runtime) throws Exception {
ModeFlags modes = new ModeFlags(ModeFlags.RDWR);
- openFile.setMainStream(new ChannelStream(runtime, new ChannelDescriptor(new UnixDomainSocketChannel(fd), getNewFileno(), modes, new java.io.FileDescriptor())));
+ openFile.setMainStream(new ChannelStream(new ChannelDescriptor(new UnixDomainSocketChannel(fd), getNewFileno(), modes, new java.io.FileDescriptor())));
openFile.setPipeStream(openFile.getMainStream());
openFile.setMode(modes.getOpenFileFlags());
openFile.getMainStream().setSync(true);
Index: src/org/jruby/internal/runtime/GlobalVariables.java
===================================================================
--- src/org/jruby/internal/runtime/GlobalVariables.java (revision 8091)
+++ src/org/jruby/internal/runtime/GlobalVariables.java (working copy)
@@ -47,13 +47,8 @@
* @author jpetersen
*/
public class GlobalVariables {
- private Ruby runtime;
private Map<String, GlobalVariable> globalVariables = new ConcurrentHashMap<String, GlobalVariable>();
- public GlobalVariables(Ruby runtime) {
- this.runtime = runtime;
- }
-
public void define(String name, IAccessor accessor) {
assert name != null;
assert accessor != null;
@@ -89,15 +84,16 @@
assert name.startsWith("$");
assert oldName.startsWith("$");
- if (runtime.getSafeLevel() >= 4) {
- throw runtime.newSecurityError("Insecure: can't alias global variable");
+ if (Ruby.getCurrentRuntime().getSafeLevel() >= 4) {
+ throw Ruby.getCurrentRuntime().newSecurityError("Insecure: can't alias global variable");
}
GlobalVariable oldVariable = createIfNotDefined(oldName);
GlobalVariable variable = (GlobalVariable)globalVariables.get(name);
if (variable != null && oldVariable != variable && variable.isTracing()) {
- throw new RaiseException(runtime, runtime.getRuntimeError(), "can't alias in tracer", false);
+ throw new RaiseException(Ruby.getCurrentRuntime(), Ruby.getCurrentRuntime().getRuntimeError(),
+ "can't alias in tracer", false);
}
globalVariables.put(name, oldVariable);
@@ -111,16 +107,16 @@
if (variable != null) {
return variable.getAccessor().getValue();
}
- runtime.getWarnings().warning(ID.GLOBAL_NOT_INITIALIZED, "global variable `" + name + "' not initialized", name);
- return runtime.getNil();
+ Ruby.getCurrentRuntime().getWarnings().warning(ID.GLOBAL_NOT_INITIALIZED, "global variable `" + name + "' not initialized", name);
+ return Ruby.getCurrentRuntime().getNil();
}
public IRubyObject set(String name, IRubyObject value) {
assert name != null;
assert name.startsWith("$");
- if (runtime.getSafeLevel() >= 4) {
- throw runtime.newSecurityError("Insecure: can't change global variable value");
+ if (Ruby.getCurrentRuntime().getSafeLevel() >= 4) {
+ throw Ruby.getCurrentRuntime().newSecurityError("Insecure: can't change global variable value");
}
GlobalVariable variable = createIfNotDefined(name);
@@ -165,7 +161,7 @@
private GlobalVariable createIfNotDefined(String name) {
GlobalVariable variable = (GlobalVariable)globalVariables.get(name);
if (variable == null) {
- variable = GlobalVariable.newUndefined(runtime, name);
+ variable = GlobalVariable.newUndefined(Ruby.getCurrentRuntime(), name);
globalVariables.put(name, variable);
}
return variable;
Index: src/org/jruby/internal/runtime/RuntimeVariableAccessor.java
===================================================================
--- src/org/jruby/internal/runtime/RuntimeVariableAccessor.java (revision 0)
+++ src/org/jruby/internal/runtime/RuntimeVariableAccessor.java (revision 0)
@@ -0,0 +1,32 @@
+package org.jruby.internal.runtime;
+
+import org.jruby.runtime.IAccessor;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.Ruby;
+
+/**
+ * @author Fabio Kung
+ */
+public class RuntimeVariableAccessor implements IAccessor {
+ private final String name;
+
+ public RuntimeVariableAccessor(String name) {
+ this.name = name;
+ }
+
+ public RuntimeVariableAccessor(String name, IRubyObject value) {
+ this.name = name;
+ setValue(value);
+ }
+
+ public IRubyObject getValue() {
+ Ruby runtime = Ruby.getCurrentRuntime();
+ return runtime.getRuntimeVariable(this.name);
+ }
+
+ public IRubyObject setValue(IRubyObject newValue) {
+ Ruby runtime = Ruby.getCurrentRuntime();
+ runtime.setRuntimeVariable(this.name, newValue);
+ return newValue;
+ }
+}
Index: src/org/jruby/RubyArgsFile.java
===================================================================
--- src/org/jruby/RubyArgsFile.java (revision 8091)
+++ src/org/jruby/RubyArgsFile.java (working copy)
@@ -39,6 +39,7 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
+import org.jruby.internal.runtime.RuntimeVariableAccessor;
public class RubyArgsFile {
private static final class ArgsFileData {
@@ -106,12 +107,13 @@
runtime.getEnumerable().extend_object(argsFile);
- runtime.defineReadonlyVariable("$<", argsFile);
+ runtime.getGlobalVariables().defineReadonly("$<", new RuntimeVariableAccessor("$<", argsFile));
runtime.defineGlobalConstant("ARGF", argsFile);
RubyClass argfClass = argsFile.getMetaClass();
argfClass.defineAnnotatedMethods(RubyArgsFile.class);
- runtime.defineReadonlyVariable("$FILENAME", runtime.newString("-"));
+ runtime.getGlobalVariables().defineReadonly("$FILENAME",
+ new RuntimeVariableAccessor("$FILENAME", runtime.newString("-")));
}
@JRubyMethod(name = {"fileno", "to_i"})
Index: src/org/jruby/RubyFile.java
===================================================================
--- src/org/jruby/RubyFile.java (revision 8091)
+++ src/org/jruby/RubyFile.java (working copy)
@@ -165,7 +165,7 @@
super(runtime, runtime.getFile());
this.path = path;
try {
- this.openFile.setMainStream(new ChannelStream(runtime, new ChannelDescriptor(Channels.newChannel(in), getNewFileno(), new FileDescriptor())));
+ this.openFile.setMainStream(new ChannelStream(new ChannelDescriptor(Channels.newChannel(in), getNewFileno(), new FileDescriptor())));
} catch (InvalidValueException ex) {
throw runtime.newErrnoEINVALError();
}
Index: src/org/jruby/Ruby.java
===================================================================
--- src/org/jruby/Ruby.java (revision 8091)
+++ src/org/jruby/Ruby.java (working copy)
@@ -110,6 +110,7 @@
import org.jruby.runtime.ObjectSpace;
import org.jruby.runtime.RubyEvent;
import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.GlobalVariableAcessor;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.encoding.EncodingService;
import org.jruby.runtime.load.Library;
@@ -122,6 +123,7 @@
import org.jruby.util.JRubyClassLoader;
import org.jruby.util.JavaNameMangler;
import org.jruby.util.KCode;
+import org.jruby.util.RuntimeContainer;
import org.jruby.util.SafePropertyAccessor;
import org.jruby.util.collections.WeakHashSet;
import org.jruby.util.io.ChannelDescriptor;
@@ -136,7 +138,7 @@
* multiple instances of each class. This means that in multi-runtime mode
* (or really, multi-VM mode, where each JRuby instance is a ruby "VM"), objects
* generally can't be transported across runtimes without marshaling.
- *
+ *
* This class roots everything that makes the JRuby runtime function, and
* provides a number of utility methods for constructing global types and
* accessing global runtime structures.
@@ -183,16 +185,27 @@
config.setError(err);
return newInstance(config);
}
-
+
+ public static Ruby getCurrentRuntime() {
+ JRubyClassLoader loader = (JRubyClassLoader) Thread.currentThread().getContextClassLoader();
+ while (!(loader instanceof RuntimeContainer)) {
+ loader = (JRubyClassLoader) loader.getParent();
+ }
+ return ((RuntimeContainer) loader).getRuntime();
+ }
+
/**
* Create and initialize a new JRuby runtime. The properties of the
* specified RubyInstanceConfig will be used to determine various JRuby
* runtime characteristics.
- *
+ *
* @param config The configuration to use for the new instance
* @see org.jruby.RubyInstanceConfig
*/
private Ruby(RubyInstanceConfig config) {
+ Thread currentThread = Thread.currentThread();
+ currentThread.setContextClassLoader(new RuntimeContainer(currentThread.getContextClassLoader(), this));
+
this.config = config;
this.threadService = new ThreadService(this);
if(config.isSamplingEnabled()) {
@@ -209,18 +222,18 @@
this.beanManager = new BeanManager(this, config.isManagementEnabled());
this.jitCompiler = new JITCompiler(this);
this.parserStats = new ParserStats(this);
-
+
this.beanManager.register(new Config(this));
this.beanManager.register(parserStats);
this.beanManager.register(new ClassCache(this));
}
-
+
/**
* Evaluates a script under the current scope (perhaps the top-level
* scope) and returns the result (generally the last value calculated).
* This version goes straight into the interpreter, bypassing compilation
* and runtime preparation typical to normal script runs.
- *
+ *
* @param script The scriptlet to run
* @returns The result of the eval
*/
@@ -229,7 +242,7 @@
DynamicScope currentScope = context.getCurrentScope();
ManyVarsDynamicScope newScope = new ManyVarsDynamicScope(new EvalStaticScope(currentScope.getStaticScope()), currentScope);
Node node = parseEval(script, "<script>", newScope, 0);
-
+
try {
context.preEvalScriptlet(newScope);
return node.interpret(this, context, context.getFrameSelf(), Block.NULL_BLOCK);
@@ -243,20 +256,20 @@
context.postEvalScriptlet();
}
}
-
+
/**
- * Parse and execute the specified script
+ * Parse and execute the specified script
* This differs from the other methods in that it accepts a string-based script and
* parses and runs it as though it were loaded at a command-line. This is the preferred
* way to start up a new script when calling directly into the Ruby object (which is
* generally *dis*couraged.
- *
+ *
* @param script The contents of the script to run as a normal, root script
* @return The last value of the script
*/
public IRubyObject executeScript(String script, String filename) {
byte[] bytes;
-
+
try {
bytes = script.getBytes(KCode.NONE.getKCode());
} catch (UnsupportedEncodingException e) {
@@ -265,7 +278,7 @@
Node node = parseInline(new ByteArrayInputStream(bytes), filename, null);
ThreadContext context = getCurrentContext();
-
+
String oldFile = context.getFile();
int oldLine = context.getLine();
try {
@@ -277,22 +290,22 @@
context.setLine(oldLine);
}
}
-
+
/**
* Run the script contained in the specified input stream, using the
* specified filename as the name of the script being executed. The stream
* will be read fully before being parsed and executed. The given filename
* will be used for the ruby $PROGRAM_NAME and $0 global variables in this
* runtime.
- *
+ *
* This method is intended to be called once per runtime, generally from
* Main or from main-like top-level entry points.
- *
+ *
* As part of executing the script loaded from the input stream, various
* RubyInstanceConfig properties will be used to determine whether to
* compile the script before execution or run with various wrappers (for
* looping, printing, and so on, see jruby -help).
- *
+ *
* @param inputStream The InputStream from which to read the script contents
* @param filename The filename to use when parsing, and for $PROGRAM_NAME
* and $0 ruby global variables.
@@ -314,7 +327,7 @@
getGlobalVariables().set("$" + entry.getKey().toString(), varvalue);
}
-
+
if(config.isYARVEnabled()) {
if (config.isShowBytecode()) System.err.print("error: bytecode printing only works with JVM bytecode");
new YARVCompiledRunner(this, inputStream, filename).run();
@@ -350,7 +363,7 @@
* is used to verify that the script syntax is valid, for jruby -c. The
* current scope (generally the top-level scope) is used as the parent
* scope for parsing.
- *
+ *
* @param inputStream The input stream from which to read the script
* @param filename The filename to use for parsing
* @returns The root node of the parsed script
@@ -362,12 +375,12 @@
return parseFile(inputStream, filename, getCurrentContext().getCurrentScope());
}
}
-
+
/**
* Run the given script with a "while gets; end" loop wrapped around it.
* This is primarily used for the -n command-line flag, to allow writing
* a short script that processes input lines using the specified code.
- *
+ *
* @param scriptNode The root node of the script to execute
* @param printing Whether $_ should be printed after each loop (as in the
* -p command-line flag)
@@ -380,7 +393,7 @@
*/
public IRubyObject runWithGetsLoop(Node scriptNode, boolean printing, boolean processLineEnds, boolean split, boolean yarvCompile) {
ThreadContext context = getCurrentContext();
-
+
Script script = null;
YARVCompiledRunner runner = null;
boolean compile = getInstanceConfig().getCompileMode().shouldPrecompileCLI();
@@ -393,22 +406,22 @@
} else if (yarvCompile) {
runner = tryCompileYarv(scriptNode);
}
-
+
if (processLineEnds) {
getGlobalVariables().set("$\\", getGlobalVariables().get("$/"));
}
-
+
while (RubyKernel.gets(context, getTopSelf(), IRubyObject.NULL_ARRAY).isTrue()) {
loop: while (true) { // Used for the 'redo' command
try {
if (processLineEnds) {
getGlobalVariables().get("$_").callMethod(context, "chop!");
}
-
+
if (split) {
getGlobalVariables().set("$F", getGlobalVariables().get("$_").callMethod(context, "split"));
}
-
+
if (script != null) {
runScript(script);
} else if (runner != null) {
@@ -416,7 +429,7 @@
} else {
runInterpreter(scriptNode);
}
-
+
if (printing) RubyKernel.print(context, getKernel(), new IRubyObject[] {getGlobalVariables().get("$_")});
break loop;
} catch (JumpException.RedoJump rj) {
@@ -430,14 +443,14 @@
}
}
}
-
+
return getNil();
}
-
+
/**
* Run the specified script without any of the loop-processing wrapper
* code.
- *
+ *
* @param scriptNode The root node of the script to be executed
* @param yarvCompile Whether to compile the script to YARV (Ruby 1.9)
* bytecode before execution
@@ -456,7 +469,7 @@
return getNil();
}
}
-
+
if (script != null) {
if (config.isShowBytecode()) {
return nilObject;
@@ -470,11 +483,11 @@
return runInterpreter(scriptNode);
}
}
-
+
private Script tryCompile(Node node) {
return tryCompile(node, new JRubyClassLoader(getJRubyClassLoader()));
}
-
+
private Script tryCompile(Node node, JRubyClassLoader classLoader) {
Script script = null;
try {
@@ -533,10 +546,10 @@
System.err.println("Error, could not compile; pass -d or -J-Djruby.jit.logging.verbose=true for more details");
}
}
-
+
return script;
}
-
+
private YARVCompiledRunner tryCompileYarv(Node node) {
try {
StandardYARVCompiler compiler = new StandardYARVCompiler(this);
@@ -553,17 +566,17 @@
return null;
}
}
-
+
private IRubyObject runScript(Script script) {
ThreadContext context = getCurrentContext();
-
+
try {
return script.load(context, context.getFrameSelf(), IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
} catch (JumpException.ReturnJump rj) {
return (IRubyObject) rj.getValue();
}
}
-
+
private IRubyObject runYarv(YARVCompiledRunner runner) {
try {
return runner.run();
@@ -571,12 +584,12 @@
return (IRubyObject) rj.getValue();
}
}
-
+
private IRubyObject runInterpreter(Node scriptNode) {
ThreadContext context = getCurrentContext();
-
+
assert scriptNode != null : "scriptNode is not null";
-
+
try {
return scriptNode.interpret(this, context, getTopSelf(), Block.NULL_BLOCK);
} catch (JumpException.ReturnJump rj) {
@@ -587,11 +600,11 @@
public Parser getParser() {
return parser;
}
-
+
public BeanManager getBeanManager() {
return beanManager;
}
-
+
public JITCompiler getJITCompiler() {
return jitCompiler;
}
@@ -602,16 +615,16 @@
public static Ruby getDefaultInstance() {
return newInstance();
}
-
+
@Deprecated
public static Ruby getCurrentInstance() {
return null;
}
-
+
@Deprecated
public static void setCurrentInstance(Ruby runtime) {
}
-
+
public int allocSymbolId() {
return symbolLastId.incrementAndGet();
}
@@ -621,7 +634,7 @@
/**
* Retrieve the module with the given name from the Object namespace.
- *
+ *
* @param name The name of the module
* @return The module or null if not found
*/
@@ -633,7 +646,7 @@
* Retrieve the module with the given name from the Object namespace. The
* module name must be an interned string, but this method will be faster
* than the non-interned version.
- *
+ *
* @param internedName The name of the module; <em>must</em> be an interned String
* @return The module or null if not found
*/
@@ -641,7 +654,7 @@
return (RubyModule) objectClass.fastGetConstantAt(internedName);
}
- /**
+ /**
* Retrieve the class with the given name from the Object namespace.
*
* @param name The name of the class
@@ -655,7 +668,7 @@
* Retrieve the class with the given name from the Object namespace. The
* module name must be an interned string, but this method will be faster
* than the non-interned version.
- *
+ *
* @param internedName the name of the class; <em>must</em> be an interned String!
* @return
*/
@@ -663,7 +676,7 @@
return objectClass.fastGetClass(internedName);
}
- /**
+ /**
* Define a new class under the Object namespace. Roughly equivalent to
* rb_define_class in MRI.
*
@@ -677,7 +690,7 @@
return defineClassUnder(name, superClass, allocator, objectClass);
}
- /**
+ /**
* A variation of defineClass that allows passing in an array of subplementary
* call sites for improving dynamic invocation performance.
*
@@ -694,7 +707,7 @@
/**
* Define a new class with the given name under the given module or class
* namespace. Roughly equivalent to rb_define_class_under in MRI.
- *
+ *
* If the name specified is already bound, its value will be returned if:
* * It is a class
* * No new superclass is being defined
@@ -738,23 +751,23 @@
}
return klazz;
}
-
+
boolean parentIsObject = parent == objectClass;
if (superClass == null) {
- String className = parentIsObject ? name : parent.getName() + "::" + name;
+ String className = parentIsObject ? name : parent.getName() + "::" + name;
warnings.warn(ID.NO_SUPER_CLASS, "no super class for `" + className + "', Object assumed", className);
-
+
superClass = objectClass;
}
return RubyClass.newClass(this, superClass, name, allocator, parent, !parentIsObject, callSites);
}
- /**
+ /**
* Define a new module under the Object namespace. Roughly equivalent to
* rb_define_module in MRI.
- *
+ *
* @param name The name of the new module
* @returns The new module
*/
@@ -765,7 +778,7 @@
/**
* Define a new module with the given name under the given module or
* class namespace. Roughly equivalent to rb_define_module_under in MRI.
- *
+ *
* @param name The name of the new module
* @param parent The class or module namespace under which to define the
* module
@@ -773,12 +786,12 @@
*/
public RubyModule defineModuleUnder(String name, RubyModule parent) {
IRubyObject moduleObj = parent.getConstantAt(name);
-
+
boolean parentIsObject = parent == objectClass;
if (moduleObj != null ) {
if (moduleObj.isModule()) return (RubyModule)moduleObj;
-
+
if (parentIsObject) {
throw newTypeError(moduleObj.getMetaClass().getName() + " is not a module");
} else {
@@ -792,7 +805,7 @@
/**
* From Object, retrieve the named module. If it doesn't exist a
* new module is created.
- *
+ *
* @param name The name of the module
* @returns The existing or new module
*/
@@ -810,9 +823,9 @@
}
- /**
+ /**
* Retrieve the current safe level.
- *
+ *
* @see org.jruby.Ruby#setSaveLevel
*/
public int getSafeLevel() {
@@ -820,15 +833,15 @@
}
- /**
+ /**
* Set the current safe level:
- *
+ *
* 0 - strings from streams/environment/ARGV are tainted (default)
* 1 - no dangerous operation by tainted value
* 2 - process/file operations prohibited
* 3 - all generated objects are tainted
* 4 - no global (non-tainted) variable modification/no direct output
- *
+ *
* The safe level is set using $SAFE in Ruby code. It is not particularly
* well supported in JRuby.
*/
@@ -877,7 +890,7 @@
public boolean isClassDefined(String name) {
return getModule(name) != null;
}
-
+
/**
* A ThreadFactory for when we're using pooled threads; we want to create
* the threads with daemon = true so they don't keep us from shutting down.
@@ -886,12 +899,12 @@
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
-
+
return thread;
}
}
- /**
+ /**
* This method is called immediately after constructing the Ruby instance.
* The main thread is prepared for execution, all core classes and libraries
* are initialized, and any libraries required on the command line are
@@ -902,12 +915,12 @@
ThreadContext tc = getCurrentContext();
safeLevel = config.getSafeLevel();
-
+
// Construct key services
loadService = config.createLoadService(this);
posix = POSIXFactory.getPOSIX(new JRubyPOSIXHandler(this), RubyInstanceConfig.nativeEnabled);
javaSupport = new JavaSupport(this);
-
+
if (RubyInstanceConfig.POOLING_ENABLED) {
Executors.newCachedThreadPool();
executor = new ThreadPoolExecutor(
@@ -918,7 +931,7 @@
new SynchronousQueue<Runnable>(),
new DaemonThreadFactory());
}
-
+
// initialize the root of the class hierarchy completely
initRoot();
@@ -927,11 +940,11 @@
// Initialize all the core classes
bootstrap();
-
+
// Initialize the "dummy" class used as a marker
dummyClass = new RubyClass(this, classClass);
dummyClass.freeze(tc);
-
+
// Create global constants and variables
RubyGlobal.createGlobals(tc, this);
@@ -940,7 +953,7 @@
// initialize builtin libraries
initBuiltins();
-
+
// Require in all libraries specified on command line
for (String scriptName : config.requiredLibraries()) {
RubyKernel.require(getTopSelf(), newString(scriptName), Block.NULL_BLOCK);
@@ -969,8 +982,8 @@
RubyObject.createObjectClass(this, objectClass);
RubyModule.createModuleClass(this, moduleClass);
- RubyClass.createClassClass(this, classClass);
-
+ RubyClass.createClassClass(classClass);
+
// set constants now that they're initialized
objectClass.setConstant("Object", objectClass);
objectClass.setConstant("Class", classClass);
@@ -1144,10 +1157,10 @@
scriptError = defineClassIfAllowed("ScriptError", exceptionClass);
rangeError = defineClassIfAllowed("RangeError", standardError);
signalException = defineClassIfAllowed("SignalException", exceptionClass);
-
+
if (profile.allowClass("NameError")) {
nameError = RubyNameError.createNameErrorClass(this, standardError);
- nameErrorMessage = RubyNameError.createNameErrorMessageClass(this, nameError);
+ nameErrorMessage = RubyNameError.createNameErrorMessageClass(this, nameError);
}
if (profile.allowClass("NoMethodError")) {
noMethodError = RubyNoMethodError.createNoMethodErrorClass(this, nameError);
@@ -1185,14 +1198,14 @@
if (config.getCompatVersion() == CompatVersion.RUBY1_9) {
if (profile.allowClass("EncodingError")) {
- encodingError = defineClass("EncodingError", standardError, standardError.getAllocator());
+ encodingError = defineClass("EncodingError", standardError, standardError.getAllocator());
encodingCompatibilityError = defineClassUnder("CompatibilityError", encodingError, encodingError.getAllocator(), encodingClass);
}
}
initErrno();
}
-
+
private RubyClass defineClassIfAllowed(String name, RubyClass superClass) {
// TODO: should probably apply the null object pattern for a
// non-allowed class, rather than null
@@ -1237,9 +1250,9 @@
private void initBuiltins() {
addLazyBuiltin("java.rb", "java", "org.jruby.javasupport.Java");
addLazyBuiltin("jruby.rb", "jruby", "org.jruby.libraries.JRubyLibrary");
-
+
addLazyBuiltin("minijava.rb", "minijava", "org.jruby.java.MiniJava");
-
+
addLazyBuiltin("jruby/ext.rb", "jruby/ext", "org.jruby.RubyJRuby$ExtLibrary");
addLazyBuiltin("jruby/core_ext.rb", "jruby/ext", "org.jruby.RubyJRuby$CoreExtLibrary");
addLazyBuiltin("jruby/type.rb", "jruby/type", "org.jruby.RubyJRuby$TypeLibrary");
@@ -1270,22 +1283,22 @@
if(RubyInstanceConfig.NATIVE_NET_PROTOCOL) {
addLazyBuiltin("net/protocol.rb", "net/protocol", "org.jruby.libraries.NetProtocolBufferedIOLibrary");
}
-
+
if (config.getCompatVersion() == CompatVersion.RUBY1_9) {
addLazyBuiltin("fiber.so", "fiber", "org.jruby.libraries.FiberLibrary");
}
-
+
addBuiltinIfAllowed("openssl.so", new Library() {
public void load(Ruby runtime, boolean wrap) throws IOException {
runtime.getLoadService().require("jruby/openssl/stub");
}
});
-
+
String[] builtins = {"fcntl", "yaml", "yaml/syck", "jsignal" };
for (String library : builtins) {
addBuiltinIfAllowed(library + ".rb", new BuiltinScript(library));
}
-
+
RubyKernel.autoload(topSelf, newSymbol("Java"), newString("java"));
if (config.getCompatVersion() == CompatVersion.RUBY1_9) {
@@ -1334,11 +1347,11 @@
public String getCurrentDirectory() {
return currentDirectory;
}
-
+
public RubyModule getEtc() {
return etcModule;
}
-
+
public void setEtc(RubyModule etcModule) {
this.etcModule = etcModule;
}
@@ -1354,14 +1367,14 @@
public RubyClass getClassClass() {
return classClass;
}
-
+
public RubyModule getKernel() {
return kernelModule;
}
void setKernel(RubyModule kernelModule) {
this.kernelModule = kernelModule;
}
-
+
public RubyClass getDummy() {
return dummyClass;
}
@@ -1371,14 +1384,14 @@
}
void setComparable(RubyModule comparableModule) {
this.comparableModule = comparableModule;
- }
+ }
public RubyClass getNumeric() {
return numericClass;
}
void setNumeric(RubyClass numericClass) {
this.numericClass = numericClass;
- }
+ }
public RubyClass getFloat() {
return floatClass;
@@ -1386,14 +1399,14 @@
void setFloat(RubyClass floatClass) {
this.floatClass = floatClass;
}
-
+
public RubyClass getInteger() {
return integerClass;
}
void setInteger(RubyClass integerClass) {
this.integerClass = integerClass;
- }
-
+ }
+
public RubyClass getFixnum() {
return fixnumClass;
}
@@ -1452,7 +1465,7 @@
public RubyClass getArray() {
return arrayClass;
- }
+ }
void setArray(RubyClass arrayClass) {
this.arrayClass = arrayClass;
}
@@ -1532,77 +1545,77 @@
}
void setMethod(RubyClass methodClass) {
this.methodClass = methodClass;
- }
+ }
public RubyClass getUnboundMethod() {
return unboundMethodClass;
}
void setUnboundMethod(RubyClass unboundMethodClass) {
this.unboundMethodClass = unboundMethodClass;
- }
+ }
public RubyClass getMatchData() {
return matchDataClass;
}
void setMatchData(RubyClass matchDataClass) {
this.matchDataClass = matchDataClass;
- }
+ }
public RubyClass getRegexp() {
return regexpClass;
}
void setRegexp(RubyClass regexpClass) {
this.regexpClass = regexpClass;
- }
+ }
public RubyClass getTime() {
return timeClass;
}
void setTime(RubyClass timeClass) {
this.timeClass = timeClass;
- }
+ }
public RubyModule getMath() {
return mathModule;
}
void setMath(RubyModule mathModule) {
this.mathModule = mathModule;
- }
+ }
public RubyModule getMarshal() {
return marshalModule;
}
void setMarshal(RubyModule marshalModule) {
this.marshalModule = marshalModule;
- }
+ }
public RubyClass getBignum() {
return bignumClass;
}
void setBignum(RubyClass bignumClass) {
this.bignumClass = bignumClass;
- }
+ }
public RubyClass getDir() {
return dirClass;
}
void setDir(RubyClass dirClass) {
this.dirClass = dirClass;
- }
+ }
public RubyClass getFile() {
return fileClass;
}
void setFile(RubyClass fileClass) {
this.fileClass = fileClass;
- }
+ }
public RubyClass getFileStat() {
return fileStatClass;
}
void setFileStat(RubyClass fileStatClass) {
this.fileStatClass = fileStatClass;
- }
+ }
public RubyModule getFileTest() {
return fileTestModule;
@@ -1610,20 +1623,20 @@
void setFileTest(RubyModule fileTestModule) {
this.fileTestModule = fileTestModule;
}
-
+
public RubyClass getIO() {
return ioClass;
}
void setIO(RubyClass ioClass) {
this.ioClass = ioClass;
- }
+ }
public RubyClass getThread() {
return threadClass;
}
void setThread(RubyClass threadClass) {
this.threadClass = threadClass;
- }
+ }
public RubyClass getThreadGroup() {
return threadGroupClass;
@@ -1631,7 +1644,7 @@
void setThreadGroup(RubyClass threadGroupClass) {
this.threadGroupClass = threadGroupClass;
}
-
+
public RubyThreadGroup getDefaultThreadGroup() {
return defaultThreadGroup;
}
@@ -1644,14 +1657,14 @@
}
void setContinuation(RubyClass continuationClass) {
this.continuationClass = continuationClass;
- }
+ }
public RubyClass getStructClass() {
return structClass;
}
void setStructClass(RubyClass structClass) {
this.structClass = structClass;
- }
+ }
public IRubyObject getTmsStruct() {
return tmsStruct;
@@ -1659,7 +1672,7 @@
void setTmsStruct(RubyClass tmsStruct) {
this.tmsStruct = tmsStruct;
}
-
+
public IRubyObject getPasswdStruct() {
return passwdStruct;
}
@@ -1679,43 +1692,43 @@
}
void setGC(RubyModule gcModule) {
this.gcModule = gcModule;
- }
+ }
public RubyModule getObjectSpaceModule() {
return objectSpaceModule;
}
void setObjectSpaceModule(RubyModule objectSpaceModule) {
this.objectSpaceModule = objectSpaceModule;
- }
+ }
public RubyModule getProcess() {
return processModule;
}
void setProcess(RubyModule processModule) {
this.processModule = processModule;
- }
+ }
public RubyClass getProcStatus() {
- return procStatusClass;
+ return procStatusClass;
}
void setProcStatus(RubyClass procStatusClass) {
this.procStatusClass = procStatusClass;
}
-
+
public RubyModule getProcUID() {
return procUIDModule;
}
void setProcUID(RubyModule procUIDModule) {
this.procUIDModule = procUIDModule;
}
-
+
public RubyModule getProcGID() {
return procGIDModule;
}
void setProcGID(RubyModule procGIDModule) {
this.procGIDModule = procGIDModule;
}
-
+
public RubyModule getProcSysModule() {
return procSysModule;
}
@@ -1780,11 +1793,11 @@
public RubyClass getFatal() {
return fatal;
}
-
+
public RubyClass getInterrupt() {
return interrupt;
}
-
+
public RubyClass getTypeError() {
return typeError;
}
@@ -1796,7 +1809,7 @@
public RubyClass getIndexError() {
return indexError;
}
-
+
public RubyClass getSyntaxError() {
return syntaxError;
}
@@ -1804,11 +1817,11 @@
public RubyClass getStandardError() {
return standardError;
}
-
+
public RubyClass getRuntimeError() {
return runtimeError;
}
-
+
public RubyClass getIOError() {
return ioError;
}
@@ -1909,31 +1922,23 @@
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
-
+
return loader;
}
public synchronized JRubyClassLoader getJRubyClassLoader() {
// FIXME: Get rid of laziness and handle restricted access elsewhere
if (!Ruby.isSecurityRestricted() && jrubyClassLoader == null) {
- jrubyClassLoader = new JRubyClassLoader(config.getLoader());
+ jrubyClassLoader = new RuntimeContainer(config.getLoader(), this);
}
-
+
return jrubyClassLoader;
}
/** Defines a global variable
*/
public void defineVariable(final GlobalVariable variable) {
- globalVariables.define(variable.name(), new IAccessor() {
- public IRubyObject getValue() {
- return variable.get();
- }
-
- public IRubyObject setValue(IRubyObject newValue) {
- return variable.set(newValue);
- }
- });
+ globalVariables.define(variable.name(), new GlobalVariableAcessor(variable));
}
/** defines a readonly global variable
@@ -1942,7 +1947,7 @@
public void defineReadonlyVariable(String name, IRubyObject value) {
globalVariables.defineReadonly(name, new ValueAccessor(value));
}
-
+
public Node parseFile(InputStream in, String file, DynamicScope scope) {
if (parserStats != null) parserStats.addLoadParse();
return parser.parse(file, in, scope, new ParserConfiguration(0, false, false, true));
@@ -1955,42 +1960,42 @@
public Node parseEval(String content, String file, DynamicScope scope, int lineNumber) {
byte[] bytes;
-
+
try {
bytes = content.getBytes(KCode.NONE.getKCode());
} catch (UnsupportedEncodingException e) {
bytes = content.getBytes();
}
-
+
if (parserStats != null) parserStats.addEvalParse();
- return parser.parse(file, new ByteArrayInputStream(bytes), scope,
+ return parser.parse(file, new ByteArrayInputStream(bytes), scope,
new ParserConfiguration(lineNumber, false));
}
@Deprecated
- public Node parse(String content, String file, DynamicScope scope, int lineNumber,
+ public Node parse(String content, String file, DynamicScope scope, int lineNumber,
boolean extraPositionInformation) {
byte[] bytes;
-
+
try {
bytes = content.getBytes(KCode.NONE.getKCode());
} catch (UnsupportedEncodingException e) {
bytes = content.getBytes();
}
- return parser.parse(file, new ByteArrayInputStream(bytes), scope,
+ return parser.parse(file, new ByteArrayInputStream(bytes), scope,
new ParserConfiguration(lineNumber, extraPositionInformation, false));
}
-
+
public Node parseEval(ByteList content, String file, DynamicScope scope, int lineNumber) {
if (parserStats != null) parserStats.addEvalParse();
return parser.parse(file, content, scope, new ParserConfiguration(lineNumber, false));
}
- public Node parse(ByteList content, String file, DynamicScope scope, int lineNumber,
+ public Node parse(ByteList content, String file, DynamicScope scope, int lineNumber,
boolean extraPositionInformation) {
if (parserStats != null) parserStats.addJRubyModuleParse();
- return parser.parse(file, content, scope,
+ return parser.parse(file, content, scope,
new ParserConfiguration(lineNumber, extraPositionInformation, false));
}
@@ -2147,12 +2152,12 @@
}
}
}
-
+
public void loadFile(String scriptName, InputStream in, boolean wrap) {
IRubyObject self = wrap ? TopSelfFactory.createTopSelf(this) : getTopSelf();
ThreadContext context = getCurrentContext();
String file = context.getFile();
-
+
try {
secure(4); /* should alter global state */
@@ -2167,20 +2172,20 @@
context.setFile(file);
}
}
-
+
public void compileAndLoadFile(String filename, InputStream in, boolean wrap) {
IRubyObject self = wrap ? TopSelfFactory.createTopSelf(this) : getTopSelf();
ThreadContext context = getCurrentContext();
String file = context.getFile();
-
+
try {
secure(4); /* should alter global state */
context.setFile(filename);
context.preNodeEval(objectClass, self, filename);
-
+
Node scriptNode = parseFile(in, filename, null);
-
+
Script script = tryCompile(scriptNode, new JRubyClassLoader(jrubyClassLoader));
if (script == null) {
System.err.println("Error, could not compile; pass -J-Djruby.jit.logging.verbose=true for more details");
@@ -2203,7 +2208,7 @@
secure(4); /* should alter global state */
context.preNodeEval(objectClass, self);
-
+
script.load(context, self, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
} catch (JumpException.ReturnJump rj) {
return;
@@ -2214,16 +2219,16 @@
public class CallTraceFuncHook extends EventHook {
private RubyProc traceFunc;
-
+
public void setTraceFunc(RubyProc traceFunc) {
this.traceFunc = traceFunc;
}
-
+
public void eventHandler(ThreadContext context, String eventName, String file, int line, String name, IRubyObject type) {
if (!context.isWithinTrace()) {
if (file == null) file = "(ruby)";
if (type == null) type = getFalse();
-
+
RubyBinding binding = RubyBinding.newBinding(Ruby.this);
context.preTrace();
@@ -2246,14 +2251,14 @@
return true;
}
};
-
+
private final CallTraceFuncHook callTraceFuncHook = new CallTraceFuncHook();
-
+
public void addEventHook(EventHook hook) {
eventHooks.add(hook);
hasEventHooks = true;
}
-
+
public void removeEventHook(EventHook hook) {
eventHooks.remove(hook);
hasEventHooks = !eventHooks.isEmpty();
@@ -2261,15 +2266,15 @@
public void setTraceFunction(RubyProc traceFunction) {
removeEventHook(callTraceFuncHook);
-
+
if (traceFunction == null) {
return;
}
-
+
callTraceFuncHook.setTraceFunc(traceFunction);
addEventHook(callTraceFuncHook);
}
-
+
public void callEventHooks(ThreadContext context, RubyEvent event, String file, int line, String name, IRubyObject type) {
for (EventHook eventHook : eventHooks) {
if (eventHook.isInterestedInEvent(event)) {
@@ -2277,11 +2282,11 @@
}
}
}
-
+
public boolean hasEventHooks() {
return hasEventHooks;
}
-
+
public GlobalVariables getGlobalVariables() {
return globalVariables;
}
@@ -2325,7 +2330,7 @@
finalizers.put(finalizer, null);
}
}
-
+
public void removeInternalFinalizer(Finalizable finalizer) {
synchronized (internalFinalizersMutex) {
if (internalFinalizers != null) {
@@ -2435,15 +2440,15 @@
public RubyArray newArray(IRubyObject[] objects) {
return RubyArray.newArray(this, objects);
}
-
+
public RubyArray newArrayNoCopy(IRubyObject[] objects) {
return RubyArray.newArrayNoCopy(this, objects);
}
-
+
public RubyArray newArrayNoCopyLight(IRubyObject[] objects) {
return RubyArray.newArrayNoCopyLight(this, objects);
}
-
+
public RubyArray newArray(List<IRubyObject> list) {
return RubyArray.newArray(this, list);
}
@@ -2459,7 +2464,7 @@
public RubyFileStat newFileStat(String filename, boolean lstat) {
return RubyFileStat.newFileStat(this, filename, lstat);
}
-
+
public RubyFileStat newFileStat(FileDescriptor descriptor) {
return RubyFileStat.newFileStat(this, descriptor);
}
@@ -2514,7 +2519,7 @@
public RubyString newString(String string) {
return RubyString.newString(this, string);
}
-
+
public RubyString newString(ByteList byteList) {
return RubyString.newString(this, byteList);
}
@@ -2522,7 +2527,7 @@
@Deprecated
public RubyString newStringShared(ByteList byteList) {
return RubyString.newStringShared(this, byteList);
- }
+ }
public RubySymbol newSymbol(String name) {
return symbolTable.getSymbol(name);
@@ -2533,7 +2538,7 @@
* name String. Don't intern your string just to call this version - the
* overhead of interning will more than wipe out any benefit from the faster
* lookup.
- *
+ *
* @param internedName the symbol name, <em>must</em> be interned! if in
* doubt, call {@link #newSymbol(String)} instead.
* @return the symbol for name
@@ -2550,8 +2555,8 @@
public RaiseException newRuntimeError(String message) {
return newRaiseException(getRuntimeError(), message);
- }
-
+ }
+
public RaiseException newArgumentError(String message) {
return newRaiseException(getArgumentError(), message);
}
@@ -2635,14 +2640,14 @@
public RaiseException newErrnoEEXISTError(String message) {
return newRaiseException(getErrno().fastGetClass("EEXIST"), message);
}
-
+
public RaiseException newErrnoEDOMError(String message) {
return newRaiseException(getErrno().fastGetClass("EDOM"), "Domain error - " + message);
- }
-
+ }
+
public RaiseException newErrnoECHILDError() {
return newRaiseException(getErrno().fastGetClass("ECHILD"), "No child processes");
- }
+ }
public RaiseException newIndexError(String message) {
return newRaiseException(getIndexError(), message);
@@ -2683,7 +2688,7 @@
public RaiseException newNotImplementedError(String message) {
return newRaiseException(getNotImplementedError(), message);
}
-
+
public RaiseException newInvalidEncoding(String message) {
return newRaiseException(fastGetClass("Iconv").fastGetClass("InvalidEncoding"), message);
}
@@ -2803,6 +2808,14 @@
return stackTraces;
}
+ public IRubyObject getRuntimeVariable(String name) {
+ return this.runtimeVariables.get(name);
+ }
+
+ public void setRuntimeVariable(String name, IRubyObject value) {
+ this.runtimeVariables.put(name, value);
+ }
+
public void setRandomSeed(long randomSeed) {
this.randomSeed = randomSeed;
}
@@ -2919,27 +2932,27 @@
public static boolean isSecurityRestricted() {
return securityRestricted;
}
-
+
public static void setSecurityRestricted(boolean restricted) {
securityRestricted = restricted;
}
-
+
public POSIX getPosix() {
return posix;
}
-
+
public void setRecordSeparatorVar(GlobalVariable recordSeparatorVar) {
this.recordSeparatorVar = recordSeparatorVar;
}
-
+
public GlobalVariable getRecordSeparatorVar() {
return recordSeparatorVar;
}
-
+
public Set<Script> getJittedMethods() {
return jittedMethods;
}
-
+
public ExecutorService getExecutor() {
return executor;
}
@@ -2958,7 +2971,7 @@
private volatile int constantGeneration = 1;
private final ThreadService threadService;
-
+
private POSIX posix;
private int stackTraces = 0;
@@ -2972,17 +2985,17 @@
private Random random = new Random();
private List<EventHook> eventHooks = new Vector<EventHook>();
- private boolean hasEventHooks;
+ private boolean hasEventHooks;
private boolean globalAbortOnExceptionEnabled = false;
private boolean doNotReverseLookupEnabled = false;
private volatile boolean objectSpaceEnabled;
-
+
private final Set<Script> jittedMethods = Collections.synchronizedSet(new WeakHashSet<Script>());
-
+
private static ThreadLocal<Ruby> currentRuntime = new ThreadLocal<Ruby>();
-
+
private long globalState = 1;
-
+
private int safeLevel = -1;
// Default objects
@@ -2994,7 +3007,7 @@
private IRubyObject verbose;
private IRubyObject debug;
-
+
private RubyThreadGroup defaultThreadGroup;
/**
@@ -3029,7 +3042,7 @@
marshalModule, etcModule, fileTestModule, gcModule,
objectSpaceModule, processModule, procUIDModule, procGIDModule,
procSysModule, precisionModule, errnoModule;
-
+
// record separator var, to speed up io ops that use it
private GlobalVariable recordSeparatorVar;
@@ -3047,13 +3060,13 @@
// Java support
private JavaSupport javaSupport;
private JRubyClassLoader jrubyClassLoader;
-
+
// Management/monitoring
private BeanManager beanManager;
// Parser stats
private ParserStats parserStats;
-
+
// Compilation
private final JITCompiler jitCompiler;
@@ -3081,7 +3094,8 @@
private LoadService loadService;
private EncodingService encodingService;
- private GlobalVariables globalVariables = new GlobalVariables(this);
+ private GlobalVariables globalVariables = new GlobalVariables();
+ private Map<String, IRubyObject> runtimeVariables = new ConcurrentHashMap<String, IRubyObject>();
private RubyWarnings warnings = new RubyWarnings(this);
// Contains a list of all blocks (as Procs) that should be called when
@@ -3105,7 +3119,7 @@
* weakly referenced, to be executed on tearDown.
*/
private Map<Finalizable, Object> finalizers;
-
+
/**
* A list of JRuby-internal finalizers, weakly referenced,
* to be executed on tearDown.
@@ -3117,7 +3131,8 @@
// mutex that controls modifications of internal finalizers
private final Object internalFinalizersMutex = new Object();
-
+
// A thread pool to use for executing this runtime's Ruby threads
private ExecutorService executor;
+
}
Index: src/org/jruby/RubyModule.java
===================================================================
--- src/org/jruby/RubyModule.java (revision 8091)
+++ src/org/jruby/RubyModule.java (working copy)
@@ -190,13 +190,16 @@
private final Map<String, CacheEntry> cachedMethods = new ConcurrentHashMap<String, CacheEntry>(12, 0.75f, 1);
protected static class Generation {
- public volatile int hash;
+ private volatile int hash;
public Generation() {
hash = hashCode();
}
public synchronized void update() {
hash = hash + (hashCode() * 31);
}
+ public int hash() {
+ return hash;
+ }
}
protected final Generation generation;
@@ -946,7 +949,7 @@
}
public final int getSerialNumber() {
- return generation.hash;
+ return generation.hash();
}
private CacheEntry cacheHit(String name) {
Index: src/org/jruby/util/RuntimeContainer.java
===================================================================
--- src/org/jruby/util/RuntimeContainer.java (revision 0)
+++ src/org/jruby/util/RuntimeContainer.java (revision 0)
@@ -0,0 +1,19 @@
+package org.jruby.util;
+
+import org.jruby.Ruby;
+
+/**
+ * @author Fabio Kung
+ */
+public class RuntimeContainer extends JRubyClassLoader {
+ private final Ruby runtime;
+
+ public RuntimeContainer(ClassLoader parent, Ruby runtime) {
+ super(parent);
+ this.runtime = runtime;
+ }
+
+ public Ruby getRuntime() {
+ return runtime;
+ }
+}
Index: src/org/jruby/util/io/ChannelDescriptor.java
===================================================================
--- src/org/jruby/util/io/ChannelDescriptor.java (revision 8091)
+++ src/org/jruby/util/io/ChannelDescriptor.java (working copy)
@@ -94,13 +94,6 @@
private AtomicInteger refCounter;
/**
- * Used to work-around blocking problems with STDIN. In most cases <code>null</code>.
- * See {@link #ChannelDescriptor(InputStream, int, ModeFlags, FileDescriptor)}
- * for more details. You probably should not use it.
- */
- private InputStream baseInputStream;
-
- /**
* Process streams get Channel.newChannel()ed into FileChannel but are not actually
* seekable. So instead of just the isSeekable check doing instanceof FileChannel,
* we must also add this boolean to check, which we set to false when it's known
@@ -148,28 +141,6 @@
}
/**
- * Special constructor to create the ChannelDescriptor out of the stream, file number,
- * mode flags, and file descriptor object. The channel will be created from the
- * provided stream. The channel will be kept open until all ChannelDescriptor
- * references to it have been closed. <b>Note:</b> in most cases, you should not
- * use this constructor, it's reserved mostly for STDIN.
- *
- * @param baseInputStream The stream to create the channel for the new descriptor
- * @param fileno The file number for the new descriptor
- * @param originalModes The mode flags for the new descriptor
- * @param fileDescriptor The java.io.FileDescriptor object for the new descriptor
- */
- public ChannelDescriptor(InputStream baseInputStream, int fileno, ModeFlags originalModes, FileDescriptor fileDescriptor) {
- // The reason why we need the stream is to be able to invoke available() on it.
- // STDIN in Java is non-interruptible, non-selectable, and attempt to read
- // on such stream might lead to thread being blocked without *any* way to unblock it.
- // That's where available() comes it, so at least we could check whether
- // anything is available to be read without blocking.
- this(Channels.newChannel(baseInputStream), fileno, originalModes, fileDescriptor, new AtomicInteger(1), true);
- this.baseInputStream = baseInputStream;
- }
-
- /**
* Construct a new ChannelDescriptor with the given channel, file number,
* and file descriptor object. The channel will be kept open until all ChannelDescriptor
* references to it have been closed. The channel's capabilities will be used
@@ -217,30 +188,20 @@
}
/**
- * This is intentionally non-public, since it should not be really
- * used outside of very limited use case (handling of STDIN).
- * See {@link #ChannelDescriptor(InputStream, int, ModeFlags, FileDescriptor)}
- * for more info.
- */
- /*package-protected*/ InputStream getBaseInputStream() {
- return baseInputStream;
- }
-
- /**
* Whether the channel associated with this descriptor is seekable (i.e.
* whether it is instanceof FileChannel).
*
* @return true if the associated channel is seekable, false otherwise
*/
public boolean isSeekable() {
- return canBeSeekable && channel instanceof FileChannel;
+ return canBeSeekable && getChannel() instanceof FileChannel;
}
/**
* Set the channel to be explicitly seekable or not, for streams that appear
* to be seekable with the instanceof FileChannel check.
*
- * @param seekable Whether the channel is seekable or not.
+ * @param canBeSeekable Whether the channel is seekable or not.
*/
public void setCanBeSeekable(boolean canBeSeekable) {
this.canBeSeekable = canBeSeekable;
@@ -251,7 +212,7 @@
* for which many operations are simply noops.
*/
public boolean isNull() {
- return channel instanceof NullChannel;
+ return getChannel() instanceof NullChannel;
}
/**
@@ -261,7 +222,7 @@
* @return true if the associated channel is writable, false otherwise
*/
public boolean isWritable() {
- return channel instanceof WritableByteChannel;
+ return getChannel() instanceof WritableByteChannel;
}
/**
@@ -270,7 +231,7 @@
* @return true if the associated channel is open, false otherwise
*/
public boolean isOpen() {
- return channel.isOpen();
+ return getChannel().isOpen();
}
/**
@@ -321,7 +282,7 @@
if (DEBUG) getLogger("ChannelDescriptor").info("Reopen fileno " + newFileno + ", refs now: " + refCounter.get());
- return new ChannelDescriptor(channel, newFileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
+ return new ChannelDescriptor(getChannel(), newFileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
}
}
@@ -338,7 +299,7 @@
if (DEBUG) getLogger("ChannelDescriptor").info("Reopen fileno " + fileno + ", refs now: " + refCounter.get());
- return new ChannelDescriptor(channel, fileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
+ return new ChannelDescriptor(getChannel(), fileno, originalModes, fileDescriptor, refCounter, canBeSeekable);
}
}
@@ -386,10 +347,10 @@
* @return the new offset into the FileChannel.
*/
public long lseek(long offset, int whence) throws IOException, InvalidValueException, PipeException, BadDescriptorException {
- if (channel instanceof FileChannel) {
+ if (getChannel() instanceof FileChannel) {
checkOpen();
- FileChannel fileChannel = (FileChannel)channel;
+ FileChannel fileChannel = (FileChannel)getChannel();
try {
long pos;
switch (whence) {
@@ -459,7 +420,7 @@
public int read(ByteBuffer buffer) throws IOException, BadDescriptorException {
checkOpen();
- ReadableByteChannel readChannel = (ReadableByteChannel) channel;
+ ReadableByteChannel readChannel = (ReadableByteChannel) getChannel();
int bytesRead = 0;
bytesRead = readChannel.read(buffer);
@@ -478,10 +439,10 @@
public int internalWrite(ByteBuffer buffer) throws IOException, BadDescriptorException {
checkOpen();
- WritableByteChannel writeChannel = (WritableByteChannel)channel;
+ WritableByteChannel writeChannel = (WritableByteChannel)getChannel();
if (isSeekable() && originalModes.isAppendable()) {
- FileChannel fileChannel = (FileChannel)channel;
+ FileChannel fileChannel = (FileChannel)getChannel();
fileChannel.position(fileChannel.size());
}
@@ -677,7 +638,7 @@
}
// if channel is already closed, we're no longer valid
- if (!channel.isOpen()) {
+ if (!getChannel().isOpen()) {
throw new BadDescriptorException();
}
@@ -687,7 +648,7 @@
if (DEBUG) getLogger("ChannelDescriptor").info("Descriptor for fileno " + fileno + " refs: " + count);
if (count <= 0) {
- channel.close();
+ getChannel().close();
}
}
}
Index: src/org/jruby/util/io/ChannelStream.java
===================================================================
--- src/org/jruby/util/io/ChannelStream.java (revision 8091)
+++ src/org/jruby/util/io/ChannelStream.java (working copy)
@@ -87,10 +87,9 @@
private final static int BULK_READ_SIZE = 16 * 1024;
private final static ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
- private Ruby runtime;
protected ModeFlags modes;
protected boolean sync = false;
-
+
protected volatile ByteBuffer buffer; // r/w buffer
protected boolean reading; // are we reading or writing?
private ChannelDescriptor descriptor;
@@ -100,25 +99,23 @@
private boolean eof = false;
- public ChannelStream(Ruby runtime, ChannelDescriptor descriptor, ModeFlags modes, FileDescriptor fileDescriptor) throws InvalidValueException {
+ public ChannelStream(ChannelDescriptor descriptor, ModeFlags modes, FileDescriptor fileDescriptor) throws InvalidValueException {
descriptor.checkNewModes(modes);
-
- this.runtime = runtime;
+
this.descriptor = descriptor;
this.modes = modes;
this.buffer = ByteBuffer.allocate(BUFSIZE);
buffer.flip();
this.reading = true;
-
+
// this constructor is used by fdopen, so we don't increment descriptor ref count
}
- public ChannelStream(Ruby runtime, ChannelDescriptor descriptor) {
- this(runtime, descriptor, descriptor.getFileDescriptor());
+ public ChannelStream(ChannelDescriptor descriptor) {
+ this(descriptor, descriptor.getFileDescriptor());
}
- public ChannelStream(Ruby runtime, ChannelDescriptor descriptor, FileDescriptor fileDescriptor) {
- this.runtime = runtime;
+ public ChannelStream(ChannelDescriptor descriptor, FileDescriptor fileDescriptor) {
this.descriptor = descriptor;
this.modes = descriptor.getOriginalModes();
buffer = ByteBuffer.allocate(BUFSIZE);
@@ -126,10 +123,9 @@
this.reading = true;
}
- public ChannelStream(Ruby runtime, ChannelDescriptor descriptor, ModeFlags modes) throws InvalidValueException {
+ public ChannelStream(ChannelDescriptor descriptor, ModeFlags modes) throws InvalidValueException {
descriptor.checkNewModes(modes);
-
- this.runtime = runtime;
+
this.descriptor = descriptor;
this.modes = modes;
buffer = ByteBuffer.allocate(BUFSIZE);
@@ -138,9 +134,9 @@
}
public Ruby getRuntime() {
- return runtime;
+ return Ruby.getCurrentRuntime();
}
-
+
public void checkReadable() throws IOException {
if (!modes.isReadable()) throw new IOException("not opened for reading");
}
@@ -152,11 +148,11 @@
public void checkPermissionsSubsetOf(ModeFlags subsetModes) {
subsetModes.isSubsetOf(modes);
}
-
+
public ModeFlags getModes() {
return modes;
}
-
+
public boolean isSync() {
return sync;
}
@@ -176,11 +172,11 @@
Thread.sleep(10);
}
}
-
+
public boolean readDataBuffered() {
return reading && buffer.hasRemaining();
}
-
+
public boolean writeDataBuffered() {
return !reading && buffer.position() > 0;
}
@@ -202,22 +198,22 @@
PARAGRAPH_SEPARATOR : separatorString;
descriptor.checkOpen();
-
+
if (feof()) {
return null;
}
-
+
int c = read();
-
+
if (c == -1) {
return null;
}
-
+
// unread back
buffer.position(buffer.position() - 1);
ByteList buf = new ByteList(40);
-
+
byte first = separator.bytes[separator.begin];
LineLoop : while (true) {
@@ -225,7 +221,7 @@
byte[] bytes = buffer.array();
int offset = buffer.position();
int max = buffer.limit();
-
+
// iterate over remainder of buffer until we find a match
for (int i = offset; i < max; i++) {
c = bytes[i];
@@ -240,13 +236,13 @@
break ReadLoop;
}
}
-
+
// no match, append remainder of buffer and continue with next block
buf.append(bytes, offset, buffer.remaining());
int read = refillBuffer();
if (read == -1) break LineLoop;
}
-
+
// found a match above, check if remaining separator characters match, appending as we go
for (int i = 0; i < separator.realSize; i++) {
if (c == -1) {
@@ -272,7 +268,7 @@
return buf;
}
-
+
/**
* An version of read that reads all bytes up to and including a terminator byte.
* <p>
@@ -282,7 +278,7 @@
* @param dst The output buffer.
* @param terminator The byte to terminate reading.
* @return The number of bytes read, or -1 if EOF is reached.
- *
+ *
* @throws java.io.IOException
* @throws org.jruby.util.io.BadDescriptorException
*/
@@ -290,7 +286,7 @@
checkReadable();
ensureRead();
descriptor.checkOpen();
-
+
int totalRead = 0;
boolean found = false;
if (ungotc != -1) {
@@ -324,7 +320,7 @@
}
return totalRead;
}
-
+
public synchronized ByteList readall() throws IOException, BadDescriptorException {
if (descriptor.isSeekable()) {
invalidateBuffer();
@@ -336,7 +332,7 @@
}
left += ungotc != -1 ? 1 : 0;
ByteList result = new ByteList((int) left);
- ByteBuffer buf = ByteBuffer.wrap(result.unsafeBytes(),
+ ByteBuffer buf = ByteBuffer.wrap(result.unsafeBytes(),
result.begin(), (int) left);
if (ungotc != -1) {
buf.put((byte) ungotc);
@@ -358,7 +354,7 @@
ByteList byteList = new ByteList();
ByteList read = fread(BUFSIZE);
-
+
if (read == null) {
eof = true;
return byteList;
@@ -370,14 +366,14 @@
}
return byteList;
- }
+ }
}
-
+
/**
* <p>Close IO handler resources.</p>
- * @throws IOException
- * @throws BadDescriptorException
- *
+ * @throws IOException
+ * @throws BadDescriptorException
+ *
* @see org.jruby.util.IOHandler#close()
*/
public synchronized void fclose() throws IOException, BadDescriptorException {
@@ -408,7 +404,7 @@
/**
* Internal close, to safely work for finalizing.
* @param finalizing true if this is in a finalizing context
- * @throws IOException
+ * @throws IOException
* @throws BadDescriptorException
*/
private void closeForFinalize() {
@@ -422,8 +418,8 @@
}
/**
- * @throws IOException
- * @throws BadDescriptorException
+ * @throws IOException
+ * @throws BadDescriptorException
* @see org.jruby.util.IOHandler#flush()
*/
public synchronized int fflush() throws IOException, BadDescriptorException {
@@ -435,14 +431,14 @@
}
return 0;
}
-
+
/**
* Flush the write buffer to the channel (if needed)
* @throws IOException
*/
private void flushWrite() throws IOException, BadDescriptorException {
if (reading || !modes.isWritable() || buffer.position() == 0) return; // Don't bother
-
+
int len = buffer.position();
buffer.flip();
int n = descriptor.write(buffer);
@@ -452,7 +448,7 @@
}
buffer.clear();
}
-
+
/**
* Flush the write buffer to the channel (if needed)
* @throws IOException
@@ -494,12 +490,7 @@
* @see org.jruby.util.IOHandler#getInputStream()
*/
public InputStream newInputStream() {
- InputStream in = descriptor.getBaseInputStream();
- if (in == null) {
- return new BufferedInputStream(Channels.newInputStream((ReadableByteChannel)descriptor.getChannel()));
- } else {
- return in;
- }
+ return new BufferedInputStream(Channels.newInputStream((ReadableByteChannel) descriptor.getChannel()));
}
/**
@@ -508,28 +499,28 @@
public OutputStream newOutputStream() {
return new BufferedOutputStream(Channels.newOutputStream((WritableByteChannel)descriptor.getChannel()));
}
-
+
public void clearerr() {
eof = false;
}
-
+
/**
- * @throws IOException
- * @throws BadDescriptorException
+ * @throws IOException
+ * @throws BadDescriptorException
* @see org.jruby.util.IOHandler#isEOF()
*/
public boolean feof() throws IOException, BadDescriptorException {
checkReadable();
-
+
if (eof) {
return true;
} else {
return false;
}
}
-
+
/**
- * @throws IOException
+ * @throws IOException
* @see org.jruby.util.IOHandler#pos()
*/
public synchronized long fgetpos() throws IOException, PipeException, InvalidValueException, BadDescriptorException {
@@ -550,14 +541,14 @@
throw new PipeException();
}
}
-
+
/**
* Implementation of libc "lseek", which seeks on seekable streams, raises
* EPIPE if the fd is assocated with a pipe, socket, or FIFO, and doesn't
* do anything for other cases (like stdio).
- *
- * @throws IOException
- * @throws InvalidValueException
+ *
+ * @throws IOException
+ * @throws InvalidValueException
* @see org.jruby.util.IOHandler#seek(long, int)
*/
public synchronized void lseek(long offset, int type) throws IOException, InvalidValueException, PipeException, BadDescriptorException {
@@ -636,7 +627,7 @@
reading = true;
}
}
-
+
private void resetForWrite() throws IOException {
if (descriptor.isSeekable()) {
FileChannel fileChannel = (FileChannel)descriptor.getChannel();
@@ -648,7 +639,7 @@
buffer.clear();
reading = false;
}
-
+
/**
* Ensure buffer is ready for writing.
* @throws IOException
@@ -661,25 +652,25 @@
public synchronized ByteList read(int number) throws IOException, BadDescriptorException {
checkReadable();
ensureReadNonBuffered();
-
+
ByteList byteList = new ByteList(number);
-
+
// TODO this should entry into error handling somewhere
int bytesRead = descriptor.read(number, byteList);
-
+
if (bytesRead == -1) {
eof = true;
}
-
+
return byteList;
}
private ByteList bufferedRead(int number) throws IOException, BadDescriptorException {
checkReadable();
ensureRead();
-
+
ByteList result = new ByteList(0);
-
+
int len = -1;
if (buffer.hasRemaining()) { // already have some bytes buffered
len = (number <= buffer.remaining()) ? number : buffer.remaining();
@@ -704,26 +695,26 @@
break;
}
}
-
+
//
// Complete the request by filling the read buffer first
//
while (!done && result.length() != number) {
int read = refillBuffer();
-
+
if (read == -1) {
eof = true;
break;
} else if (read == 0) {
break;
}
-
+
// append what we read into our buffer and allow the loop to continue
int desired = number - result.length();
len = (desired < read) ? desired : read;
result.append(buffer, len);
}
-
+
if (result.length() == 0 && number != 0) {
if (eof) {
throw new EOFException();
@@ -731,10 +722,10 @@
}
return result;
}
-
+
private int bufferedRead() throws IOException, BadDescriptorException {
ensureRead();
-
+
if (!buffer.hasRemaining()) {
int len = refillBuffer();
if (len == -1) {
@@ -746,42 +737,42 @@
}
return buffer.get() & 0xFF;
}
-
+
/**
- * @throws IOException
- * @throws BadDescriptorException
+ * @throws IOException
+ * @throws BadDescriptorException
* @see org.jruby.util.IOHandler#syswrite(String buf)
*/
private int bufferedWrite(ByteList buf) throws IOException, BadDescriptorException {
getRuntime().secure(4);
checkWritable();
ensureWrite();
-
+
// Ruby ignores empty syswrites
if (buf == null || buf.length() == 0) return 0;
-
+
if (buf.length() > buffer.capacity()) { // Doesn't fit in buffer. Write immediately.
flushWrite(); // ensure nothing left to write
-
+
int n = descriptor.write(ByteBuffer.wrap(buf.unsafeBytes(), buf.begin(), buf.length()));
if(n != buf.length()) {
// TODO: check the return value here
}
} else {
if (buf.length() > buffer.remaining()) flushWrite();
-
+
buffer.put(buf.unsafeBytes(), buf.begin(), buf.length());
}
-
+
if (isSync()) sync();
-
+
return buf.realSize;
}
-
+
/**
- * @throws IOException
- * @throws BadDescriptorException
+ * @throws IOException
+ * @throws BadDescriptorException
* @see org.jruby.util.IOHandler#syswrite(String buf)
*/
private int bufferedWrite(int c) throws IOException, BadDescriptorException {
@@ -790,14 +781,14 @@
ensureWrite();
if (!buffer.hasRemaining()) flushWrite();
-
+
buffer.put((byte) c);
-
+
if (isSync()) sync();
-
+
return 1;
}
-
+
public synchronized void ftruncate(long newLength) throws IOException,
BadDescriptorException, InvalidValueException {
Channel ch = descriptor.getChannel();
@@ -810,20 +801,20 @@
// truncate can't lengthen files, so we save position, seek/write, and go back
long position = fileChannel.position();
int difference = (int)(newLength - fileChannel.size());
-
+
fileChannel.position(fileChannel.size());
// FIXME: This worries me a bit, since it could allocate a lot with a large newLength
fileChannel.write(ByteBuffer.allocate(difference));
fileChannel.position(position);
} else {
fileChannel.truncate(newLength);
- }
+ }
}
-
+
/**
* Invalidate buffer before a position change has occurred (e.g. seek),
* flushing writes if required, and correcting file position if reading
- * @throws IOException
+ * @throws IOException
*/
private void invalidateBuffer() throws IOException, BadDescriptorException {
if (!reading) flushWrite();
@@ -862,13 +853,13 @@
if (c == -1) {
return -1;
}
-
+
// putting a bit back, so we're not at EOF anymore
eof = false;
// save the ungot
ungotc = c;
-
+
return c;
}
@@ -876,7 +867,7 @@
if (eof) {
return -1;
}
-
+
checkReadable();
int c = read();
@@ -885,7 +876,7 @@
eof = true;
return c;
}
-
+
return c & 0xff;
}
@@ -896,12 +887,12 @@
getRuntime().secure(4);
checkWritable();
ensureWrite();
-
+
// Ruby ignores empty syswrites
if (buf == null || buf.length() == 0) return 0;
-
+
if (buffer.position() != 0 && !flushWrite(false)) return 0;
-
+
if (descriptor.getChannel() instanceof SelectableChannel) {
SelectableChannel selectableChannel = (SelectableChannel)descriptor.getChannel();
synchronized (selectableChannel.blockingLock()) {
@@ -1002,13 +993,13 @@
} else {
// otherwise, we try an unbuffered read to get whatever's available
return read(number);
- }
+ }
}
public synchronized int read() throws IOException, BadDescriptorException {
try {
descriptor.checkOpen();
-
+
if (ungotc >= 0) {
int c = ungotc;
ungotc = -1;
@@ -1021,11 +1012,11 @@
return -1;
}
}
-
+
public ChannelDescriptor getDescriptor() {
return descriptor;
}
-
+
public void setBlocking(boolean block) throws IOException {
if (!(descriptor.getChannel() instanceof SelectableChannel)) {
return;
@@ -1059,7 +1050,7 @@
if (descriptor.isOpen()) {
descriptor.close();
}
-
+
if (path.equals("/dev/null") || path.equalsIgnoreCase("nul:") || path.equalsIgnoreCase("nul")) {
descriptor = new ChannelDescriptor(new NullChannel(), descriptor.getFileno(), modes, new FileDescriptor());
} else {
@@ -1083,27 +1074,27 @@
RandomAccessFile file = new RandomAccessFile(theFile, modes.toJavaModeString());
if (modes.isTruncate()) file.setLength(0L);
-
+
descriptor = new ChannelDescriptor(file.getChannel(), descriptor.getFileno(), modes, file.getFD());
-
+
if (modes.isAppendable()) lseek(0, SEEK_END);
}
}
-
+
public static Stream fopen(Ruby runtime, String path, ModeFlags modes) throws FileNotFoundException, DirectoryAsFileException, FileExistsException, IOException, InvalidValueException, PipeException, BadDescriptorException {
String cwd = runtime.getCurrentDirectory();
-
+
ChannelDescriptor descriptor = ChannelDescriptor.open(cwd, path, modes);
-
+
Stream stream = fdopen(runtime, descriptor, modes);
-
+
if (modes.isAppendable()) stream.lseek(0, Stream.SEEK_END);
-
+
return stream;
}
-
+
public static Stream fdopen(Ruby runtime, ChannelDescriptor descriptor, ModeFlags modes) throws InvalidValueException {
- Stream handler = new ChannelStream(runtime, descriptor, modes, descriptor.getFileDescriptor());
+ Stream handler = new ChannelStream(descriptor, modes, descriptor.getFileDescriptor());
return handler;
}
Index: src/org/jruby/RubyGlobal.java
===================================================================
--- src/org/jruby/RubyGlobal.java (revision 8091)
+++ src/org/jruby/RubyGlobal.java (working copy)
@@ -43,29 +43,28 @@
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.environment.OSEnvironmentReaderExcepton;
import org.jruby.environment.OSEnvironment;
-import org.jruby.internal.runtime.ValueAccessor;
+import org.jruby.internal.runtime.RuntimeVariableAccessor;
import org.jruby.javasupport.JavaUtil;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.runtime.Constants;
import org.jruby.runtime.GlobalVariable;
-import org.jruby.runtime.IAccessor;
import org.jruby.runtime.ReadonlyGlobalVariable;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.KCode;
/** This class initializes global variables and constants.
- *
+ *
* @author jpetersen
*/
public class RubyGlobal {
-
+
/**
* Obligate string-keyed and string-valued hash, used for ENV and ENV_JAVA
- *
+ *
*/
public static class StringOnlyRubyHash extends RubyHash {
-
+
public StringOnlyRubyHash(Ruby runtime, Map valueMap, IRubyObject defaultValue) {
super(runtime, valueMap, defaultValue);
}
@@ -95,26 +94,26 @@
if (value.isNil()) {
return super.delete(context, key, org.jruby.runtime.Block.NULL_BLOCK);
}
-
+
//return super.aset(getRuntime().newString("sadfasdF"), getRuntime().newString("sadfasdF"));
return super.op_aset(context, RuntimeHelpers.invoke(context, key, "to_str"),
value.isNil() ? getRuntime().getNil() : RuntimeHelpers.invoke(context, value, "to_str"));
}
-
+
@JRubyMethod
@Override
public IRubyObject to_s(){
return getRuntime().newString("ENV");
}
}
-
+
public static void createGlobals(ThreadContext context, Ruby runtime) {
runtime.defineGlobalConstant("TOPLEVEL_BINDING", runtime.newBinding());
-
+
runtime.defineGlobalConstant("TRUE", runtime.getTrue());
runtime.defineGlobalConstant("FALSE", runtime.getFalse());
runtime.defineGlobalConstant("NIL", runtime.getNil());
-
+
// define ARGV and $* for this runtime
RubyArray argvArray = runtime.newArray();
String[] argv = runtime.getInstanceConfig().getArgv();
@@ -122,12 +121,11 @@
argvArray.append(RubyString.newStringShared(runtime, argv[i].getBytes()));
}
runtime.defineGlobalConstant("ARGV", argvArray);
- runtime.getGlobalVariables().defineReadonly("$*", new ValueAccessor(argvArray));
+ runtime.getGlobalVariables().defineReadonly("$*", new RuntimeVariableAccessor("$*", argvArray));
- IAccessor d = new ValueAccessor(runtime.newString(
- runtime.getInstanceConfig().displayedFileName()));
- runtime.getGlobalVariables().define("$PROGRAM_NAME", d);
- runtime.getGlobalVariables().define("$0", d);
+ RubyString fileName = runtime.newString(runtime.getInstanceConfig().displayedFileName());
+ runtime.getGlobalVariables().define("$PROGRAM_NAME", new RuntimeVariableAccessor("$PROGRAM_NAME", fileName));
+ runtime.getGlobalVariables().define("$0", new RuntimeVariableAccessor("$0", fileName));
// Version information:
IRubyObject version = runtime.newString(Constants.RUBY_VERSION).freeze(context);
@@ -144,36 +142,36 @@
runtime.defineGlobalConstant("VERSION", version);
runtime.defineGlobalConstant("RELEASE_DATE", release);
runtime.defineGlobalConstant("PLATFORM", platform);
-
+
IRubyObject jrubyVersion = runtime.newString(Constants.VERSION).freeze(context);
runtime.defineGlobalConstant("JRUBY_VERSION", jrubyVersion);
-
- GlobalVariable kcodeGV = new KCodeGlobalVariable(runtime, "$KCODE", runtime.newString("NONE"));
+
+ GlobalVariable kcodeGV = new KCodeGlobalVariable("$KCODE", runtime.newString("NONE"));
runtime.defineVariable(kcodeGV);
runtime.defineVariable(new GlobalVariable.Copy(runtime, "$-K", kcodeGV));
IRubyObject defaultRS = runtime.newString(runtime.getInstanceConfig().getRecordSeparator()).freeze(context);
- GlobalVariable rs = new StringGlobalVariable(runtime, "$/", defaultRS);
+ GlobalVariable rs = new StringGlobalVariable("$/", defaultRS);
runtime.defineVariable(rs);
runtime.setRecordSeparatorVar(rs);
runtime.getGlobalVariables().setDefaultSeparator(defaultRS);
- runtime.defineVariable(new StringGlobalVariable(runtime, "$\\", runtime.getNil()));
- runtime.defineVariable(new StringGlobalVariable(runtime, "$,", runtime.getNil()));
+ runtime.defineVariable(new StringGlobalVariable("$\\", runtime.getNil()));
+ runtime.defineVariable(new StringGlobalVariable("$,", runtime.getNil()));
- runtime.defineVariable(new LineNumberGlobalVariable(runtime, "$.", RubyFixnum.one(runtime)));
- runtime.defineVariable(new LastlineGlobalVariable(runtime, "$_"));
- runtime.defineVariable(new LastExitStatusVariable(runtime, "$?"));
+ runtime.defineVariable(new LineNumberGlobalVariable("$.", RubyFixnum.one(runtime)));
+ runtime.defineVariable(new LastlineGlobalVariable("$_"));
+ runtime.defineVariable(new LastExitStatusVariable("$?"));
- runtime.defineVariable(new ErrorInfoGlobalVariable(runtime, "$!", runtime.getNil()));
- runtime.defineVariable(new NonEffectiveGlobalVariable(runtime, "$=", runtime.getFalse()));
+ runtime.defineVariable(new ErrorInfoGlobalVariable("$!", runtime.getNil()));
+ runtime.defineVariable(new NonEffectiveGlobalVariable("$=", runtime.getFalse()));
if(runtime.getInstanceConfig().getInputFieldSeparator() == null) {
- runtime.defineVariable(new GlobalVariable(runtime, "$;", runtime.getNil()));
+ runtime.defineVariable(new GlobalVariable("$;", runtime.getNil()));
} else {
- runtime.defineVariable(new GlobalVariable(runtime, "$;", RubyRegexp.newRegexp(runtime, runtime.getInstanceConfig().getInputFieldSeparator(), 0)));
+ runtime.defineVariable(new GlobalVariable("$;", RubyRegexp.newRegexp(runtime, runtime.getInstanceConfig().getInputFieldSeparator(), 0)));
}
-
+
Boolean verbose = runtime.getInstanceConfig().getVerbose();
- IRubyObject verboseValue = null;
+ IRubyObject verboseValue;
if (verbose == null) {
verboseValue = runtime.getNil();
} else if(verbose == Boolean.TRUE) {
@@ -181,68 +179,67 @@
} else {
verboseValue = runtime.getFalse();
}
- runtime.defineVariable(new VerboseGlobalVariable(runtime, "$VERBOSE", verboseValue));
-
+ runtime.defineVariable(new VerboseGlobalVariable("$VERBOSE", verboseValue));
+
IRubyObject debug = runtime.newBoolean(runtime.getInstanceConfig().isDebug());
- runtime.defineVariable(new DebugGlobalVariable(runtime, "$DEBUG", debug));
- runtime.defineVariable(new DebugGlobalVariable(runtime, "$-d", debug));
+ runtime.defineVariable(new DebugGlobalVariable("$DEBUG", debug));
+ runtime.defineVariable(new DebugGlobalVariable("$-d", debug));
- runtime.defineVariable(new SafeGlobalVariable(runtime, "$SAFE"));
+ runtime.defineVariable(new SafeGlobalVariable("$SAFE"));
- runtime.defineVariable(new BacktraceGlobalVariable(runtime, "$@"));
+ runtime.defineVariable(new BacktraceGlobalVariable("$@"));
IRubyObject stdin = new RubyIO(runtime, STDIO.IN);
IRubyObject stdout = new RubyIO(runtime, STDIO.OUT);
IRubyObject stderr = new RubyIO(runtime, STDIO.ERR);
- runtime.defineVariable(new InputGlobalVariable(runtime, "$stdin", stdin));
+ runtime.getGlobalVariables().define("$stdin", new RuntimeVariableAccessor("$stdin", stdin));
- runtime.defineVariable(new OutputGlobalVariable(runtime, "$stdout", stdout));
+ runtime.getGlobalVariables().define("$stdout", new RuntimeOutputAccessor("$stdout", stdout));
runtime.getGlobalVariables().alias("$>", "$stdout");
runtime.getGlobalVariables().alias("$defout", "$stdout");
- runtime.defineVariable(new OutputGlobalVariable(runtime, "$stderr", stderr));
+ runtime.getGlobalVariables().define("$stderr", new RuntimeOutputAccessor("$stderr", stderr));
runtime.getGlobalVariables().alias("$deferr", "$stderr");
runtime.defineGlobalConstant("STDIN", stdin);
runtime.defineGlobalConstant("STDOUT", stdout);
runtime.defineGlobalConstant("STDERR", stderr);
- runtime.defineVariable(new LoadedFeatures(runtime, "$\""));
- runtime.defineVariable(new LoadedFeatures(runtime, "$LOADED_FEATURES"));
+ runtime.defineVariable(new LoadedFeatures("$\""));
+ runtime.defineVariable(new LoadedFeatures("$LOADED_FEATURES"));
- runtime.defineVariable(new LoadPath(runtime, "$:"));
- runtime.defineVariable(new LoadPath(runtime, "$-I"));
- runtime.defineVariable(new LoadPath(runtime, "$LOAD_PATH"));
-
- runtime.defineVariable(new MatchMatchGlobalVariable(runtime, "$&"));
- runtime.defineVariable(new PreMatchGlobalVariable(runtime, "$`"));
- runtime.defineVariable(new PostMatchGlobalVariable(runtime, "$'"));
- runtime.defineVariable(new LastMatchGlobalVariable(runtime, "$+"));
- runtime.defineVariable(new BackRefGlobalVariable(runtime, "$~"));
+ runtime.defineVariable(new LoadPath("$:"));
+ runtime.defineVariable(new LoadPath("$-I"));
+ runtime.defineVariable(new LoadPath("$LOAD_PATH"));
- // On platforms without a c-library accessable through JNA, getpid will return hashCode
+ runtime.defineVariable(new MatchMatchGlobalVariable("$&"));
+ runtime.defineVariable(new PreMatchGlobalVariable("$`"));
+ runtime.defineVariable(new PostMatchGlobalVariable("$'"));
+ runtime.defineVariable(new LastMatchGlobalVariable("$+"));
+ runtime.defineVariable(new BackRefGlobalVariable("$~"));
+
+ // On platforms without a c-library accessable through JNA, getpid will return hashCode
// as $$ used to. Using $$ to kill processes could take down many runtimes, but by basing
// $$ on getpid() where available, we have the same semantics as MRI.
- runtime.getGlobalVariables().defineReadonly("$$", new ValueAccessor(runtime.newFixnum(runtime.getPosix().getpid())));
+ RubyFixnum pid = runtime.newFixnum(runtime.getPosix().getpid());
+ runtime.getGlobalVariables().defineReadonly("$$", new RuntimeVariableAccessor("$$", pid));
// after defn of $stderr as the call may produce warnings
defineGlobalEnvConstants(runtime);
-
- // Fixme: Do we need the check or does Main.java not call this...they should consolidate
- if (runtime.getGlobalVariables().get("$*").isNil()) {
- runtime.getGlobalVariables().defineReadonly("$*", new ValueAccessor(runtime.newArray()));
- }
-
- runtime.getGlobalVariables().defineReadonly("$-p",
- new ValueAccessor(runtime.getInstanceConfig().isAssumePrinting() ? runtime.getTrue() : runtime.getNil()));
- runtime.getGlobalVariables().defineReadonly("$-n",
- new ValueAccessor(runtime.getInstanceConfig().isAssumeLoop() ? runtime.getTrue() : runtime.getNil()));
- runtime.getGlobalVariables().defineReadonly("$-a",
- new ValueAccessor(runtime.getInstanceConfig().isSplit() ? runtime.getTrue() : runtime.getNil()));
- runtime.getGlobalVariables().defineReadonly("$-l",
- new ValueAccessor(runtime.getInstanceConfig().isProcessLineEnds() ? runtime.getTrue() : runtime.getNil()));
+ IRubyObject assumePrinting = runtime.getInstanceConfig().isAssumePrinting() ? runtime.getTrue() : runtime.getNil();
+ runtime.getGlobalVariables().defineReadonly("$-p", new RuntimeVariableAccessor("$-p", assumePrinting));
+
+ IRubyObject assumeLoop = runtime.getInstanceConfig().isAssumeLoop() ? runtime.getTrue() : runtime.getNil();
+ runtime.getGlobalVariables().defineReadonly("$-n", new RuntimeVariableAccessor("$-n", assumeLoop));
+
+ IRubyObject split = runtime.getInstanceConfig().isSplit() ? runtime.getTrue() : runtime.getNil();
+ runtime.getGlobalVariables().defineReadonly("$-a", new RuntimeVariableAccessor("$-a", split));
+
+ IRubyObject processLineEnds = runtime.getInstanceConfig().isProcessLineEnds() ? runtime.getTrue() : runtime.getNil();
+ runtime.getGlobalVariables().defineReadonly("$-l", new RuntimeVariableAccessor("S-l", processLineEnds));
+
// ARGF, $< object
RubyArgsFile.initArgsFile(runtime);
}
@@ -254,10 +251,10 @@
try {
environmentVariableMap = environment.getEnvironmentVariableMap(runtime);
} catch (OSEnvironmentReaderExcepton e) {
- // If the environment variables are not accessible shouldn't terminate
+ // If the environment variables are not accessible shouldn't terminate
runtime.getWarnings().warn(ID.MISCELLANEOUS, e.getMessage());
}
-
+
if (environmentVariableMap == null) {
// if the environment variables can't be obtained, define an empty ENV
environmentVariableMap = new HashMap();
@@ -272,103 +269,109 @@
Map systemProps = environment.getSystemPropertiesMap(runtime);
runtime.defineGlobalConstant("ENV_JAVA", new StringOnlyRubyHash(
runtime, systemProps, runtime.getNil()));
-
+
}
+ private static Ruby getRuntime() {
+ return Ruby.getCurrentRuntime();
+ }
+
private static class NonEffectiveGlobalVariable extends GlobalVariable {
- public NonEffectiveGlobalVariable(Ruby runtime, String name, IRubyObject value) {
- super(runtime, name, value);
+ public NonEffectiveGlobalVariable(String name, IRubyObject value) {
+ super(name, value);
}
@Override
public IRubyObject set(IRubyObject value) {
- runtime.getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective; ignored", name);
+ getRuntime().getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective; ignored", name);
return value;
}
+
@Override
public IRubyObject get() {
- runtime.getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective", name);
- return runtime.getFalse();
+ getRuntime().getWarnings().warn(ID.INEFFECTIVE_GLOBAL, "warning: variable " + name + " is no longer effective", name);
+ return getRuntime().getFalse();
}
+
}
private static class LastExitStatusVariable extends GlobalVariable {
- public LastExitStatusVariable(Ruby runtime, String name) {
- super(runtime, name, runtime.getNil());
+ public LastExitStatusVariable(String name) {
+ super(name, getRuntime().getNil());
}
-
+
@Override
public IRubyObject get() {
- IRubyObject lastExitStatus = runtime.getCurrentContext().getLastExitStatus();
- return lastExitStatus == null ? runtime.getNil() : lastExitStatus;
+ IRubyObject lastExitStatus = getRuntime().getCurrentContext().getLastExitStatus();
+ return lastExitStatus == null ? getRuntime().getNil() : lastExitStatus;
}
-
+
@Override
public IRubyObject set(IRubyObject lastExitStatus) {
- runtime.getCurrentContext().setLastExitStatus(lastExitStatus);
-
+ getRuntime().getCurrentContext().setLastExitStatus(lastExitStatus);
+
return lastExitStatus;
}
}
private static class MatchMatchGlobalVariable extends GlobalVariable {
- public MatchMatchGlobalVariable(Ruby runtime, String name) {
- super(runtime, name, runtime.getNil());
+ public MatchMatchGlobalVariable(String name) {
+ super(name, getRuntime().getNil());
}
-
+
@Override
public IRubyObject get() {
- return RubyRegexp.last_match(runtime.getCurrentContext().getCurrentFrame().getBackRef());
+ return RubyRegexp.last_match(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
}
}
private static class PreMatchGlobalVariable extends GlobalVariable {
- public PreMatchGlobalVariable(Ruby runtime, String name) {
- super(runtime, name, runtime.getNil());
+ public PreMatchGlobalVariable(String name) {
+ super(name, getRuntime().getNil());
}
-
+
@Override
public IRubyObject get() {
- return RubyRegexp.match_pre(runtime.getCurrentContext().getCurrentFrame().getBackRef());
+ return RubyRegexp.match_pre(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
}
}
private static class PostMatchGlobalVariable extends GlobalVariable {
- public PostMatchGlobalVariable(Ruby runtime, String name) {
- super(runtime, name, runtime.getNil());
+ public PostMatchGlobalVariable(String name) {
+ super(name, getRuntime().getNil());
}
-
+
@Override
public IRubyObject get() {
- return RubyRegexp.match_post(runtime.getCurrentContext().getCurrentFrame().getBackRef());
+ return RubyRegexp.match_post(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
}
}
private static class LastMatchGlobalVariable extends GlobalVariable {
- public LastMatchGlobalVariable(Ruby runtime, String name) {
- super(runtime, name, runtime.getNil());
+ public LastMatchGlobalVariable(String name) {
+ super(name, getRuntime().getNil());
}
-
+
@Override
public IRubyObject get() {
- return RubyRegexp.match_last(runtime.getCurrentContext().getCurrentFrame().getBackRef());
+ return RubyRegexp.match_last(getRuntime().getCurrentContext().getCurrentFrame().getBackRef());
}
}
private static class BackRefGlobalVariable extends GlobalVariable {
- public BackRefGlobalVariable(Ruby runtime, String name) {
- super(runtime, name, runtime.getNil());
+ public BackRefGlobalVariable(String name) {
+ super(name, getRuntime().getNil());
}
-
+
@Override
public IRubyObject get() {
- return RuntimeHelpers.getBackref(runtime, runtime.getCurrentContext());
+ return RuntimeHelpers.getBackref(getRuntime(), getRuntime().getCurrentContext());
}
@Override
public IRubyObject set(IRubyObject value) {
- RuntimeHelpers.setBackref(runtime, runtime.getCurrentContext(), value);
+ RuntimeHelpers.setBackref(getRuntime(), getRuntime().getCurrentContext(), value);
return value;
}
}
@@ -376,113 +379,113 @@
&