/*
 * Copyright (C) 2018 Igalia S.L.
 *
 * 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.
 */

#include "config.h"
#include "JSCVirtualMachine.h"

#include "JSCContextPrivate.h"
#include "JSCVirtualMachinePrivate.h"
#include "JSContextRef.h"
#include <wtf/HashMap.h>
#include <wtf/Lock.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/glib/WTFGType.h>

/**
 * JSCVirtualMachine:
 * @short_description: JavaScript Virtual Machine
 * @title: JSCVirtualMachine
 * @see_also: JSCContext
 *
 * JSCVirtualMachine represents a group of JSCContext<!-- -->s. It allows
 * concurrent JavaScript execution by creating a different instance of
 * JSCVirtualMachine in each thread.
 *
 * To create a group of JSCContext<!-- -->s pass the same JSCVirtualMachine
 * instance to every JSCContext constructor.
 */

struct _JSCVirtualMachinePrivate {
    JSContextGroupRef jsContextGroup;
    HashMap<JSGlobalContextRef, JSCContext*> contextCache;
};

WEBKIT_DEFINE_TYPE(JSCVirtualMachine, jsc_virtual_machine, G_TYPE_OBJECT)

static Lock wrapperCacheMutex;

static HashMap<JSContextGroupRef, JSCVirtualMachine*>& wrapperMap() WTF_REQUIRES_LOCK(wrapperCacheMutex)
{
    static LazyNeverDestroyed<HashMap<JSContextGroupRef, JSCVirtualMachine*>> shared;
    static std::once_flag onceKey;
    std::call_once(onceKey, [&] {
        shared.construct();
    });
    return shared;
}

static void addWrapper(JSContextGroupRef group, JSCVirtualMachine* vm)
{
    Locker locker { wrapperCacheMutex };
    ASSERT(!wrapperMap().contains(group));
    wrapperMap().set(group, vm);
}

static void removeWrapper(JSContextGroupRef group)
{
    Locker locker { wrapperCacheMutex };
    ASSERT(wrapperMap().contains(group));
    wrapperMap().remove(group);
}

static void jscVirtualMachineSetContextGroup(JSCVirtualMachine *vm, JSContextGroupRef group)
{
    if (group) {
        ASSERT(!vm->priv->jsContextGroup);
        vm->priv->jsContextGroup = group;
        JSContextGroupRetain(vm->priv->jsContextGroup);
        addWrapper(vm->priv->jsContextGroup, vm);
    } else if (vm->priv->jsContextGroup) {
        removeWrapper(vm->priv->jsContextGroup);
        JSContextGroupRelease(vm->priv->jsContextGroup);
        vm->priv->jsContextGroup = nullptr;
    }
}

static void jscVirtualMachineEnsureContextGroup(JSCVirtualMachine *vm)
{
    if (vm->priv->jsContextGroup)
        return;

    auto* jsContextGroup = JSContextGroupCreate();
    jscVirtualMachineSetContextGroup(vm, jsContextGroup);
    JSContextGroupRelease(jsContextGroup);
}

static void jscVirtualMachineDispose(GObject* object)
{
    JSCVirtualMachine* vm = JSC_VIRTUAL_MACHINE(object);
    jscVirtualMachineSetContextGroup(vm, nullptr);

    G_OBJECT_CLASS(jsc_virtual_machine_parent_class)->dispose(object);
}

static void jsc_virtual_machine_class_init(JSCVirtualMachineClass* klass)
{
    GObjectClass* objClass = G_OBJECT_CLASS(klass);
    objClass->dispose = jscVirtualMachineDispose;
}

GRefPtr<JSCVirtualMachine> jscVirtualMachineGetOrCreate(JSContextGroupRef jsContextGroup)
{
    GRefPtr<JSCVirtualMachine> vm = wrapperMap().get(jsContextGroup);
    if (!vm) {
        vm = adoptGRef(jsc_virtual_machine_new());
        jscVirtualMachineSetContextGroup(vm.get(), jsContextGroup);
    }
    return vm;
}

JSContextGroupRef jscVirtualMachineGetContextGroup(JSCVirtualMachine* vm)
{
    jscVirtualMachineEnsureContextGroup(vm);
    return vm->priv->jsContextGroup;
}

void jscVirtualMachineAddContext(JSCVirtualMachine* vm, JSCContext* context)
{
    ASSERT(vm->priv->jsContextGroup);
    auto jsContext = jscContextGetJSContext(context);
    ASSERT(JSContextGetGroup(jsContext) == vm->priv->jsContextGroup);
    ASSERT(!vm->priv->contextCache.contains(jsContext));
    vm->priv->contextCache.set(jsContext, context);
}

void jscVirtualMachineRemoveContext(JSCVirtualMachine* vm, JSCContext* context)
{
    ASSERT(vm->priv->jsContextGroup);
    auto jsContext = jscContextGetJSContext(context);
    ASSERT(JSContextGetGroup(jsContext) == vm->priv->jsContextGroup);
    ASSERT(vm->priv->contextCache.contains(jsContext));
    vm->priv->contextCache.remove(jsContext);
}

JSCContext* jscVirtualMachineGetContext(JSCVirtualMachine* vm, JSGlobalContextRef jsContext)
{
    return vm->priv->contextCache.get(jsContext);
}

/**
 * jsc_virtual_machine_new:
 *
 * Create a new #JSCVirtualMachine.
 *
 * Returns: (transfer full): the newly created #JSCVirtualMachine.
 */
JSCVirtualMachine* jsc_virtual_machine_new()
{
    return JSC_VIRTUAL_MACHINE(g_object_new(JSC_TYPE_VIRTUAL_MACHINE, nullptr));
}
