<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"

#include "sal.h"
#include "gcenv.structs.h"
#include "gcenv.base.h"

#include <stdlib.h>

#ifndef CPPCODEGEN

//
// This is the mechanism whereby multiple linked modules contribute their global data for initialization at
// startup of the application.
//
// ILC creates sections in the output obj file to mark the beginning and end of merged global data.
// It defines sentinel symbols that are used to get the addresses of the start and end of global data
// at runtime. The section names are platform-specific to match platform-specific linker conventions.
//
#if defined(_MSC_VER)

#pragma section(".modules$A", read)
#pragma section(".modules$Z", read)
extern "C" __declspec(allocate(".modules$A")) void * __modules_a[];
extern "C" __declspec(allocate(".modules$Z")) void * __modules_z[];

__declspec(allocate(".modules$A")) void * __modules_a[] = { nullptr };
__declspec(allocate(".modules$Z")) void * __modules_z[] = { nullptr };

//
// Each obj file compiled from managed code has a .modules$I section containing a pointer to its ReadyToRun
// data (which points at eager class constructors, frozen strings, etc).
//
// The #pragma ... /merge directive folds the book-end sections and all .modules$I sections from all input
// obj files into .rdata in alphabetical order.
//
#pragma comment(linker, "/merge:.modules=.rdata")

extern "C" void __managedcode_a();
extern "C" void __managedcode_z();

#else // _MSC_VER

#if defined(__APPLE__)

extern void * __modules_a[] __asm("section$start$__DATA$__modules");
extern void * __modules_z[] __asm("section$end$__DATA$__modules");
extern char __managedcode_a __asm("section$start$__TEXT$__managedcode");
extern char __managedcode_z __asm("section$end$__TEXT$__managedcode");

#else // __APPLE__

extern "C" void * __start___modules[];
extern "C" void * __stop___modules[];
static void * (&__modules_a)[] = __start___modules;
static void * (&__modules_z)[] = __stop___modules;

extern "C" char __start___managedcode;
extern "C" char __stop___managedcode;
static char& __managedcode_a = __start___managedcode;
static char& __managedcode_z = __stop___managedcode;

#endif // __APPLE__

#endif // _MSC_VER

#endif // !CPPCODEGEN

#ifdef CPPCODEGEN

#pragma warning(disable:4297)

extern "C" Object * RhNewObject(MethodTable * pMT);
extern "C" Object * RhNewArray(MethodTable * pMT, int32_t elements);
extern "C" void * RhTypeCast_IsInstanceOf(void * pObject, MethodTable * pMT);
extern "C" void * RhTypeCast_CheckCast(void * pObject, MethodTable * pMT);
extern "C" void RhpStelemRef(void * pArray, int index, void * pObj);
extern "C" void * RhpLdelemaRef(void * pArray, int index, MethodTable * pMT);
extern "C" __NORETURN void RhpThrowEx(void * pEx);

extern "C" Object * __allocate_object(MethodTable * pMT)
{
    return RhNewObject(pMT);
}

extern "C" Object * __allocate_array(size_t elements, MethodTable * pMT)
{
    return RhNewArray(pMT, (int32_t)elements); // TODO: type mismatch
}

extern "C" Object * __castclass(void * obj, MethodTable * pTargetMT)
{
    return (Object *)RhTypeCast_CheckCast(obj, pTargetMT);
}

extern "C" Object * __isinst(void * obj, MethodTable * pTargetMT)
{
    return (Object *)RhTypeCast_IsInstanceOf(obj, pTargetMT);
}

extern "C" void __stelem_ref(void * pArray, unsigned idx, void * obj)
{
    RhpStelemRef(pArray, idx, obj);
}

extern "C" void* __ldelema_ref(void * pArray, unsigned idx, MethodTable * type)
{
    return RhpLdelemaRef(pArray, idx, type);
}

extern "C" void __throw_exception(void * pEx)
{
    RhpThrowEx(pEx);
}

void __range_check_fail()
{
    throw "ThrowRangeOverflowException";
}

extern "C" void RhpReversePInvoke2(ReversePInvokeFrame* pRevFrame);
extern "C" void RhpReversePInvokeReturn2(ReversePInvokeFrame* pRevFrame);

void __reverse_pinvoke(ReversePInvokeFrame* pRevFrame)
{
    RhpReversePInvoke2(pRevFrame);
}

void __reverse_pinvoke_return(ReversePInvokeFrame* pRevFrame)
{
    RhpReversePInvokeReturn2(pRevFrame);
}

namespace System_Private_CoreLib { namespace System {

    class Object {
    public:
        MethodTable * get_EEType() { return *(MethodTable **)this; }
    };

    class Array : public Object {
    public:
        int32_t GetArrayLength() {
            return *(int32_t *)((void **)this + 1);
        }
        void * GetArrayData() {
            return (void **)this + 2;
        }
    };

    class String : public Object { public:
        static MethodTable * __getMethodTable();
    };

    class String__Array : public Object { public:
        static MethodTable * __getMethodTable();
    };

    class EETypePtr { public:
        intptr_t m_value;
    };

}; };

Object * __load_string_literal(const char * string)
{
    // TODO: Cache/intern string literals
    // TODO: Unicode string literals

    size_t len = strlen(string);

    Object * pString = RhNewArray(System_Private_CoreLib::System::String::__getMethodTable(), (int32_t)len);

    uint16_t * p = (uint16_t *)((char*)pString + sizeof(intptr_t) + sizeof(int32_t));
    for (size_t i = 0; i < len; i++)
        p[i] = string[i];
    return pString;
}

extern "C" void RhpThrowEx(void * pEx)
{
    throw "RhpThrowEx";
}
extern "C" void RhpThrowHwEx()
{
    throw "RhpThrowHwEx";
}
extern "C" void RhpCallCatchFunclet()
{
    throw "RhpCallCatchFunclet";
}
extern "C" void RhpCallFilterFunclet()
{
    throw "RhpCallFilterFunclet";
}
extern "C" void RhpCallFinallyFunclet()
{
    throw "RhpCallFinallyFunclet";
}
extern "C" void RhpUniversalTransition()
{
    throw "RhpUniversalTransition";
}
extern "C" void RhpUniversalTransition_DebugStepTailCall()
{
    throw "RhpUniversalTransition_DebugStepTailCall";
}

void* RtRHeaderWrapper();

#endif // CPPCODEGEN

extern "C" void __fail_fast()
{
    // TODO: FailFast
    throw "__fail_fast";
}

extern "C" void RhpEtwExceptionThrown()
{
    throw "RhpEtwExceptionThrown";
}

extern "C" bool REDHAWK_PALAPI PalInit();

#define DLL_PROCESS_ATTACH      1
extern "C" BOOL WINAPI RtuDllMain(HANDLE hPalInstance, DWORD dwReason, void* pvReserved);

extern "C" int32_t RhpEnableConservativeStackReporting();

extern "C" void RhpShutdown();

#ifndef CPPCODEGEN

extern "C" bool RhpRegisterCoffModule(void * pModule,
    void * pvStartRange, uint32_t cbRange,
    void ** pClasslibFunctions, uint32_t nClasslibFunctions);

extern "C" bool RhpRegisterUnixModule(void * pModule,
    void * pvStartRange, uint32_t cbRange,
    void ** pClasslibFunctions, uint32_t nClasslibFunctions);

#ifdef _WIN32
extern "C" void* WINAPI GetModuleHandleW(const wchar_t *);
#else
extern "C" void* WINAPI PalGetModuleHandleFromPointer(void* pointer);
#endif

extern "C" void GetRuntimeException();
extern "C" void FailFast();
extern "C" void AppendExceptionStackFrame();

typedef void(*pfn)();

static const pfn c_classlibFunctions[] = {
    &GetRuntimeException,
    &FailFast,
    nullptr, // &UnhandledExceptionHandler,
    &AppendExceptionStackFrame,
};

#endif // !CPPCODEGEN

extern "C" void InitializeModules(void ** modules, int count);

