|  | /* | 
|  | * Copyright (C) 2016 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 "VM.h" | 
|  | #include <wtf/FastMalloc.h> | 
|  | #include <wtf/HashFunctions.h> | 
|  | #include <wtf/PrintStream.h> | 
|  |  | 
|  | namespace JSC { namespace Wasm { | 
|  |  | 
|  | namespace { | 
|  | 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 (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 (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) |