mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2024-11-23 04:09:40 +00:00
210 lines
6.0 KiB
C++
210 lines
6.0 KiB
C++
/*
|
|
* Copyright (C) 2017 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "CPU.h"
|
|
|
|
#include <wtf/PrintStream.h>
|
|
#include <wtf/StringPrintStream.h>
|
|
#include <wtf/Vector.h>
|
|
|
|
namespace JSC {
|
|
|
|
namespace Probe {
|
|
class Context;
|
|
} // namespace Probe
|
|
|
|
namespace Printer {
|
|
|
|
struct Context;
|
|
|
|
union Data {
|
|
Data()
|
|
{
|
|
const intptr_t uninitialized = 0xdeadb0d0;
|
|
memcpy(&buffer, &uninitialized, sizeof(uninitialized));
|
|
}
|
|
Data(uintptr_t value)
|
|
: Data(&value, sizeof(value))
|
|
{ }
|
|
Data(const void* pointer)
|
|
: Data(&pointer, sizeof(pointer))
|
|
{ }
|
|
Data(void* src, size_t size)
|
|
{
|
|
RELEASE_ASSERT(size <= sizeof(buffer));
|
|
memcpy(&buffer, src, size);
|
|
}
|
|
|
|
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
|
|
T as() const
|
|
{
|
|
return static_cast<T>(value);
|
|
}
|
|
|
|
template<typename T, typename = typename std::enable_if<std::is_pointer<T>::value>::type>
|
|
const T as(int = 0) const
|
|
{
|
|
return reinterpret_cast<const T>(pointer);
|
|
}
|
|
|
|
template<typename T, typename = typename std::enable_if<!std::is_integral<T>::value && !std::is_pointer<T>::value>::type>
|
|
const T& as() const
|
|
{
|
|
static_assert(sizeof(T) <= sizeof(buffer), "size is not sane");
|
|
return *reinterpret_cast<const T*>(&buffer);
|
|
}
|
|
|
|
uintptr_t value;
|
|
const void* pointer;
|
|
#if USE(JSVALUE64)
|
|
UCPURegister buffer[4];
|
|
#elif USE(JSVALUE32_64)
|
|
UCPURegister buffer[6];
|
|
#endif
|
|
};
|
|
|
|
struct Context {
|
|
Context(Probe::Context& probeContext, Data& data)
|
|
: probeContext(probeContext)
|
|
, data(data)
|
|
{ }
|
|
|
|
Probe::Context& probeContext;
|
|
Data& data;
|
|
};
|
|
|
|
typedef void (*Callback)(PrintStream&, Context&);
|
|
|
|
struct PrintRecord {
|
|
PrintRecord(Data data, Callback printer)
|
|
: data(data)
|
|
, printer(printer)
|
|
{ }
|
|
|
|
PrintRecord(Callback printer)
|
|
: printer(printer)
|
|
{ }
|
|
|
|
template<template<class> class Printer, typename T>
|
|
PrintRecord(const Printer<T>& other)
|
|
{
|
|
static_assert(std::is_base_of<PrintRecord, Printer<T>>::value, "Printer should extend PrintRecord");
|
|
static_assert(sizeof(PrintRecord) == sizeof(Printer<T>), "Printer should be the same size as PrintRecord");
|
|
data = other.data;
|
|
printer = other.printer;
|
|
}
|
|
|
|
Data data;
|
|
Callback printer;
|
|
|
|
protected:
|
|
PrintRecord() { }
|
|
};
|
|
|
|
template<typename T> struct Printer;
|
|
|
|
typedef Vector<PrintRecord> PrintRecordList;
|
|
|
|
inline void appendPrinter(PrintRecordList&) { }
|
|
|
|
template<typename First, typename... Arguments>
|
|
inline void appendPrinter(PrintRecordList& printRecordList, First first, Arguments&&... others)
|
|
{
|
|
printRecordList.append(Printer<First>(first));
|
|
appendPrinter(printRecordList, std::forward<Arguments>(others)...);
|
|
}
|
|
|
|
template<typename... Arguments>
|
|
inline PrintRecordList* makePrintRecordList(Arguments&&... arguments)
|
|
{
|
|
// FIXME: the current implementation intentionally leaks the PrintRecordList.
|
|
// We may want to fix this in the future if we want to use the print mechanism
|
|
// in tests that may compile a lot of prints.
|
|
// https://bugs.webkit.org/show_bug.cgi?id=171123
|
|
auto printRecordList = new PrintRecordList();
|
|
appendPrinter(*printRecordList, std::forward<Arguments>(arguments)...);
|
|
return printRecordList;
|
|
}
|
|
|
|
// Some utility functions for specializing printers.
|
|
|
|
void printConstCharString(PrintStream&, Context&);
|
|
void printIntptr(PrintStream&, Context&);
|
|
void printUintptr(PrintStream&, Context&);
|
|
void printPointer(PrintStream&, Context&);
|
|
|
|
void setPrinter(PrintRecord&, CString&&);
|
|
|
|
// Specialized printers.
|
|
|
|
template<>
|
|
struct Printer<const char*> : public PrintRecord {
|
|
Printer(const char* str)
|
|
: PrintRecord(str, printConstCharString)
|
|
{ }
|
|
};
|
|
|
|
template<>
|
|
struct Printer<char*> : public Printer<const char*> {
|
|
Printer(char* str)
|
|
: Printer<const char*>(str)
|
|
{ }
|
|
};
|
|
|
|
template<>
|
|
struct Printer<RawPointer> : public PrintRecord {
|
|
Printer(RawPointer rawPointer)
|
|
: PrintRecord(rawPointer.value(), printPointer)
|
|
{ }
|
|
};
|
|
|
|
template<typename T, typename = typename std::enable_if_t<std::is_integral<T>::value && std::numeric_limits<T>::is_signed>>
|
|
void setPrinter(PrintRecord& record, T value, intptr_t = 0)
|
|
{
|
|
record.data.value = static_cast<uintptr_t>(value);
|
|
record.printer = printIntptr;
|
|
}
|
|
|
|
template<typename T, typename = typename std::enable_if_t<std::is_integral<T>::value && !std::numeric_limits<T>::is_signed>>
|
|
void setPrinter(PrintRecord& record, T value, uintptr_t = 0)
|
|
{
|
|
record.data.value = static_cast<uintptr_t>(value);
|
|
record.printer = printUintptr;
|
|
}
|
|
|
|
template<typename T>
|
|
struct Printer : public PrintRecord {
|
|
Printer(T value)
|
|
{
|
|
setPrinter(*this, value);
|
|
}
|
|
};
|
|
|
|
} // namespace Printer
|
|
|
|
} // namespace JSC
|