#if defined(_WIN32)
extern "C" int __managed__Main(int argc, wchar_t* argv[]);
int wmain(int argc, wchar_t* argv[])
#else
extern "C" int __managed__Main(int argc, char* argv[]);
int main(int argc, char* argv[])
#endif
{
    if (!PalInit())
        return -1;

    if (!RtuDllMain(NULL, DLL_PROCESS_ATTACH, NULL))
        return -1;

    if (!RhpEnableConservativeStackReporting())
        return -1;

#ifndef CPPCODEGEN
#if defined(_WIN32)
    if (!RhpRegisterCoffModule(GetModuleHandleW(NULL),
#else // _WIN32
    if (!RhpRegisterUnixModule(PalGetModuleHandleFromPointer((void*)&main),
#endif // _WIN32
        (void*)&__managedcode_a, (uint32_t)((char *)&__managedcode_z - (char*)&__managedcode_a),
        (void **)&c_classlibFunctions, _countof(c_classlibFunctions)))
    {
        return -1;
    }
#endif // !CPPCODEGEN

#ifdef CPPCODEGEN
    ReversePInvokeFrame frame;
    __reverse_pinvoke(&frame);
#endif

#ifndef CPPCODEGEN
    InitializeModules(__modules_a, (int)((__modules_z - __modules_a)));
#else // !CPPCODEGEN
    InitializeModules((void**)RtRHeaderWrapper(), 2);
#endif // !CPPCODEGEN

    int retval;
    try
    {
        retval = __managed__Main(argc, argv);
    }
    catch (const char* &e)
    {
        printf("Call to an unimplemented runtime method; execution cannot continue.\n");
        printf("Method: %s\n", e);
        retval = -1;
    }

#ifdef CPPCODEGEN
    __reverse_pinvoke_return(&frame);
#endif

    RhpShutdown();

    return retval;
}
<commit_msg>Fix native build warnings (#2448)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"

#include "sal.h"
#include "gcenv.structs.h"
#include "gcenv.base.h"

#include <stdlib.h>

#ifndef CPPCODEGEN

//
// This is the mechanism whereby multiple linked modules contribute their global data for initialization at
// startup of the application.
//
// ILC creates sections in the output obj file to mark the beginning and end of merged global data.
// It defines sentinel symbols that are used to get the addresses of the start and end of global data
// at runtime. The section names are platform-specific to match platform-specific linker conventions.
//
#if defined(_MSC_VER)

#pragma section(".modules$A", read)
#pragma section(".modules$Z", read)
extern "C" __declspec(allocate(".modules$A")) void * __modules_a[];
extern "C" __declspec(allocate(".modules$Z")) void * __modules_z[];

__declspec(allocate(".modules$A")) void * __modules_a[] = { nullptr };
__declspec(allocate(".modules$Z")) void * __modules_z[] = { nullptr };

//
// Each obj file compiled from managed code has a .modules$I section containing a pointer to its ReadyToRun
// data (which points at eager class constructors, frozen strings, etc).
//
// The #pragma ... /merge directive folds the book-end sections and all .modules$I sections from all input
// obj files into .rdata in alphabetical order.
//
#pragma comment(linker, "/merge:.modules=.rdata")

extern "C" void __managedcode_a();
extern "C" void __managedcode_z();

#else // _MSC_VER

#if defined(__APPLE__)

extern void * __modules_a[] __asm("section$start$__DATA$__modules");
extern void * __modules_z[] __asm("section$end$__DATA$__modules");
extern char __managedcode_a __asm("section$start$__TEXT$__managedcode");
extern char __managedcode_z __asm("section$end$__TEXT$__managedcode");

#else // __APPLE__

extern "C" void * __start___modules[];
extern "C" void * __stop___modules[];
static void * (&__modules_a)[] = __start___modules;
static void * (&__modules_z)[] = __stop___modules;

extern "C" char __start___managedcode;
extern "C" char __stop___managedcode;
static char& __managedcode_a = __start___managedcode;
static char& __managedcode_z = __stop___managedcode;

#endif // __APPLE__

#endif // _MSC_VER

#endif // !CPPCODEGEN

#ifdef CPPCODEGEN

#pragma warning(disable:4297)

extern "C" Object * RhNewObject(MethodTable * pMT);
extern "C" Object * RhNewArray(MethodTable * pMT, int32_t elements);
extern "C" void * RhTypeCast_IsInstanceOf(void * pObject, MethodTable * pMT);
extern "C" void * RhTypeCast_CheckCast(void * pObject, MethodTable * pMT);
extern "C" void RhpStelemRef(void * pArray, int index, void * pObj);
extern "C" void * RhpLdelemaRef(void * pArray, int index, MethodTable * pMT);
extern "C" __NORETURN void RhpThrowEx(void * pEx);

extern "C" Object * __allocate_object(MethodTable * pMT)
{
    return RhNewObject(pMT);
}

extern "C" Object * __allocate_array(size_t elements, MethodTable * pMT)
{
    return RhNewArray(pMT, (int32_t)elements); // TODO: type mismatch
}

extern "C" Object * __castclass(void * obj, MethodTable * pTargetMT)
{
    return (Object *)RhTypeCast_CheckCast(obj, pTargetMT);
}

extern "C" Object * __isinst(void * obj, MethodTable * pTargetMT)
{
    return (Object *)RhTypeCast_IsInstanceOf(obj, pTargetMT);
}

extern "C" void __stelem_ref(void * pArray, unsigned idx, void * obj)
{
    RhpStelemRef(pArray, idx, obj);
}

extern "C" void* __ldelema_ref(void * pArray, unsigned idx, MethodTable * type)
{
    return RhpLdelemaRef(pArray, idx, type);
}

extern "C" void __throw_exception(void * pEx)
{
    RhpThrowEx(pEx);
}

void __range_check_fail()
{
    throw "ThrowRangeOverflowException";
}

extern "C" void RhpReversePInvoke2(ReversePInvokeFrame* pRevFrame);
extern "C" void RhpReversePInvokeReturn2(ReversePInvokeFrame* pRevFrame);

void __reverse_pinvoke(ReversePInvokeFrame* pRevFrame)
{
    RhpReversePInvoke2(pRevFrame);
}

void __reverse_pinvoke_return(ReversePInvokeFrame* pRevFrame)
{
    RhpReversePInvokeReturn2(pRevFrame);
}

namespace System_Private_CoreLib { namespace System {

    class Object {
    public:
        MethodTable * get_EEType() { return *(MethodTable **)this; }
    };

    class Array : public Object {
    public:
        int32_t GetArrayLength() {
            return *(int32_t *)((void **)this + 1);
        }
        void * GetArrayData() {
            return (void **)this + 2;
        }
    };

    class String : public Object { public:
        static MethodTable * __getMethodTable();
    };

    class String__Array : public Object { public:
        static MethodTable * __getMethodTable();
    };

    class EETypePtr { public:
        intptr_t m_value;
    };

}; };

Object * __load_string_literal(const char * string)
{
    // TODO: Cache/intern string literals
    // TODO: Unicode string literals

    size_t len = strlen(string);

    Object * pString = RhNewArray(System_Private_CoreLib::System::String::__getMethodTable(), (int32_t)len);

    uint16_t * p = (uint16_t *)((char*)pString + sizeof(intptr_t) + sizeof(int32_t));
    for (size_t i = 0; i < len; i++)
        p[i] = string[i];
    return pString;
}

extern "C" void RhpThrowEx(void * pEx)
{
    throw "RhpThrowEx";
}
extern "C" void RhpThrowHwEx()
{
    throw "RhpThrowHwEx";
}
extern "C" void RhpCallCatchFunclet()
{
    throw "RhpCallCatchFunclet";
}
extern "C" void RhpCallFilterFunclet()
{
    throw "RhpCallFilterFunclet";
}
extern "C" void RhpCallFinallyFunclet()
{
    throw "RhpCallFinallyFunclet";
}
extern "C" void RhpUniversalTransition()
{
    throw "RhpUniversalTransition";
}
extern "C" void RhpUniversalTransition_DebugStepTailCall()
{
    throw "RhpUniversalTransition_DebugStepTailCall";
}

void* RtRHeaderWrapper();

#endif // CPPCODEGEN

extern "C" void __fail_fast()
{
    // TODO: FailFast
    printf("Call to an unimplemented runtime method; execution cannot continue.\n");
    printf("Method: __fail_fast\n");
    exit(-1);
}

extern "C" bool REDHAWK_PALAPI PalInit();

#define DLL_PROCESS_ATTACH      1
extern "C" BOOL WINAPI RtuDllMain(HANDLE hPalInstance, DWORD dwReason, void* pvReserved);

extern "C" int32_t RhpEnableConservativeStackReporting();

extern "C" void RhpShutdown();

#ifndef CPPCODEGEN

extern "C" bool RhpRegisterCoffModule(void * pModule,
    void * pvStartRange, uint32_t cbRange,
    void ** pClasslibFunctions, uint32_t nClasslibFunctions);

extern "C" bool RhpRegisterUnixModule(void * pModule,
    void * pvStartRange, uint32_t cbRange,
    void ** pClasslibFunctions, uint32_t nClasslibFunctions);

#ifdef _WIN32
extern "C" void* WINAPI GetModuleHandleW(const wchar_t *);
#else
extern "C" void* WINAPI PalGetModuleHandleFromPointer(void* pointer);
#endif

extern "C" void GetRuntimeException();
extern "C" void FailFast();
extern "C" void AppendExceptionStackFrame();

typedef void(*pfn)();

static const pfn c_classlibFunctions[] = {
    &GetRuntimeException,
    &FailFast,
    nullptr, // &UnhandledExceptionHandler,
    &AppendExceptionStackFrame,
};

#endif // !CPPCODEGEN

extern "C" void InitializeModules(void ** modules, int count);

#if defined(_WIN32)
extern "C" int __managed__Main(int argc, wchar_t* argv[]);
int wmain(int argc, wchar_t* argv[])
#else
extern "C" int __managed__Main(int argc, char* argv[]);
int main(int argc, char* argv[])
#endif
{
    if (!PalInit())
        return -1;

    if (!RtuDllMain(NULL, DLL_PROCESS_ATTACH, NULL))
        return -1;

    if (!RhpEnableConservativeStackReporting())
        return -1;

#ifndef CPPCODEGEN
#if defined(_WIN32)
    if (!RhpRegisterCoffModule(GetModuleHandleW(NULL),
#else // _WIN32
    if (!RhpRegisterUnixModule(PalGetModuleHandleFromPointer((void*)&main),
#endif // _WIN32
        (void*)&__managedcode_a, (uint32_t)((char *)&__managedcode_z - (char*)&__managedcode_a),
        (void **)&c_classlibFunctions, _countof(c_classlibFunctions)))
    {
        return -1;
    }
#endif // !CPPCODEGEN

#ifdef CPPCODEGEN
    ReversePInvokeFrame frame;
    __reverse_pinvoke(&frame);
#endif

#ifndef CPPCODEGEN
    InitializeModules(__modules_a, (int)((__modules_z - __modules_a)));
#else // !CPPCODEGEN
    InitializeModules((void**)RtRHeaderWrapper(), 2);
#endif // !CPPCODEGEN

    int retval;
    try
    {
        retval = __managed__Main(argc, argv);
    }
    catch (const char* &e)
    {
        printf("Call to an unimplemented runtime method; execution cannot continue.\n");
        printf("Method: %s\n", e);
        retval = -1;
    }

#ifdef CPPCODEGEN
    __reverse_pinvoke_return(&frame);
#endif

    RhpShutdown();

    return retval;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/protobuf/JSONEncoder.h"
#include "logjoin/SessionContext.h"

using namespace stx;

namespace cm {

JoinedEvent::JoinedEvent(
    RefPtr<msg::MessageSchema> _schema) :
    schema(_schema) {}

void JoinedEvent::addUInt32Field(const String& name, uint32_t val) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::UINT32) {
    return;
  }

  data.addChild(field_id, uint32_t(val));
}

void JoinedEvent::addBoolField(const String& name, bool val) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::BOOLEAN) {
    return;
  }

  if (val) {
    data.addChild(field_id, msg::TRUE);
  } else {
    data.addChild(field_id, msg::FALSE);
  }
}

void JoinedEvent::addStringField(const String& name, const String& value) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::STRING) {
    return;
  }

  data.addChild(field_id, value);
}

void JoinedEvent::addObject(
    const String& name,
    Function<void (JoinedEvent* ev)> fn) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::OBJECT) {
    return;
  }

  auto subschema = schema->fieldSchema(field_id);

  JoinedEvent subev(subschema);
  fn(&subev);
  subev.data.id = field_id;
  data.addChild(subev.data);
}

void JoinedEvent::toJSON(json::JSONOutputStream* json) const {
  json->beginObject();
  json->addObjectEntry("type");
  json->addString(schema->name());
  json->addComma();
  json->addObjectEntry("data");
  msg::JSONEncoder::encode(data, *schema, json);
  json->endObject();
}

SessionContext::SessionContext(
    TrackedSession session,
    RefPtr<CustomerConfigRef> cconf) :
    uuid(session.uuid),
    customer_key(session.customer_key),
    events(session.events),
    customer_config(cconf) {}

JoinedEvent* SessionContext::addOutputEvent(const String& evtype) {
  const auto& logjoin_cfg = customer_config->config.logjoin_config();

  for (const auto& evschema : logjoin_cfg.session_events()) {
    if (evschema.evtype() == evtype) {
      auto schema = msg::MessageSchema::decode(evschema.schema());

      auto event = new JoinedEvent(schema);
      output_events_.emplace_back(event);
      return event;
    }
  }

  RAISEF(kNotFoundError, "event schema not found: $0", evtype);
  return nullptr;
}

const Vector<ScopedPtr<JoinedEvent>>& SessionContext::outputEvents() const {
  return output_events_;
}

} // namespace cm
<commit_msg>debug log<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/protobuf/JSONEncoder.h"
#include "logjoin/SessionContext.h"

using namespace stx;

namespace cm {

JoinedEvent::JoinedEvent(
    RefPtr<msg::MessageSchema> _schema) :
    schema(_schema) {}

void JoinedEvent::addUInt32Field(const String& name, uint32_t val) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::UINT32) {
    return;
  }

  data.addChild(field_id, uint32_t(val));
}

void JoinedEvent::addBoolField(const String& name, bool val) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::BOOLEAN) {
    return;
  }

  if (val) {
    data.addChild(field_id, msg::TRUE);
  } else {
    data.addChild(field_id, msg::FALSE);
  }
}

void JoinedEvent::addStringField(const String& name, const String& value) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::STRING) {
    return;
  }

  data.addChild(field_id, value);
}

