Made BytecodeClass.computeMethodMap thread-safe

This commit is contained in:
Andreas Sewe 2013-05-07 11:21:37 +02:00 committed by Manu Sridharan
parent d0b5e8ddd2
commit bc2594237b
2 changed files with 29 additions and 31 deletions

View File

@ -78,7 +78,7 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
* *
* TODO: get rid of this for classes (though keep it for interfaces) instead ... use a VMT. * TODO: get rid of this for classes (though keep it for interfaces) instead ... use a VMT.
*/ */
protected Map<Selector, IMethod> methodMap; protected volatile Map<Selector, IMethod> methodMap;
/** /**
* A mapping from Selector to IMethod used to cache method lookups from superclasses * A mapping from Selector to IMethod used to cache method lookups from superclasses
@ -385,13 +385,11 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods() * @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
*/ */
public Collection<IMethod> getDeclaredMethods() { public Collection<IMethod> getDeclaredMethods() {
if (methodMap == null) { try {
try { computeMethodMap();
computeMethodMap(); } catch (InvalidClassFileException e) {
} catch (InvalidClassFileException e) { e.printStackTrace();
e.printStackTrace(); Assertions.UNREACHABLE();
Assertions.UNREACHABLE();
}
} }
return Collections.unmodifiableCollection(methodMap.values()); return Collections.unmodifiableCollection(methodMap.values());
} }
@ -400,13 +398,11 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
* @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.types.Selector) * @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.types.Selector)
*/ */
public IMethod getMethod(Selector selector) { public IMethod getMethod(Selector selector) {
if (methodMap == null) { try {
try { computeMethodMap();
computeMethodMap(); } catch (InvalidClassFileException e1) {
} catch (InvalidClassFileException e1) { e1.printStackTrace();
e1.printStackTrace(); Assertions.UNREACHABLE();
Assertions.UNREACHABLE();
}
} }
// my methods + cached parent stuff // my methods + cached parent stuff
@ -555,15 +551,19 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
*/ */
protected void computeMethodMap() throws InvalidClassFileException { protected void computeMethodMap() throws InvalidClassFileException {
if (methodMap == null) { if (methodMap == null) {
IMethod[] methods = computeDeclaredMethods(); synchronized (this) {
if (methods.length > 5) { if (methodMap == null) {
methodMap = HashMapFactory.make(methods.length); IMethod[] methods = computeDeclaredMethods();
} else { if (methods.length > 5) {
methodMap = new SmallMap<Selector, IMethod>(); methodMap = HashMapFactory.make(methods.length);
} } else {
for (int i = 0; i < methods.length; i++) { methodMap = new SmallMap<Selector, IMethod>();
IMethod m = methods[i]; }
methodMap.put(m.getReference().getSelector(), m); for (int i = 0; i < methods.length; i++) {
IMethod m = methods[i];
methodMap.put(m.getReference().getSelector(), m);
}
}
} }
} }
} }

View File

@ -64,13 +64,11 @@ public abstract class JVMClass<T extends IClassLoader> extends BytecodeClass<T>
* @see com.ibm.wala.classLoader.IClass#getClassInitializer() * @see com.ibm.wala.classLoader.IClass#getClassInitializer()
*/ */
public IMethod getClassInitializer() { public IMethod getClassInitializer() {
if (methodMap == null) { try {
try { computeMethodMap();
computeMethodMap(); } catch (InvalidClassFileException e) {
} catch (InvalidClassFileException e) { e.printStackTrace();
e.printStackTrace(); Assertions.UNREACHABLE();
Assertions.UNREACHABLE();
}
} }
return methodMap.get(MethodReference.clinitSelector); return methodMap.get(MethodReference.clinitSelector);
} }