1. It is not passed as a parameter to Interpreter/Codegen, instead Codegen access it directly when necessary.

2. ClassNameHelper.reset method is removed as inherently thread unsafe and data that should be used during compilation of single script is stored in Codegen itself.

3. Instead of a special DefaultClassRepository null is used to indicate that generated classes should not be stored and JavaAdapter is modified to take ClassRepository as a parameter, not ClassNameHelper.
This commit is contained in:
igor%mir2.org 2003-02-15 14:21:33 +00:00
Родитель cb81ad7f8d
Коммит de021ba69a
8 изменённых файлов: 67 добавлений и 90 удалений

Просмотреть файл

@ -63,13 +63,6 @@ public abstract class ClassNameHelper {
return helper; return helper;
} }
static void clearCache() {
ClassNameHelper helper = savedNameHelper;
if (helper != null) {
helper.reset();
}
}
/** /**
* Get the current target class file name. * Get the current target class file name.
* <p> * <p>
@ -187,8 +180,6 @@ public abstract class ClassNameHelper {
*/ */
public abstract void setClassName(String initialName); public abstract void setClassName(String initialName);
public abstract void reset();
// Implement class file saving here instead of inside codegen. // Implement class file saving here instead of inside codegen.
private class FileClassRepository implements ClassRepository { private class FileClassRepository implements ClassRepository {

Просмотреть файл

@ -1641,7 +1641,6 @@ public class Context {
if (isCachingEnabled && !cachingEnabled) { if (isCachingEnabled && !cachingEnabled) {
// Caching is being turned off. Empty caches. // Caching is being turned off. Empty caches.
JavaMembers.classTable = new Hashtable(); JavaMembers.classTable = new Hashtable();
ClassNameHelper.clearCache();
} }
isCachingEnabled = cachingEnabled; isCachingEnabled = cachingEnabled;
FunctionObject.setCachingEnabled(cachingEnabled); FunctionObject.setCachingEnabled(cachingEnabled);
@ -2039,12 +2038,8 @@ public class Context {
Interpreter compiler = optimizationLevel == -1 Interpreter compiler = optimizationLevel == -1
? new Interpreter() ? new Interpreter()
: getCompiler(); : getCompiler();
ClassNameHelper nameHelper = optimizationLevel == -1
? null
: ClassNameHelper.get(this);
errorCount = 0; errorCount = 0;
IRFactory irf = compiler.createIRFactory(ts, nameHelper, scope); IRFactory irf = compiler.createIRFactory(this, ts, scope);
Parser p = new Parser(irf); Parser p = new Parser(irf);
Node tree = (Node) p.parse(ts); Node tree = (Node) p.parse(ts);
if (tree == null) if (tree == null)
@ -2071,8 +2066,7 @@ public class Context {
Object result = compiler.compile(this, scope, tree, Object result = compiler.compile(this, scope, tree,
dynamicSecurityDomain, dynamicSecurityDomain,
securityController, securityController);
nameHelper);
return errorCount == 0 ? result : null; return errorCount == 0 ? result : null;
} }

Просмотреть файл

@ -60,8 +60,8 @@ public class Interpreter {
// Last icode // Last icode
END_ICODE = TokenStream.LAST_TOKEN + 6; END_ICODE = TokenStream.LAST_TOKEN + 6;
public IRFactory createIRFactory(TokenStream ts, public IRFactory createIRFactory(Context cx, TokenStream ts,
ClassNameHelper nameHelper, Scriptable scope) Scriptable scope)
{ {
return new IRFactory(ts, scope); return new IRFactory(ts, scope);
} }
@ -72,8 +72,7 @@ public class Interpreter {
public Object compile(Context cx, Scriptable scope, Node tree, public Object compile(Context cx, Scriptable scope, Node tree,
Object securityDomain, Object securityDomain,
SecurityController securityController, SecurityController securityController)
ClassNameHelper nameHelper)
{ {
version = cx.getLanguageVersion(); version = cx.getLanguageVersion();
itsData = new InterpreterData(securityDomain); itsData = new InterpreterData(securityDomain);

Просмотреть файл

@ -184,7 +184,7 @@ public class JavaAdapter extends ScriptableObject {
String adapterName, Class superClass, String adapterName, Class superClass,
Class[] interfaces, Class[] interfaces,
String scriptClassName, String scriptClassName,
ClassNameHelper nameHelper) ClassRepository repository)
throws ClassNotFoundException throws ClassNotFoundException
{ {
ClassFileWriter cfw = new ClassFileWriter(adapterName, ClassFileWriter cfw = new ClassFileWriter(adapterName,
@ -319,11 +319,9 @@ public class JavaAdapter extends ScriptableObject {
} }
byte[] bytes = cfw.toByteArray(); byte[] bytes = cfw.toByteArray();
if (nameHelper != null) { if (repository != null) {
try { try {
if (!nameHelper.getClassRepository().storeClass(adapterName, if (!repository.storeClass(adapterName, bytes, true)) {
bytes, true))
{
return null; return null;
} }
} catch(IOException iox) { } catch(IOException iox) {

Просмотреть файл

@ -56,10 +56,19 @@ public class Codegen extends Interpreter {
public Codegen() { public Codegen() {
} }
public IRFactory createIRFactory(TokenStream ts, private Codegen(Codegen parent) {
ClassNameHelper nameHelper, Scriptable scope) this.nameHelper = parent.nameHelper;
this.classNames = parent.classNames;
}
public IRFactory createIRFactory(Context cx, TokenStream ts,
Scriptable scope)
{ {
return new OptIRFactory(ts, nameHelper, scope); if (nameHelper == null) {
nameHelper = (OptClassNameHelper)ClassNameHelper.get(cx);
classNames = new ObjToIntMap();
}
return new OptIRFactory(ts, scope, this);
} }
public Node transform(Node tree, TokenStream ts, Scriptable scope) { public Node transform(Node tree, TokenStream ts, Scriptable scope) {
@ -69,15 +78,12 @@ public class Codegen extends Interpreter {
public Object compile(Context cx, Scriptable scope, Node tree, public Object compile(Context cx, Scriptable scope, Node tree,
Object securityDomain, Object securityDomain,
SecurityController securityController, SecurityController securityController)
ClassNameHelper cnh)
{ {
ObjArray classFiles = new ObjArray(); ObjArray classFiles = new ObjArray();
ObjArray names = new ObjArray(); ObjArray names = new ObjArray();
String generatedName = null; String generatedName = null;
OptClassNameHelper nameHelper = (OptClassNameHelper) cnh;
Exception e = null; Exception e = null;
Class result = null; Class result = null;
ClassLoader parentLoader = cx.getClass().getClassLoader(); ClassLoader parentLoader = cx.getClass().getClassLoader();
@ -88,22 +94,22 @@ public class Codegen extends Interpreter {
loader = securityController.createClassLoader(parentLoader, loader = securityController.createClassLoader(parentLoader,
securityDomain); securityDomain);
} }
nameHelper.reset();
ClassRepository repository = nameHelper.getClassRepository();
try { try {
if (cx.getOptimizationLevel() > 0) { if (cx.getOptimizationLevel() > 0) {
(new Optimizer()).optimize(tree, cx.getOptimizationLevel()); (new Optimizer()).optimize(tree, cx.getOptimizationLevel());
} }
generatedName = generateCode(tree, names, classFiles, nameHelper); generatedName = generateCode(tree, names, classFiles);
ClassRepository repository = nameHelper.getClassRepository();
for (int i=0; i < names.size(); i++) { for (int i=0; i < names.size(); i++) {
String name = (String) names.get(i); String name = (String) names.get(i);
byte[] classFile = (byte[]) classFiles.get(i); byte[] classFile = (byte[]) classFiles.get(i);
boolean isTopLevel = name.equals(generatedName); boolean isTopLevel = name.equals(generatedName);
try { try {
if (repository.storeClass(name, classFile, isTopLevel)) { if (repository == null
|| repository.storeClass(name, classFile, isTopLevel))
{
Class cl = loader.defineClass(name, classFile); Class cl = loader.defineClass(name, classFile);
if (isTopLevel) { if (isTopLevel) {
result = cl; result = cl;
@ -129,7 +135,7 @@ public class Codegen extends Interpreter {
Class[] interfaces = nameHelper.getTargetImplements(); Class[] interfaces = nameHelper.getTargetImplements();
Class superClass = nameHelper.getTargetExtends(); Class superClass = nameHelper.getTargetExtends();
if (interfaces != null || superClass != null) { if (interfaces != null || superClass != null) {
String name = nameHelper.getJavaScriptClassName(null, true); String name = getScriptClassName(null, true);
ScriptableObject obj = new NativeObject(); ScriptableObject obj = new NativeObject();
for (Node cursor = tree.getFirstChild(); cursor != null; for (Node cursor = tree.getFirstChild(); cursor != null;
cursor = cursor.getNext()) cursor = cursor.getNext())
@ -147,7 +153,7 @@ public class Codegen extends Interpreter {
superClass, superClass,
interfaces, interfaces,
generatedName, generatedName,
nameHelper); repository);
} catch (ClassNotFoundException exn) { } catch (ClassNotFoundException exn) {
// should never happen // should never happen
throw new Error(exn.toString()); throw new Error(exn.toString());
@ -184,6 +190,23 @@ public class Codegen extends Interpreter {
} }
} }
String getScriptClassName(String functionName, boolean primary)
{
String result = nameHelper.getScriptClassName(functionName, primary);
// We wish to produce unique class names between calls to reset()
// we disregard case since we may write the class names to file
// systems that are case insensitive
String lowerResult = result.toLowerCase();
String base = lowerResult;
int count = 0;
while (classNames.has(lowerResult)) {
lowerResult = base + ++count;
}
classNames.put(lowerResult, 0);
return count == 0 ? result : (result + count);
}
void addByteCode(byte theOpcode) void addByteCode(byte theOpcode)
{ {
classFile.add(theOpcode); classFile.add(theOpcode);
@ -337,15 +360,14 @@ public class Codegen extends Interpreter {
} }
public String generateCode(Node tree, ObjArray names, ObjArray classFiles, public String generateCode(Node tree, ObjArray names, ObjArray classFiles)
OptClassNameHelper nameHelper)
{ {
ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP); ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP);
if (fns != null) { if (fns != null) {
for (int i = 0; i != fns.size(); ++i) { for (int i = 0; i != fns.size(); ++i) {
OptFunctionNode fn = (OptFunctionNode) fns.get(i); OptFunctionNode fn = (OptFunctionNode) fns.get(i);
Codegen codegen = new Codegen(); Codegen codegen = new Codegen(this);
codegen.generateCode(fn, names, classFiles, nameHelper); codegen.generateCode(fn, names, classFiles);
} }
} }
@ -456,7 +478,7 @@ public class Codegen extends Interpreter {
vars = (VariableTable) tree.getProp(Node.VARS_PROP); vars = (VariableTable) tree.getProp(Node.VARS_PROP);
boolean isPrimary = nameHelper.getTargetExtends() == null && boolean isPrimary = nameHelper.getTargetExtends() == null &&
nameHelper.getTargetImplements() == null; nameHelper.getTargetImplements() == null;
this.name = nameHelper.getJavaScriptClassName(null, isPrimary); this.name = getScriptClassName(null, isPrimary);
classFile = new ClassFileWriter(name, superClassName, itsSourceFile); classFile = new ClassFileWriter(name, superClassName, itsSourceFile);
classFile.addInterface("org/mozilla/javascript/Script"); classFile.addInterface("org/mozilla/javascript/Script");
generateScriptCtor(cx, tree); generateScriptCtor(cx, tree);
@ -3691,6 +3713,9 @@ public class Codegen extends Interpreter {
"org.mozilla.javascript.NativeFunction"; "org.mozilla.javascript.NativeFunction";
private static final String scriptSuperClassName = private static final String scriptSuperClassName =
"org.mozilla.javascript.NativeScript"; "org.mozilla.javascript.NativeScript";
private OptClassNameHelper nameHelper;
private ObjToIntMap classNames;
private String superClassName; private String superClassName;
private String superClassSlashName; private String superClassSlashName;
private String name; private String name;

Просмотреть файл

@ -48,12 +48,8 @@ public class OptClassNameHelper extends ClassNameHelper {
setClassName(null); setClassName(null);
} }
public synchronized void reset() { synchronized String getScriptClassName(String functionName,
classNames = null; boolean primary)
}
public synchronized String getJavaScriptClassName(String functionName,
boolean primary)
{ {
StringBuffer s = new StringBuffer(); StringBuffer s = new StringBuffer();
if (packageName != null && packageName.length() > 0) { if (packageName != null && packageName.length() > 0) {
@ -73,26 +69,10 @@ public class OptClassNameHelper extends ClassNameHelper {
s.append(++serial); s.append(++serial);
} }
} else { } else {
synchronized(defaultRepository) { s.append(globalSerial++);
s.append(globalSerial++);
}
} }
// We wish to produce unique class names between calls to reset() return s.toString();
// we disregard case since we may write the class names to file
// systems that are case insensitive
String result = s.toString();
String lowerResult = result.toLowerCase();
String base = lowerResult;
int count = 0;
if (classNames == null)
classNames = new Hashtable();
while (classNames.get(lowerResult) != null) {
lowerResult = base + ++count;
}
classNames.put(lowerResult, Boolean.TRUE);
return count == 0 ? result : (result + count);
} }
public String getTargetPackage() { public String getTargetPackage() {
@ -130,7 +110,7 @@ public class OptClassNameHelper extends ClassNameHelper {
} else { } else {
packageName = "org.mozilla.javascript.gen"; packageName = "org.mozilla.javascript.gen";
this.initialName = "c"; this.initialName = "c";
classRepository = defaultRepository; classRepository = null;
appendFunctionName = false; appendFunctionName = false;
} }
serial = fserial = 0; serial = fserial = 0;
@ -141,24 +121,15 @@ public class OptClassNameHelper extends ClassNameHelper {
} }
public void setClassRepository(ClassRepository classRepository) { public void setClassRepository(ClassRepository classRepository) {
this.classRepository = classRepository != null ? classRepository : defaultRepository; this.classRepository = classRepository;
} }
private boolean appendFunctionName; private boolean appendFunctionName;
private String packageName; private String packageName;
private String initialName; private String initialName;
private static int globalSerial=1; private int globalSerial=1;
private int serial, fserial; private int serial, fserial;
private Class targetExtends; private Class targetExtends;
private Class[] targetImplements; private Class[] targetImplements;
private ClassRepository classRepository; private ClassRepository classRepository;
private Hashtable classNames;
static class DefaultRepository implements ClassRepository {
public boolean storeClass(String name, byte[] bytes, boolean tl) {
return true;
}
}
private static ClassRepository defaultRepository = new DefaultRepository();
} }

Просмотреть файл

@ -41,12 +41,10 @@ import java.util.*;
public class OptFunctionNode extends FunctionNode { public class OptFunctionNode extends FunctionNode {
public OptFunctionNode(String name, Node statements, public OptFunctionNode(String name, Node statements, String className)
ClassNameHelper nameHelper)
{ {
super(name, statements); super(name, statements);
OptClassNameHelper nh = (OptClassNameHelper) nameHelper; itsClassName = className;
itsClassName = nh.getJavaScriptClassName(name, false);
} }
public String getDirectCallParameterSignature() { public String getDirectCallParameterSignature() {

Просмотреть файл

@ -44,17 +44,18 @@ import org.mozilla.javascript.*;
* @see IRFactory * @see IRFactory
* @author Norris Boyd * @author Norris Boyd
*/ */
public class OptIRFactory extends IRFactory { class OptIRFactory extends IRFactory {
public OptIRFactory(TokenStream ts, ClassNameHelper nameHelper, Scriptable scope) { OptIRFactory(TokenStream ts, Scriptable scope, Codegen compiler) {
super(ts, scope); super(ts, scope);
this.nameHelper = nameHelper; this.compiler = compiler;
} }
public Object createFunctionNode(String name, Object statements) public Object createFunctionNode(String name, Object statements)
{ {
return new OptFunctionNode(name, (Node)statements, nameHelper); String className = compiler.getScriptClassName(name, false);
return new OptFunctionNode(name, (Node)statements, className);
} }
private ClassNameHelper nameHelper; private Codegen compiler;
} }