void JoinedEvent::addObject(
    const String& name,
    Function<void (JoinedEvent* ev)> fn) {
  if (!schema->hasField(name)) {
    return;
  }

  auto field_id = schema->fieldId(name);
  if (schema->fieldType(field_id) != msg::FieldType::OBJECT) {
    return;
  }

  auto subschema = schema->fieldSchema(field_id);

  JoinedEvent subev(subschema);
  fn(&subev);
  subev.data.id = field_id;
  data.addChild(subev.data);
}

void JoinedEvent::toJSON(json::JSONOutputStream* json) const {
  json->beginObject();
  json->addObjectEntry("type");
  json->addString(schema->name());
  json->addComma();
  json->addObjectEntry("data");
  msg::JSONEncoder::encode(data, *schema, json);
  json->endObject();
}

SessionContext::SessionContext(
    TrackedSession session,
    RefPtr<CustomerConfigRef> cconf) :
    uuid(session.uuid),
    customer_key(session.customer_key),
    events(session.events),
    customer_config(cconf) {}

JoinedEvent* SessionContext::addOutputEvent(const String& evtype) {
  const auto& logjoin_cfg = customer_config->config.logjoin_config();

  for (const auto& evschema : logjoin_cfg.session_events()) {
    if (evschema.evtype() == evtype) {
      auto schema = msg::MessageSchema::decode(evschema.schema());

      auto event = new JoinedEvent(schema);
      output_events_.emplace_back(event);
      return event;
    }
  }

  RAISEF(kNotFoundError, "event schema not found: $0 -- $1", evtype, logjoin_cfg.DebugString());
  return nullptr;
}

const Vector<ScopedPtr<JoinedEvent>>& SessionContext::outputEvents() const {
  return output_events_;
}

} // namespace cm
<|endoftext|>


<commit_before>
#include "accurate_intersections_approx.hpp"
#include "accurate_intersections_incprec.hpp"
#include "accurate_intersections_resultant.hpp"
#include "geometry.hpp"
#include "line.hpp"
#include "quadric.hpp"
#include "quadric_classify.hpp"
#include "timer.hpp"

#include <fstream>
#include <iomanip>
#include <list>
#include <random>

#include <signal.h>
#include <unistd.h>

struct GlobalVars {
  bool run = true;
} globals;

void sigInt(int signum) { globals.run = false; }

template <int dim, typename fptype>
std::list<Geometry::Quadric<dim, fptype>> parseQuadrics(
    const char *fname, int *minExp, int *maxExp) {
  std::ifstream file(fname);
  if(!file.is_open()) {
    return std::list<Geometry::Quadric<dim, fptype>>();
  }
  int buf = 0;
  file >> buf;
  if(minExp != NULL) {
    *minExp = buf;
  }
  file >> buf;
  if(maxExp != NULL) {
    *maxExp = buf;
  }
  if(*minExp > 0) {
    std::cout
        << "Cannot generate a line with these exponents\n"
        << *minExp << ", " << *maxExp << "\n";
    exit(1);
  }
  std::cout << "Using " << *minExp << ", " << *maxExp
            << " as the range of exponents\n";

  using Qf = Geometry::Quadric<dim, fptype>;
  int qtypeCount[QuadricClassify::QUADT_ERRORINVALID];
  for(int i = 0; i < QuadricClassify::QUADT_ERRORINVALID;
      i++)
    qtypeCount[i] = 0;
  std::list<Qf> quads;
  int imQuads = 0;
  int numQuads = 0;
  while(!file.eof()) {
    Qf q;
    file >> q;
    QuadricClassify::QuadType type =
        QuadricClassify::classifyQuadric(q);
    if(!QuadricClassify::isImaginary(type) &&
       type != QuadricClassify::QUADT_ERROR &&
       type != QuadricClassify::QUADT_DEGENERATE &&
       type != QuadricClassify::QUADT_ERRORINVALID) {
      quads.push_back(q);
      qtypeCount[type]++;
    } else {
      std::cout << "Quadric " << numQuads
                << " is invalid, returned type "
                << QuadricClassify::QuadTypeNames[type]
                << "\n";
      imQuads++;
    }
    numQuads++;
  }
  for(int i = 0; i < QuadricClassify::QUADT_ERRORINVALID;
      i++) {
    std::cout << qtypeCount[i] << " "
              << QuadricClassify::QuadTypeNames[i] << "\n";
  }
  return quads;
}

bool isSameInt(mpfr::mpreal int1, mpfr::mpreal int2) {
  /* Use a heuristic on truth to determine whether adjacent
   * intersections occur at the same place.
   * This will basically be a threshold on the largest
   * different bit in the mantissa.
   */
  /* A relative heuristic does not work when one (or both!)
   * is 0 */
  if(int1 == 0.0 || int2 == 0.0) {
    constexpr const double eps = 0.000001;
    return (mpfr::fabs(int1 - int2) < eps);
  }
  mpfr::mpreal largest =
      mpfr::max(mpfr::fabs(int1), mpfr::fabs(int2));
  mp_exp_t largestExp = largest.get_exp();
  mpfr::mpreal diff = mpfr::fabs(int1 - int2);
  int p1 = int1.getPrecision(), p2 = int2.getPrecision();
  int minPrec = std::min(p1, p2);
  mp_exp_t maxExp = largestExp - minPrec * 1 / 48,
           diffExp = diff.get_exp();
  return maxExp >= diffExp;
}

template <typename ListTest, typename ListTrue>
bool validateResults(ListTest &inter, ListTrue &truth) {
  /* Note that because the same method is used to determine
   * if an intersection is in the list, these lists will be
   * the same length
   */
  if(inter->size() != truth->size()) {
    return false;
  }
  auto j = truth->begin();
  for(auto i = inter->begin();
      i != inter->end() || j != truth->end(); i++, j++) {
    if(i->q != j->q || i->intPos != j->intPos) {
      return false;
    }
  }
  return true;
}

template <typename List>
int countIP(List inter) {
  int numIP = 0;
  for(auto i : *inter) numIP += i.incPrecCount();
  return numIP;
}

using rngAlg = std::mt19937_64;

template <int dim, typename fptype>
using randLineGen = Geometry::Line<dim, fptype> (*)(
    rngAlg &rng, int minExp, int maxExp);

template <int dim, typename fptype, typename cmpAlg>
std::shared_ptr<std::list<cmpAlg>> __attribute__((noinline))
runTest(
    std::list<Geometry::Quadric<dim, fptype>> &quads,
    Geometry::Line<dim, fptype> &line, Timer::Timer &timer,
    double eps = std::numeric_limits<fptype>::infinity()) {
  timer.startTimer();
  auto inter =
      Geometry::sortIntersections<dim, fptype, cmpAlg>(
          line, quads, fptype(eps));
  timer.stopTimer();
  return inter;
}

template <int dim, typename fptype>
void intersectionTest(
    std::list<Geometry::Quadric<dim, fptype>> &quads,
    std::ostream &results, const int numTests,
    randLineGen<dim, fptype> rlgf, int minExp, int maxExp) {
  /* First build a scene of quadrics.
   * Then generate random lines on a disk centered at the
   * intersection of the cylinders.
   * Then sort the intersections
   * Finally validate them with a higher precision sort
   */
  using Vf = Geometry::Vector<dim, fptype>;
  using Pf = Geometry::Point<dim, fptype>;
  using Lf = Geometry::Line<dim, fptype>;

  std::random_device rd;
  rngAlg engine(rd());

  const double eps = 0.75 / (2 * quads.size());

  constexpr const int numTestTypes = 3;
  Timer::Timer testTimes[numTestTypes];
  struct TimeArr {
    struct TestData {
      long long ns;
      int numIP;
      bool correct;
    } mpTime, fpTime, resTime;
  } *times = new struct TimeArr[numTests];
  /* Run the tests */
  int t;
  for(t = 0; t < numTests && globals.run; t++) {
    Lf line = rlgf(engine, minExp, maxExp);
    /* Then sort the intersections */
    auto resultant = runTest<
        dim, fptype,
        Geometry::IntersectionResultant<dim, fptype>>(
        quads, line, testTimes[0], eps);
    auto fpApproximate = runTest<
        dim, fptype,
        Geometry::IntersectionApproximate<dim, fptype>>(
        quads, line, testTimes[1], eps);
    auto mpApproximate = runTest<
        dim, fptype,
        Geometry::IntersectionIncreasedPrec<dim, fptype>>(
        quads, line, testTimes[2], eps);

    times[t].resTime.ns = testTimes[0].instant_ns();
    times[t].fpTime.ns = testTimes[1].instant_ns();
    times[t].mpTime.ns = testTimes[2].instant_ns();

    times[t].mpTime.correct =
        validateResults(mpApproximate, resultant);
    times[t].fpTime.correct =
        validateResults(fpApproximate, resultant);

    times[t].resTime.numIP = countIP(resultant);
    times[t].fpTime.numIP = countIP(fpApproximate);
    times[t].mpTime.numIP = countIP(mpApproximate);
  }
  /* Output all of the results */
  results << "Test #, Approximate Times (ns), Approximates "
             "Correct, Increased Precs, MP Time (ns), MP "
             "Correct, Resultants, Resultant Time (ns)\n";
  int resTotIP = 0;
  int fpTotIP = 0;
  int mpTotIP = 0;
  int mpTotIncorrect = 0;
  int fpTotIncorrect = 0;
  for(int i = 0; i < t; i++) {
    results << i + 1 << ", " << times[i].fpTime.ns << ", "
            << times[i].fpTime.correct << ", "
            << times[i].mpTime.numIP << ", "
            << times[i].mpTime.ns << ", "
            << times[i].mpTime.correct << ", "
            << times[i].resTime.numIP << ", "
            << times[i].resTime.ns << "\n";
    resTotIP += times[i].resTime.numIP;
    mpTotIP += times[i].mpTime.numIP;
    fpTotIncorrect += 1 - times[i].fpTime.correct;
    mpTotIncorrect += 1 - times[i].mpTime.correct;
  }
  results << "\n"
          << "Total FP Time: " << testTimes[1].elapsed_s()
          << "." << std::setw(9) << std::setfill('0')
          << testTimes[1].elapsed_ns() << "\n"
          << "Total FP Disagreements: " << fpTotIncorrect
          << "\n\n"

          << "Total MP Computations: " << mpTotIP << "\n"
          << "Total MP Time (s): "
          << testTimes[2].elapsed_s() << "." << std::setw(9)
          << std::setfill('0') << testTimes[2].elapsed_ns()
          << "\n"
          << "Total Resultant Disagreements: "
          << mpTotIncorrect << "\n\n"

          << "Total Resultant Computations: " << resTotIP
          << "\n"
          << "Total Resultant Time (s): "
          << testTimes[0].elapsed_s() << "." << std::setw(9)
          << std::setfill('0') << testTimes[0].elapsed_ns()
          << "\n";
  delete[] times;
}

void lockCPU() {
  const int numCPUs = sysconf(_SC_NPROCESSORS_ONLN);
  const int cpuSets =
      numCPUs / CPU_SETSIZE + ((numCPUs % CPU_SETSIZE) > 0);
  cpu_set_t *cpus = new cpu_set_t[cpuSets];
  const size_t cpuSize = sizeof(cpu_set_t[cpuSets]);
  sched_getaffinity(0, cpuSize, cpus);
  for(int i = 1; i < numCPUs; i++) CPU_CLR(i, cpus);
  CPU_SET(0, cpus);
  sched_setaffinity(0, cpuSize, cpus);
  delete[] cpus;
}

