1/* 2 * Copyright (C) 2009 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#ifndef RepatchBuffer_h 27#define RepatchBuffer_h 28 29#if ENABLE(JIT) 30 31#include "CodeBlock.h" 32#include <MacroAssembler.h> 33#include <wtf/Noncopyable.h> 34 35namespace JSC { 36 37// RepatchBuffer: 38// 39// This class is used to modify code after code generation has been completed, 40// and after the code has potentially already been executed. This mechanism is 41// used to apply optimizations to the code. 42// 43class RepatchBuffer { 44 typedef MacroAssemblerCodePtr CodePtr; 45 46public: 47 RepatchBuffer(CodeBlock* codeBlock) 48 : m_codeBlock(codeBlock) 49 { 50#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) 51 RefPtr<JITCode> code = codeBlock->jitCode(); 52 m_start = code->start(); 53 m_size = code->size(); 54 55 ExecutableAllocator::makeWritable(m_start, m_size); 56#endif 57 } 58 59 ~RepatchBuffer() 60 { 61#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) 62 ExecutableAllocator::makeExecutable(m_start, m_size); 63#endif 64 } 65 66 CodeBlock* codeBlock() const { return m_codeBlock; } 67 68 void relink(CodeLocationJump jump, CodeLocationLabel destination) 69 { 70 MacroAssembler::repatchJump(jump, destination); 71 } 72 73 void relink(CodeLocationCall call, CodeLocationLabel destination) 74 { 75 MacroAssembler::repatchCall(call, destination); 76 } 77 78 void relink(CodeLocationCall call, FunctionPtr destination) 79 { 80 MacroAssembler::repatchCall(call, destination); 81 } 82 83 void relink(CodeLocationNearCall nearCall, CodePtr destination) 84 { 85 MacroAssembler::repatchNearCall(nearCall, CodeLocationLabel(destination)); 86 } 87 88 void relink(CodeLocationNearCall nearCall, CodeLocationLabel destination) 89 { 90 MacroAssembler::repatchNearCall(nearCall, destination); 91 } 92 93 void repatch(CodeLocationDataLabel32 dataLabel32, int32_t value) 94 { 95 MacroAssembler::repatchInt32(dataLabel32, value); 96 } 97 98 void repatch(CodeLocationDataLabelCompact dataLabelCompact, int32_t value) 99 { 100 MacroAssembler::repatchCompact(dataLabelCompact, value); 101 } 102 103 void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value) 104 { 105 MacroAssembler::repatchPointer(dataLabelPtr, value); 106 } 107 108 void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label) 109 { 110 relink(CodeLocationCall(CodePtr(returnAddress)), label); 111 } 112 113 void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction) 114 { 115 relinkCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction)); 116 } 117 118 void relinkCallerToFunction(ReturnAddressPtr returnAddress, FunctionPtr function) 119 { 120 relink(CodeLocationCall(CodePtr(returnAddress)), function); 121 } 122 123 void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label) 124 { 125 relink(CodeLocationNearCall(CodePtr(returnAddress)), label); 126 } 127 128 void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction) 129 { 130 relinkNearCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction)); 131 } 132 133 void replaceWithLoad(CodeLocationConvertibleLoad label) 134 { 135 MacroAssembler::replaceWithLoad(label); 136 } 137 138 void replaceWithAddressComputation(CodeLocationConvertibleLoad label) 139 { 140 MacroAssembler::replaceWithAddressComputation(label); 141 } 142 143 void setLoadInstructionIsActive(CodeLocationConvertibleLoad label, bool isActive) 144 { 145 if (isActive) 146 replaceWithLoad(label); 147 else 148 replaceWithAddressComputation(label); 149 } 150 151 static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) 152 { 153 return MacroAssembler::startOfBranchPtrWithPatchOnRegister(label); 154 } 155 156 static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label) 157 { 158 return MacroAssembler::startOfPatchableBranchPtrWithPatchOnAddress(label); 159 } 160 161 static CodeLocationLabel startOfPatchableBranch32WithPatchOnAddress(CodeLocationDataLabel32 label) 162 { 163 return MacroAssembler::startOfPatchableBranch32WithPatchOnAddress(label); 164 } 165 166 void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 167 { 168 MacroAssembler::replaceWithJump(instructionStart, destination); 169 } 170 171 // This is a *bit* of a silly API, since we currently always also repatch the 172 // immediate after calling this. But I'm fine with that, since this just feels 173 // less yucky. 174 void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, MacroAssembler::RegisterID reg, void* value) 175 { 176 MacroAssembler::revertJumpReplacementToBranchPtrWithPatch(instructionStart, reg, value); 177 } 178 179 void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, MacroAssembler::Address address, void* value) 180 { 181 MacroAssembler::revertJumpReplacementToPatchableBranchPtrWithPatch(instructionStart, address, value); 182 } 183 184 void revertJumpReplacementToPatchableBranch32WithPatch(CodeLocationLabel instructionStart, MacroAssembler::Address address, int32_t value) 185 { 186 MacroAssembler::revertJumpReplacementToPatchableBranch32WithPatch(instructionStart, address, value); 187 } 188 189private: 190 CodeBlock* m_codeBlock; 191#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) 192 void* m_start; 193 size_t m_size; 194#endif 195}; 196 197} // namespace JSC 198 199#endif // ENABLE(ASSEMBLER) 200 201#endif // RepatchBuffer_h 202