tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

source.cpp (6747B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #define ANNOTATE(property) __attribute__((annotate(property)))
      8 
      9 extern void GC() ANNOTATE("GC Call");
     10 
     11 void GC() {
     12  // If the implementation is too trivial, the function body won't be emitted at
     13  // all.
     14  asm("");
     15 }
     16 
     17 // Special-cased function -- code that can run JS has an artificial edge to
     18 // js::RunScript.
     19 namespace js {
     20 void RunScript() { GC(); }
     21 }  // namespace js
     22 
     23 struct Cell {
     24  int f;
     25 } ANNOTATE("GC Thing");
     26 
     27 extern void foo();
     28 
     29 void bar() { GC(); }
     30 
     31 typedef void (*func_t)();
     32 
     33 class Base {
     34 public:
     35  int ANNOTATE("field annotation") dummy;
     36  virtual void someGC() ANNOTATE("Base pure virtual method") = 0;
     37  virtual void someGC(int) ANNOTATE("overloaded Base pure virtual method") = 0;
     38  virtual void sibGC() = 0;
     39  virtual void onBase() { bar(); }
     40  func_t functionField;
     41 
     42  // For now, this is just to verify that the plugin doesn't crash. The
     43  // analysis code does not yet look at this annotation or output it anywhere
     44  // (though it *is* being recorded.)
     45  static float testAnnotations() ANNOTATE("static func");
     46 
     47  // Similar, though sixgill currently completely ignores parameter annotations.
     48  static double testParamAnnotations(Cell& ANNOTATE("param annotation")
     49                                         ANNOTATE("second param annot") cell)
     50      ANNOTATE("static func") ANNOTATE("second func");
     51 };
     52 
     53 float Base::testAnnotations() {
     54  asm("");
     55  return 1.1;
     56 }
     57 
     58 double Base::testParamAnnotations(Cell& cell) {
     59  asm("");
     60  return 1.2;
     61 }
     62 
     63 class Super : public Base {
     64 public:
     65  virtual void ANNOTATE("Super pure virtual") noneGC() = 0;
     66  virtual void allGC() = 0;
     67  virtual void onSuper() { asm(""); }
     68  void nonVirtualFunc() { asm(""); }
     69 };
     70 
     71 class Sub1 : public Super {
     72 public:
     73  void noneGC() override { foo(); }
     74  void someGC() override ANNOTATE("Sub1 override") ANNOTATE("second attr") {
     75    foo();
     76  }
     77  void someGC(int) override ANNOTATE("Sub1 override for int overload") {
     78    foo();
     79  }
     80  void allGC() override {
     81    foo();
     82    bar();
     83  }
     84  void sibGC() override { foo(); }
     85  void onBase() override { foo(); }
     86 } ANNOTATE("CSU1") ANNOTATE("CSU2");
     87 
     88 class Sub2 : public Super {
     89 public:
     90  void noneGC() override { foo(); }
     91  void someGC() override {
     92    foo();
     93    bar();
     94  }
     95  void someGC(int) override {
     96    foo();
     97    bar();
     98  }
     99  void allGC() override {
    100    foo();
    101    bar();
    102  }
    103  void sibGC() override { foo(); }
    104 };
    105 
    106 class Sibling : public Base {
    107 public:
    108  virtual void noneGC() { foo(); }
    109  void someGC() override {
    110    foo();
    111    bar();
    112  }
    113  void someGC(int) override {
    114    foo();
    115    bar();
    116  }
    117  virtual void allGC() {
    118    foo();
    119    bar();
    120  }
    121  void sibGC() override { bar(); }
    122 };
    123 
    124 class AutoSuppressGC {
    125 public:
    126  AutoSuppressGC() {}
    127  ~AutoSuppressGC() {}
    128 } ANNOTATE("Suppress GC");
    129 
    130 void use(Cell*) { asm(""); }
    131 
    132 class nsISupports {
    133 public:
    134  virtual ANNOTATE("Can run script") void danger() { asm(""); }
    135 
    136  virtual ~nsISupports() = 0;
    137 };
    138 
    139 class nsIPrincipal : public nsISupports {
    140 public:
    141  ~nsIPrincipal() override {};
    142 };
    143 
    144 struct JSPrincipals {
    145  int debugToken;
    146  JSPrincipals() = default;
    147  virtual ~JSPrincipals() { GC(); }
    148 };
    149 
    150 class nsJSPrincipals : public nsIPrincipal, public JSPrincipals {
    151 public:
    152  void Release() { delete this; }
    153 };
    154 
    155 class SafePrincipals : public nsIPrincipal {
    156 public:
    157  ~SafePrincipals() { foo(); }
    158 };
    159 
    160 void f() {
    161  Sub1 s1;
    162  Sub2 s2;
    163 
    164  static Cell cell;
    165  {
    166    Cell* c1 = &cell;
    167    s1.noneGC();
    168    use(c1);
    169  }
    170  {
    171    Cell* c2 = &cell;
    172    s2.someGC();
    173    use(c2);
    174  }
    175  {
    176    Cell* c3 = &cell;
    177    s1.allGC();
    178    use(c3);
    179  }
    180  {
    181    Cell* c4 = &cell;
    182    s2.noneGC();
    183    use(c4);
    184  }
    185  {
    186    Cell* c5 = &cell;
    187    s2.someGC();
    188    use(c5);
    189  }
    190  {
    191    Cell* c6 = &cell;
    192    s2.allGC();
    193    use(c6);
    194  }
    195 
    196  Super* super = &s2;
    197  {
    198    Cell* c7 = &cell;
    199    super->noneGC();
    200    use(c7);
    201  }
    202  {
    203    Cell* c8 = &cell;
    204    super->someGC();
    205    use(c8);
    206  }
    207  {
    208    Cell* c9 = &cell;
    209    super->allGC();
    210    use(c9);
    211  }
    212 
    213  {
    214    Cell* c10 = &cell;
    215    s1.functionField();
    216    use(c10);
    217  }
    218  {
    219    Cell* c11 = &cell;
    220    super->functionField();
    221    use(c11);
    222  }
    223  {
    224    Cell* c12 = &cell;
    225    super->sibGC();
    226    use(c12);
    227  }
    228 
    229  Base* base = &s2;
    230  {
    231    Cell* c13 = &cell;
    232    base->sibGC();
    233    use(c13);
    234  }
    235 
    236  nsJSPrincipals pals;
    237  {
    238    Cell* c14 = &cell;
    239    nsISupports* p = &pals;
    240    p->danger();
    241    use(c14);
    242  }
    243 
    244  // Base defines, Sub1 overrides, static Super can call either.
    245  {
    246    Cell* c15 = &cell;
    247    super->onBase();
    248    use(c15);
    249  }
    250 
    251  {
    252    Cell* c16 = &cell;
    253    s2.someGC(7);
    254    use(c16);
    255  }
    256 
    257  {
    258    Cell* c17 = &cell;
    259    super->someGC(7);
    260    use(c17);
    261  }
    262 
    263  {
    264    nsJSPrincipals* princ = new nsJSPrincipals();
    265    Cell* c18 = &cell;
    266    delete princ;  // Can GC
    267    use(c18);
    268  }
    269 
    270  {
    271    nsJSPrincipals* princ = new nsJSPrincipals();
    272    nsISupports* supp = static_cast<nsISupports*>(princ);
    273    Cell* c19 = &cell;
    274    delete supp;  // Can GC
    275    use(c19);
    276  }
    277 
    278  {
    279    auto* safe = new SafePrincipals();
    280    Cell* c20 = &cell;
    281    delete safe;  // Cannot GC
    282    use(c20);
    283  }
    284 
    285  {
    286    auto* safe = new SafePrincipals();
    287    nsISupports* supp = static_cast<nsISupports*>(safe);
    288    Cell* c21 = &cell;
    289    delete supp;  // Compiler thinks destructor can GC.
    290    use(c21);
    291  }
    292 }
    293 
    294 template <typename Function>
    295 void Call1(Function&& f) {
    296  f();
    297 }
    298 
    299 template <typename Function>
    300 void Call2(Function&& f) {
    301  f();
    302 }
    303 
    304 void function_pointers() {
    305  Cell cell;
    306 
    307  {
    308    auto* f = GC;
    309    Cell* c22 = &cell;
    310    f();
    311    use(c22);
    312  }
    313 
    314  {
    315    auto* f = GC;
    316    auto*& g = f;
    317    Cell* c23 = &cell;
    318    g();
    319    use(c23);
    320  }
    321 
    322  {
    323    auto* f = GC;
    324    Call1([&] {
    325      Cell* c24 = &cell;
    326      f();
    327      use(c24);
    328    });
    329  }
    330 }
    331 
    332 // Use a separate function to test `mallocSizeOf` annotations. Bug 1872197:
    333 // functions that are specialized on a lambda function and call that function
    334 // will have that call get mixed up with other calls of lambdas defined within
    335 // the same function.
    336 void annotated_function_pointers() {
    337  Cell cell;
    338 
    339  // Variables with the specific name "mallocSizeOf" are
    340  // annotated to not GC. (Heh... even though here, they
    341  // *do* GC!)
    342 
    343  {
    344    auto* mallocSizeOf = GC;
    345    Cell* c25 = &cell;
    346    mallocSizeOf();
    347    use(c25);
    348  }
    349 
    350  {
    351    auto* f = GC;
    352    auto*& mallocSizeOf = f;
    353    Cell* c26 = &cell;
    354    mallocSizeOf();
    355    use(c26);
    356  }
    357 
    358  {
    359    auto* mallocSizeOf = GC;
    360    Call2([&] {
    361      Cell* c27 = &cell;
    362      mallocSizeOf();
    363      use(c27);
    364    });
    365  }
    366 }