package org.jruby;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.anno.TypePopulator;
import org.jruby.ast.ArrayNode;
import org.jruby.ast.BlockNode;
import org.jruby.ast.CallNode;
import org.jruby.ast.FCallNode;
import org.jruby.ast.GlobalAsgnNode;
import org.jruby.ast.GlobalVarNode;
import org.jruby.ast.StrNode;
import org.jruby.ast.VCallNode;
import org.jruby.ast.WhileNode;
import org.jruby.compiler.Constantizable;
import org.jruby.compiler.NotCompilableException;
import org.jruby.ext.jruby.JRubyLibrary;
import org.jruby.ext.jruby.JRubyUtilLibrary;
import org.jruby.ext.thread.ConditionVariable;
import org.jruby.ext.thread.Mutex;
import org.jruby.ext.thread.SizedQueue;
import org.jruby.ir.IRScope;
import org.jruby.ir.IRScriptBody;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.runtime.IRReturnJump;
import org.jruby.javasupport.Java;
import org.jruby.javasupport.JavaClass;
import org.jruby.javasupport.JavaPackage;
import org.jruby.javasupport.JavaSupport;
import org.jruby.javasupport.JavaSupportImpl;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.management.Caches;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.invokedynamic.InvokeDynamicSupport;
import org.jruby.util.CommonByteLists;
import org.jruby.util.MRIRecursionGuard;
import org.jruby.util.StringSupport;
import org.jruby.util.StrptimeParser;
import org.jruby.util.StrptimeToken;
import org.jruby.util.collections.ConcurrentWeakHashMap;
import org.jruby.util.io.EncodingUtils;
import org.objectweb.asm.util.TraceClassVisitor;
import jnr.constants.Constant;
import jnr.constants.ConstantSet;
import jnr.constants.platform.Errno;
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
import org.jcodings.Encoding;
import org.joda.time.DateTimeZone;
import org.joni.WarnCallback;
import org.jruby.ast.Node;
import org.jruby.ast.RootNode;
import org.jruby.ast.executable.RuntimeCache;
import org.jruby.ast.executable.Script;
import org.jruby.ast.executable.ScriptAndCode;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.common.RubyWarnings;
import org.jruby.compiler.JITCompiler;
import org.jruby.embed.Extension;
import org.jruby.exceptions.MainExitException;
import org.jruby.exceptions.RaiseException;
import org.jruby.ext.JRubyPOSIXHandler;
import org.jruby.ext.coverage.CoverageData;
import org.jruby.ext.ffi.FFI;
import org.jruby.ext.fiber.ThreadFiber;
import org.jruby.ext.fiber.ThreadFiberLibrary;
import org.jruby.ext.tracepoint.TracePoint;
import org.jruby.internal.runtime.GlobalVariables;
import org.jruby.internal.runtime.ThreadService;
import org.jruby.internal.runtime.ValueAccessor;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.ir.Compiler;
import org.jruby.ir.IRManager;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.ir.persistence.IRReader;
import org.jruby.ir.persistence.IRReaderStream;
import org.jruby.ir.persistence.util.IRFileExpert;
import org.jruby.javasupport.proxy.JavaProxyClassFactory;
import org.jruby.management.BeanManager;
import org.jruby.management.BeanManagerFactory;
import org.jruby.management.Config;
import org.jruby.management.ParserStats;
import org.jruby.parser.Parser;
import org.jruby.parser.ParserConfiguration;
import org.jruby.parser.StaticScopeFactory;
import org.jruby.platform.Platform;
import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallSite;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.EventHook;
import org.jruby.runtime.GlobalVariable;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.IAccessor;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ObjectSpace;
import org.jruby.runtime.RubyEvent;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.encoding.EncodingService;
import org.jruby.runtime.invokedynamic.MethodNames;
import org.jruby.runtime.load.BasicLibraryService;
import org.jruby.runtime.load.CompiledScriptLoader;
import org.jruby.runtime.load.LoadService;
import org.jruby.runtime.opto.Invalidator;
import org.jruby.runtime.opto.OptoFactory;
import org.jruby.runtime.profile.ProfileCollection;
import org.jruby.runtime.profile.ProfilingService;
import org.jruby.runtime.profile.ProfilingServiceLookup;
import org.jruby.runtime.profile.builtin.ProfiledMethods;
import org.jruby.runtime.scope.ManyVarsDynamicScope;
import org.jruby.threading.DaemonThreadFactory;
import org.jruby.util.ByteList;
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.DefinedMessage;
import org.jruby.util.JRubyClassLoader;
import org.jruby.util.SecurityHelper;
import org.jruby.util.SelfFirstJRubyClassLoader;
import org.jruby.util.IOInputStream;
import org.jruby.util.IOOutputStream;
import org.jruby.util.ClassDefiningJRubyClassLoader;
import org.jruby.util.KCode;
import org.jruby.util.SafePropertyAccessor;
import org.jruby.util.cli.Options;
import org.jruby.util.collections.WeakHashSet;
import org.jruby.util.func.Function1;
import org.jruby.util.io.FilenoUtil;
import org.jruby.util.io.SelectorPool;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
import org.objectweb.asm.ClassReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.ref.WeakReference;
import java.net.BindException;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Stack;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import static java.lang.invoke.MethodHandles.explicitCastArguments;
import static java.lang.invoke.MethodHandles.insertArguments;
import static java.lang.invoke.MethodType.methodType;
import static org.jruby.internal.runtime.GlobalVariable.Scope.GLOBAL;
import static org.jruby.util.RubyStringBuilder.str;
import static org.jruby.util.RubyStringBuilder.ids;
import static org.jruby.util.RubyStringBuilder.types;
import static org.jruby.runtime.Arity.UNLIMITED_ARGUMENTS;
public final class Ruby implements Constantizable {
private static final Logger LOG = LoggerFactory.getLogger(Ruby.class);
static {
if (RubyInstanceConfig.JIT_LOADING_DEBUG) LOG.setDebugEnable(true);
}
private Ruby(RubyInstanceConfig config) {
this.config = config;
this.threadService = new ThreadService(this);
if( config.isProfiling() ) {
this.profilingServiceLookup = new ProfilingServiceLookup(this);
} else {
this.profilingServiceLookup = null;
}
constant = OptoFactory.newConstantWrapper(Ruby.class, this);
if (!Ruby.isSecurityRestricted()) {
if (config.isClassloaderDelegate()){
jrubyClassLoader = new JRubyClassLoader(config.getLoader());
}
else {
jrubyClassLoader = new SelfFirstJRubyClassLoader(config.getLoader());
}
}
else {
jrubyClassLoader = null;
}
this.staticScopeFactory = new StaticScopeFactory(this);
this.beanManager = BeanManagerFactory.create(this, config.isManagementEnabled());
this.jitCompiler = new JITCompiler(this);
this.parserStats = new ParserStats(this);
this.caches = new Caches();
Random myRandom;
try {
myRandom = new SecureRandom();
} catch (Throwable t) {
LOG.debug("unable to instantiate SecureRandom, falling back on Random", t);
myRandom = new Random();
}
this.random = myRandom;
if (RubyInstanceConfig.CONSISTENT_HASHING_ENABLED) {
this.hashSeedK0 = -561135208506705104l;
this.hashSeedK1 = 7114160726623585955l;
} else {
this.hashSeedK0 = this.random.nextLong();
this.hashSeedK1 = this.random.nextLong();
}
this.configBean = new Config(this);
this.runtimeBean = new org.jruby.management.Runtime(this);
registerMBeans();
this.runtimeCache = new RuntimeCache();
runtimeCache.initMethodCache(ClassIndex.MAX_CLASSES.ordinal() * MethodNames.values().length - 1);
checkpointInvalidator = OptoFactory.newConstantInvalidator(this);
if (config.isObjectSpaceEnabled()) {
objectSpacer = ENABLED_OBJECTSPACE;
} else {
objectSpacer = DISABLED_OBJECTSPACE;
}
posix = POSIXFactory.getPOSIX(new JRubyPOSIXHandler(this), config.isNativeEnabled());
filenoUtil = new FilenoUtil(posix);
reinitialize(false);
}
public void registerMBeans() {
this.beanManager.register(jitCompiler);
this.beanManager.register(configBean);
this.beanManager.register(parserStats);
this.beanManager.register(runtimeBean);
this.beanManager.register(caches);
}
void reinitialize(boolean reinitCore) {
this.doNotReverseLookupEnabled = true;
this.staticScopeFactory = new StaticScopeFactory(this);
this.in = config.getInput();
this.out = config.getOutput();
this.err = config.getError();
this.objectSpaceEnabled = config.isObjectSpaceEnabled();
this.siphashEnabled = config.isSiphashEnabled();
this.profile = config.getProfile();
this.currentDirectory = config.getCurrentDirectory();
this.kcode = config.getKCode();
if (reinitCore) {
RubyGlobal.initARGV(this);
RubyGlobal.initSTDIO(this, globalVariables);
}
}
public static Ruby newInstance() {
return newInstance(new RubyInstanceConfig());
}
public static Ruby newInstance(RubyInstanceConfig config) {
Ruby ruby = new Ruby(config);
ruby.init();
setGlobalRuntimeFirstTimeOnly(ruby);
return ruby;
}
public static Ruby newInstance(InputStream in, PrintStream out, PrintStream err) {
RubyInstanceConfig config = new RubyInstanceConfig();
config.setInput(in);
config.setOutput(out);
config.setError(err);
return newInstance(config);
}
public static boolean isGlobalRuntimeReady() {
return globalRuntime != null;
}
private static synchronized void setGlobalRuntimeFirstTimeOnly(Ruby runtime) {
if (globalRuntime == null) {
globalRuntime = runtime;
}
}
public static synchronized Ruby getGlobalRuntime() {
if (globalRuntime == null) {
newInstance();
}
return globalRuntime;
}
public void useAsGlobalRuntime() {
synchronized(Ruby.class) {
globalRuntime = this;
}
}
public static void clearGlobalRuntime() {
globalRuntime = null;
}
public static Ruby getThreadLocalRuntime() {
return threadLocalRuntime.get();
}
public static void setThreadLocalRuntime(Ruby ruby) {
threadLocalRuntime.set(ruby);
}
public IRubyObject evalScriptlet(String script) {
ThreadContext context = getCurrentContext();
DynamicScope currentScope = context.getCurrentScope();
ManyVarsDynamicScope newScope = new ManyVarsDynamicScope(getStaticScopeFactory().newEvalScope(currentScope.getStaticScope()), currentScope);
return evalScriptlet(script, newScope);
}
public IRubyObject evalScriptlet(String script, DynamicScope scope) {
ThreadContext context = getCurrentContext();
RootNode rootNode = (RootNode) parseEval(script, "<script>", scope, 0);
context.preEvalScriptlet(scope);
try {
return interpreter.execute(this, rootNode, context.getFrameSelf());
} finally {
context.postEvalScriptlet();
}
}
public IRubyObject executeScript(String script, String filename) {
byte[] bytes = encodeToBytes(script);
ParseResult root = (ParseResult) parseInline(new ByteArrayInputStream(bytes), filename, null);
ThreadContext context = getCurrentContext();
String oldFile = context.getFile();
int oldLine = context.getLine();
try {
context.setFileAndLine(root.getFile(), root.getLine());
return runInterpreter(root);
} finally {
context.setFileAndLine(oldFile, oldLine);
}
}
public void runFromMain(InputStream inputStream, String filename) {
IAccessor d = new ValueAccessor(newString(filename));
getGlobalVariables().define("$PROGRAM_NAME", d, GLOBAL);
getGlobalVariables().define("$0", d, GLOBAL);
for (Map.Entry<String, String> entry : config.getOptionGlobals().entrySet()) {
final IRubyObject varvalue;
if (entry.getValue() != null) {
varvalue = newString(entry.getValue());
} else {
varvalue = getTrue();
}
getGlobalVariables().set('$' + entry.getKey(), varvalue);
}
if (filename.endsWith(".class")) {
IRScope script = CompiledScriptLoader.loadScriptFromFile(this, inputStream, null, filename, false);
if (script == null) {
throw new MainExitException(1, "error: .class file specified is not a compiled JRuby script");
}
script.setFileName(filename);
runInterpreter(script);
return;
}
ParseResult parseResult = parseFromMain(filename, inputStream);
if (fetchGlobalConstant("DATA") == null) {
try {inputStream.close();} catch (IOException ioe) {}
}
if (parseResult instanceof RootNode) {
RootNode scriptNode = (RootNode) parseResult;
ThreadContext context = getCurrentContext();
String oldFile = context.getFile();
int oldLine = context.getLine();
try {
context.setFileAndLine(scriptNode.getFile(), scriptNode.getLine());
if (config.isAssumePrinting() || config.isAssumeLoop()) {
runWithGetsLoop(scriptNode, config.isAssumePrinting(), config.isProcessLineEnds(),
config.isSplit());
} else {
runNormally(scriptNode);
}
} finally {
context.setFileAndLine(oldFile, oldLine);
}
} else {
runInterpreter(parseResult);
}
}
public Node parseFromMain(InputStream inputStream, String filename) {
if (config.isInlineScript()) {
return parseInline(inputStream, filename, getCurrentContext().getCurrentScope());
} else {
return parseFileFromMain(inputStream, filename, getCurrentContext().getCurrentScope());
}
}
public ParseResult parseFromMain(String fileName, InputStream in) {
if (config.isInlineScript()) return (ParseResult) parseInline(in, fileName, getCurrentContext().getCurrentScope());
return parseFileFromMain(fileName, in, getCurrentContext().getCurrentScope());
}
@Deprecated
public IRubyObject runWithGetsLoop(Node scriptNode, boolean printing, boolean processLineEnds, boolean split, boolean unused) {
return runWithGetsLoop((RootNode) scriptNode, printing, processLineEnds, split);
}
public IRubyObject runWithGetsLoop(RootNode scriptNode, boolean printing, boolean processLineEnds, boolean split) {
ThreadContext context = getCurrentContext();
scriptNode = addGetsLoop(scriptNode, printing, processLineEnds, split);
Script script = null;
boolean compile = getInstanceConfig().getCompileMode().shouldPrecompileCLI();
if (compile) {
try {
script = tryCompile(scriptNode);
if (Options.JIT_LOGGING.load()) {
LOG.info("successfully compiled: {}", scriptNode.getFile());
}
} catch (Throwable e) {
if (Options.JIT_LOGGING.load()) {
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error("failed to compile: " + scriptNode.getFile(), e);
}
else {
LOG.error("failed to compile: " + scriptNode.getFile() + " - " + e);
}
}
}
if (compile && script == null) {
}
}
Helpers.preLoad(context, ((RootNode) scriptNode).getStaticScope().getVariables());
try {
if (script != null) {
runScriptBody(script);
} else {
runInterpreterBody(scriptNode);
}
} finally {
Helpers.postLoad(context);
}
return getNil();
}
private RootNode addGetsLoop(RootNode oldRoot, boolean printing, boolean processLineEndings, boolean split) {
ISourcePosition pos = oldRoot.getPosition();
BlockNode newBody = new BlockNode(pos);
RubySymbol dollarSlash = newSymbol(CommonByteLists.DOLLAR_SLASH);
newBody.add(new GlobalAsgnNode(pos, dollarSlash, new StrNode(pos, ((RubyString) globalVariables.get("$/")).getByteList())));
if (processLineEndings) newBody.add(new GlobalAsgnNode(pos, newSymbol(CommonByteLists.DOLLAR_BACKSLASH), new GlobalVarNode(pos, dollarSlash)));
GlobalVarNode dollarUnderscore = new GlobalVarNode(pos, newSymbol("$_"));
BlockNode whileBody = new BlockNode(pos);
newBody.add(new WhileNode(pos, new VCallNode(pos, newSymbol("gets")), whileBody));
if (processLineEndings) whileBody.add(new CallNode(pos, dollarUnderscore, newSymbol("chomp!"), null, null, false));
if (split) whileBody.add(new GlobalAsgnNode(pos, newSymbol("$F"), new CallNode(pos, dollarUnderscore, newSymbol("split"), null, null, false)));
if (oldRoot.getBodyNode() instanceof BlockNode) {
whileBody.addAll(((BlockNode) oldRoot.getBodyNode()));
} else {
whileBody.add(oldRoot.getBodyNode());
}
if (printing) whileBody.add(new FCallNode(pos, newSymbol("puts"), new ArrayNode(pos, dollarUnderscore), null));
return new RootNode(pos, oldRoot.getScope(), newBody, oldRoot.getFile());
}
public IRubyObject runNormally(Node scriptNode, boolean wrap) {
ScriptAndCode scriptAndCode = null;
boolean compile = getInstanceConfig().getCompileMode().shouldPrecompileCLI();
if (compile || config.isShowBytecode()) {
scriptAndCode = precompileCLI((RootNode) scriptNode);
}
if (scriptAndCode != null) {
if (config.isShowBytecode()) {
TraceClassVisitor tracer = new TraceClassVisitor(new PrintWriter(System.err));
ClassReader reader = new ClassReader(scriptAndCode.bytecode());
reader.accept(tracer, 0);
return getNil();
}
return runScript(scriptAndCode.script(), wrap);
} else {
return runInterpreter(scriptNode);
}
}
public IRubyObject runNormally(Node scriptNode) {
return runNormally(scriptNode, false);
}
private ScriptAndCode precompileCLI(RootNode scriptNode) {
ScriptAndCode scriptAndCode = null;
try {
scriptAndCode = tryCompile(scriptNode, new ClassDefiningJRubyClassLoader(getJRubyClassLoader()));
if (scriptAndCode != null && Options.JIT_LOGGING.load()) {
LOG.info("done compiling target script: {}", scriptNode.getFile());
}
} catch (Exception e) {
if (Options.JIT_LOGGING.load()) {
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error("failed to compile target script: " + scriptNode.getFile(), e);
}
else {
LOG.error("failed to compile target script: " + scriptNode.getFile() + " - " + e);
}
}
}
return scriptAndCode;
}
public Script tryCompile(Node node) {
return tryCompile((RootNode) node, new ClassDefiningJRubyClassLoader(getJRubyClassLoader())).script();
}
private ScriptAndCode tryCompile(RootNode root, ClassDefiningClassLoader classLoader) {
try {
return Compiler.getInstance().execute(this, root, classLoader);
} catch (NotCompilableException e) {
if (Options.JIT_LOGGING.load()) {
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error("failed to compile target script: " + root.getFile(), e);
}
else {
LOG.error("failed to compile target script: " + root.getFile() + " - " + e.getLocalizedMessage());
}
}
return null;
}
}
public IRubyObject runScript(Script script) {
return runScript(script, false);
}
public IRubyObject runScript(Script script, boolean wrap) {
return script.load(getCurrentContext(), getTopSelf(), wrap);
}
public IRubyObject runScriptBody(Script script) {
return script.__file__(getCurrentContext(), getTopSelf(), Block.NULL_BLOCK);
}
public IRubyObject runInterpreter(ThreadContext context, ParseResult parseResult, IRubyObject self) {
try {
return interpreter.execute(this, parseResult, self);
} catch (IRReturnJump ex) {
if (!ex.methodToReturnFrom.getStaticScope().getIRScope().isScriptScope()) {
System.err.println("Unexpected 'return' escaped the runtime from " + ex.returnScope + " to " + ex.methodToReturnFrom.getStaticScope().getIRScope());
System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(ex, false));
Throwable t = ex;
while ((t = t.getCause()) != null) {
System.err.println("Caused by:");
System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(t, false));
}
}
}
return context.nil;
}
public IRubyObject runInterpreter(ThreadContext context, Node rootNode, IRubyObject self) {
assert rootNode != null : "scriptNode is not null";
return interpreter.execute(this, (ParseResult) rootNode, self);
}
public IRubyObject runInterpreter(Node scriptNode) {
return runInterpreter(getCurrentContext(), scriptNode, getTopSelf());
}
public IRubyObject runInterpreter(ParseResult parseResult) {
return runInterpreter(getCurrentContext(), parseResult, getTopSelf());
}
public IRubyObject runInterpreterBody(Node scriptNode) {
assert scriptNode != null : "scriptNode is not null";
assert scriptNode instanceof RootNode : "scriptNode is not a RootNode";
return runInterpreter(scriptNode);
}
public Parser getParser() {
return parser;
}
public BeanManager getBeanManager() {
return beanManager;
}
public JITCompiler getJITCompiler() {
return jitCompiler;
}
public Caches getCaches() {
return caches;
}
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();
}
public int allocModuleId() {
return moduleLastId.incrementAndGet();
}
public void addModule(RubyModule module) {
allModules.put(module, RubyBasicObject.NEVER);
}
public void eachModule(Consumer<RubyModule> func) {
Enumeration<RubyModule> e = allModules.keys();
while (e.hasMoreElements()) {
func.accept(e.nextElement());
}
}
@Deprecated
public void eachModule(Function1<Object, IRubyObject> func) {
Enumeration<RubyModule> e = allModules.keys();
while (e.hasMoreElements()) {
func.apply(e.nextElement());
}
}
public RubyModule getModule(String name) {
return objectClass.getModule(name);
}
@Deprecated
public RubyModule fastGetModule(String internedName) {
return getModule(internedName);
}
public RubyClass getClass(String name) {
return objectClass.getClass(name);
}
@Deprecated
public RubyClass fastGetClass(String internedName) {
return getClass(internedName);
}
@Extension
public RubyClass defineClass(String name, RubyClass superClass, ObjectAllocator allocator) {
return defineClassUnder(name, superClass, allocator, objectClass);
}
public RubyClass defineClass(String name, RubyClass superClass, ObjectAllocator allocator, CallSite[] callSites) {
return defineClassUnder(name, superClass, allocator, objectClass, callSites);
}
@Extension
public RubyClass defineClassUnder(String name, RubyClass superClass, ObjectAllocator allocator, RubyModule parent) {
return defineClassUnder(name, superClass, allocator, parent, null);
}
public RubyClass defineClassUnder(String id, RubyClass superClass, ObjectAllocator allocator, RubyModule parent, CallSite[] callSites) {
IRubyObject classObj = parent.getConstantAt(id);
if (classObj != null) {
if (!(classObj instanceof RubyClass)) throw newTypeError(str(this, ids(this, id), " is not a class"));
RubyClass klazz = (RubyClass)classObj;
if (klazz.getSuperClass().getRealClass() != superClass) {
throw newNameError(str(this, ids(this, id), " is already defined"), id);
}
if (klazz.getAllocator() != allocator) {
klazz.setAllocator(allocator);
}
return klazz;
}
boolean parentIsObject = parent == objectClass;
if (superClass == null) {
IRubyObject className = parentIsObject ? ids(this, id) :
parent.toRubyString(getCurrentContext()).append(newString("::")).append(ids(this, id));
warnings.warn(ID.NO_SUPER_CLASS, str(this, "no super class for `", className, "', Object assumed"));
superClass = objectClass;
}
return RubyClass.newClass(this, superClass, id, allocator, parent, !parentIsObject, callSites);
}
@Extension
public RubyModule defineModule(String name) {
return defineModuleUnder(name, objectClass);
}
@Extension
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;
RubyString typeName = parentIsObject ?
types(this, moduleObj.getMetaClass()) : types(this, parent, moduleObj.getMetaClass());
throw newTypeError(str(this, typeName, " is not a module"));
}
return RubyModule.newModule(this, name, parent, !parentIsObject);
}
public RubyModule getOrCreateModule(String id) {
IRubyObject module = objectClass.getConstantAt(id);
if (module == null) {
module = defineModule(id);
} else if (!module.isModule()) {
throw newTypeError(str(this, ids(this, id), " is not a Module"));
}
return (RubyModule) module;
}
public KCode getKCode() {
return kcode;
}
public void setKCode(KCode kcode) {
this.kcode = kcode;
}
public void defineGlobalConstant(String name, IRubyObject value) {
objectClass.defineConstant(name, value);
}
public IRubyObject fetchGlobalConstant(String name) {
return objectClass.fetchConstant(name, false);
}
public boolean isClassDefined(String name) {
return getModule(name) != null;
}
private void init() {
loadService = config.createLoadService(this);
javaSupport = loadJavaSupport();
executor = new ThreadPoolExecutor(
RubyInstanceConfig.POOL_MIN,
RubyInstanceConfig.POOL_MAX,
RubyInstanceConfig.POOL_TTL,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new DaemonThreadFactory("Ruby-" + getRuntimeNumber() + "-Worker"));
fiberExecutor = new ThreadPoolExecutor(
0,
Integer.MAX_VALUE,
RubyInstanceConfig.FIBER_POOL_TTL,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new DaemonThreadFactory("Ruby-" + getRuntimeNumber() + "-Fiber"));
initRoot();
threadService.initMainThread();
final ThreadContext context = getCurrentContext();
context.prepareTopLevel(objectClass, topSelf);
bootstrap();
initDefinedMessages();
initThreadStatuses();
irManager = new IRManager(this, getInstanceConfig());
IRScope top = new IRScriptBody(irManager, "", context.getCurrentScope().getStaticScope());
top.allocateInterpreterContext(Collections.EMPTY_LIST);
dummyClass = new RubyClass(this, classClass);
dummyClass.setFrozen(true);
RubyGlobal.createGlobals(this);
getLoadService().init(config.getLoadPaths());
bootingCore = false;
if (!RubyInstanceConfig.DEBUG_PARSER) {
initJavaSupport();
initRubyKernel();
if (!config.isDisableGems()) {
defineModule("Gem");
}
if (!config.isDisableDidYouMean()) {
defineModule("DidYouMean");
}
loadService.provide("enumerator", "enumerator.rb");
loadService.provide("rational", "rational.rb");
loadService.provide("complex", "complex.rb");
loadService.provide("thread", "thread.rb");
initRubyPreludes();
}
SecurityHelper.checkCryptoRestrictions(this);
ThreadFiber.initRootFiber(context, context.getThread());
if(config.isProfiling()) {
getLoadService().require("jruby/profiler/shutdown_hook");
kernelModule.invalidateCacheDescendants();
RubyKernel.recacheBuiltinMethods(this);
RubyBasicObject.recacheBuiltinMethods(this);
}
if (config.getLoadGemfile()) {
loadBundler();
}
deprecatedNetworkStackProperty();
bootingRuntime = false;
for (String scriptName : config.getRequiredLibraries()) {
topSelf.callMethod(context, "require", RubyString.newString(this, scriptName));
}
}
public JavaSupport loadJavaSupport() {
return new JavaSupportImpl(this);
}
private void loadBundler() {
loadService.loadFromClassLoader(getClassLoader(), "jruby/bundler/startup.rb", false);
}
private boolean doesReflectionWork() {
try {
ClassLoader.class.getDeclaredMethod("getResourceAsStream", String.class);
return true;
} catch (Exception e) {
return false;
}
}
private void bootstrap() {
initCore();
initExceptions();
initLibraries();
}
private void initDefinedMessages() {
for (DefinedMessage definedMessage : DefinedMessage.values()) {
RubyString str = freezeAndDedupString(
RubyString.newString(this, ByteList.create(definedMessage.getText())));
definedMessages.put(definedMessage, str);
}
}
private void initThreadStatuses() {
for (RubyThread.Status status : RubyThread.Status.values()) {
RubyString str = RubyString.newString(this, status.bytes);
str.setFrozen(true);
threadStatuses.put(status, str);
}
}
private void initRoot() {
basicObjectClass = RubyClass.createBootstrapClass(this, "BasicObject", null, RubyBasicObject.BASICOBJECT_ALLOCATOR);
objectClass = RubyClass.createBootstrapClass(this, "Object", basicObjectClass, RubyObject.OBJECT_ALLOCATOR);
moduleClass = RubyClass.createBootstrapClass(this, "Module", objectClass, RubyModule.MODULE_ALLOCATOR);
classClass = RubyClass.createBootstrapClass(this, "Class", moduleClass, RubyClass.CLASS_ALLOCATOR);
basicObjectClass.setMetaClass(classClass);
objectClass.setMetaClass(basicObjectClass);
moduleClass.setMetaClass(classClass);
classClass.setMetaClass(classClass);
RubyClass metaClass;
metaClass = basicObjectClass.makeMetaClass(classClass);
metaClass = objectClass.makeMetaClass(metaClass);
metaClass = moduleClass.makeMetaClass(metaClass);
metaClass = classClass.makeMetaClass(metaClass);
RubyBasicObject.createBasicObjectClass(this, basicObjectClass);
RubyObject.createObjectClass(this, objectClass);
RubyModule.createModuleClass(this, moduleClass);
RubyClass.createClassClass(this, classClass);
basicObjectClass.setConstant("BasicObject", basicObjectClass);
objectClass.setConstant("BasicObject", basicObjectClass);
objectClass.setConstant("Object", objectClass);
objectClass.setConstant("Class", classClass);
objectClass.setConstant("Module", moduleClass);
RubyModule kernel = RubyKernel.createKernelModule(this);
objectClass.includeModule(kernelModule);
if (config.getKernelGsubDefined()) {
kernel.addMethod("gsub", new JavaMethod(kernel, Visibility.PRIVATE, "gsub") {
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
switch (args.length) {
case 1:
return RubyKernel.gsub(context, self, args[0], block);
case 2:
return RubyKernel.gsub(context, self, args[0], args[1], block);
default:
throw newArgumentError(String.format("wrong number of arguments %d for 1..2", args.length));
}
}
});
}
topSelf = TopSelfFactory.createTopSelf(this, false);
RubyNil.createNilClass(this);
RubyBoolean.createFalseClass(this);
RubyBoolean.createTrueClass(this);
nilObject = new RubyNil(this);
for (int i=0; i<NIL_PREFILLED_ARRAY_SIZE; i++) nilPrefilledArray[i] = nilObject;
singleNilArray = new IRubyObject[] {nilObject};
falseObject = new RubyBoolean.False(this);
falseObject.setFrozen(true);
trueObject = new RubyBoolean.True(this);
trueObject.setFrozen(true);
reportOnException = trueObject;
}
private void initCore() {
if (profile.allowClass("Data")) {
dataClass = defineClass("Data", objectClass, ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
getObject().deprecateConstant(this, "Data");
}
RubyComparable.createComparable(this);
RubyEnumerable.createEnumerableModule(this);
RubyString.createStringClass(this);
encodingService = new EncodingService(this);
RubySymbol.createSymbolClass(this);
if (profile.allowClass("ThreadGroup")) {
RubyThreadGroup.createThreadGroupClass(this);
}
if (profile.allowClass("Thread")) {
RubyThread.createThreadClass(this);
}
if (profile.allowClass("Exception")) {
RubyException.createExceptionClass(this);
}
if (profile.allowClass("Numeric")) {
RubyNumeric.createNumericClass(this);
}
if (profile.allowClass("Integer")) {
RubyInteger.createIntegerClass(this);
}
if (profile.allowClass("Fixnum")) {
RubyFixnum.createFixnumClass(this);
}
RubyEncoding.createEncodingClass(this);
RubyConverter.createConverterClass(this);
encodingService.defineEncodings();
encodingService.defineAliases();
String encoding = config.getExternalEncoding();
if (encoding != null && !encoding.equals("")) {
Encoding loadedEncoding = encodingService.loadEncoding(ByteList.create(encoding));
if (loadedEncoding == null) throw new MainExitException(1, "unknown encoding name - " + encoding);
setDefaultExternalEncoding(loadedEncoding);
} else {
Encoding consoleEncoding = encodingService.getConsoleEncoding();
Encoding availableEncoding = consoleEncoding == null ? encodingService.getLocaleEncoding() : consoleEncoding;
setDefaultExternalEncoding(availableEncoding);
}
if (Platform.IS_WINDOWS) {
setDefaultFilesystemEncoding(encodingService.getWindowsFilesystemEncoding(this));
} else {
setDefaultFilesystemEncoding(getDefaultExternalEncoding());
}
encoding = config.getInternalEncoding();
if (encoding != null && !encoding.equals("")) {
Encoding loadedEncoding = encodingService.loadEncoding(ByteList.create(encoding));
if (loadedEncoding == null) throw new MainExitException(1, "unknown encoding name - " + encoding);
setDefaultInternalEncoding(loadedEncoding);
}
if (profile.allowClass("Complex")) {
RubyComplex.createComplexClass(this);
}
if (profile.allowClass("Rational")) {
RubyRational.createRationalClass(this);
}
if (profile.allowClass("Hash")) {
RubyHash.createHashClass(this);
}
if (profile.allowClass("Array")) {
RubyArray.createArrayClass(this);
emptyFrozenArray = newEmptyArray();
emptyFrozenArray.setFrozen(true);
}
if (profile.allowClass("Float")) {
RubyFloat.createFloatClass(this);
}
if (profile.allowClass("Bignum")) {
RubyBignum.createBignumClass(this);
RubyRandom.createRandomClass(this);
}
ioClass = RubyIO.createIOClass(this);
if (profile.allowClass("Struct")) {
RubyStruct.createStructClass(this);
}
if (profile.allowClass("Binding")) {
RubyBinding.createBindingClass(this);
}
if (profile.allowModule("Math")) {
RubyMath.createMathModule(this);
}
if (profile.allowClass("Regexp")) {
RubyRegexp.createRegexpClass(this);
}
if (profile.allowClass("Range")) {
RubyRange.createRangeClass(this);
}
if (profile.allowModule("ObjectSpace")) {
RubyObjectSpace.createObjectSpaceModule(this);
}
if (profile.allowModule("GC")) {
RubyGC.createGCModule(this);
}
if (profile.allowClass("Proc")) {
RubyProc.createProcClass(this);
}
if (profile.allowClass("Method")) {
RubyMethod.createMethodClass(this);
}
if (profile.allowClass("MatchData")) {
RubyMatchData.createMatchDataClass(this);
}
if (profile.allowModule("Marshal")) {
RubyMarshal.createMarshalModule(this);
}
if (profile.allowClass("Dir")) {
RubyDir.createDirClass(this);
}
if (profile.allowModule("FileTest")) {
RubyFileTest.createFileTestModule(this);
}
if (profile.allowClass("File")) {
RubyFile.createFileClass(this);
}
if (profile.allowClass("File::Stat")) {
RubyFileStat.createFileStatClass(this);
}
if (profile.allowModule("Process")) {
RubyProcess.createProcessModule(this);
}
if (profile.allowClass("Time")) {
RubyTime.createTimeClass(this);
}
if (profile.allowClass("UnboundMethod")) {
RubyUnboundMethod.defineUnboundMethodClass(this);
}
if (profile.allowModule("Signal")) {
RubySignal.createSignal(this);
}
if (profile.allowClass("Enumerator")) {
RubyEnumerator.defineEnumerator(this);
}
initContinuation();
TracePoint.createTracePointClass(this);
RubyWarnings.createWarningModule(this);
}
@SuppressWarnings("deprecation")
private void initContinuation() {
if (profile.allowClass("Continuation")) {
RubyContinuation.createContinuation(this);
}
}
public static final int NIL_PREFILLED_ARRAY_SIZE = RubyArray.ARRAY_DEFAULT_SIZE * 8;
private final IRubyObject nilPrefilledArray[] = new IRubyObject[NIL_PREFILLED_ARRAY_SIZE];
public IRubyObject[] getNilPrefilledArray() {
return nilPrefilledArray;
}
private void initExceptions() {
ifAllowed("StandardError", (ruby) -> standardError = RubyStandardError.define(ruby, exceptionClass));
ifAllowed("RubyError", (ruby) -> runtimeError = RubyRuntimeError.define(ruby, standardError));
ifAllowed("FrozenError", (ruby) -> frozenError = RubyFrozenError.define(ruby, runtimeError));
ifAllowed("IOError", (ruby) -> ioError = RubyIOError.define(ruby, standardError));
ifAllowed("ScriptError", (ruby) -> scriptError = RubyScriptError.define(ruby, exceptionClass));
ifAllowed("RangeError", (ruby) -> rangeError = RubyRangeError.define(ruby, standardError));
ifAllowed("SignalException", (ruby) -> signalException = RubySignalException.define(ruby, exceptionClass));
ifAllowed("NameError", (ruby) -> {
nameError = RubyNameError.define(ruby, standardError);
nameErrorMessage = RubyNameError.RubyNameErrorMessage.define(ruby, nameError);
});
ifAllowed("NoMethodError", (ruby) -> noMethodError = RubyNoMethodError.define(ruby, nameError));
ifAllowed("SystemExit", (ruby) -> systemExit = RubySystemExit.define(ruby, exceptionClass));
ifAllowed("LocalJumpError", (ruby) -> localJumpError = RubyLocalJumpError.define(ruby, standardError));
ifAllowed("SystemCallError", (ruby) -> systemCallError = RubySystemCallError.define(ruby, standardError));
ifAllowed("Fatal", (ruby) -> fatal = RubyFatal.define(ruby, exceptionClass));
ifAllowed("Interrupt", (ruby) -> interrupt = RubyInterrupt.define(ruby, signalException));
ifAllowed("TypeError", (ruby) -> typeError = RubyTypeError.define(ruby, standardError));
ifAllowed("ArgumentError", (ruby) -> argumentError = RubyArgumentError.define(ruby, standardError));
ifAllowed("UncaughtThrowError", (ruby) -> uncaughtThrowError = RubyUncaughtThrowError.define(ruby, argumentError));
ifAllowed("IndexError", (ruby) -> indexError = RubyIndexError.define(ruby, standardError));
ifAllowed("StopIteration", (ruby) -> stopIteration = RubyStopIteration.define(ruby, indexError));
ifAllowed("SyntaxError", (ruby) -> syntaxError = RubySyntaxError.define(ruby, scriptError));
ifAllowed("LoadError", (ruby) -> loadError = RubyLoadError.define(ruby, scriptError));
ifAllowed("NotImplementedError", (ruby) -> notImplementedError = RubyNotImplementedError.define(ruby, scriptError));
ifAllowed("SecurityError", (ruby) -> securityError = RubySecurityError.define(ruby, exceptionClass));
ifAllowed("NoMemoryError", (ruby) -> noMemoryError = RubyNoMemoryError.define(ruby, exceptionClass));
ifAllowed("RegexpError", (ruby) -> regexpError = RubyRegexpError.define(ruby, standardError));
ifAllowed("InterruptedRegexpError", (ruby) -> interruptedRegexpError = RubyInterruptedRegexpError.define(ruby, regexpError));
ifAllowed("EOFError", (ruby) -> eofError = RubyEOFError.define(ruby, ioError));
ifAllowed("ThreadError", (ruby) -> threadError = RubyThreadError.define(ruby, standardError));
ifAllowed("ConcurrencyError", (ruby) -> concurrencyError = RubyConcurrencyError.define(ruby, threadError));
ifAllowed("SystemStackError", (ruby) -> systemStackError = RubySystemStackError.define(ruby, exceptionClass));
ifAllowed("ZeroDivisionError", (ruby) -> zeroDivisionError = RubyZeroDivisionError.define(ruby, standardError));
ifAllowed("FloatDomainError", (ruby) -> floatDomainError = RubyFloatDomainError.define(ruby, rangeError));
ifAllowed("EncodingError", (ruby) -> {
encodingError = RubyEncodingError.define(ruby, standardError);
encodingCompatibilityError = RubyEncodingError.RubyCompatibilityError.define(ruby, encodingError, encodingClass);
invalidByteSequenceError = RubyEncodingError.RubyInvalidByteSequenceError.define(ruby, encodingError, encodingClass);
undefinedConversionError = RubyEncodingError.RubyUndefinedConversionError.define(ruby, encodingError, encodingClass);
converterNotFoundError = RubyEncodingError.RubyConverterNotFoundError.define(ruby, encodingError, encodingClass);
});
ifAllowed("Fiber", (ruby) -> fiberError = RubyFiberError.define(ruby, standardError));
ifAllowed("ConcurrencyError", (ruby) -> concurrencyError = RubyConcurrencyError.define(ruby, threadError));
ifAllowed("KeyError", (ruby) -> keyError = RubyKeyError.define(ruby, indexError));
ifAllowed("DomainError", (ruby) -> mathDomainError = RubyDomainError.define(ruby, argumentError, mathModule));
initErrno();
initNativeException();
}
private void ifAllowed(String name, Consumer<Ruby> callback) {
if (profile.allowClass(name)) {
callback.accept(this);
}
}
@SuppressWarnings("deprecation")
private void initNativeException() {
if (profile.allowClass("NativeException")) {
nativeException = NativeException.createClass(this, runtimeError);
}
}
private void initLibraries() {
Mutex.setup(this);
ConditionVariable.setup(this);
org.jruby.ext.thread.Queue.setup(this);
SizedQueue.setup(this);
new ThreadFiberLibrary().load(this, false);
}
private final Map<Integer, RubyClass> errnos = new HashMap<>();
public RubyClass getErrno(int n) {
return errnos.get(n);
}
private void initErrno() {
if (profile.allowModule("Errno")) {
errnoModule = defineModule("Errno");
try {
createSysErr(Errno.EAGAIN.intValue(), Errno.EAGAIN.name());
for (Errno e : Errno.values()) {
Constant c = (Constant) e;
if (Character.isUpperCase(c.name().charAt(0))) {
createSysErr(c.intValue(), c.name());
}
}
errnos.put(Errno.ENOSYS.intValue(), notImplementedError);
} catch (Exception e) {
LOG.error(e);
}
}
}
private void createSysErr(int i, String name) {
if (profile.allowClass(name)) {
if (errnos.get(i) == null) {
RubyClass errno = getErrno().defineClassUnder(name, systemCallError, systemCallError.getAllocator());
errnos.put(i, errno);
errno.defineConstant("Errno", newFixnum(i));
} else {
getErrno().setConstant(name, errnos.get(i));
}
}
}
private void initJavaSupport() {
boolean reflectionWorks = doesReflectionWork();
if (reflectionWorks) {
new Java().load(this, false);
new JRubyLibrary().load(this, false);
new JRubyUtilLibrary().load(this, false);
loadService.provide("java", "java.rb");
loadService.provide("jruby", "jruby.rb");
loadService.provide("jruby/util", "jruby/util.rb");
}
}
private void initRubyKernel() {
loadService.loadFromClassLoader(getClassLoader(), "jruby/kernel.rb", false);
}
private void initRubyPreludes() {
if (RubyInstanceConfig.DEBUG_PARSER) return;
loadService.loadFromClassLoader(getClassLoader(), "jruby/preludes.rb", false);
}
public IRManager getIRManager() {
return irManager;
}
public IRubyObject getTopSelf() {
return topSelf;
}
public IRubyObject getRootFiber() {
return rootFiber;
}
public void setRootFiber(IRubyObject fiber) {
rootFiber = fiber;
}
public void setCurrentDirectory(String dir) {
currentDirectory = dir;
}
public String getCurrentDirectory() {
return currentDirectory;
}
public void setCurrentLine(int line) {
currentLine = line;
}
public int getCurrentLine() {
return currentLine;
}
public void setArgsFile(IRubyObject argsFile) {
this.argsFile = argsFile;
}
public IRubyObject getArgsFile() {
return argsFile;
}
public RubyModule getEtc() {
return etcModule;
}
public void setEtc(RubyModule etcModule) {
this.etcModule = etcModule;
}
public RubyClass getObject() {
return objectClass;
}
public RubyClass getBasicObject() {
return basicObjectClass;
}
public RubyClass getModule() {
return moduleClass;
}
public RubyClass getClassClass() {
return classClass;
}
public RubyModule getKernel() {
return kernelModule;
}
void setKernel(RubyModule kernelModule) {
this.kernelModule = kernelModule;
}
public DynamicMethod getPrivateMethodMissing() {
return privateMethodMissing;
}
public void setPrivateMethodMissing(DynamicMethod method) {
privateMethodMissing = method;
}
public DynamicMethod getProtectedMethodMissing() {
return protectedMethodMissing;
}
public void setProtectedMethodMissing(DynamicMethod method) {
protectedMethodMissing = method;
}
public DynamicMethod getVariableMethodMissing() {
return variableMethodMissing;
}
public void setVariableMethodMissing(DynamicMethod method) {
variableMethodMissing = method;
}
public DynamicMethod getSuperMethodMissing() {
return superMethodMissing;
}
public void setSuperMethodMissing(DynamicMethod method) {
superMethodMissing = method;
}
public DynamicMethod getNormalMethodMissing() {
return normalMethodMissing;
}
public void setNormalMethodMissing(DynamicMethod method) {
normalMethodMissing = method;
}
public DynamicMethod getDefaultMethodMissing() {
return defaultMethodMissing;
}
public boolean isDefaultMethodMissing(DynamicMethod method) {
return defaultMethodMissing == method || defaultModuleMethodMissing == method;
}
public void setDefaultMethodMissing(DynamicMethod method, DynamicMethod moduleMethod) {
defaultMethodMissing = method;
defaultModuleMethodMissing = moduleMethod;
}
public DynamicMethod getRespondToMethod() {
return respondTo;
}
public void setRespondToMethod(DynamicMethod rtm) {
this.respondTo = rtm;
}
public DynamicMethod getRespondToMissingMethod() {
return respondToMissing;
}
public void setRespondToMissingMethod(DynamicMethod rtmm) {
this.respondToMissing = rtmm;
}
public RubyClass getDummy() {
return dummyClass;
}
public RubyModule getComparable() {
return comparableModule;
}
void setComparable(RubyModule comparableModule) {
this.comparableModule = comparableModule;
}
public RubyClass getNumeric() {
return numericClass;
}
void setNumeric(RubyClass numericClass) {
this.numericClass = numericClass;
}
public RubyClass getFloat() {
return floatClass;
}
void setFloat(RubyClass floatClass) {
this.floatClass = floatClass;
}
public RubyClass getInteger() {
return integerClass;
}
void setInteger(RubyClass integerClass) {
this.integerClass = integerClass;
}
public RubyClass getFixnum() {
return fixnumClass;
}
void setFixnum(RubyClass fixnumClass) {
this.fixnumClass = fixnumClass;
}
public RubyClass getComplex() {
return complexClass;
}
void setComplex(RubyClass complexClass) {
this.complexClass = complexClass;
}
public RubyClass getRational() {
return rationalClass;
}
void setRational(RubyClass rationalClass) {
this.rationalClass = rationalClass;
}
public RubyModule getEnumerable() {
return enumerableModule;
}
void setEnumerable(RubyModule enumerableModule) {
this.enumerableModule = enumerableModule;
}
public RubyClass getEnumerator() {
return enumeratorClass;
}
void setEnumerator(RubyClass enumeratorClass) {
this.enumeratorClass = enumeratorClass;
}
public RubyClass getYielder() {
return yielderClass;
}
void setYielder(RubyClass yielderClass) {
this.yielderClass = yielderClass;
}
public RubyClass getGenerator() {
return generatorClass;
}
public void setGenerator(RubyClass generatorClass) {
this.generatorClass = generatorClass;
}
public RubyClass getFiber() {
return fiberClass;
}
public void setFiber(RubyClass fiberClass) {
this.fiberClass = fiberClass;
}
public RubyClass getString() {
return stringClass;
}
void setString(RubyClass stringClass) {
this.stringClass = stringClass;
}
public RubyClass getEncoding() {
return encodingClass;
}
void setEncoding(RubyClass encodingClass) {
this.encodingClass = encodingClass;
}
public RubyClass getConverter() {
return converterClass;
}
void setConverter(RubyClass converterClass) {
this.converterClass = converterClass;
}
public RubyClass getSymbol() {
return symbolClass;
}
void setSymbol(RubyClass symbolClass) {
this.symbolClass = symbolClass;
}
public RubyClass getArray() {
return arrayClass;
}
void setArray(RubyClass arrayClass) {
this.arrayClass = arrayClass;
}
public RubyClass getHash() {
return hashClass;
}
void setHash(RubyClass hashClass) {
this.hashClass = hashClass;
}
public RubyClass getRange() {
return rangeClass;
}
void setRange(RubyClass rangeClass) {
this.rangeClass = rangeClass;
}
public RubyBoolean getTrue() {
return trueObject;
}
public RubyBoolean getFalse() {
return falseObject;
}
public IRubyObject getNil() {
return nilObject;
}
public IRubyObject[] getSingleNilArray() {
return singleNilArray;
}
public RubyClass getNilClass() {
return nilClass;
}
void setNilClass(RubyClass nilClass) {
this.nilClass = nilClass;
}
public RubyClass getTrueClass() {
return trueClass;
}
void setTrueClass(RubyClass trueClass) {
this.trueClass = trueClass;
}
public RubyClass getFalseClass() {
return falseClass;
}
void setFalseClass(RubyClass falseClass) {
this.falseClass = falseClass;
}
public RubyClass getProc() {
return procClass;
}
void setProc(RubyClass procClass) {
this.procClass = procClass;
}
public RubyClass getBinding() {
return bindingClass;
}
void setBinding(RubyClass bindingClass) {
this.bindingClass = bindingClass;
}
public RubyClass getMethod() {
return methodClass;
}
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;
}
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;
}
void setThreadGroup(RubyClass threadGroupClass) {
this.threadGroupClass = threadGroupClass;
}
public RubyThreadGroup getDefaultThreadGroup() {
return defaultThreadGroup;
}
void setDefaultThreadGroup(RubyThreadGroup defaultThreadGroup) {
this.defaultThreadGroup = defaultThreadGroup;
}
public RubyClass getContinuation() {
return continuationClass;
}
void setContinuation(RubyClass continuationClass) {
this.continuationClass = continuationClass;
}
public RubyClass getStructClass() {
return structClass;
}
void setStructClass(RubyClass structClass) {
this.structClass = structClass;
}
public RubyClass getRandomClass() {
return randomClass;
}
void setRandomClass(RubyClass randomClass) {
this.randomClass = randomClass;
}
public IRubyObject getTmsStruct() {
return tmsStruct;
}
void setTmsStruct(RubyClass tmsStruct) {
this.tmsStruct = tmsStruct;
}
public IRubyObject getPasswdStruct() {
return passwdStruct;
}
public void setPasswdStruct(RubyClass passwdStruct) {
this.passwdStruct = passwdStruct;
}
public IRubyObject getGroupStruct() {
return groupStruct;
}
public void setGroupStruct(RubyClass groupStruct) {
this.groupStruct = groupStruct;
}
public RubyModule getGC() {
return gcModule;
}
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;
}
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;
}
void setProcSys(RubyModule procSysModule) {
this.procSysModule = procSysModule;
}
public RubyModule getPrecision() {
return precisionModule;
}
void setPrecision(RubyModule precisionModule) {
this.precisionModule = precisionModule;
}
public RubyHash getENV() {
return envObject;
}
public void setENV(RubyHash env) {
envObject = env;
}
public RubyClass getLocation() {
return locationClass;
}
public void setLocation(RubyClass location) {
this.locationClass = location;
}
public RubyModule getWarning() {
return warningModule;
}
public void setWarning(RubyModule warningModule) {
this.warningModule = warningModule;
}
public RubyModule getErrno() {
return errnoModule;
}
public RubyClass getException() {
return exceptionClass;
}
void setException(RubyClass exceptionClass) {
this.exceptionClass = exceptionClass;
}
public RubyClass getNameError() {
return nameError;
}
public RubyClass getNameErrorMessage() {
return nameErrorMessage;
}
public RubyClass getNoMethodError() {
return noMethodError;
}
public RubyClass getSignalException() {
return signalException;
}
public RubyClass getRangeError() {
return rangeError;
}
public RubyClass getSystemExit() {
return systemExit;
}
public RubyClass getLocalJumpError() {
return localJumpError;
}
public RubyClass getNativeException() {
return nativeException;
}
public RubyClass getSystemCallError() {
return systemCallError;
}
public RubyClass getKeyError() {
return keyError;
}
public RubyClass getFatal() {
return fatal;
}
public RubyClass getInterrupt() {
return interrupt;
}
public RubyClass getTypeError() {
return typeError;
}
public RubyClass getArgumentError() {
return argumentError;
}
public RubyClass getUncaughtThrowError() {
return uncaughtThrowError;
}
public RubyClass getIndexError() {
return indexError;
}
public RubyClass getStopIteration() {
return stopIteration;
}
public RubyClass getSyntaxError() {
return syntaxError;
}
public RubyClass getStandardError() {
return standardError;
}
public RubyClass getRuntimeError() {
return runtimeError;
}
public RubyClass getFrozenError() {
return frozenError;
}
public RubyClass getIOError() {
return ioError;
}
public RubyClass getLoadError() {
return loadError;
}
public RubyClass getNotImplementedError() {
return notImplementedError;
}
public RubyClass getSecurityError() {
return securityError;
}
public RubyClass getNoMemoryError() {
return noMemoryError;
}
public RubyClass getRegexpError() {
return regexpError;
}
public RubyClass getInterruptedRegexpError() {
return interruptedRegexpError;
}
public RubyClass getEOFError() {
return eofError;
}
public RubyClass getThreadError() {
return threadError;
}
public RubyClass getConcurrencyError() {
return concurrencyError;
}
public RubyClass getSystemStackError() {
return systemStackError;
}
public RubyClass getZeroDivisionError() {
return zeroDivisionError;
}
public RubyClass getFloatDomainError() {
return floatDomainError;
}
public RubyClass getMathDomainError() {
return mathDomainError;
}
public RubyClass getEncodingError() {
return encodingError;
}
public RubyClass getEncodingCompatibilityError() {
return encodingCompatibilityError;
}
public RubyClass getConverterNotFoundError() {
return converterNotFoundError;
}
public RubyClass getFiberError() {
return fiberError;
}
public RubyClass getUndefinedConversionError() {
return undefinedConversionError;
}
public RubyClass getInvalidByteSequenceError() {
return invalidByteSequenceError;
}
RubyRandom.RandomType defaultRand;
public RubyRandom.RandomType getDefaultRand() {
return defaultRand;
}
public void setDefaultRand(RubyRandom.RandomType defaultRand) {
this.defaultRand = defaultRand;
}
private RubyHash charsetMap;
@Deprecated
public RubyHash getCharsetMap() {
if (charsetMap == null) charsetMap = new RubyHash(this);
return charsetMap;
}
public IRubyObject getVerbose() {
return verboseValue;
}
public boolean isVerbose() {
return verbose;
}
public boolean warningsEnabled() {
return warningsEnabled;
}
public void setVerbose(IRubyObject verbose) {
this.verbose = verbose.isTrue();
this.verboseValue = verbose;
warningsEnabled = !verbose.isNil();
}
public IRubyObject getDebug() {
return debug ? trueObject : falseObject;
}
public boolean isDebug() {
return debug;
}
public void setDebug(IRubyObject debug) {
this.debug = debug.isTrue();
}
public JavaSupport getJavaSupport() {
return javaSupport;
}
public static ClassLoader getClassLoader() {
ClassLoader loader = Ruby.class.getClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
return loader;
}
public JRubyClassLoader getJRubyClassLoader() {
return jrubyClassLoader;
}
public void defineVariable(final GlobalVariable variable, org.jruby.internal.runtime.GlobalVariable.Scope scope) {
globalVariables.define(variable.name(), new IAccessor() {
@Override
public IRubyObject getValue() {
return variable.get();
}
@Override
public IRubyObject setValue(IRubyObject newValue) {
return variable.set(newValue);
}
}, scope);
}
public void defineReadonlyVariable(String name, IRubyObject value, org.jruby.internal.runtime.GlobalVariable.Scope scope) {
globalVariables.defineReadonly(name, new ValueAccessor(value), scope);
}
public Node parseFile(InputStream in, String file, DynamicScope scope) {
return parseFile(in, file, scope, 0);
}
public ParseResult parseFile(String file, InputStream in, DynamicScope scope) {
return parseFile(file, in, scope, 0);
}
public Node parseFile(InputStream in, String file, DynamicScope scope, int lineNumber) {
addLoadParseToStats();
return parseFileAndGetAST(in, file, scope, lineNumber, false);
}
public ParseResult parseFile(String file, InputStream in, DynamicScope scope, int lineNumber) {
addLoadParseToStats();
if (!RubyInstanceConfig.IR_READING) return (ParseResult) parseFileAndGetAST(in, file, scope, lineNumber, false);
try {
return IRReader.load(getIRManager(), new IRReaderStream(getIRManager(), IRFileExpert.getIRPersistedFile(file), new ByteList(file.getBytes())));
} catch (IOException e) {
return (ParseResult) parseFileAndGetAST(in, file, scope, lineNumber, false);
}
}
public Node parseFileFromMain(InputStream in, String file, DynamicScope scope) {
addLoadParseToStats();
return parseFileFromMainAndGetAST(in, file, scope);
}
public ParseResult parseFileFromMain(String file, InputStream in, DynamicScope scope) {
addLoadParseToStats();
if (!RubyInstanceConfig.IR_READING) return (ParseResult) parseFileFromMainAndGetAST(in, file, scope);
try {
return IRReader.load(getIRManager(), new IRReaderStream(getIRManager(), IRFileExpert.getIRPersistedFile(file), new ByteList(file.getBytes())));
} catch (IOException ex) {
if (config.isVerbose()) {
LOG.info(ex);
}
else {
LOG.debug(ex);
}
return (ParseResult) parseFileFromMainAndGetAST(in, file, scope);
}
}
private Node parseFileFromMainAndGetAST(InputStream in, String file, DynamicScope scope) {
return parseFileAndGetAST(in, file, scope, 0, true);
}
private Node parseFileAndGetAST(InputStream in, String file, DynamicScope scope, int lineNumber, boolean isFromMain) {
ParserConfiguration parserConfig =
new ParserConfiguration(this, lineNumber, false, true, isFromMain, config);
setupSourceEncoding(parserConfig, UTF8Encoding.INSTANCE);
return parser.parse(file, in, scope, parserConfig);
}
public Node parseInline(InputStream in, String file, DynamicScope scope) {
addEvalParseToStats();
ParserConfiguration parserConfig =
new ParserConfiguration(this, 0, false, true, false, config);
setupSourceEncoding(parserConfig, getEncodingService().getLocaleEncoding());
return parser.parse(file, in, scope, parserConfig);
}
private void setupSourceEncoding(ParserConfiguration parserConfig, Encoding defaultEncoding) {
if (config.getSourceEncoding() != null) {
if (config.isVerbose()) {
config.getError().println("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
}
parserConfig.setDefaultEncoding(getEncodingService().getEncodingFromString(config.getSourceEncoding()));
} else {
parserConfig.setDefaultEncoding(defaultEncoding);
}
}
public Node parseEval(String content, String file, DynamicScope scope, int lineNumber) {
addEvalParseToStats();
return parser.parse(file, encodeToBytes(content), scope, new ParserConfiguration(this, lineNumber, false, false, config));
}
private byte[] encodeToBytes(String string) {
Charset charset = getDefaultCharset();
byte[] bytes = charset == null ? string.getBytes() : string.getBytes(charset);
return bytes;
}
@Deprecated
public Node parse(String content, String file, DynamicScope scope, int lineNumber,
boolean extraPositionInformation) {
return parser.parse(file, content.getBytes(), scope, new ParserConfiguration(this,
lineNumber, extraPositionInformation, false, true, config));
}
public Node parseEval(ByteList content, String file, DynamicScope scope, int lineNumber) {
addEvalParseToStats();
return parser.parse(file, content, scope, new ParserConfiguration(this,
lineNumber, false, false, false, config));
}
public Node parse(ByteList content, String file, DynamicScope scope, int lineNumber,
boolean extraPositionInformation) {
addEvalParseToStats();
return parser.parse(file, content, scope, new ParserConfiguration(this,
lineNumber, extraPositionInformation, false, true, config));
}
public ThreadService getThreadService() {
return threadService;
}
public ThreadContext getCurrentContext() {
return threadService.getCurrentContext();
}
public LoadService getLoadService() {
return loadService;
}
public Encoding getDefaultInternalEncoding() {
return defaultInternalEncoding;
}
public void setDefaultInternalEncoding(Encoding defaultInternalEncoding) {
this.defaultInternalEncoding = defaultInternalEncoding;
}
public Encoding getDefaultExternalEncoding() {
return defaultExternalEncoding;
}
public void setDefaultExternalEncoding(Encoding defaultExternalEncoding) {
this.defaultExternalEncoding = defaultExternalEncoding;
}
public Encoding getDefaultFilesystemEncoding() {
return defaultFilesystemEncoding;
}
public void setDefaultFilesystemEncoding(Encoding defaultFilesystemEncoding) {
this.defaultFilesystemEncoding = defaultFilesystemEncoding;
}
public Charset getDefaultCharset() {
Encoding enc = getDefaultEncoding();
Charset charset = EncodingUtils.charsetForEncoding(enc);
return charset;
}
public Encoding getDefaultEncoding() {
Encoding enc = getDefaultInternalEncoding();
if (enc == null) {
enc = UTF8Encoding.INSTANCE;
}
return enc;
}
public EncodingService getEncodingService() {
return encodingService;
}
public RubyWarnings getWarnings() {
return warnings;
}
WarnCallback getRegexpWarnings() {
return regexpWarnings;
}
public PrintStream getErrorStream() {
return new PrintStream(new IOOutputStream(getGlobalVariables().get("$stderr")));
}
public InputStream getInputStream() {
return new IOInputStream(getGlobalVariables().get("$stdin"));
}
public PrintStream getOutputStream() {
return new PrintStream(new IOOutputStream(getGlobalVariables().get("$stdout")));
}
public RubyModule getClassFromPath(final String path) {
return getClassFromPath(path, getTypeError(), true);
}
public RubyModule getClassFromPath(final String path, RubyClass undefinedExceptionClass, boolean flexibleSearch) {
if (path.length() == 0 || path.charAt(0) == '#') {
throw newRaiseException(getTypeError(), str(this, "can't retrieve anonymous class ", ids(this, path)));
}
ThreadContext context = getCurrentContext();
RubyModule c = getObject();
int pbeg = 0, p = 0;
for (int l = path.length(); p < l; ) {
while ( p < l && path.charAt(p) != ':' ) p++;
final String str = path.substring(pbeg, p);
if ( p < l && path.charAt(p) == ':' ) {
if ( ++p < l && path.charAt(p) != ':' ) {
throw newRaiseException(undefinedExceptionClass, str(this, "undefined class/module ", ids(this, path)));
}
pbeg = ++p;
}
boolean isJava = c instanceof JavaPackage || JavaClass.isProxyType(context, c);
IRubyObject cc = flexibleSearch || isJava ? c.getConstant(str) : c.getConstantAt(str);
if (!flexibleSearch && cc == null) return null;
if (!(cc instanceof RubyModule)) {
throw newRaiseException(getTypeError(), str(this, ids(this, path), " does not refer to class/module"));
}
c = (RubyModule) cc;
}
return c;
}
public void printError(final RubyException ex) {
if (ex == null) return;
PrintStream errorStream = getErrorStream();
String backtrace = config.getTraceType().printBacktrace(ex, errorStream == System.err && getPosix().isatty(FileDescriptor.err));
try {
errorStream.print(backtrace);
} catch (Exception e) {
System.err.print(backtrace);
}
}
public void printError(final Throwable ex) {
if (ex instanceof RaiseException) {
printError(((RaiseException) ex).getException());
return;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream errorStream = getErrorStream();
ex.printStackTrace(new PrintStream(baos));
try {
errorStream.write(baos.toByteArray());
} catch (Exception e) {
try {
System.err.write(baos.toByteArray());
} catch (IOException ioe) {
ioe.initCause(e);
throw new RuntimeException("BUG: could not write exception trace", ioe);
}
}
}
static final String ROOT_FRAME_NAME = "(root)";
public void loadFile(String scriptName, InputStream in, boolean wrap) {
IRubyObject self = wrap ? getTopSelf().rbClone() : getTopSelf();
ThreadContext context = getCurrentContext();
try {
context.preNodeEval(self);
ParseResult parseResult = parseFile(scriptName, in, null);
if (wrap) wrapWithModule((RubyBasicObject) self, parseResult);
runInterpreter(context, parseResult, self);
} finally {
context.postNodeEval();
}
}
public void loadScope(IRScope scope, boolean wrap) {
IRubyObject self = wrap ? TopSelfFactory.createTopSelf(this, true) : getTopSelf();
if (wrap) {
scope.getStaticScope().setModule(RubyModule.newModule(this));
}
runInterpreter(getCurrentContext(), scope, self);
}
public void compileAndLoadFile(String filename, InputStream in, boolean wrap) {
IRubyObject self = wrap ? getTopSelf().rbClone() : getTopSelf();
ParseResult parseResult = parseFile(filename, in, null);
RootNode root = (RootNode) parseResult;
if (wrap) {
wrapWithModule((RubyBasicObject) self, root);
} else {
root.getStaticScope().setModule(getObject());
}
runNormally(root, wrap);
}
private void wrapWithModule(RubyBasicObject self, ParseResult result) {
RubyModule wrapper = RubyModule.newModule(this);
self.extend(new IRubyObject[] {wrapper});
StaticScope top = result.getStaticScope();
StaticScope newTop = staticScopeFactory.newLocalScope(null);
top.setPreviousCRefScope(newTop);
top.setModule(wrapper);
}
public void loadScript(Script script) {
loadScript(script, false);
}
public void loadScript(Script script, boolean wrap) {
script.load(getCurrentContext(), getTopSelf(), wrap);
}
public void loadExtension(String extName, BasicLibraryService extension, boolean wrap) {
IRubyObject self = wrap ? TopSelfFactory.createTopSelf(this, true) : getTopSelf();
ThreadContext context = getCurrentContext();
try {
context.preExtensionLoad(self);
extension.basicLoad(this);
} catch (IOException ioe) {
throw newIOErrorFromException(ioe);
} finally {
context.postNodeEval();
}
}
public void addBoundMethod(String className, String methodName, String rubyName) {
Map<String, String> javaToRuby = boundMethods.get(className);
if (javaToRuby == null) boundMethods.put(className, javaToRuby = new HashMap<>());
javaToRuby.put(methodName, rubyName);
}
public void addBoundMethods(String className, String... tuples) {
Map<String, String> javaToRuby = boundMethods.get(className);
if (javaToRuby == null) boundMethods.put(className, javaToRuby = new HashMap<>(tuples.length / 2 + 1, 1));
for (int i = 0; i < tuples.length; i += 2) {
javaToRuby.put(tuples[i], tuples[i+1]);
}
}
@Deprecated
public void addBoundMethodsPacked(String className, String packedTuples) {
List<String> names = StringSupport.split(packedTuples, ';');
for (int i = 0; i < names.size(); i += 2) {
addBoundMethod(className, names.get(i), names.get(i+1));
}
}
@Deprecated
public void addSimpleBoundMethodsPacked(String className, String packedNames) {
List<String> names = StringSupport.split(packedNames, ';');
for (String name : names) {
addBoundMethod(className, name, name);
}
}
public Map<String, Map<String, String>> getBoundMethods() {
return boundMethods;
}
public void setJavaProxyClassFactory(JavaProxyClassFactory factory) {
this.javaProxyClassFactory = factory;
}
public JavaProxyClassFactory getJavaProxyClassFactory() {
return javaProxyClassFactory;
}
private static final EnumSet<RubyEvent> interest =
EnumSet.of(
RubyEvent.C_CALL,
RubyEvent.C_RETURN,
RubyEvent.CALL,
RubyEvent.CLASS,
RubyEvent.END,
RubyEvent.LINE,
RubyEvent.RAISE,
RubyEvent.RETURN
);
public static 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 = context.nil;
Ruby runtime = context.runtime;
RubyBinding binding = RubyBinding.newBinding(runtime, context.currentBinding());
context.preTrace();
try {
traceFunc.call(context, new IRubyObject[]{
runtime.newString(eventName),
runtime.newString(file),
runtime.newFixnum(line),
name != null ? runtime.newSymbol(name) : runtime.getNil(),
binding,
type
});
} finally {
context.postTrace();
}
}
}
@Override
public boolean isInterestedInEvent(RubyEvent event) {
return interest.contains(event);
}
@Override
public EnumSet<RubyEvent> eventSet() {
return interest;
}
};
private static final CallTraceFuncHook callTraceFuncHook = new CallTraceFuncHook();
public synchronized void addEventHook(EventHook hook) {
if (!RubyInstanceConfig.FULL_TRACE_ENABLED && hook.needsDebug()) {
getWarnings().warn("tracing (e.g. set_trace_func) will not capture all events without --debug flag");
}
EventHook[] hooks = eventHooks;
EventHook[] newHooks = Arrays.copyOf(hooks, hooks.length + 1);
newHooks[hooks.length] = hook;
eventHooks = newHooks;
hasEventHooks = true;
}
public synchronized void removeEventHook(EventHook hook) {
EventHook[] hooks = eventHooks;
if (hooks.length == 0) return;
int pivot = -1;
for (int i = 0; i < hooks.length; i++) {
if (hooks[i] == hook) {
pivot = i;
break;
}
}
if (pivot == -1) return;
EventHook[] newHooks = new EventHook[hooks.length - 1];
if (pivot != 0) System.arraycopy(hooks, 0, newHooks, 0, pivot);
if (pivot != hooks.length-1) System.arraycopy(hooks, pivot + 1, newHooks, pivot, hooks.length - (pivot + 1));
eventHooks = newHooks;
hasEventHooks = newHooks.length > 0;
}
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) {
if (context.isEventHooksEnabled()) {
EventHook hooks[] = eventHooks;
for (EventHook eventHook: hooks) {
if (eventHook.isInterestedInEvent(event)) {
IRubyObject klass = context.nil;
if (type instanceof RubyModule) {
if (((RubyModule) type).isIncluded()) {
klass = ((RubyModule) type).getNonIncludedClass();
} else if (((RubyModule) type).isSingleton()) {
klass = ((MetaClass) type).getAttached();
}
}
eventHook.event(context, event, file, line, name, klass);
}
}
}
}
public boolean hasEventHooks() {
return hasEventHooks;
}
public GlobalVariables getGlobalVariables() {
return globalVariables;
}
public void setGlobalVariables(GlobalVariables globalVariables) {
this.globalVariables = globalVariables;
}
public IRubyObject pushExitBlock(RubyProc proc) {
atExitBlocks.push(proc);
return proc;
}
public void pushEndBlock(RubyProc proc) {
if (alreadyRegisteredEndBlock(proc) != null) return;
pushExitBlock(proc);
}
private RubyProc alreadyRegisteredEndBlock(RubyProc newProc) {
Block block = newProc.getBlock();
for (RubyProc proc: atExitBlocks) {
if (block.equals(proc.getBlock())) return proc;
}
return null;
}
public void addInternalFinalizer(Finalizable finalizer) {
synchronized (internalFinalizersMutex) {
if (internalFinalizers == null) {
internalFinalizers = new WeakHashMap<Finalizable, Object>();
}
internalFinalizers.put(finalizer, null);
}
}
public void addFinalizer(Finalizable finalizer) {
synchronized (finalizersMutex) {
if (finalizers == null) {
finalizers = new WeakHashMap<Finalizable, Object>();
}
finalizers.put(finalizer, null);
}
}
public void removeInternalFinalizer(Finalizable finalizer) {
synchronized (internalFinalizersMutex) {
if (internalFinalizers != null) {
internalFinalizers.remove(finalizer);
}
}
}
public void removeFinalizer(Finalizable finalizer) {
synchronized (finalizersMutex) {
if (finalizers != null) {
finalizers.remove(finalizer);
}
}
}
public void tearDown() {
tearDown(true);
}
public void tearDown(boolean systemExit) {
int status = 0;
mriRecursionGuard = null;
final ThreadContext context = getCurrentContext();
if (!context.hasAnyScopes()) {
StaticScope topStaticScope = getStaticScopeFactory().newLocalScope(null);
context.pushScope(new ManyVarsDynamicScope(topStaticScope, null));
}
while (!atExitBlocks.empty()) {
RubyProc proc = atExitBlocks.pop();
try {
proc.call(context, IRubyObject.NULL_ARRAY);
} catch (RaiseException rj) {
if (rj.getException() instanceof RubyLocalJumpError) {
RubyLocalJumpError rlje = (RubyLocalJumpError) rj.getException();
String filename = proc.getBlock().getBinding().filename;
if (rlje.getReason() == RubyLocalJumpError.Reason.RETURN) {
getWarnings().warn(filename, "unexpected return");
} else {
getWarnings().warn(filename, "break from proc-closure");
}
} else {
RubyException raisedException = rj.getException();
if (!getSystemExit().isInstance(raisedException)) {
status = 1;
printError(raisedException);
} else {
IRubyObject statusObj = raisedException.callMethod(context, "status");
if (statusObj != null && !statusObj.isNil()) {
status = RubyNumeric.fix2int(statusObj);
}
}
}
} catch (IRReturnJump e) {
getWarnings().warn(proc.getBlock().getBinding().filename, "unexpected return");
}
}
IRubyObject trapResult = RubySignal.__jtrap_osdefault_kernel(this.getNil(), this.newString("EXIT"));
if (trapResult instanceof RubyArray) {
IRubyObject[] trapResultEntries = ((RubyArray) trapResult).toJavaArray();
IRubyObject exitHandlerProc = trapResultEntries[0];
if (exitHandlerProc instanceof RubyProc) {
((RubyProc) exitHandlerProc).call(context, getSingleNilArray());
}
}
if (finalizers != null) {
synchronized (finalizersMutex) {
for (Iterator<Finalizable> finalIter = new ArrayList<>(
finalizers.keySet()).iterator(); finalIter.hasNext();) {
Finalizable f = finalIter.next();
if (f != null) {
try {
f.finalize();
} catch (Throwable t) {
}
}
finalIter.remove();
}
}
}
synchronized (internalFinalizersMutex) {
if (internalFinalizers != null) {
for (Iterator<Finalizable> finalIter = new ArrayList<>(
internalFinalizers.keySet()).iterator(); finalIter.hasNext();) {
Finalizable f = finalIter.next();
if (f != null) {
try {
f.finalize();
} catch (Throwable t) {
}
}
finalIter.remove();
}
}
}
getBeanManager().unregisterCompiler();
getBeanManager().unregisterConfig();
getBeanManager().unregisterParserStats();
getBeanManager().unregisterMethodCache();
getBeanManager().unregisterRuntime();
getSelectorPool().cleanup();
if (config.isProfilingEntireRun()) {
ProfileCollection profileCollection = threadService.getMainThread().getContext().getProfileCollection();
printProfileData(profileCollection);
}
getThreadService().teardown();
getJITCompiler().shutdown();
getExecutor().shutdown();
getFiberExecutor().shutdown();
if (systemExit && status != 0) {
throw newSystemExit(status);
}
if (this == globalRuntime) {
synchronized (Ruby.class) {
if (this == globalRuntime) {
globalRuntime = null;
}
}
}
}
public void releaseClassLoader() {
if (jrubyClassLoader != null) {
jrubyClassLoader.close();
}
}
public synchronized void printProfileData( ProfileCollection profileData ) {
getProfilingService().newProfileReporter(getCurrentContext()).report(profileData);
}
private ProfilingServiceLookup getProfilingServiceLookup() {
return profilingServiceLookup;
}
public ProfilingService getProfilingService() {
ProfilingServiceLookup lockup = getProfilingServiceLookup();
return lockup == null ? null : lockup.getService();
}
public RubyArray newEmptyArray() {
return RubyArray.newEmptyArray(this);
}
public RubyArray newArray() {
return RubyArray.newArray(this);
}
public RubyArray newArrayLight() {
return RubyArray.newArrayLight(this);
}
public RubyArray newArray(IRubyObject object) {
return RubyArray.newArray(this, object);
}
public RubyArray newArray(IRubyObject car, IRubyObject cdr) {
return RubyArray.newArray(this, car, cdr);
}
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);
}
public RubyArray newArray(int size) {
return RubyArray.newArray(this, size);
}
public RubyArray getEmptyFrozenArray() {
return emptyFrozenArray;
}
public RubyBoolean newBoolean(boolean value) {
return value ? trueObject : falseObject;
}
public RubyFileStat newFileStat(String filename, boolean lstat) {
return RubyFileStat.newFileStat(this, filename, lstat);
}
public RubyFileStat newFileStat(FileDescriptor descriptor) {
return RubyFileStat.newFileStat(this, descriptor);
}
public RubyFixnum newFixnum(long value) {
return RubyFixnum.newFixnum(this, value);
}
public RubyFixnum newFixnum(int value) {
return RubyFixnum.newFixnum(this, value);
}
public RubyFixnum newFixnum(Constant value) {
return RubyFixnum.newFixnum(this, value.intValue());
}
public RubyFloat newFloat(double value) {
return RubyFloat.newFloat(this, value);
}
public RubyNumeric newNumeric() {
return RubyNumeric.newNumeric(this);
}
public RubyRational newRational(long num, long den) {
return RubyRational.newRationalRaw(this, newFixnum(num), newFixnum(den));
}
public RubyRational newRationalReduced(long num, long den) {
return (RubyRational)RubyRational.newRationalConvert(getCurrentContext(), newFixnum(num), newFixnum(den));
}
public RubyProc newProc(Block.Type type, Block block) {
if (type != Block.Type.LAMBDA && block.getProcObject() != null) return block.getProcObject();
return RubyProc.newProc(this, block, type);
}
public RubyProc newBlockPassProc(Block.Type type, Block block) {
if (type != Block.Type.LAMBDA && block.getProcObject() != null) return block.getProcObject();
return RubyProc.newProc(this, block, type);
}
public RubyBinding newBinding() {
return RubyBinding.newBinding(this, getCurrentContext().currentBinding());
}
public RubyBinding newBinding(Binding binding) {
return RubyBinding.newBinding(this, binding);
}
public RubyString newString() {
return RubyString.newString(this, new ByteList());
}
public RubyString newString(String string) {
return RubyString.newString(this, string);
}
public RubyString newString(ByteList byteList) {
return RubyString.newString(this, byteList);
}
@Deprecated
public RubyString newStringShared(ByteList byteList) {
return RubyString.newStringShared(this, byteList);
}
public RubySymbol newSymbol(String name) {
return symbolTable.getSymbol(name);
}
public RubySymbol newSymbol(String name, Encoding encoding) {
ByteList byteList = RubyString.encodeBytelist(name, encoding);
return symbolTable.getSymbol(byteList);
}
public RubySymbol newSymbol(ByteList name) {
return symbolTable.getSymbol(name);
}
public RubySymbol fastNewSymbol(String internedName) {
return symbolTable.fastGetSymbol(internedName);
}
public RubyTime newTime(long milliseconds) {
return RubyTime.newTime(this, milliseconds);
}
public RaiseException newRuntimeError(String message) {
return newRaiseException(getRuntimeError(), message);
}
public RaiseException newArgumentError(String message) {
return newRaiseException(getArgumentError(), message);
}
public RaiseException newArgumentError(int got, int expected) {
return newArgumentError(got, expected, expected);
}
public RaiseException newArgumentError(int got, int min, int max) {
if (min == max) {
return newRaiseException(getArgumentError(), "wrong number of arguments (given " + got + ", expected " + min + ")");
} else if (max == UNLIMITED_ARGUMENTS) {
return newRaiseException(getArgumentError(), "wrong number of arguments (given " + got + ", expected " + min + "+)");
} else {
return newRaiseException(getArgumentError(), "wrong number of arguments (given " + got + ", expected " + min + ".." + max + ")");
}
}
public RaiseException newArgumentError(String name, int got, int expected) {
return newArgumentError(name, got, expected, expected);
}
public RaiseException newArgumentError(String name, int got, int min, int max) {
if (min == max) {
return newRaiseException(getArgumentError(), str(this, "wrong number of arguments calling `", ids(this, name), ("` (given " + got + ", expected " + min + ")")));
} else if (max == UNLIMITED_ARGUMENTS) {
return newRaiseException(getArgumentError(), str(this, "wrong number of arguments calling `", ids(this, name), ("` (given " + got + ", expected " + min + "+)")));
} else {
return newRaiseException(getArgumentError(), str(this, "wrong number of arguments calling `", ids(this, name), ("` (given " + got + ", expected " + min + ".." + max + ")")));
}
}
public RaiseException newErrnoEBADFError() {
return newRaiseException(getErrno().getClass("EBADF"), "Bad file descriptor");
}
public RaiseException newErrnoEISCONNError() {
return newRaiseException(getErrno().getClass("EISCONN"), "Socket is already connected");
}
public RaiseException newErrnoEINPROGRESSError() {
return newRaiseException(getErrno().getClass("EINPROGRESS"), "Operation now in progress");
}
public RaiseException newErrnoEINPROGRESSWritableError() {
return newLightweightErrnoException(getIO().getClass("EINPROGRESSWaitWritable"), "");
}
public RaiseException newErrnoENOPROTOOPTError() {
return newRaiseException(getErrno().getClass("ENOPROTOOPT"), "Protocol not available");
}
public RaiseException newErrnoEPIPEError() {
return newRaiseException(getErrno().getClass("EPIPE"), "Broken pipe");
}
public RaiseException newErrnoECONNABORTEDError() {
return newRaiseException(getErrno().getClass("ECONNABORTED"),
"An established connection was aborted by the software in your host machine");
}
public RaiseException newErrnoECONNREFUSEDError() {
return newRaiseException(getErrno().getClass("ECONNREFUSED"), "Connection refused");
}
public RaiseException newErrnoECONNREFUSEDError(String message) {
return newRaiseException(getErrno().getClass("ECONNREFUSED"), message);
}
public RaiseException newErrnoECONNRESETError() {
return newRaiseException(getErrno().getClass("ECONNRESET"), "Connection reset by peer");
}
public RaiseException newErrnoEADDRINUSEError() {
return newRaiseException(getErrno().getClass("EADDRINUSE"), "Address in use");
}
public RaiseException newErrnoEADDRINUSEError(String message) {
return newRaiseException(getErrno().getClass("EADDRINUSE"), message);
}
public RaiseException newErrnoEHOSTUNREACHError(String message) {
return newRaiseException(getErrno().getClass("EHOSTUNREACH"), message);
}
public RaiseException newErrnoEINVALError() {
return newRaiseException(getErrno().getClass("EINVAL"), "Invalid file");
}
public RaiseException newErrnoELOOPError() {
return newRaiseException(getErrno().getClass("ELOOP"), "Too many levels of symbolic links");
}
public RaiseException newErrnoEMFILEError() {
return newRaiseException(getErrno().getClass("EMFILE"), "Too many open files");
}
public RaiseException newErrnoENFILEError() {
return newRaiseException(getErrno().getClass("ENFILE"), "Too many open files in system");
}
public RaiseException newErrnoENOENTError() {
return newRaiseException(getErrno().getClass("ENOENT"), "File not found");
}
public RaiseException newErrnoEACCESError(String message) {
return newRaiseException(getErrno().getClass("EACCES"), message);
}
public RaiseException newErrnoEAGAINError(String message) {
return newLightweightErrnoException(getErrno().getClass("EAGAIN"), message);
}
public RaiseException newErrnoEAGAINReadableError(String message) {
return newLightweightErrnoException(getIO().getClass("EAGAINWaitReadable"), message);
}
public RaiseException newErrnoEAGAINWritableError(String message) {
return newLightweightErrnoException(getIO().getClass("EAGAINWaitWritable"), message);
}
public RaiseException newErrnoEISDirError(String message) {
return newRaiseException(getErrno().getClass("EISDIR"), message);
}
public RaiseException newErrnoEPERMError(String name) {
return newRaiseException(getErrno().getClass("EPERM"), "Operation not permitted - " + name);
}
public RaiseException newErrnoEISDirError() {
return newErrnoEISDirError("Is a directory");
}
public RaiseException newErrnoESPIPEError() {
return newRaiseException(getErrno().getClass("ESPIPE"), "Illegal seek");
}
public RaiseException newErrnoEBADFError(String message) {
return newRaiseException(getErrno().getClass("EBADF"), message);
}
public RaiseException newErrnoEINPROGRESSError(String message) {
return newRaiseException(getErrno().getClass("EINPROGRESS"), message);
}
public RaiseException newErrnoEINPROGRESSWritableError(String message) {
return newLightweightErrnoException(getIO().getClass("EINPROGRESSWaitWritable"), message);
}
public RaiseException newErrnoEISCONNError(String message) {
return newRaiseException(getErrno().getClass("EISCONN"), message);
}
public RaiseException newErrnoEINVALError(String message) {
return newRaiseException(getErrno().getClass("EINVAL"), message);
}
public RaiseException newErrnoENOTDIRError(String message) {
return newRaiseException(getErrno().getClass("ENOTDIR"), message);
}
public RaiseException newErrnoENOTEMPTYError(String message) {
return newRaiseException(getErrno().getClass("ENOTEMPTY"), message);
}
public RaiseException newErrnoENOTSOCKError(String message) {
return newRaiseException(getErrno().getClass("ENOTSOCK"), message);
}
public RaiseException newErrnoENOTCONNError(String message) {
return newRaiseException(getErrno().getClass("ENOTCONN"), message);
}
public RaiseException newErrnoENOTCONNError() {
return newRaiseException(getErrno().getClass("ENOTCONN"), "Socket is not connected");
}
public RaiseException newErrnoENOENTError(String message) {
return newRaiseException(getErrno().getClass("ENOENT"), message);
}
public RaiseException newErrnoEOPNOTSUPPError(String message) {
return newRaiseException(getErrno().getClass("EOPNOTSUPP"), message);
}
public RaiseException newErrnoESPIPEError(String message) {
return newRaiseException(getErrno().getClass("ESPIPE"), message);
}
public RaiseException newErrnoEEXISTError(String message) {
return newRaiseException(getErrno().getClass("EEXIST"), message);
}
public RaiseException newErrnoEDOMError(String message) {
return newRaiseException(getErrno().getClass("EDOM"), "Domain error - " + message);
}
public RaiseException newErrnoECHILDError() {
return newRaiseException(getErrno().getClass("ECHILD"), "No child processes");
}
public RaiseException newErrnoEADDRNOTAVAILError(String message) {
return newRaiseException(getErrno().getClass("EADDRNOTAVAIL"), message);
}
public RaiseException newErrnoESRCHError() {
return newRaiseException(getErrno().getClass("ESRCH"), null);
}
public RaiseException newErrnoEWOULDBLOCKError() {
return newRaiseException(getErrno().getClass("EWOULDBLOCK"), null);
}
public RaiseException newErrnoEDESTADDRREQError(String func) {
return newRaiseException(getErrno().getClass("EDESTADDRREQ"), func);
}
public RaiseException newErrnoENETUNREACHError() {
return newRaiseException(getErrno().getClass("ENETUNREACH"), null);
}
public RaiseException newErrnoEMSGSIZEError() {
return newRaiseException(getErrno().getClass("EMSGSIZE"), null);
}
public RaiseException newErrnoEXDEVError(String message) {
return newRaiseException(getErrno().getClass("EXDEV"), message);
}
public RaiseException newIndexError(String message) {
return newRaiseException(getIndexError(), message);
}
public RaiseException newSecurityError(String message) {
return newRaiseException(getSecurityError(), message);
}
public RaiseException newSystemCallError(String message) {
return newRaiseException(getSystemCallError(), message);
}
public RaiseException newKeyError(String message, IRubyObject recv, IRubyObject key) {
return new RubyKeyError(this, getKeyError(), message, recv, key).toThrowable();
}
public RaiseException newErrnoEINTRError() {
return newRaiseException(getErrno().getClass("EINTR"), "Interrupted");
}
public RaiseException newErrnoEAFNOSUPPORTError(String message) {
return newRaiseException(getErrno().getClass("EAFNOSUPPORT"), message);
}
public RaiseException newErrnoFromLastPOSIXErrno() {
RubyClass errnoClass = getErrno(getPosix().errno());
if (errnoClass == null) errnoClass = systemCallError;
return newRaiseException(errnoClass, null);
}
public RaiseException newErrnoFromInt(int errno, String methodName, String message) {
if (Platform.IS_WINDOWS && ("stat".equals(methodName) || "lstat".equals(methodName))) {
if (errno == 20047) return newErrnoENOENTError(message);
if (errno == Errno.ESRCH.intValue()) return newErrnoENOENTError(message);
}
return newErrnoFromInt(errno, message);
}
public RaiseException newErrnoFromInt(int errno, String message) {
RubyClass errnoClass = getErrno(errno);
if (errnoClass != null) {
return newRaiseException(errnoClass, message);
} else {
return newSystemCallError("Unknown Error (" + errno + ") - " + message);
}
}
public RaiseException newErrnoFromErrno(Errno errno, String message) {
if (errno == null || errno == Errno.__UNKNOWN_CONSTANT__) {
return newSystemCallError(message);
}
return newErrnoFromInt(errno.intValue(), message);
}
public RaiseException newErrnoFromInt(int errno) {
Errno errnoObj = Errno.valueOf(errno);
if (errnoObj == null) {
return newSystemCallError("Unknown Error (" + errno + ")");
}
String message = errnoObj.description();
return newErrnoFromInt(errno, message);
}
private final static Pattern ADDR_NOT_AVAIL_PATTERN = Pattern.compile("assign.*address");
public RaiseException newErrnoEADDRFromBindException(BindException be) {
return newErrnoEADDRFromBindException(be, null);
}
public RaiseException newErrnoEADDRFromBindException(BindException be, String contextMessage) {
String msg = be.getMessage();
if (msg == null) {
msg = "bind";
} else {
msg = "bind - " + msg;
}
if (contextMessage != null) {
msg = msg + contextMessage;
}
if(ADDR_NOT_AVAIL_PATTERN.matcher(msg).find()) {
return newErrnoEADDRNOTAVAILError(msg);
} else {
return newErrnoEADDRINUSEError(msg);
}
}
public RaiseException newTypeError(String message) {
return newRaiseException(getTypeError(), message);
}
public RaiseException newThreadError(String message) {
return newRaiseException(getThreadError(), message);
}
public RaiseException newConcurrencyError(String message) {
return newRaiseException(getConcurrencyError(), message);
}
public RaiseException newSyntaxError(String message) {
return newRaiseException(getSyntaxError(), message);
}
public RaiseException newRegexpError(String message) {
return newRaiseException(getRegexpError(), message);
}
public RaiseException newInterruptedRegexpError(String message) {
return newRaiseException(getInterruptedRegexpError(), message);
}
public RaiseException newRangeError(String message) {
return newRaiseException(getRangeError(), message);
}
public RaiseException newNotImplementedError(String message) {
return newRaiseException(getNotImplementedError(), message);
}
@Deprecated
public RaiseException newInvalidEncoding(String message) {
return newRaiseException(getClass("Iconv").getClass("InvalidEncoding"), message);
}
@Deprecated
public RaiseException newIllegalSequence(String message) {
return newRaiseException(getClass("Iconv").getClass("IllegalSequence"), message);
}
public RaiseException newNameError(String message, IRubyObject recv, IRubyObject name) {
return newNameError(message, recv, name, false);
}
public RaiseException newNameError(String message, IRubyObject recv, IRubyObject name, boolean privateCall) {
IRubyObject msg = new RubyNameError.RubyNameErrorMessage(this, message, recv, name);
RubyException err = RubyNameError.newNameError(getNameError(), msg, name, privateCall);
return err.toThrowable();
}
public RaiseException newNameError(String message, IRubyObject recv, String name) {
return newNameError(message, recv, name, false);
}
public RaiseException newNameError(String message, IRubyObject recv, String name, boolean privateCall) {
RubySymbol nameSym = newSymbol(name);
return newNameError(message, recv, nameSym, privateCall);
}
public RaiseException newNameError(String message, String name, Throwable exception, boolean printWhenVerbose) {
if (exception != null) {
if (printWhenVerbose && isVerbose()) {
LOG.error(exception);
} else if (isDebug()) {
LOG.debug(exception);
}
}
return new RubyNameError(this, getNameError(), message, name).toThrowable();
}
public RaiseException newNameError(String message, String name) {
return newNameError(message, name, null);
}
public RaiseException newNameError(String message, String name, Throwable origException) {
return newNameError(message, name, origException, false);
}
public RaiseException newNoMethodError(String message, IRubyObject recv, String name, RubyArray args) {
return newNoMethodError(message, recv, name, args, false);
}
public RaiseException newNoMethodError(String message, IRubyObject recv, String name, RubyArray args, boolean privateCall) {
RubySymbol nameStr = newSymbol(name);
IRubyObject msg = new RubyNameError.RubyNameErrorMessage(this, message, recv, nameStr);
RubyException err = RubyNoMethodError.newNoMethodError(getNoMethodError(), msg, nameStr, args, privateCall);
return err.toThrowable();
}
public RaiseException newNoMethodError(String message, String name, IRubyObject args) {
return new RubyNoMethodError(this, getNoMethodError(), message, name, args).toThrowable();
}
public RaiseException newLocalJumpError(RubyLocalJumpError.Reason reason, IRubyObject exitValue, String message) {
return new RubyLocalJumpError(this, getLocalJumpError(), message, reason, exitValue).toThrowable();
}
public RaiseException newLocalJumpErrorNoBlock() {
return newLocalJumpError(RubyLocalJumpError.Reason.NOREASON, getNil(), "no block given");
}
public RaiseException newRedoLocalJumpError() {
return newLocalJumpError(RubyLocalJumpError.Reason.REDO, getNil(), "unexpected redo");
}
public RaiseException newLoadError(String message) {
return newRaiseException(getLoadError(), message);
}
public RaiseException newLoadError(String message, String path) {
RaiseException loadError = newRaiseException(getLoadError(), message);
loadError.getException().setInstanceVariable("@path", newString(path));
return loadError;
}
public RaiseException newFrozenError(String objectType) {
return newFrozenError(objectType, false);
}
public RaiseException newFrozenError(RubyModule type) {
return newRaiseException(getFrozenError(), str(this, "can't modify frozen ", types(this, type)));
}
public RaiseException newFrozenError(String objectType, boolean runtimeError) {
return newRaiseException(getFrozenError(), str(this, "can't modify frozen ", ids(this, objectType)));
}
public RaiseException newSystemStackError(String message) {
return newRaiseException(getSystemStackError(), message);
}
public RaiseException newSystemStackError(String message, StackOverflowError error) {
if ( isDebug() ) LOG.debug(error);
return newRaiseException(getSystemStackError(), message);
}
public RaiseException newSystemExit(int status) {
return RubySystemExit.newInstance(this, status, "exit").toThrowable();
}
public RaiseException newSystemExit(int status, String message) {
return RubySystemExit.newInstance(this, status, message).toThrowable();
}
public RaiseException newIOError(String message) {
return newRaiseException(getIOError(), message);
}
public RaiseException newStandardError(String message) {
return newRaiseException(getStandardError(), message);
}
public RaiseException newIOErrorFromException(final IOException ex) {
return Helpers.newIOErrorFromException(this, ex);
}
public RaiseException newTypeError(IRubyObject receivedObject, RubyClass expectedType) {
return newTypeError(receivedObject, expectedType.getName());
}
public RaiseException newTypeError(IRubyObject receivedObject, RubyModule expectedType) {
return newTypeError(receivedObject, expectedType.getName());
}
public RaiseException newTypeError(IRubyObject receivedObject, String expectedType) {
return newRaiseException(getTypeError(),
str(this, "wrong argument type ",
receivedObject.getMetaClass().getRealClass().toRubyString(getCurrentContext()),
" (expected ", ids(this, expectedType), ")"));
}
public RaiseException newEOFError() {
return newRaiseException(getEOFError(), "End of file reached");
}
public RaiseException newEOFError(String message) {
return newRaiseException(getEOFError(), message);
}
public RaiseException newZeroDivisionError() {
return newRaiseException(getZeroDivisionError(), "divided by 0");
}
public RaiseException newFloatDomainError(String message){
return newRaiseException(getFloatDomainError(), message);
}
public RaiseException newMathDomainError(String message) {
return newRaiseException(getMathDomainError(), "Numerical argument is out of domain - \"" + message + "\"");
}
public RaiseException newEncodingError(String message){
return newRaiseException(getEncodingError(), message);
}
public RaiseException newEncodingCompatibilityError(String message){
return newRaiseException(getEncodingCompatibilityError(), message);
}
public RaiseException newConverterNotFoundError(String message) {
return newRaiseException(getConverterNotFoundError(), message);
}
public RaiseException newFiberError(String message) {
return newRaiseException(getFiberError(), message);
}
public RaiseException newUndefinedConversionError(String message) {
return newRaiseException(getUndefinedConversionError(), message);
}
public RaiseException newInvalidByteSequenceError(String message) {
return newRaiseException(getInvalidByteSequenceError(), message);
}
public RaiseException newRaiseException(RubyClass exceptionClass, String message) {
return RaiseException.from(this, exceptionClass, message);
}
private RaiseException newLightweightErrnoException(RubyClass exceptionClass, String message) {
if (RubyInstanceConfig.ERRNO_BACKTRACE) {
return RaiseException.from(this, exceptionClass, message);
} else {
return RaiseException.from(this, exceptionClass, ERRNO_BACKTRACE_MESSAGE, disabledBacktrace());
}
}
public RaiseException newStopIteration(IRubyObject result, String message) {
final ThreadContext context = getCurrentContext();
if (message == null) message = STOPIERATION_BACKTRACE_MESSAGE;
RubyException ex = RubyStopIteration.newInstance(context, result, message);
if (!RubyInstanceConfig.STOPITERATION_BACKTRACE) {
ex.setBacktrace(disabledBacktrace());
}
return ex.toThrowable();
}
@Deprecated
public RaiseException newLightweightStopIterationError(String message) {
return newStopIteration(null, message);
}
private IRubyObject disabledBacktrace() {
return RubyArray.newEmptyArray(this);
}
public RubyObject.Data newData(RubyClass objectClass, Object sval) {
return new RubyObject.Data(this, objectClass, sval);
}
public RubySymbol.SymbolTable getSymbolTable() {
return symbolTable;
}
public ObjectSpace getObjectSpace() {
return objectSpace;
}
public InputStream getIn() {
return in;
}
public PrintStream getOut() {
return out;
}
public PrintStream getErr() {
return err;
}
public boolean isGlobalAbortOnExceptionEnabled() {
return globalAbortOnExceptionEnabled;
}
public void setGlobalAbortOnExceptionEnabled(boolean enable) {
globalAbortOnExceptionEnabled = enable;
}
public IRubyObject getReportOnException() {
return reportOnException;
}
public void setReportOnException(IRubyObject enable) {
reportOnException = enable;
}
public boolean isDoNotReverseLookupEnabled() {
return doNotReverseLookupEnabled;
}
public void setDoNotReverseLookupEnabled(boolean b) {
doNotReverseLookupEnabled = b;
}
private final ThreadLocal<Map<Object, Object>> inspect = new ThreadLocal<>();
public void registerInspecting(Object obj) {
Map<Object, Object> val = inspect.get();
if (val == null) inspect.set(val = new IdentityHashMap<>(8));
val.put(obj, null);
}
public boolean isInspecting(Object obj) {
Map<Object, Object> val = inspect.get();
return val == null ? false : val.containsKey(obj);
}
public void unregisterInspecting(Object obj) {
Map<Object, Object> val = inspect.get();
if (val != null ) val.remove(obj);
}
public boolean isObjectSpaceEnabled() {
return objectSpaceEnabled;
}
public void setObjectSpaceEnabled(boolean objectSpaceEnabled) {
this.objectSpaceEnabled = objectSpaceEnabled;
}
public boolean isSiphashEnabled() {
return siphashEnabled;
}
public long getStartTime() {
return startTime;
}
public Profile getProfile() {
return profile;
}
public String getJRubyHome() {
return config.getJRubyHome();
}
public void setJRubyHome(String home) {
config.setJRubyHome(home);
}
public RubyInstanceConfig getInstanceConfig() {
return config;
}
@Deprecated
public boolean is2_0() {
return true;
}
@Deprecated
public long getGlobalState() {
synchronized(this) {
return globalState;
}
}
@Deprecated
public void incGlobalState() {
synchronized(this) {
globalState = (globalState+1) & 0x8fffffff;
}
}
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 ExecutorService getExecutor() {
return executor;
}
public ExecutorService getFiberExecutor() {
return fiberExecutor;
}
public Map<String, DateTimeZone> getTimezoneCache() {
return timeZoneCache;
}
@Deprecated
public int getConstantGeneration() {
return -1;
}
public Invalidator getConstantInvalidator(String constantName) {
Invalidator invalidator = constantNameInvalidators.get(constantName);
if (invalidator != null) {
return invalidator;
} else {
return addConstantInvalidator(constantName);
}
}
private Invalidator addConstantInvalidator(String constantName) {
final Invalidator invalidator = OptoFactory.newConstantInvalidator(this);
constantNameInvalidators.putIfAbsent(constantName, invalidator);
return constantNameInvalidators.get(constantName);
}
public Invalidator getCheckpointInvalidator() {
return checkpointInvalidator;
}
public <E extends Enum<E>> void loadConstantSet(RubyModule module, Class<E> enumClass) {
for (E e : EnumSet.allOf(enumClass)) {
Constant c = (Constant) e;
if (Character.isUpperCase(c.name().charAt(0))) {
module.setConstant(c.name(), newFixnum(c.intValue()));
}
}
}
public void loadConstantSet(RubyModule module, String constantSetName) {
for (Constant c : ConstantSet.getConstantSet(constantSetName)) {
if (Character.isUpperCase(c.name().charAt(0))) {
module.setConstant(c.name(), newFixnum(c.intValue()));
}
}
}
public long getNextDynamicMethodSerial() {
return dynamicMethodSerial.getAndIncrement();
}
public int getNextModuleGeneration() {
return moduleGeneration.incrementAndGet();
}
public Object getHierarchyLock() {
return hierarchyLock;
}
public SelectorPool getSelectorPool() {
return selectorPool;
}
public RuntimeCache getRuntimeCache() {
return runtimeCache;
}
public List<StrptimeToken> getCachedStrptimePattern(String pattern) {
List<StrptimeToken> tokens = strptimeFormatCache.get(pattern);
if (tokens == null) {
tokens = new StrptimeParser().compilePattern(pattern);
strptimeFormatCache.put(pattern, tokens);
}
return tokens;
}
void addProfiledMethod(final String id, final DynamicMethod method) {
if (!config.isProfiling() || method.isUndefined()) return;
getProfilingService().addProfiledMethod(id, method);
}
public void incrementExceptionCount() {
exceptionCount.incrementAndGet();
}
public int getExceptionCount() {
return exceptionCount.get();
}
public void incrementBacktraceCount() {
backtraceCount.incrementAndGet();
}
public int getBacktraceCount() {
return backtraceCount.get();
}
public void incrementWarningCount() {
warningCount.incrementAndGet();
}
public int getWarningCount() {
return warningCount.get();
}
public void incrementCallerCount() {
callerCount.incrementAndGet();
}
public int getCallerCount() {
return callerCount.get();
}
@Deprecated
public void reopenFixnum() {
fixnumInvalidator.invalidate();
fixnumReopened = true;
}
@Deprecated
public Invalidator getFixnumInvalidator() {
return fixnumInvalidator;
}
@Deprecated
public boolean isFixnumReopened() {
return fixnumReopened;
}
@Deprecated
public void reopenFloat() {
floatInvalidator.invalidate();
floatReopened = true;
}
@Deprecated
public Invalidator getFloatInvalidator() {
return floatInvalidator;
}
@Deprecated
public boolean isFloatReopened() {
return floatReopened;
}
public boolean isBootingCore() {
return bootingCore;
}
public boolean isBooting() {
return bootingRuntime;
}
public CoverageData getCoverageData() {
return coverageData;
}
public Random getRandom() {
return random;
}
public long getHashSeedK0() {
return hashSeedK0;
}
public long getHashSeedK1() {
return hashSeedK1;
}
public StaticScopeFactory getStaticScopeFactory() {
return staticScopeFactory;
}
public FFI getFFI() {
return ffi;
}
public void setFFI(FFI ffi) {
this.ffi = ffi;
}
public RubyString getDefinedMessage(DefinedMessage definedMessage) {
return definedMessages.get(definedMessage);
}
public RubyString getThreadStatus(RubyThread.Status status) {
return threadStatuses.get(status);
}
public RubyString freezeAndDedupString(RubyString string) {
if (string.getMetaClass() != stringClass) {
RubyString duped = string.strDup(this);
duped.setFrozen(true);
return duped;
}
FStringEqual wrapper = DEDUP_WRAPPER_CACHE.get();
if (wrapper == null) {
wrapper = new FStringEqual(string);
DEDUP_WRAPPER_CACHE.set(wrapper);
} else {
wrapper.string = string;
}
WeakReference<RubyString> dedupedRef = dedupMap.get(wrapper);
RubyString deduped;
if (dedupedRef == null || (deduped = dedupedRef.get()) == null) {
DEDUP_WRAPPER_CACHE.remove();
deduped = string.strDup(this);
deduped.setFrozen(true);
final WeakReference<RubyString> weakref = new WeakReference<>(deduped);
wrapper.string = deduped;
dedupedRef = dedupMap.computeIfAbsent(wrapper, key -> weakref);
if (dedupedRef == null) return deduped;
RubyString unduped = dedupedRef.get();
if (unduped != null) return unduped;
while (true) {
wrapper.string = string;
dedupedRef = dedupMap.computeIfPresent(wrapper, (key, old) -> old.get() == null ? weakref : old);
unduped = dedupedRef.get();
if (unduped != null) return unduped;
}
} else {
wrapper.string = null;
}
return deduped;
}
static class FStringEqual {
RubyString string;
FStringEqual(RubyString string) {
this.string = string;
}
public boolean equals(Object other) {
if (other instanceof FStringEqual) {
RubyString otherString = ((FStringEqual) other).string;
return this.string.equals(otherString) && this.string.getEncoding() == otherString.getEncoding();
}
return false;
}
public int hashCode() {
return string.hashCode();
}
}
private final ThreadLocal<FStringEqual> DEDUP_WRAPPER_CACHE = new ThreadLocal<>();
public int () {
return runtimeNumber;
}
@Override
public Object constant() {
return constant;
}
public void setBaseNewMethod(DynamicMethod baseNewMethod) {
this.baseNewMethod = baseNewMethod;
}
public DynamicMethod getBaseNewMethod() {
return baseNewMethod;
}
public MethodHandle getNullToNilHandle() {
MethodHandle nullToNil = this.nullToNil;
if (nullToNil != null) return nullToNil;
nullToNil = InvokeDynamicSupport.findStatic(Helpers.class, "nullToNil", methodType(IRubyObject.class, IRubyObject.class, IRubyObject.class));
nullToNil = insertArguments(nullToNil, 1, nilObject);
nullToNil = explicitCastArguments(nullToNil, methodType(IRubyObject.class, Object.class));
return this.nullToNil = nullToNil;
}
private void addLoadParseToStats() {
if (parserStats != null) parserStats.addLoadParse();
}
private void addEvalParseToStats() {
if (parserStats != null) parserStats.addEvalParse();
}
public FilenoUtil getFilenoUtil() {
return filenoUtil;
}
public RubyClass getData() {
return dataClass;
}
public Map<Class, Consumer<RubyModule>> getJavaExtensionDefinitions() { return javaExtensionDefinitions; }
@Deprecated
private static final RecursiveFunctionEx<RecursiveFunction> LEGACY_RECURSE = new RecursiveFunctionEx<RecursiveFunction>() {
@Override
public IRubyObject call(ThreadContext context, RecursiveFunction func, IRubyObject obj, boolean recur) {
return func.call(obj, recur);
}
};
@Deprecated
public int getSafeLevel() {
return 0;
}
@Deprecated
public void setSafeLevel(int safeLevel) {
}
@Deprecated
public void checkSafeString(IRubyObject object) {
}
@Deprecated
public void secure(int level) {
}
@Deprecated
public RaiseException newNameErrorObject(String message, IRubyObject name) {
RubyException error = new RubyNameError(this, getNameError(), message, name);
return error.toThrowable();
}
@Deprecated
public boolean is1_8() {
return false;
}
@Deprecated
public boolean is1_9() {
return true;
}
@Deprecated
public IRubyObject safeRecurse(RecursiveFunction func, IRubyObject obj, String name, boolean outer) {
return safeRecurse(LEGACY_RECURSE, getCurrentContext(), func, obj, name, outer);
}
@Deprecated
public ProfiledMethods getProfiledMethods() {
return new ProfiledMethods(this);
}
public interface RecursiveFunctionEx<T> extends ThreadContext.RecursiveFunctionEx<T> {
IRubyObject call(ThreadContext context, T state, IRubyObject obj, boolean recur);
}
@Deprecated
public interface RecursiveFunction extends MRIRecursionGuard.RecursiveFunction {}
@Deprecated
public <T> IRubyObject safeRecurse(RecursiveFunctionEx<T> func, ThreadContext context, T state, IRubyObject obj, String name, boolean outer) {
return context.safeRecurse(func, state, obj, name, outer);
}
@Deprecated
public IRubyObject execRecursive(RecursiveFunction func, IRubyObject obj) {
return oldRecursionGuard().execRecursive(func, obj);
}
@Deprecated
public IRubyObject execRecursiveOuter(RecursiveFunction func, IRubyObject obj) {
return oldRecursionGuard().execRecursiveOuter(func, obj);
}
@Deprecated
public <T extends IRubyObject> T recursiveListOperation(Callable<T> body) {
return oldRecursionGuard().recursiveListOperation(body);
}
@Deprecated
private MRIRecursionGuard oldRecursionGuard() {
MRIRecursionGuard mriRecursionGuard = this.mriRecursionGuard;
if (mriRecursionGuard != null) return mriRecursionGuard;
synchronized (this) {
mriRecursionGuard = this.mriRecursionGuard;
if (mriRecursionGuard != null) return mriRecursionGuard;
return mriRecursionGuard = new MRIRecursionGuard(this);
}
}
private final ConcurrentHashMap<String, Invalidator> constantNameInvalidators =
new ConcurrentHashMap<String, Invalidator>(
16 ,
0.75f ,
1 );
private final Invalidator checkpointInvalidator;
private final ThreadService threadService;
private final POSIX posix;
private final ObjectSpace objectSpace = new ObjectSpace();
private final RubySymbol.SymbolTable symbolTable = new RubySymbol.SymbolTable(this);
private static final EventHook[] EMPTY_HOOKS = new EventHook[0];
private volatile EventHook[] eventHooks = EMPTY_HOOKS;
private boolean hasEventHooks;
private boolean globalAbortOnExceptionEnabled = false;
private IRubyObject reportOnException;
private boolean doNotReverseLookupEnabled = false;
private volatile boolean objectSpaceEnabled;
private boolean siphashEnabled;
private long globalState = 1;
private IRubyObject topSelf;
private IRubyObject rootFiber;
private RubyNil nilObject;
private IRubyObject[] singleNilArray;
private RubyBoolean trueObject;
private RubyBoolean falseObject;
final RubyFixnum[] fixnumCache = new RubyFixnum[2 * RubyFixnum.CACHE_OFFSET];
final Object[] fixnumConstants = new Object[fixnumCache.length];
private boolean verbose, warningsEnabled, debug;
private IRubyObject verboseValue;
private RubyThreadGroup defaultThreadGroup;
private RubyClass
basicObjectClass, objectClass, moduleClass, classClass, nilClass, trueClass,
falseClass, numericClass, floatClass, integerClass, fixnumClass,
complexClass, rationalClass, enumeratorClass, yielderClass, fiberClass, generatorClass,
arrayClass, hashClass, rangeClass, stringClass, encodingClass, converterClass, symbolClass,
procClass, bindingClass, methodClass, unboundMethodClass,
matchDataClass, regexpClass, timeClass, bignumClass, dirClass,
fileClass, fileStatClass, ioClass, threadClass, threadGroupClass,
continuationClass, structClass, tmsStruct, passwdStruct,
groupStruct, procStatusClass, exceptionClass, runtimeError, frozenError, ioError,
scriptError, nameError, nameErrorMessage, noMethodError, signalException,
rangeError, dummyClass, systemExit, localJumpError, nativeException,
systemCallError, fatal, interrupt, typeError, argumentError, uncaughtThrowError, indexError, stopIteration,
syntaxError, standardError, loadError, notImplementedError, securityError, noMemoryError,
regexpError, eofError, threadError, concurrencyError, systemStackError, zeroDivisionError, floatDomainError, mathDomainError,
encodingError, encodingCompatibilityError, converterNotFoundError, undefinedConversionError,
invalidByteSequenceError, fiberError, randomClass, keyError, locationClass, interruptedRegexpError, dataClass;
private RubyModule
kernelModule, comparableModule, enumerableModule, mathModule,
marshalModule, etcModule, fileTestModule, gcModule,
objectSpaceModule, processModule, procUIDModule, procGIDModule,
procSysModule, precisionModule, errnoModule, warningModule;
private DynamicMethod privateMethodMissing, protectedMethodMissing, variableMethodMissing,
superMethodMissing, normalMethodMissing, defaultMethodMissing, defaultModuleMethodMissing,
respondTo, respondToMissing;
private GlobalVariable recordSeparatorVar;
private volatile String currentDirectory;
private volatile int currentLine = 0;
private volatile IRubyObject argsFile;
private final long startTime = System.currentTimeMillis();
final RubyInstanceConfig config;
private InputStream in;
private PrintStream out;
private PrintStream err;
private JavaSupport javaSupport;
private final JRubyClassLoader jrubyClassLoader;
private BeanManager beanManager;
private ParserStats parserStats;
private final JITCompiler jitCompiler;
private final Caches caches;
private volatile static boolean securityRestricted = false;
static {
if (SafePropertyAccessor.isSecurityProtected("jruby.reflected.handles")) {
securityRestricted = true;
} else {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
sm.checkCreateClassLoader();
} catch (SecurityException se) {
securityRestricted = true;
}
}
}
}
private final Parser parser = new Parser(this);
private LoadService loadService;
private Encoding defaultInternalEncoding, defaultExternalEncoding, defaultFilesystemEncoding;
private EncodingService encodingService;
private GlobalVariables globalVariables = new GlobalVariables(this);
private final RubyWarnings warnings = new RubyWarnings(this);
private final WarnCallback regexpWarnings = new WarnCallback() {
@Override
public void warn(String message) {
getWarnings().warning(message);
}
};
private final Stack<RubyProc> atExitBlocks = new Stack<>();
private Profile profile;
private KCode kcode = KCode.NONE;
private final AtomicInteger symbolLastId = new AtomicInteger(128);
private final AtomicInteger moduleLastId = new AtomicInteger(0);
private final ConcurrentWeakHashMap<RubyModule, Object> allModules = new ConcurrentWeakHashMap<>(128);
private final Map<String, DateTimeZone> timeZoneCache = new HashMap<>();
private Map<Finalizable, Object> finalizers;
private Map<Finalizable, Object> internalFinalizers;
private final Object finalizersMutex = new Object();
private final Object internalFinalizersMutex = new Object();
private ExecutorService executor;
private ExecutorService fiberExecutor;
private final Object hierarchyLock = new Object();
private final AtomicLong dynamicMethodSerial = new AtomicLong(1);
private final AtomicInteger moduleGeneration = new AtomicInteger(1);
private final Map<String, Map<String, String>> boundMethods = new HashMap();
private final SelectorPool selectorPool = new SelectorPool();
private final RuntimeCache runtimeCache;
public static final String ERRNO_BACKTRACE_MESSAGE = "errno backtraces disabled; run with -Xerrno.backtrace=true to enable";
public static final String STOPIERATION_BACKTRACE_MESSAGE = "StopIteration backtraces disabled; run with -Xstop_iteration.backtrace=true to enable";
private final AtomicInteger exceptionCount = new AtomicInteger();
private final AtomicInteger backtraceCount = new AtomicInteger();
private final AtomicInteger callerCount = new AtomicInteger();
private final AtomicInteger warningCount = new AtomicInteger();
private Invalidator
fixnumInvalidator = OptoFactory.newGlobalInvalidator(0),
floatInvalidator = OptoFactory.newGlobalInvalidator(0);
private boolean fixnumReopened, floatReopened;
private volatile boolean bootingCore = true;
private volatile boolean bootingRuntime = true;
private RubyHash envObject;
private final CoverageData coverageData = new CoverageData();
private static volatile Ruby globalRuntime;
private static ThreadLocal<Ruby> threadLocalRuntime = new ThreadLocal<Ruby>();
final Random random;
private final long hashSeedK0;
private final long hashSeedK1;
private StaticScopeFactory staticScopeFactory;
private IRManager irManager;
private FFI ffi;
private JavaProxyClassFactory javaProxyClassFactory;
private final ProfilingServiceLookup profilingServiceLookup;
private final EnumMap<DefinedMessage, RubyString> definedMessages = new EnumMap<>(DefinedMessage.class);
private final EnumMap<RubyThread.Status, RubyString> threadStatuses = new EnumMap<>(RubyThread.Status.class);
public interface ObjectSpacer {
void addToObjectSpace(Ruby runtime, boolean useObjectSpace, IRubyObject object);
}
private static final ObjectSpacer DISABLED_OBJECTSPACE = new ObjectSpacer() {
@Override
public void addToObjectSpace(Ruby runtime, boolean useObjectSpace, IRubyObject object) {
}
};
private static final ObjectSpacer ENABLED_OBJECTSPACE = new ObjectSpacer() {
@Override
public void addToObjectSpace(Ruby runtime, boolean useObjectSpace, IRubyObject object) {
if (useObjectSpace) runtime.objectSpace.add(object);
}
};
private final ObjectSpacer objectSpacer;
public void addToObjectSpace(boolean useObjectSpace, IRubyObject object) {
objectSpacer.addToObjectSpace(this, useObjectSpace, object);
}
private RubyArray emptyFrozenArray;
private ConcurrentHashMap<FStringEqual, WeakReference<RubyString>> dedupMap = new ConcurrentHashMap<>();
private static final AtomicInteger RUNTIME_NUMBER = new AtomicInteger(0);
private final int = RUNTIME_NUMBER.getAndIncrement();
private final Config configBean;
private final org.jruby.management.Runtime runtimeBean;
private final FilenoUtil filenoUtil;
private final Interpreter interpreter = new Interpreter();
private final Object constant;
private DynamicMethod baseNewMethod;
private MethodHandle nullToNil;
public final ClassValue<TypePopulator> POPULATORS = new ClassValue<TypePopulator>() {
@Override
protected TypePopulator computeValue(Class<?> type) {
return RubyModule.loadPopulatorFor(type);
}
};
public final JavaSites sites = new JavaSites();
private volatile MRIRecursionGuard mriRecursionGuard;
private final Map<Class, Consumer<RubyModule>> javaExtensionDefinitions = new WeakHashMap<>();
private final Map<String, List<StrptimeToken>> strptimeFormatCache = new ConcurrentHashMap<>();
transient RubyString tzVar;
@Deprecated
private void setNetworkStack() {
deprecatedNetworkStackProperty();
}
@SuppressWarnings("deprecation")
private void deprecatedNetworkStackProperty() {
if (Options.PREFER_IPV4.load()) {
LOG.warn("Warning: not setting network stack system property because socket subsystem may already be booted."
+ "If you need this option please set it manually as a JVM property.\n"
+ "Use JAVA_OPTS=-Djava.net.preferIPv4Stack=true OR prepend -J as a JRuby option.");
}
}
}