mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2025-04-08 09:51:46 +00:00
199 lines
5.6 KiB
C++
199 lines
5.6 KiB
C++
/*
|
|
* Copyright (C) 2015-2019 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
|
|
|
|
#if ENABLE(B3_JIT)
|
|
|
|
#include "B3HeapRange.h"
|
|
#include "B3Kind.h"
|
|
#include "B3Origin.h"
|
|
#include "B3Type.h"
|
|
#include <wtf/HashTable.h>
|
|
|
|
namespace JSC { namespace B3 {
|
|
|
|
class Procedure;
|
|
class Value;
|
|
|
|
// ValueKeys are useful for CSE. They abstractly describe the value that a Value returns when it
|
|
// executes. Any Value that has the same ValueKey is guaranteed to return the same value, provided
|
|
// that they return a non-empty ValueKey. Operations that have effects, or that can have their
|
|
// behavior affected by other operations' effects, will return an empty ValueKey. You have to use
|
|
// other mechanisms for doing CSE for impure operations.
|
|
|
|
class ValueKey {
|
|
public:
|
|
ValueKey()
|
|
{
|
|
}
|
|
|
|
ValueKey(Kind kind, Type type)
|
|
: m_kind(kind)
|
|
, m_type(type)
|
|
{
|
|
}
|
|
|
|
ValueKey(Kind, Type, Value* child);
|
|
|
|
ValueKey(Kind, Type, Value* left, Value* right);
|
|
|
|
ValueKey(Kind, Type, Value* a, Value* b, Value* c);
|
|
|
|
ValueKey(Kind kind, Type type, int64_t value)
|
|
: m_kind(kind)
|
|
, m_type(type)
|
|
{
|
|
u.value = value;
|
|
}
|
|
|
|
ValueKey(Kind kind, Type type, double value)
|
|
: m_kind(kind)
|
|
, m_type(type)
|
|
{
|
|
u.doubleValue = value;
|
|
}
|
|
|
|
ValueKey(Kind kind, Type type, float value)
|
|
: m_kind(kind)
|
|
, m_type(type)
|
|
{
|
|
// This means that upper 32bit of u.value is 0.
|
|
u.floatValue = value;
|
|
}
|
|
|
|
static ValueKey intConstant(Type type, int64_t value);
|
|
|
|
Kind kind() const { return m_kind; }
|
|
Opcode opcode() const { return kind().opcode(); }
|
|
Type type() const { return m_type; }
|
|
unsigned childIndex(unsigned index) const { return u.indices[index]; }
|
|
Value* child(Procedure&, unsigned index) const;
|
|
int64_t value() const { return u.value; }
|
|
double doubleValue() const { return u.doubleValue; }
|
|
float floatValue() const { return u.floatValue; }
|
|
|
|
bool operator==(const ValueKey& other) const
|
|
{
|
|
return m_kind == other.m_kind
|
|
&& m_type == other.m_type
|
|
&& u == other.u;
|
|
}
|
|
|
|
bool operator!=(const ValueKey& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
unsigned hash() const
|
|
{
|
|
return m_kind.hash() + m_type.hash() + WTF::IntHash<int32_t>::hash(u.indices[0]) + u.indices[1] + u.indices[2];
|
|
}
|
|
|
|
explicit operator bool() const { return *this != ValueKey(); }
|
|
|
|
void dump(PrintStream&) const;
|
|
|
|
bool canMaterialize() const
|
|
{
|
|
if (!*this)
|
|
return false;
|
|
switch (opcode()) {
|
|
case CheckAdd:
|
|
case CheckSub:
|
|
case CheckMul:
|
|
return false;
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool isConstant() const
|
|
{
|
|
return B3::isConstant(opcode());
|
|
}
|
|
|
|
// Attempts to materialize the Value for this ValueKey. May return nullptr if the value cannot
|
|
// be materialized. This happens for CheckAdd and friends. You can use canMaterialize() to check
|
|
// if your key is materializable.
|
|
Value* materialize(Procedure&, Origin) const;
|
|
|
|
ValueKey(WTF::HashTableDeletedValueType)
|
|
: m_type { Int32 }
|
|
{
|
|
}
|
|
|
|
bool isHashTableDeletedValue() const
|
|
{
|
|
return *this == ValueKey(WTF::HashTableDeletedValue);
|
|
}
|
|
|
|
private:
|
|
Kind m_kind;
|
|
Type m_type { Void };
|
|
union U {
|
|
unsigned indices[3];
|
|
int64_t value;
|
|
double doubleValue;
|
|
float floatValue;
|
|
|
|
U()
|
|
{
|
|
indices[0] = 0;
|
|
indices[1] = 0;
|
|
indices[2] = 0;
|
|
}
|
|
|
|
bool operator==(const U& other) const
|
|
{
|
|
return indices[0] == other.indices[0]
|
|
&& indices[1] == other.indices[1]
|
|
&& indices[2] == other.indices[2];
|
|
}
|
|
} u;
|
|
};
|
|
|
|
struct ValueKeyHash {
|
|
static unsigned hash(const ValueKey& key) { return key.hash(); }
|
|
static bool equal(const ValueKey& a, const ValueKey& b) { return a == b; }
|
|
static constexpr bool safeToCompareToEmptyOrDeleted = true;
|
|
};
|
|
|
|
} } // namespace JSC::B3
|
|
|
|
namespace WTF {
|
|
|
|
template<typename T> struct DefaultHash;
|
|
template<> struct DefaultHash<JSC::B3::ValueKey> : JSC::B3::ValueKeyHash { };
|
|
|
|
template<typename T> struct HashTraits;
|
|
template<> struct HashTraits<JSC::B3::ValueKey> : public SimpleClassHashTraits<JSC::B3::ValueKey> {
|
|
static constexpr bool emptyValueIsZero = false;
|
|
};
|
|
|
|
} // namespace WTF
|
|
|
|
#endif // ENABLE(B3_JIT)
|