]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/ThreadLocalStackItem.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / generic / ThreadLocalStackItem.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/ThreadLocalStackItem.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/ThreadLocalStackItem.java
new file mode 100644 (file)
index 0000000..fe8959f
--- /dev/null
@@ -0,0 +1,81 @@
+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); 
+    }    
+    
+}