/*
 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

#pragma once

#include "CallData.h"
#include "CellState.h"
#include "ConstructData.h"
#include "EnumerationMode.h"
#include "Heap.h"
#include "HeapCell.h"
#include "IndexingType.h"
#include "JSLock.h"
#include "JSTypeInfo.h"
#include "SlotVisitor.h"
#include "SubspaceAccess.h"
#include "TypedArrayType.h"
#include "WriteBarrier.h"

namespace JSC {

class CompleteSubspace;
class CopyVisitor;
class GCDeferralContext;
class ExecState;
class Identifier;
class JSArrayBufferView;
class JSDestructibleObject;
class JSGlobalObject;
class LLIntOffsetsExtractor;
class PropertyDescriptor;
class PropertyName;
class PropertyNameArray;
class Structure;
class JSCellLock;

enum class GCDeferralContextArgPresense {
    HasArg,
    DoesNotHaveArg
};

template<typename T> void* allocateCell(Heap&, size_t = sizeof(T));
template<typename T> void* tryAllocateCell(Heap&, size_t = sizeof(T));
template<typename T> void* allocateCell(Heap&, GCDeferralContext*, size_t = sizeof(T));
template<typename T> void* tryAllocateCell(Heap&, GCDeferralContext*, size_t = sizeof(T));

#define DECLARE_EXPORT_INFO                                                  \
    protected:                                                               \
        static JS_EXPORT_PRIVATE const ::JSC::ClassInfo s_info;              \
    public:                                                                  \
        static constexpr const ::JSC::ClassInfo* info() { return &s_info; }

#define DECLARE_INFO                                                         \
    protected:                                                               \
        static const ::JSC::ClassInfo s_info;                                \
    public:                                                                  \
        static constexpr const ::JSC::ClassInfo* info() { return &s_info; }

class JSCell : public HeapCell {
    friend class JSValue;
    friend class MarkedBlock;
    template<typename T>
    friend void* tryAllocateCellHelper(Heap&, size_t, GCDeferralContext*, AllocationFailureMode);

public:
    static const unsigned StructureFlags = 0;

    static const bool needsDestruction = false;

    // Don't call this directly. Call JSC::subspaceFor<Type>(vm) instead.
    // FIXME: Refer to Subspace by reference.
    // https://bugs.webkit.org/show_bug.cgi?id=166988
    template<typename CellType, SubspaceAccess>
    static CompleteSubspace* subspaceFor(VM&);

    static JSCell* seenMultipleCalleeObjects() { return bitwise_cast<JSCell*>(static_cast<uintptr_t>(1)); }

    enum CreatingEarlyCellTag { CreatingEarlyCell };
    JSCell(CreatingEarlyCellTag);
    
protected:
    JSCell(VM&, Structure*);
    JS_EXPORT_PRIVATE static void destroy(JSCell*);

public:
    // Querying the type.
    bool isString() const;
    bool isBigInt() const;
    bool isSymbol() const;
    bool isObject() const;
    bool isGetterSetter() const;
    bool isCustomGetterSetter() const;
    bool isProxy() const;
    bool isFunction(VM&);
    bool isCallable(VM&, CallType&, CallData&);
    bool isConstructor(VM&);
    bool isConstructor(VM&, ConstructType&, ConstructData&);
    bool inherits(VM&, const ClassInfo*) const;
    template<typename Target> bool inherits(VM&) const;
    bool isAPIValueWrapper() const;
    
    // Each cell has a built-in lock. Currently it's simply available for use if you need it. It's
    // a full-blown WTF::Lock. Note that this lock is currently used in JSArray and that lock's
    // ordering with the Structure lock is that the Structure lock must be acquired first.

    // We use this abstraction to make it easier to grep for places where we lock cells.
    // to lock a cell you can just do:
    // auto locker = holdLock(cell->cellLocker());
    JSCellLock& cellLock() { return *reinterpret_cast<JSCellLock*>(this); }
    
    JSType type() const;
    IndexingType indexingTypeAndMisc() const;
    IndexingType indexingMode() const;
    IndexingType indexingType() const;
    StructureID structureID() const { return m_structureID; }
    Structure* structure() const;
    Structure* structure(VM&) const;
    void setStructure(VM&, Structure*);
    void setStructureIDDirectly(StructureID id) { m_structureID = id; }
    void clearStructure() { m_structureID = 0; }

    TypeInfo::InlineTypeFlags inlineTypeFlags() const { return m_flags; }
    
    const char* className(VM&) const;

    // Extracting the value.
    JS_EXPORT_PRIVATE bool getString(ExecState*, String&) const;
    JS_EXPORT_PRIVATE String getString(ExecState*) const; // null string if not a string
    JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
    const JSObject* getObject() const; // NULL if not an object
        
    // Returns information about how to call/construct this cell as a function/constructor. May tell
    // you that the cell is not callable or constructor (default is that it's not either). If it
    // says that the function is callable, and the OverridesGetCallData type flag is set, and
    // this is an object, then typeof will return "function" instead of "object". These methods
    // cannot change their minds and must be thread-safe. They are sometimes called from compiler
    // threads.
    JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
    JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);

    // Basic conversions.
    JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
    bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
    bool toBoolean(ExecState*) const;
    TriState pureToBoolean() const;
    JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
    JSObject* toObject(ExecState*, JSGlobalObject*) const;

    void dump(PrintStream&) const;
    JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&);

    size_t estimatedSizeInBytes(VM&) const;
    JS_EXPORT_PRIVATE static size_t estimatedSize(JSCell*, VM&);

    static void visitChildren(JSCell*, SlotVisitor&);
    static void visitOutputConstraints(JSCell*, SlotVisitor&);

    JS_EXPORT_PRIVATE static void heapSnapshot(JSCell*, HeapSnapshotBuilder&);

    // Object operations, with the toObject operation included.
    const ClassInfo* classInfo(VM&) const;
    const MethodTable* methodTable(VM&) const;
    static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
    static bool putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
    bool putInline(ExecState*, PropertyName, JSValue, PutPropertySlot&);
        
    static bool deleteProperty(JSCell*, ExecState*, PropertyName);
    static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);

    static JSValue toThis(JSCell*, ExecState*, ECMAMode);

    static bool canUseFastGetOwnProperty(const Structure&);
    JSValue fastGetOwnProperty(VM&, Structure&, PropertyName);

    // The recommended idiom for using cellState() is to switch on it or perform an == comparison on it
    // directly. We deliberately avoid helpers for this, because we want transparency about how the various
    // CellState values influences our various algorithms. 
    CellState cellState() const { return m_cellState; }
    
    void setCellState(CellState data) const { const_cast<JSCell*>(this)->m_cellState = data; }
    
    bool atomicCompareExchangeCellStateWeakRelaxed(CellState oldState, CellState newState)
    {
        return WTF::atomicCompareExchangeWeakRelaxed(&m_cellState, oldState, newState);
    }

    CellState atomicCompareExchangeCellStateStrong(CellState oldState, CellState newState)
    {
        return WTF::atomicCompareExchangeStrong(&m_cellState, oldState, newState);
    }

    static ptrdiff_t structureIDOffset()
    {
        return OBJECT_OFFSETOF(JSCell, m_structureID);
    }

    static ptrdiff_t typeInfoFlagsOffset()
    {
        return OBJECT_OFFSETOF(JSCell, m_flags);
    }

    static ptrdiff_t typeInfoTypeOffset()
    {
        return OBJECT_OFFSETOF(JSCell, m_type);
    }

    // DO NOT store to this field. Always use a CAS loop, since some bits are flipped using CAS
    // from other threads due to the internal lock. One exception: you don't need the CAS if the
    // object has not escaped yet.
    static ptrdiff_t indexingTypeAndMiscOffset()
    {
        return OBJECT_OFFSETOF(JSCell, m_indexingTypeAndMisc);
    }

    static ptrdiff_t cellStateOffset()
    {
        return OBJECT_OFFSETOF(JSCell, m_cellState);
    }
    
    static const TypedArrayType TypedArrayStorageType = NotTypedArray;

    void setPerCellBit(bool);
    bool perCellBit() const;
protected:

    void finishCreation(VM&);
    void finishCreation(VM&, Structure*, CreatingEarlyCellTag);

    // Dummy implementations of override-able static functions for classes to put in their MethodTable
    static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
    static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);

    static uint32_t getEnumerableLength(ExecState*, JSObject*);
    static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    static NO_RETURN_DUE_TO_CRASH bool preventExtensions(JSObject*, ExecState*);
    static NO_RETURN_DUE_TO_CRASH bool isExtensible(JSObject*, ExecState*);
    static NO_RETURN_DUE_TO_CRASH bool setPrototype(JSObject*, ExecState*, JSValue, bool);
    static NO_RETURN_DUE_TO_CRASH JSValue getPrototype(JSObject*, ExecState*);

    static String className(const JSObject*, VM&);
    static String toStringName(const JSObject*, ExecState*);
    JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
    static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
    static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);

private:
    friend class LLIntOffsetsExtractor;
    friend class JSCellLock;

    JS_EXPORT_PRIVATE JSObject* toObjectSlow(ExecState*, JSGlobalObject*) const;

    StructureID m_structureID;
    IndexingType m_indexingTypeAndMisc; // DO NOT store to this field. Always CAS.
    JSType m_type;
    TypeInfo::InlineTypeFlags m_flags;
    CellState m_cellState;
};

class JSCellLock : public JSCell {
public:
    void lock();
    bool tryLock();
    void unlock();
    bool isLocked() const;
private:
    JS_EXPORT_PRIVATE void lockSlow();
    JS_EXPORT_PRIVATE void unlockSlow();
};

// FIXME: Refer to Subspace by reference.
// https://bugs.webkit.org/show_bug.cgi?id=166988
template<typename Type>
inline auto subspaceFor(VM& vm)
{
    return Type::template subspaceFor<Type, SubspaceAccess::OnMainThread>(vm);
}

template<typename Type>
inline auto subspaceForConcurrently(VM& vm)
{
    return Type::template subspaceFor<Type, SubspaceAccess::Concurrently>(vm);
}

} // namespace JSC
