BytecodeOperandsForCheckpoint.h
1 /* 2 * Copyright (C) 2020 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #pragma once 27 28 #include "ArrayProfile.h" 29 #include "BytecodeStructs.h" 30 #include "ValueProfile.h" 31 32 namespace JSC { 33 34 template<typename BytecodeMetadata> 35 ArrayProfile* arrayProfileForImpl(BytecodeMetadata& metadata, unsigned checkpointIndex) 36 { 37 UNUSED_PARAM(checkpointIndex); 38 return &metadata.m_callLinkInfo.m_arrayProfile; 39 } 40 41 template<typename BytecodeMetadata> 42 bool hasArrayProfileFor(BytecodeMetadata& metadata, unsigned checkpointIndex) 43 { 44 return arrayProfileForImpl(metadata, checkpointIndex); 45 } 46 47 template<typename BytecodeMetadata> 48 ArrayProfile& arrayProfileFor(BytecodeMetadata& metadata, unsigned checkpointIndex) 49 { 50 ASSERT(hasArrayProfileFor(metadata, checkpointIndex)); 51 return *arrayProfileForImpl(metadata, checkpointIndex); 52 } 53 54 template<typename BytecodeMetadata> 55 ValueProfile* valueProfileForImpl(BytecodeMetadata& metadata, unsigned checkpointIndex) 56 { 57 UNUSED_PARAM(checkpointIndex); 58 if constexpr (BytecodeMetadata::opcodeID == op_iterator_open) { 59 switch (checkpointIndex) { 60 case OpIteratorOpen::symbolCall: return &metadata.m_iteratorProfile; 61 case OpIteratorOpen::getNext: return &metadata.m_nextProfile; 62 default: RELEASE_ASSERT_NOT_REACHED(); 63 } 64 65 } else if constexpr (BytecodeMetadata::opcodeID == op_iterator_next) { 66 switch (checkpointIndex) { 67 case OpIteratorNext::computeNext: return &metadata.m_nextResultProfile; 68 case OpIteratorNext::getDone: return &metadata.m_doneProfile; 69 case OpIteratorNext::getValue: return &metadata.m_valueProfile; 70 default: RELEASE_ASSERT_NOT_REACHED(); 71 } 72 } else 73 return &metadata.m_profile; 74 } 75 76 template<typename BytecodeMetadata> 77 bool hasValueProfileFor(BytecodeMetadata& metadata, unsigned checkpointIndex) 78 { 79 return valueProfileForImpl(metadata, checkpointIndex); 80 } 81 82 template<typename BytecodeMetadata> 83 ValueProfile& valueProfileFor(BytecodeMetadata& metadata, unsigned checkpointIndex) 84 { 85 ASSERT(hasValueProfileFor(metadata, checkpointIndex)); 86 return *valueProfileForImpl(metadata, checkpointIndex); 87 } 88 89 template<typename Bytecode> 90 Operand destinationFor(const Bytecode& bytecode, unsigned checkpointIndex, JITType type = JITType::None) 91 { 92 UNUSED_PARAM(checkpointIndex); 93 if constexpr (Bytecode::opcodeID == op_iterator_open) { 94 switch (checkpointIndex) { 95 case OpIteratorOpen::symbolCall: return bytecode.m_iterator; 96 case OpIteratorOpen::getNext: return bytecode.m_next; 97 default: RELEASE_ASSERT_NOT_REACHED(); 98 } 99 return { }; 100 } else if constexpr (Bytecode::opcodeID == op_iterator_next) { 101 switch (checkpointIndex) { 102 case OpIteratorNext::computeNext: { 103 if (type == JITType::DFGJIT || type == JITType::FTLJIT) 104 return Operand::tmp(OpIteratorNext::nextResult); 105 return bytecode.m_value; // We reuse value as a temp because its either not used in subsequent bytecodes or written as the temp object . 106 } 107 case OpIteratorNext::getDone: return bytecode.m_done; 108 case OpIteratorNext::getValue: return bytecode.m_value; 109 default: RELEASE_ASSERT_NOT_REACHED(); 110 } 111 return { }; 112 } else 113 return bytecode.m_dst; 114 } 115 116 // Call-like opcode locations 117 118 template<typename Bytecode> 119 VirtualRegister calleeFor(const Bytecode& bytecode, unsigned checkpointIndex) 120 { 121 UNUSED_PARAM(checkpointIndex); 122 if constexpr (Bytecode::opcodeID == op_iterator_open) { 123 ASSERT(checkpointIndex == OpIteratorOpen::symbolCall); 124 return bytecode.m_symbolIterator; 125 } else if constexpr (Bytecode::opcodeID == op_iterator_next) { 126 ASSERT(checkpointIndex == OpIteratorNext::computeNext); 127 return bytecode.m_next; 128 } else 129 return bytecode.m_callee; 130 } 131 132 template<typename Bytecode> 133 unsigned argumentCountIncludingThisFor(const Bytecode& bytecode, unsigned checkpointIndex) 134 { 135 UNUSED_PARAM(checkpointIndex); 136 if constexpr (Bytecode::opcodeID == op_iterator_open) { 137 ASSERT(checkpointIndex == OpIteratorOpen::symbolCall); 138 return 1; 139 } else if constexpr (Bytecode::opcodeID == op_iterator_next) { 140 ASSERT(checkpointIndex == OpIteratorNext::computeNext); 141 return 1; 142 } else 143 return bytecode.m_argc; 144 } 145 146 template<typename Bytecode> 147 ptrdiff_t stackOffsetInRegistersForCall(const Bytecode& bytecode, unsigned checkpointIndex) 148 { 149 UNUSED_PARAM(checkpointIndex); 150 if constexpr (Bytecode::opcodeID == op_iterator_open) { 151 ASSERT(checkpointIndex == OpIteratorOpen::symbolCall); 152 return CallFrame::headerSizeInRegisters - bytecode.m_iterable.offset(); 153 } else if constexpr (Bytecode::opcodeID == op_iterator_next) { 154 ASSERT(checkpointIndex == OpIteratorNext::computeNext); 155 return CallFrame::headerSizeInRegisters - bytecode.m_iterator.offset(); 156 } else 157 return bytecode.m_argv; 158 } 159 160 template<typename BytecodeMetadata> 161 LLIntCallLinkInfo& callLinkInfoFor(BytecodeMetadata& metadata, unsigned checkpointIndex) 162 { 163 UNUSED_PARAM(checkpointIndex); 164 return metadata.m_callLinkInfo; 165 } 166 167 } // namespace JSC