/*
 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#pragma once

#include "IsoSubspace.h"
#include "JSCast.h"
#include "VM.h"
#include "Watchpoint.h"
#include "WriteBarrier.h"

namespace JSC {

// Allocate one of these if you'd like to infer a constant value. Writes to the value should use
// notifyWrite(). So long as exactly one value had ever been written and invalidate() has never been
// called, and you register a watchpoint, you can rely on the inferredValue() being the one true
// value.
//
// Commonly used for inferring singletons - in that case each allocation does notifyWrite(). But you
// can use it for other things as well.

class InferredValue final : public JSCell {
public:
    typedef JSCell Base;
    
    template<typename CellType>
    static IsoSubspace* subspaceFor(VM& vm)
    {
        return &vm.inferredValueSpace;
    }

    static InferredValue* create(VM&);
    
    static const bool needsDestruction = true;
    static void destroy(JSCell*);
    
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
    
    static void visitChildren(JSCell*, SlotVisitor&);
    
    DECLARE_INFO;
    
    // For the purpose of deciding whether or not to watch this variable, you only need
    // to inspect inferredValue(). If this returns something other than the empty
    // value, then it means that at all future safepoints, this watchpoint set will be
    // in one of these states:
    //
    //    IsWatched: in this case, the variable's value must still be the
    //        inferredValue.
    //
    //    IsInvalidated: in this case the variable's value may be anything but you'll
    //        either notice that it's invalidated and not install the watchpoint, or
    //        you will have been notified that the watchpoint was fired.
    JSValue inferredValue() { return m_value.get(); }

    // Forwards some WatchpointSet methods.
    WatchpointState state() const { return m_set.state(); }
    bool isStillValid() const { return m_set.isStillValid(); }
    bool hasBeenInvalidated() const { return m_set.hasBeenInvalidated(); }
    void add(Watchpoint* watchpoint) { m_set.add(watchpoint); }
    
    void notifyWrite(VM& vm, JSValue value, const FireDetail& detail)
    {
        if (LIKELY(m_set.stateOnJSThread() == IsInvalidated))
            return;
        notifyWriteSlow(vm, value, detail);
    }
    
    void notifyWrite(VM& vm, JSValue value, const char* reason)
    {
        if (LIKELY(m_set.stateOnJSThread() == IsInvalidated))
            return;
        notifyWriteSlow(vm, value, reason);
    }
    
    void invalidate(VM& vm, const FireDetail& detail)
    {
        m_value.clear();
        m_set.invalidate(vm, detail);
    }
    
    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
    
    void finalizeUnconditionally(VM&);
    
private:
    InferredValue(VM&);
    ~InferredValue();
    
    JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&);
    JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const char* reason);
    
    InlineWatchpointSet m_set;
    WriteBarrier<Unknown> m_value;
};

// FIXME: We could have an InlineInferredValue, which only allocates the InferredValue object when
// a notifyWrite() transitions us towards watching, and then clears the reference (allowing the object
// to die) when we get invalidated.

} // namespace JSC
