/ assembler / CodeLocation.h
CodeLocation.h
  1  /*
  2   * Copyright (C) 2009-2018 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 "MacroAssemblerCodeRef.h"
 29  
 30  #if ENABLE(ASSEMBLER)
 31  
 32  namespace JSC {
 33  
 34  enum class NearCallMode : uint8_t { Regular, Tail };
 35  
 36  template<PtrTag> class CodeLocationInstruction;
 37  template<PtrTag> class CodeLocationLabel;
 38  template<PtrTag> class CodeLocationJump;
 39  template<PtrTag> class CodeLocationCall;
 40  template<PtrTag> class CodeLocationNearCall;
 41  template<PtrTag> class CodeLocationDataLabelCompact;
 42  template<PtrTag> class CodeLocationDataLabel32;
 43  template<PtrTag> class CodeLocationDataLabelPtr;
 44  template<PtrTag> class CodeLocationConvertibleLoad;
 45  
 46  // The CodeLocation* types are all pretty much do-nothing wrappers around
 47  // CodePtr (or MacroAssemblerCodePtr, to give it its full name).  These
 48  // classes only exist to provide type-safety when linking and patching code.
 49  //
 50  // The one new piece of functionallity introduced by these classes is the
 51  // ability to create (or put another way, to re-discover) another CodeLocation
 52  // at an offset from one you already know.  When patching code to optimize it
 53  // we often want to patch a number of instructions that are short, fixed
 54  // offsets apart.  To reduce memory overhead we will only retain a pointer to
 55  // one of the instructions, and we will use the *AtOffset methods provided by
 56  // CodeLocationCommon to find the other points in the code to modify.
 57  template<PtrTag tag>
 58  class CodeLocationCommon : public MacroAssemblerCodePtr<tag> {
 59      using Base = MacroAssemblerCodePtr<tag>;
 60  public:
 61      template<PtrTag resultTag = tag> CodeLocationInstruction<resultTag> instructionAtOffset(int offset);
 62      template<PtrTag resultTag = tag> CodeLocationLabel<resultTag> labelAtOffset(int offset);
 63      template<PtrTag resultTag = tag> CodeLocationJump<resultTag> jumpAtOffset(int offset);
 64      template<PtrTag resultTag = tag> CodeLocationCall<resultTag> callAtOffset(int offset);
 65      template<PtrTag resultTag = tag> CodeLocationNearCall<resultTag> nearCallAtOffset(int offset, NearCallMode);
 66      template<PtrTag resultTag = tag> CodeLocationDataLabelPtr<resultTag> dataLabelPtrAtOffset(int offset);
 67      template<PtrTag resultTag = tag> CodeLocationDataLabel32<resultTag> dataLabel32AtOffset(int offset);
 68      template<PtrTag resultTag = tag> CodeLocationDataLabelCompact<resultTag> dataLabelCompactAtOffset(int offset);
 69      template<PtrTag resultTag = tag> CodeLocationConvertibleLoad<resultTag> convertibleLoadAtOffset(int offset);
 70  
 71      template<typename T = void*>
 72      T dataLocation() const { return Base::template dataLocation<T>(); }
 73  
 74      template<typename T, typename = std::enable_if_t<std::is_base_of<CodeLocationCommon<tag>, T>::value>>
 75      operator T()
 76      {
 77          return T(MacroAssemblerCodePtr<tag>::createFromExecutableAddress(this->executableAddress()));
 78      }
 79  
 80  protected:
 81      CodeLocationCommon()
 82      {
 83      }
 84  
 85      CodeLocationCommon(MacroAssemblerCodePtr<tag> location)
 86          : MacroAssemblerCodePtr<tag>(location)
 87      {
 88      }
 89  };
 90  
 91  template<PtrTag tag>
 92  class CodeLocationInstruction : public CodeLocationCommon<tag> {
 93  public:
 94      CodeLocationInstruction() { }
 95      explicit CodeLocationInstruction(MacroAssemblerCodePtr<tag> location)
 96          : CodeLocationCommon<tag>(location) { }
 97      explicit CodeLocationInstruction(void* location)
 98          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
 99  };
100  
101  template<PtrTag tag>
102  class CodeLocationLabel : public CodeLocationCommon<tag> {
103  public:
104      CodeLocationLabel() { }
105      explicit CodeLocationLabel(MacroAssemblerCodePtr<tag> location)
106          : CodeLocationCommon<tag>(location) { }
107      explicit CodeLocationLabel(void* location)
108          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
109  
110      template<PtrTag newTag>
111      CodeLocationLabel<newTag> retagged() { return CodeLocationLabel<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }
112  
113      template<typename T = void*>
114      T untaggedExecutableAddress() const { return CodeLocationCommon<tag>::template untaggedExecutableAddress<T>(); }
115  
116      template<typename T = void*>
117      T dataLocation() const { return CodeLocationCommon<tag>::template dataLocation<T>(); }
118  };
119  
120  template<PtrTag tag>
121  class CodeLocationJump : public CodeLocationCommon<tag> {
122  public:
123      CodeLocationJump() { }
124      explicit CodeLocationJump(MacroAssemblerCodePtr<tag> location)
125          : CodeLocationCommon<tag>(location) { }
126      explicit CodeLocationJump(void* location)
127          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
128  
129      template<PtrTag newTag>
130      CodeLocationJump<newTag> retagged() { return CodeLocationJump<newTag>(MacroAssemblerCodePtr<tag>::template retagged<newTag>()); }
131  };
132  
133  template<PtrTag tag>
134  class CodeLocationCall : public CodeLocationCommon<tag> {
135  public:
136      CodeLocationCall() { }
137      explicit CodeLocationCall(MacroAssemblerCodePtr<tag> location)
138          : CodeLocationCommon<tag>(location) { }
139      explicit CodeLocationCall(void* location)
140          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
141  
142      template<PtrTag newTag>
143      CodeLocationCall<newTag> retagged() { return CodeLocationCall<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }
144  };
145  
146  template<PtrTag tag>
147  class CodeLocationNearCall : public CodeLocationCommon<tag> {
148  public:
149      CodeLocationNearCall() { }
150      explicit CodeLocationNearCall(MacroAssemblerCodePtr<tag> location, NearCallMode callMode)
151          : CodeLocationCommon<tag>(location), m_callMode(callMode) { }
152      explicit CodeLocationNearCall(void* location, NearCallMode callMode)
153          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)), m_callMode(callMode) { }
154      NearCallMode callMode() { return m_callMode; }
155  private:
156      NearCallMode m_callMode { NearCallMode::Regular };
157  };
158  
159  template<PtrTag tag>
160  class CodeLocationDataLabel32 : public CodeLocationCommon<tag> {
161  public:
162      CodeLocationDataLabel32() { }
163      explicit CodeLocationDataLabel32(MacroAssemblerCodePtr<tag> location)
164          : CodeLocationCommon<tag>(location) { }
165      explicit CodeLocationDataLabel32(void* location)
166          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
167  };
168  
169  template<PtrTag tag>
170  class CodeLocationDataLabelCompact : public CodeLocationCommon<tag> {
171  public:
172      CodeLocationDataLabelCompact() { }
173      explicit CodeLocationDataLabelCompact(MacroAssemblerCodePtr<tag> location)
174          : CodeLocationCommon<tag>(location) { }
175      explicit CodeLocationDataLabelCompact(void* location)
176          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
177  };
178  
179  template<PtrTag tag>
180  class CodeLocationDataLabelPtr : public CodeLocationCommon<tag> {
181  public:
182      CodeLocationDataLabelPtr() { }
183      explicit CodeLocationDataLabelPtr(MacroAssemblerCodePtr<tag> location)
184          : CodeLocationCommon<tag>(location) { }
185      explicit CodeLocationDataLabelPtr(void* location)
186          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
187  };
188  
189  template<PtrTag tag>
190  class CodeLocationConvertibleLoad : public CodeLocationCommon<tag> {
191  public:
192      CodeLocationConvertibleLoad() { }
193      explicit CodeLocationConvertibleLoad(MacroAssemblerCodePtr<tag> location)
194          : CodeLocationCommon<tag>(location) { }
195      explicit CodeLocationConvertibleLoad(void* location)
196          : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
197  };
198  
199  template<PtrTag tag>
200  template<PtrTag resultTag>
201  inline CodeLocationInstruction<resultTag> CodeLocationCommon<tag>::instructionAtOffset(int offset)
202  {
203      ASSERT_VALID_CODE_OFFSET(offset);
204      return CodeLocationInstruction<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
205  }
206  
207  template<PtrTag tag>
208  template<PtrTag resultTag>
209  inline CodeLocationLabel<resultTag> CodeLocationCommon<tag>::labelAtOffset(int offset)
210  {
211      ASSERT_VALID_CODE_OFFSET(offset);
212      return CodeLocationLabel<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
213  }
214  
215  template<PtrTag tag>
216  template<PtrTag resultTag>
217  inline CodeLocationJump<resultTag> CodeLocationCommon<tag>::jumpAtOffset(int offset)
218  {
219      ASSERT_VALID_CODE_OFFSET(offset);
220      return CodeLocationJump<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
221  }
222  
223  template<PtrTag tag>
224  template<PtrTag resultTag>
225  inline CodeLocationCall<resultTag> CodeLocationCommon<tag>::callAtOffset(int offset)
226  {
227      ASSERT_VALID_CODE_OFFSET(offset);
228      return CodeLocationCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
229  }
230  
231  template<PtrTag tag>
232  template<PtrTag resultTag>
233  inline CodeLocationNearCall<resultTag> CodeLocationCommon<tag>::nearCallAtOffset(int offset, NearCallMode callMode)
234  {
235      ASSERT_VALID_CODE_OFFSET(offset);
236      return CodeLocationNearCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset), callMode);
237  }
238  
239  template<PtrTag tag>
240  template<PtrTag resultTag>
241  inline CodeLocationDataLabelPtr<resultTag> CodeLocationCommon<tag>::dataLabelPtrAtOffset(int offset)
242  {
243      ASSERT_VALID_CODE_OFFSET(offset);
244      return CodeLocationDataLabelPtr<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
245  }
246  
247  template<PtrTag tag>
248  template<PtrTag resultTag>
249  inline CodeLocationDataLabel32<resultTag> CodeLocationCommon<tag>::dataLabel32AtOffset(int offset)
250  {
251      ASSERT_VALID_CODE_OFFSET(offset);
252      return CodeLocationDataLabel32<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
253  }
254  
255  template<PtrTag tag>
256  template<PtrTag resultTag>
257  inline CodeLocationDataLabelCompact<resultTag> CodeLocationCommon<tag>::dataLabelCompactAtOffset(int offset)
258  {
259      ASSERT_VALID_CODE_OFFSET(offset);
260      return CodeLocationDataLabelCompact<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
261  }
262  
263  template<PtrTag tag>
264  template<PtrTag resultTag>
265  inline CodeLocationConvertibleLoad<resultTag> CodeLocationCommon<tag>::convertibleLoadAtOffset(int offset)
266  {
267      ASSERT_VALID_CODE_OFFSET(offset);
268      return CodeLocationConvertibleLoad<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
269  }
270  
271  } // namespace JSC
272  
273  #endif // ENABLE(ASSEMBLER)