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

#import "config.h"

#import "JavaScriptCore.h"

#if JSC_OBJC_API_ENABLED

#import "APICast.h"
#import "IntegrityInlines.h"
#import "JITWorklist.h"
#import "JSManagedValueInternal.h"
#import "JSVirtualMachineInternal.h"
#import "JSVirtualMachinePrivate.h"
#import "JSWrapperMap.h"
#import "SigillCrashAnalyzer.h"
#import "SlotVisitorInlines.h"
#import <mutex>
#import <wtf/Lock.h>
#import <wtf/RetainPtr.h>

static NSMapTable *globalWrapperCache = 0;

static Lock wrapperCacheMutex;

static void initWrapperCache()
{
    ASSERT(!globalWrapperCache);
    NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
    NSPointerFunctionsOptions valueOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
    globalWrapperCache = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
}

static NSMapTable *wrapperCache() WTF_REQUIRES_LOCK(wrapperCacheMutex)
{
    if (!globalWrapperCache)
        initWrapperCache();
    return globalWrapperCache;
}

@interface JSVMWrapperCache : NSObject
+ (void)addWrapper:(JSVirtualMachine *)wrapper forJSContextGroupRef:(JSContextGroupRef)group;
+ (JSVirtualMachine *)wrapperForJSContextGroupRef:(JSContextGroupRef)group;
@end

@implementation JSVMWrapperCache

+ (void)addWrapper:(JSVirtualMachine *)wrapper forJSContextGroupRef:(JSContextGroupRef)group
{
    Locker locker { wrapperCacheMutex };
    NSMapInsert(wrapperCache(), group, (__bridge void*)wrapper);
}

+ (JSVirtualMachine *)wrapperForJSContextGroupRef:(JSContextGroupRef)group
{
    Locker locker { wrapperCacheMutex };
    return (__bridge JSVirtualMachine *)NSMapGet(wrapperCache(), group);
}

@end

@implementation JSVirtualMachine {
    JSContextGroupRef m_group;
    Lock m_externalDataMutex;
    RetainPtr<NSMapTable> m_contextCache;
    RetainPtr<NSMapTable> m_externalObjectGraph;
    RetainPtr<NSMapTable> m_externalRememberedSet;
}

- (instancetype)init
{
    JSContextGroupRef group = JSContextGroupCreate();
    self = [self initWithContextGroupRef:group];
    // The extra JSContextGroupRetain is balanced here.
    JSContextGroupRelease(group);
    return self;
}

