/*
 * Copyright (C) 2013-2021 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 "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