template <typename fptype>
bool checkExp(fptype fpVal, int minExp, int maxExp) {
  if(fpVal == fptype(0.0)) {
    return true;
  }
  GenericFP::fpconvert<fptype> *fpbits =
      reinterpret_cast<GenericFP::fpconvert<fptype> *>(
          &fpVal);
  int exponent = fpbits->exponent;
  exponent -= fpbits->centralExp;
  if(exponent < minExp || exponent > maxExp) {
    return false;
  } else {
    return true;
  }
}

template <int dim, typename fptype>
Geometry::Line<dim, fptype> defRandLine(rngAlg &rng,
                                        int minExp,
                                        int maxExp) {
  constexpr const fptype minPos = 0, maxPos = 1;
  std::uniform_real_distribution<fptype> genPos(minPos,
                                                maxPos);
  std::uniform_real_distribution<fptype> genDir(-1.0, 1.0);
  /* First build the line */
  Geometry::Vector<dim, fptype> lineDir;
  Geometry::Vector<dim, fptype> lineInt;
  for(int i = 0; i < dim; i++) {
    do {
      lineInt.set(i, genPos(rng));
    } while(checkExp(lineInt.get(i), minExp, maxExp) ==
            false);
    do {
      lineDir.set(i, genDir(rng));
    } while(checkExp(lineDir.get(i), minExp, maxExp) ==
            false);
  }
  return Geometry::Line<dim, fptype>(
      Geometry::Point<dim, fptype>(lineInt), lineInt);
}

template <int dim, typename fptype>
Geometry::Line<dim, fptype> nestedEllRandLine(rngAlg &rng,
                                              int minExp,
                                              int maxExp) {
  constexpr const fptype minPos = 0.0, maxPos = 1.0;
  std::uniform_real_distribution<fptype> genPos(minPos,
                                                maxPos);
  Geometry::Vector<dim, fptype> lineInt;
  for(int i = 0; i < dim; i++) {
    fptype tmp = genPos(rng);
    lineInt.set(i, genPos(rng));
  }
  /* Direct the line towards (1.0, 0.5, 0.5) */
  const Geometry::Vector<dim, fptype> destination(
      {1.0, 0.5, 0.5});
  Geometry::Vector<dim, fptype> lineDir =
      destination - lineInt;
  return Geometry::Line<dim, fptype>(
      Geometry::Point<dim, fptype>(lineInt), lineDir);
}

template <int dim, typename fptype>
Geometry::Line<dim, fptype> cylRandLine(rngAlg &rng,
                                        int minExp,
                                        int maxExp) {
  constexpr const fptype minPos = 0.375, maxPos = 0.625;
  std::uniform_real_distribution<fptype> genPos(minPos,
                                                maxPos);
  std::uniform_real_distribution<fptype> genDir(-1.0, 1.0);
  /* First build the line */
  Geometry::Vector<dim, fptype> lineDir;
  Geometry::Vector<dim, fptype> lineInt;
  lineInt.set(1, genPos(rng));
  for(int i = 0; i < dim; i++) {
    lineInt.set(i, lineInt.get(1));
    lineDir.set(i, genDir(rng));
  }
  lineInt.set(0, genPos(rng));
  return Geometry::Line<dim, fptype>(
      Geometry::Point<dim, fptype>(lineInt), lineInt);
}

int main(int argc, char **argv) {
  using fptype = float;
  constexpr const int dim = 3;
  lockCPU();
  std::list<Geometry::Quadric<dim, fptype>> quads;
  const char *outFName = "results";
  int numTests = 1e4;
  int minExp, maxExp;
  if(argc > 1) {
    quads = parseQuadrics<dim, fptype>(argv[1], &minExp,
                                       &maxExp);
  } else {
    quads = parseQuadrics<dim, fptype>("cylinders.csg",
                                       &minExp, &maxExp);
  }
  if(argc > 2) {
    outFName = argv[2];
  }
  if(argc > 3) {
    numTests = atoi(argv[3]);
  }
  randLineGen<dim, fptype> rlg = cylRandLine<dim, fptype>;
  if(argc > 4) {
    int lineGenAlg = atoi(argv[4]);
    switch(lineGenAlg) {
      case 1:
        rlg = nestedEllRandLine<dim, fptype>;
        break;
      case 2:
        rlg = cylRandLine<dim, fptype>;
        break;
      default:
        rlg = defRandLine<dim, fptype>;
    }
  }
  std::ofstream results(outFName);
  signal(SIGINT, sigInt);
  intersectionTest(quads, results, numTests, rlg, minExp,
                   maxExp);
  return 0;
}
<commit_msg>Fixed epsilon used, also fixed output<commit_after>
#include "accurate_intersections_approx.hpp"
#include "accurate_intersections_incprec.hpp"
#include "accurate_intersections_resultant.hpp"
#include "geometry.hpp"
#include "line.hpp"
#include "quadric.hpp"
#include "quadric_classify.hpp"
#include "timer.hpp"

#include <fstream>
#include <iomanip>
#include <list>
#include <random>

#include <signal.h>
#include <unistd.h>

struct GlobalVars {
  bool run = true;
} globals;

void sigInt(int signum) { globals.run = false; }

template <int dim, typename fptype>
std::list<Geometry::Quadric<dim, fptype>> parseQuadrics(
    const char *fname, int *minExp, int *maxExp) {
  std::ifstream file(fname);
  if(!file.is_open()) {
    return std::list<Geometry::Quadric<dim, fptype>>();
  }
  int buf = 0;
  file >> buf;
  if(minExp != NULL) {
    *minExp = buf;
  }
  file >> buf;
  if(maxExp != NULL) {
    *maxExp = buf;
  }
  if(*minExp > 0) {
    std::cout
        << "Cannot generate a line with these exponents\n"
        << *minExp << ", " << *maxExp << "\n";
    exit(1);
  }
  std::cout << "Using " << *minExp << ", " << *maxExp
            << " as the range of exponents\n";

  using Qf = Geometry::Quadric<dim, fptype>;
  int qtypeCount[QuadricClassify::QUADT_ERRORINVALID];
  for(int i = 0; i < QuadricClassify::QUADT_ERRORINVALID;
      i++)
    qtypeCount[i] = 0;
  std::list<Qf> quads;
  int imQuads = 0;
  int numQuads = 0;
  while(!file.eof()) {
    Qf q;
    file >> q;
    QuadricClassify::QuadType type =
        QuadricClassify::classifyQuadric(q);
    if(!QuadricClassify::isImaginary(type) &&
       type != QuadricClassify::QUADT_ERROR &&
       type != QuadricClassify::QUADT_DEGENERATE &&
       type != QuadricClassify::QUADT_ERRORINVALID) {
      quads.push_back(q);
      qtypeCount[type]++;
    } else {
      std::cout << "Quadric " << numQuads
                << " is invalid, returned type "
                << QuadricClassify::QuadTypeNames[type]
                << "\n";
      imQuads++;
    }
    numQuads++;
  }
  for(int i = 0; i < QuadricClassify::QUADT_ERRORINVALID;
      i++) {
    std::cout << qtypeCount[i] << " "
              << QuadricClassify::QuadTypeNames[i] << "\n";
  }
  return quads;
}

bool isSameInt(mpfr::mpreal int1, mpfr::mpreal int2) {
  /* Use a heuristic on truth to determine whether adjacent
   * intersections occur at the same place.
   * This will basically be a threshold on the largest
   * different bit in the mantissa.
   */
  /* A relative heuristic does not work when one (or both!)
   * is 0 */
  if(int1 == 0.0 || int2 == 0.0) {
    constexpr const double eps = 0.000001;
    return (mpfr::fabs(int1 - int2) < eps);
  }
  mpfr::mpreal largest =
      mpfr::max(mpfr::fabs(int1), mpfr::fabs(int2));
  mp_exp_t largestExp = largest.get_exp();
  mpfr::mpreal diff = mpfr::fabs(int1 - int2);
  int p1 = int1.getPrecision(), p2 = int2.getPrecision();
  int minPrec = std::min(p1, p2);
  mp_exp_t maxExp = largestExp - minPrec * 1 / 48,
           diffExp = diff.get_exp();
  return maxExp >= diffExp;
}

template <typename ListTest, typename ListTrue>
bool validateResults(ListTest &inter, ListTrue &truth) {
  /* Note that because the same method is used to determine
   * if an intersection is in the list, these lists will be
   * the same length
   */
  if(inter->size() != truth->size()) {
    return false;
  }
  auto j = truth->begin();
  for(auto i = inter->begin();
      i != inter->end() || j != truth->end(); i++, j++) {
    if(i->q != j->q || i->intPos != j->intPos) {
      return false;
    }
  }
  return true;
}

template <typename List>
int countIP(List inter) {
  int numIP = 0;
  for(auto i : *inter) numIP += i.incPrecCount();
  return numIP;
}

using rngAlg = std::mt19937_64;

template <int dim, typename fptype>
using randLineGen = Geometry::Line<dim, fptype> (*)(
    rngAlg &rng, int minExp, int maxExp);

template <int dim, typename fptype, typename cmpAlg>
std::shared_ptr<std::list<cmpAlg>> __attribute__((noinline))
runTest(
    std::list<Geometry::Quadric<dim, fptype>> &quads,
    Geometry::Line<dim, fptype> &line, Timer::Timer &timer,
    double eps = std::numeric_limits<fptype>::infinity()) {
  timer.startTimer();
  auto inter =
      Geometry::sortIntersections<dim, fptype, cmpAlg>(
          line, quads, fptype(eps));
  timer.stopTimer();
  return inter;
}