- (instancetype)initWithContextGroupRef:(JSContextGroupRef)group
{
    self = [super init];
    if (!self)
        return nil;
    
    m_group = JSContextGroupRetain(group);
    
    NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
    NSPointerFunctionsOptions valueOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
    m_contextCache = adoptNS([[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0]);
    
    NSPointerFunctionsOptions weakIDOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
    NSPointerFunctionsOptions strongIDOptions = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality;
    m_externalObjectGraph = adoptNS([[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:strongIDOptions capacity:0]);

    NSPointerFunctionsOptions integerOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality;
    m_externalRememberedSet = adoptNS([[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:integerOptions capacity:0]);
   
    [JSVMWrapperCache addWrapper:self forJSContextGroupRef:group];
 
    return self;
}

- (void)dealloc
{
    JSContextGroupRelease(m_group);
    [super dealloc];
}

static id getInternalObjcObject(id object)
{
    if ([object isKindOfClass:[JSManagedValue class]]) {
        JSValue* value = [static_cast<JSManagedValue *>(object) value];
        if (!value)
            return nil;
        id temp = tryUnwrapObjcObject([value.context JSGlobalContextRef], [value JSValueRef]);
        if (temp)
            return temp;
        return object;
    }
    
    if ([object isKindOfClass:[JSValue class]]) {
        JSValue *value = static_cast<JSValue *>(object);
        object = tryUnwrapObjcObject([value.context JSGlobalContextRef], [value JSValueRef]);
    }

    return object;
}

- (bool)isOldExternalObject:(id)object
{
    JSC::VM* vm = toJS(m_group);
    return vm->heap.collectorSlotVisitor().containsOpaqueRoot((__bridge void*)object);
}

- (void)addExternalRememberedObject:(id)object
{
    Locker locker { m_externalDataMutex };
    ASSERT([self isOldExternalObject:object]);
    [m_externalRememberedSet setObject:@YES forKey:object];
}

- (void)addManagedReference:(id)object withOwner:(id)owner
{
    @autoreleasepool {
        if ([object isKindOfClass:[JSManagedValue class]])
            [object didAddOwner:owner];

        object = getInternalObjcObject(object);
        owner = getInternalObjcObject(owner);

        if (!object || !owner)
            return;

        JSC::JSLockHolder locker(toJS(m_group));
        if ([self isOldExternalObject:owner] && ![self isOldExternalObject:object])
            [self addExternalRememberedObject:owner];

        Locker externalDataMutexLocker { m_externalDataMutex };
        RetainPtr<NSMapTable> ownedObjects = [m_externalObjectGraph objectForKey:owner];
        if (!ownedObjects) {
            NSPointerFunctionsOptions weakIDOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
            NSPointerFunctionsOptions integerOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality;
            ownedObjects = adoptNS([[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:integerOptions capacity:1]);

            [m_externalObjectGraph setObject:ownedObjects.get() forKey:owner];
        }

        size_t count = reinterpret_cast<size_t>(NSMapGet(ownedObjects.get(), (__bridge void*)object));
        NSMapInsert(ownedObjects.get(), (__bridge void*)object, reinterpret_cast<void*>(count + 1));
    }
}

- (void)removeManagedReference:(id)object withOwner:(id)owner
{
    @autoreleasepool {
        if ([object isKindOfClass:[JSManagedValue class]])
            [object didRemoveOwner:owner];

        object = getInternalObjcObject(object);
        owner = getInternalObjcObject(owner);

        if (!object || !owner)
            return;

        JSC::JSLockHolder locker(toJS(m_group));

        Locker externalDataMutexLocker { m_externalDataMutex };
        NSMapTable *ownedObjects = [m_externalObjectGraph objectForKey:owner];
        if (!ownedObjects)
            return;

        size_t count = reinterpret_cast<size_t>(NSMapGet(ownedObjects, (__bridge void*)object));
        if (count > 1) {
            NSMapInsert(ownedObjects, (__bridge void*)object, reinterpret_cast<void*>(count - 1));
            return;
        }

        if (count == 1)
            NSMapRemove(ownedObjects, (__bridge void*)object);

        if (![ownedObjects count]) {
            [m_externalObjectGraph removeObjectForKey:owner];
            [m_externalRememberedSet removeObjectForKey:owner];
        }
    }
}

@end

@implementation JSVirtualMachine(Internal)

JSContextGroupRef getGroupFromVirtualMachine(JSVirtualMachine *virtualMachine)
{
    return virtualMachine->m_group;
}

+ (JSVirtualMachine *)virtualMachineWithContextGroupRef:(JSContextGroupRef)group
{
    auto virtualMachine = retainPtr([JSVMWrapperCache wrapperForJSContextGroupRef:group]);
    if (!virtualMachine)
        virtualMachine = adoptNS([[JSVirtualMachine alloc] initWithContextGroupRef:group]);
    return virtualMachine.autorelease();
}

- (JSContext *)contextForGlobalContextRef:(JSGlobalContextRef)globalContext
{
    return (__bridge JSContext *)NSMapGet(m_contextCache.get(), globalContext);
}

- (void)addContext:(JSContext *)wrapper forGlobalContextRef:(JSGlobalContextRef)globalContext
{
    NSMapInsert(m_contextCache.get(), globalContext, (__bridge void*)wrapper);
}

- (Lock&)externalDataMutex
{
    return m_externalDataMutex;
}

- (NSMapTable *)externalObjectGraph
{
    return m_externalObjectGraph.get();
}

- (NSMapTable *)externalRememberedSet
{
    return m_externalRememberedSet.get();
}

- (void)shrinkFootprintWhenIdle
{
    JSC::VM* vm = toJS(m_group);
    JSC::JSLockHolder locker(vm);
    vm->shrinkFootprintWhenIdle();
}

+ (NSUInteger)setNumberOfDFGCompilerThreads:(NSUInteger)numberOfThreads
{
#if ENABLE(DFG_JIT)
    return JSC::JITWorklist::ensureGlobalWorklist().setMaximumNumberOfConcurrentDFGCompilations(numberOfThreads);
#else
    return 0;
#endif // ENABLE(DFG_JIT)
}

+ (NSUInteger)setNumberOfFTLCompilerThreads:(NSUInteger)numberOfThreads
{
#if ENABLE(DFG_JIT)
    return JSC::JITWorklist::ensureGlobalWorklist().setMaximumNumberOfConcurrentFTLCompilations(numberOfThreads);
#else
    return 0;
#endif // ENABLE(DFG_JIT)
}

- (JSContextGroupRef)JSContextGroupRef
{
    return m_group;
}

- (BOOL)isWebThreadAware
{
    JSC::VM* vm = toJS(m_group);
    return vm->apiLock().isWebThreadAware();
}

+ (void)setCrashOnVMCreation:(BOOL)shouldCrash
{
    JSC::VM::setCrashOnVMCreation(shouldCrash);
}

@end

static void scanExternalObjectGraph(JSC::VM& vm, JSC::AbstractSlotVisitor& visitor, void* root, bool lockAcquired)
{
    @autoreleasepool {
        JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:toRef(&vm)];
        if (!virtualMachine)
            return;
        NSMapTable *externalObjectGraph = [virtualMachine externalObjectGraph];
        Lock& externalDataMutex = [virtualMachine externalDataMutex];
        Vector<void*> stack;
        stack.append(root);
        while (!stack.isEmpty()) {
            void* nextRoot = stack.last();
            stack.removeLast();
            if (!visitor.addOpaqueRoot(nextRoot))
                continue;

            auto appendOwnedObjects = [&] {
                NSMapTable *ownedObjects = [externalObjectGraph objectForKey:(__bridge id)nextRoot];
                for (id ownedObject in ownedObjects)
                    stack.append((__bridge void*)ownedObject);
            };

            if (lockAcquired)
                appendOwnedObjects();
            else {
                Locker locker { externalDataMutex };
                appendOwnedObjects();
            }
        }
    }
}

void scanExternalObjectGraph(JSC::VM& vm, JSC::AbstractSlotVisitor& visitor, void* root)
{
    bool lockAcquired = false;
    scanExternalObjectGraph(vm, visitor, root, lockAcquired);
}

void scanExternalRememberedSet(JSC::VM& vm, JSC::AbstractSlotVisitor& visitor)
{
    @autoreleasepool {
        JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:toRef(&vm)];
        if (!virtualMachine)
            return;
        Lock& externalDataMutex = [virtualMachine externalDataMutex];
        Locker locker { externalDataMutex };
        NSMapTable *externalObjectGraph = [virtualMachine externalObjectGraph];
        NSMapTable *externalRememberedSet = [virtualMachine externalRememberedSet];
        for (id key in externalRememberedSet) {
            NSMapTable *ownedObjects = [externalObjectGraph objectForKey:key];
            bool lockAcquired = true;
            for (id ownedObject in ownedObjects)
                scanExternalObjectGraph(vm, visitor, (__bridge void*)ownedObject, lockAcquired);
        }
        [externalRememberedSet removeAllObjects];
    }
}

#endif // JSC_OBJC_API_ENABLED
