/*
 * Copyright (C) 2015 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. 
 */

#include "config.h"
#include "PropertyCondition.h"

#include "GetterSetter.h"
#include "JSCInlines.h"
#include "TrackedReferences.h"

namespace JSC {

namespace PropertyConditionInternal {
static bool verbose = false;
}

void PropertyCondition::dumpInContext(PrintStream& out, DumpContext* context) const
{
    if (!*this) {
        out.print("<invalid>");
        return;
    }
    
    out.print(m_kind, " of ", m_uid);
    switch (m_kind) {
    case Presence:
        out.print(" at ", offset(), " with attributes ", attributes());
        return;
    case Absence:
    case AbsenceOfSetEffect:
        out.print(" with prototype ", inContext(JSValue(prototype()), context));
        return;
    case Equivalence:
        out.print(" with ", inContext(requiredValue(), context));
        return;
    }
    RELEASE_ASSERT_NOT_REACHED();
}

void PropertyCondition::dump(PrintStream& out) const
{
    dumpInContext(out, nullptr);
}

bool PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(
    Structure* structure, JSObject* base) const
{
    if (PropertyConditionInternal::verbose) {
        dataLog(
            "Determining validity of ", *this, " with structure ", pointerDump(structure), " and base ",
            JSValue(base), " assuming impure property watchpoints are set.\n");
    }
    
    if (!*this) {
        if (PropertyConditionInternal::verbose)
            dataLog("Invalid because unset.\n");
        return false;
    }
    
    if (!structure->propertyAccessesAreCacheable()) {
        if (PropertyConditionInternal::verbose)
            dataLog("Invalid because accesses are not cacheable.\n");
        return false;
    }
    
    switch (m_kind) {
    case Presence: {
        unsigned currentAttributes;
        PropertyOffset currentOffset = structure->getConcurrently(uid(), currentAttributes);
        if (currentOffset != offset() || currentAttributes != attributes()) {
            if (PropertyConditionInternal::verbose) {
                dataLog(
                    "Invalid because we need offset, attributes to be ", offset(), ", ", attributes(),
                    " but they are ", currentOffset, ", ", currentAttributes, "\n");
            }
            return false;
        }
        return true;
    }
        
    case Absence: {
        if (structure->isDictionary()) {
            if (PropertyConditionInternal::verbose)
                dataLog("Invalid because it's a dictionary.\n");
            return false;
        }

        if (structure->hasPolyProto()) {
            // FIXME: I think this is too conservative. We can probably prove this if
            // we have the base. Anyways, we should make this work when integrating
            // OPC and poly proto.
            // https://bugs.webkit.org/show_bug.cgi?id=177339
            return false;
        }

        PropertyOffset currentOffset = structure->getConcurrently(uid());
        if (currentOffset != invalidOffset) {
            if (PropertyConditionInternal::verbose)
                dataLog("Invalid because the property exists at offset: ", currentOffset, "\n");
            return false;
        }

        if (structure->storedPrototypeObject() != prototype()) {
            if (PropertyConditionInternal::verbose) {
                dataLog(
                    "Invalid because the prototype is ", structure->storedPrototype(), " even though "
                    "it should have been ", JSValue(prototype()), "\n");
            }
            return false;
        }
        
        return true;
    }
    
    case AbsenceOfSetEffect: {
        if (structure->isDictionary()) {
            if (PropertyConditionInternal::verbose)
                dataLog("Invalid because it's a dictionary.\n");
            return false;
        }
        
        unsigned currentAttributes;
        PropertyOffset currentOffset = structure->getConcurrently(uid(), currentAttributes);
        if (currentOffset != invalidOffset) {
            if (currentAttributes & (PropertyAttribute::ReadOnly | PropertyAttribute::Accessor | PropertyAttribute::CustomAccessor)) {
                if (PropertyConditionInternal::verbose) {
                    dataLog(
                        "Invalid because we expected not to have a setter, but we have one at offset ",
                        currentOffset, " with attributes ", currentAttributes, "\n");
                }
                return false;
            }
        }

        if (structure->hasPolyProto()) {
            // FIXME: I think this is too conservative. We can probably prove this if
            // we have the base. Anyways, we should make this work when integrating
            // OPC and poly proto.
            // https://bugs.webkit.org/show_bug.cgi?id=177339
            return false;
        }
        
        if (structure->storedPrototypeObject() != prototype()) {
            if (PropertyConditionInternal::verbose) {
                dataLog(
                    "Invalid because the prototype is ", structure->storedPrototype(), " even though "
                    "it should have been ", JSValue(prototype()), "\n");
            }
            return false;
        }
        
        return true;
    }
        
    case Equivalence: {
        if (!base || base->structure() != structure) {
            // Conservatively return false, since we cannot verify this one without having the
            // object.
            if (PropertyConditionInternal::verbose) {
                dataLog(
                    "Invalid because we don't have a base or the base has the wrong structure: ",
                    RawPointer(base), "\n");
            }
            return false;
        }
        
        // FIXME: This is somewhat racy, and maybe more risky than we want.
        // https://bugs.webkit.org/show_bug.cgi?id=134641
        
        PropertyOffset currentOffset = structure->getConcurrently(uid());
        if (currentOffset == invalidOffset) {
            if (PropertyConditionInternal::verbose) {
                dataLog(
                    "Invalid because the base no long appears to have ", uid(), " on its structure: ",
                        RawPointer(base), "\n");
            }
            return false;
        }

        JSValue currentValue = base->getDirect(currentOffset);
        if (currentValue != requiredValue()) {
            if (PropertyConditionInternal::verbose) {
                dataLog(
                    "Invalid because the value is ", currentValue, " but we require ", requiredValue(),
                    "\n");
            }
            return false;
        }
        
        return true;
    } }
    
    RELEASE_ASSERT_NOT_REACHED();
    return false;
}

bool PropertyCondition::validityRequiresImpurePropertyWatchpoint(Structure* structure) const
{
    if (!*this)
        return false;
    
    switch (m_kind) {
    case Presence:
    case Absence:
    case Equivalence:
        return structure->needImpurePropertyWatchpoint();
    default:
        return false;
    }
}

bool PropertyCondition::isStillValid(Structure* structure, JSObject* base) const
{
    if (!isStillValidAssumingImpurePropertyWatchpoint(structure, base))
        return false;

    // Currently we assume that an impure property can cause a property to appear, and can also
    // "shadow" an existing JS property on the same object. Hence it affects both presence and
    // absence. It doesn't affect AbsenceOfSetEffect because impure properties aren't ever setters.
    switch (m_kind) {
    case Absence:
        if (structure->typeInfo().getOwnPropertySlotIsImpure() || structure->typeInfo().getOwnPropertySlotIsImpureForPropertyAbsence())
            return false;
        break;
    case Presence:
    case Equivalence:
        if (structure->typeInfo().getOwnPropertySlotIsImpure())
            return false;
        break;
    default:
        break;
    }
    
    return true;
}

bool PropertyCondition::isWatchableWhenValid(
    Structure* structure, WatchabilityEffort effort) const
{
    if (structure->transitionWatchpointSetHasBeenInvalidated())
        return false;
    
    switch (m_kind) {
    case Equivalence: {
        PropertyOffset offset = structure->getConcurrently(uid());
        
        // This method should only be called when some variant of isValid returned true, which
        // implies that we already confirmed that the structure knows of the property. We should
        // also have verified that the Structure is a cacheable dictionary, which means we
        // shouldn't have a TOCTOU race either.
        RELEASE_ASSERT(offset != invalidOffset);
        
        WatchpointSet* set = nullptr;
        switch (effort) {
        case MakeNoChanges:
            set = structure->propertyReplacementWatchpointSet(offset);
            break;
        case EnsureWatchability:
            set = structure->ensurePropertyReplacementWatchpointSet(
                *Heap::heap(structure)->vm(), offset);
            break;
        }
        
        if (!set || !set->isStillValid())
            return false;
        
        break;
    }
        
    default:
        break;
    }
    
    return true;
}

bool PropertyCondition::isWatchableAssumingImpurePropertyWatchpoint(
    Structure* structure, JSObject* base, WatchabilityEffort effort) const
{
    return isStillValidAssumingImpurePropertyWatchpoint(structure, base)
        && isWatchableWhenValid(structure, effort);
}

bool PropertyCondition::isWatchable(
    Structure* structure, JSObject* base, WatchabilityEffort effort) const
{
    return isStillValid(structure, base)
        && isWatchableWhenValid(structure, effort);
}

bool PropertyCondition::isStillLive() const
{
    if (hasPrototype() && prototype() && !Heap::isMarked(prototype()))
        return false;
    
    if (hasRequiredValue()
        && requiredValue()
        && requiredValue().isCell()
        && !Heap::isMarked(requiredValue().asCell()))
        return false;
    
    return true;
}

void PropertyCondition::validateReferences(const TrackedReferences& tracked) const
{
    if (hasPrototype())
        tracked.check(prototype());
    
    if (hasRequiredValue())
        tracked.check(requiredValue());
}

bool PropertyCondition::isValidValueForAttributes(VM& vm, JSValue value, unsigned attributes)
{
    bool attributesClaimAccessor = !!(attributes & PropertyAttribute::Accessor);
    bool valueClaimsAccessor = !!jsDynamicCast<GetterSetter*>(vm, value);
    return attributesClaimAccessor == valueClaimsAccessor;
}

bool PropertyCondition::isValidValueForPresence(VM& vm, JSValue value) const
{
    return isValidValueForAttributes(vm, value, attributes());
}

PropertyCondition PropertyCondition::attemptToMakeEquivalenceWithoutBarrier(VM& vm, JSObject* base) const
{
    Structure* structure = base->structure();
    if (!structure->isValidOffset(offset()))
        return PropertyCondition();
    JSValue value = base->getDirect(offset());
    if (!isValidValueForPresence(vm, value))
        return PropertyCondition();
    return equivalenceWithoutBarrier(uid(), value);
}

} // namespace JSC

namespace WTF {

void printInternal(PrintStream& out, JSC::PropertyCondition::Kind condition)
{
    switch (condition) {
    case JSC::PropertyCondition::Presence:
        out.print("Presence");
        return;
    case JSC::PropertyCondition::Absence:
        out.print("Absence");
        return;
    case JSC::PropertyCondition::AbsenceOfSetEffect:
        out.print("Absence");
        return;
    case JSC::PropertyCondition::Equivalence:
        out.print("Equivalence");
        return;
    }
    RELEASE_ASSERT_NOT_REACHED();
}

} // namespace WTF
