Changeset d318a18
- Timestamp:
- Jul 18, 2018, 5:18:29 PM (6 years ago)
- Branches:
- new-env
- Children:
- eff03a94
- Parents:
- 5c14030
- Location:
- src
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/GC.cc
r5c14030 rd318a18 41 41 42 42 const GC& GC::operator<< (const GC_Object* obj) const { 43 if( obj ) 44 { 43 if( obj ) { 45 44 if( obj->mark != this->mark ) { 46 45 obj->mark = this->mark; … … 49 48 } 50 49 return *this; 50 } 51 52 bool GC::notrace_mark(const GC_Object* obj) const { 53 if ( obj && obj->mark != this->mark ) { 54 obj->mark = this->mark; 55 return true; 56 } 57 return false; 51 58 } 52 59 -
src/Common/GC.h
r5c14030 rd318a18 38 38 /// Traces a traceable object 39 39 const GC& operator<< (const GC_Object*) const; 40 41 /// No-trace mark; returns true if the object exists and was not already marked 42 bool notrace_mark(const GC_Object*) const; 40 43 41 44 /// Adds a new object to garbage collection -
src/Common/PersistentDisjointSet.h
r5c14030 rd318a18 281 281 const Base& rerooted() const { 282 282 reroot(); 283 assertf(mode == BASE, "reroot results in base"); 283 284 return as<Base>(); 284 285 } … … 332 333 } 333 334 334 /// Adds fresh class including only one item; returns updated map 335 /// Adds fresh class including only one item; returns updated map (or self if no change) 335 336 template<typename E> 336 337 Self* add(E&& i) { 337 338 reroot(); 338 339 // transfer map to new node 340 Self* ret = new Self{ BASE, take_as<Base>() }; 339 340 // add new element to node 341 Base base_map = take_as<Base>(); 342 bool added = base_map.emplace( i, Node{ i } ).second; 343 344 // fail early on node already present 345 if ( ! added ) { 346 as<Base>() = std::move(base_map); 347 return this; 348 } 349 350 // make new return node and reset self as REM node 351 Self* ret = new Self{ BASE, std::move(base_map) }; 341 352 reset_as_base(); 342 343 // set self to REM node344 353 init<Add>( ret, i ); 345 354 mode = REM; 346 347 // add element in returned map348 Base& base_map = ret->as<Base>();349 bool added = base_map.emplace( i, Node{ std::forward<E>(i) } ).second;350 assertf(added, "added element already present in map");351 355 352 356 return ret; … … 460 464 const Base& self = rerooted(); 461 465 462 Elm crnt = i; 463 do { 466 // exit early if class not present 467 auto it = self.find( i ); 468 if ( it == self.end() ) return; 469 470 // apply f to each member of class 471 f( i ); 472 for ( Elm crnt = it->second.next; crnt != i; crnt = it->second.next ) { 464 473 f( crnt ); 465 autoit = self.find( crnt );474 it = self.find( crnt ); 466 475 assertf( it != self.end(), "current node must exist in base" ); 467 crnt = it->second.next; 468 } while ( crnt != i ); 476 } 469 477 } 470 478 -
src/Common/PersistentMap.h
r5c14030 rd318a18 141 141 gc.maybe_trace( entry.first, entry.second ); 142 142 } 143 return; 144 } 143 } break; 145 144 case REM: { 146 145 const Rem& self = as<Rem>(); 147 146 gc << self.base; 148 147 gc.maybe_trace( self.key ); 149 return; 150 } 148 } break; 151 149 case INS: case UPD: { 152 150 const Ins& self = as<Ins>(); 153 151 gc << self.base; 154 152 gc.maybe_trace( self.key, self.val ); 155 return; 156 } 153 } break; 157 154 default: assertf(false, "invalid mode"); 158 155 } … … 198 195 199 196 base_map.erase( it ); 200 break; 201 } 197 } break; 202 198 case INS: { 203 199 Ins& self = mut_this->as<Ins>(); … … 207 203 208 204 base_map.emplace( std::move(self.key), std::move(self.val) ); 209 break; 210 } 205 } break; 211 206 case UPD: { 212 207 Ins& self = mut_this->as<Ins>(); … … 218 213 219 214 it->second = std::move(self.val); 220 break; 221 } 215 } break; 222 216 default: assertf(false, "invalid mode"); 223 217 } -
src/ResolvExpr/TypeEnvironment.cc
r5c14030 rd318a18 33 33 34 34 namespace ResolvExpr { 35 #if 1 36 #define PRE_POST_VALIDATE auto dbg = ValidateGuard{this, __func__}; 37 #define PRE_POST_VALIDATE_NOM auto dbg = ValidateGuard{this}; 38 struct ValidateGuard { 39 const TypeEnvironment* env; 40 const TypeEnvironment::Classes* old_classes; 41 const TypeEnvironment::Bindings* old_bindings; 42 const char* last_fn; 43 44 void validate_classes( const TypeEnvironment::Classes* c ) { 45 typedef TypeEnvironment::Classes C; 46 47 assertf( c != nullptr, "classes non-null" ); 48 49 C::Mode cmode = c->get_mode(); 50 if ( cmode == C::BASE ) { 51 // xxx - consistency checks 52 } else { 53 assertf( cmode == C::ADD || cmode == C::REM || cmode == C::ADDTO || cmode == C::REMFROM, "valid classes mode" ); 54 validate_classes( c->get_base() ); 55 } 56 } 57 58 void validate_bindings( const TypeEnvironment::Bindings* b ) { 59 typedef TypeEnvironment::Bindings B; 60 61 assertf( b != nullptr, "bindings non-null" ); 62 63 B::Mode bmode = b->get_mode(); 64 if ( bmode == B::BASE ) { 65 // xxx - consistency checks 66 } else { 67 assertf( bmode == B::REM || bmode == B::INS || bmode == B::UPD, "valid bindings mode" ); 68 validate_bindings( b->get_base() ); 69 } 70 } 71 72 void validate_env() { 73 validate_classes( env->classes ); 74 validate_bindings( env->bindings ); 75 76 // xxx - joint validation 77 } 78 79 ValidateGuard(const TypeEnvironment* e) 80 : env{e}, old_classes{e->classes}, old_bindings{e->bindings}, last_fn{e->last_fn} 81 { validate_env(); } 82 ValidateGuard(const TypeEnvironment* e, const char* fn) 83 : env{e}, old_classes{e->classes}, old_bindings{e->bindings}, last_fn{fn} 84 { validate_env(); } 85 ~ValidateGuard() { 86 validate_env(); 87 if ( env->classes != old_classes ) validate_classes( old_classes ); 88 if ( env->bindings != old_bindings ) validate_bindings( old_bindings ); 89 const_cast<TypeEnvironment*>(env)->last_fn = last_fn; 90 } 91 }; 92 #else 93 #define PRE_POST_VALIDATE 94 #define PRE_POST_VALIDATE_NOM 95 #endif 96 35 97 void printAssertionSet( const AssertionSet &assertions, std::ostream &os, int indent ) { 36 98 for ( AssertionSet::const_iterator i = assertions.begin(); i != assertions.end(); ++i ) { … … 53 115 std::pair<interned_string, interned_string> TypeEnvironment::mergeClasses( 54 116 interned_string root1, interned_string root2 ) { 117 PRE_POST_VALIDATE 55 118 // merge classes 56 119 Classes* newClasses = classes->merge( root1, root2 ); … … 100 163 const TypeDecl::Data& data, AssertionSet& need, AssertionSet& have, 101 164 const OpenVarSet& openVars, WidenMode widenMode, const SymTab::Indexer& indexer ) { 165 PRE_POST_VALIDATE 102 166 // remove references from other, so that type variables can only bind to value types 103 167 bindTo = bindTo->stripReferences(); … … 148 212 const TypeDecl::Data& data, AssertionSet& need, AssertionSet& have, 149 213 const OpenVarSet& openVars, WidenMode widenMode, const SymTab::Indexer& indexer ) { 214 PRE_POST_VALIDATE 150 215 ClassRef class1 = lookup( var1->get_name() ); 151 216 ClassRef class2 = lookup( var2->get_name() ); … … 237 302 238 303 void TypeEnvironment::add( const Type::ForallList &tyDecls ) { 304 PRE_POST_VALIDATE 239 305 for ( Type::ForallList::const_iterator i = tyDecls.begin(); i != tyDecls.end(); ++i ) { 240 306 interned_string name = (*i)->get_name(); … … 245 311 246 312 void TypeEnvironment::add( const TypeSubstitution & sub ) { 313 PRE_POST_VALIDATE 247 314 interned_string not_found{nullptr}; 248 315 … … 251 318 252 319 // filter overlapping classes out of existing environment 253 // (this is a very shady assumption, but has worked for a long time...)320 // xxx - this is a very shady assumption, but has worked for a long time... 254 321 interned_string root = classes->find_or_default( var, not_found ); 255 322 if ( root != not_found ) { … … 270 337 271 338 void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const { 339 PRE_POST_VALIDATE_NOM 272 340 bindings->for_each([&]( interned_string root, const BoundType& bound ){ 273 341 classes->for_class(root, [&]( interned_string var ) { … … 300 368 } 301 369 370 namespace { 371 // temporary representation of an equivalence class 372 struct EqvClass { 373 std::vector<interned_string> vars; 374 BoundType bound; 375 376 EqvClass() = default; 377 EqvClass(const BoundType& b) : bound{b} {} 378 }; 379 } 380 302 381 void TypeEnvironment::simpleCombine( const TypeEnvironment &o ) { 382 PRE_POST_VALIDATE 383 // check for same environment 384 if ( classes == o.classes && bindings == o.bindings ) return; 385 386 // read out equivalence classes (avoids conflicting reroots) 387 std::vector<EqvClass> ecs; 303 388 o.bindings->for_each( [&]( interned_string root, const BoundType& bound ) { 304 // add members of new class 389 ecs.emplace_back(bound); 390 o.classes->for_class( root, [&]( interned_string var ) { 391 ecs.back().vars.push_back( var ); 392 } ); 393 } ); 394 395 // read equivalence classes into self 396 for ( EqvClass& ec : ecs ) { 397 // merge vars 305 398 interned_string new_root{nullptr}; 306 o.classes->for_class( root, [this,&new_root]( interned_string var ) { 307 classes = classes->add( var ); 399 for ( interned_string var : ec.vars ) { 400 Classes* new_classes = classes->add( var ); 401 if ( new_classes == classes ) { var = classes->find( var ); } 402 else { classes = new_classes; } 308 403 new_root = new_root ? mergeClasses( new_root, var ).first : var; 309 } );310 // set binding for new class311 bindings = bindings->set( new_root, bound );312 } );404 } 405 // set binding 406 bindings = bindings->set( new_root, ec.bound ); 407 } 313 408 } 314 409 … … 322 417 323 418 void TypeEnvironment::addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ) { 419 PRE_POST_VALIDATE 420 if ( classes == actualEnv.classes && bindings == actualEnv.bindings ) { 421 // actualEnv already the same, just need to update openVars 422 extractOpenVars( openVars ); 423 return; 424 } else assertf(classes != actualEnv.classes && bindings != actualEnv.bindings, "classes & bindings updated together"); 425 426 // read out equivalence classes (avoids conflicting reroots) 427 std::vector<EqvClass> ecs; 324 428 actualEnv.bindings->for_each( [&]( interned_string root, const BoundType& bound ) { 325 // add members of new class, setting openVars concurrently 429 ecs.emplace_back(bound); 430 actualEnv.classes->for_class( root, [&]( interned_string var ) { 431 ecs.back().vars.push_back( var ); 432 } ); 433 } ); 434 435 // add members of new class, setting openVars concurrently 436 for ( EqvClass& ec : ecs ) { 437 // merge vars 326 438 interned_string new_root{nullptr}; 327 actualEnv.classes->for_class( root, [&]( interned_string var ) { 328 classes = classes->add( var ); 439 for ( interned_string var : ec.vars ) { 440 openVars[ var ] = ec.bound.data; 441 Classes* new_classes = classes->add( var ); 442 if ( new_classes == classes ) { 443 // xxx - this case is a bit sketchy, but has been working 444 // xxx - merging the classes is a departure from previous behaviour 445 var = classes->find( var ); 446 } else { classes = new_classes; } 329 447 new_root = new_root ? mergeClasses( new_root, var ).first : var; 330 openVars[ var ] = bound.data; 331 } ); 332 // add new type binding without widening 448 } 449 // set binding without widening 333 450 bindings = bindings->set( new_root, 334 BoundType{ maybeClone( bound.type), false,bound.data } );335 } );451 BoundType{ maybeClone(ec.bound.type), false, ec.bound.data } ); 452 } 336 453 } 337 454 338 455 void TypeEnvironment::forbidWidening() { 456 PRE_POST_VALIDATE 339 457 bindings = bindings->mutate_each([]( const interned_string&, BoundType& c ) { 340 458 if ( c.allowWidening ) { … … 352 470 353 471 PassVisitor<GcTracer> & operator<<( PassVisitor<GcTracer> & gc, const TypeEnvironment & env ) { 354 for ( ClassRef c : env ) { 355 maybeAccept( c.get_bound().type, gc ); 356 } 472 gc.pass.visit( env ); 473 // for ( ClassRef c : env ) { 474 // maybeAccept( c.get_bound().type, gc ); 475 // } 357 476 return gc; 358 477 } -
src/ResolvExpr/TypeEnvironment.h
r5c14030 rd318a18 138 138 }; 139 139 140 class ValidateGuard; 141 140 142 class TypeEnvironment { 141 143 friend ClassRef; 142 144 friend GcTracer; 145 143 146 /// Backing storage for equivalence classes 144 147 using Classes = PersistentDisjointSet<interned_string>; … … 152 155 /// may be null. 153 156 Bindings* bindings; 157 158 // for debugging 159 friend ValidateGuard; 160 const char* last_fn = "<none>"; 154 161 155 162 /// Merges the classes rooted at root1 and root2, returning a pair containing the root and … … 234 241 T ClassRef::get_vars() const { 235 242 T vars; 236 if ( ! env->classes->count( root ) ) return vars;237 243 env->classes->for_class( root, [&vars]( interned_string var ) { 238 244 vars.insert( vars.end(), var ); -
src/SynTree/GcTracer.h
r5c14030 rd318a18 25 25 #include "Common/GC.h" 26 26 #include "Common/PassVisitor.h" 27 28 class Expression; 27 #include "ResolvExpr/TypeEnvironment.h" 29 28 30 29 /// Implements `trace` method for syntax nodes … … 34 33 public: 35 34 GcTracer( const GC& gc ) : gc(gc) {} 35 36 template<typename... Args> 37 void traceAll(Args&... args) { ::traceAll(gc, args...); } 36 38 37 39 // mark node and children … … 151 153 maybeAccept( type->baseUnion, *visitor ); 152 154 } 155 156 private: 157 void visit( const ResolvExpr::TypeEnvironment::Classes* c ) { 158 typedef ResolvExpr::TypeEnvironment::Classes C; 159 // trace all parent classes, short-circuiting at one traced 160 while ( gc.notrace_mark( c ) && c->get_mode() != C::BASE ) { c = c->get_base(); } 161 } 162 163 void visit( const ResolvExpr::TypeEnvironment::Bindings* b ) { 164 typedef ResolvExpr::TypeEnvironment::Bindings B; 165 166 while ( true ) { 167 if ( ! gc.notrace_mark( b ) ) return; // short-circuit if already traced 168 169 if ( b->get_mode() == B::BASE ) break; // break if this is a base map 170 171 if ( b->get_mode() != B::REM ) { // trace bound intermediate elements 172 maybeAccept( b->get_val().type, *visitor ); 173 } 174 175 b = b->get_base(); 176 } 177 178 // trace bound elements in base binding 179 b->for_each( [&](interned_string, const ResolvExpr::BoundType& bound) { 180 maybeAccept( bound.type, *visitor ); // trace bound elements 181 } ); 182 } 183 184 public: 185 void visit( const ResolvExpr::TypeEnvironment& env ) { 186 visit( env.classes ); 187 visit( env.bindings ); 188 } 153 189 }; 154 190
Note: See TracChangeset
for help on using the changeset viewer.