Skip to content

Commit

Permalink
copy dispatch vector correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
guoyiteng committed Apr 29, 2019
1 parent 3cb0d1a commit b640699
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 116 deletions.
3 changes: 1 addition & 2 deletions compiler/src/jlang/extension/JLangArrayInitExt.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import polyglot.ast.ArrayInit;
import polyglot.ast.Expr;
import polyglot.ast.Node;
import polyglot.types.Type;
import polyglot.util.InternalCompilerError;
import polyglot.util.SerialVersionUID;

Expand All @@ -31,7 +30,7 @@ public Node leaveTranslateLLVM(LLVMTranslator v) {

LLVMValueRef len = LLVMConstInt(
v.utils.toLL(v.ts.Int()), n.elements().size(), /*signExtend*/ 0);
LLVMValueRef array = JLangNewArrayExt.translateNewArray(v, len, n.type().toArray());
LLVMValueRef array = JLangNewArrayExt.translateNew1DArray(v, len, n.type().toArray());

if (!n.elements().isEmpty()) {
LLVMValueRef base = v.obj.buildArrayBaseElementPtr(array, n.type().toArray());
Expand Down
124 changes: 40 additions & 84 deletions compiler/src/jlang/extension/JLangNewArrayExt.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,6 @@
public class JLangNewArrayExt extends JLangExt {
private static final long serialVersionUID = SerialVersionUID.generate();

@Override
public Node desugar(DesugarLocally v) {
NewArray n = (NewArray) node();

// Desugar multidimensional arrays.
// (Note that array initializer expressions are an exception,
// since they have their own translation.)
if (n.init() == null && n.dims().size() > 1) {
try {
return desugarMultidimensional(v);
} catch (SemanticException e) {
throw new InternalCompilerError(e);
}
}

return super.desugar(v);
}

/**
* Desugars multidimensional arrays into a runtime call, which in turn builds the
* multidimensional array by recursively building and initializing single dimensional arrays.
Expand Down Expand Up @@ -92,82 +74,56 @@ public Node leaveTranslateLLVM(LLVMTranslator v) {
if (n.init() != null) {
// Steal the translation of the initializer.
res = v.getTranslation(n.init());
}
else {
if (n.dims().size() > 1)
throw new InternalCompilerError("Multidimensional arrays should be desugared");
LLVMValueRef len = v.getTranslation(n.dims().get(0));
} else if (n.dims().size() > 1) {
LLVMValueRef[] len = n.dims().stream()
.map(v::<LLVMValueRef>getTranslation)
.toArray(LLVMValueRef[]::new);

res = translateNewArray(v, len, n.type().toArray());
} else {
LLVMValueRef len = v.getTranslation(n.dims().get(0));
res = translateNew1DArray(v, len, n.type().toArray());
}

v.addTranslation(n, res);
return super.leaveTranslateLLVM(v);
}

public static LLVMValueRef translateNewArray(LLVMTranslator v, LLVMValueRef len, ArrayType type) {
public static LLVMValueRef translateNewArray(LLVMTranslator v, LLVMValueRef[] len, ArrayType type) {
ClassType arrType = v.ts.ArrayObject();
TypeSystem ts = v.ts;
ConstructorInstance arrayConstructor;
try {
arrayConstructor = ts.findConstructor(
arrType, Collections.nCopies(2, ts.Int()), arrType, /*fromClient*/ true);
} catch (SemanticException e) {
throw new InternalCompilerError(e);
LLVMTypeRef createArrayType = v.utils.functionType(
v.utils.toLL(arrType),
v.utils.i8Ptr(),
v.utils.ptrTypeRef(v.utils.i32()),
v.utils.i32(),
v.utils.i32()
);
LLVMValueRef createArray = v.utils.getFunction(Constants.CREATE_ARRAY, createArrayType);
LLVMValueRef name = v.utils.buildGlobalCStr(v.mangler.userVisibleEntityName(type));
LLVMValueRef arrSize = LLVMConstInt(v.utils.i32(), len.length, 0);
LLVMValueRef arrLen = v.utils.buildArrayAlloca("arr.len", v.utils.i32(), arrSize);
LLVMValueRef numOfCdvMethods = LLVMConstInt(v.utils.i32(), v.cdvMethods(arrType).size(), 0);

for (int i = 0; i < len.length; i++) {
LLVMValueRef gep = v.utils.buildGEP(arrLen, i);
LLVMBuildStore(v.builder, len[i], gep);
}
int sizeOfType = v.utils.sizeOfType(type.base());

LLVMTypeRef i64 = LLVMInt64TypeInContext(v.context);
LLVMTypeRef i32 = LLVMInt32TypeInContext(v.context);
LLVMValueRef elemSizeArg = LLVMConstInt(i32, sizeOfType, /*sign-extend*/ 0);
LLVMValueRef arrLen64 = LLVMBuildSExt(v.builder, len, i64, "arr.len");
LLVMValueRef elemSize = LLVMConstInt(i64, sizeOfType, /*sign-extend*/ 0);
LLVMValueRef contentSize = LLVMBuildMul(v.builder, elemSize, arrLen64, "mul");
LLVMValueRef headerSize = v.obj.sizeOf(arrType);
LLVMValueRef size = LLVMBuildAdd(v.builder, headerSize, contentSize, "size");

LLVMValueRef[] arg = {len, elemSizeArg};

// LLVMTranslator v, LLVMValueRef[] args, LLVMValueRef size, ConstructorInstance ci

ReferenceType clazz = arrayConstructor.container();

// Allocate space for the new object.
LLVMValueRef calloc = LLVMGetNamedFunction(v.mod, Constants.CALLOC);
LLVMValueRef obj = v.utils.buildFunCall(calloc, size);

// Bitcast object
LLVMValueRef objCast = LLVMBuildBitCast(v.builder, obj, v.utils.toLL(clazz), "obj_cast");

// Set the Dispatch vector
// TODO: Could probably do this inside the constructor function instead?
LLVMValueRef gep = v.obj.buildDispatchVectorElementPtr(objCast, clazz);

LLVMValueRef initDV = v.utils.getFunction(Constants.INIT_ARRAY_DV_FUNC,
v.utils.functionType(v.utils.ptrTypeRef(v.dv.structTypeRef(clazz)), v.utils.i8Ptr()));
// TODO: should use className instead of signature name
LLVMValueRef name = v.utils.buildGlobalCStr(v.mangler.jniUnescapedSignature(type));
LLVMValueRef dv = v.utils.buildFunCall(initDV, name);

LLVMBuildStore(v.builder, dv, gep);

// Call the constructor function
String mangledFuncName = v.mangler.proc(arrayConstructor);

LLVMTypeRef funcType = v.utils.toLL(arrayConstructor);
LLVMValueRef funcPtr = v.utils.getFunction(mangledFuncName, funcType);

// Bitcast the function so that the formal types are the types that
// the arguments were cast to by DesugarImplicitConversions. It is
// needed due to potential mismatch between the types caused by erasure.
LLVMTypeRef funcTyCast = v.utils.toLLFuncTy(
clazz, v.ts.Void(), arrayConstructor.formalTypes());
funcPtr = LLVMBuildBitCast(v.builder, funcPtr, v.utils.ptrTypeRef(funcTyCast), "cast");

LLVMValueRef[] llvmArgs = Stream.concat(
Stream.of(objCast), Arrays.stream(arg))
.toArray(LLVMValueRef[]::new);
v.utils.buildProcCall(funcPtr, llvmArgs);
return v.utils.buildFunCall(createArray, name, arrLen, arrSize, numOfCdvMethods);
}

return objCast;
public static LLVMValueRef translateNew1DArray(LLVMTranslator v, LLVMValueRef len, ArrayType type) {
ClassType arrType = v.ts.ArrayObject();
LLVMTypeRef create1DArrayType = v.utils.functionType(
v.utils.toLL(arrType),
v.utils.i8Ptr(),
v.utils.i32(),
v.utils.i32()
);
LLVMValueRef create1DArray = v.utils.getFunction(Constants.CREATE_1D_ARRAY, create1DArrayType);
LLVMValueRef name = v.utils.buildGlobalCStr(v.mangler.userVisibleEntityName(type));
LLVMValueRef numOfCdvMethods = LLVMConstInt(v.utils.i32(), v.cdvMethods(arrType).size(), 0);

return v.utils.buildFunCall(create1DArray, name, len, numOfCdvMethods);
}
}
3 changes: 2 additions & 1 deletion compiler/src/jlang/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public class Constants {
public static final String CREATE_EXCEPTION = "createUnwindException";
public static final String THROW_EXCEPTION = "throwUnwindException";
public static final String EXTRACT_EXCEPTION = "extractJavaExceptionObject";
public static final String INIT_ARRAY_DV_FUNC = "initArrayDispatchVector";
public static final String CREATE_ARRAY = "createArray";
public static final String CREATE_1D_ARRAY = "create1DArray";

public static final Set<String> NON_INVOKE_FUNCTIONS = new HashSet<>(CollectionUtil.list(
CALLOC, CREATE_EXCEPTION, EXTRACT_EXCEPTION
Expand Down
32 changes: 32 additions & 0 deletions compiler/src/jlang/util/JLangMangler.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,38 @@ else if (et.isClass()) {
}
}

/**
* Returns the name of the entity (class, primitive types, array, and etc.) formatted for
* use by Class#getName().
* Rules to mangle the name are specified here:
* https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName()
*
* E.g., package.Clazz$InnerClass
*/
public String userVisibleEntityName(Type t) {
Type et = v.ts.erasureType(t);
if (et.isBoolean()) return "boolean";
else if (et.isByte()) return "byte";
else if (et.isChar()) return "char";
else if (et.isShort()) return "short";
else if (et.isInt()) return "int";
else if (et.isLong()) return "long";
else if (et.isFloat()) return "float";
else if (et.isDouble()) return "double";
else if (et.isVoid()) return "void";
else if (et.isArray()) {
// jni replace "." with "/" so we need to revert it here.
return jniUnescapedSignature(et).replace("/", ".");
}
else if (et.isClass()) {
ClassType base = (ClassType) et.toClass().declaration();
return base.fullName();
}
else {
throw new InternalCompilerError("Unsupported type for mangling: " + et);
}
}

private boolean isValidCFuncChar(char c) {
return Character.isDigit(c) || Character.isLetter(c) || c == '_';
}
Expand Down
16 changes: 16 additions & 0 deletions compiler/src/jlang/util/LLVMUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ public LLVMTypeRef i8Ptr() {
return ptrTypeRef(i8());
}

public LLVMTypeRef i32Ptr() {
return ptrTypeRef(i32());
}

public LLVMTypeRef intType(int numBits) {
return LLVMIntTypeInContext(v.context, numBits);
}
Expand Down Expand Up @@ -338,6 +342,18 @@ public void buildCtor(Supplier<LLVMValueRef> ctor) {
LLVMPositionBuilderAtEnd(v.builder, prevBlock);
}

/**
* Allocates space for a new variable on the stack, and returns the pointer to this space.
* Does not change the position of the instruction builder.
*/
public LLVMValueRef buildArrayAlloca(String name, LLVMTypeRef t, LLVMValueRef size) {
LLVMBasicBlockRef prevBlock = LLVMGetInsertBlock(v.builder);
LLVMPositionBuilderAtEnd(v.builder, LLVMGetEntryBasicBlock(v.currFn()));
LLVMValueRef res = LLVMBuildArrayAlloca(v.builder, t, size, name);
LLVMPositionBuilderAtEnd(v.builder, prevBlock);
return res;
}

/**
* Allocates space for a new variable on the stack, and returns the pointer to this space.
* Does not change the position of the instruction builder.
Expand Down
3 changes: 2 additions & 1 deletion runtime/linux_version.map
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ SUNWprivate_1.1 {
jio*;
Java_sun_misc_Unsafe*;
RegisterJavaClass; #TODO rename all of the functions called from JLang-compiled code to have same prefix
initArrayDispatchVector;
createArray;
create1DArray;
InternStringLit;
GetJavaNativeFunc; #Then we can just export PREFIX*
createUnwindException;
Expand Down
83 changes: 57 additions & 26 deletions runtime/native/class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,6 @@ const jclass initArrayClass(const char* name) {
return newKlazz;
}

// TODO: support dv cache and fix the warning (class.cpp:203).
DispatchVector* initArrayDispatchVector(const char* name) {
DispatchVector* runtimeArrayCdv = getRuntimeArrayCdv();
JClassRep** newClassPtr = new JClassRep*(Unwrap(initArrayClass(name)));
DispatchVector* newCdv = new DispatchVector{newClassPtr, runtimeArrayCdv->Idv(), runtimeArrayCdv->SuperTypes()};
return newCdv;
}

bool registeringClass = false;

/**
Expand Down Expand Up @@ -307,17 +299,18 @@ bool isPrimitiveClass(jclass cls) {

/**
* Returns the number of bytes used to store the given type in an array
* It respects size defined in LLVMUtils.sizeOfType(Type t).
*/
int arrayRepSize(jclass cls) {
PRIM_KLASS_SIZE(cls, int, sizeof(int))
} else PRIM_KLASS_SIZE(cls, byte, sizeof(char))
} else PRIM_KLASS_SIZE(cls, short, sizeof(short))
} else PRIM_KLASS_SIZE(cls, long, sizeof(long))
} else PRIM_KLASS_SIZE(cls, float, sizeof(float))
} else PRIM_KLASS_SIZE(cls, double, sizeof(double))
} else PRIM_KLASS_SIZE(cls, char, sizeof(char))
} else PRIM_KLASS_SIZE(cls, boolean, sizeof(char))
} else PRIM_KLASS_SIZE(cls, void, sizeof(void*))
PRIM_KLASS_SIZE(cls, int, 4)
} else PRIM_KLASS_SIZE(cls, byte, 1)
} else PRIM_KLASS_SIZE(cls, short, 2)
} else PRIM_KLASS_SIZE(cls, long, 8)
} else PRIM_KLASS_SIZE(cls, float, 4)
} else PRIM_KLASS_SIZE(cls, double, 8)
} else PRIM_KLASS_SIZE(cls, char, 2)
} else PRIM_KLASS_SIZE(cls, boolean, 1)
} else PRIM_KLASS_SIZE(cls, void, 8)
} else {
return sizeof(void*);
}
Expand Down Expand Up @@ -400,10 +393,25 @@ jclass GetComponentClass(jclass cls) {
return NULL;
}

