Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Patch vtable slots and similar when tiering is enabled #21292

Merged
merged 12 commits into from
Jan 12, 2019

Commits on Jan 11, 2019

  1. Patch vtable slots and similar when tiering is enabled

    For a method eligible for tiered compilation and vtable slot backpatching:
      - The entry point to the final code is versionable, as for any method eligible for tiering
      - It does not have a precode (`HasPrecode()` returns false)
      - It does not have a stable entry point (`HasStableEntryPoint()` returns false)
      - A call to the method may be:
        - An indirect call through the `MethodTable`'s backpatchable vtable slot
        - A direct call to a backpatchable `FuncPtrStub`, perhaps through a `JumpStub`
        - For interface methods, an indirect call through the virtual stub dispatch (VSD) indirection cell to a backpatchable `DispatchStub` or a `ResolveStub` that refers to a backpatchable `ResolveCacheEntry`
      - The purpose is that typical calls to the method have no additional overhead when tiering is enabled
    
    Recording and backpatching slots:
      - In order for all vtable slots for the method to be backpatchable:
        - A vtable slot initially points to the `MethodDesc`'s temporary entry point, even when the method is inherited by a derived type (the slot's value is not copied from the parent)
        - The temporary entry point always points to the prestub and is never backpatched, in order to be able to discover new vtable slots through which the method may be called
        - The prestub, as part of `DoBackpatch()`, records any slots that are transitioned from the temporary entry point to the method's at-the-time current, non-prestub entry point
        - Any further changes to the method's entry point cause recorded slots to be backpatched in `BackpatchEntryPointSlots()`
      - In order for the `FuncPtrStub` to be backpatchable:
        - After the `FuncPtrStub` is created and exposed, it is patched to point to the method's at-the-time current entry point if necessary
        - Any further changes to the method's entry point cause the `FuncPtrStub` to be backpatched in `BackpatchEntryPointSlots()`
      - In order for VSD entities to be backpatchable:
        - A `DispatchStub`'s entry point target is aligned and recorded for backpatching in `BackpatchEntryPointSlots()`
          - The DispatchStub was modified on x86 and x64 such that the entry point target is aligned to a pointer to make it backpatchable
        - A `ResolveCacheEntry`'s entry point target is recorded for backpatching in `BackpatchEntryPointSlots()`
    
    Slot lifetime and management of recorded slots:
      - A slot is recorded in the `LoaderAllocator` in which the slot is allocated, see `RecordAndBackpatchEntryPointSlot()`
      - An inherited slot that has a shorter lifetime than the `MethodDesc`, when recorded, needs to be accessible by the `MethodDesc` for backpatching, so the dependent `LoaderAllocator` with the slot to backpatch is also recorded in the `MethodDesc`'s `LoaderAllocator`, see `MethodDescVirtualInfo::AddDependentLoaderAllocatorsWithSlotsToBackpatch_Locked()`
      - At the end of a `LoaderAllocator`'s lifetime, the `LoaderAllocator` is unregistered from dependency `LoaderAllocators`, see `LoaderAllocator::ClearDependencyMethodDescEntryPointSlotsToBackpatchHash()`
      - When a `MethodDesc`'s entry point changes, backpatching also includes iterating over recorded dependent `LoaderAllocators` to backpatch the relevant slots recorded there, see `BackpatchEntryPointSlots()`
    
    Synchronization between entry point changes and backpatching slots
      - A global lock is used to ensure that all recorded backpatchable slots corresponding to a `MethodDesc` point to the same entry point, see `DoBackpatch()` and `BackpatchEntryPointSlots()` for examples
    
    Due to startup time perf issues:
      - `IsEligibleForTieredCompilation()` is called more frequently with this change and in hotter paths. I chose to use a `MethodDesc` flag to store that information for fast retreival. The flag is initialized by `DetermineAndSetIsEligibleForTieredCompilation()`.
      - Initially, I experimented with allowing a tiered vtable method to have a precode, and allocated a new precode that would also be the stable entry point when a direct call is necessary. That also allows recording a new slot to be optional - in the event of an OOM, the slot may just point to the stable entry point. There are a large number of such methods and the allocations were slowing down startup perf. So, I had to eliminate precodes for tiered vtable methods and that in turn means that recording slots is necessary for versionability.
    
    @jkotas @davidwrighton @noahfalk @AndyAyersMS
    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    11af3fb View commit details
    Browse the repository at this point in the history
  2. Rebase, Address feedback

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    94942b9 View commit details
    Browse the repository at this point in the history
  3. Small fix

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    1bde1d4 View commit details
    Browse the repository at this point in the history
  4. Small fixes and cleanup

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    f73b1c3 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    5b0240d View commit details
    Browse the repository at this point in the history
  6. Move most of the new code in LoaderAllocator to MethodDescDispatchInf…

    …oTracker, to consolidate related functionality
    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    d08bea4 View commit details
    Browse the repository at this point in the history
  7. Remove dependency on tiered vtable methods for entry point slot backp…

    …atching infrastructure
    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    6cd66f1 View commit details
    Browse the repository at this point in the history
  8. Renames

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    d1bf27a View commit details
    Browse the repository at this point in the history
  9. Small fix

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    f0a6069 View commit details
    Browse the repository at this point in the history
  10. Simplify

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    36259f6 View commit details
    Browse the repository at this point in the history
  11. Address feedback

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    2539a94 View commit details
    Browse the repository at this point in the history
  12. Fix

    kouvel committed Jan 11, 2019
    Configuration menu
    Copy the full SHA
    aa6d7e3 View commit details
    Browse the repository at this point in the history