| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 1 | // Copyright (c) 1994-2006 Sun Microsystems Inc. | 
 | 2 | // 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 | // | 
 | 8 | // - Redistributions of source code must retain the above copyright notice, | 
 | 9 | // this list of conditions and the following disclaimer. | 
 | 10 | // | 
 | 11 | // - Redistribution in binary form must reproduce the above copyright | 
 | 12 | // notice, this list of conditions and the following disclaimer in the | 
 | 13 | // documentation and/or other materials provided with the | 
 | 14 | // distribution. | 
 | 15 | // | 
 | 16 | // - Neither the name of Sun Microsystems or the names of contributors may | 
 | 17 | // be used to endorse or promote products derived from this software without | 
 | 18 | // specific prior written permission. | 
 | 19 | // | 
 | 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 | 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
 | 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
 | 23 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
 | 24 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 
 | 25 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
 | 26 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
 | 27 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 | 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 
 | 29 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
 | 30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 
 | 31 | // OF THE POSSIBILITY OF SUCH DAMAGE. | 
 | 32 |  | 
 | 33 | // The original source code covered by the above license above has been modified | 
 | 34 | // significantly by Google Inc. | 
 | 35 | // Copyright 2006-2008 the V8 project authors. All rights reserved. | 
 | 36 |  | 
 | 37 | #ifndef V8_ARM_ASSEMBLER_ARM_INL_H_ | 
 | 38 | #define V8_ARM_ASSEMBLER_ARM_INL_H_ | 
 | 39 |  | 
 | 40 | #include "arm/assembler-arm.h" | 
 | 41 | #include "cpu.h" | 
| Leon Clarke | f7060e2 | 2010-06-03 12:02:55 +0100 | [diff] [blame] | 42 | #include "debug.h" | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 43 |  | 
 | 44 |  | 
 | 45 | namespace v8 { | 
 | 46 | namespace internal { | 
 | 47 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 48 |  | 
 | 49 | void RelocInfo::apply(intptr_t delta) { | 
 | 50 |   if (RelocInfo::IsInternalReference(rmode_)) { | 
 | 51 |     // absolute code pointer inside code object moves with the code object. | 
 | 52 |     int32_t* p = reinterpret_cast<int32_t*>(pc_); | 
 | 53 |     *p += delta;  // relocate entry | 
 | 54 |   } | 
 | 55 |   // We do not use pc relative addressing on ARM, so there is | 
 | 56 |   // nothing else to do. | 
 | 57 | } | 
 | 58 |  | 
 | 59 |  | 
 | 60 | Address RelocInfo::target_address() { | 
 | 61 |   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); | 
 | 62 |   return Assembler::target_address_at(pc_); | 
 | 63 | } | 
 | 64 |  | 
 | 65 |  | 
 | 66 | Address RelocInfo::target_address_address() { | 
 | 67 |   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); | 
 | 68 |   return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_)); | 
 | 69 | } | 
 | 70 |  | 
 | 71 |  | 
