|  | /* | 
|  | * Copyright (C) 2015-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. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #if ENABLE(B3_JIT) | 
|  |  | 
|  | #include "AirGenerationContext.h" | 
|  | #include "B3ValueRep.h" | 
|  | #include "MacroAssembler.h" | 
|  | #include "RegisterSet.h" | 
|  | #include <wtf/Box.h> | 
|  |  | 
|  | namespace JSC { | 
|  |  | 
|  | class CCallHelpers; | 
|  |  | 
|  | namespace B3 { | 
|  |  | 
|  | class CheckSpecial; | 
|  | class PatchpointSpecial; | 
|  | class Procedure; | 
|  | class StackmapValue; | 
|  |  | 
|  | // NOTE: It's possible to capture StackmapGenerationParams by value, but not all of the methods will | 
|  | // work if you do that. | 
|  | class StackmapGenerationParams { | 
|  | public: | 
|  | // This is the stackmap value that we're generating. | 
|  | StackmapValue* value() const { return m_value; } | 
|  |  | 
|  | // This tells you the actual value representations that were chosen. This is usually different | 
|  | // from the constraints we supplied. | 
|  | const Vector<ValueRep>& reps() const { return m_reps; }; | 
|  |  | 
|  | // Usually we wish to access the reps. We make this easy by making ourselves appear to be a | 
|  | // collection of reps. | 
|  | unsigned size() const { return m_reps.size(); } | 
|  | const ValueRep& at(unsigned index) const { return m_reps[index]; } | 
|  | const ValueRep& operator[](unsigned index) const { return at(index); } | 
|  | Vector<ValueRep>::const_iterator begin() const { return m_reps.begin(); } | 
|  | Vector<ValueRep>::const_iterator end() const { return m_reps.end(); } | 
|  |  | 
|  | // This tells you the registers that were used. | 
|  | // NOTE: This will report bogus information if you did proc.setNeedsUsedRegisters(false). | 
|  | const RegisterSetBuilder& usedRegisters() const; | 
|  |  | 
|  | // This is a useful helper if you want to do register allocation inside of a patchpoint. The | 
|  | // usedRegisters() set is not directly useful for this purpose because: | 
|  | // | 
|  | // - You can only use callee-save registers for scratch if they were saved in the prologue. So, | 
|  | //   if a register is callee-save, it's not enough that it's not in usedRegisters(). | 
|  | // | 
|  | // - Scratch registers are going to be in usedRegisters() at the patchpoint. So, if you want to | 
|  | //   find one of your requested scratch registers using usedRegisters(), you'll have a bad time. | 
|  | // | 
|  | // This gives you the used register set that's useful for allocating scratch registers. This set | 
|  | // is defined as: | 
|  | // | 
|  | //     (usedRegisters() | (RegisterSetBuilder::calleeSaveRegisters() - proc.calleeSaveRegisters())) | 
|  | //     - gpScratchRegisters - fpScratchRegisters | 
|  | // | 
|  | // I.e. it is like usedRegisters() but also includes unsaved callee-saves and excludes scratch | 
|  | // registers. | 
|  | // | 
|  | // NOTE: This will report bogus information if you did proc.setNeedsUsedRegisters(false). | 
|  | JS_EXPORT_PRIVATE RegisterSetBuilder unavailableRegisters() const; | 
|  |  | 
|  | GPRReg gpScratch(unsigned index) const { return m_gpScratch[index]; } | 
|  | FPRReg fpScratch(unsigned index) const { return m_fpScratch[index]; } | 
|  |  | 
|  | // This is computed lazily, so it won't work if you capture StackmapGenerationParams by value. | 
|  | // These labels will get populated before any late paths or link tasks execute. | 
|  | JS_EXPORT_PRIVATE Vector<Box<MacroAssembler::Label>> successorLabels() const; | 
|  |  | 
|  | // This is computed lazily, so it won't work if you capture StackmapGenerationParams by value. | 
|  | // Returns true if the successor at the given index is going to be emitted right after the | 
|  | // patchpoint. | 
|  | JS_EXPORT_PRIVATE bool fallsThroughToSuccessor(unsigned successorIndex) const; | 
|  |  | 
|  | // These are provided for convenience; they mean that you don't have to capture them if you don't want to. | 
|  | JS_EXPORT_PRIVATE Procedure& proc() const; | 
|  | JS_EXPORT_PRIVATE Air::Code& code() const; | 
|  |  | 
|  | // The Air::GenerationContext gives you even more power. | 
|  | Air::GenerationContext& context() const { return m_context; }; | 
|  |  | 
|  | template<typename Functor> | 
|  | void addLatePath(const Functor& functor) const | 
|  | { | 
|  | context().latePaths.append( | 
|  | createSharedTask<Air::GenerationContext::LatePathFunction>( | 
|  | [=] (CCallHelpers& jit, Air::GenerationContext&) { | 
|  | functor(jit); | 
|  | })); | 
|  | } | 
|  |  | 
|  | private: | 
|  | friend class CheckSpecial; | 
|  | friend class PatchpointSpecial; | 
|  |  | 
|  | StackmapGenerationParams(StackmapValue*, const Vector<ValueRep>& reps, Air::GenerationContext&); | 
|  |  | 
|  | StackmapValue* m_value; | 
|  | Vector<ValueRep> m_reps; | 
|  | Vector<GPRReg> m_gpScratch; | 
|  | Vector<FPRReg> m_fpScratch; | 
|  | Air::GenerationContext& m_context; | 
|  | }; | 
|  |  | 
|  | } } // namespace JSC::B3 | 
|  |  | 
|  | #endif // ENABLE(B3_JIT) |