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.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.management.InlineStats;
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.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.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);
profilingServiceLookup = config.isProfiling() ? new ProfilingServiceLookup(this) : null;
constant = OptoFactory.newConstantWrapper(Ruby.class, this);
this.jrubyClassLoader = initJRubyClassLoader(config);
this.staticScopeFactory = new StaticScopeFactory(this);
this.beanManager = BeanManagerFactory.create(this, config.isManagementEnabled());
this.jitCompiler = new JITCompiler(this);
this.parserStats = new ParserStats(this);
this.inlineStats = new InlineStats();
this.caches = new Caches();
this.random = initRandom();
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);
this.objectSpacer = initObjectSpacer(config);
posix = POSIXFactory.getPOSIX(new JRubyPOSIXHandler(this), config.isNativeEnabled());
filenoUtil = new FilenoUtil(posix);
reinitialize(false);
loadService = this.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"));
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);
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 = kernelModule = RubyKernel.createKernelModule(this);
objectClass.includeModule(kernelModule);
initKernelGsub(kernel);
topSelf = TopSelfFactory.createTopSelf(this, false);
nilClass = RubyNil.createNilClass(this);
falseClass = RubyBoolean.createFalseClass(this);
trueClass = RubyBoolean.createTrueClass(this);
nilObject = new RubyNil(this);
nilPrefilledArray = new IRubyObject[NIL_PREFILLED_ARRAY_SIZE];
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;
threadService.initMainThread();
final ThreadContext context = getCurrentContext();
context.prepareTopLevel(objectClass, topSelf);
dataClass = initDataClass();
comparableModule = RubyComparable.createComparable(this);
enumerableModule = RubyEnumerable.createEnumerableModule(this);
stringClass = RubyString.createStringClass(this);
encodingService = new EncodingService(this);
symbolClass = RubySymbol.createSymbolClass(this);
threadGroupClass = profile.allowClass("ThreadGroup") ? RubyThreadGroup.createThreadGroupClass(this) : null;
threadClass = profile.allowClass("Thread") ? RubyThread.createThreadClass(this) : null;
exceptionClass = profile.allowClass("Exception") ? RubyException.createExceptionClass(this) : null;
numericClass = profile.allowClass("Numeric") ? RubyNumeric.createNumericClass(this) : null;
integerClass = profile.allowClass("Integer") ? RubyInteger.createIntegerClass(this) : null;
fixnumClass = profile.allowClass("Fixnum") ? RubyFixnum.createFixnumClass(this) : null;
encodingClass = RubyEncoding.createEncodingClass(this);
converterClass = RubyConverter.createConverterClass(this);
encodingService.defineEncodings();
encodingService.defineAliases();
initDefaultEncodings();
complexClass = profile.allowClass("Complex") ? RubyComplex.createComplexClass(this) : null;
rationalClass = profile.allowClass("Rational") ? RubyRational.createRationalClass(this) : null;
hashClass = profile.allowClass("Hash") ? RubyHash.createHashClass(this) : null;
if (profile.allowClass("Array")) {
arrayClass = RubyArray.createArrayClass(this);
emptyFrozenArray = newEmptyArray();
emptyFrozenArray.setFrozen(true);
} else {
arrayClass = null;
emptyFrozenArray = null;
}
floatClass = profile.allowClass("Float") ? RubyFloat.createFloatClass(this) : null;
if (profile.allowClass("Bignum")) {
bignumClass = RubyBignum.createBignumClass(this);
randomClass = RubyRandom.createRandomClass(this);
} else {
bignumClass = null;
randomClass = null;
defaultRand = null;
}
ioClass = RubyIO.createIOClass(this);
structClass = profile.allowClass("Struct") ? RubyStruct.createStructClass(this) : null;
bindingClass = profile.allowClass("Binding") ? RubyBinding.createBindingClass(this) : null;
mathModule = profile.allowModule("Math") ? RubyMath.createMathModule(this) : null;
regexpClass = profile.allowClass("Regexp") ? RubyRegexp.createRegexpClass(this) : null;
rangeClass = profile.allowClass("Range") ? RubyRange.createRangeClass(this) : null;
objectSpaceModule = profile.allowModule("ObjectSpace") ? RubyObjectSpace.createObjectSpaceModule(this) : null;
gcModule = profile.allowModule("GC") ? RubyGC.createGCModule(this) : null;
procClass = profile.allowClass("Proc") ? RubyProc.createProcClass(this) : null;
methodClass = profile.allowClass("Method") ? RubyMethod.createMethodClass(this) : null;
matchDataClass = profile.allowClass("MatchData") ? RubyMatchData.createMatchDataClass(this) : null;
marshalModule = profile.allowModule("Marshal") ? RubyMarshal.createMarshalModule(this) : null;
dirClass = profile.allowClass("Dir") ? RubyDir.createDirClass(this) : null;
fileTestModule = profile.allowModule("FileTest") ? RubyFileTest.createFileTestModule(this) : null;
fileClass = profile.allowClass("File") ? RubyFile.createFileClass(this) : null;
fileStatClass = profile.allowClass("File::Stat") ? RubyFileStat.createFileStatClass(this) : null;
processModule = profile.allowModule("Process") ? RubyProcess.createProcessModule(this) : null;
timeClass = profile.allowClass("Time") ? RubyTime.createTimeClass(this) : null;
unboundMethodClass = profile.allowClass("UnboundMethod") ? RubyUnboundMethod.defineUnboundMethodClass(this) : null;
if (profile.allowModule("Signal")) RubySignal.createSignal(this);
if (profile.allowClass("Enumerator")) {
enumeratorClass = RubyEnumerator.defineEnumerator(this, enumerableModule);
generatorClass = RubyGenerator.createGeneratorClass(this, enumeratorClass);
yielderClass = RubyYielder.createYielderClass(this);
} else {
enumeratorClass = null;
generatorClass = null;
yielderClass = null;
}
continuationClass = initContinuation();
TracePoint.createTracePointClass(this);
warningModule = RubyWarnings.createWarningModule(this);
initExceptions();
Mutex.setup(this);
ConditionVariable.setup(this);
org.jruby.ext.thread.Queue.setup(this);
SizedQueue.setup(this);
fiberClass = new ThreadFiberLibrary().createFiberClass(this);
ThreadFiber.initRootFiber(context, context.getThread());
initDefinedMessages();
initThreadStatuses();
irManager = new IRManager(this, getInstanceConfig());
IRScope top = new IRScriptBody(irManager, "", context.getCurrentScope().getStaticScope());
top.allocateInterpreterContext(Collections.EMPTY_LIST, 0, IRScope.allocateInitialFlags(top));
dummyClass = new RubyClass(this, classClass);
dummyClass.setFrozen(true);
RubyGlobal.createGlobals(this);
getLoadService().init(this.config.getLoadPaths());
coreIsBooted = true;
if (!RubyInstanceConfig.DEBUG_PARSER) {
initBootLibraries();
}
SecurityHelper.checkCryptoRestrictions(this);
if(this.config.isProfiling()) {
initProfiling();
}
if (this.config.getLoadGemfile()) {
loadBundler();
}
deprecatedNetworkStackProperty();
runtimeIsBooted = true;
}
private void initProfiling() {
getLoadService().require("jruby/profiler/shutdown_hook");
kernelModule.invalidateCacheDescendants();
RubyKernel.recacheBuiltinMethods(this, kernelModule);
RubyBasicObject.recacheBuiltinMethods(this);
}
private void initBootLibraries() {
initJavaSupport();
initRubyKernel();
if (!this.config.isDisableGems()) {
defineModule("Gem");
}
if (!this.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();
}
private void initKernelGsub(RubyModule kernel) {
if (this.config.getKernelGsubDefined()) {
kernel.addMethod("gsub", new JavaMethod(kernel, Visibility.PRIVATE, "gsub") {
@Override
public IRubyObject call(ThreadContext context1, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
switch (args.length) {
case 1:
return RubyKernel.gsub(context1, self, args[0], block);
case 2:
return RubyKernel.gsub(context1, self, args[0], args[1], block);
default:
throw newArgumentError(String.format("wrong number of arguments %d for 1..2", args.length));
}
}
});
}
}
private ObjectSpacer initObjectSpacer(RubyInstanceConfig config) {
ObjectSpacer objectSpacer;
if (config.isObjectSpaceEnabled()) {
objectSpacer = ENABLED_OBJECTSPACE;
} else {
objectSpacer = DISABLED_OBJECTSPACE;
}
return objectSpacer;
}
private JRubyClassLoader initJRubyClassLoader(RubyInstanceConfig config) {
JRubyClassLoader jrubyClassLoader;
if (!Ruby.isSecurityRestricted()) {
if (config.isClassloaderDelegate()){
jrubyClassLoader = new JRubyClassLoader(config.getLoader());
}
else {
jrubyClassLoader = new SelfFirstJRubyClassLoader(config.getLoader());
}
}
else {
jrubyClassLoader = null;
}
return jrubyClassLoader;
}
private void initDefaultEncodings() {
String encoding = this.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 = this.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);
}
}
private RubyClass initDataClass() {
RubyClass dataClass = null;
if (profile.allowClass("Data")) {
dataClass = defineClass("Data", objectClass, ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
getObject().deprecateConstant(this, "Data");
}
return dataClass;
}
private Random initRandom() {
Random myRandom;
try {
myRandom = new SecureRandom();
} catch (Throwable t) {
LOG.debug("unable to instantiate SecureRandom, falling back on Random", t);
myRandom = new Random();
}
return myRandom;
}
public void registerMBeans() {
this.beanManager.register(jitCompiler);
this.beanManager.register(configBean);
this.beanManager.register(parserStats);
this.beanManager.register(runtimeBean);
this.beanManager.register(caches);
this.beanManager.register(inlineStats);
}
void reinitialize(boolean reinitCore) {
this.doNotReverseLookupEnabled = true;
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.loadRequiredLibraries();
setGlobalRuntimeFirstTimeOnly(ruby);
return ruby;
}
private void loadRequiredLibraries() {
ThreadContext context = getCurrentContext();
for (String scriptName : this.config.getRequiredLibraries()) {
topSelf.callMethod(context, "require", RubyString.newString(this, scriptName));
}
}
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 InlineStats getInlineStats() {
return inlineStats;
}
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;
}
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 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);
}
}
@SuppressWarnings("deprecation")
private RubyClass initContinuation() {
if (profile.allowClass("Continuation")) {
return RubyContinuation.createContinuation(this);
}
return null;
}
public static final int NIL_PREFILLED_ARRAY_SIZE = RubyArray.ARRAY_DEFAULT_SIZE * 8;
private final IRubyObject nilPrefilledArray[];
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 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 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;
}
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;
}
public RubyClass getNumeric() {
return numericClass;
}
public RubyClass getFloat() {
return floatClass;
}
public RubyClass getInteger() {
return integerClass;
}
public RubyClass getFixnum() {
return fixnumClass;
}
public RubyClass getComplex() {
return complexClass;
}
public RubyClass getRational() {
return rationalClass;
}
public RubyModule getEnumerable() {
return enumerableModule;
}
public RubyClass getEnumerator() {
return enumeratorClass;
}
public RubyClass getYielder() {
return yielderClass;
}
public RubyClass getGenerator() {
return generatorClass;
}
public RubyClass getFiber() {
return fiberClass;
}
public RubyClass getString() {
return stringClass;
}
public RubyClass getEncoding() {
return encodingClass;
}
public RubyClass getConverter() {
return converterClass;
}
public RubyClass getSymbol() {
return symbolClass;
}
public RubyClass getArray() {
return arrayClass;
}
public RubyClass getHash() {
return hashClass;
}
public RubyClass getRange() {
return 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;
}
public RubyClass getTrueClass() {
return trueClass;
}
public RubyClass getFalseClass() {
return falseClass;
}
public RubyClass getProc() {
return procClass;
}
public RubyClass getBinding() {
return bindingClass;
}
public RubyClass getMethod() {
return methodClass;
}
public RubyClass getUnboundMethod() {
return unboundMethodClass;
}
public RubyClass getMatchData() {
return matchDataClass;
}
public RubyClass getRegexp() {
return regexpClass;
}
public RubyClass getTime() {
return timeClass;
}
public RubyModule getMath() {
return mathModule;
}
public RubyModule getMarshal() {
return marshalModule;
}
public RubyClass getBignum() {
return bignumClass;
}
public RubyClass getDir() {
return dirClass;
}
public RubyClass getFile() {
return fileClass;
}
public RubyClass getFileStat() {
return fileStatClass;
}
public RubyModule getFileTest() {
return fileTestModule;
}
public RubyClass getIO() {
return ioClass;
}
public RubyClass getThread() {
return threadClass;
}
public RubyClass getThreadGroup() {
return threadGroupClass;
}
public RubyThreadGroup getDefaultThreadGroup() {
return defaultThreadGroup;
}
void setDefaultThreadGroup(RubyThreadGroup defaultThreadGroup) {
this.defaultThreadGroup = defaultThreadGroup;
}
public RubyClass getContinuation() {
return continuationClass;
}
public RubyClass getStructClass() {
return structClass;
}
public RubyClass getRandomClass() {
return 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;
}
public RubyModule getObjectSpaceModule() {
return objectSpaceModule;
}
public RubyModule getProcess() {
return 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 RubyModule getErrno() {
return errnoModule;
}
public RubyClass getException() {
return 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(threadService);
}
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());
switch(eventName) {
case "c_return":
eventName = "c-return";
break;
case "c_call":
eventName = "c-call";
break;
};
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 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;
}
@Deprecated
public void setGlobalVariables(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);
}
threadService = new ThreadService(this);
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 newErrnoFromBindException(BindException be, String contextMessage) {
Errno errno = Helpers.errnoFromException(be);
if (errno != null) {
return newErrnoFromErrno(errno, contextMessage);
}
return newErrnoEADDRFromBindException(be, contextMessage);
}
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 !coreIsBooted;
}
public boolean isBooting() {
return !runtimeIsBooted;
}
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();
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;
public boolean equals(Object other) {
if (other instanceof FStringEqual) {
RubyString otherString = ((FStringEqual) other).string;
RubyString string = this.string;
if (string == null || otherString == null) return false;
return string.equals(otherString) && string.getEncoding() == otherString.getEncoding();
}
return false;
}
public int hashCode() {
RubyString string = this.string;
if (string == null) return 0;
return string.hashCode();
}
}
private final ThreadLocal<FStringEqual> DEDUP_WRAPPER_CACHE = ThreadLocal.withInitial(FStringEqual::new);
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);
}
}
@Deprecated
public IRubyObject getRootFiber() {
return rootFiber;
}
@Deprecated
public void setRootFiber(IRubyObject fiber) {
rootFiber = fiber;
}
@Deprecated
void setKernel(RubyModule kernelModule) {
}
@Deprecated
void setComparable(RubyModule comparableModule) {
}
@Deprecated
void setNumeric(RubyClass numericClass) {
}
@Deprecated
void setFloat(RubyClass floatClass) {
}
@Deprecated
void setInteger(RubyClass integerClass) {
}
@Deprecated
void setFixnum(RubyClass fixnumClass) {
}
@Deprecated
void setComplex(RubyClass complexClass) {
}
@Deprecated
void setRational(RubyClass rationalClass) {
}
@Deprecated
void setEnumerable(RubyModule enumerableModule) {
}
@Deprecated
void setEnumerator(RubyClass enumeratorClass) {
}
@Deprecated
void setYielder(RubyClass yielderClass) {
}
@Deprecated
public void setGenerator(RubyClass generatorClass) {
}
@Deprecated
public void setFiber(RubyClass fiberClass) {
}
@Deprecated
void setString(RubyClass stringClass) {
}
@Deprecated
void setEncoding(RubyClass encodingClass) {
}
@Deprecated
void setConverter(RubyClass converterClass) {
}
@Deprecated
void setSymbol(RubyClass symbolClass) {
}
@Deprecated
void setArray(RubyClass arrayClass) {
}
@Deprecated
void setHash(RubyClass hashClass) {
}
@Deprecated
void setRange(RubyClass rangeClass) {
}
@Deprecated
void setNilClass(RubyClass nilClass) {
}
@Deprecated
void setTrueClass(RubyClass trueClass) {
}
@Deprecated
void setFalseClass(RubyClass falseClass) {
}
@Deprecated
void setProc(RubyClass procClass) {
}
@Deprecated
void setBinding(RubyClass bindingClass) {
}
@Deprecated
void setMethod(RubyClass methodClass) {
}
@Deprecated
void setUnboundMethod(RubyClass unboundMethodClass) {
}
@Deprecated
void setMatchData(RubyClass matchDataClass) {
}
@Deprecated
void setRegexp(RubyClass regexpClass) {
}
@Deprecated
void setTime(RubyClass timeClass) {
}
@Deprecated
void setMath(RubyModule mathModule) {
}
@Deprecated
void setMarshal(RubyModule marshalModule) {
}
@Deprecated
void setBignum(RubyClass bignumClass) {
}
@Deprecated
void setDir(RubyClass dirClass) {
}
@Deprecated
void setFile(RubyClass fileClass) {
}
@Deprecated
void setFileStat(RubyClass fileStatClass) {
}
@Deprecated
void setFileTest(RubyModule fileTestModule) {
}
@Deprecated
void setIO(RubyClass ioClass) {
}
@Deprecated
void setThread(RubyClass threadClass) {
}
@Deprecated
void setThreadGroup(RubyClass threadGroupClass) {
}
@Deprecated
void setContinuation(RubyClass continuationClass) {
}
@Deprecated
void setStructClass(RubyClass structClass) {
}
@Deprecated
void setRandomClass(RubyClass randomClass) {
}
@Deprecated
void setGC(RubyModule gcModule) {
}
@Deprecated
void setObjectSpaceModule(RubyModule objectSpaceModule) {
}
@Deprecated
void setProcess(RubyModule processModule) {
}
@Deprecated
public void setWarning(RubyModule warningModule) {
}
@Deprecated
void setException(RubyClass exceptionClass) {
}
private final ConcurrentHashMap<String, Invalidator> constantNameInvalidators =
new ConcurrentHashMap<String, Invalidator>(
16 ,
0.75f ,
1 );
private final Invalidator checkpointInvalidator;
private 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;
@Deprecated
private long globalState = 1;
private final IRubyObject topSelf;
private final RubyNil nilObject;
private final IRubyObject[] singleNilArray;
private final RubyBoolean trueObject;
private final RubyBoolean falseObject;
final RubyFixnum[] fixnumCache = new RubyFixnum[2 * RubyFixnum.CACHE_OFFSET];
final Object[] fixnumConstants = new Object[fixnumCache.length];
@Deprecated
private IRubyObject rootFiber;
private boolean verbose, warningsEnabled, debug;
private IRubyObject verboseValue;
private RubyThreadGroup defaultThreadGroup;
private final RubyClass basicObjectClass;
private final RubyClass objectClass;
private final RubyClass moduleClass;
private final RubyClass classClass;
private final RubyClass nilClass;
private final RubyClass trueClass;
private final RubyClass falseClass;
private final RubyClass numericClass;
private final RubyClass floatClass;
private final RubyClass integerClass;
private final RubyClass fixnumClass;
private final RubyClass complexClass;
private final RubyClass rationalClass;
private final RubyClass enumeratorClass;
private final RubyClass yielderClass;
private final RubyClass fiberClass;
private final RubyClass generatorClass;
private final RubyClass arrayClass;
private final RubyClass hashClass;
private final RubyClass rangeClass;
private final RubyClass stringClass;
private final RubyClass encodingClass;
private final RubyClass converterClass;
private final RubyClass symbolClass;
private final RubyClass procClass;
private final RubyClass bindingClass;
private final RubyClass methodClass;
private final RubyClass unboundMethodClass;
private final RubyClass matchDataClass;
private final RubyClass regexpClass;
private final RubyClass timeClass;
private final RubyClass bignumClass;
private final RubyClass dirClass;
private final RubyClass fileClass;
private final RubyClass fileStatClass;
private final RubyClass ioClass;
private final RubyClass threadClass;
private final RubyClass threadGroupClass;
private final RubyClass continuationClass;
private final RubyClass structClass;
private final RubyClass exceptionClass;
private final RubyClass dummyClass;
private final RubyClass randomClass;
private final RubyClass dataClass;
private RubyClass tmsStruct;
private RubyClass passwdStruct;
private RubyClass groupStruct;
private RubyClass procStatusClass;
private RubyClass runtimeError;
private RubyClass frozenError;
private RubyClass ioError;
private RubyClass scriptError;
private RubyClass nameError;
private RubyClass nameErrorMessage;
private RubyClass noMethodError;
private RubyClass signalException;
private RubyClass rangeError;
private RubyClass systemExit;
private RubyClass localJumpError;
private RubyClass nativeException;
private RubyClass systemCallError;
private RubyClass fatal;
private RubyClass interrupt;
private RubyClass typeError;
private RubyClass argumentError;
private RubyClass uncaughtThrowError;
private RubyClass indexError;
private RubyClass stopIteration;
private RubyClass syntaxError;
private RubyClass standardError;
private RubyClass loadError;
private RubyClass notImplementedError;
private RubyClass securityError;
private RubyClass noMemoryError;
private RubyClass regexpError;
private RubyClass eofError;
private RubyClass threadError;
private RubyClass concurrencyError;
private RubyClass systemStackError;
private RubyClass zeroDivisionError;
private RubyClass floatDomainError;
private RubyClass mathDomainError;
private RubyClass encodingError;
private RubyClass encodingCompatibilityError;
private RubyClass converterNotFoundError;
private RubyClass undefinedConversionError;
private RubyClass invalidByteSequenceError;
private RubyClass fiberError;
private RubyClass keyError;
private RubyClass locationClass;
private RubyClass interruptedRegexpError;
private final RubyModule kernelModule;
private final RubyModule comparableModule;
private final RubyModule enumerableModule;
private final RubyModule mathModule;
private final RubyModule marshalModule;
private final RubyModule fileTestModule;
private final RubyModule gcModule;
private final RubyModule objectSpaceModule;
private final RubyModule processModule;
private final RubyModule warningModule;
private RubyModule etcModule;
private RubyModule procUIDModule;
private RubyModule procGIDModule;
private RubyModule procSysModule;
private RubyModule precisionModule;
private RubyModule errnoModule;
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 final BeanManager beanManager;
private final ParserStats parserStats;
private InlineStats inlineStats;
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 final LoadService loadService;
private Encoding defaultInternalEncoding, defaultExternalEncoding, defaultFilesystemEncoding;
private final EncodingService encodingService;
private final 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 final ExecutorService executor;
private final 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 final Invalidator
fixnumInvalidator = OptoFactory.newGlobalInvalidator(0),
floatInvalidator = OptoFactory.newGlobalInvalidator(0);
private boolean fixnumReopened, floatReopened;
private final boolean coreIsBooted;
private final boolean runtimeIsBooted;
private RubyHash envObject;
private final CoverageData coverageData = new CoverageData();
private static volatile Ruby globalRuntime;
private static final ThreadLocal<Ruby> threadLocalRuntime = new ThreadLocal<Ruby>();
final Random random;
private final long hashSeedK0;
private final long hashSeedK1;
private final StaticScopeFactory staticScopeFactory;
private final 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 final RubyArray emptyFrozenArray;
private final 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.");
}
}
@Deprecated
public RaiseException newErrnoEADDRFromBindException(BindException be) {
return newErrnoEADDRFromBindException(be, null);
}
}