package org.simantics.scl.compiler.constants.generic; import org.cojen.classfile.TypeDesc; import org.objectweb.asm.Label; import org.simantics.scl.compiler.internal.codegen.references.Val; import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; import org.simantics.scl.compiler.internal.codegen.utils.PreparationStep; import org.simantics.scl.compiler.internal.codegen.utils.SCLContextPreparationStep; import org.simantics.scl.compiler.top.SCLCompilerConfiguration; public class ThreadLocalStackItem implements StackItem, PreparationStep { private static final TypeDesc THREAD_LOCAL = TypeDesc.forClass(ThreadLocal.class); String variableName; TypeDesc type; public ThreadLocalStackItem(String variableName, TypeDesc type) { this.variableName = variableName; this.type = type; } @Override public void push(MethodBuilder mb, Val[] parameters) { mb.loadLocal(mb.getPreparation(this)); } @Override public void prepare(MethodBuilder mb) { LocalVariable var = mb.getPreparation(this); if(var == null) { var = mb.createLocalVariable("context", type); LocalVariable sclContext = SCLContextPreparationStep.getCurrent(mb); mb.loadLocal(sclContext); mb.loadConstant(variableName); mb.invokeVirtual("gnu/trove/map/hash/THashMap", "get", TypeDesc.OBJECT, new TypeDesc[] {TypeDesc.OBJECT}); mb.checkCast(type); mb.storeLocal(var); if(SCLCompilerConfiguration.NULL_CHECK_THREAD_LOCAL_VARIABLES) { Label exit = mb.createLabel(); mb.loadLocal(var); mb.ifNullBranch(exit, false); // This code should me redundant because of static type caughts the problem mb.newObject(TypeDesc.forClass(IllegalStateException.class)); mb.dup(); mb.loadConstant("Thread local variable missing"); mb.invokeConstructor(TypeDesc.forClass(IllegalStateException.class), new TypeDesc[] {TypeDesc.STRING}); mb.throwObject(); mb.setLocation(exit); } mb.addPreparation(this, var); } } @Override public int hashCode() { return 234234 + type.hashCode() + 31*variableName.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ThreadLocalStackItem other = (ThreadLocalStackItem) obj; return variableName.equals(other.variableName) && type.equals(other.type); } }