blob: 1926d7ced1f04a442b490d8e49576814ba79ef31 [file] [log] [blame]
/*
* Copyright (C) 2015 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.
*/
#ifndef B3StackmapValue_h
#define B3StackmapValue_h
#if ENABLE(B3_JIT)
#include "B3ConstrainedValue.h"
#include "B3Value.h"
#include "B3ValueRep.h"
#include "CCallHelpers.h"
#include "RegisterSet.h"
#include <wtf/SharedTask.h>
namespace JSC { namespace B3 {
class StackmapValue;
namespace Air {
struct GenerationContext;
}
struct StackmapGenerationParams {
// This is the stackmap value that we're generating.
StackmapValue* value;
// This tells you the actual value representations that were chosen. This is usually different
// from the constraints we supplied.
Vector<ValueRep> reps;
// This tells you the registers that were used.
RegisterSet usedRegisters;
// The Air::GenerationContext gives you even more power.
Air::GenerationContext* context;
};
typedef void StackmapGeneratorFunction(CCallHelpers&, const StackmapGenerationParams&);
typedef SharedTask<StackmapGeneratorFunction> StackmapGenerator;
class JS_EXPORT_PRIVATE StackmapValue : public Value {
public:
static bool accepts(Opcode opcode)
{
// This needs to include opcodes of all subclasses.
switch (opcode) {
case CheckAdd:
case CheckSub:
case CheckMul:
case Check:
case Patchpoint:
return true;
default:
return false;
}
}
~StackmapValue();
// Use this to add children. Note that you could also add children by doing
// children().append(). That will work fine, but it's not recommended.
void append(const ConstrainedValue&);
template<typename VectorType>
void appendAnys(const VectorType& vector)
{
for (Value* value : vector)
append(value);
}
// This is a helper for something you might do a lot of: append a value that should be constrained
// to SomeRegister.
void appendSomeRegister(Value*);
const Vector<ValueRep>& reps() const { return m_reps; }
void clobberEarly(const RegisterSet& set)
{
m_earlyClobbered.merge(set);
}
void clobberLate(const RegisterSet& set)
{
m_lateClobbered.merge(set);
}
void clobber(const RegisterSet& set)
{
clobberEarly(set);
clobberLate(set);
}
const RegisterSet& earlyClobbered() const { return m_earlyClobbered; }
const RegisterSet& lateClobbered() const { return m_lateClobbered; }
void setGenerator(RefPtr<StackmapGenerator> generator)
{
m_generator = generator;
}
template<typename Functor>
void setGenerator(const Functor& functor)
{
m_generator = createSharedTask<StackmapGeneratorFunction>(functor);
}
ConstrainedValue constrainedChild(unsigned index) const
{
return ConstrainedValue(child(index), index < m_reps.size() ? m_reps[index] : ValueRep());
}
void setConstrainedChild(unsigned index, const ConstrainedValue&);
void setConstraint(unsigned index, const ValueRep&);
class ConstrainedValueCollection {
public:
ConstrainedValueCollection(const StackmapValue& value)
: m_value(value)
{
}
unsigned size() const { return m_value.numChildren(); }
ConstrainedValue at(unsigned index) const { return m_value.constrainedChild(index); }
ConstrainedValue operator[](unsigned index) const { return at(index); }
class iterator {
public:
iterator()
: m_collection(nullptr)
, m_index(0)
{
}
iterator(const ConstrainedValueCollection& collection, unsigned index)
: m_collection(&collection)
, m_index(index)
{
}
ConstrainedValue operator*() const
{
return m_collection->at(m_index);
}
iterator& operator++()
{
m_index++;
return *this;
}
bool operator==(const iterator& other) const
{
ASSERT(m_collection == other.m_collection);
return m_index == other.m_index;
}
bool operator!=(const iterator& other) const
{
return !(*this == other);
}
private:
const ConstrainedValueCollection* m_collection;
unsigned m_index;
};
iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, size()); }
private:
const StackmapValue& m_value;
};
ConstrainedValueCollection constrainedChildren() const
{
return ConstrainedValueCollection(*this);
}
protected:
void dumpChildren(CommaPrinter&, PrintStream&) const override;
void dumpMeta(CommaPrinter&, PrintStream&) const override;
StackmapValue(unsigned index, CheckedOpcodeTag, Opcode, Type, Origin);
private:
friend class CheckSpecial;
friend class PatchpointSpecial;
friend class StackmapSpecial;
Vector<ValueRep> m_reps;
RefPtr<StackmapGenerator> m_generator;
RegisterSet m_earlyClobbered;
RegisterSet m_lateClobbered;
RegisterSet m_usedRegisters; // Stackmaps could be further duplicated by Air, but that's unlikely, so we just merge the used registers sets if that were to happen.
};
} } // namespace JSC::B3
#endif // ENABLE(B3_JIT)
#endif // B3StackmapValue_h