efficient fail fast dynamic subtype checking
play

Efficient Fail-Fast Dynamic Subtype Checking Rohan Padhye and Koushik - PowerPoint PPT Presentation

Efficient Fail-Fast Dynamic Subtype Checking Rohan Padhye and Koushik Sen UC Berkeley VMIL 2019 Dynamic Subtype Checking S S obj = .. T if (obj instance of T) { . ? } obj 2 Dynamic Subtype Checking S S obj = new X() T if (obj


  1. Efficient Fail-Fast Dynamic Subtype Checking Rohan Padhye and Koushik Sen UC Berkeley VMIL 2019

  2. Dynamic Subtype Checking S S obj = ….. T if (obj instance of T) { …. ? } obj 2

  3. Dynamic Subtype Checking S S obj = new X() T if (obj instance of T) { …. ? } X X <: T ? obj 3

  4. General Solution: Linear Search T S P X <: T ? A B X 4

  5. General Solution: Linear Search T S P X <: T ? A B X 5

  6. General Solution: Linear Search T S P X <: T ? A B X 6

  7. General Solution: Linear Search T S P X <: T ? A B X 7

  8. General Solution: Linear Search T S P X <: T A B Subtype test successful X 8

  9. General Solution: Linear Search T S P X <: T ? A B X 9

  10. General Solution: Linear Search T S P X <: T ? A B X 10

  11. General Solution: Linear Search T S P X <: T ? A B X 11

  12. General Solution: Linear Search T S P X <: T A B Subtype test fails X 12

  13. Implementations must consider trade-offs Constant time? Constant space? (per-class) Supports multiple inheritance? Supports open hierarchies? Pick up to 3 13

  14. Existing Schemes 14

  15. Existing Schemes 15

  16. Case Study: HotSpot JVM Metadata for C class A implements I1 { … } Primary Secondary class B extends A implements I2 { … } depth super super interface I5 extends I6, I7, I2 { … } 0 class C extends B implements I3, I4, I5 { … } object I1 1 I2 A object I1 2 I6 B 3 I7 C A I2 I6 I7 4 I5 5 I3 B I3 I4 I5 6 I4 7 C 16

  17. Case Study: HotSpot JVM Metadata for H class A implements I1 { … } Primary Secondary class B extends A implements I2 { … } depth super super interface I5 extends I6, I7, I2 { … } 0 class C extends B implements I3, I4, I5 { … } object I1 1 I2 A class D extends C 2 I6 B class E extends D 3 I7 C class F extends E 4 I5 D class G extends F 5 I3 E class H extends G 6 I4 F 7 H G 17

  18. Case Study: HotSpot JVM Metadata for C Metadata for H Primary Secondary Primary Secondary depth super super depth super super X <: C ? X.primary[3] == C? 0 0 object I1 object I1 1 1 I2 I2 A A X <: D ? 2 2 I6 I6 B B X.primary[4] == D? 3 3 I7 I7 C C 4 4 I5 I5 D X <: H ? X.secondary_check(H) 5 5 I3 I3 E 6 6 I4 I4 F X <: I5 ? 7 7 H G X.secondary_check(I5) 18

  19. Case Study: HotSpot JVM Metadata for H Secondary super I1 X.secondary_check(T) := { I2 if (X.cache == T) return true; I6 if (X == T) return true; foreach S in X.secondaries { I7 if (S == T) { I5 X <: H ? X.cache = S X.secondary_check(H) I3 return true; } I4 X <: I5 ? } H X.secondary_check(I5) return false; } 19

  20. Case Study: HotSpot JVM Observations: 1. Fast path for success 2. Failure == linear search X.secondary_check(T) := { if (X.cache == T) return true; if (X == T) return true; foreach S in X.secondaries { if (S == T) { X.cache = S return true; } } return false; } 20

  21. Is this assumption always true? Are there workloads where dynamic subtype tests often fail? 21

  22. Case Study: Scala’s Pattern Matching obj match { if (obj instanceof A) { A x = (A) obj; case x:A => x.method_on_A() x.method_on_A(); case y:B => y.method_on_B() } else if (obj instanceof B) { case z:C => z.method_on_C() B y = (B) obj; … Compile to JVM y.method_on_B(); } } else if (obj instanceof C) { C z = (C) obj; z.method_on_C(); } … 22

  23. Profiling Scala’s Pattern Matching Small workload: scalac Hello.scala 47,597 instanceof tests 93% failed Large workload: sbt compile # builds scalac 3.1 billion instanceof tests 76% failed 45 million secondary scans 23

  24. Cast Study: LLVM Compiler Infrastructure if (AllocationInst *AI = dyn_cast<AllocationInst>(Val)) { … } else if (CallInst *CI = dyn_cast<CallInst>(Val)) { … } else if … static bool isLoopInvariant(const Value *V, const Loop *L) { if (isa<Constant>(V) || isa<Argument>(V) || isa<GlobalValue>(V)) return true; // Otherwise, it must be an instruction... return !L->contains(cast<Instruction>(V)->getParent()); } 24

  25. Cast Study: LLVM Compiler Infrastructure Inheritance diagram: class CallInst 25

  26. Profiling the LLVM Compiler Infrastructure Small workload: clang++ Hello.cpp 5.5 million dyn_cast<T>/isa<T> operations 74% failed Large workload: clang selfie.c # 10K LoC 93.7 million dyn_cast<T>/isa<T> operations 78% failed 26

  27. Takeaway : In some workloads… Dynamic subtype tests often fail But fast path is optimized for successful tests L 27

  28. Can we fail fast when linear search is likely? (with no overhead for the current fast path) 28

  29. Solution: Bl Bloom oom Filters 29

  30. Fail-Fast using Bloom Filters α = {1, 3} S For each type T: α(T) := k distinct integers, chosen randomly from [1.. m ] β(T) := α(T) ∪ α(S 1 ) ∪ α(S 2 ) ∪ … ∪ α(S n ) A B where S 1 , S 2 , … S n are all the (transitive) super-types of T α = {7, 9} α = {11, 4} X Invariant: α = {5, 8} T <: S ⇒ α(S) ⊆ β(T) X <: T ? No T α = {1, 6} Y β = {1, 3, 4, 6, 7, 9, 11} α = {7, 11} Y <: T ? Maybe 30

  31. Fail-Fast using Bloom Filters α = 0x000000000101 S For each type T: α(T) := compile_time_random(parity= k ) // m-bit integer β(T) := α(T) | α(S 1 ) | α(S 2 ) | …| α(S n ) A B where S 1 , S 2 , … S n are all the (transitive) super-types of T α = 0x010000001000 α = 0x000101000000 X Invariant: α = 0x000010010000 T <: S ⇒ α(S) & β(T) = α(S) X <: T ? No T α = 0x000000100001 Y β = 0x010101101101 α = 0x010001000000 Y <: T ? Maybe 31

  32. Fail-Fast using Bloom Filters Worst-case only when false positive in bloom filters 32

  33. Choosing parameters m = size of machine word k = parity ?? n = num. of transitive supertypes False positive rate: 33

  34. Preliminary Evaluation (JVM HotSpot) 34

  35. Preliminary Evaluation (JVM HotSpot) 35

  36. Preliminary Evaluation (JVM HotSpot) obj match { if (obj instanceof A) { A x = (A) obj; case x:A => x.method_on_A() x.method_on_A(); case y:B => y.method_on_B() } else if (obj instanceof B) { case z:C => z.method_on_C() B y = (B) obj; … Compile to JVM y.method_on_B(); } } else if (obj instanceof C) { C z = (C) obj; z.method_on_C(); } … 36

  37. Preliminary Evaluation (JVM HotSpot) Rewrite if T is a secondary type 37

  38. Preliminary Evaluation (JVM HotSpot) 38

  39. Preliminary Evaluation (JVM HotSpot) obj match { trait Base case x:A => x.method_on_A() trait A extends Base { def method_on_A(): Int } case y:B => y.method_on_B() trait B extends Base { def method_on_B(): Int } object objA extends traitA { … } object objB extends traitB { … } obj = chooseRandom({objA, objB}) } 39

  40. Preliminary Evaluation (JVM HotSpot) obj match { trait Base case x:A => x.method_on_A() trait A extends Base { def method_on_A(): Int } case y:B => y.method_on_B() trait B extends Base { def method_on_B(): Int } case z:C => z.method_on_C() … case u:D => u.method_on_D() object objA extends traitA { … } case v:E => v.method_on_E() object objB extends traitB { … } … obj = chooseRandom({objA, objB, …}) } 40

  41. Preliminary Evaluation (JVM HotSpot) obj match { trait Base case x:A => x.method_on_A() trait A extends Base { def method_on_A(): Int } case y:B => y.method_on_B() trait B extends Base { def method_on_B(): Int } case z:C => z.method_on_C() … case u:D => u.method_on_D() object objA extends traitA { … } case v:E => v.method_on_E() object objB extends traitB { … } … … case q:H => q.method_on_H() obj = chooseRandom({objA, objB, …}) } 41

  42. Preliminary Evaluation (JVM HotSpot) obj match { trait Base extends N1, N2, N3, … N10 case x:A => x.method_on_A() trait A extends Base { def method_on_A(): Int } case y:B => y.method_on_B() trait B extends Base { def method_on_B(): Int } case z:C => z.method_on_C() … case u:D => u.method_on_D() object objA extends traitA { … } case v:E => v.method_on_E() object objB extends traitB { … } … … case q:H => q.method_on_H() obj = chooseRandom({objA, objB, …}) } 42

  43. Summary Dynamic subtype tests often fail (in some workloads) Worst-case linear search occurs (in production VMs) Bloom filters can enable fail-fast refutations (high probability) expected constant time + constant space + multiple inheritance + open hierarchy 43

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend