]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/ThreadLocalStackItem.java
(refs #7250) Merging master, minor CHR bugfixes
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / generic / ThreadLocalStackItem.java
1 package org.simantics.scl.compiler.constants.generic;
2
3 import org.cojen.classfile.TypeDesc;
4 import org.objectweb.asm.Label;
5 import org.simantics.scl.compiler.internal.codegen.references.Val;
6 import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
7 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
8 import org.simantics.scl.compiler.internal.codegen.utils.PreparationStep;
9 import org.simantics.scl.compiler.internal.codegen.utils.SCLContextPreparationStep;
10 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
11
12 public class ThreadLocalStackItem implements StackItem, PreparationStep<LocalVariable> {
13     
14     private static final TypeDesc THREAD_LOCAL = 
15             TypeDesc.forClass(ThreadLocal.class);
16     
17     String variableName;
18     TypeDesc type;
19     
20     public ThreadLocalStackItem(String variableName, TypeDesc type) {
21         this.variableName = variableName;
22         this.type = type;
23     }
24
25     @Override
26     public void push(MethodBuilder mb, Val[] parameters) {
27         mb.loadLocal(mb.getPreparation(this));
28     }
29
30     @Override
31     public void prepare(MethodBuilder mb) {
32         LocalVariable var = mb.getPreparation(this);
33         if(var == null) {
34             var = mb.createLocalVariable("context", type);
35             LocalVariable sclContext = SCLContextPreparationStep.getCurrent(mb);
36             mb.loadLocal(sclContext);
37             mb.loadConstant(variableName);
38             mb.invokeVirtual("gnu/trove/map/hash/THashMap", "get", 
39                     TypeDesc.OBJECT, new TypeDesc[] {TypeDesc.OBJECT});
40             mb.checkCast(type);
41             mb.storeLocal(var);
42             
43             if(SCLCompilerConfiguration.NULL_CHECK_THREAD_LOCAL_VARIABLES) {
44                 Label exit = mb.createLabel();
45                 mb.loadLocal(var);
46                 mb.ifNullBranch(exit, false);
47
48                 // This code should me redundant because of static type caughts the problem
49                 mb.newObject(TypeDesc.forClass(IllegalStateException.class));
50                 mb.dup();
51                 mb.loadConstant("Thread local variable missing");
52                 mb.invokeConstructor(TypeDesc.forClass(IllegalStateException.class), 
53                         new TypeDesc[] {TypeDesc.STRING});
54                 mb.throwObject();
55
56                 mb.setLocation(exit);
57             }
58             
59             mb.addPreparation(this, var);
60         }
61     }
62
63     @Override
64     public int hashCode() {
65         return 234234 + type.hashCode() + 31*variableName.hashCode();
66     }
67
68     @Override
69     public boolean equals(Object obj) {
70         if (this == obj)
71             return true;
72         if (obj == null)
73             return false;
74         if (getClass() != obj.getClass())
75             return false;
76         ThreadLocalStackItem other = (ThreadLocalStackItem) obj;
77         return variableName.equals(other.variableName)
78                 && type.equals(other.type); 
79     }    
80     
81 }