static int _numOfRuntimeArrayCdvMethods = 0;
DispatchVector* initArrayDispatchVector(const char* name) {
DispatchVector* runtimeArrayCdv = getRuntimeArrayCdv();
const JavaClassInfo* runtimeArrayInfo = GetJavaClassInfo(runtimeArrayCdv->Class()->Wrap());
int runtimeArrayCdvSize = sizeof(DispatchVector) + _numOfRuntimeArrayCdvMethods * sizeof(void*);
DispatchVector* newCdv = (DispatchVector*)malloc(runtimeArrayCdvSize);
memcpy(newCdv, runtimeArrayCdv, runtimeArrayCdvSize);
JClassRep** newClassPtr = new JClassRep*(Unwrap(initArrayClass(name)));
newCdv->SetClassPtr(newClassPtr);
const JavaClassInfo* info = GetJavaClassInfo((*newClassPtr)->Wrap());
// TODO: temporary bad solution
const_cast<JavaClassInfo*>(info)->cdv = (void*)newCdv;
return newCdv;
}

/**
* Helper function to initialize an array in runtime.
*/
JArrayRep* initArray(const char* arrType, int* len, int depth) {
JArrayRep* initArrayHelper(const char* arrType, int* len, int depth) {
const char* componentName = getComponentName(arrType);
DispatchVector* cdv = initArrayDispatchVector(arrType);

Expand All @@ -416,7 +424,6 @@ JArrayRep* initArray(const char* arrType, int* len, int depth) {
elementSize = arrayRepSize(primComponent);
}

// TODO: not sure if this is correct
JArrayRep* arr = (JArrayRep*)GC_MALLOC(sizeof(JArrayRep) + elementSize * (*len));
arr->Super()->SetCdv(cdv);
arr->SetLength(*len);
Expand All @@ -426,18 +433,42 @@ JArrayRep* initArray(const char* arrType, int* len, int depth) {
if (depth > 1) {
void** data = (void**)arr->Data();
for (int i = 0; i < (*len); ++i) {
data[i] = (void*)initArray(componentName, len + 1, depth - 1);
data[i] = (void*)initArrayHelper(componentName, len + 1, depth - 1);
}
}
return arr;
}

jarray initArray(const char* arrType, jarray len) {
JArrayRep* arrLen = Unwrap(len);
// TODO: casting jint to int is fine?
int* data = (int*)arrLen->Data();
int size = arrLen->Length();
JArrayRep* arr = initArray(arrType, data, size);
jarray createArray(const char* arrType, int* len, int sizeOfLen, int numOfCdvMethods) {
if (_numOfRuntimeArrayCdvMethods == 0) {
_numOfRuntimeArrayCdvMethods = numOfCdvMethods;
}
JArrayRep* arr = initArrayHelper(arrType, len, sizeOfLen);
return arr->Wrap();
}

// TODO: Or pass length as a pointer and discard 1D array special case
jarray create1DArray(const char* arrType, int len, int numOfCdvMethods) {
if (_numOfRuntimeArrayCdvMethods == 0) {
_numOfRuntimeArrayCdvMethods = numOfCdvMethods;
}
const char* componentName = getComponentName(arrType);
DispatchVector* cdv = initArrayDispatchVector(arrType);

jclass primComponent = primitiveComponentNameToClass(componentName);
int elementSize;
if (primComponent == NULL) {
// any array or reference type
elementSize = sizeof(void*);
} else {
elementSize = arrayRepSize(primComponent);
}

JArrayRep* arr = (JArrayRep*)GC_MALLOC(sizeof(JArrayRep) + elementSize * len);
arr->Super()->SetCdv(cdv);
arr->SetLength(len);
arr->SetElemSize(elementSize);

return arr->Wrap();
}

Expand Down
4 changes: 2 additions & 2 deletions runtime/native/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ struct JavaClassInfo {
void
RegisterJavaClass(jclass cls, const JavaClassInfo* data);

DispatchVector* initArrayDispatchVector(const char* name);
jarray createArray(const char* arrType, int* len, int sizeOfLen, int numOfCdvMethods);

jarray initArray(const char* arrType, jarray len);
jarray create1DArray(const char* arrType, int len, int numOfCdvMethods);

void InternStringLit(jstring str);

Expand Down
Loading

0 comments on commit b640699

Please sign in to comment.