LCOV - code coverage report
Current view: top level - js/src/vm - PIC.h (source / functions) Hit Total Coverage
Test: output.info Lines: 39 58 67.2 %
Date: 2017-07-14 16:53:18 Functions: 12 15 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       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             : #ifndef vm_PIC_h
       8             : #define vm_PIC_h
       9             : 
      10             : #include "jsapi.h"
      11             : #include "jscntxt.h"
      12             : #include "jsfriendapi.h"
      13             : #include "jsobj.h"
      14             : 
      15             : #include "gc/Barrier.h"
      16             : #include "gc/Heap.h"
      17             : #include "gc/Marking.h"
      18             : 
      19             : #include "js/Value.h"
      20             : #include "vm/GlobalObject.h"
      21             : 
      22             : namespace js {
      23             : 
      24             : class Shape;
      25             : 
      26             : template <typename Category> class PICChain;
      27             : 
      28             : /*
      29             :  * The basic PICStub just has a pointer to the next stub.
      30             :  */
      31             : template <typename Category>
      32             : class PICStub
      33             : {
      34             :   friend class PICChain<Category>;
      35             :   private:
      36             :     typedef typename Category::Stub CatStub;
      37             :     typedef typename Category::Chain CatChain;
      38             : 
      39             :   protected:
      40             :     CatStub* next_;
      41             : 
      42          18 :     PICStub() : next_(nullptr) {}
      43             :     explicit PICStub(const CatStub* next) : next_(next) {
      44             :         MOZ_ASSERT(next_);
      45             :     }
      46             :     explicit PICStub(const CatStub& other) : next_(other.next_) {}
      47             : 
      48             :   public:
      49          18 :     CatStub* next() const {
      50          18 :         return next_;
      51             :     }
      52             : 
      53             :   protected:
      54           0 :     void append(CatStub* stub) {
      55           0 :         MOZ_ASSERT(!next_);
      56           0 :         MOZ_ASSERT(!stub->next_);
      57           0 :         next_ = stub;
      58           0 :     }
      59             : };
      60             : 
      61             : /*
      62             :  * The basic PIC just has a pointer to the list of stubs.
      63             :  */
      64             : template <typename Category>
      65             : class PICChain
      66             : {
      67             :   private:
      68             :     typedef typename Category::Stub CatStub;
      69             :     typedef typename Category::Chain CatChain;
      70             : 
      71             :   protected:
      72             :     CatStub* stubs_;
      73             : 
      74          18 :     PICChain() : stubs_(nullptr) {}
      75             :     // PICs should never be copy constructed.
      76             :     PICChain(const PICChain<Category>& other) = delete;
      77             : 
      78             :   public:
      79          55 :     CatStub* stubs() const {
      80          55 :         return stubs_;
      81             :     }
      82             : 
      83          18 :     void addStub(CatStub* stub) {
      84          18 :         MOZ_ASSERT(stub);
      85          18 :         MOZ_ASSERT(!stub->next());
      86          18 :         if (!stubs_) {
      87          18 :             stubs_ = stub;
      88          18 :             return;
      89             :         }
      90             : 
      91           0 :         CatStub* cur = stubs_;
      92           0 :         while (cur->next())
      93           0 :             cur = cur->next();
      94           0 :         cur->append(stub);
      95             :     }
      96             : 
      97          18 :     unsigned numStubs() const {
      98          18 :         unsigned count = 0;
      99          18 :         for (CatStub* stub = stubs_; stub; stub = stub->next())
     100           0 :             count++;
     101          18 :         return count;
     102             :     }
     103             : 
     104           0 :     void removeStub(CatStub* stub, CatStub* previous) {
     105           0 :         if (previous) {
     106           0 :             MOZ_ASSERT(previous->next() == stub);
     107           0 :             previous->next_ = stub->next();
     108             :         } else {
     109           0 :             MOZ_ASSERT(stub == stubs_);
     110           0 :             stubs_ = stub->next();
     111             :         }
     112           0 :         js_delete(stub);
     113           0 :     }
     114             : };
     115             : 
     116             : /*
     117             :  *  ForOfPIC defines a PIC category for optimizing for-of operations.
     118             :  */
     119             : struct ForOfPIC
     120             : {
     121             :     /* Forward declarations so template-substitution works. */
     122             :     class Stub;
     123             :     class Chain;
     124             : 
     125             :     ForOfPIC() = delete;
     126             :     ForOfPIC(const ForOfPIC& other) = delete;
     127             : 
     128             :     typedef PICStub<ForOfPIC> BaseStub;
     129             :     typedef PICChain<ForOfPIC> BaseChain;
     130             : 
     131             :     /*
     132             :      * A ForOfPIC has only one kind of stub for now: one that holds the shape
     133             :      * of an array object that does not override its @@iterator property.
     134             :      */
     135             :     class Stub : public BaseStub
     136             :     {
     137             :       private:
     138             :         // Shape of matching array object.
     139             :         Shape* shape_;
     140             : 
     141             :       public:
     142          18 :         explicit Stub(Shape* shape)
     143          18 :           : BaseStub(),
     144          18 :             shape_(shape)
     145             :         {
     146          18 :             MOZ_ASSERT(shape_);
     147          18 :         }
     148             : 
     149          37 :         Shape* shape() {
     150          37 :             return shape_;
     151             :         }
     152             :     };
     153             : 
     154             :     /*
     155             :      * A ForOfPIC chain holds the following:
     156             :      *
     157             :      *  Array.prototype (arrayProto_)
     158             :      *      To ensure that the incoming array has the standard proto.
     159             :      *
     160             :      *  Array.prototype's shape (arrayProtoShape_)
     161             :      *      To ensure that Array.prototype has not been modified.
     162             :      *
     163             :      *  ArrayIterator.prototype (arrayIteratorProto_)
     164             :      *  ArrayIterator.prototype's shape (arrayIteratorProtoShape_)
     165             :      *      To ensure that an ArrayIterator.prototype has not been modified.
     166             :      *
     167             :      *  Array.prototype's slot number for @@iterator (arrayProtoIteratorSlot_)
     168             :      *  Array.prototype's canonical value for @@iterator (canonicalIteratorFunc_)
     169             :      *      To quickly retrieve and ensure that the iterator constructor
     170             :      *      stored in the slot has not changed.
     171             :      *
     172             :      *  ArrayIterator.prototype's slot number for 'next' (arrayIteratorProtoNextSlot_)
     173             :      *  ArrayIterator.prototype's canonical value for 'next' (canonicalNextFunc_)
     174             :      *      To quickly retrieve and ensure that the 'next' method for ArrayIterator
     175             :      *      objects has not changed.
     176             :      */
     177           0 :     class Chain : public BaseChain
     178             :     {
     179             :       private:
     180             :         // Pointer to canonical Array.prototype and ArrayIterator.prototype
     181             :         GCPtrNativeObject arrayProto_;
     182             :         GCPtrNativeObject arrayIteratorProto_;
     183             : 
     184             :         // Shape of matching Array.prototype object, and slot containing
     185             :         // the @@iterator for it, and the canonical value.
     186             :         GCPtrShape arrayProtoShape_;
     187             :         uint32_t arrayProtoIteratorSlot_;
     188             :         GCPtrValue canonicalIteratorFunc_;
     189             : 
     190             :         // Shape of matching ArrayIteratorProto, and slot containing
     191             :         // the 'next' property, and the canonical value.
     192             :         GCPtrShape arrayIteratorProtoShape_;
     193             :         uint32_t arrayIteratorProtoNextSlot_;
     194             :         GCPtrValue canonicalNextFunc_;
     195             : 
     196             :         // Initialization flag marking lazy initialization of above fields.
     197             :         bool initialized_;
     198             : 
     199             :         // Disabled flag is set when we don't want to try optimizing anymore
     200             :         // because core objects were changed.
     201             :         bool disabled_;
     202             : 
     203             :         static const unsigned MAX_STUBS = 10;
     204             : 
     205             :       public:
     206          18 :         Chain()
     207          18 :           : BaseChain(),
     208             :             arrayProto_(nullptr),
     209             :             arrayIteratorProto_(nullptr),
     210             :             arrayProtoShape_(nullptr),
     211             :             arrayProtoIteratorSlot_(-1),
     212          36 :             canonicalIteratorFunc_(UndefinedValue()),
     213             :             arrayIteratorProtoShape_(nullptr),
     214             :             arrayIteratorProtoNextSlot_(-1),
     215             :             initialized_(false),
     216          54 :             disabled_(false)
     217          18 :         {}
     218             : 
     219             :         // Initialize the canonical iterator function.
     220             :         bool initialize(JSContext* cx);
     221             : 
     222             :         // Check if a given array object is optimized by this PIC.
     223             :         Stub* isArrayOptimized(ArrayObject* obj);
     224             : 
     225             :         // Try to optimize this chain for an object.
     226             :         bool tryOptimizeArray(JSContext* cx, HandleArrayObject array, bool* optimized);
     227             : 
     228             :         // Check if the global array-related objects have not been messed with
     229             :         // in a way that would disable this PIC.
     230             :         bool isArrayStateStillSane();
     231             : 
     232             :         // Check if ArrayIterator.next is still optimizable.
     233         137 :         inline bool isArrayNextStillSane() {
     234         548 :             return (arrayIteratorProto_->lastProperty() == arrayIteratorProtoShape_) &&
     235         411 :                 (arrayIteratorProto_->getSlot(arrayIteratorProtoNextSlot_) == canonicalNextFunc_);
     236             :         }
     237             : 
     238             :         void trace(JSTracer* trc);
     239             :         void sweep(FreeOp* fop);
     240             : 
     241             :       private:
     242             :         // Get a matching optimized stub for the given object.
     243             :         Stub* getMatchingStub(JSObject* obj);
     244             : 
     245             :         // Check if the given object is for-of optimizable with this PIC.
     246             :         bool isOptimizableArray(JSObject* obj);
     247             : 
     248             :         // Reset the PIC and all info associated with it.
     249             :         void reset(JSContext* cx);
     250             : 
     251             :         // Erase the stub chain.
     252             :         void eraseChain();
     253             :     };
     254             : 
     255             :     // Class for object that holds ForOfPIC chain.
     256             :     static const Class class_;
     257             : 
     258             :     static NativeObject* createForOfPICObject(JSContext* cx, Handle<GlobalObject*> global);
     259             : 
     260          63 :     static inline Chain* fromJSObject(NativeObject* obj) {
     261          63 :         MOZ_ASSERT(js::GetObjectClass(obj) == &ForOfPIC::class_);
     262          63 :         return (ForOfPIC::Chain*) obj->getPrivate();
     263             :     }
     264          63 :     static inline Chain* getOrCreate(JSContext* cx) {
     265          63 :         NativeObject* obj = cx->global()->getForOfPICObject();
     266          63 :         if (obj)
     267          45 :             return fromJSObject(obj);
     268          18 :         return create(cx);
     269             :     }
     270             :     static Chain* create(JSContext* cx);
     271             : };
     272             : 
     273             : 
     274             : } // namespace js
     275             : 
     276             : #endif /* vm_PIC_h */

Generated by: LCOV version 1.13