OMCompiler/Compiler/FrontEnd/InstHashTable.mo
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of OpenModelica. | ||
| 3 | * | ||
| 4 | * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), | ||
| 5 | * c/o Linköpings universitet, Department of Computer and Information Science, | ||
| 6 | * SE-58183 Linköping, Sweden. | ||
| 7 | * | ||
| 8 | * All rights reserved. | ||
| 9 | * | ||
| 10 | * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR | ||
| 11 | * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. | ||
| 12 | * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES | ||
| 13 | * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL | ||
| 14 | * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. | ||
| 15 | * | ||
| 16 | * The OpenModelica software and the OSMC (Open Source Modelica Consortium) | ||
| 17 | * Public License (OSMC-PL) are obtained from OSMC, either from the above | ||
| 18 | * address, from the URLs: | ||
| 19 | * http://www.openmodelica.org or | ||
| 20 | * https://github.com/OpenModelica/ or | ||
| 21 | * http://www.ida.liu.se/projects/OpenModelica, | ||
| 22 | * and in the OpenModelica distribution. | ||
| 23 | * | ||
| 24 | * GNU AGPL version 3 is obtained from: | ||
| 25 | * https://www.gnu.org/licenses/licenses.html#GPL | ||
| 26 | * | ||
| 27 | * This program is distributed WITHOUT ANY WARRANTY; without | ||
| 28 | * even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 29 | * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH | ||
| 30 | * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. | ||
| 31 | * | ||
| 32 | * See the full OSMC Public License conditions for more details. | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | encapsulated package InstHashTable "hash table implementation for cashing instantiation results" | ||
| 37 | |||
| 38 | import Absyn; | ||
| 39 | import DAE.Connect; | ||
| 40 | import ConnectionGraph; | ||
| 41 | import ClassInf; | ||
| 42 | import DAE; | ||
| 43 | import FCore; | ||
| 44 | import InstTypes; | ||
| 45 | import SCode; | ||
| 46 | |||
| 47 | protected | ||
| 48 | |||
| 49 | import Flags; | ||
| 50 | import Global; | ||
| 51 | import OperatorOverloading; | ||
| 52 | |||
| 53 | public | ||
| 54 | |||
| 55 | type Key = Absyn.Path; | ||
| 56 | type Value = CachedInstItems; | ||
| 57 | |||
| 58 | type CachedInstItemInputs = tuple<DAE.Mod, DAE.Prefix, | ||
| 59 | Connect.Sets, ClassInf.State, SCode.Element, InstTypes.InstDims, Boolean, | ||
| 60 | Option<DAE.ComponentRef>, InstTypes.CallingScope>; | ||
| 61 | |||
| 62 | type CachedInstItemOutputs = tuple<FCore.Graph, DAE.DAElist, Connect.Sets, | ||
| 63 | ClassInf.State, list<DAE.Var>, Option<DAE.Type>, Option<SCode.Attributes>, | ||
| 64 | DAE.EqualityConstraint, ConnectionGraph.ConnectionGraph>; | ||
| 65 | |||
| 66 | type CachedPartialInstItemInputs = tuple<DAE.Mod, DAE.Prefix, | ||
| 67 | ClassInf.State, SCode.Element, InstTypes.InstDims>; | ||
| 68 | |||
| 69 | type CachedPartialInstItemOutputs = tuple<FCore.Graph, ClassInf.State, list<DAE.Var>>; | ||
| 70 | |||
| 71 | type CachedInstItems = list<Option<CachedInstItem>>; | ||
| 72 | |||
| 73 | |||
| 74 | public function init | ||
| 75 | protected | ||
| 76 | HashTable ht; | ||
| 77 | algorithm | ||
| 78 | /* adrpo: reuse it if is already there! */ | ||
| 79 | try | ||
| 80 | 26606 | ht := getGlobalRoot(Global.instHashIndex); | |
| 81 | 23948 | ht := BaseHashTable.clear(ht); | |
| 82 | 23948 | setGlobalRoot(Global.instHashIndex, ht); | |
| 83 | else | ||
| 84 | 2658 | setGlobalRoot(Global.instHashIndex, emptyInstHashTable()); | |
| 85 | end try; | ||
| 86 | end init; | ||
| 87 | |||
| 88 | function release | ||
| 89 | algorithm | ||
| 90 | 1104 | setGlobalRoot(Global.instHashIndex, emptyInstHashTable()); | |
| 91 | 1104 | OperatorOverloading.initCache(); | |
| 92 | end release; | ||
| 93 | |||
| 94 | function get | ||
| 95 | input Key k; | ||
| 96 | output Value v; | ||
| 97 | protected | ||
| 98 | HashTable ht; | ||
| 99 | algorithm | ||
| 100 | 2299644 | ht := getGlobalRoot(Global.instHashIndex); | |
| 101 | 2299644 | v := BaseHashTable.get(k, ht); | |
| 102 | end get; | ||
| 103 | |||
| 104 | uniontype CachedInstItem | ||
| 105 | // *important* inputs/outputs for instClassIn | ||
| 106 | record FUNC_instClassIn | ||
| 107 | CachedInstItemInputs inputs; | ||
| 108 | CachedInstItemOutputs outputs; | ||
| 109 | end FUNC_instClassIn; | ||
| 110 | |||
| 111 | // *important* inputs/outputs for partialInstClassIn | ||
| 112 | record FUNC_partialInstClassIn | ||
| 113 | CachedPartialInstItemInputs inputs; | ||
| 114 | CachedPartialInstItemOutputs outputs; | ||
| 115 | end FUNC_partialInstClassIn; | ||
| 116 | |||
| 117 | end CachedInstItem; | ||
| 118 | |||
| 119 | function addToInstCache | ||
| 120 | input Absyn.Path fullEnvPathPlusClass; | ||
| 121 | input Option<CachedInstItem> fullInstOpt; | ||
| 122 | input Option<CachedInstItem> partialInstOpt; | ||
| 123 | algorithm | ||
| 124 | () := matchcontinue(fullInstOpt, partialInstOpt) | ||
| 125 | local | ||
| 126 | HashTable instHash; | ||
| 127 | Option<CachedInstItem> opt; | ||
| 128 | list<Option<CachedInstItem>> lst; | ||
| 129 | |||
| 130 | // nothing is we have -d=noCache | ||
| 131 | case (_, _) | ||
| 132 | algorithm | ||
| 133 |
1/2✓ Branch 1 taken 845768 times.
✗ Branch 2 not taken.
|
845768 | false := Flags.isSet(Flags.CACHE); |
| 134 | then | ||
| 135 | (); | ||
| 136 | |||
| 137 | // we have them both | ||
| 138 | case (SOME(_), SOME(_)) | ||
| 139 | algorithm | ||
| 140 | ✗ | instHash := getGlobalRoot(Global.instHashIndex); | |
| 141 | ✗ | instHash := BaseHashTable.add((fullEnvPathPlusClass,{fullInstOpt,partialInstOpt}),instHash); | |
| 142 | ✗ | setGlobalRoot(Global.instHashIndex, instHash); | |
| 143 | then | ||
| 144 | (); | ||
| 145 | |||
| 146 | // we have a partial inst result and the full in the cache | ||
| 147 | case (NONE(), SOME(_)) | ||
| 148 | algorithm | ||
| 149 | 42305 | instHash := getGlobalRoot(Global.instHashIndex); | |
| 150 | // see if we have a full inst here | ||
| 151 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 421 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 421 times.
|
42305 | {opt,_} := BaseHashTable.get(fullEnvPathPlusClass, instHash); |
| 152 | 421 | instHash := BaseHashTable.add((fullEnvPathPlusClass,{opt,partialInstOpt}),instHash); | |
| 153 | 421 | setGlobalRoot(Global.instHashIndex, instHash); | |
| 154 | then | ||
| 155 | (); | ||
| 156 | |||
| 157 | // we have a partial inst result and the full is NOT in the cache | ||
| 158 | case (NONE(), SOME(_)) | ||
| 159 | algorithm | ||
| 160 | 41884 | instHash := getGlobalRoot(Global.instHashIndex); | |
| 161 | // see if we have a full inst here | ||
| 162 | // failed above {SOME(fullInst),_} = get(fullEnvPathPlusClass, instHash); | ||
| 163 | 41884 | instHash := BaseHashTable.add((fullEnvPathPlusClass,{NONE(),partialInstOpt}),instHash); | |
| 164 | 41884 | setGlobalRoot(Global.instHashIndex, instHash); | |
| 165 | then | ||
| 166 | (); | ||
| 167 | |||
| 168 | // we have a full inst result and the partial in the cache | ||
| 169 | case (SOME(_), NONE()) | ||
| 170 | algorithm | ||
| 171 | 803463 | instHash := getGlobalRoot(Global.instHashIndex); | |
| 172 | // see if we have a partial inst here | ||
| 173 |
6/10✗ Branch 1 not taken.
✓ Branch 2 taken 523555 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 523555 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 523555 times.
✓ Branch 7 taken 522987 times.
✓ Branch 8 taken 568 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 568 times.
|
803463 | _::(lst as {SOME(_)}) := BaseHashTable.get(fullEnvPathPlusClass, instHash); |
| 174 | 568 | instHash := BaseHashTable.add((fullEnvPathPlusClass,fullInstOpt::lst),instHash); | |
| 175 | 568 | setGlobalRoot(Global.instHashIndex, instHash); | |
| 176 | then | ||
| 177 | (); | ||
| 178 | |||
| 179 | // we have a full inst result and the partial is NOT in the cache | ||
| 180 | case (SOME(_), NONE()) | ||
| 181 | algorithm | ||
| 182 | 802895 | instHash := getGlobalRoot(Global.instHashIndex); | |
| 183 | // see if we have a partial inst here | ||
| 184 | // failed above {_,SOME(partialInst)} = get(fullEnvPathPlusClass, instHash); | ||
| 185 | 802895 | instHash := BaseHashTable.add((fullEnvPathPlusClass,{fullInstOpt,NONE()}),instHash); | |
| 186 | 802895 | setGlobalRoot(Global.instHashIndex, instHash); | |
| 187 | then | ||
| 188 | (); | ||
| 189 | |||
| 190 | // we failed above??!! | ||
| 191 | else (); | ||
| 192 | end matchcontinue; | ||
| 193 | end addToInstCache; | ||
| 194 | |||
| 195 | protected type HashTableKeyFunctionsType = tuple<FuncHashKey,FuncKeyEqual,FuncKeyStr,FuncValueStr>; | ||
| 196 | protected type HashTable = tuple< | ||
| 197 | array<list<tuple<Key,Integer>>>, | ||
| 198 | tuple<Integer,Integer,array<Option<tuple<Key,Value>>>>, | ||
| 199 | Integer, | ||
| 200 | HashTableKeyFunctionsType | ||
| 201 | >; | ||
| 202 | |||
| 203 | protected partial function FuncHashKey | ||
| 204 | input Key cr; | ||
| 205 | output Integer res; | ||
| 206 | end FuncHashKey; | ||
| 207 | |||
| 208 | protected partial function FuncKeyEqual | ||
| 209 | input Key cr1; | ||
| 210 | input Key cr2; | ||
| 211 | output Boolean res; | ||
| 212 | end FuncKeyEqual; | ||
| 213 | |||
| 214 | protected partial function FuncKeyStr | ||
| 215 | input Key cr; | ||
| 216 | output String res; | ||
| 217 | end FuncKeyStr; | ||
| 218 | |||
| 219 | protected partial function FuncValueStr | ||
| 220 | input Value exp; | ||
| 221 | output String res; | ||
| 222 | end FuncValueStr; | ||
| 223 | |||
| 224 | protected function opaqVal | ||
| 225 | "Don't actually print what is stored in the value... It's too damn long." | ||
| 226 | input Value v; | ||
| 227 | output String str; | ||
| 228 | algorithm | ||
| 229 | str := "OPAQUE_VALUE"; | ||
| 230 | end opaqVal; | ||
| 231 | |||
| 232 | protected function emptyInstHashTable | ||
| 233 | "Returns an empty HashTable." | ||
| 234 | output HashTable hashTable; | ||
| 235 | algorithm | ||
| 236 | 3762 | hashTable := emptyInstHashTableSized(Flags.getConfigInt(Flags.INST_CACHE_SIZE)); | |
| 237 | 3762 | OperatorOverloading.initCache(); | |
| 238 | end emptyInstHashTable; | ||
| 239 | |||
| 240 | protected function emptyInstHashTableSized | ||
| 241 | "Returns an empty HashTable, using the given bucket size." | ||
| 242 | input Integer size; | ||
| 243 | output HashTable hashTable; | ||
| 244 | algorithm | ||
| 245 | 3762 | hashTable := BaseHashTable.emptyHashTableWork(size,(AbsynUtil.pathHash,AbsynUtil.pathEqual,AbsynUtil.pathStringDefault,opaqVal)); | |
| 246 | end emptyInstHashTableSized; | ||
| 247 | |||
| 248 | annotation(__OpenModelica_Interface="frontend"); | ||
| 249 | end InstHashTable; | ||
| 250 |