template <int dim, typename fptype>
void intersectionTest(
    std::list<Geometry::Quadric<dim, fptype>> &quads,
    std::ostream &results, const int numTests,
    randLineGen<dim, fptype> rlgf, int minExp, int maxExp) {
  /* First build a scene of quadrics.
   * Then generate random lines on a disk centered at the
   * intersection of the cylinders.
   * Then sort the intersections
   * Finally validate them with a higher precision sort
   */
  using Vf = Geometry::Vector<dim, fptype>;
  using Pf = Geometry::Point<dim, fptype>;
  using Lf = Geometry::Line<dim, fptype>;

  std::random_device rd;
  rngAlg engine(rd());

  const double eps = 1.52587890625e-5;

  constexpr const int numTestTypes = 3;
  Timer::Timer testTimes[numTestTypes];
  struct TimeArr {
    struct TestData {
      long long ns;
      int numIP;
      bool correct;
    } mpTime, fpTime, resTime;
  } *times = new struct TimeArr[numTests];
  /* Run the tests */
  int t;
  for(t = 0; t < numTests && globals.run; t++) {
    Lf line = rlgf(engine, minExp, maxExp);
    /* Then sort the intersections */
    auto resultant = runTest<
        dim, fptype,
        Geometry::IntersectionResultant<dim, fptype>>(
        quads, line, testTimes[0], eps);
    auto fpApproximate = runTest<
        dim, fptype,
        Geometry::IntersectionApproximate<dim, fptype>>(
        quads, line, testTimes[1], eps);
    auto mpApproximate = runTest<
        dim, fptype,
        Geometry::IntersectionIncreasedPrec<dim, fptype>>(
        quads, line, testTimes[2], eps);

    times[t].resTime.ns = testTimes[0].instant_ns();
    times[t].fpTime.ns = testTimes[1].instant_ns();
    times[t].mpTime.ns = testTimes[2].instant_ns();

    times[t].mpTime.correct =
        validateResults(mpApproximate, resultant);
    times[t].fpTime.correct =
        validateResults(fpApproximate, resultant);

    times[t].resTime.numIP = countIP(resultant);
    times[t].fpTime.numIP = countIP(fpApproximate);
    times[t].mpTime.numIP = countIP(mpApproximate);
  }
  /* Output all of the results */
  results << "Test #, Approximate Times (ns), Approximates "
             "Correct, Increased Precs, MP Time (ns), MP "
             "Correct, Resultants, Resultant Time (ns)\n";
  int resTotIP = 0;
  int fpTotIP = 0;
  int mpTotIP = 0;
  int mpTotIncorrect = 0;
  int fpTotIncorrect = 0;
  for(int i = 0; i < t; i++) {
    results << i + 1 << ", " << times[i].fpTime.ns << ", "
            << times[i].fpTime.correct << ", "
            << times[i].mpTime.numIP << ", "
            << times[i].mpTime.ns << ", "
            << times[i].mpTime.correct << ", "
            << times[i].resTime.numIP << ", "
            << times[i].resTime.ns << "\n";
    resTotIP += times[i].resTime.numIP;
    mpTotIP += times[i].mpTime.numIP;
    fpTotIncorrect += 1 - times[i].fpTime.correct;
    mpTotIncorrect += 1 - times[i].mpTime.correct;
  }
  results << "\n"
          << "Total FP Time: " << testTimes[1].elapsed_s()
          << "." << std::setw(9) << std::setfill('0')
          << testTimes[1].elapsed_ns() << "\n"
          << "Total FP Disagreements: " << fpTotIncorrect
          << "\n\n"

          << "Total MP Computations: " << mpTotIP << "\n"
          << "Total MP Time (s): "
          << testTimes[2].elapsed_s() << "." << std::setw(9)
          << std::setfill('0') << testTimes[2].elapsed_ns()
          << "\n"
          << "Total MP Disagreements: "
          << mpTotIncorrect << "\n\n"

          << "Total Resultant Computations: " << resTotIP
          << "\n"
          << "Total Resultant Time (s): "
          << testTimes[0].elapsed_s() << "." << std::setw(9)
          << std::setfill('0') << testTimes[0].elapsed_ns()
          << "\n";
  delete[] times;
}

void lockCPU() {
  const int numCPUs = sysconf(_SC_NPROCESSORS_ONLN);
  const int cpuSets =
      numCPUs / CPU_SETSIZE + ((numCPUs % CPU_SETSIZE) > 0);
  cpu_set_t *cpus = new cpu_set_t[cpuSets];
  const size_t cpuSize = sizeof(cpu_set_t[cpuSets]);
  sched_getaffinity(0, cpuSize, cpus);
  for(int i = 1; i < numCPUs; i++) CPU_CLR(i, cpus);
  CPU_SET(0, cpus);
  sched_setaffinity(0, cpuSize, cpus);
  delete[] cpus;
}

template <typename fptype>
bool checkExp(fptype fpVal, int minExp, int maxExp) {
  if(fpVal == fptype(0.0)) {
    return true;
  }
  GenericFP::fpconvert<fptype> *fpbits =
      reinterpret_cast<GenericFP::fpconvert<fptype> *>(
          &fpVal);
  int exponent = fpbits->exponent;
  exponent -= fpbits->centralExp;
  if(exponent < minExp || exponent > maxExp) {
    return false;
  } else {
    return true;
  }
}

template <int dim, typename fptype>
Geometry::Line<dim, fptype> defRandLine(rngAlg &rng,
                                        int minExp,
                                        int maxExp) {
  constexpr const fptype minPos = 0, maxPos = 1;
  std::uniform_real_distribution<fptype> genPos(minPos,
                                                maxPos);
  std::uniform_real_distribution<fptype> genDir(-1.0, 1.0);
  /* First build the line */
  Geometry::Vector<dim, fptype> lineDir;
  Geometry::Vector<dim, fptype> lineInt;
  for(int i = 0; i < dim; i++) {
    do {
      lineInt.set(i, genPos(rng));
    } while(checkExp(lineInt.get(i), minExp, maxExp) ==
            false);
    do {
      lineDir.set(i, genDir(rng));
    } while(checkExp(lineDir.get(i), minExp, maxExp) ==
            false);
  }
  return Geometry::Line<dim, fptype>(
      Geometry::Point<dim, fptype>(lineInt), lineInt);
}

template <int dim, typename fptype>
Geometry::Line<dim, fptype> nestedEllRandLine(rngAlg &rng,
                                              int minExp,
                                              int maxExp) {
  constexpr const fptype minPos = 0.0, maxPos = 1.0;
  std::uniform_real_distribution<fptype> genPos(minPos,
                                                maxPos);
  Geometry::Vector<dim, fptype> lineInt;
  for(int i = 0; i < dim; i++) {
    fptype tmp = genPos(rng);
    lineInt.set(i, genPos(rng));
  }
  /* Direct the line towards (1.0, 0.5, 0.5) */
  const Geometry::Vector<dim, fptype> destination(
      {1.0, 0.5, 0.5});
  Geometry::Vector<dim, fptype> lineDir =
      destination - lineInt;
  return Geometry::Line<dim, fptype>(
      Geometry::Point<dim, fptype>(lineInt), lineDir);
}

template <int dim, typename fptype>
Geometry::Line<dim, fptype> cylRandLine(rngAlg &rng,
                                        int minExp,
                                        int maxExp) {
  constexpr const fptype minPos = 0.375, maxPos = 0.625;
  std::uniform_real_distribution<fptype> genPos(minPos,
                                                maxPos);
  std::uniform_real_distribution<fptype> genDir(-1.0, 1.0);
  /* First build the line */
  Geometry::Vector<dim, fptype> lineDir;
  Geometry::Vector<dim, fptype> lineInt;
  lineInt.set(1, genPos(rng));
  for(int i = 0; i < dim; i++) {
    lineInt.set(i, lineInt.get(1));
    lineDir.set(i, genDir(rng));
  }
  lineInt.set(0, genPos(rng));
  return Geometry::Line<dim, fptype>(
      Geometry::Point<dim, fptype>(lineInt), lineInt);
}

int main(int argc, char **argv) {
  using fptype = float;
  constexpr const int dim = 3;
  lockCPU();
  std::list<Geometry::Quadric<dim, fptype>> quads;
  const char *outFName = "results";
  int numTests = 1e4;
  int minExp, maxExp;
  if(argc > 1) {
    quads = parseQuadrics<dim, fptype>(argv[1], &minExp,
                                       &maxExp);
  } else {
    quads = parseQuadrics<dim, fptype>("cylinders.csg",
                                       &minExp, &maxExp);
  }
  if(argc > 2) {
    outFName = argv[2];
  }
  if(argc > 3) {
    numTests = atoi(argv[3]);
  }
  randLineGen<dim, fptype> rlg = cylRandLine<dim, fptype>;
  if(argc > 4) {
    int lineGenAlg = atoi(argv[4]);
    switch(lineGenAlg) {
      case 1:
        rlg = nestedEllRandLine<dim, fptype>;
				std::cout << "Using the nested spheres random lines\n";
        break;
      case 2:
				std::cout << "Using the cylinders random lines\n";
        rlg = cylRandLine<dim, fptype>;
        break;
      default:
				std::cout << "Using the default random lines\n";
        rlg = defRandLine<dim, fptype>;
    }
  }
  std::ofstream results(outFName);
  signal(SIGINT, sigInt);
  intersectionTest(quads, results, numTests, rlg, minExp,
                   maxExp);
  return 0;
}
<|endoftext|>


<commit_before>#include "terminalpp/ansi/control_sequence.hpp"
#include <iostream>

namespace terminalpp { namespace ansi {

bool operator==(control_sequence const &lhs, control_sequence const &rhs)
{
    if (lhs.initiator == rhs.initiator
        && lhs.command == rhs.command
        && lhs.meta == rhs.meta)
    {
        // TODO: look up an algorithm to do this.  Mismatch? Equal_Range
        if (lhs.arguments.size() != rhs.arguments.size())
        {
            return false;
        }

        for (auto itl = lhs.arguments.begin(), itr = rhs.arguments.begin();
             itl != lhs.arguments.end();
             ++itl, ++itr)
        {
            if (*itl != *itr)
            {
                return false;
            }
        }

        return true;
    }

    return false;
}

}}
<commit_msg>Simplified ansi control sequence equality operator.<commit_after>#include "terminalpp/ansi/control_sequence.hpp"

namespace terminalpp { namespace ansi {

bool operator==(control_sequence const &lhs, control_sequence const &rhs)
{
    return lhs.initiator == rhs.initiator
        && lhs.command == rhs.command
        && lhs.meta == rhs.meta
        && lhs.arguments.size() == rhs.arguments.size()
        && lhs.arguments == rhs.arguments;
}

}}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 */

#ifndef __ARCH_SPARC_MISCREGFILE_HH__
#define __ARCH_SPARC_MISCREGFILE_HH__

#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
#include "cpu/cpuevent.hh"

#include <string>

namespace SparcISA
{
    //These functions map register indices to names
    std::string getMiscRegName(RegIndex);

    enum MiscRegIndex
    {
        /** Ancillary State Registers */
//        MISCREG_Y,
//        MISCREG_CCR,
        MISCREG_ASI,
        MISCREG_TICK,
        MISCREG_FPRS,
        MISCREG_PCR,
        MISCREG_PIC,
        MISCREG_GSR,
        MISCREG_SOFTINT_SET,
        MISCREG_SOFTINT_CLR,
        MISCREG_SOFTINT, /* 10 */
        MISCREG_TICK_CMPR,
        MISCREG_STICK,
        MISCREG_STICK_CMPR,

        /** Privilged Registers */
        MISCREG_TPC,
        MISCREG_TNPC,
        MISCREG_TSTATE,
        MISCREG_TT,
        MISCREG_PRIVTICK,
        MISCREG_TBA,
        MISCREG_PSTATE, /* 20 */
        MISCREG_TL,
        MISCREG_PIL,
        MISCREG_CWP,
//        MISCREG_CANSAVE,
//        MISCREG_CANRESTORE,
//        MISCREG_CLEANWIN,
//        MISCREG_OTHERWIN,
//        MISCREG_WSTATE,
        MISCREG_GL,

        /** Hyper privileged registers */
        MISCREG_HPSTATE, /* 30 */
        MISCREG_HTSTATE,
        MISCREG_HINTP,
        MISCREG_HTBA,
        MISCREG_HVER,
        MISCREG_STRAND_STS_REG,
        MISCREG_HSTICK_CMPR,

        /** Floating Point Status Register */
        MISCREG_FSR,

        /** MMU Internal Registers */
        MISCREG_MMU_P_CONTEXT,
        MISCREG_MMU_S_CONTEXT, /* 40 */
        MISCREG_MMU_PART_ID,
        MISCREG_MMU_LSU_CTRL,

