--- /dev/null
+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<LocalVariable> {
+
+ 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);
+ }
+
+}