/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef vm_PIC_h
#define vm_PIC_h

#include "jsapi.h"
#include "jscntxt.h"
#include "jsfriendapi.h"
#include "jsobj.h"

#include "gc/Barrier.h"
#include "gc/Heap.h"
#include "gc/Marking.h"

#include "js/Value.h"
#include "vm/GlobalObject.h"

namespace js {

class Shape;

template <typename Category> class PICChain;

/*
 * The basic PICStub just has a pointer to the next stub.
 */
template <typename Category>
class PICStub
{
  friend class PICChain<Category>;
  private:
    typedef typename Category::Stub CatStub;
    typedef typename Category::Chain CatChain;

  protected:
    CatStub* next_;

    PICStub() : next_(nullptr) {}
    explicit PICStub(const CatStub* next) : next_(next) {
        MOZ_ASSERT(next_);
    }
    explicit PICStub(const CatStub& other) : next_(other.next_) {}

  public:
    CatStub* next() const {
        return next_;
    }

  protected:
    void append(CatStub* stub) {
        MOZ_ASSERT(!next_);
        MOZ_ASSERT(!stub->next_);
        next_ = stub;
    }
};

/*
 * The basic PIC just has a pointer to the list of stubs.
 */
template <typename Category>
class PICChain
{
  private:
    typedef typename Category::Stub CatStub;
    typedef typename Category::Chain CatChain;

  protected:
    CatStub* stubs_;

    PICChain() : stubs_(nullptr) {}
    // PICs should never be copy constructed.
    PICChain(const PICChain<Category>& other) = delete;

  public:
    CatStub* stubs() const {
        return stubs_;
    }

    void addStub(CatStub* stub) {
        MOZ_ASSERT(stub);
        MOZ_ASSERT(!stub->next());
        if (!stubs_) {
            stubs_ = stub;
            return;
        }

        CatStub* cur = stubs_;
        while (cur->next())
            cur = cur->next();
        cur->append(stub);
    }

    unsigned numStubs() const {
        unsigned count = 0;
        for (CatStub* stub = stubs_; stub; stub = stub->next())
            count++;
        return count;
    }

    void removeStub(CatStub* stub, CatStub* previous) {
        if (previous) {
            MOZ_ASSERT(previous->next() == stub);
            previous->next_ = stub->next();
        } else {
            MOZ_ASSERT(stub == stubs_);
            stubs_ = stub->next();
        }
        js_delete(stub);
    }
};

/*
 *  ForOfPIC defines a PIC category for optimizing for-of operations.
 */
struct ForOfPIC
{
    /* Forward declarations so template-substitution works. */
    class Stub;
    class Chain;

    ForOfPIC() = delete;
    ForOfPIC(const ForOfPIC& other) = delete;

    typedef PICStub<ForOfPIC> BaseStub;
    typedef PICChain<ForOfPIC> BaseChain;

    /*
     * A ForOfPIC has only one kind of stub for now: one that holds the shape
     * of an array object that does not override its @@iterator property.
     */
    class Stub : public BaseStub
    {
      private:
        // Shape of matching array object.
        Shape* shape_;

      public:
        explicit Stub(Shape* shape)
          : BaseStub(),
            shape_(shape)
        {
            MOZ_ASSERT(shape_);
        }

        Shape* shape() {
            return shape_;
        }
    };