        MISCREG_MMU_ITLB_C0_TSB_PS0,
        MISCREG_MMU_ITLB_C0_TSB_PS1,
        MISCREG_MMU_ITLB_C0_CONFIG,
        MISCREG_MMU_ITLB_CX_TSB_PS0,
        MISCREG_MMU_ITLB_CX_TSB_PS1,
        MISCREG_MMU_ITLB_CX_CONFIG,
        MISCREG_MMU_ITLB_SFSR,
        MISCREG_MMU_ITLB_TAG_ACCESS, /* 50 */

        MISCREG_MMU_DTLB_C0_TSB_PS0,
        MISCREG_MMU_DTLB_C0_TSB_PS1,
        MISCREG_MMU_DTLB_C0_CONFIG,
        MISCREG_MMU_DTLB_CX_TSB_PS0,
        MISCREG_MMU_DTLB_CX_TSB_PS1,
        MISCREG_MMU_DTLB_CX_CONFIG,
        MISCREG_MMU_DTLB_SFSR,
        MISCREG_MMU_DTLB_SFAR,
        MISCREG_MMU_DTLB_TAG_ACCESS,

        /** Scratchpad regiscers **/
        MISCREG_SCRATCHPAD_R0, /* 60 */
        MISCREG_SCRATCHPAD_R1,
        MISCREG_SCRATCHPAD_R2,
        MISCREG_SCRATCHPAD_R3,
        MISCREG_SCRATCHPAD_R4,
        MISCREG_SCRATCHPAD_R5,
        MISCREG_SCRATCHPAD_R6,
        MISCREG_SCRATCHPAD_R7,

        /* CPU Queue Registers */
        MISCREG_QUEUE_CPU_MONDO_HEAD,
        MISCREG_QUEUE_CPU_MONDO_TAIL,
        MISCREG_QUEUE_DEV_MONDO_HEAD, /* 70 */
        MISCREG_QUEUE_DEV_MONDO_TAIL,
        MISCREG_QUEUE_RES_ERROR_HEAD,
        MISCREG_QUEUE_RES_ERROR_TAIL,
        MISCREG_QUEUE_NRES_ERROR_HEAD,
        MISCREG_QUEUE_NRES_ERROR_TAIL,

        /* All the data for the TLB packed up in one register. */
        MISCREG_TLB_DATA,
        MISCREG_NUMMISCREGS
    };

    struct HPSTATE {
        const static uint64_t id = 0x800;   // this impl. dependent (id) field m
        const static uint64_t ibe = 0x400;
        const static uint64_t red = 0x20;
        const static uint64_t hpriv = 0x4;
        const static uint64_t tlz = 0x1;
    };

    struct PSTATE {
        const static int cle = 0x200;
        const static int tle = 0x100;
        const static int mm = 0xC0;
        const static int pef = 0x10;
        const static int am = 0x8;
        const static int priv = 0x4;
        const static int ie = 0x2;
    };

    const int NumMiscArchRegs = MISCREG_NUMMISCREGS;
    const int NumMiscRegs = MISCREG_NUMMISCREGS;

    // The control registers, broken out into fields
    class MiscRegFile
    {
      private:

        /* ASR Registers */
        //uint64_t y;		// Y (used in obsolete multiplication)
        //uint8_t ccr;		// Condition Code Register
        uint8_t asi;		// Address Space Identifier
        uint64_t tick;		// Hardware clock-tick counter
        uint8_t	fprs;		// Floating-Point Register State
        uint64_t gsr;		// General Status Register
        uint64_t softint;
        uint64_t tick_cmpr;	// Hardware tick compare registers
        uint64_t stick;		// Hardware clock-tick counter
        uint64_t stick_cmpr;	// Hardware tick compare registers

        /* Privileged Registers */
        uint64_t tpc[MaxTL];	// Trap Program Counter (value from
                                // previous trap level)
        uint64_t tnpc[MaxTL];	// Trap Next Program Counter (value from
                                // previous trap level)
        uint64_t tstate[MaxTL];	// Trap State
        uint16_t tt[MaxTL];	// Trap Type (Type of trap which occured
                                // on the previous level)
        uint64_t tba;		// Trap Base Address

        uint16_t pstate;	// Process State Register
        uint8_t tl;		// Trap Level
        uint8_t pil;		// Process Interrupt Register
        uint8_t cwp;		// Current Window Pointer
        //uint8_t cansave;	// Savable windows
        //uint8_t canrestore;	// Restorable windows
        //uint8_t cleanwin;	// Clean windows
        //uint8_t otherwin;	// Other windows
        //uint8_t wstate;		// Window State
        uint8_t gl;             // Global level register

        /** Hyperprivileged Registers */
        uint64_t hpstate;	// Hyperprivileged State Register
        uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register
        uint64_t hintp;
        uint64_t htba;		// Hyperprivileged Trap Base Address register
        uint64_t hstick_cmpr;	// Hardware tick compare registers

        uint64_t strandStatusReg;// Per strand status register

        /** Floating point misc registers. */
        uint64_t fsr;		// Floating-Point State Register

        /** MMU Internal Registers */
        uint16_t priContext;
        uint16_t secContext;
        uint16_t partId;
        uint64_t lsuCtrlReg;

        uint64_t iTlbC0TsbPs0;
        uint64_t iTlbC0TsbPs1;
        uint64_t iTlbC0Config;
        uint64_t iTlbCXTsbPs0;
        uint64_t iTlbCXTsbPs1;
        uint64_t iTlbCXConfig;
        uint64_t iTlbSfsr;
        uint64_t iTlbTagAccess;

        uint64_t dTlbC0TsbPs0;
        uint64_t dTlbC0TsbPs1;
        uint64_t dTlbC0Config;
        uint64_t dTlbCXTsbPs0;
        uint64_t dTlbCXTsbPs1;
        uint64_t dTlbCXConfig;
        uint64_t dTlbSfsr;
        uint64_t dTlbSfar;
        uint64_t dTlbTagAccess;

        uint64_t scratchPad[8];

        uint64_t cpu_mondo_head;
        uint64_t cpu_mondo_tail;
        uint64_t dev_mondo_head;
        uint64_t dev_mondo_tail;
        uint64_t res_error_head;
        uint64_t res_error_tail;
        uint64_t nres_error_head;
        uint64_t nres_error_tail;

        // These need to check the int_dis field and if 0 then
        // set appropriate bit in softint and checkinterrutps on the cpu
#if FULL_SYSTEM
        void  setFSRegWithEffect(int miscReg, const MiscReg &val,
                ThreadContext *tc);
        MiscReg readFSRegWithEffect(int miscReg, ThreadContext * tc);

        // Update interrupt state on softint or pil change
        void checkSoftInt(ThreadContext *tc);

        /** Process a tick compare event and generate an interrupt on the cpu if
         * appropriate. */
        void processTickCompare(ThreadContext *tc);
        void processSTickCompare(ThreadContext *tc);
        void processHSTickCompare(ThreadContext *tc);

        typedef CpuEventWrapper<MiscRegFile,
                &MiscRegFile::processTickCompare> TickCompareEvent;
        TickCompareEvent *tickCompare;

        typedef CpuEventWrapper<MiscRegFile,
                &MiscRegFile::processSTickCompare> STickCompareEvent;
        STickCompareEvent *sTickCompare;

        typedef CpuEventWrapper<MiscRegFile,
                &MiscRegFile::processHSTickCompare> HSTickCompareEvent;
        HSTickCompareEvent *hSTickCompare;
#endif
      public:

        void clear();

        MiscRegFile()
        {
            clear();
        }

        MiscReg readReg(int miscReg);

        MiscReg readRegWithEffect(int miscReg, ThreadContext *tc);

        void setReg(int miscReg, const MiscReg &val);

        void setRegWithEffect(int miscReg,
                const MiscReg &val, ThreadContext * tc);

        int getInstAsid()
        {
            return priContext | (uint32_t)partId << 13;
        }

        int getDataAsid()
        {
            return priContext | (uint32_t)partId << 13;
        }

        void serialize(std::ostream & os);

        void unserialize(Checkpoint * cp, const std::string & section);

        void copyMiscRegs(ThreadContext * tc);

      protected:

        bool isHyperPriv() { return (hpstate & (1 << 2)); }
        bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
        bool isNonPriv() { return !isPriv(); }
    };
}

#endif
<commit_msg>Add in a declaration of class Checkpoint rather than expecting it to come from some other include.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 */

#ifndef __ARCH_SPARC_MISCREGFILE_HH__
#define __ARCH_SPARC_MISCREGFILE_HH__

#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
#include "cpu/cpuevent.hh"

#include <string>

class Checkpoint;

namespace SparcISA
{
    //These functions map register indices to names
    std::string getMiscRegName(RegIndex);

    enum MiscRegIndex
    {
        /** Ancillary State Registers */
//        MISCREG_Y,
//        MISCREG_CCR,
        MISCREG_ASI,
        MISCREG_TICK,
        MISCREG_FPRS,
        MISCREG_PCR,
        MISCREG_PIC,
        MISCREG_GSR,
        MISCREG_SOFTINT_SET,
        MISCREG_SOFTINT_CLR,
        MISCREG_SOFTINT, /* 10 */
        MISCREG_TICK_CMPR,
        MISCREG_STICK,
        MISCREG_STICK_CMPR,

        /** Privilged Registers */
        MISCREG_TPC,
        MISCREG_TNPC,
        MISCREG_TSTATE,
        MISCREG_TT,
        MISCREG_PRIVTICK,
        MISCREG_TBA,
        MISCREG_PSTATE, /* 20 */
        MISCREG_TL,
        MISCREG_PIL,
        MISCREG_CWP,
//        MISCREG_CANSAVE,
//        MISCREG_CANRESTORE,
//        MISCREG_CLEANWIN,
//        MISCREG_OTHERWIN,
//        MISCREG_WSTATE,
        MISCREG_GL,

        /** Hyper privileged registers */
        MISCREG_HPSTATE, /* 30 */
        MISCREG_HTSTATE,
        MISCREG_HINTP,
        MISCREG_HTBA,
        MISCREG_HVER,
        MISCREG_STRAND_STS_REG,
        MISCREG_HSTICK_CMPR,

        /** Floating Point Status Register */
        MISCREG_FSR,

        /** MMU Internal Registers */
        MISCREG_MMU_P_CONTEXT,
        MISCREG_MMU_S_CONTEXT, /* 40 */
        MISCREG_MMU_PART_ID,
        MISCREG_MMU_LSU_CTRL,

        MISCREG_MMU_ITLB_C0_TSB_PS0,
        MISCREG_MMU_ITLB_C0_TSB_PS1,
        MISCREG_MMU_ITLB_C0_CONFIG,
        MISCREG_MMU_ITLB_CX_TSB_PS0,
        MISCREG_MMU_ITLB_CX_TSB_PS1,
        MISCREG_MMU_ITLB_CX_CONFIG,
        MISCREG_MMU_ITLB_SFSR,
        MISCREG_MMU_ITLB_TAG_ACCESS, /* 50 */