| Leon Clarke | f7060e2 | 2010-06-03 12:02:55 +0100 | [diff] [blame] | 72 | int RelocInfo::target_address_size() { | 
 | 73 |   return Assembler::kExternalTargetSize; | 
 | 74 | } | 
 | 75 |  | 
 | 76 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 77 | void RelocInfo::set_target_address(Address target) { | 
 | 78 |   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); | 
 | 79 |   Assembler::set_target_address_at(pc_, target); | 
 | 80 | } | 
 | 81 |  | 
 | 82 |  | 
 | 83 | Object* RelocInfo::target_object() { | 
 | 84 |   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 85 |   return Memory::Object_at(Assembler::target_address_address_at(pc_)); | 
 | 86 | } | 
 | 87 |  | 
 | 88 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 89 | Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 90 |   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 
 | 91 |   return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_)); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 92 | } | 
 | 93 |  | 
 | 94 |  | 
 | 95 | Object** RelocInfo::target_object_address() { | 
 | 96 |   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 
 | 97 |   return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_)); | 
 | 98 | } | 
 | 99 |  | 
 | 100 |  | 
 | 101 | void RelocInfo::set_target_object(Object* target) { | 
 | 102 |   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 
 | 103 |   Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target)); | 
 | 104 | } | 
 | 105 |  | 
 | 106 |  | 
 | 107 | Address* RelocInfo::target_reference_address() { | 
 | 108 |   ASSERT(rmode_ == EXTERNAL_REFERENCE); | 
 | 109 |   return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); | 
 | 110 | } | 
 | 111 |  | 
 | 112 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 113 | Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() { | 
 | 114 |   ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL); | 
 | 115 |   Address address = Memory::Address_at(pc_); | 
 | 116 |   return Handle<JSGlobalPropertyCell>( | 
 | 117 |       reinterpret_cast<JSGlobalPropertyCell**>(address)); | 
 | 118 | } | 
 | 119 |  | 
 | 120 |  | 
 | 121 | JSGlobalPropertyCell* RelocInfo::target_cell() { | 
 | 122 |   ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL); | 
 | 123 |   Address address = Memory::Address_at(pc_); | 
 | 124 |   Object* object = HeapObject::FromAddress( | 
 | 125 |       address - JSGlobalPropertyCell::kValueOffset); | 
 | 126 |   return reinterpret_cast<JSGlobalPropertyCell*>(object); | 
 | 127 | } | 
 | 128 |  | 
 | 129 |  | 
 | 130 | void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell) { | 
 | 131 |   ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL); | 
 | 132 |   Address address = cell->address() + JSGlobalPropertyCell::kValueOffset; | 
 | 133 |   Memory::Address_at(pc_) = address; | 
 | 134 | } | 
 | 135 |  | 
 | 136 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 137 | Address RelocInfo::call_address() { | 
| Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 138 |   // The 2 instructions offset assumes patched debug break slot or return | 
 | 139 |   // sequence. | 
 | 140 |   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 
 | 141 |          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 142 |   return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); | 
 | 143 | } | 
 | 144 |  | 
 | 145 |  | 
 | 146 | void RelocInfo::set_call_address(Address target) { | 
| Ben Murdoch | bb769b2 | 2010-08-11 14:56:33 +0100 | [diff] [blame] | 147 |   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 
 | 148 |          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 149 |   Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; | 
 | 150 | } | 
 | 151 |  | 
 | 152 |  | 
 | 153 | Object* RelocInfo::call_object() { | 
 | 154 |   return *call_object_address(); | 
 | 155 | } | 
 | 156 |  | 
 | 157 |  | 
| Ben Murdoch | bb769b2 | 2010-08-11 14:56:33 +0100 | [diff] [blame] | 158 | void RelocInfo::set_call_object(Object* target) { | 
 | 159 |   *call_object_address() = target; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 160 | } | 
 | 161 |  | 
 | 162 |  | 
| Ben Murdoch | bb769b2 | 2010-08-11 14:56:33 +0100 | [diff] [blame] | 163 | Object** RelocInfo::call_object_address() { | 
 | 164 |   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 
 | 165 |          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 
 | 166 |   return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 167 | } | 
 | 168 |  | 
 | 169 |  | 
| Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 170 | bool RelocInfo::IsPatchedReturnSequence() { | 
| Steve Block | 6ded16b | 2010-05-10 14:33:55 +0100 | [diff] [blame] | 171 |   Instr current_instr = Assembler::instr_at(pc_); | 
 | 172 |   Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); | 
 | 173 | #ifdef USE_BLX | 
 | 174 |   // A patched return sequence is: | 
 | 175 |   //  ldr ip, [pc, #0] | 
 | 176 |   //  blx ip | 
 | 177 |   return ((current_instr & kLdrPCMask) == kLdrPCPattern) | 
 | 178 |           && ((next_instr & kBlxRegMask) == kBlxRegPattern); | 
 | 179 | #else | 
 | 180 |   // A patched return sequence is: | 
 | 181 |   //  mov lr, pc | 
 | 182 |   //  ldr pc, [pc, #-4] | 
 | 183 |   return (current_instr == kMovLrPc) | 
 | 184 |           && ((next_instr & kLdrPCMask) == kLdrPCPattern); | 
 | 185 | #endif | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 186 | } | 
 | 187 |  | 
 | 188 |  | 
| Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 189 | bool RelocInfo::IsPatchedDebugBreakSlotSequence() { | 
 | 190 |   Instr current_instr = Assembler::instr_at(pc_); | 
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 191 |   return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); | 
| Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 192 | } | 
 | 193 |  | 
 | 194 |  | 
