blob: 6a42d517195ea4fb61d92b10c8cc377367c2eb9d [file] [log] [blame]
/*
* Copyright (C) 2016-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.
*/
#include "config.h"
#include "WasmSignature.h"
#if ENABLE(WEBASSEMBLY)
#include <wtf/FastMalloc.h>
#include <wtf/HashFunctions.h>
#include <wtf/PrintStream.h>
#include <wtf/text/WTFString.h>
namespace JSC { namespace Wasm {
namespace {
namespace WasmSignatureInternal {
static const bool verbose = false;
}
}
String Signature::toString() const
{
String result(makeString(returnType()));
result.append(" (");
for (SignatureArgCount arg = 0; arg < argumentCount(); ++arg) {
if (arg)
result.append(", ");
result.append(makeString(argument(arg)));
}
result.append(')');
return result;
}
void Signature::dump(PrintStream& out) const
{
out.print(toString());
}
unsigned Signature::hash() const
{
unsigned accumulator = 0xa1bcedd8u;
for (uint32_t i = 0; i < argumentCount(); ++i)
accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(argument(i))));
accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(returnType())));
return accumulator;
}
RefPtr<Signature> Signature::tryCreate(SignatureArgCount argumentCount)
{
// We use WTF_MAKE_FAST_ALLOCATED for this class.
auto result = tryFastMalloc(allocatedSize(argumentCount));
void* memory = nullptr;
if (!result.getValue(memory))
return nullptr;
Signature* signature = new (NotNull, memory) Signature(argumentCount);
return adoptRef(signature);
}
SignatureInformation::SignatureInformation()
{
}
SignatureInformation& SignatureInformation::singleton()
{
static SignatureInformation* theOne;
static std::once_flag signatureInformationFlag;
std::call_once(signatureInformationFlag, [] () {
theOne = new SignatureInformation;
});
return *theOne;
}
std::pair<SignatureIndex, Ref<Signature>> SignatureInformation::adopt(Ref<Signature>&& signature)
{
SignatureInformation& info = singleton();
LockHolder lock(info.m_lock);
SignatureIndex nextValue = info.m_nextIndex;
auto addResult = info.m_signatureMap.add(SignatureHash { signature.ptr() }, nextValue);
if (addResult.isNewEntry) {
++info.m_nextIndex;
RELEASE_ASSERT(info.m_nextIndex > nextValue); // crash on overflow.
ASSERT(nextValue == addResult.iterator->value);
if (WasmSignatureInternal::verbose)
dataLogLn("Adopt new signature ", signature.get(), " with index ", addResult.iterator->value, " hash: ", signature->hash());
auto addResult = info.m_indexMap.add(nextValue, signature.copyRef());
RELEASE_ASSERT(addResult.isNewEntry);
ASSERT(info.m_indexMap.size() == info.m_signatureMap.size());
return std::make_pair(nextValue, WTFMove(signature));
}
if (WasmSignatureInternal::verbose)
dataLogLn("Existing signature ", signature.get(), " with index ", addResult.iterator->value, " hash: ", signature->hash());
ASSERT(addResult.iterator->value != Signature::invalidIndex);
ASSERT(info.m_indexMap.contains(addResult.iterator->value));
return std::make_pair(addResult.iterator->value, Ref<Signature>(*info.m_indexMap.get(addResult.iterator->value)));
}
const Signature& SignatureInformation::get(SignatureIndex index)
{
ASSERT(index != Signature::invalidIndex);
SignatureInformation& info = singleton();
LockHolder lock(info.m_lock);
return *info.m_indexMap.get(index);
}
SignatureIndex SignatureInformation::get(const Signature& signature)
{
SignatureInformation& info = singleton();
LockHolder lock(info.m_lock);
auto result = info.m_signatureMap.get(SignatureHash { &signature });
ASSERT(result != Signature::invalidIndex);
return result;
}
void SignatureInformation::tryCleanup()
{
SignatureInformation& info = singleton();
LockHolder lock(info.m_lock);
Vector<std::pair<SignatureIndex, Signature*>> toRemove;
for (const auto& pair : info.m_indexMap) {
const Ref<Signature>& signature = pair.value;
if (signature->refCount() == 1) {
// We're the only owner.
toRemove.append(std::make_pair(pair.key, signature.ptr()));
}
}
for (const auto& pair : toRemove) {
bool removed = info.m_signatureMap.remove(SignatureHash { pair.second });
ASSERT_UNUSED(removed, removed);
removed = info.m_indexMap.remove(pair.first);
ASSERT_UNUSED(removed, removed);
}
if (info.m_signatureMap.isEmpty()) {
ASSERT(info.m_indexMap.isEmpty());
info.m_nextIndex = Signature::firstValidIndex;
}
}
} } // namespace JSC::Wasm
#endif // ENABLE(WEBASSEMBLY)