Simpler class mangling, and discourage usage of className.

This commit is contained in:
Michael Bebenita 2015-03-11 17:41:01 -07:00
Родитель ad99e0431b
Коммит 7a129e8c6b
9 изменённых файлов: 78 добавлений и 66 удалений

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

@ -106,7 +106,7 @@ module J2ME {
var argArray = [];
function buildExceptionLog(ex, stackTrace) {
var className = ex.klass.classInfo.className;
var className = ex.klass.classInfo.getClassNameSlow();
var classInfo: ClassInfo = ex.klass.classInfo;
var detailMessage = util.fromJavaString(classInfo.getFieldByName(toUTF8("detailMessage"), toUTF8("Ljava/lang/String;"), false).get(ex));
return className + ": " + (detailMessage || "") + "\n" + stackTrace.map(function(entry) {
@ -147,9 +147,9 @@ module J2ME {
}
var classInfo = frame.methodInfo.classInfo;
if (classInfo && classInfo.className) {
if (classInfo && classInfo.getClassNameSlow()) {
stackTrace.push({
className: classInfo.className,
className: classInfo.getClassNameSlow(),
methodName: frame.methodInfo.name,
methodSignature: frame.methodInfo.signature,
offset: frame.pc
@ -1022,8 +1022,8 @@ module J2ME {
object = stack[stack.length - 1];
if (object && !isAssignableTo(object.klass, classInfo.klass)) {
throw $.newClassCastException(
object.klass.classInfo.className + " is not assignable to " +
classInfo.className);
object.klass.classInfo.getClassNameSlow() + " is not assignable to " +
classInfo.getClassNameSlow());
}
break;
case Bytecodes.INSTANCEOF:
@ -1134,7 +1134,7 @@ module J2ME {
var calleeMethodInfo = mi.classInfo.constantPool.resolveMethod(index, isStatic);
// Fast path for some of the most common interpreter call targets.
if (calleeMethodInfo.classInfo.className === "java/lang/Object" &&
if (calleeMethodInfo.classInfo.getClassNameSlow() === "java/lang/Object" &&
calleeMethodInfo.name === "<init>") {
stack.pop();
continue;

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

@ -89,7 +89,7 @@ module J2ME {
if (!result) {
result = classInfo.subClasses.length === 0;
}
// console.log(classInfo.className + " is final class " + result);
// console.log(classInfo.getClassNameSlow() + " is final class " + result);
return result;
*/
}

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

@ -814,31 +814,31 @@ module J2ME {
classInfo = (<ArrayClassInfo>classInfo).elementClass;
}
if (!CLASSES.isPreInitializedClass(classInfo)) {
if (this.target === CompilationTarget.Runtime && $.initialized[classInfo.className]) {
var message = "Optimized ClassInitializationCheck: " + classInfo.className + ", is already initialized.";
if (this.target === CompilationTarget.Runtime && $.initialized[classInfo.getClassNameSlow()]) {
var message = "Optimized ClassInitializationCheck: " + classInfo.getClassNameSlow() + ", is already initialized.";
baselineCounter && baselineCounter.count(message);
} else if (this.initializedClasses[classInfo.className]) {
var message = "Optimized ClassInitializationCheck: " + classInfo.className + ", block redundant.";
} else if (this.initializedClasses[classInfo.getClassNameSlow()]) {
var message = "Optimized ClassInitializationCheck: " + classInfo.getClassNameSlow() + ", block redundant.";
emitDebugInfoComments && this.blockEmitter.writeLn("// " + message);
baselineCounter && baselineCounter.count(message);
} else if (classInfo === this.methodInfo.classInfo) {
var message = "Optimized ClassInitializationCheck: " + classInfo.className + ", self access.";
var message = "Optimized ClassInitializationCheck: " + classInfo.getClassNameSlow() + ", self access.";
emitDebugInfoComments && this.blockEmitter.writeLn("// " + message);
baselineCounter && baselineCounter.count(message);
} else if (!classInfo.isInterface && this.methodInfo.classInfo.isAssignableTo(classInfo)) {
var message = "Optimized ClassInitializationCheck: " + classInfo.className + ", base access.";
var message = "Optimized ClassInitializationCheck: " + classInfo.getClassNameSlow() + ", base access.";
emitDebugInfoComments && this.blockEmitter.writeLn("// " + message);
baselineCounter && baselineCounter.count(message);
} else {
baselineCounter && baselineCounter.count("ClassInitializationCheck: " + classInfo.className);
this.blockEmitter.writeLn("if ($.initialized[\"" + classInfo.className + "\"] === undefined) { " + this.runtimeClassObject(classInfo) + ".initialize(); }");
baselineCounter && baselineCounter.count("ClassInitializationCheck: " + classInfo.getClassNameSlow());
this.blockEmitter.writeLn("if ($.initialized[\"" + classInfo.getClassNameSlow() + "\"] === undefined) { " + this.runtimeClassObject(classInfo) + ".initialize(); }");
if (canStaticInitializerYield(classInfo)) {
this.emitUnwind(this.blockEmitter, String(this.pc), String(this.pc));
} else {
emitCompilerAssertions && this.emitNoUnwindAssertion();
}
}
this.initializedClasses[classInfo.className] = true;
this.initializedClasses[classInfo.getClassNameSlow()] = true;
}
}

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

@ -194,7 +194,7 @@ module J2ME {
}
function classNameWithDots(classInfo: ClassInfo) {
return classInfo.className.replace(/\//g, '.');
return classInfo.getClassNameSlow().replace(/\//g, '.');
}
export function emitMethodMetaData(emitter: Emitter, methodInfo: MethodInfo, compiledMethodInfo: CompiledMethodInfo) {
@ -215,7 +215,7 @@ module J2ME {
var mangledClassName = classInfo.mangledName;
emitter.writer.writeLn(mangledClassName + ".classSymbols = [" + referencedClasses.map(classInfo => {
return quote(classInfo.className);
return quote(classInfo.getClassNameSlow());
}).join(", ") + "];");
}
@ -372,14 +372,14 @@ module J2ME {
return false;
}
for (var i = 0; i < list.length; i++) {
if (list[i].className === superClass.className) {
if (list[i].getClassNameSlow() === superClass.getClassNameSlow()) {
return true;
}
}
for (var j = 0; j < interfaces; j++) {
for (var i = 0; i < list.length; i++) {
if (list[i].className === interfaces[j].className) {
if (list[i].getClassNameSlow() === interfaces[j].getClassNameSlow()) {
return true;
}
}
@ -416,7 +416,7 @@ module J2ME {
var classInfo = filteredClassInfoList[i];
if (emitter.debugInfo) {
writer.writeLn("// " + classInfo.className + (classInfo.superClass ? " extends " + classInfo.superClass.className : ""));
writer.writeLn("// " + classInfo.getClassNameSlow() + (classInfo.superClass ? " extends " + classInfo.superClass.getClassNameSlow() : ""));
}
// Don't compile interfaces.
if (classInfo.isInterface) {

4
jsc.ts
Просмотреть файл

@ -244,9 +244,9 @@ module J2ME {
}
function classFilter(classInfo: ClassInfo): boolean {
if (classNameList) {
return classNameList.indexOf(classInfo.className) >= 0;
return classNameList.indexOf(classInfo.getClassNameSlow()) >= 0;
} else if (classFilterOption.value) {
return !!classInfo.className.match(classFilterOption.value);
return !!classInfo.getClassNameSlow().match(classFilterOption.value);
}
return false;
}

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

@ -285,9 +285,9 @@ Native["java/lang/Class.getSuperclass.()Ljava/lang/Class;"] = function() {
Native["java/lang/Class.invoke_clinit.()V"] = function() {
var classInfo = this.runtimeKlass.templateKlass.classInfo;
var className = classInfo.className;
var className = classInfo.getClassNameSlow();
var clinit = classInfo.staticInitializer;
if (clinit && clinit.classInfo.className === className) {
if (clinit && clinit.classInfo.getClassNameSlow() === className) {
$.ctx.executeFrames([Frame.create(clinit, [], 0)]);
}
};
@ -301,7 +301,7 @@ Native["java/lang/Class.init9.()V"] = function() {
};
Native["java/lang/Class.getName.()Ljava/lang/String;"] = function() {
return J2ME.newString(this.runtimeKlass.templateKlass.classInfo.className.replace(/\//g, "."));
return J2ME.newString(this.runtimeKlass.templateKlass.classInfo.getClassNameSlow().replace(/\//g, "."));
};
Native["java/lang/Class.forName0.(Ljava/lang/String;)V"] = function(name) {
@ -401,7 +401,7 @@ Native["java/lang/Throwable.fillInStackTrace.()V"] = function() {
if (!methodName)
return;
var classInfo = methodInfo.classInfo;
var className = classInfo.className;
var className = classInfo.getClassNameSlow();
this.stackTrace.unshift({ className: className, methodName: methodName, methodSignature: methodInfo.signature, offset: frame.bci });
}.bind(this));
};
@ -414,7 +414,7 @@ Native["java/lang/Throwable.obtainBackTrace.()Ljava/lang/Object;"] = function()
var methodNames = J2ME.newObjectArray(depth);
var offsets = J2ME.newIntArray(depth);
this.stackTrace.forEach(function(e, n) {
classNames[n] = J2ME.newString(e.className);
classNames[n] = J2ME.newString(e.getClassNameSlow());
methodNames[n] = J2ME.newString(e.methodName);
offsets[n] = e.offset;
});

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

@ -132,9 +132,9 @@ module J2ME {
loadClassBytes(bytes: Uint8Array): ClassInfo {
enterTimeline("loadClassBytes");
var classInfo = new ClassInfo(bytes);
leaveTimeline("loadClassBytes", {className: classInfo.className});
loadWriter && loadWriter.writeLn(classInfo.className + " -> " + classInfo.superClassName + ";");
this.classes[classInfo.className] = classInfo;
leaveTimeline("loadClassBytes", {className: classInfo.getClassNameSlow()});
loadWriter && loadWriter.writeLn(classInfo.getClassNameSlow() + " -> " + classInfo.superClassName + ";");
this.classes[classInfo.getClassNameSlow()] = classInfo;
return classInfo;
}

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

@ -443,7 +443,7 @@ module J2ME {
r = this.resolved[i] = classInfo.getMethodByName(name, type);
}
if (!r) {
throw $.newRuntimeException(classInfo.className + "." + fromUTF8(name) + "." + fromUTF8(type) + " not found");
throw $.newRuntimeException(classInfo.getClassNameSlow() + "." + fromUTF8(name) + "." + fromUTF8(type) + " not found");
}
break;
default:
@ -577,6 +577,14 @@ module J2ME {
return methodInfo.classInfo.mangledName + "_" + methodInfo.index;
}
export function mangleClass(classInfo: ClassInfo): string {
var name = StringUtilities.variableLengthEncodeInt32(hashUTF8String(classInfo.utf8Name));
// Also use the length for some more precision.
name += StringUtilities.toEncoding(classInfo.utf8Name.length & 0x3f);
return "$" + name;
}
export function mangleMethod(methodInfo: MethodInfo) {
// TODO: Get rid of JS strings in the computation of the hash.
var name = methodInfo.name + "_" + hashStringToString(methodInfo.signature);
@ -629,7 +637,6 @@ module J2ME {
this.vTableIndex = -1;
// Lazify;
this.implKey = this.classInfo.className + "." + this.name + "." + this.signature;
this.state = MethodState.Cold;
// TODO: Make this lazy.
@ -681,7 +688,7 @@ module J2ME {
}
get implKey(): string {
return this.classInfo.className + "." + this.name + "." + this.signature;
return this.classInfo.getClassNameSlow() + "." + this.name + "." + this.signature;
}
get isNative(): boolean {
@ -847,7 +854,7 @@ module J2ME {
}
}
get className(): string {
getClassNameSlow(): string {
return this._name || (this._name = ByteStream.readString(this.utf8Name));
}
@ -872,7 +879,7 @@ module J2ME {
}
private trace(writer: IndentingWriter) {
writer.enter(this.className + " VTable:");
writer.enter(this.getClassNameSlow() + " VTable:");
for (var i = 0; i < this.vTable.length; i++) {
writer.writeLn(i + ": " + ByteStream.readString(this.vTable[i].utf8Name) + "." + ByteStream.readString(this.vTable[i].utf8Signature));
}
@ -1224,7 +1231,7 @@ module J2ME {
super(null);
this.elementClass = elementClass;
this.superClass = CLASSES.java_lang_Object;
this.superClassName = CLASSES.java_lang_Object.className;
this.superClassName = CLASSES.java_lang_Object.getClassNameSlow();
}
isAssignableTo(toClass: ClassInfo): boolean {
@ -1250,7 +1257,7 @@ module J2ME {
} else {
this.utf8Name = strcat3(UTF8.OpenBracketL, elementClass.utf8Name, UTF8.Semicolon);
}
this.mangledName = mangleClassName(this.className);
this.mangledName = mangleClassName(this.getClassNameSlow());
}
}

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

@ -316,6 +316,18 @@ module J2ME {
return hash;
}
export function hashUTF8String(s: Uint8Array): number {
var hash = HashUtilities.hashBytesTo32BitsMurmur(s, 0, s.length);
if (!release) { // Check to see that no collisions have ever happened.
if (hashMap[hash] && hashMap[hash] !== s) {
assert(false, "This is very bad.")
}
hashMap[hash] = s;
}
return hash;
}
function isIdentifierChar(c: number): boolean {
return (c >= 97 && c <= 122) || // a .. z
(c >= 65 && c <= 90) || // A .. Z
@ -407,13 +419,6 @@ module J2ME {
return "$" + hashStringToString(name);
}
export function mangleClass(classInfo: ClassInfo) {
if (classInfo.mangledName) {
return classInfo.mangledName;
}
return mangleClassName(classInfo.className);
}
/**
* This class is abstract and should never be initialized. It only acts as a template for
* actual runtime objects.
@ -473,7 +478,7 @@ module J2ME {
* different threads that need trigger the Class.initialize() code so they block.
*/
setClassInitialized(runtimeKlass: RuntimeKlass) {
var className = runtimeKlass.templateKlass.classInfo.className;
var className = runtimeKlass.templateKlass.classInfo.getClassNameSlow();
this.initialized[className] = true;
}
@ -862,7 +867,7 @@ module J2ME {
release || assert(!runtimeKlass.classObject);
runtimeKlass.classObject = <java.lang.Class><any>new Klasses.java.lang.Class();
runtimeKlass.classObject.runtimeKlass = runtimeKlass;
var className = runtimeKlass.templateKlass.classInfo.className;
var className = runtimeKlass.templateKlass.classInfo.getClassNameSlow();
if (className === "java/lang/Object" ||
className === "java/lang/Class" ||
className === "java/lang/String" ||
@ -898,11 +903,11 @@ module J2ME {
* adds it to the runtime.
*/
export function registerKlass(klass: Klass, classInfo: ClassInfo) {
linkWriter && linkWriter.writeLn("Registering Klass: " + classInfo.className);
linkWriter && linkWriter.writeLn("Registering Klass: " + classInfo.getClassNameSlow());
Object.defineProperty(RuntimeTemplate.prototype, classInfo.mangledName, {
configurable: true,
get: function () {
linkWriter && linkWriter.writeLn("Creating Runtime Klass: " + classInfo.className);
linkWriter && linkWriter.writeLn("Creating Runtime Klass: " + classInfo.getClassNameSlow());
release || assert(!(klass instanceof RuntimeKlass));
var runtimeKlass = new RuntimeKlass(klass);
initializeClassObject(runtimeKlass);
@ -982,12 +987,12 @@ module J2ME {
J2ME.emitKlass(emitter, classInfo);
(1, eval)(source);
leaveTimeline("emitKlassConstructor");
// consoleWriter.writeLn("Synthesizing Klass: " + classInfo.className);
// consoleWriter.writeLn("Synthesizing Klass: " + classInfo.getClassNameSlow());
// consoleWriter.writeLn(source);
klass = <Klass>jsGlobal[mangledName];
release || assert(klass, mangledName);
klass.toString = function () {
return "[Synthesized Klass " + classInfo.className + "]";
return "[Synthesized Klass " + classInfo.getClassNameSlow() + "]";
};
return klass;
}
@ -1006,11 +1011,11 @@ module J2ME {
var klass = findKlass(classInfo);
if (klass) {
release || assert (!classInfo.isInterface, "Interfaces should not be compiled.");
linkWriter && linkWriter.greenLn("Found Compiled Klass: " + classInfo.className);
linkWriter && linkWriter.greenLn("Found Compiled Klass: " + classInfo.getClassNameSlow());
release || assert(!classInfo.klass);
classInfo.klass = klass;
klass.toString = function () {
return "[Compiled Klass " + classInfo.className + "]";
return "[Compiled Klass " + classInfo.getClassNameSlow() + "]";
};
if (klass.classSymbols) {
registerKlassSymbols(klass.classSymbols);
@ -1061,7 +1066,7 @@ module J2ME {
};
klass.isInterfaceKlass = true;
klass.toString = function () {
return "[Interface Klass " + classInfo.className + "]";
return "[Interface Klass " + classInfo.getClassNameSlow() + "]";
};
setKlassSymbol(mangledName, klass);
} else if (classInfo instanceof ArrayClassInfo) {
@ -1076,7 +1081,7 @@ module J2ME {
Debug.unexpected("Should never be instantiated.")
};
klass.toString = function () {
return "[Primitive Klass " + classInfo.className + "]";
return "[Primitive Klass " + classInfo.getClassNameSlow() + "]";
};
} else {
klass = emitKlassConstructor(classInfo, mangledName);
@ -1085,7 +1090,7 @@ module J2ME {
}
export function makeArrayKlassConstructor(elementKlass: Klass): Klass {
var klass = <Klass><any> getArrayConstructor(elementKlass.classInfo.className);
var klass = <Klass><any> getArrayConstructor(elementKlass.classInfo.getClassNameSlow());
if (!klass) {
klass = <Klass><any> function (size: number) {
var array = createEmptyObjectArray(size);
@ -1132,10 +1137,10 @@ module J2ME {
case PrimitiveClassInfo.S: Klasses.short = klass; break;
case PrimitiveClassInfo.I: Klasses.int = klass; break;
case PrimitiveClassInfo.J: Klasses.long = klass; break;
default: J2ME.Debug.assertUnreachable("linking primitive " + classInfo.className)
default: J2ME.Debug.assertUnreachable("linking primitive " + classInfo.getClassNameSlow())
}
} else {
switch (classInfo.className) {
switch (classInfo.getClassNameSlow()) {
case "java/lang/Object": Klasses.java.lang.Object = klass; break;
case "java/lang/Class" : Klasses.java.lang.Class = klass; break;
case "java/lang/String": Klasses.java.lang.String = klass; break;
@ -1163,7 +1168,7 @@ module J2ME {
case "java/io/UTFDataFormatException": Klasses.java.io.UTFDataFormatException = klass; break;
}
}
linkWriter && linkWriter.writeLn("Link: " + classInfo.className + " -> " + klass);
linkWriter && linkWriter.writeLn("Link: " + classInfo.getClassNameSlow() + " -> " + klass);
enterTimeline("linkKlassMethods");
linkKlassMethods(classInfo.klass);
@ -1180,7 +1185,7 @@ module J2ME {
}
function findNativeMethodBinding(methodInfo: MethodInfo) {
var classBindings = Bindings[methodInfo.classInfo.className];
var classBindings = Bindings[methodInfo.classInfo.getClassNameSlow()];
if (classBindings && classBindings.native) {
var method = classBindings.native[methodInfo.name + "." + methodInfo.signature];
if (method) {
@ -1306,7 +1311,7 @@ module J2ME {
function linkKlassFields(klass: Klass) {
var classInfo = klass.classInfo;
var fields = classInfo.getFields();
var classBindings = Bindings[klass.classInfo.className];
var classBindings = Bindings[klass.classInfo.getClassNameSlow()];
if (classBindings && classBindings.fields) {
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
@ -1358,7 +1363,7 @@ module J2ME {
}
linkWriter && linkWriter.enter("Link Klass Methods: " + klass);
var methods = klass.classInfo.getMethods();
var classBindings = Bindings[klass.classInfo.className];
var classBindings = Bindings[klass.classInfo.getClassNameSlow()];
for (var i = 0; i < methods.length; i++) {
var methodInfo = methods[i];
if (methodInfo.isAbstract) {
@ -1600,7 +1605,7 @@ module J2ME {
"\n}";
codeWriter && codeWriter.writeLns(source);
var referencedClasses = compiledMethod.referencedClasses.map(function(v) { return v.className });
var referencedClasses = compiledMethod.referencedClasses.map(function(v) { return v.getClassNameSlow() });
if (enableCompiledMethodCache) {
CompiledMethodCache.put({
@ -1759,7 +1764,7 @@ module J2ME {
if (elementKlass.arrayKlass) {
return elementKlass.arrayKlass;
}
var className = elementKlass.classInfo.className;
var className = elementKlass.classInfo.getClassNameSlow();
if (!(elementKlass.classInfo instanceof PrimitiveClassInfo) && className[0] !== "[") {
className = "L" + className + ";";
}
@ -1790,7 +1795,7 @@ module J2ME {
if (value instanceof Klasses.java.lang.String) {
return "\"" + value.str + "\"";
}
return "[" + value.klass.classInfo.className + hashcode + "]";
return "[" + value.klass.classInfo.getClassNameSlow() + hashcode + "]";
}
export function fromJavaString(value: java.lang.String): string {
@ -1866,7 +1871,7 @@ module J2ME {
}
export function classInitCheck(classInfo: ClassInfo) {
if (classInfo instanceof ArrayClassInfo || $.initialized[classInfo.className]) {
if (classInfo instanceof ArrayClassInfo || $.initialized[classInfo.getClassNameSlow()]) {
return;
}
linkKlass(classInfo);