package org.simantics.scl.compiler.internal.codegen.chr; import org.cojen.classfile.TypeDesc; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo; import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator; import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder; import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils; import org.simantics.scl.compiler.internal.codegen.utils.Constants; import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase; import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; public class CHRHashIndexCodeGenerator implements CHRCodeGenerationConstants { public static ClassBuilder generateHashIndex(ClassBuilder storeClassBuilder, CHRConstraint constraint, IndexInfo indexInfo, TypeDesc factClassTypeDesc, String factClassName) { // new CHRHashIndex() { // @Override // protected boolean keyEquals(Object a, Object b) { // return ((ExampleFact)a).c0 == ((ExampleFact)b).c0; // } // @Override // protected int keyHashCode(Object key) { // return ((ExampleFact)key).c0; // } // } ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder(); JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator(); String hashIndexClassName = factClassName + "$" + indexInfo.indexName; ClassBuilder hashIndexClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, hashIndexClassName, "org/simantics/scl/runtime/chr/CHRHashIndex"); // Method: keyEquals { // @Override // protected boolean keyEquals(Object a, Object b) { // return ((ExampleFact)a).c0 == ((ExampleFact)b).c0; // } MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyEquals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]); mb.loadLocal(mb.getParameter(0)); mb.checkCast(factClassTypeDesc); LocalVariable aVar = mb.createLocalVariable("a", factClassTypeDesc); mb.storeLocal(aVar); mb.loadLocal(mb.getParameter(1)); mb.checkCast(factClassTypeDesc); LocalVariable bVar = mb.createLocalVariable("b", factClassTypeDesc); mb.storeLocal(bVar); Label failure = mb.createLabel(); int curMask = indexInfo.indexMask; for(int i=0;i>=1) if((curMask&1) == 1) { TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]); if(fieldTypeDesc.equals(TypeDesc.VOID)) continue; mb.loadLocal(aVar); mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc); mb.loadLocal(bVar); mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc); CodeBuilderUtils.equals(mb, fieldTypeDesc, failure); } mb.loadConstant(true); mb.returnValue(TypeDesc.BOOLEAN); mb.setLocation(failure); mb.loadConstant(false); mb.returnValue(TypeDesc.BOOLEAN); mb.finish(); } // Method: keyHashCode { // @Override // protected int keyHashCode(Object key) { // return (0x811C9DC5^((ExampleFact)key).c0)*16777619; // } MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyHashCode", TypeDesc.INT, Constants.OBJECTS[1]); mb.loadLocal(mb.getParameter(0)); mb.checkCast(factClassTypeDesc); LocalVariable factVar = mb.createLocalVariable("fact", factClassTypeDesc); mb.storeLocal(factVar); mb.loadConstant(0x811C9DC5); int curMask = indexInfo.indexMask; for(int i=0;i>=1) if((curMask&1) == 1) { TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]); if(fieldTypeDesc.equals(TypeDesc.VOID)) continue; mb.loadLocal(factVar); mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc); CodeBuilderUtils.hashCode(mb, fieldTypeDesc); mb.math(Opcodes.IXOR); mb.loadConstant(16777619); mb.math(Opcodes.IMUL); } mb.returnValue(TypeDesc.INT); mb.finish(); } hashIndexClassBuilder.addDefaultConstructor(); return hashIndexClassBuilder; } }