0
@@ -41,15 +41,14 @@ import java.lang.reflect.Field;
0
import java.lang.reflect.Method;
0
import java.lang.reflect.Modifier;
0
import java.util.ArrayList;
0
+import java.util.Collection;
0
import java.util.Collections;
0
import java.util.HashMap;
0
-import java.util.Iterator;
0
import java.util.HashSet;
0
import java.util.concurrent.ConcurrentHashMap;
0
-import java.util.concurrent.atomic.AtomicInteger;
0
import java.util.concurrent.locks.ReentrantLock;
0
import org.jruby.anno.JRubyMethod;
0
@@ -88,8 +87,8 @@ import org.jruby.exceptions.RaiseException;
0
import org.jruby.internal.runtime.methods.JavaMethod;
0
import org.jruby.javasupport.util.RuntimeHelpers;
0
import org.jruby.runtime.ClassIndex;
0
+import org.jruby.runtime.ConstantCacheMap;
0
import org.jruby.runtime.MethodFactory;
0
-import org.jruby.runtime.MethodIndex;
0
import org.jruby.util.collections.WeakHashSet;
0
@@ -186,15 +185,8 @@ public class RubyModule extends RubyObject {
0
// write methods are overridden here to use this lock rather than Java
0
// synchronization for faster concurrent writes for modules/classes.
0
protected final ReentrantLock variableWriteLock = new ReentrantLock();
0
- protected transient volatile ConstantTableEntry[] constantTable =
0
- new ConstantTableEntry[CONSTANT_TABLE_DEFAULT_CAPACITY];
0
- protected transient int constantTableSize;
0
- protected transient int constantTableThreshold =
0
- (int)(CONSTANT_TABLE_DEFAULT_CAPACITY * CONSTANT_TABLE_LOAD_FACTOR);
0
+ private final Map<String, IRubyObject> constants = new ConcurrentHashMap<String, IRubyObject>();
0
private final Map<String, DynamicMethod> methods = new ConcurrentHashMap<String, DynamicMethod>(12, 0.75f, 1);
0
private final Map<String, CacheEntry> cachedMethods = new ConcurrentHashMap<String, CacheEntry>(12, 0.75f, 1);
0
@@ -500,10 +492,21 @@ public class RubyModule extends RubyObject {
0
doIncludeModule(module);
0
invalidateCacheDescendants();
0
+ private void flushConstants() {
0
+ ConstantCacheMap map = getRuntime().getConstantCacheMap();
0
+ for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
+ for (String name : p.getConstantNames()) {
0
public void defineMethod(String name, Callback method) {
0
Visibility visibility = name.equals("initialize") ?
0
@@ -527,7 +530,7 @@ public class RubyModule extends RubyObject {
0
public void defineAnnotatedConstants(Class clazz) {
0
Field[] declaredFields = clazz.getDeclaredFields();
0
for (Field field : declaredFields) {
0
- if
(Modifier.isStatic(field.getModifiers())) {
0
+ if
(Modifier.isStatic(field.getModifiers())) {
0
defineAnnotatedConstant(field);
0
@@ -862,17 +865,15 @@ public class RubyModule extends RubyObject {
0
callMethod(context, "method_undefined", runtime.newSymbol(name));
0
@JRubyMethod(name = "include?", required = 1)
0
public IRubyObject include_p(ThreadContext context, IRubyObject arg) {
0
- if (!arg.isModule()) {
0
- throw context.getRuntime().newTypeError(arg, context.getRuntime().getModule());
0
- for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
- if ((p instanceof IncludedModuleWrapper) && ((IncludedModuleWrapper) p).getNonIncludedClass() == arg) {
0
- return context.getRuntime().getTrue();
0
+ if (!arg.isModule()) throw context.getRuntime().newTypeError(arg, context.getRuntime().getModule());
0
+ RubyModule moduleToCompare = (RubyModule) arg;
0
+ // See if module is in chain...Cannot match against itself so start at superClass.
0
+ for (RubyModule p = getSuperClass(); p != null; p = p.getSuperClass()) {
0
+ if (p.isSame(moduleToCompare)) return context.getRuntime().getTrue();
0
return context.getRuntime().getFalse();
0
@@ -1005,10 +1006,8 @@ public class RubyModule extends RubyObject {
0
* @return The method, or UndefinedMethod if not found
0
public RubyModule findImplementer(RubyModule clazz) {
0
- for (RubyModule searchModule = this; searchModule != null; searchModule = searchModule.getSuperClass()) {
0
- if (searchModule.isSame(clazz)) {
0
+ for (RubyModule module = this; module != null; module = module.getSuperClass()) {
0
+ if (module.isSame(clazz)) return module;
0
@@ -1454,16 +1453,18 @@ public class RubyModule extends RubyObject {
0
if (!getMetaClass().isSingleton()) setMetaClass(originalModule.getSingletonClassClone());
0
setSuperClass(originalModule.getSuperClass());
0
- if (originalModule.hasVariables()){
0
- syncVariables(originalModule.getVariableList());
0
+ if (originalModule.hasVariables()) syncVariables(originalModule.getVariableList());
0
+ syncConstants(originalModule);
0
originalModule.cloneMethods(this);
0
+ public void syncConstants(RubyModule other) {
0
+ constants.putAll(other.constants);
0
/** rb_mod_included_modules
0
@@ -1496,10 +1497,8 @@ public class RubyModule extends RubyObject {
0
public List<IRubyObject> getAncestorList() {
0
ArrayList<IRubyObject> list = new ArrayList<IRubyObject>();
0
- for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
- if(!p.isSingleton()) {
0
- list.add(p.getNonIncludedClass());
0
+ for (RubyModule module = this; module != null; module = module.getSuperClass()) {
0
+ if(!module.isSingleton()) list.add(module.getNonIncludedClass());
0
@@ -1510,8 +1509,8 @@ public class RubyModule extends RubyObject {
0
// when scanning the hierarchy. However the == check may be safe; we should only ever have
0
// one instance bound to a given type/constant. If it's found to be unsafe, examine ways
0
// to avoid the == call.
0
- for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
- if (p.getNonIncludedClass() == type) return true;
0
+ for (RubyModule module = this; module != null; module = module.getSuperClass()) {
0
+ if (module.getNonIncludedClass() == type) return true;
0
@@ -1584,11 +1583,8 @@ public class RubyModule extends RubyObject {
0
throw getRuntime().newTypeError("compared with non class/module");
0
- if (isKindOfModule((RubyModule) obj)) {
0
- return getRuntime().getTrue();
0
- } else if (((RubyModule) obj).isKindOfModule(this)) {
0
- return getRuntime().getFalse();
0
+ if (isKindOfModule((RubyModule) obj)) return getRuntime().getTrue();
0
+ if (((RubyModule) obj).isKindOfModule(this)) return getRuntime().getFalse();
0
return getRuntime().getNil();
0
@@ -1631,20 +1627,15 @@ public class RubyModule extends RubyObject {
0
RubyModule module = (RubyModule) obj;
0
- if (module.isKindOfModule(this)) {
0
- return getRuntime().newFixnum(1);
0
- } else if (this.isKindOfModule(module)) {
0
- return getRuntime().newFixnum(-1);
0
+ if (module.isKindOfModule(this)) return getRuntime().newFixnum(1);
0
+ if (this.isKindOfModule(module)) return getRuntime().newFixnum(-1);
0
return getRuntime().getNil();
0
public boolean isKindOfModule(RubyModule type) {
0
- for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
+ for (RubyModule module = this; module != null; module = module.getSuperClass()) {
0
+ if (module.isSame(type)) return true;
0
@@ -1692,9 +1683,7 @@ public class RubyModule extends RubyObject {
0
return getRuntime().getNil();
0
public IRubyObject attr_reader(IRubyObject[] args) {
0
return attr_reader(getRuntime().getCurrentContext(), args);
0
@@ -1723,9 +1712,8 @@ public class RubyModule extends RubyObject {
0
return context.getRuntime().getNil();
0
public IRubyObject attr_accessor(IRubyObject[] args) {
0
return attr_accessor(getRuntime().getCurrentContext(), args);
0
@@ -1761,14 +1749,13 @@ public class RubyModule extends RubyObject {
0
for (RubyModule type = this; type != null; type = type.getSuperClass()) {
0
RubyModule realType = type.getNonIncludedClass();
0
- for (Iterator iter = type.getMethods().entrySet().iterator(); iter.hasNext();) {
0
- Map.Entry entry = (Map.Entry) iter.next();
0
- DynamicMethod method = (DynamicMethod) entry.getValue();
0
+ for (Map.Entry entry : type.getMethods().entrySet()) {
0
String methodName = (String) entry.getKey();
0
if (! seen.contains(methodName)) {
0
+ DynamicMethod method = (DynamicMethod) entry.getValue();
0
if (method.getImplementationClass() == realType &&
0
(!not && method.getVisibility() == visibility || (not && method.getVisibility() != visibility)) &&
0
! method.isUndefined()) {
0
@@ -2233,17 +2220,12 @@ public class RubyModule extends RubyObject {
0
Set<String> names = new HashSet<String>();
0
for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
- for (String name : p.getClassVariableNameList()) {
0
+ names.addAll(p.getClassVariableNameList());
0
- Ruby runtime = context.getRuntime();
0
- RubyArray ary = runtime.newArray();
0
+ RubyArray ary = context.getRuntime().newArray();
0
- for (String name : names) {
0
- ary.append(runtime.newString(name));
0
@@ -2267,7 +2249,7 @@ public class RubyModule extends RubyObject {
0
@JRubyMethod(name = "const_get", required = 1)
0
public IRubyObject const_get(IRubyObject symbol) {
0
- return
fastGetConstant(validateConstant(symbol.asJavaString()).intern());
0
+ return
getConstant(validateConstant(symbol.asJavaString()));
0
@@ -2279,31 +2261,32 @@ public class RubyModule extends RubyObject {
0
@JRubyMethod(name = "remove_const", required = 1, visibility = PRIVATE)
0
- public IRubyObject remove_const(ThreadContext context, IRubyObject name) {
0
- String id = validateConstant(name.asJavaString());
0
+ public IRubyObject remove_const(ThreadContext context, IRubyObject rubyName) {
0
+ String name = validateConstant(rubyName.asJavaString());
0
- if ((value = deleteConstant(id)) != null) {
0
+ if ((value = deleteConstant(name)) != null) {
0
+ getRuntime().getConstantCacheMap().remove(name);
0
- context.getRuntime().getLoadService().removeAutoLoadFor(getName() + "::" +
id);
0
+ context.getRuntime().getLoadService().removeAutoLoadFor(getName() + "::" +
name);
0
// FIXME: I'm not sure this is right, but the old code returned
0
// the undef, which definitely isn't right...
0
return context.getRuntime().getNil();
0
- if (hasConstantInHierarchy(id)) {
0
- throw cannotRemoveError(id);
0
+ if (hasConstantInHierarchy(name)) {
0
+ throw cannotRemoveError(name);
0
- throw context.getRuntime().newNameError("constant " +
id + " not defined for " + getName(), id);
0
+ throw context.getRuntime().newNameError("constant " +
name + " not defined for " + getName(), name);
0
private boolean hasConstantInHierarchy(final String name) {
0
for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
if (p.hasConstant(name)) {
0
@@ -2315,13 +2298,17 @@ public class RubyModule extends RubyObject {
0
* @return Nothing! Absolutely nothing! (though subclasses might choose to return something)
0
@JRubyMethod(name = "const_missing", required = 1, frame = true)
0
- public IRubyObject const_missing(ThreadContext context, IRubyObject name, Block block) {
0
- /* Uninitialized constant */
0
- if (this != context.getRuntime().getObject()) {
0
- throw context.getRuntime().newNameError("uninitialized constant " + getName() + "::" + name.asJavaString(), "" + getName() + "::" + name.asJavaString());
0
+ public IRubyObject const_missing(ThreadContext context, IRubyObject rubyName, Block block) {
0
+ Ruby runtime = context.getRuntime();
0
+ if (this != runtime.getObject()) {
0
+ name = getName() + "::" + rubyName.asJavaString();
0
+ name = rubyName.asJavaString();
0
- throw
context.getRuntime().newNameError("uninitialized constant " + name.asJavaString(), name.asJavaString());
0
+ throw
runtime.newNameError("uninitialized constant " + name, name);
0
@@ -2333,30 +2320,14 @@ public class RubyModule extends RubyObject {
0
RubyArray array = runtime.newArray();
0
RubyModule objectClass = runtime.getObject();
0
- if (getRuntime().getModule() == this) {
0
- for (String name : objectClass.getStoredConstantNameList()) {
0
- array.append(runtime.newString(name));
0
- } else if (objectClass == this) {
0
- for (String name : getStoredConstantNameList()) {
0
- array.append(runtime.newString(name));
0
+ if (getRuntime().getModule() == this || objectClass == this) {
0
+ array.addAll(objectClass.getConstantNames());
0
Set<String> names = new HashSet<String>();
0
- for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
- if (objectClass != p) {
0
- for (String name : p.getStoredConstantNameList()) {
0
- for (String name : names) {
0
- array.append(runtime.newString(name));
0
+ for (RubyModule module = this; module != null && module != objectClass; module = module.getSuperClass()) {
0
+ names.addAll(module.getConstantNames());
0
@@ -2484,22 +2455,16 @@ public class RubyModule extends RubyObject {
0
public IRubyObject getConstantAt(String name) {
0
- if ((value = fetchConstant(name)) != UNDEF) {
0
- return getRuntime().getLoadService().autoload(getName() + "::" + name);
0
+ IRubyObject value = fetchConstant(name);
0
+ return value == UNDEF ? resolveUndefConstant(getRuntime(), name) : value;
0
public IRubyObject fastGetConstantAt(String internedName) {
0
assert internedName == internedName.intern() : internedName + " is not interned";
0
- if ((value = fastFetchConstant(internedName)) != UNDEF) {
0
- deleteConstant(internedName);
0
- return getRuntime().getLoadService().autoload(getName() + "::" + internedName);
0
+ IRubyObject value = fastFetchConstant(internedName);
0
+ return value == UNDEF ? resolveUndefConstant(getRuntime(), internedName) : value;
0
@@ -2509,74 +2474,43 @@ public class RubyModule extends RubyObject {
0
* @return The value for the constant, or null if not found
0
public IRubyObject getConstant(String name) {
0
+ return fastGetConstant(name);
0
+ public IRubyObject fastGetConstant(String internedName) {
0
+ IRubyObject value = getConstantNoConstMissing(internedName);
0
+ Ruby runtime = getRuntime();
0
+ return value == null ? callMethod(runtime.getCurrentContext(), "const_missing",
0
+ runtime.fastNewSymbol(internedName)) : value;
0
+ public IRubyObject getConstantNoConstMissing(String name) {
0
assert IdUtil.isConstant(name);
0
- boolean retryForModule = false;
0
- if ((value = p.constantTableFetch(name)) != null) {
0
- p.deleteConstant(name);
0
- if (getRuntime().getLoadService().autoload(
0
- p.getName() + "::" + name) == null) {
0
- p = p.getSuperClass();
0
+ for (RubyModule p = this; p != null; p = p.getSuperClass()) {
0
+ IRubyObject value = p.getConstantInner(name);
0
- if (!retryForModule && !isClass()) {
0
- retryForModule = true;
0
- p = getRuntime().getObject();
0
+ if (value != null) return value == UNDEF ? null : value;
0
+ IRubyObject value = getRuntime().getObject().getConstantInner(name);
0
+
return value == UNDEF ? null : value;
0
- return callMethod(getRuntime().getCurrentContext(),
0
- "const_missing", getRuntime().newSymbol(name));
0
- public IRubyObject fastGetConstant(String internedName) {
0
- assert internedName == internedName.intern() : internedName + " is not interned";
0
- assert IdUtil.isConstant(internedName);
0
- boolean retryForModule = false;
0
+ protected IRubyObject getConstantInner(String name) {
0
+ IRubyObject value = constantTableFetch(name);
0
- if ((value = p.constantTableFastFetch(internedName)) != null) {
0
- p.deleteConstant(internedName);
0
- if (getRuntime().getLoadService().autoload(
0
- p.getName() + "::" + internedName) == null) {
0
- p = p.getSuperClass();
0
- if (!retryForModule && !isClass()) {
0
- retryForModule = true;
0
- p = getRuntime().getObject();
0
+ for (; value == UNDEF; value = constantTableFetch(name)) {
0
+ if (resolveUndefConstant(getRuntime(), name) == null) return UNDEF;
0
- return callMethod(getRuntime().getCurrentContext(),
0
- "const_missing", getRuntime().fastNewSymbol(internedName));
0
// not actually called anywhere (all known uses call the fast version)
0
@@ -2587,27 +2521,26 @@ public class RubyModule extends RubyObject {
0
public IRubyObject fastGetConstantFrom(String internedName) {
0
assert internedName == internedName.intern() : internedName + " is not interned";
0
assert IdUtil.isConstant(internedName);
0
- RubyClass objectClass = getRuntime().getObject();
0
+ Ruby runtime = getRuntime();
0
+ RubyClass objectClass = runtime.getObject();
0
if ((value = p.constantTableFastFetch(internedName)) != null) {
0
- if (p == objectClass && this != objectClass) {
0
- String badCName = getName() + "::" + internedName;
0
- getRuntime().getWarnings().warn(ID.CONSTANT_BAD_REFERENCE, "toplevel constant " +
0
- internedName + " referenced by " + badCName, badCName);
0
+ if (p.resolveUndefConstant(runtime, internedName) == null) break;
0
+ continue; // Not that is loaded loop around to resolve it next pass
0
- p.deleteConstant(internedName);
0
- if (getRuntime().getLoadService().autoload(
0
- p.getName() + "::" + internedName) == null) {
0
+ if (p == objectClass && this != objectClass) {
0
+ String badCName = getName() + "::" + internedName;
0
+ runtime.getWarnings().warn(ID.CONSTANT_BAD_REFERENCE, "toplevel constant " +
0
+ internedName + " referenced by " + badCName, badCName);
0
@@ -2615,6 +2548,13 @@ public class RubyModule extends RubyObject {
0
return callMethod(getRuntime().getCurrentContext(),
0
"const_missing", getRuntime().fastNewSymbol(internedName));
0
+ public IRubyObject resolveUndefConstant(Ruby runtime, String name) {
0
+ return runtime.getLoadService().autoload(getName() + "::" + name);
0
* Set the named constant on this module. Also, if the value provided is another Module and
0
* that module has not yet been named, assign it the specified name.
0
@@ -2624,12 +2564,14 @@ public class RubyModule extends RubyObject {
0
* @return The result of setting the variable.
0
public IRubyObject setConstant(String name, IRubyObject value) {
0
- if ((oldValue = fetchConstant(name)) != null) {
0
+ IRubyObject oldValue = fetchConstant(name);
0
+ if (oldValue != null) {
0
+ Ruby runtime = getRuntime();
0
+ runtime.getConstantCacheMap().remove(name);
0
if (oldValue == UNDEF) {
0
-
getRuntime().getLoadService().removeAutoLoadFor(getName() + "::" + name);
0
+
runtime.getLoadService().removeAutoLoadFor(getName() + "::" + name);
0
-
getRuntime().getWarnings().warn(ID.CONSTANT_ALREADY_INITIALIZED, "already initialized constant " + name, name);
0
+
runtime.getWarnings().warn(ID.CONSTANT_ALREADY_INITIALIZED, "already initialized constant " + name, name);
0
@@ -2642,38 +2584,12 @@ public class RubyModule extends RubyObject {
0
module.setBaseName(name);
0
module.setParent(this);
0
- module.setParent(this);
0
public IRubyObject fastSetConstant(String internedName, IRubyObject value) {
0
- assert internedName == internedName.intern() : internedName + " is not interned";
0
- if ((oldValue = fastFetchConstant(internedName)) != null) {
0
- if (oldValue == UNDEF) {
0
- getRuntime().getLoadService().removeAutoLoadFor(getName() + "::" + internedName);
0
- getRuntime().getWarnings().warn(ID.CONSTANT_ALREADY_INITIALIZED, "already initialized constant " + internedName, internedName);
0
- fastStoreConstant(internedName, value);
0
- // if adding a module under a constant name, set that module's basename to the constant name
0
- if (value instanceof RubyModule) {
0
- RubyModule module = (RubyModule)value;
0
- if (module.getBaseName() == null) {
0
- module.setBaseName(internedName);
0
- module.setParent(this);
0
- module.setParent(this);
0
+ return setConstant(internedName, value);
0
@@ -2759,12 +2675,9 @@ public class RubyModule extends RubyObject {
0
* @see #setInternalModuleVariable(String, IRubyObject)
0
public boolean hasInternalModuleVariable(final String name) {
0
- RubyModule module = this;
0
- if (module.hasInternalVariable(name)) {
0
- } while ((module = module.getSuperClass()) != null);
0
+ for (RubyModule module = this; module != null; module = module.getSuperClass()) {
0
+ if (module.hasInternalVariable(name)) return true;
0
@@ -2778,13 +2691,10 @@ public class RubyModule extends RubyObject {
0
* @see #setInternalModuleVariable(String, IRubyObject)
0
public IRubyObject searchInternalModuleVariable(final String name) {
0
- RubyModule module = this;
0
- if ((value = module.getInternalVariable(name)) != null) {
0
- } while ((module = module.getSuperClass()) != null);
0
+ for (RubyModule module = this; module != null; module = module.getSuperClass()) {
0
+ IRubyObject value = module.getInternalVariable(name);
0
+ if (value != null) return value;
0
@@ -2799,13 +2709,12 @@ public class RubyModule extends RubyObject {
0
* @see #searchInternalModuleVariable(String)
0
public void setInternalModuleVariable(final String name, final IRubyObject value) {
0
- RubyModule module = this;
0
+ for (RubyModule module = this; module != null; module = module.getSuperClass()) {
0
if (module.hasInternalVariable(name)) {
0
module.setInternalVariable(name, value);
0
- }
while ((module = module.getSuperClass()) != null);0
setInternalVariable(name, value);
0
@@ -2958,26 +2867,22 @@ public class RubyModule extends RubyObject {
0
return constantTableRemove(name);
0
public List<Variable<IRubyObject>> getStoredConstantList() {
0
- ArrayList<Variable<IRubyObject>> list = new ArrayList<Variable<IRubyObject>>();
0
- ConstantTableEntry[] table = constantTableGetTable();
0
- for (int i = table.length; --i >= 0; ) {
0
- for (ConstantTableEntry e = table[i]; e != null; e = e.next) {
0
public List<String> getStoredConstantNameList() {
0
- ArrayList<String> list = new ArrayList<String>();
0
- ConstantTableEntry[] table = constantTableGetTable();
0
- for (int i = table.length; --i >= 0; ) {
0
- for (ConstantTableEntry e = table[i]; e != null; e = e.next) {
0
+ return new ArrayList<String>(constants.keySet());
0
+ * @return a list of constant names that exists at time this was called
0
+ public Collection<String> getConstantNames() {
0
+ return constants.keySet();
0
protected static final String ERR_INSECURE_SET_CONSTANT = "Insecure: can't modify constant";
0
@@ -2991,583 +2896,41 @@ public class RubyModule extends RubyObject {
0
protected final void ensureConstantsSettable() {
0
- Ruby runtime = getRuntime();
0
- if (!isFrozen() && (runtime.getSafeLevel() < 4 || isTaint())) {
0
- if (runtime.getSafeLevel() >= 4 && !isTaint()) {
0
- throw runtime.newSecurityError(ERR_INSECURE_SET_CONSTANT);
0
- if (this instanceof RubyModule) {
0
- throw runtime.newFrozenError(ERR_FROZEN_CONST_TYPE);
0
- throw runtime.newFrozenError("");
0
- ////////////////// VARIABLE TABLE METHODS ////////////////
0
- // Overridden to use variableWriteLock in place of synchronization
0
- protected IRubyObject variableTableStore(String name, IRubyObject value) {
0
- int hash = name.hashCode();
0
- (lock = variableWriteLock).lock();
0
- VariableTableEntry[] table;
0
- if ((table = variableTable) == null) {
0
- table = new VariableTableEntry[VARIABLE_TABLE_DEFAULT_CAPACITY];
0
- e = new VariableTableEntry(hash, name.intern(), value, null);
0
- table[hash & (VARIABLE_TABLE_DEFAULT_CAPACITY - 1)] = e;
0
- variableTableThreshold = (int)(VARIABLE_TABLE_DEFAULT_CAPACITY * VARIABLE_TABLE_LOAD_FACTOR);
0
- variableTableSize = 1;
0
- variableTable = table;
0
- if ((potentialNewSize = variableTableSize + 1) > variableTableThreshold) {
0
- table = variableTableRehash();
0
- for (e = table[index = hash & (table.length - 1)]; e != null; e = e.next) {
0
- if (hash == e.hash && name.equals(e.name)) {
0
- // external volatile value initialization intended to obviate the need for
0
- // readValueUnderLock technique used in ConcurrentHashMap. may be a little
0
- // slower, but better to pay a price on first write rather than all reads.
0
- e = new VariableTableEntry(hash, name.intern(), value, table[index]);
0
- variableTableSize = potentialNewSize;
0
- variableTable = table; // write-volatile
0
- protected IRubyObject variableTableFastStore(String internedName, IRubyObject value) {
0
- assert internedName == internedName.intern() : internedName + " not interned";
0
- int hash = internedName.hashCode();
0
- (lock = variableWriteLock).lock();
0
- VariableTableEntry[] table;
0
- if ((table = variableTable) == null) {
0
- table = new VariableTableEntry[VARIABLE_TABLE_DEFAULT_CAPACITY];
0
- e = new VariableTableEntry(hash, internedName, value, null);
0
- table[hash & (VARIABLE_TABLE_DEFAULT_CAPACITY - 1)] = e;
0
- variableTableThreshold = (int)(VARIABLE_TABLE_DEFAULT_CAPACITY * VARIABLE_TABLE_LOAD_FACTOR);
0
- variableTableSize = 1;
0
- variableTable = table;
0
- if ((potentialNewSize = variableTableSize + 1) > variableTableThreshold) {
0
- table = variableTableRehash();
0
- for (e = table[index = hash & (table.length - 1)]; e != null; e = e.next) {
0
- if (internedName == e.name) {
0
- // external volatile value initialization intended to obviate the need for
0
- // readValueUnderLock technique used in ConcurrentHashMap. may be a little
0
- // slower, but better to pay a price on first write rather than all reads.
0
- e = new VariableTableEntry(hash, internedName, value, table[index]);
0
- variableTableSize = potentialNewSize;
0
- variableTable = table; // write-volatile
0
- protected IRubyObject variableTableRemove(String name) {
0
- (lock = variableWriteLock).lock();
0
- VariableTableEntry[] table;
0
- if ((table = variableTable) != null) {
0
- int hash = name.hashCode();
0
- int index = hash & (table.length - 1);
0
- VariableTableEntry first = table[index];
0
- for (e = first; e != null; e = e.next) {
0
- if (hash == e.hash && name.equals(e.name)) {
0
- IRubyObject oldValue = e.value;
0
- // All entries following removed node can stay
0
- // in list, but all preceding ones need to be
0
- VariableTableEntry newFirst = e.next;
0
- for (VariableTableEntry p = first; p != e; p = p.next) {
0
- newFirst = new VariableTableEntry(p.hash, p.name, p.value, newFirst);
0
- table[index] = newFirst;
0
- variableTable = table; // write-volatile
0
- protected IRubyObject variableTableReadLocked(VariableTableEntry entry) {
0
- (lock = variableWriteLock).lock();
0
- protected void variableTableSync(List<Variable<IRubyObject>> vars) {
0
- (lock = variableWriteLock).lock();
0
- variableTableSize = 0;
0
- variableTableThreshold = (int)(VARIABLE_TABLE_DEFAULT_CAPACITY * VARIABLE_TABLE_LOAD_FACTOR);
0
- variableTable = new VariableTableEntry[VARIABLE_TABLE_DEFAULT_CAPACITY];
0
- for (Variable<IRubyObject> var : vars) {
0
- assert !var.isConstant() && var.getValue() != null;
0
- variableTableStore(var.getName(), var.getValue());
0
- public void syncVariables(List<Variable<IRubyObject>> variables) {
0
- ArrayList<Variable<IRubyObject>> constants = new ArrayList<Variable<IRubyObject>>(variables.size());
0
- Variable<IRubyObject> var;
0
- for (Iterator<Variable<IRubyObject>> iter = variables.iterator(); iter.hasNext(); ) {
0
- if ((var = iter.next()).isConstant()) {
0
- (lock = variableWriteLock).lock();
0
- variableTableSync(variables);
0
- constantTableSync(constants);
0
- @SuppressWarnings("unchecked")
0
- @Deprecated // born deprecated
0
- public Map getVariableMap() {
0
- Map map = variableTableGetMap();
0
- constantTableGetMap(map);
0
- public boolean hasVariables() {
0
- return variableTableGetSize() > 0 || constantTableGetSize() > 0;
0
- public int getVariableCount() {
0
- return variableTableGetSize() + constantTableGetSize();
0
- public List<Variable<IRubyObject>> getVariableList() {
0
- VariableTableEntry[] vtable = variableTableGetTable();
0
- ConstantTableEntry[] ctable = constantTableGetTable();
0
- ArrayList<Variable<IRubyObject>> list = new ArrayList<Variable<IRubyObject>>();
0
- IRubyObject readValue;
0
- for (int i = vtable.length; --i >= 0; ) {
0
- for (VariableTableEntry e = vtable[i]; e != null; e = e.next) {
0
- if ((readValue = e.value) == null) readValue = variableTableReadLocked(e);
0
- list.add(new VariableEntry<IRubyObject>(e.name, readValue));
0
- for (int i = ctable.length; --i >= 0; ) {
0
- for (ConstantTableEntry e = ctable[i]; e != null; e = e.next) {
0
+ boolean isSecure = getRuntime().getSafeLevel() >= 4 && !isTaint();
0
- public List<String> getVariableNameList() {
0
- VariableTableEntry[] vtable = variableTableGetTable();
0
- ConstantTableEntry[] ctable = constantTableGetTable();
0
- ArrayList<String> list = new ArrayList<String>();
0
- for (int i = vtable.length; --i >= 0; ) {
0
- for (VariableTableEntry e = vtable[i]; e != null; e = e.next) {
0
- for (int i = ctable.length; --i >= 0; ) {
0
- for (ConstantTableEntry e = ctable[i]; e != null; e = e.next) {
0
- ////////////////// CONSTANT TABLE METHODS, ETC. ////////////////
0
- protected static final int CONSTANT_TABLE_DEFAULT_CAPACITY = 8; // MUST be power of 2!
0
- protected static final int CONSTANT_TABLE_MAXIMUM_CAPACITY = 1 << 30;
0
- protected static final float CONSTANT_TABLE_LOAD_FACTOR = 0.75f;
0
- protected static final class ConstantTableEntry implements Variable<IRubyObject> {
0
- final IRubyObject value;
0
- final ConstantTableEntry next;
0
- // constant table entry values are final; if a constant is redefined, the
0
- // entry will be removed and replaced with a new entry.
0
- ConstantTableEntry next) {
0
- public String getName() {
0
- public IRubyObject getValue() {
0
- public final boolean isClassVariable() {
0
- public final boolean isConstant() {
0
- public final boolean isInstanceVariable() {
0
- public final boolean isRubyVariable() {
0
+ if (isSecure) throw getRuntime().newSecurityError(ERR_INSECURE_SET_CONSTANT);
0
+ if (isFrozen()) throw getRuntime().newFrozenError(ERR_FROZEN_CONST_TYPE);
0
protected boolean constantTableContains(String name) {
0
- int hash = name.hashCode();
0
- ConstantTableEntry[] table;
0
- for (ConstantTableEntry e = (table = constantTable)[hash & (table.length - 1)]; e != null; e = e.next) {
0
- if (hash == e.hash && name.equals(e.name)) {
0
+ return constants.containsKey(name);
0
protected boolean constantTableFastContains(String internedName) {
0
- ConstantTableEntry[] table;
0
- for (ConstantTableEntry e = (table = constantTable)[internedName.hashCode() & (table.length - 1)]; e != null; e = e.next) {
0
- if (internedName == e.name) {
0
+ return constants.containsKey(internedName);
0
protected IRubyObject constantTableFetch(String name) {
0
- int hash = name.hashCode();
0
- ConstantTableEntry[] table;
0
- for (ConstantTableEntry e = (table = constantTable)[hash & (table.length - 1)]; e != null; e = e.next) {
0
- if (hash == e.hash && name.equals(e.name)) {
0
+ return constants.get(name);
0
protected IRubyObject constantTableFastFetch(String internedName) {
0
- ConstantTableEntry[] table;
0
- for (ConstantTableEntry e = (table = constantTable)[internedName.hashCode() & (table.length - 1)]; e != null; e = e.next) {
0
- if (internedName == e.name) {
0
+ return constants.get(internedName);
0
protected IRubyObject constantTableStore(String name, IRubyObject value) {
0
- int hash = name.hashCode();
0
- (lock = variableWriteLock).lock();
0
- ConstantTableEntry[] table;
0
- ConstantTableEntry first;
0
- if ((potentialNewSize = constantTableSize + 1) > constantTableThreshold) {
0
- table = constantTableRehash();
0
- table = constantTable;
0
- for (e = first = table[index = hash & (table.length - 1)]; e != null; e = e.next) {
0
- if (hash == e.hash && name.equals(e.name)) {
0
- // if value is unchanged, do nothing
0
- if (value == e.value) {
0
- // create new entry, prepend to any trailing entries
0
- ConstantTableEntry newFirst = new ConstantTableEntry(e.hash, e.name, value, e.next);
0
- // all entries before this one must be cloned
0
- for (ConstantTableEntry n = first; n != e; n = n.next) {
0
- newFirst = new ConstantTableEntry(n.hash, n.name, n.value, newFirst);
0
- table[index] = newFirst;
0
- constantTable = table; // write-volatile
0
- table[index] = new ConstantTableEntry(hash, name.intern(), value, table[index]);
0
- constantTableSize = potentialNewSize;
0
- constantTable = table; // write-volatile
0
+ constants.put(name, value);
0
protected IRubyObject constantTableFastStore(String internedName, IRubyObject value) {
0
- assert internedName == internedName.intern() : internedName + " not interned";
0
- int hash = internedName.hashCode();
0
- (lock = variableWriteLock).lock();
0
- ConstantTableEntry[] table;
0
- ConstantTableEntry first;
0
- if ((potentialNewSize = constantTableSize + 1) > constantTableThreshold) {
0
- table = constantTableRehash();
0
- table = constantTable;
0
- for (e = first = table[index = hash & (table.length - 1)]; e != null; e = e.next) {
0
- if (internedName == e.name) {
0
- // if value is unchanged, do nothing
0
- if (value == e.value) {
0
- // create new entry, prepend to any trailing entries
0
- ConstantTableEntry newFirst = new ConstantTableEntry(e.hash, e.name, value, e.next);
0
- // all entries before this one must be cloned
0
- for (ConstantTableEntry n = first; n != e; n = n.next) {
0
- newFirst = new ConstantTableEntry(n.hash, n.name, n.value, newFirst);
0
- table[index] = newFirst;
0
- constantTable = table; // write-volatile
0
- table[index] = new ConstantTableEntry(hash, internedName, value, table[index]);
0
- constantTableSize = potentialNewSize;
0
- constantTable = table; // write-volatile
0
+ constants.put(internedName, value);
0
protected IRubyObject constantTableRemove(String name) {
0
- (lock = variableWriteLock).lock();
0
- ConstantTableEntry[] table;
0
- if ((table = constantTable) != null) {
0
- int hash = name.hashCode();
0
- int index = hash & (table.length - 1);
0
- ConstantTableEntry first = table[index];
0
- for (e = first; e != null; e = e.next) {
0
- if (hash == e.hash && name.equals(e.name)) {
0
- IRubyObject oldValue = e.value;
0
- // All entries following removed node can stay
0
- // in list, but all preceding ones need to be
0
- ConstantTableEntry newFirst = e.next;
0
- for (ConstantTableEntry p = first; p != e; p = p.next) {
0
- newFirst = new ConstantTableEntry(p.hash, p.name, p.value, newFirst);
0
- table[index] = newFirst;
0
- constantTable = table; // write-volatile
0
- protected ConstantTableEntry[] constantTableGetTable() {
0
+ return constants.remove(name);
0
- protected int constantTableGetSize() {
0
- if (constantTable != null) {
0
- return constantTableSize;
0
- protected void constantTableSync(List<Variable<IRubyObject>> vars) {
0
- (lock = variableWriteLock).lock();
0
- constantTableSize = 0;
0
- constantTableThreshold = (int)(CONSTANT_TABLE_DEFAULT_CAPACITY * CONSTANT_TABLE_LOAD_FACTOR);
0
- constantTable = new ConstantTableEntry[CONSTANT_TABLE_DEFAULT_CAPACITY];
0
- for (Variable<IRubyObject> var : vars) {
0
- assert var.isConstant() && var.getValue() != null;
0
- constantTableStore(var.getName(), var.getValue());
0
- // MUST be called from synchronized/locked block!
0
- // should only be called by constantTableStore/constantTableFastStore
0
- private final ConstantTableEntry[] constantTableRehash() {
0
- ConstantTableEntry[] oldTable = constantTable;
0
- if ((oldCapacity = oldTable.length) >= CONSTANT_TABLE_MAXIMUM_CAPACITY) {
0
- int newCapacity = oldCapacity << 1;
0
- ConstantTableEntry[] newTable = new ConstantTableEntry[newCapacity];
0
- constantTableThreshold = (int)(newCapacity * CONSTANT_TABLE_LOAD_FACTOR);
0
- int sizeMask = newCapacity - 1;
0
- for (int i = oldCapacity; --i >= 0; ) {
0
- // We need to guarantee that any existing reads of old Map can
0
- // proceed. So we cannot yet null out each bin.
0
- ConstantTableEntry next = e.next;
0
- int idx = e.hash & sizeMask;
0
- // Single node on list
0
- // Reuse trailing consecutive sequence at same slot
0
- ConstantTableEntry lastRun = e;
0
- for (ConstantTableEntry last = next;
0
- int k = last.hash & sizeMask;
0
- newTable[lastIdx] = lastRun;
0
- // Clone all remaining nodes
0
- for (ConstantTableEntry p = e; p != lastRun; p = p.next) {
0
- int k = p.hash & sizeMask;
0
- ConstantTableEntry m = new ConstantTableEntry(p.hash, p.name, p.value, newTable[k]);
0
- constantTable = newTable;
0
- * Method to help ease transition to new variables implementation.
0
- * Will likely be deprecated in the near future.
0
- @SuppressWarnings("unchecked")
0
- protected Map constantTableGetMap() {
0
- HashMap map = new HashMap();
0
- ConstantTableEntry[] table;
0
- if ((table = constantTable) != null) {
0
- for (int i = table.length; --i >= 0; ) {
0
- for (ConstantTableEntry e = table[i]; e != null; e = e.next) {
0
- map.put(e.name, e.value);
0
- * Method to help ease transition to new variables implementation.
0
- * Will likely be deprecated in the near future.
0
- @SuppressWarnings("unchecked")
0
- protected Map constantTableGetMap(Map map) {
0
- ConstantTableEntry[] table;
0
- if ((table = constantTable) != null) {
0
- for (int i = table.length; --i >= 0; ) {
0
- for (ConstantTableEntry e = table[i]; e != null; e = e.next) {
0
- map.put(e.name, e.value);
0
- private CacheEntry UNDEFINED_METHOD = new CacheEntry(-1, UndefinedMethod.getInstance());
0
public static class CacheEntry {
0
private int generation;