        MISCREG_MMU_DTLB_C0_TSB_PS0,
        MISCREG_MMU_DTLB_C0_TSB_PS1,
        MISCREG_MMU_DTLB_C0_CONFIG,
        MISCREG_MMU_DTLB_CX_TSB_PS0,
        MISCREG_MMU_DTLB_CX_TSB_PS1,
        MISCREG_MMU_DTLB_CX_CONFIG,
        MISCREG_MMU_DTLB_SFSR,
        MISCREG_MMU_DTLB_SFAR,
        MISCREG_MMU_DTLB_TAG_ACCESS,

        /** Scratchpad regiscers **/
        MISCREG_SCRATCHPAD_R0, /* 60 */
        MISCREG_SCRATCHPAD_R1,
        MISCREG_SCRATCHPAD_R2,
        MISCREG_SCRATCHPAD_R3,
        MISCREG_SCRATCHPAD_R4,
        MISCREG_SCRATCHPAD_R5,
        MISCREG_SCRATCHPAD_R6,
        MISCREG_SCRATCHPAD_R7,

        /* CPU Queue Registers */
        MISCREG_QUEUE_CPU_MONDO_HEAD,
        MISCREG_QUEUE_CPU_MONDO_TAIL,
        MISCREG_QUEUE_DEV_MONDO_HEAD, /* 70 */
        MISCREG_QUEUE_DEV_MONDO_TAIL,
        MISCREG_QUEUE_RES_ERROR_HEAD,
        MISCREG_QUEUE_RES_ERROR_TAIL,
        MISCREG_QUEUE_NRES_ERROR_HEAD,
        MISCREG_QUEUE_NRES_ERROR_TAIL,

        /* All the data for the TLB packed up in one register. */
        MISCREG_TLB_DATA,
        MISCREG_NUMMISCREGS
    };

    struct HPSTATE {
        const static uint64_t id = 0x800;   // this impl. dependent (id) field m
        const static uint64_t ibe = 0x400;
        const static uint64_t red = 0x20;
        const static uint64_t hpriv = 0x4;
        const static uint64_t tlz = 0x1;
    };

    struct PSTATE {
        const static int cle = 0x200;
        const static int tle = 0x100;
        const static int mm = 0xC0;
        const static int pef = 0x10;
        const static int am = 0x8;
        const static int priv = 0x4;
        const static int ie = 0x2;
    };

    const int NumMiscArchRegs = MISCREG_NUMMISCREGS;
    const int NumMiscRegs = MISCREG_NUMMISCREGS;

    // The control registers, broken out into fields
    class MiscRegFile
    {
      private:

        /* ASR Registers */
        //uint64_t y;		// Y (used in obsolete multiplication)
        //uint8_t ccr;		// Condition Code Register
        uint8_t asi;		// Address Space Identifier
        uint64_t tick;		// Hardware clock-tick counter
        uint8_t	fprs;		// Floating-Point Register State
        uint64_t gsr;		// General Status Register
        uint64_t softint;
        uint64_t tick_cmpr;	// Hardware tick compare registers
        uint64_t stick;		// Hardware clock-tick counter
        uint64_t stick_cmpr;	// Hardware tick compare registers

        /* Privileged Registers */
        uint64_t tpc[MaxTL];	// Trap Program Counter (value from
                                // previous trap level)
        uint64_t tnpc[MaxTL];	// Trap Next Program Counter (value from
                                // previous trap level)
        uint64_t tstate[MaxTL];	// Trap State
        uint16_t tt[MaxTL];	// Trap Type (Type of trap which occured
                                // on the previous level)
        uint64_t tba;		// Trap Base Address

        uint16_t pstate;	// Process State Register
        uint8_t tl;		// Trap Level
        uint8_t pil;		// Process Interrupt Register
        uint8_t cwp;		// Current Window Pointer
        //uint8_t cansave;	// Savable windows
        //uint8_t canrestore;	// Restorable windows
        //uint8_t cleanwin;	// Clean windows
        //uint8_t otherwin;	// Other windows
        //uint8_t wstate;		// Window State
        uint8_t gl;             // Global level register

        /** Hyperprivileged Registers */
        uint64_t hpstate;	// Hyperprivileged State Register
        uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register
        uint64_t hintp;
        uint64_t htba;		// Hyperprivileged Trap Base Address register
        uint64_t hstick_cmpr;	// Hardware tick compare registers

        uint64_t strandStatusReg;// Per strand status register

        /** Floating point misc registers. */
        uint64_t fsr;		// Floating-Point State Register

        /** MMU Internal Registers */
        uint16_t priContext;
        uint16_t secContext;
        uint16_t partId;
        uint64_t lsuCtrlReg;

        uint64_t iTlbC0TsbPs0;
        uint64_t iTlbC0TsbPs1;
        uint64_t iTlbC0Config;
        uint64_t iTlbCXTsbPs0;
        uint64_t iTlbCXTsbPs1;
        uint64_t iTlbCXConfig;
        uint64_t iTlbSfsr;
        uint64_t iTlbTagAccess;

        uint64_t dTlbC0TsbPs0;
        uint64_t dTlbC0TsbPs1;
        uint64_t dTlbC0Config;
        uint64_t dTlbCXTsbPs0;
        uint64_t dTlbCXTsbPs1;
        uint64_t dTlbCXConfig;
        uint64_t dTlbSfsr;
        uint64_t dTlbSfar;
        uint64_t dTlbTagAccess;

        uint64_t scratchPad[8];

        uint64_t cpu_mondo_head;
        uint64_t cpu_mondo_tail;
        uint64_t dev_mondo_head;
        uint64_t dev_mondo_tail;
        uint64_t res_error_head;
        uint64_t res_error_tail;
        uint64_t nres_error_head;
        uint64_t nres_error_tail;

        // These need to check the int_dis field and if 0 then
        // set appropriate bit in softint and checkinterrutps on the cpu
#if FULL_SYSTEM
        void  setFSRegWithEffect(int miscReg, const MiscReg &val,
                ThreadContext *tc);
        MiscReg readFSRegWithEffect(int miscReg, ThreadContext * tc);

        // Update interrupt state on softint or pil change
        void checkSoftInt(ThreadContext *tc);

        /** Process a tick compare event and generate an interrupt on the cpu if
         * appropriate. */
        void processTickCompare(ThreadContext *tc);
        void processSTickCompare(ThreadContext *tc);
        void processHSTickCompare(ThreadContext *tc);

        typedef CpuEventWrapper<MiscRegFile,
                &MiscRegFile::processTickCompare> TickCompareEvent;
        TickCompareEvent *tickCompare;

        typedef CpuEventWrapper<MiscRegFile,
                &MiscRegFile::processSTickCompare> STickCompareEvent;
        STickCompareEvent *sTickCompare;

        typedef CpuEventWrapper<MiscRegFile,
                &MiscRegFile::processHSTickCompare> HSTickCompareEvent;
        HSTickCompareEvent *hSTickCompare;
#endif
      public:

        void clear();

        MiscRegFile()
        {
            clear();
        }

        MiscReg readReg(int miscReg);

        MiscReg readRegWithEffect(int miscReg, ThreadContext *tc);

        void setReg(int miscReg, const MiscReg &val);

        void setRegWithEffect(int miscReg,
                const MiscReg &val, ThreadContext * tc);

        int getInstAsid()
        {
            return priContext | (uint32_t)partId << 13;
        }

        int getDataAsid()
        {
            return priContext | (uint32_t)partId << 13;
        }

        void serialize(std::ostream & os);

        void unserialize(Checkpoint * cp, const std::string & section);

        void copyMiscRegs(ThreadContext * tc);

      protected:

        bool isHyperPriv() { return (hpstate & (1 << 2)); }
        bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
        bool isNonPriv() { return !isPriv(); }
    };
}

#endif
<|endoftext|>


<commit_before>//
// Copyright (C) 2014, 2015 Ableton AG, Berlin. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//

/*!
 * @file
 */

#pragma once

#include <atria/xform/config.hpp>
#include <atria/xform/state_traits.hpp>
#include <atria/estd/memory.hpp>
#include <atria/meta/pack.hpp>
#include <string>
#include <stdexcept>

#if ABL_TRACE_ANY_STATE_ALLOC
#include <iostream>
#endif

namespace atria {
namespace xform {

/*!
 * Polymorphically holds any value implementing the `state_traits`.
 * This type is used for the implementation of `transducer`.
 */
class any_state
{
public:
  any_state() noexcept
    : data_(reinterpret_cast<char*>(&null_holder_))
    , size_(0)
    {}

  ~any_state() noexcept {
    if (size_) {
      content()->~holder_base();
      delete [] data_;
    }
  }

  any_state(any_state&& other)
    : data_(other.data_)
  {
    auto size = other.size_;
    other.size_ = 0;
    size_ = size;
  }

  any_state(const any_state& other)
    : data_(new char[other.size_])
    , size_(other.size_)
  {
#if ABL_TRACE_ANY_STATE_ALLOC
    std::cout << "alloc-c" << std::endl;
#endif
    other.content()->clone(data_);
  }

  template<typename ValueType>
  any_state(ValueType&& value,
            estd::enable_if_t<
              !std::is_base_of<any_state,
                               estd::decay_t<ValueType> >::value &&
              !std::is_base_of<meta::bottom,
                               estd::decay_t<ValueType> >::value
            >* = 0)
    : data_(new char[sizeof(holder<estd::decay_t<ValueType> >)])
    , size_(sizeof(holder<estd::decay_t<ValueType> >))
    {
      new (data_) holder<estd::decay_t<ValueType> >(
          std::forward<ValueType>(value));
#if ABL_TRACE_ANY_STATE_ALLOC
      std::cout << "alloc-n " << typeid(estd::decay_t<ValueType>).name() << std::endl;
#endif
    }

  any_state& operator=(any_state&& other)
  {
    data_ = other.data_;
    size_ = other.size_;
    other.size_ = 0;
    return *this;
  }

  any_state& operator=(const any_state& rhs)
  {
    if (&rhs != this) {
      realloc_(rhs.content()->size());
      rhs.content()->clone(data_);
    }
    return *this;
  }

  template <typename ValueType>
  auto operator=(ValueType&& rhs)
    -> estd::enable_if_t<
      !std::is_base_of<any_state, estd::decay_t<ValueType> >::value,
      any_state&>
  {
    realloc_(sizeof(holder<estd::decay_t<ValueType> >));
    new (data_) holder<estd::decay_t<ValueType> >(
      std::forward<ValueType>(rhs));
    return *this;
  }

  template <typename T>
  estd::decay_t<T>& as() &
    { return as_impl(meta::pack<estd::decay_t<T> >{}); }

  template <typename T>
  estd::decay_t<T>&& as() &&
    { return std::move(as_impl(meta::pack<estd::decay_t<T> >{})); }

  template <typename T>
  const estd::decay_t<T>& as() const& {
    return const_cast<any_state*>(this)->as_impl(
      meta::pack<estd::decay_t<T> >{});
  }

  template <typename T>
  void check() const {
    if (!has<T>()) {
      throw std::runtime_error(
        std::string("Have ") + type().name() +
        ", but expect " + typeid(estd::decay_t<T>).name());
    }
  }

  template <typename T>
  bool has() const {
    return has_impl(meta::pack<estd::decay_t<T> >{});
  }

  const std::type_info& type() const noexcept {
    return content()->type();
  }

private:
  void realloc_(std::size_t size) {
    if (size_ > 0)
      content()->~holder_base();
    if (size_ < size) {
      if (size_ > 0)
        delete [] data_;
      data_ = new char[size];
      size_ = size;
#if ABL_TRACE_ANY_STATE_ALLOC
      std::cout << "alloc-r" << std::endl;
#endif
    }
  }

