Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.codename1.tools.translator.ByteCodeClass Maven / Gradle / Ivy
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codename1.tools.translator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Parsed class file
*
* @author Shai Almog
*/
public class ByteCodeClass {
/**
* @param isAnonymous the isAnonymous to set
*/
public void setIsAnonymous(boolean isAnonymous) {
this.isAnonymous = isAnonymous;
}
/**
* @param isSynthetic the isSynthetic to set
*/
public void setIsSynthetic(boolean isSynthetic) {
this.isSynthetic = isSynthetic;
}
/**
* @param isAnnotation the isAnnotation to set
*/
public void setIsAnnotation(boolean isAnnotation) {
this.isAnnotation = isAnnotation;
}
private List fullFieldList;
private List staticFieldList;
private Set dependsClassesInterfaces = new TreeSet();
private Set exportsClassesInterfaces = new TreeSet();
private List methods = new ArrayList();
private List fields = new ArrayList();
private String clsName;
private String originalClassName;
private String baseClass;
private List baseInterfaces;
private boolean isInterface;
private boolean isAbstract;
private boolean isSynthetic;
private boolean isAnnotation;
private boolean isAnonymous;
private boolean eliminated;
private static boolean saveUnitTests;
private boolean isUnitTest;
private static Set arrayTypes = new TreeSet();
private ByteCodeClass baseClassObject;
private List baseInterfacesObject;
List virtualMethodList;
private String sourceFile;
private int classOffset;
private boolean marked;
private static ByteCodeClass mainClass;
private boolean finalClass;
private boolean isEnum;
private static Set writableFields = new HashSet();
/**
*
* @param clsName Class name with mangling. e.g. java_lang_String
* @param originalClassName Classname without mangling. e.g. java/lang/String
*/
public ByteCodeClass(String clsName, String originalClassName) {
this.clsName = clsName;
this.originalClassName = originalClassName;
}
/**
* Checks if this class has been eliminated.
* @return
*/
public boolean isEliminated() {
return eliminated;
}
/**
* Marks class as eliminated. Will recursively set all class methods
* as eliminated too.
* @param eliminated True to set eliminated.
* @return Number of methods that were newly marked as eliminated by this call.
*/
public int setEliminated(boolean eliminated) {
int nfound = 0;
if (this.eliminated) return nfound;
this.eliminated = eliminated;
if (eliminated) {
for (BytecodeMethod m : methods) {
if (!m.isEliminated()) {
m.setEliminated(true);
nfound++;
}
}
}
return nfound;
}
/**
* Class name in original JVM format: e.g. java/lang/String
* @return
*/
public String getOriginalClassName() {
return originalClassName;
}
static ByteCodeClass getMainClass() {
return mainClass;
}
static void setSaveUnitTests(boolean save) {
saveUnitTests = save;
}
public void addMethod(BytecodeMethod m) {
if(m.isMain()) {
if (mainClass == null) {
mainClass = this;
} else {
throw new RuntimeException("Multiple main classes: "+mainClass.clsName+" and "+this.clsName);
}
}
m.setSourceFile(sourceFile);
m.setForceVirtual(isInterface);
methods.add(m);
}
public void addField(ByteCodeField m) {
fields.add(m);
}
public String generateCSharpCode() {
return "";
}
public void addWritableField(String field) {
writableFields.add(field);
}
/**
* Marks dependencies in this class based on the provided classes in this round of optimization.
* @param lst The list of classes that are available in this optimization step.
* @param nativeSources Array of native sources in this round. Used to check if native files reference
* this class or methods.
*/
public static void markDependencies(List lst, String[] nativeSources) {
mainClass.markDependent(lst);
for(ByteCodeClass bc : lst) {
if (bc.marked) {
continue;
}
if (bc.isEliminated()) {
continue;
}
if(bc.clsName.equals("java_lang_Boolean")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_String")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Integer")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Byte")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Short")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Character")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Thread")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Long")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Double")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_lang_Float")) {
bc.markDependent(lst);
continue;
}
if(bc.clsName.equals("java_text_DateFormat")) {
bc.markDependent(lst);
continue;
}
if (bc.getUsedByNative() == UsedByNativeResult.Unknown) {
// We don't yet know if this class is used by native
// calculate it now.
bc.calcUsedByNative(nativeSources);
}
if(bc.getUsedByNative() == UsedByNativeResult.Used){
bc.markDependent(lst);
continue;
}
if(saveUnitTests && bc.isUnitTest) {
bc.markDependent(lst);
continue;
}
}
// mark all non-final classes that aren't inherited as final for use in
// additional optimizations
for(ByteCodeClass bc : lst) {
if(bc.isFinalClass() || bc.isInterface || bc.isIsAbstract()) {
continue;
}
boolean found = false;
for(ByteCodeClass bk : lst) {
if(bk.baseClassObject == bc) {
found = true;
break;
}
}
if(!found) {
bc.setFinalClass(true);
}
}
// we try to disable the "virtual" aspect of methods where possible
for(ByteCodeClass bc : lst) {
if(bc.isFinalClass()) {
for(BytecodeMethod meth : bc.methods) {
if(meth.canBeVirtual() && !bc.isMethodFromBaseOrInterface(meth)) {
meth.setVirtualOverriden(true);
}
}
}
}
}
public boolean isMethodPrivate(String name, String desc) {
for (BytecodeMethod meth : methods) {
if (meth.getMethodName().equals(name) && desc.equals(meth.getSignature())) {
return meth.isPrivate();
}
}
return false;
}
public void unmark() {
marked = false;
}
private void markDependent(List lst) {
if(marked) {
return;
}
marked = true;
// make sure the method/classname are in the constant pool so we can later
// look them up in case of a stack trace exception
Parser.addToConstantPool(clsName);
for(BytecodeMethod bm : methods) {
if(!bm.isEliminated()) {
Parser.addToConstantPool(bm.getMethodName());
bm.addToConstantPool();
}
}
for(String s : dependsClassesInterfaces) {
ByteCodeClass cls = findClass(s, lst);
// annotation can be null
if(cls != null) {
cls.markDependent(lst);
}
}
}
public static List clearUnmarked(List lst) {
List response = new ArrayList();
for(ByteCodeClass bc : lst) {
if(bc.marked) {
response.add(bc);
}
}
return response;
}
private ByteCodeClass findClass(String s, List lst) {
for(ByteCodeClass c : lst) {
if(c.clsName.equals(s)) {
return c;
}
}
return null;
}
public void updateAllDependencies() {
dependsClassesInterfaces.clear();
exportsClassesInterfaces.clear();
dependsClassesInterfaces.add("java_lang_NullPointerException");
setBaseClass(baseClass);
if (isAnnotation) {
dependsClassesInterfaces.add("java_lang_annotation_Annotation");
}
for(String s : baseInterfaces) {
s = s.replace('/', '_').replace('$', '_');
if(!dependsClassesInterfaces.contains(s)) {
dependsClassesInterfaces.add(s);
}
exportsClassesInterfaces.add(s);
}
if(virtualMethodList != null) {
virtualMethodList.clear();
} else {
virtualMethodList = new ArrayList();
}
fillVirtualMethodTable(virtualMethodList);
for(BytecodeMethod m : methods) {
if(m.isEliminated()) {
continue;
}
for(String s : m.getDependentClasses()) {
if(!dependsClassesInterfaces.contains(s)) {
dependsClassesInterfaces.add(s);
}
}
//for (String s : m.getExportedClasses()) {
// exportsClassesInterfaces.add(s);
//}
}
for(ByteCodeField m : fields) {
for(String s : m.getDependentClasses()) {
if(!dependsClassesInterfaces.contains(s)) {
dependsClassesInterfaces.add(s);
}
}
//for (String s : m.getExportedClasses()) {
// exportsClassesInterfaces.add(s);
//}
}
}
private boolean isMethodFromBaseOrInterface(BytecodeMethod bm) {
if(baseInterfacesObject != null) {
for(ByteCodeClass bi : baseInterfacesObject) {
if(bi.getMethods().contains(bm)) {
return true;
}
if(bi.getBaseClassObject() != null) {
boolean b = bi.isMethodFromBaseOrInterface(bm);
if(b) {
return true;
}
}
}
}
if(baseClassObject != null) {
if(baseClassObject.getMethods().contains(bm)) {
return true;
}
return baseClassObject.isMethodFromBaseOrInterface(bm);
}
return false;
}
private boolean hasDefaultConstructor() {
for(BytecodeMethod bm : methods) {
if(bm.isDefaultConstructor()) {
return true;
}
}
return false;
}
private boolean hasFinalizer() {
for(BytecodeMethod bm : methods) {
if(bm.isFinalizer()) {
return true;
}
}
return false;
}
public static void addArrayType(String type, int dimenstions) {
String arr = dimenstions + "_" + type;
if(!arrayTypes.contains(arr)) {
arrayTypes.add(arr);
}
}
public String generateCCode(List allClasses) {
StringBuilder b = new StringBuilder();
b.append("#include \"");
b.append(clsName);
b.append(".h\"\n");
for(String s : dependsClassesInterfaces) {
if (exportsClassesInterfaces.contains(s)) {
continue;
}
b.append("#include \"");
b.append(s);
b.append(".h\"\n");
}
b.append("const struct clazz *base_interfaces_for_");
b.append(clsName);
b.append("[] = {");
boolean first = true;
for(String ints : baseInterfaces) {
if(!first) {
b.append(", ");
}
first = false;
b.append("&class__");
b.append(ints.replace('/', '_').replace('$', '_'));
}
b.append("};\n");
// class struct, contains vtable, static fields and meta data (class name), type info etc.
b.append("struct clazz class__");
b.append(clsName);
b.append(" = {\n");
// object fields so class will be compatible to object
if(clsName.equals("java_lang_Class")) {
b.append(" DEBUG_GC_INIT 0, 999999, 0, 0, 0, 0, &__FINALIZER_");
} else {
b.append(" DEBUG_GC_INIT &class__java_lang_Class, 999999, 0, 0, 0, 0, &__FINALIZER_");
}
b.append(clsName);
b.append(" ,0 , &__GC_MARK_");
b.append(clsName);
// initialized defaults to false
b.append(", 0, ");
// the numberic id of the class
b.append("cn1_class_id_");
b.append(clsName);
b.append(", ");
// name of the class
b.append("\"");
b.append(clsName.replace('_', '.'));
b.append("\", ");
// is array class type
b.append("0, ");
// array type dimensions
b.append("0, ");
// array internal type
b.append("0, ");
// primitive type
b.append("JAVA_FALSE, ");
// reference to the base class
if(baseClass != null) {
b.append("&class__");
b.append(baseClass.replace('/', '_').replace('$', '_'));
} else {
b.append("(const struct clazz*)0");
}
b.append(", ");
// references to the base interfaces
b.append("base_interfaces_for_");
b.append(clsName);
b.append(", ");
// number of base interfaces
b.append(baseInterfaces.size());
// new instance function pointer
if(!isInterface && !isAbstract && hasDefaultConstructor()) {
b.append(", &__NEW_INSTANCE_");
b.append(clsName);
} else {
b.append(", 0");
}
// vtable
b.append(", 0\n");
if (isEnum) {
b.append(", &__VALUE_OF_");
b.append(clsName);
} else {
b.append(", 0");
}
/*
JAVA_BOOLEAN isSynthetic;
JAVA_BOOLEAN isInterface;
JAVA_BOOLEAN isAnonymous;
JAVA_BOOLEAN isAnnotation;
*/
b
.append(", ")
.append(isSynthetic?"JAVA_TRUE":"0")
.append(", ")
.append(isInterface?"JAVA_TRUE":"0")
.append(", ")
.append(isAnonymous?"JAVA_TRUE":"0")
.append(", ")
.append(isAnnotation?"JAVA_TRUE":"0")
.append(", ")
.append(getArrayClazz(1));
b.append("};\n\n");
// create class objects for 1 - 3 dimension arrays
for(int iter = 1 ; iter < 4 ; iter++) {
if(!(arrayTypes.contains(iter + "_" + clsName) || arrayTypes.contains((iter + 1) + "_" + clsName) ||
arrayTypes.contains((iter + 2) + "_" + clsName))) {
continue;
}
b.append("struct clazz class_array");
b.append(iter);
b.append("__");
b.append(clsName);
if(clsName.equals("java_lang_Class")) {
b.append(" = {\n DEBUG_GC_INIT 0, 999999, 0, 0, 0, 0, 0, &arrayFinalizerFunction, &gcMarkArrayObject, 0, cn1_array_");
} else {
b.append(" = {\n DEBUG_GC_INIT &class__java_lang_Class, 999999, 0, 0, 0, 0, 0, &arrayFinalizerFunction, &gcMarkArrayObject, 0, cn1_array_");
}
b.append(iter);
b.append("_id_");
b.append(clsName);
b.append(", \"");
b.append(clsName.replace('_', '.'));
for (int arrayDim = 0; arrayDim < iter; arrayDim++) {
b.append("[]");
}
b.append("\", ");
// array class type, dimension & internal type
b.append("JAVA_TRUE, ");
b.append(iter);
b.append(", &class__");
b.append(clsName);
/*
JAVA_BOOLEAN primitiveType;
const struct clazz* baseClass;
const struct clazz** baseInterfaces;
const int baseInterfaceCount;
void* newInstanceFp;
// virtual method table lookup
void** vtable;
void* enumValueOfFp;
JAVA_BOOLEAN isSynthetic;
JAVA_BOOLEAN isInterface;
JAVA_BOOLEAN isAnonymous;
JAVA_BOOLEAN isAnnotation;
*/
// primitive type is always false here object is always the base class of the array it has no base interfaces
b.append(", JAVA_FALSE, &class__java_lang_Object, EMPTY_INTERFACES, 0, ");
// new instance function pointer and vtable
b.append("0, 0, 0, 0, 0, 0, 0, "+getArrayClazz(iter+1)+"\n};\n\n");
}
staticFieldList = new ArrayList();
buildStaticFieldList(staticFieldList);
String enumValuesField = null;
// static fields for the class
for(ByteCodeField bf : staticFieldList) {
if(bf.isStaticField() && bf.getClsName().equals(clsName)) {
if (isEnum && ("_VALUES".equals(bf.getFieldName().replace('$','_')) || "ENUM_VALUES".equals(bf.getFieldName().replace('$','_')))) {
enumValuesField = bf.getFieldName();
}
if(bf.isFinal() && bf.getValue() != null && !writableFields.contains(bf.getFieldName())) {
// static getter
b.append(bf.getCDefinition());
b.append(" get_static_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName().replace('$', '_'));
b.append("(CODENAME_ONE_THREAD_STATE) {\n return ");
if(bf.getValue() instanceof String) {
b.append("STRING_FROM_CONSTANT_POOL_OFFSET(");
b.append(Parser.addToConstantPool((String)bf.getValue()));
b.append(") /* ");
b.append(String.valueOf(bf.getValue()).replace("*/", "* /"));
b.append(" */");
} else {
if(bf.getValue() instanceof Number) {
if(bf.getValue() instanceof Double) {
Double d = ((Double)bf.getValue());
if(d.isNaN()) {
b.append("0.0/0.0");
} else {
if(d.isInfinite()) {
if(d.doubleValue() > 0) {
b.append("1.0f / 0.0f");
} else {
b.append("-1.0f / 0.0f");
}
} else {
b.append(bf.getValue());
}
}
} else {
if(bf.getValue() instanceof Float) {
Float d = ((Float)bf.getValue());
if(d.isNaN()) {
b.append("0.0/0.0");
} else {
if(d.isInfinite()) {
if(d.floatValue() > 0) {
b.append("1.0f / 0.0f");
} else {
b.append("-1.0f / 0.0f");
}
} else {
b.append(bf.getValue());
}
}
} else {
b.append(bf.getValue());
}
}
} else {
if(bf.getValue() instanceof Boolean) {
if(((Boolean)bf.getValue()).booleanValue()) {
b.append("JAVA_TRUE");
} else {
b.append("JAVA_FALSE");
}
} else {
b.append("JAVA_NULL");
}
}
}
b.append(";\n}\n\n");
} else {
b.append(bf.getCDefinition());
b.append(" STATIC_FIELD_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append(" = 0;\n");
// static getter
b.append(bf.getCDefinition());
b.append(" get_static_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName().replace('$', '_'));
b.append("(CODENAME_ONE_THREAD_STATE) {\n __STATIC_INITIALIZER_");
b.append(bf.getClsName());
b.append("(threadStateData);\n return STATIC_FIELD_");
b.append(bf.getClsName());
b.append("_");
b.append(bf.getFieldName());
b.append(";\n}\n\n");
// static setter
b.append("void set_static_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName().replace('$', '_'));
b.append("(CODENAME_ONE_THREAD_STATE, ");
b.append(bf.getCDefinition());
b.append(" __cn1StaticVal) {\n __STATIC_INITIALIZER_");
b.append(bf.getClsName());
if(bf.isObjectType()) {
if(bf.isFinal()) {
b.append("(threadStateData);\n STATIC_FIELD_");
} else {
b.append("(threadStateData);\n STATIC_FIELD_");
}
} else {
b.append("(threadStateData);\n STATIC_FIELD_");
}
b.append(bf.getClsName());
b.append("_");
b.append(bf.getFieldName());
if(bf.shouldRemoveFromHeapCollection()) {
if(bf.getType() != null && bf.getType().endsWith("String")) {
b.append(" = __cn1StaticVal;\n removeObjectFromHeapCollection(threadStateData, __cn1StaticVal);\n if(__cn1StaticVal != 0) {\n removeObjectFromHeapCollection(threadStateData, ((struct obj__java_lang_String*)__cn1StaticVal)->java_lang_String_value);\n }\n}\n\n");
} else {
b.append(" = __cn1StaticVal;\n removeObjectFromHeapCollection(threadStateData, __cn1StaticVal);\n}\n\n");
}
} else {
b.append(" = __cn1StaticVal;\n}\n\n");
}
}
}
}
if(isInterface) {
b.append("int **classToInterfaceMap_");
b.append(clsName);
b.append(";\n");
}
fullFieldList = new ArrayList();
buildInstanceFieldList(fullFieldList);
String nullCheck = "";
if (System.getProperty("fieldNullChecks", "false").equals("true")) {
nullCheck = "if(__cn1T == JAVA_NULL){throwException(getThreadLocalData(), __NEW_INSTANCE_java_lang_NullPointerException(getThreadLocalData()));}\n";
}
for(ByteCodeField fld : fullFieldList) {
b.append(fld.getCDefinition());
b.append(" get_field_");
b.append(clsName);
b.append("_");
b.append(fld.getFieldName());
b.append("(JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" return (*(struct obj__");
b.append(clsName);
b.append("*)__cn1T).");
b.append(fld.getClsName());
b.append("_");
b.append(fld.getFieldName());
b.append(";\n}\n\n");
b.append("void set_field_");
b.append(clsName);
b.append("_");
b.append(fld.getFieldName());
b.append("(CODENAME_ONE_THREAD_STATE, ");
b.append(fld.getCDefinition());
if(fld.isObjectType()) {
b.append(" __cn1Val, JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" (*(struct obj__");
} else {
b.append(" __cn1Val, JAVA_OBJECT __cn1T) {\n ").append(nullCheck).append(" (*(struct obj__");
}
b.append(clsName);
b.append("*)__cn1T).");
b.append(fld.getClsName());
b.append("_");
b.append(fld.getFieldName());
b.append(" = __cn1Val;\n}\n\n");
}
// finalizer and GC_RELEASE to cleanup variables
b.append("JAVA_VOID __FINALIZER_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT objToDelete) {\n");
if(hasFinalizer()) {
b.append(" ");
b.append(clsName);
b.append("_finalize__(threadStateData, objToDelete);\n");
}
// invoke the finalize method of the base
if(baseClass != null) {
b.append(" __FINALIZER_");
b.append(baseClass.replace('/', '_').replace('$', '_'));
b.append("(threadStateData, objToDelete);\n");
}
b.append("}\n\n");
// mark function for the GC mark cycle to tag the objects that are reachable
b.append("void __GC_MARK_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT objToMark, JAVA_BOOLEAN force) {\n struct obj__");
b.append(clsName);
b.append("* objInstance = (struct obj__");
b.append(clsName);
b.append("*)objToMark;\n");
for(ByteCodeField fld : fullFieldList) {
if(!fld.isStaticField() && fld.isObjectType() && fld.getClsName().equals(clsName)) {
b.append(" gcMarkObject(threadStateData, objInstance->");
b.append(fld.getClsName());
b.append("_");
b.append(fld.getFieldName());
b.append(", force);\n");
}
}
// invoke the mark method of the base
if(baseClass != null) {
b.append(" __GC_MARK_");
b.append(baseClass.replace('/', '_').replace('$', '_'));
b.append("(threadStateData, objToMark, force);\n");
} else {
// we can do this in Object.java only since all code will reach here eventually
b.append(" objToMark->__codenameOneGcMark = currentGcMarkValue;\n");
}
b.append("}\n\n");
// initialize object instances
if(!isInterface && !isAbstract) {
b.append("JAVA_OBJECT __NEW_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE) {\n __STATIC_INITIALIZER_");
b.append(clsName);
b.append("(threadStateData);\n JAVA_OBJECT o = codenameOneGcMalloc(threadStateData, sizeof(struct obj__");
b.append(clsName);
b.append("), &class__");
b.append(clsName);
b.append(");\n return o;\n}\n\n");
if(hasDefaultConstructor()) {
b.append("JAVA_OBJECT __NEW_INSTANCE_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE) {\n __STATIC_INITIALIZER_");
b.append(clsName);
b.append("(threadStateData);\n JAVA_OBJECT o = codenameOneGcMalloc(threadStateData, sizeof(struct obj__");
b.append(clsName);
b.append("), &class__");
b.append(clsName);
b.append(");\n");
b.append(clsName);
b.append("___INIT____(threadStateData, o);\n return o;\n}\n\n");
}
}
if(arrayTypes.contains("1_" + clsName) || arrayTypes.contains("2_" + clsName) || arrayTypes.contains("3_" + clsName)) {
b.append("JAVA_OBJECT __NEW_ARRAY_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, JAVA_INT size) {\n");
b.append(" JAVA_OBJECT o = allocArray(threadStateData, size, &class_array1__");
b.append(clsName);
b.append(", sizeof(JAVA_OBJECT), 1);\n (*o).__codenameOneParentClsReference = &class_array1__");
b.append(clsName);
b.append(";\n return o;\n}\n\n");
}
/*b.append("JAVA_OBJECT __NEW_MULTI_ARRAY_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, JAVA_INT dimensions, JAVA_INT* sizes) {\n JAVA_OBJECT o = JAVA_NULL;\n");
b.append(" switch(dimensions) {\n case 2: o = allocMultiArray(sizes, &class_array2__");
b.append(clsName);
b.append(", sizeof(JAVA_OBJECT), 2); break;\n");
b.append(" case 3: o = allocMultiArray(sizes, &class_array3__");
b.append(clsName);
b.append(", sizeof(JAVA_OBJECT), 3); break;\n");
b.append(" case 4: o = allocMultiArray(sizes, &class_array4__");
b.append(clsName);
b.append(", sizeof(JAVA_OBJECT), 4); break;\n");
b.append(" default: return JAVA_NULL;\n }\n (*o).__codenameOneParentClsReference = &class__");
b.append(clsName);
b.append(";\n return o;\n}\n\n");*/
String clInitMethod = null;
if(isInterface) {
for(BytecodeMethod m : methods) {
if(m.getMethodName().equals("__CLINIT__")) {
m.appendMethodC(b);
clInitMethod = clsName + "_" + m.getMethodName() + "__";
} else {
m.appendInterfaceMethodC(b);
}
}
} else {
for(BytecodeMethod m : methods) {
m.appendMethodC(b);
if(m.getMethodName().indexOf("_CLINIT_") > -1) {
clInitMethod = clsName + "_" + m.getMethodName() + "__";
}
if(m.isMain()) {
b.append("\nint main(int argc, char *argv[]) {\n initConstantPool();\n");
b.append(" ");
b.append(clsName);
b.append("_main___java_lang_String_1ARRAY(getThreadLocalData(), JAVA_NULL);\n}\n\n");
}
}
}
if(baseClassObject != null) {
List bm = new ArrayList(methods);
appendSuperStub(b, bm, baseClassObject);
}
int offset = 0;
if(clsName.equals("java_lang_Class")) {
// special case for Class which can't have a vtable since it has no class of its own...
appendClassVFunctions(b);
} else {
if(isInterface) {
// special case, object virtual calls on interfaces should act
// as if they are regular virtual calls
for(BytecodeMethod m : virtualMethodList) {
if(m.getClsName().equals("java_lang_Object")) {
m.appendVirtualMethodC(clsName, b, "" + offset, true);
} else {
// we pretend to have a virtual method here but the optimizer says its not really needed
if(!m.isVirtualOverriden()) {
m.appendVirtualMethodC(clsName, b, "classToInterfaceMap_" + clsName +
"[__cn1ThisObject->__codenameOneParentClsReference->classId][" + offset + "]", true);
}
offset++;
}
}
} else {
for(BytecodeMethod m : virtualMethodList) {
m.appendVirtualMethodC(clsName, b, offset);
offset++;
}
}
}
if(!isInterface) {
b.append("void __INIT_VTABLE_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, void** vtable) {\n ");
if(baseClass != null) {
b.append(" __INIT_VTABLE_");
b.append(baseClass.replace('/', '_').replace('$', '_'));
b.append("(threadStateData, vtable);\n");
}
for(int iter = 0 ; iter < virtualMethodList.size() ; iter++) {
BytecodeMethod bm = virtualMethodList.get(iter);
if(bm.getClsName().equals(clsName) && !bm.isVirtualOverriden()) {
b.append(" vtable[");
b.append(iter);
b.append("] = &");
bm.appendFunctionPointer(b);
b.append(";\n");
}
}
b.append("}\n\n");
}
if (isEnum) {
b.append("JAVA_OBJECT __VALUE_OF_").append(clsName).append("(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT value) {\n ");
if (enumValuesField != null) {
b.append(" JAVA_ARRAY values = (JAVA_ARRAY)get_static_").append(clsName).append("_").append(enumValuesField.replace('$', '_')).append("(threadStateData);\n");
b.append(" JAVA_ARRAY_OBJECT* data = (JAVA_ARRAY_OBJECT*)values->data;\n");
b.append(" int len = values->length;\n");
b.append(" for (int i=0; i bm, ByteCodeClass base) {
// append super stub
BytecodeMethod.setAcceptStaticOnEquals(true);
for(BytecodeMethod m : base.methods) {
if(!m.isPrivate() && !bm.contains(m)) {
m.appendSuperCall(b, clsName);
bm.add(m);
}
}
if(base.baseClassObject != null) {
appendSuperStub(b, bm, base.baseClassObject);
}
BytecodeMethod.setAcceptStaticOnEquals(false);
}
private void appendSuperStubHeader(StringBuilder b, List bm, ByteCodeClass base) {
BytecodeMethod.setAcceptStaticOnEquals(true);
// append super stub
for(BytecodeMethod m : base.methods) {
if(!m.isPrivate() && !bm.contains(m)) {
m.appendMethodHeader(b, clsName);
bm.add(m);
}
}
if(base.baseClassObject != null) {
appendSuperStubHeader(b, bm, base.baseClassObject);
}
BytecodeMethod.setAcceptStaticOnEquals(false);
}
private void buildInstanceFieldList(List fieldList) {
buildInstanceFieldList(fieldList, true);
}
private void buildInstanceFieldList(List fieldList, boolean includePrivateFields) {
for(ByteCodeField bf : fields) {
// We don't include private fields from parent classes.
if (!includePrivateFields && bf.isPrivate()) continue;
if(!bf.isStaticField() && !fieldList.contains(bf)) {
fieldList.add(bf);
}
}
if(baseClassObject != null) {
baseClassObject.buildInstanceFieldList(fieldList, false);
}
}
private List buildStaticFieldList(List fieldList) {
return buildStaticFieldList(fieldList, true);
}
private List buildStaticFieldList(List fieldList, boolean includePrivateFields) {
if (fields != null) {
for(ByteCodeField bf : fields) {
// We don't include private fields from parent classes.
if (!includePrivateFields && bf.isPrivate()) continue;
if(bf.isStaticField() && !fieldList.contains(bf)) {
fieldList.add(bf);
}
}
}
if(baseInterfacesObject != null) {
for(ByteCodeClass baseInterface : baseInterfacesObject) {
baseInterface.buildStaticFieldList(fieldList, false);
}
}
if(baseClassObject != null) {
baseClassObject.buildStaticFieldList(fieldList, false);
}
return fieldList;
}
private void addFields(StringBuilder b) {
if(baseClassObject != null) {
baseClassObject.addFields(b);
}
for(ByteCodeField bf : fields) {
if(!bf.isStaticField()) {
b.append(" ");
b.append(bf.getCDefinition());
b.append(" ");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append(";\n");
}
}
}
public String generateCHeader() {
StringBuilder b = new StringBuilder();
b.append("#ifndef __");
b.append(clsName.toUpperCase());
b.append("__\n");
b.append("#define __");
b.append(clsName.toUpperCase());
b.append("__\n\n");
b.append("#include \"cn1_globals.h\"\n");
for(String s : exportsClassesInterfaces) {
/*
if(s.startsWith("java_lang_annotation") || s.startsWith("java_lang_Deprecated") ||
s.startsWith("java_lang_Override") || s.startsWith("java_lang_SuppressWarnings")) {
continue;
}
*/
//if (isAnnotation) {
// continue;
//}
b.append("#include \"");
b.append(s);
b.append(".h\"\n");
}
b.append("extern struct clazz class__");
b.append(clsName);
b.append(";\n");
if(arrayTypes.contains("1_" + clsName) || arrayTypes.contains("2_" + clsName) || arrayTypes.contains("3_" + clsName)) {
b.append("extern struct clazz class_array1__");
b.append(clsName);
b.append(";\n");
}
if(arrayTypes.contains("2_" + clsName) || arrayTypes.contains("3_" + clsName)) {
b.append("extern struct clazz class_array2__");
b.append(clsName);
b.append(";\n");
}
if(arrayTypes.contains("3_" + clsName)) {
b.append("extern struct clazz class_array3__");
b.append(clsName);
b.append(";\n");
}
if(!isInterface) {
b.append("extern void __INIT_VTABLE_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, void** vtable);\n");
}
b.append("extern void __STATIC_INITIALIZER_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE);\n");
b.append("extern void __FINALIZER_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT objToDelete);\n");
b.append("extern void __GC_MARK_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT objToMark, JAVA_BOOLEAN force);\n");
if(!isInterface && !isAbstract) {
b.append("extern JAVA_OBJECT __NEW_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE);\n");
if(hasDefaultConstructor()) {
b.append("extern JAVA_OBJECT __NEW_INSTANCE_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE);\n");
}
}
if (isEnum) {
b.append("extern JAVA_OBJECT __VALUE_OF_").append(clsName).append("(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT value);\n");
}
if(arrayTypes.contains("1_" + clsName)) {
b.append("extern JAVA_OBJECT __NEW_ARRAY_");
b.append(clsName);
b.append("(CODENAME_ONE_THREAD_STATE, JAVA_INT size);\n");
}
appendMethodsToHeader(b);
if(baseClassObject != null) {
// append super stub
List bm = new ArrayList(methods);
appendSuperStubHeader(b, bm, baseClassObject);
}
for(BytecodeMethod m : virtualMethodList) {
if(m.isVirtualOverriden()) {
b.append("#define virtual_");
b.append(m.getClsName());
b.append("_");
b.append(m.getCMethodName());
b.append("__");
m.appendArgumentTypes(b);
b.append(" ");
b.append(m.getClsName());
b.append("_");
b.append(m.getCMethodName());
b.append("__");
m.appendArgumentTypes(b);
b.append("\n");
} else {
m.appendVirtualMethodHeader(b, clsName);
}
}
// static fields for the class
for(ByteCodeField bf : staticFieldList) {
if(bf.isStaticField()) {
if(bf.getClsName().equals(clsName)) {
b.append("extern ");
b.append(bf.getCDefinition());
b.append(" get_static_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append("();\n");
if(!(bf.isFinal() && bf.getValue() != null && !writableFields.contains(bf.getFieldName()))) {
b.append("extern ");
b.append(bf.getCDefinition());
b.append(" STATIC_FIELD_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append(";\n");
b.append("extern void");
b.append(" set_static_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append("(CODENAME_ONE_THREAD_STATE, ");
b.append(bf.getCDefinition());
b.append(" v);\n");
}
} else {
b.append("#define get_static_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append("(threadStateArgument) get_static_");
b.append(bf.getClsName());
b.append("_");
b.append(bf.getFieldName());
b.append("(threadStateArgument)\n");
b.append("#define set_static_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append("(threadStateArgument, valueArgument) set_static_");
b.append(bf.getClsName());
b.append("_");
b.append(bf.getFieldName());
b.append("(threadStateArgument, valueArgument)\n");
}
}
}
for(ByteCodeField fld : fullFieldList) {
b.append(fld.getCDefinition());
b.append(" get_field_");
b.append(clsName);
b.append("_");
b.append(fld.getFieldName());
b.append("(JAVA_OBJECT t);\n");
b.append("void set_field_");
b.append(clsName);
b.append("_");
b.append(fld.getFieldName());
b.append("(CODENAME_ONE_THREAD_STATE, ");
b.append(fld.getCDefinition());
b.append(" __cn1Val, JAVA_OBJECT __cn1T);\n");
}
b.append("\n\n");
// object struct contains instace field variables
b.append("struct obj__");
b.append(clsName);
b.append(" {\n");
// reference to the class, reference counter for the arc portion of the GC
// and a mutex for synchronization code
b.append(" DEBUG_GC_VARIABLES\n struct clazz *__codenameOneParentClsReference;\n");
b.append(" int __codenameOneReferenceCount;\n");
b.append(" void* __codenameOneThreadData;\n");
b.append(" int __codenameOneGcMark;\n");
b.append(" void* __ownerThread;\n");
b.append(" int __heapPosition;\n");
addFields(b);
b.append("};\n\n");
b.append("\n\n#endif //__");
b.append(clsName.toUpperCase());
b.append("__\n");
return b.toString();
}
private void appendMethodsToHeader(StringBuilder b) {
for(BytecodeMethod m : methods) {
m.appendMethodHeader(b);
/*if(!m.isForceVirtual() && m.isVirtualBlockedDueToFinal() && !m.isVirtualOverriden()) {
b.append("#define virtual_");
b.append(clsName);
b.append("_");
b.append(m.getMethodName());
b.append("__");
m.appendArgumentTypes(b);
b.append(" ");
b.append(m.getClsName());
b.append("_");
b.append(m.getMethodName());
b.append("__");
m.appendArgumentTypes(b);
b.append("\n");
}*/
}
/*if(baseClassObject != null) {
baseClassObject.appendVirtualBlockedMethodsToHeader(b, clsName);
}*/
}
/*private void appendVirtualBlockedMethodsToHeader(StringBuilder b, String clsName) {
for(BytecodeMethod m : methods) {
if(m.isVirtualBlockedDueToFinal() && !m.isVirtualOverriden()) {
b.append("#define virtual_");
b.append(clsName);
b.append("_");
b.append(m.getMethodName());
b.append("__");
m.appendArgumentTypes(b);
b.append(" ");
b.append(m.getClsName());
b.append("_");
b.append(m.getMethodName());
b.append("__");
m.appendArgumentTypes(b);
b.append("\n");
}
}
if(baseClassObject != null) {
baseClassObject.appendVirtualBlockedMethodsToHeader(b, clsName);
}
}*/
/**
* @param baseClass the baseClass to set
*/
public void setBaseClass(String baseClass) {
this.baseClass = baseClass;
if(baseClass != null) {
String b = baseClass.replace('/', '_').replace('$', '_');
if(!dependsClassesInterfaces.contains(b)) {
dependsClassesInterfaces.add(b);
}
exportsClassesInterfaces.add(b);
}
}
public void setBaseInterfaces(String[] interfaces) {
baseInterfaces = Arrays.asList(interfaces);
if(baseInterfaces != null) {
for(String s : interfaces) {
s = s.replace('/', '_').replace('$', '_');
if(!dependsClassesInterfaces.contains(s)) {
dependsClassesInterfaces.add(s);
}
exportsClassesInterfaces.add(s);
}
}
}
/**
* @return the clsName
*/
public String getClsName() {
return clsName;
}
/**
* @return the baseClassObject
*/
public ByteCodeClass getBaseClassObject() {
return baseClassObject;
}
/**
* @param baseClassObject the baseClassObject to set
*/
public void setBaseClassObject(ByteCodeClass baseClassObject) {
this.baseClassObject = baseClassObject;
}
/**
* @return the baseInterfacesObject
*/
public List getBaseInterfacesObject() {
return baseInterfacesObject;
}
/**
* @param baseInterfacesObject the baseInterfacesObject to set
*/
public void setBaseInterfacesObject(List baseInterfacesObject) {
this.baseInterfacesObject = baseInterfacesObject;
}
/**
* @return the baseInterfaces
*/
public List getBaseInterfaces() {
return baseInterfaces;
}
public void fillVirtualMethodTable(List virtualMethods) {
fillVirtualMethodTable(virtualMethods, true);
}
private void fillVirtualMethodTable(List virtualMethods, boolean replace) {
if(baseClassObject != null) {
baseClassObject.fillVirtualMethodTable(virtualMethods, true);
}
if(baseInterfacesObject != null) {
for(ByteCodeClass bc : baseInterfacesObject) {
bc.fillVirtualMethodTable(virtualMethods, false);
}
}
for(BytecodeMethod bm : methods) {
if (bm.isEliminated()) continue;
if(bm.canBeVirtual()) {
int offset = virtualMethods.indexOf(bm);
if(offset < 0) {
virtualMethods.add(bm);
if(isInterface) {
bm.setForceVirtual(true);
}
} else {
if(replace) {
virtualMethods.set(offset, bm);
if(isInterface) {
bm.setForceVirtual(true);
}
}
}
} else {
}
}
}
/*private boolean isMethodIn(ByteCodeClass bc, BytecodeMethod bm) {
if(methods.contains(bm)) {
return true;
}
if(baseInterfacesObject != null) {
for(ByteCodeClass cc : baseInterfacesObject) {
if(isMethodIn(cc, bm)) {
return true;
}
}
}
if(baseClassObject != null) {
return isMethodIn(baseClassObject, bm);
}
return false;
}*/
/**
* @return the baseClass
*/
public String getBaseClass() {
return baseClass;
}
public void setSourceFile(String sourceFile) {
this.sourceFile = sourceFile;
}
/**
* @return the classOffset
*/
public int getClassOffset() {
return classOffset;
}
/**
* @param classOffset the classOffset to set
*/
public void setClassOffset(int classOffset) {
this.classOffset = classOffset;
}
public int updateMethodOffsets(int initial) {
for(BytecodeMethod m : methods) {
m.setMethodOffset(initial);
initial++;
}
return initial;
}
public int getMethodCountIncludingBase() {
int size = methods.size();
if(baseClassObject != null) {
size += baseClassObject.getMethodCountIncludingBase();
}
if(baseInterfacesObject != null) {
for(ByteCodeClass bo : baseInterfacesObject) {
size += bo.getMethodCountIncludingBase();
}
}
return size;
}
public List getMethods() {
return methods;
}
public List getFields() {
return fields;
}
/**
* @return the isInterface
*/
public boolean isIsInterface() {
return isInterface;
}
/**
* @param isInterface the isInterface to set
*/
public void setIsInterface(boolean isInterface) {
this.isInterface = isInterface;
}
public void setIsUnitTest(boolean isUnitTest) {
this.isUnitTest = isUnitTest;
}
/**
* @return the isAbstract
*/
public boolean isIsAbstract() {
return isAbstract;
}
/**
* @param isAbstract the isAbstract to set
*/
public void setIsAbstract(boolean isAbstract) {
this.isAbstract = isAbstract;
}
private void appendClassVFunctions(StringBuilder b) {
// special case, class has no Class object within it so no real virtual functions
b.append("JAVA_BOOLEAN virtual_java_lang_Class_equals___java_lang_Object_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject, JAVA_OBJECT __cn1Arg1) {\n" +
" return java_lang_Object_equals___java_lang_Object_R_boolean(threadStateData, __cn1ThisObject, __cn1Arg1);\n" +
"}\n" +
"\n" +
"\n" +
"JAVA_OBJECT virtual_java_lang_Class_getClass___R_java_lang_Class(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject) {\n" +
" return java_lang_Object_getClass___R_java_lang_Class(threadStateData, __cn1ThisObject);\n" +
"}\n" +
"\n" +
"\n" +
"JAVA_INT virtual_java_lang_Class_hashCode___R_int(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject) {\n" +
" return java_lang_Object_hashCode___R_int(threadStateData, __cn1ThisObject);\n" +
"}\n" +
"\n" +
"\n" +
"JAVA_VOID virtual_java_lang_Class_notify__(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject) {\n" +
" java_lang_Object_notify__(threadStateData, __cn1ThisObject);\n" +
"}\n" +
"\n" +
"JAVA_VOID virtual_java_lang_Class_notifyAll__(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject) {\n" +
" java_lang_Object_notifyAll__(threadStateData, __cn1ThisObject);\n" +
"}\n" +
"\n" +
"\n" +
"JAVA_OBJECT virtual_java_lang_Class_toString___R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject) {\n" +
" return java_lang_Object_toString___R_java_lang_String(threadStateData, __cn1ThisObject);\n" +
"}\n" +
"\n" +
"\n" +
"JAVA_VOID virtual_java_lang_Class_wait__(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject) {\n" +
" java_lang_Object_wait__(threadStateData, __cn1ThisObject);\n" +
"}\n" +
"\n" +
"\n" +
"JAVA_VOID virtual_java_lang_Class_wait___long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject, JAVA_LONG __cn1Arg1) {\n" +
" java_lang_Object_wait___long(threadStateData, __cn1ThisObject, __cn1Arg1);\n" +
"}\n" +
"\n" +
"\n" +
"JAVA_VOID virtual_java_lang_Class_wait___long_int(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT __cn1ThisObject, JAVA_LONG __cn1Arg1, JAVA_INT __cn1Arg2) {\n" +
" java_lang_Object_wait___long_int(threadStateData, __cn1ThisObject, __cn1Arg1, __cn1Arg2);\n" +
"}\n");
}
/**
* @return the finalClass
*/
public boolean isFinalClass() {
return finalClass;
}
/**
* @param finalClass the finalClass to set
*/
public void setFinalClass(boolean finalClass) {
this.finalClass = finalClass;
}
public void appendStaticFieldsExtern(StringBuilder b) {
for(ByteCodeField bf : fields) {
if(bf.isStaticField() && bf.isObjectType() && !bf.shouldRemoveFromHeapCollection()) {
b.append("extern ");
b.append(bf.getCDefinition());
b.append(" STATIC_FIELD_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append(";\n");
}
}
}
private boolean isTrulyFinal(ByteCodeField bf) {
if(bf.isFinal()) {
if(bf.isObjectType()) {
if(bf.getType() != null) {
return bf.getType().endsWith("String");
}
} else {
return true;
}
}
return false;
}
public void appendStaticFieldsMark(StringBuilder b) {
for(ByteCodeField bf : fields) {
if(bf.isStaticField() && bf.isObjectType() && !bf.shouldRemoveFromHeapCollection()) {
b.append(" gcMarkObject(threadStateData, STATIC_FIELD_");
b.append(clsName);
b.append("_");
b.append(bf.getFieldName());
b.append(", JAVA_TRUE);\n");
}
}
}
/**
* 3-state variable to keep track of whether the class is used by native sources.
* 3 states, because we need to know if it is unknown.
*/
private UsedByNativeResult usedByNative = UsedByNativeResult.Unknown;
/**
* Sets usedByNative flag in this class.
* @param usedByNative True if this class is used by native sources.
*/
public void setUsedByNative(boolean usedByNative) {
this.usedByNative = usedByNative ? UsedByNativeResult.Used : UsedByNativeResult.Unused;
}
/**
* Enum to track possible values of {@link #usedByNative}.
*/
public static enum UsedByNativeResult {
/**
* The class is used by native sources.
*/
Used,
/**
* The class is not used by native sources.
*/
Unused,
/**
* We don't yet know if this class is used by native sources.
*/
Unknown;
}
/**
* Check whether this class is used by native sources.
* @return
*/
public UsedByNativeResult getUsedByNative() {
return usedByNative;
}
/**
* Calculates whether this class is used in any of the native sources.
* @param nativeSources The native sources to check.
* @see #getUsedByNative()
* @see #setUsedByNative(boolean)
*/
public void calcUsedByNative(String[] nativeSources) {
for (BytecodeMethod m : methods) {
if (usedByNative != UsedByNativeResult.Unknown) {
return;
}
m.isMethodUsedByNative(nativeSources, this);
}
}
boolean isUnitTest() {
return isUnitTest;
}
void setIsEnum(boolean b) {
this.isEnum = b;
}
private String getArrayClazz(int dim) {
if((arrayTypes.contains(dim + "_" + clsName) )) {
return "&class_array"+dim+"__"+clsName;
} else {
return "0";
}
}
}