|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 | //
|
13 | 13 | // This file defines data structures to efficiently support the request
|
14 |
| -// evaluator's request caching. |
| 14 | +// evaluator's per-request caching and dependency tracking maps. |
15 | 15 | //
|
16 | 16 | //===----------------------------------------------------------------------===//
|
17 | 17 |
|
| 18 | +#include "swift/AST/DependencyCollector.h" |
18 | 19 | #include "llvm/ADT/DenseMap.h"
|
19 | 20 | #include "llvm/ADT/StringRef.h"
|
20 | 21 |
|
@@ -279,6 +280,127 @@ class RequestCache {
|
279 | 280 | }
|
280 | 281 | };
|
281 | 282 |
|
| 283 | +/// Type-erased wrapper for caching dependencies from a single type of request. |
| 284 | +class PerRequestReferences { |
| 285 | + void *Storage; |
| 286 | + std::function<void(void *)> Deleter; |
| 287 | + |
| 288 | + PerRequestReferences(void *storage, std::function<void(void *)> deleter) |
| 289 | + : Storage(storage), Deleter(deleter) {} |
| 290 | + |
| 291 | +public: |
| 292 | + PerRequestReferences() : Storage(nullptr), Deleter([](void *) {}) {} |
| 293 | + PerRequestReferences(PerRequestReferences &&other) |
| 294 | + : Storage(other.Storage), Deleter(std::move(other.Deleter)) { |
| 295 | + other.Storage = nullptr; |
| 296 | + } |
| 297 | + |
| 298 | + PerRequestReferences &operator=(PerRequestReferences &&other) { |
| 299 | + if (&other != this) { |
| 300 | + this->~PerRequestReferences(); |
| 301 | + new (this) PerRequestReferences(std::move(other)); |
| 302 | + } |
| 303 | + return *this; |
| 304 | + } |
| 305 | + |
| 306 | + PerRequestReferences(const PerRequestReferences &) = delete; |
| 307 | + PerRequestReferences &operator=(const PerRequestReferences &) = delete; |
| 308 | + |
| 309 | + template <typename Request> |
| 310 | + static PerRequestReferences makeEmpty() { |
| 311 | + using Map = |
| 312 | + llvm::DenseMap<RequestKey<Request>, |
| 313 | + std::vector<DependencyCollector::Reference>>; |
| 314 | + return PerRequestReferences(new Map(), |
| 315 | + [](void *ptr) { delete static_cast<Map *>(ptr); }); |
| 316 | + } |
| 317 | + |
| 318 | + template <typename Request> |
| 319 | + llvm::DenseMap<RequestKey<Request>, |
| 320 | + std::vector<DependencyCollector::Reference>> * |
| 321 | + get() const { |
| 322 | + using Map = |
| 323 | + llvm::DenseMap<RequestKey<Request>, |
| 324 | + std::vector<DependencyCollector::Reference>>; |
| 325 | + assert(Storage); |
| 326 | + return static_cast<Map *>(Storage); |
| 327 | + } |
| 328 | + |
| 329 | + bool isNull() const { return !Storage; } |
| 330 | + ~PerRequestReferences() { |
| 331 | + if (Storage) |
| 332 | + Deleter(Storage); |
| 333 | + } |
| 334 | +}; |
| 335 | + |
| 336 | +/// Data structure for caching dependencies from requests. Sharded by the |
| 337 | +/// type ID zone and request kind, with a PerRequestReferences for each |
| 338 | +/// request kind. |
| 339 | +/// |
| 340 | +/// Conceptually equivalent to DenseMap<AnyRequest, vector<Reference>>, but |
| 341 | +/// without type erasure overhead for keys. |
| 342 | +class RequestReferences { |
| 343 | + |
| 344 | +#define SWIFT_TYPEID_ZONE(Name, Id) \ |
| 345 | + std::vector<PerRequestReferences> Name##ZoneRefs; \ |
| 346 | + \ |
| 347 | + template < \ |
| 348 | + typename Request, typename ZoneTypes = TypeIDZoneTypes<Zone::Name>, \ |
| 349 | + typename std::enable_if<TypeID<Request>::zone == Zone::Name>::type * = \ |
| 350 | + nullptr> \ |
| 351 | + llvm::DenseMap<RequestKey<Request>, \ |
| 352 | + std::vector<DependencyCollector::Reference>> * \ |
| 353 | + getRefs() { \ |
| 354 | + auto &refs = Name##ZoneRefs; \ |
| 355 | + if (refs.empty()) { \ |
| 356 | + refs.resize(ZoneTypes::Count); \ |
| 357 | + } \ |
| 358 | + auto idx = TypeID<Request>::localID; \ |
| 359 | + if (refs[idx].isNull()) { \ |
| 360 | + refs[idx] = PerRequestReferences::makeEmpty<Request>(); \ |
| 361 | + } \ |
| 362 | + return refs[idx].template get<Request>(); \ |
| 363 | + } |
| 364 | +#include "swift/Basic/TypeIDZones.def" |
| 365 | +#undef SWIFT_TYPEID_ZONE |
| 366 | + |
| 367 | +public: |
| 368 | + template <typename Request> |
| 369 | + typename llvm::DenseMap<RequestKey<Request>, |
| 370 | + std::vector<DependencyCollector::Reference>>::const_iterator |
| 371 | + find_as(const Request &req) { |
| 372 | + auto *refs = getRefs<Request>(); |
| 373 | + return refs->find_as(req); |
| 374 | + } |
| 375 | + |
| 376 | + template <typename Request> |
| 377 | + typename llvm::DenseMap<RequestKey<Request>, |
| 378 | + std::vector<DependencyCollector::Reference>>::const_iterator |
| 379 | + end() { |
| 380 | + auto *refs = getRefs<Request>(); |
| 381 | + return refs->end(); |
| 382 | + } |
| 383 | + |
| 384 | + template <typename Request> |
| 385 | + void insert(Request req, std::vector<DependencyCollector::Reference> val) { |
| 386 | + auto *refs = getRefs<Request>(); |
| 387 | + refs->insert({RequestKey<Request>(std::move(req)), |
| 388 | + std::move(val)}); |
| 389 | + } |
| 390 | + |
| 391 | + template <typename Request> |
| 392 | + void erase(Request req) { |
| 393 | + auto *refs = getRefs<Request>(); |
| 394 | + refs->erase(RequestKey<Request>(std::move(req))); |
| 395 | + } |
| 396 | + |
| 397 | + void clear() { |
| 398 | +#define SWIFT_TYPEID_ZONE(Name, Id) Name##ZoneRefs.clear(); |
| 399 | +#include "swift/Basic/TypeIDZones.def" |
| 400 | +#undef SWIFT_TYPEID_ZONE |
| 401 | + } |
| 402 | +}; |
| 403 | + |
282 | 404 | } // end namespace evaluator
|
283 | 405 |
|
284 | 406 | } // end namespace swift
|
|
0 commit comments