  template <typename T>
  T& as_impl(meta::pack<T>) {
#if ABL_SAFE_ANY_STATE
    check<T>();
#endif
    return reinterpret_cast<holder<T>*>(data_)->held;
  }

  any_state& as_impl(meta::pack<any_state>) {
    return *this;
  }

  template <typename T>
  bool has_impl(meta::pack<T>) const {
    return content()->type() == typeid(T);
  }

  bool has_impl(meta::pack<any_state>) const {
    return true;
  }

  friend struct state_traits<any_state>;

  struct holder_base
  {
    virtual ~holder_base();
    virtual const std::type_info& type() const noexcept = 0;
    virtual void clone(char* data) const = 0;
    virtual void move(char* data) const = 0;
    virtual any_state complete() const = 0;
    virtual bool is_reduced() const = 0;
    virtual any_state unwrap() const = 0;
    virtual any_state unwrap_all() const = 0;
    virtual any_state rewrap(any_state) const = 0;
    virtual any_state data() const = 0;
    virtual std::size_t size() const = 0;
  };

  template <typename T>
  struct holder : holder_base
  {
    T held;

    template <typename TT>
    holder(TT&& x) : held(std::forward<TT>(x)) {}

    const std::type_info& type() const noexcept override
    { return typeid(T); }

    void clone(char* data) const override
    { new (data) holder<T>(held); }

    void move(char* data) const override
    { new (data) holder<T>(std::move(held)); }

    any_state complete() const override
    { return state_complete(held); }

    bool is_reduced() const override
    { return state_is_reduced(held); }

    any_state unwrap() const override
    { return state_unwrap(held); }

    any_state unwrap_all() const override
    { return state_unwrap_all(held); }

    any_state rewrap(any_state x) const override
    { return state_rewrap(held, std::move(x)); }

    any_state data() const override
    { return state_data(held, [] { return any_state{}; }); }

    std::size_t size() const override
    { return sizeof(T); }
  };

  struct null_holder : holder_base
  {
    virtual ~null_holder();

    const std::type_info& type() const noexcept override
    { return typeid(void); }

    void clone(char* data) const override { new (data) null_holder; }
    void move(char* data) const override { new (data) null_holder; }
    any_state complete() const override { return {}; }
    bool is_reduced() const override { return false; }
    any_state unwrap() const override { return {}; }
    any_state unwrap_all() const override { return {}; }
    any_state rewrap(any_state x) const override { return x; }
    any_state data() const override { return {}; }
    std::size_t size() const override { return 0; }
  };

  holder_base* content() const { return reinterpret_cast<holder_base*>(data_); }

  char* data_;
  std::size_t size_;

  static null_holder null_holder_;
};

template <>
struct state_traits<any_state>
{
  template <typename T>
  static auto complete(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->complete())

  template <typename T>
  static auto is_reduced(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->is_reduced())

  template <typename T>
  static auto unwrap(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->unwrap())

  template <typename T>
  static auto unwrap_all(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->unwrap_all())

  template <typename T, typename U>
  static auto rewrap(T&& t, U&& x)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->rewrap(std::forward<U>(x)))

  template <typename T, typename D>
  static auto data(T&& t, D&& d)
    -> estd::decay_t<decltype(std::forward<D>(d)())>
  {
    using data_t = estd::decay_t<decltype(std::forward<D>(d)())>;
    auto data = t.content()->data();
    return data.template has<data_t>()
      ? data.template as<data_t>()
      : std::forward<D>(d)();
  }
};

} // namespace xform
} // namespace atria
<commit_msg>xform: fix `any_state` would sometimes leak memory<commit_after>//
// Copyright (C) 2014, 2015 Ableton AG, Berlin. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//

/*!
 * @file
 */

#pragma once

#include <atria/xform/config.hpp>
#include <atria/xform/state_traits.hpp>
#include <atria/estd/memory.hpp>
#include <atria/meta/pack.hpp>
#include <string>
#include <stdexcept>

#if ABL_TRACE_ANY_STATE_ALLOC
#include <iostream>
#endif

namespace atria {
namespace xform {

/*!
 * Polymorphically holds any value implementing the `state_traits`.
 * This type is used for the implementation of `transducer`.
 */
class any_state
{
public:
  any_state() noexcept
    : data_(reinterpret_cast<char*>(&null_holder_))
    , size_(0)
    {}

  ~any_state() noexcept {
    if (size_) {
      content()->~holder_base();
      delete [] data_;
    }
  }

  any_state(any_state&& other)
    : data_(other.data_)
    , size_{}
  {
    using std::swap;
    swap(size_, other.size_);
  }

  any_state(const any_state& other)
    : data_(other.size_ ? new char[other.size_] : nullptr)
    , size_(other.size_)
  {
#if ABL_TRACE_ANY_STATE_ALLOC
    std::cout << "alloc-c" << std::endl;
#endif
    other.content()->clone(data_);
  }

  template<typename ValueType>
  any_state(ValueType&& value,
            estd::enable_if_t<
              !std::is_base_of<any_state,
                               estd::decay_t<ValueType> >::value &&
              !std::is_base_of<meta::bottom,
                               estd::decay_t<ValueType> >::value
            >* = 0)
    : data_(new char[sizeof(holder<estd::decay_t<ValueType> >)])
    , size_(sizeof(holder<estd::decay_t<ValueType> >))
    {
      new (data_) holder<estd::decay_t<ValueType> >(
          std::forward<ValueType>(value));
#if ABL_TRACE_ANY_STATE_ALLOC
      std::cout << "alloc-n " << typeid(estd::decay_t<ValueType>).name() << std::endl;
#endif
    }

  any_state& operator=(any_state&& other)
  {
    using std::swap;
    swap(data_, other.data_);
    swap(size_, other.size_);
    return *this;
  }

  any_state& operator=(const any_state& rhs)
  {
    if (&rhs != this) {
      realloc_(rhs.content()->size());
      rhs.content()->clone(data_);
    }
    return *this;
  }

  template <typename ValueType>
  auto operator=(ValueType&& rhs)
    -> estd::enable_if_t<
      !std::is_base_of<any_state, estd::decay_t<ValueType> >::value,
      any_state&>
  {
    realloc_(sizeof(holder<estd::decay_t<ValueType> >));
    new (data_) holder<estd::decay_t<ValueType> >(
      std::forward<ValueType>(rhs));
    return *this;
  }

  template <typename T>
  estd::decay_t<T>& as() &
    { return as_impl(meta::pack<estd::decay_t<T> >{}); }

  template <typename T>
  estd::decay_t<T>&& as() &&
    { return std::move(as_impl(meta::pack<estd::decay_t<T> >{})); }

  template <typename T>
  const estd::decay_t<T>& as() const& {
    return const_cast<any_state*>(this)->as_impl(
      meta::pack<estd::decay_t<T> >{});
  }

  template <typename T>
  void check() const {
    if (!has<T>()) {
      throw std::runtime_error(
        std::string("Have ") + type().name() +
        ", but expect " + typeid(estd::decay_t<T>).name());
    }
  }

  template <typename T>
  bool has() const {
    return has_impl(meta::pack<estd::decay_t<T> >{});
  }

  const std::type_info& type() const noexcept {
    return content()->type();
  }

private:
  void realloc_(std::size_t size) {
    if (size_ > 0)
      content()->~holder_base();
    if (size_ < size) {
      if (size_ > 0)
        delete [] data_;
      data_ = new char[size];
      size_ = size;
#if ABL_TRACE_ANY_STATE_ALLOC
      std::cout << "alloc-r" << std::endl;
#endif
    }
  }

  template <typename T>
  T& as_impl(meta::pack<T>) {
#if ABL_SAFE_ANY_STATE
    check<T>();
#endif
    return reinterpret_cast<holder<T>*>(data_)->held;
  }

  any_state& as_impl(meta::pack<any_state>) {
    return *this;
  }

  template <typename T>
  bool has_impl(meta::pack<T>) const {
    return content()->type() == typeid(T);
  }

  bool has_impl(meta::pack<any_state>) const {
    return true;
  }

  friend struct state_traits<any_state>;

  struct holder_base
  {
    virtual ~holder_base();
    virtual const std::type_info& type() const noexcept = 0;
    virtual void clone(char* data) const = 0;
    virtual void move(char* data) const = 0;
    virtual any_state complete() const = 0;
    virtual bool is_reduced() const = 0;
    virtual any_state unwrap() const = 0;
    virtual any_state unwrap_all() const = 0;
    virtual any_state rewrap(any_state) const = 0;
    virtual any_state data() const = 0;
    virtual std::size_t size() const = 0;
  };

  template <typename T>
  struct holder : holder_base
  {
    T held;

    template <typename TT>
    holder(TT&& x) : held(std::forward<TT>(x)) {}

    const std::type_info& type() const noexcept override
    { return typeid(T); }

    void clone(char* data) const override
    { new (data) holder<T>(held); }

    void move(char* data) const override
    { new (data) holder<T>(std::move(held)); }

    any_state complete() const override
    { return state_complete(held); }

    bool is_reduced() const override
    { return state_is_reduced(held); }

    any_state unwrap() const override
    { return state_unwrap(held); }

    any_state unwrap_all() const override
    { return state_unwrap_all(held); }

    any_state rewrap(any_state x) const override
    { return state_rewrap(held, std::move(x)); }

    any_state data() const override
    { return state_data(held, [] { return any_state{}; }); }

    std::size_t size() const override
    { return sizeof(T); }
  };

  struct null_holder : holder_base
  {
    virtual ~null_holder();

    const std::type_info& type() const noexcept override
    { return typeid(void); }

    void clone(char* data) const override { new (data) null_holder; }
    void move(char* data) const override { new (data) null_holder; }
    any_state complete() const override { return {}; }
    bool is_reduced() const override { return false; }
    any_state unwrap() const override { return {}; }
    any_state unwrap_all() const override { return {}; }
    any_state rewrap(any_state x) const override { return x; }
    any_state data() const override { return {}; }
    std::size_t size() const override { return 0; }
  };

  holder_base* content() const { return reinterpret_cast<holder_base*>(data_); }

  char* data_;
  std::size_t size_;

  static null_holder null_holder_;
};

template <>
struct state_traits<any_state>
{
  template <typename T>
  static auto complete(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->complete())

  template <typename T>
  static auto is_reduced(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->is_reduced())

  template <typename T>
  static auto unwrap(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->unwrap())

  template <typename T>
  static auto unwrap_all(T&& t)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->unwrap_all())

  template <typename T, typename U>
  static auto rewrap(T&& t, U&& x)
    -> ABL_DECLTYPE_RETURN(
      std::forward<T>(t).content()->rewrap(std::forward<U>(x)))

  template <typename T, typename D>
  static auto data(T&& t, D&& d)
    -> estd::decay_t<decltype(std::forward<D>(d)())>
  {
    using data_t = estd::decay_t<decltype(std::forward<D>(d)())>;
    auto data = t.content()->data();
    return data.template has<data_t>()
      ? data.template as<data_t>()
      : std::forward<D>(d)();
  }
};

} // namespace xform
} // namespace atria
<|endoftext|>