    /*
     * A ForOfPIC chain holds the following:
     *
     *  Array.prototype (arrayProto_)
     *      To ensure that the incoming array has the standard proto.
     *
     *  Array.prototype's shape (arrayProtoShape_)
     *      To ensure that Array.prototype has not been modified.
     *
     *  ArrayIterator.prototype (arrayIteratorProto_)
     *  ArrayIterator.prototype's shape (arrayIteratorProtoShape_)
     *      To ensure that an ArrayIterator.prototype has not been modified.
     *
     *  Array.prototype's slot number for @@iterator (arrayProtoIteratorSlot_)
     *  Array.prototype's canonical value for @@iterator (canonicalIteratorFunc_)
     *      To quickly retrieve and ensure that the iterator constructor
     *      stored in the slot has not changed.
     *
     *  ArrayIterator.prototype's slot number for 'next' (arrayIteratorProtoNextSlot_)
     *  ArrayIterator.prototype's canonical value for 'next' (canonicalNextFunc_)
     *      To quickly retrieve and ensure that the 'next' method for ArrayIterator
     *      objects has not changed.
     */
    class Chain : public BaseChain
    {
      private:
        // Pointer to canonical Array.prototype and ArrayIterator.prototype
        HeapPtrNativeObject arrayProto_;
        HeapPtrNativeObject arrayIteratorProto_;

        // Shape of matching Array.prototype object, and slot containing
        // the @@iterator for it, and the canonical value.
        HeapPtrShape arrayProtoShape_;
        uint32_t arrayProtoIteratorSlot_;
        HeapValue canonicalIteratorFunc_;

        // Shape of matching ArrayIteratorProto, and slot containing
        // the 'next' property, and the canonical value.
        HeapPtrShape arrayIteratorProtoShape_;
        uint32_t arrayIteratorProtoNextSlot_;
        HeapValue canonicalNextFunc_;

        // Initialization flag marking lazy initialization of above fields.
        bool initialized_;

        // Disabled flag is set when we don't want to try optimizing anymore
        // because core objects were changed.
        bool disabled_;

        static const unsigned MAX_STUBS = 10;

      public:
        Chain()
          : BaseChain(),
            arrayProto_(nullptr),
            arrayIteratorProto_(nullptr),
            arrayProtoShape_(nullptr),
            arrayProtoIteratorSlot_(-1),
            canonicalIteratorFunc_(UndefinedValue()),
            arrayIteratorProtoShape_(nullptr),
            arrayIteratorProtoNextSlot_(-1),
            initialized_(false),
            disabled_(false)
        {}

        // Initialize the canonical iterator function.
        bool initialize(JSContext* cx);

        // Check if a given array object is optimized by this PIC.
        Stub* isArrayOptimized(ArrayObject* obj);

        // Try to optimize this chain for an object.
        bool tryOptimizeArray(JSContext* cx, HandleArrayObject array, bool* optimized);

        // Check if the global array-related objects have not been messed with
        // in a way that would disable this PIC.
        bool isArrayStateStillSane();

        // Check if ArrayIterator.next is still optimizable.
        inline bool isArrayNextStillSane() {
            return (arrayIteratorProto_->lastProperty() == arrayIteratorProtoShape_) &&
                (arrayIteratorProto_->getSlot(arrayIteratorProtoNextSlot_) == canonicalNextFunc_);
        }

        void mark(JSTracer* trc);
        void sweep(FreeOp* fop);

      private:
        // Get a matching optimized stub for the given object.
        Stub* getMatchingStub(JSObject* obj);

        // Check if the given object is for-of optimizable with this PIC.
        bool isOptimizableArray(JSObject* obj);

        // Reset the PIC and all info associated with it.
        void reset(JSContext* cx);

        // Erase the stub chain.
        void eraseChain();
    };

    // Class for object that holds ForOfPIC chain.
    static const Class jsclass;

    static NativeObject* createForOfPICObject(JSContext* cx, Handle<GlobalObject*> global);

    static inline Chain* fromJSObject(NativeObject* obj) {
        MOZ_ASSERT(js::GetObjectClass(obj) == &ForOfPIC::jsclass);
        return (ForOfPIC::Chain*) obj->getPrivate();
    }
    static inline Chain* getOrCreate(JSContext* cx) {
        NativeObject* obj = cx->global()->getForOfPICObject();
        if (obj)
            return fromJSObject(obj);
        return create(cx);
    }
    static Chain* create(JSContext* cx);
};


} // namespace js

#endif /* vm_PIC_h */
