1 package org.simantics.scl.compiler.internal.codegen.chr;
3 import org.cojen.classfile.TypeDesc;
4 import org.objectweb.asm.Label;
5 import org.objectweb.asm.Opcodes;
6 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
7 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo;
8 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
9 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
10 import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;
11 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
12 import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
13 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
14 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
16 public class CHRHashIndexCodeGenerator implements CHRCodeGenerationConstants {
18 public static ClassBuilder generateHashIndex(ClassBuilder storeClassBuilder, CHRConstraint constraint, IndexInfo indexInfo, TypeDesc factClassTypeDesc, String factClassName) {
19 // new CHRHashIndex() {
21 // protected boolean keyEquals(Object a, Object b) {
22 // return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
25 // protected int keyHashCode(Object key) {
26 // return ((ExampleFact)key).c0;
30 ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder();
31 JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator();
33 String hashIndexClassName = factClassName + "$" + indexInfo.indexName;
34 ClassBuilder hashIndexClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, hashIndexClassName, "org/simantics/scl/runtime/chr/CHRHashIndex");
41 // protected boolean keyEquals(Object a, Object b) {
42 // return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
45 MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyEquals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);
46 mb.loadLocal(mb.getParameter(0));
47 mb.checkCast(factClassTypeDesc);
48 LocalVariable aVar = mb.createLocalVariable("a", factClassTypeDesc);
51 mb.loadLocal(mb.getParameter(1));
52 mb.checkCast(factClassTypeDesc);
53 LocalVariable bVar = mb.createLocalVariable("b", factClassTypeDesc);
56 Label failure = mb.createLabel();
58 int curMask = indexInfo.indexMask;
59 for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
60 if((curMask&1) == 1) {
61 TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
62 if(fieldTypeDesc.equals(TypeDesc.VOID))
65 mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
68 mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
70 CodeBuilderUtils.equals(mb, fieldTypeDesc, failure);
72 mb.loadConstant(true);
73 mb.returnValue(TypeDesc.BOOLEAN);
75 mb.setLocation(failure);
76 mb.loadConstant(false);
77 mb.returnValue(TypeDesc.BOOLEAN);
81 // Method: keyHashCode
85 // protected int keyHashCode(Object key) {
86 // return (0x811C9DC5^((ExampleFact)key).c0)*16777619;
89 MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyHashCode", TypeDesc.INT, Constants.OBJECTS[1]);
90 mb.loadLocal(mb.getParameter(0));
91 mb.checkCast(factClassTypeDesc);
92 LocalVariable factVar = mb.createLocalVariable("fact", factClassTypeDesc);
93 mb.storeLocal(factVar);
95 mb.loadConstant(0x811C9DC5);
97 int curMask = indexInfo.indexMask;
98 for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
99 if((curMask&1) == 1) {
100 TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
101 if(fieldTypeDesc.equals(TypeDesc.VOID))
103 mb.loadLocal(factVar);
104 mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
105 CodeBuilderUtils.hashCode(mb, fieldTypeDesc);
106 mb.math(Opcodes.IXOR);
107 mb.loadConstant(16777619);
108 mb.math(Opcodes.IMUL);
111 mb.returnValue(TypeDesc.INT);
115 hashIndexClassBuilder.addDefaultConstructor();
117 return hashIndexClassBuilder;