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

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

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

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

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

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

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

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

@ -56,10 +56,19 @@ public class Codegen extends Interpreter {
public Codegen() {
}
public IRFactory createIRFactory(TokenStream ts,
ClassNameHelper nameHelper, Scriptable scope)
private Codegen(Codegen parent) {
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) {
@ -69,15 +78,12 @@ public class Codegen extends Interpreter {
public Object compile(Context cx, Scriptable scope, Node tree,
Object securityDomain,
SecurityController securityController,
ClassNameHelper cnh)
SecurityController securityController)
{
ObjArray classFiles = new ObjArray();
ObjArray names = new ObjArray();
String generatedName = null;
OptClassNameHelper nameHelper = (OptClassNameHelper) cnh;
Exception e = null;
Class result = null;
ClassLoader parentLoader = cx.getClass().getClassLoader();
@ -88,22 +94,22 @@ public class Codegen extends Interpreter {
loader = securityController.createClassLoader(parentLoader,
securityDomain);
}
nameHelper.reset();
ClassRepository repository = nameHelper.getClassRepository();
try {
if (cx.getOptimizationLevel() > 0) {
(new Optimizer()).optimize(tree, cx.getOptimizationLevel());
}
generatedName = generateCode(tree, names, classFiles, nameHelper);
ClassRepository repository = nameHelper.getClassRepository();
generatedName = generateCode(tree, names, classFiles);
for (int i=0; i < names.size(); i++) {
String name = (String) names.get(i);
byte[] classFile = (byte[]) classFiles.get(i);
boolean isTopLevel = name.equals(generatedName);
try {
if (repository.storeClass(name, classFile, isTopLevel)) {
if (repository == null
|| repository.storeClass(name, classFile, isTopLevel))
{
Class cl = loader.defineClass(name, classFile);
if (isTopLevel) {
result = cl;
@ -129,7 +135,7 @@ public class Codegen extends Interpreter {
Class[] interfaces = nameHelper.getTargetImplements();
Class superClass = nameHelper.getTargetExtends();
if (interfaces != null || superClass != null) {
String name = nameHelper.getJavaScriptClassName(null, true);
String name = getScriptClassName(null, true);
ScriptableObject obj = new NativeObject();
for (Node cursor = tree.getFirstChild(); cursor != null;
cursor = cursor.getNext())
@ -147,7 +153,7 @@ public class Codegen extends Interpreter {
superClass,
interfaces,
generatedName,
nameHelper);
repository);
} catch (ClassNotFoundException exn) {
// should never happen
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)
{
classFile.add(theOpcode);
@ -337,15 +360,14 @@ public class Codegen extends Interpreter {
}
public String generateCode(Node tree, ObjArray names, ObjArray classFiles,
OptClassNameHelper nameHelper)
public String generateCode(Node tree, ObjArray names, ObjArray classFiles)
{
ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP);
if (fns != null) {
for (int i = 0; i != fns.size(); ++i) {
OptFunctionNode fn = (OptFunctionNode) fns.get(i);
Codegen codegen = new Codegen();
codegen.generateCode(fn, names, classFiles, nameHelper);
Codegen codegen = new Codegen(this);
codegen.generateCode(fn, names, classFiles);
}
}
@ -456,7 +478,7 @@ public class Codegen extends Interpreter {
vars = (VariableTable) tree.getProp(Node.VARS_PROP);
boolean isPrimary = nameHelper.getTargetExtends() == null &&
nameHelper.getTargetImplements() == null;
this.name = nameHelper.getJavaScriptClassName(null, isPrimary);
this.name = getScriptClassName(null, isPrimary);
classFile = new ClassFileWriter(name, superClassName, itsSourceFile);
classFile.addInterface("org/mozilla/javascript/Script");
generateScriptCtor(cx, tree);
@ -3691,6 +3713,9 @@ public class Codegen extends Interpreter {
"org.mozilla.javascript.NativeFunction";
private static final String scriptSuperClassName =
"org.mozilla.javascript.NativeScript";
private OptClassNameHelper nameHelper;
private ObjToIntMap classNames;
private String superClassName;
private String superClassSlashName;
private String name;

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

@ -48,12 +48,8 @@ public class OptClassNameHelper extends ClassNameHelper {
setClassName(null);
}
public synchronized void reset() {
classNames = null;
}
public synchronized String getJavaScriptClassName(String functionName,
boolean primary)
synchronized String getScriptClassName(String functionName,
boolean primary)
{
StringBuffer s = new StringBuffer();
if (packageName != null && packageName.length() > 0) {
@ -73,26 +69,10 @@ public class OptClassNameHelper extends ClassNameHelper {
s.append(++serial);
}
} else {
synchronized(defaultRepository) {
s.append(globalSerial++);
}
s.append(globalSerial++);
}
// 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 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);
return s.toString();
}
public String getTargetPackage() {
@ -130,7 +110,7 @@ public class OptClassNameHelper extends ClassNameHelper {
} else {
packageName = "org.mozilla.javascript.gen";
this.initialName = "c";
classRepository = defaultRepository;
classRepository = null;
appendFunctionName = false;
}
serial = fserial = 0;
@ -141,24 +121,15 @@ public class OptClassNameHelper extends ClassNameHelper {
}
public void setClassRepository(ClassRepository classRepository) {
this.classRepository = classRepository != null ? classRepository : defaultRepository;
this.classRepository = classRepository;
}
private boolean appendFunctionName;
private String packageName;
private String initialName;
private static int globalSerial=1;
private int globalSerial=1;
private int serial, fserial;
private Class targetExtends;
private Class[] targetImplements;
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 OptFunctionNode(String name, Node statements,
ClassNameHelper nameHelper)
public OptFunctionNode(String name, Node statements, String className)
{
super(name, statements);
OptClassNameHelper nh = (OptClassNameHelper) nameHelper;
itsClassName = nh.getJavaScriptClassName(name, false);
itsClassName = className;
}
public String getDirectCallParameterSignature() {

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

@ -44,17 +44,18 @@ import org.mozilla.javascript.*;
* @see IRFactory
* @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);
this.nameHelper = nameHelper;
this.compiler = compiler;
}
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;
}