/js/src/methodjit/ICRepatcher.h

http://github.com/zpao/v8monkey · C Header · 181 lines · 66 code · 16 blank · 99 comment · 9 complexity · 978dfd1964e5ca92269d68d71c6a6b79 MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: set ts=4 sw=4 et tw=99:
  3. *
  4. * ***** BEGIN LICENSE BLOCK *****
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License Version
  8. * 1.1 (the "License"); you may not use this file except in compliance with
  9. * the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. * for the specific language governing rights and limitations under the
  15. * License.
  16. *
  17. * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
  18. * May 28, 2008.
  19. *
  20. * The Initial Developer of the Original Code is
  21. * Brendan Eich <brendan@mozilla.org>
  22. *
  23. * Contributor(s):
  24. * David Mandelin <dmandelin@mozilla.com>
  25. * David Anderson <danderson@mozilla.com>
  26. * Chris Leary <cdleary@mozilla.com>
  27. * Jacob Bramley <Jacob.Bramely@arm.com>
  28. *
  29. * Alternatively, the contents of this file may be used under the terms of
  30. * either of the GNU General Public License Version 2 or later (the "GPL"),
  31. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  32. * in which case the provisions of the GPL or the LGPL are applicable instead
  33. * of those above. If you wish to allow use of your version of this file only
  34. * under the terms of either the GPL or the LGPL, and not to allow others to
  35. * use your version of this file under the terms of the MPL, indicate your
  36. * decision by deleting the provisions above and replace them with the notice
  37. * and other provisions required by the GPL or the LGPL. If you do not delete
  38. * the provisions above, a recipient may use your version of this file under
  39. * the terms of any one of the MPL, the GPL or the LGPL.
  40. *
  41. * ***** END LICENSE BLOCK ***** */
  42. #if !defined jsjaeger_icrepatcher_h__ && defined JS_METHODJIT
  43. #define jsjaeger_icrepatcher_h__
  44. #include "assembler/assembler/RepatchBuffer.h"
  45. #include "assembler/moco/MocoStubs.h"
  46. #include "methodjit/ICChecker.h"
  47. namespace js {
  48. namespace mjit {
  49. namespace ic {
  50. class Repatcher : public JSC::RepatchBuffer
  51. {
  52. typedef JSC::CodeLocationLabel CodeLocationLabel;
  53. typedef JSC::CodeLocationCall CodeLocationCall;
  54. typedef JSC::FunctionPtr FunctionPtr;
  55. CodeLocationLabel label;
  56. public:
  57. explicit Repatcher(JITChunk *js)
  58. : JSC::RepatchBuffer(js->code), label(js->code.m_code.executableAddress())
  59. { }
  60. explicit Repatcher(const JSC::JITCode &code)
  61. : JSC::RepatchBuffer(code), label(code.start())
  62. { }
  63. using JSC::RepatchBuffer::relink;
  64. /* Patch a stub call. */
  65. void relink(CodeLocationCall call, FunctionPtr stub) {
  66. #if defined JS_CPU_X64 || defined JS_CPU_X86 || defined JS_CPU_SPARC
  67. JSC::RepatchBuffer::relink(call, stub);
  68. #elif defined JS_CPU_ARM
  69. /*
  70. * Stub calls on ARM look like this:
  71. *
  72. * ldr ip, =stub
  73. * call label -> ldr r8, =JaegerStubVeneer
  74. * blx r8
  75. *
  76. * ARM has to run stub calls through a veneer in order for THROW to
  77. * work properly. The address that must be patched is the load into
  78. * 'ip', not the load into 'r8'.
  79. */
  80. CheckIsStubCall(call.labelAtOffset(0));
  81. JSC::RepatchBuffer::relink(call.callAtOffset(-4), stub);
  82. #elif defined JS_CPU_MIPS
  83. /*
  84. * Stub calls on MIPS look like this:
  85. *
  86. * lui v0, hi(stub)
  87. * ori v0, v0, lo(stub)
  88. * lui t9, hi(JaegerStubVeneer)
  89. * ori t9, t9, lo(JaegerStubVeneer)
  90. * jalr t9
  91. * nop
  92. * call label -> xxx
  93. *
  94. * MIPS has to run stub calls through a veneer in order for THROW to
  95. * work properly. The address that must be patched is the load into
  96. * 'v0', not the load into 't9'.
  97. */
  98. JSC::RepatchBuffer::relink(call.callAtOffset(-8), stub);
  99. #else
  100. # error
  101. #endif
  102. }
  103. /* Patch the offset of a Value load emitted by loadValueWithAddressOffsetPatch. */
  104. void patchAddressOffsetForValueLoad(CodeLocationLabel label, uint32_t offset) {
  105. #if defined JS_CPU_X64 || defined JS_CPU_ARM || defined JS_CPU_SPARC || defined JS_CPU_MIPS
  106. repatch(label.dataLabel32AtOffset(0), offset);
  107. #elif defined JS_CPU_X86
  108. static const unsigned LOAD_TYPE_OFFSET = 6;
  109. static const unsigned LOAD_DATA_OFFSET = 12;
  110. /*
  111. * We have the following sequence to patch:
  112. *
  113. * mov <offset+4>($base), %<type>
  114. * mov <offset+0>($base), %<data>
  115. */
  116. repatch(label.dataLabel32AtOffset(LOAD_DATA_OFFSET), offset);
  117. repatch(label.dataLabel32AtOffset(LOAD_TYPE_OFFSET), offset + 4);
  118. #else
  119. # error
  120. #endif
  121. }
  122. void patchAddressOffsetForValueStore(CodeLocationLabel label, uint32_t offset, bool typeConst) {
  123. #if defined JS_CPU_ARM || defined JS_CPU_X64 || defined JS_CPU_SPARC || defined JS_CPU_MIPS
  124. (void) typeConst;
  125. repatch(label.dataLabel32AtOffset(0), offset);
  126. #elif defined JS_CPU_X86
  127. static const unsigned STORE_TYPE_OFFSET = 6;
  128. static const unsigned STORE_DATA_CONST_TYPE_OFFSET = 16;
  129. static const unsigned STORE_DATA_TYPE_OFFSET = 12;
  130. /*
  131. * The type is stored first, then the payload. Both stores can vary in
  132. * size, depending on whether or not the data is a constant in the
  133. * instruction stream (though only the first store matters for the
  134. * purpose of locating both offsets for patching).
  135. *
  136. * We have one of the following sequences to patch. Offsets are located
  137. * before 6B into a given move instruction, but the mov instructions
  138. * carrying constant payloads are 10B wide overall.
  139. *
  140. * typeConst=false, dataConst=false
  141. * mov %<type>, <offset+4>($base) ; Length is 6
  142. * mov %<data>, <offset+0>($base) ; Offset @ len(prev) + 6 = 12
  143. * typeConst=true, dataConst=false
  144. * mov $<type>, <offset+4>($base) ; Length is 10
  145. * mov %<data>, <offset+0>($base) ; Offset @ len(prev) + 6 = 16
  146. * typeConst=true, dataConst=true
  147. * mov $<type>, <offset+4>($base) ; Length is 10
  148. * mov $<data>, <offset+0>($base) ; Offset @ len(prev) + 6 = 16
  149. *
  150. * Note that we only need to know whether type is const to determine the
  151. * correct patch offsets. In all cases, the label points to the start
  152. * of the sequence.
  153. */
  154. repatch(label.dataLabel32AtOffset(STORE_TYPE_OFFSET), offset + 4);
  155. unsigned payloadOffset = typeConst ? STORE_DATA_CONST_TYPE_OFFSET : STORE_DATA_TYPE_OFFSET;
  156. repatch(label.dataLabel32AtOffset(payloadOffset), offset);
  157. #else
  158. # error
  159. #endif
  160. }
  161. };
  162. } /* namespace ic */
  163. } /* namespace mjit */
  164. } /* namespace js */
  165. #endif