| Leon Clarke | f7060e2 | 2010-06-03 12:02:55 +0100 | [diff] [blame] | 195 | void RelocInfo::Visit(ObjectVisitor* visitor) { | 
 | 196 |   RelocInfo::Mode mode = rmode(); | 
 | 197 |   if (mode == RelocInfo::EMBEDDED_OBJECT) { | 
 | 198 |     visitor->VisitPointer(target_object_address()); | 
 | 199 |   } else if (RelocInfo::IsCodeTarget(mode)) { | 
 | 200 |     visitor->VisitCodeTarget(this); | 
| Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 201 |   } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { | 
 | 202 |     visitor->VisitGlobalPropertyCell(this); | 
| Leon Clarke | f7060e2 | 2010-06-03 12:02:55 +0100 | [diff] [blame] | 203 |   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { | 
 | 204 |     visitor->VisitExternalReference(target_reference_address()); | 
 | 205 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame^] | 206 |   // TODO(isolates): Get a cached isolate below. | 
 | 207 |   } else if (((RelocInfo::IsJSReturn(mode) && | 
| Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 208 |               IsPatchedReturnSequence()) || | 
 | 209 |              (RelocInfo::IsDebugBreakSlot(mode) && | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame^] | 210 |               IsPatchedDebugBreakSlotSequence())) && | 
 | 211 |              Isolate::Current()->debug()->has_break_points()) { | 
| Leon Clarke | f7060e2 | 2010-06-03 12:02:55 +0100 | [diff] [blame] | 212 |     visitor->VisitDebugTarget(this); | 
 | 213 | #endif | 
 | 214 |   } else if (mode == RelocInfo::RUNTIME_ENTRY) { | 
 | 215 |     visitor->VisitRuntimeEntry(this); | 
 | 216 |   } | 
 | 217 | } | 
 | 218 |  | 
 | 219 |  | 
