/ bytecode / BytecodeOperandsForCheckpoint.h
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