| Iain Merrick | 7568138 | 2010-08-19 15:07:18 +0100 | [diff] [blame] | 220 | template<typename StaticVisitor> | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame^] | 221 | void RelocInfo::Visit(Heap* heap) { | 
| Iain Merrick | 7568138 | 2010-08-19 15:07:18 +0100 | [diff] [blame] | 222 |   RelocInfo::Mode mode = rmode(); | 
 | 223 |   if (mode == RelocInfo::EMBEDDED_OBJECT) { | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame^] | 224 |     StaticVisitor::VisitPointer(heap, target_object_address()); | 
| Iain Merrick | 7568138 | 2010-08-19 15:07:18 +0100 | [diff] [blame] | 225 |   } else if (RelocInfo::IsCodeTarget(mode)) { | 
 | 226 |     StaticVisitor::VisitCodeTarget(this); | 
| Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 227 |   } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { | 
 | 228 |     StaticVisitor::VisitGlobalPropertyCell(this); | 
| Iain Merrick | 7568138 | 2010-08-19 15:07:18 +0100 | [diff] [blame] | 229 |   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { | 
 | 230 |     StaticVisitor::VisitExternalReference(target_reference_address()); | 
 | 231 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame^] | 232 |   } else if (heap->isolate()->debug()->has_break_points() && | 
| Iain Merrick | 7568138 | 2010-08-19 15:07:18 +0100 | [diff] [blame] | 233 |              ((RelocInfo::IsJSReturn(mode) && | 
 | 234 |               IsPatchedReturnSequence()) || | 
 | 235 |              (RelocInfo::IsDebugBreakSlot(mode) && | 
 | 236 |               IsPatchedDebugBreakSlotSequence()))) { | 
 | 237 |     StaticVisitor::VisitDebugTarget(this); | 
 | 238 | #endif | 
 | 239 |   } else if (mode == RelocInfo::RUNTIME_ENTRY) { | 
 | 240 |     StaticVisitor::VisitRuntimeEntry(this); | 
 | 241 |   } | 
 | 242 | } | 
 | 243 |  | 
 | 244 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 245 | Operand::Operand(int32_t immediate, RelocInfo::Mode rmode)  { | 
 | 246 |   rm_ = no_reg; | 
 | 247 |   imm32_ = immediate; | 
 | 248 |   rmode_ = rmode; | 
 | 249 | } | 
 | 250 |  | 
 | 251 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 252 | Operand::Operand(const ExternalReference& f)  { | 
 | 253 |   rm_ = no_reg; | 
 | 254 |   imm32_ = reinterpret_cast<int32_t>(f.address()); | 
 | 255 |   rmode_ = RelocInfo::EXTERNAL_REFERENCE; | 
 | 256 | } | 
 | 257 |  | 
 | 258 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 259 | Operand::Operand(Smi* value) { | 
 | 260 |   rm_ = no_reg; | 
 | 261 |   imm32_ =  reinterpret_cast<intptr_t>(value); | 
 | 262 |   rmode_ = RelocInfo::NONE; | 
 | 263 | } | 
 | 264 |  | 
 | 265 |  | 
 | 266 | Operand::Operand(Register rm) { | 
 | 267 |   rm_ = rm; | 
 | 268 |   rs_ = no_reg; | 
 | 269 |   shift_op_ = LSL; | 
 | 270 |   shift_imm_ = 0; | 
 | 271 | } | 
 | 272 |  | 
 | 273 |  | 
 | 274 | bool Operand::is_reg() const { | 
 | 275 |   return rm_.is_valid() && | 
 | 276 |          rs_.is(no_reg) && | 
 | 277 |          shift_op_ == LSL && | 
 | 278 |          shift_imm_ == 0; | 
 | 279 | } | 
 | 280 |  | 
 | 281 |  | 
 | 282 | void Assembler::CheckBuffer() { | 
 | 283 |   if (buffer_space() <= kGap) { | 
 | 284 |     GrowBuffer(); | 
 | 285 |   } | 
 | 286 |   if (pc_offset() >= next_buffer_check_) { | 
 | 287 |     CheckConstPool(false, true); | 
 | 288 |   } | 
 | 289 | } | 
 | 290 |  | 
 | 291 |  | 
 | 292 | void Assembler::emit(Instr x) { | 
 | 293 |   CheckBuffer(); | 
 | 294 |   *reinterpret_cast<Instr*>(pc_) = x; | 
 | 295 |   pc_ += kInstrSize; | 
 | 296 | } | 
 | 297 |  | 
 | 298 |  | 
 | 299 | Address Assembler::target_address_address_at(Address pc) { | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 300 |   Address target_pc = pc; | 
 | 301 |   Instr instr = Memory::int32_at(target_pc); | 
 | 302 |   // If we have a bx instruction, the instruction before the bx is | 
 | 303 |   // what we need to patch. | 
 | 304 |   static const int32_t kBxInstMask = 0x0ffffff0; | 
 | 305 |   static const int32_t kBxInstPattern = 0x012fff10; | 
 | 306 |   if ((instr & kBxInstMask) == kBxInstPattern) { | 
 | 307 |     target_pc -= kInstrSize; | 
 | 308 |     instr = Memory::int32_at(target_pc); | 
 | 309 |   } | 
| Steve Block | 6ded16b | 2010-05-10 14:33:55 +0100 | [diff] [blame] | 310 |  | 
 | 311 | #ifdef USE_BLX | 
 | 312 |   // If we have a blx instruction, the instruction before it is | 
 | 313 |   // what needs to be patched. | 
 | 314 |   if ((instr & kBlxRegMask) == kBlxRegPattern) { | 
 | 315 |     target_pc -= kInstrSize; | 
 | 316 |     instr = Memory::int32_at(target_pc); | 
 | 317 |   } | 
 | 318 | #endif | 
 | 319 |  | 
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 320 |   ASSERT(IsLdrPcImmediateOffset(instr)); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 321 |   int offset = instr & 0xfff;  // offset_12 is unsigned | 
 | 322 |   if ((instr & (1 << 23)) == 0) offset = -offset;  // U bit defines offset sign | 
 | 323 |   // Verify that the constant pool comes after the instruction referencing it. | 
 | 324 |   ASSERT(offset >= -4); | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 325 |   return target_pc + offset + 8; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 326 | } | 
 | 327 |  | 
 | 328 |  | 
 | 329 | Address Assembler::target_address_at(Address pc) { | 
 | 330 |   return Memory::Address_at(target_address_address_at(pc)); | 
 | 331 | } | 
 | 332 |  | 
 | 333 |  | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 334 | void Assembler::set_target_at(Address constant_pool_entry, | 
 | 335 |                               Address target) { | 
 | 336 |   Memory::Address_at(constant_pool_entry) = target; | 
 | 337 | } | 
 | 338 |  | 
 | 339 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 340 | void Assembler::set_target_address_at(Address pc, Address target) { | 
 | 341 |   Memory::Address_at(target_address_address_at(pc)) = target; | 
 | 342 |   // Intuitively, we would think it is necessary to flush the instruction cache | 
 | 343 |   // after patching a target address in the code as follows: | 
 | 344 |   //   CPU::FlushICache(pc, sizeof(target)); | 
 | 345 |   // However, on ARM, no instruction was actually patched by the assignment | 
 | 346 |   // above; the target address is not part of an instruction, it is patched in | 
 | 347 |   // the constant pool and is read via a data access; the instruction accessing | 
 | 348 |   // this address in the constant pool remains unchanged. | 
 | 349 | } | 
 | 350 |  | 
 | 351 | } }  // namespace v8::internal | 
 | 352 |  | 
 | 353 | #endif  // V8_ARM_ASSEMBLER_ARM_INL_H_ |