| OLD | NEW | 
|---|
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 
| 2 // All Rights Reserved. | 2 // All Rights Reserved. | 
| 3 // | 3 // | 
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without | 
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions | 
| 6 // are met: | 6 // are met: | 
| 7 // | 7 // | 
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, | 
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. | 
| 10 // | 10 // | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 64   return kNumReservedRegisters; | 64   return kNumReservedRegisters; | 
| 65 } | 65 } | 
| 66 | 66 | 
| 67 | 67 | 
| 68 int DwVfpRegister::NumAllocatableRegisters() { | 68 int DwVfpRegister::NumAllocatableRegisters() { | 
| 69   return NumRegisters() - kNumReservedRegisters; | 69   return NumRegisters() - kNumReservedRegisters; | 
| 70 } | 70 } | 
| 71 | 71 | 
| 72 | 72 | 
| 73 int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) { | 73 int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) { | 
| 74   ASSERT(!reg.is(kDoubleRegZero)); | 74   DCHECK(!reg.is(kDoubleRegZero)); | 
| 75   ASSERT(!reg.is(kScratchDoubleReg)); | 75   DCHECK(!reg.is(kScratchDoubleReg)); | 
| 76   if (reg.code() > kDoubleRegZero.code()) { | 76   if (reg.code() > kDoubleRegZero.code()) { | 
| 77     return reg.code() - kNumReservedRegisters; | 77     return reg.code() - kNumReservedRegisters; | 
| 78   } | 78   } | 
| 79   return reg.code(); | 79   return reg.code(); | 
| 80 } | 80 } | 
| 81 | 81 | 
| 82 | 82 | 
| 83 DwVfpRegister DwVfpRegister::FromAllocationIndex(int index) { | 83 DwVfpRegister DwVfpRegister::FromAllocationIndex(int index) { | 
| 84   ASSERT(index >= 0 && index < NumAllocatableRegisters()); | 84   DCHECK(index >= 0 && index < NumAllocatableRegisters()); | 
| 85   ASSERT(kScratchDoubleReg.code() - kDoubleRegZero.code() == | 85   DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() == | 
| 86          kNumReservedRegisters - 1); | 86          kNumReservedRegisters - 1); | 
| 87   if (index >= kDoubleRegZero.code()) { | 87   if (index >= kDoubleRegZero.code()) { | 
| 88     return from_code(index + kNumReservedRegisters); | 88     return from_code(index + kNumReservedRegisters); | 
| 89   } | 89   } | 
| 90   return from_code(index); | 90   return from_code(index); | 
| 91 } | 91 } | 
| 92 | 92 | 
| 93 | 93 | 
| 94 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { | 94 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { | 
| 95   if (RelocInfo::IsInternalReference(rmode_)) { | 95   if (RelocInfo::IsInternalReference(rmode_)) { | 
| 96     // absolute code pointer inside code object moves with the code object. | 96     // absolute code pointer inside code object moves with the code object. | 
| 97     int32_t* p = reinterpret_cast<int32_t*>(pc_); | 97     int32_t* p = reinterpret_cast<int32_t*>(pc_); | 
| 98     *p += delta;  // relocate entry | 98     *p += delta;  // relocate entry | 
| 99   } | 99   } | 
| 100   // We do not use pc relative addressing on ARM, so there is | 100   // We do not use pc relative addressing on ARM, so there is | 
| 101   // nothing else to do. | 101   // nothing else to do. | 
| 102 } | 102 } | 
| 103 | 103 | 
| 104 | 104 | 
| 105 Address RelocInfo::target_address() { | 105 Address RelocInfo::target_address() { | 
| 106   ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 106   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 
| 107   return Assembler::target_address_at(pc_, host_); | 107   return Assembler::target_address_at(pc_, host_); | 
| 108 } | 108 } | 
| 109 | 109 | 
| 110 | 110 | 
| 111 Address RelocInfo::target_address_address() { | 111 Address RelocInfo::target_address_address() { | 
| 112   ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) | 112   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) | 
| 113                               || rmode_ == EMBEDDED_OBJECT | 113                               || rmode_ == EMBEDDED_OBJECT | 
| 114                               || rmode_ == EXTERNAL_REFERENCE); | 114                               || rmode_ == EXTERNAL_REFERENCE); | 
| 115   if (FLAG_enable_ool_constant_pool || | 115   if (FLAG_enable_ool_constant_pool || | 
| 116       Assembler::IsMovW(Memory::int32_at(pc_))) { | 116       Assembler::IsMovW(Memory::int32_at(pc_))) { | 
| 117     // We return the PC for ool constant pool since this function is used by the | 117     // We return the PC for ool constant pool since this function is used by the | 
| 118     // serializerer and expects the address to reside within the code object. | 118     // serializerer and expects the address to reside within the code object. | 
| 119     return reinterpret_cast<Address>(pc_); | 119     return reinterpret_cast<Address>(pc_); | 
| 120   } else { | 120   } else { | 
| 121     ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_))); | 121     DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_))); | 
| 122     return constant_pool_entry_address(); | 122     return constant_pool_entry_address(); | 
| 123   } | 123   } | 
| 124 } | 124 } | 
| 125 | 125 | 
| 126 | 126 | 
| 127 Address RelocInfo::constant_pool_entry_address() { | 127 Address RelocInfo::constant_pool_entry_address() { | 
| 128   ASSERT(IsInConstantPool()); | 128   DCHECK(IsInConstantPool()); | 
| 129   return Assembler::constant_pool_entry_address(pc_, host_->constant_pool()); | 129   return Assembler::constant_pool_entry_address(pc_, host_->constant_pool()); | 
| 130 } | 130 } | 
| 131 | 131 | 
| 132 | 132 | 
| 133 int RelocInfo::target_address_size() { | 133 int RelocInfo::target_address_size() { | 
| 134   return kPointerSize; | 134   return kPointerSize; | 
| 135 } | 135 } | 
| 136 | 136 | 
| 137 | 137 | 
| 138 void RelocInfo::set_target_address(Address target, | 138 void RelocInfo::set_target_address(Address target, | 
| 139                                    WriteBarrierMode write_barrier_mode, | 139                                    WriteBarrierMode write_barrier_mode, | 
| 140                                    ICacheFlushMode icache_flush_mode) { | 140                                    ICacheFlushMode icache_flush_mode) { | 
| 141   ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 141   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 
| 142   Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); | 142   Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); | 
| 143   if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 143   if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 
| 144       host() != NULL && IsCodeTarget(rmode_)) { | 144       host() != NULL && IsCodeTarget(rmode_)) { | 
| 145     Object* target_code = Code::GetCodeFromTargetAddress(target); | 145     Object* target_code = Code::GetCodeFromTargetAddress(target); | 
| 146     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 146     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 
| 147         host(), this, HeapObject::cast(target_code)); | 147         host(), this, HeapObject::cast(target_code)); | 
| 148   } | 148   } | 
| 149 } | 149 } | 
| 150 | 150 | 
| 151 | 151 | 
| 152 Object* RelocInfo::target_object() { | 152 Object* RelocInfo::target_object() { | 
| 153   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 153   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 
| 154   return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); | 154   return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); | 
| 155 } | 155 } | 
| 156 | 156 | 
| 157 | 157 | 
| 158 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 158 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 
| 159   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 159   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 
| 160   return Handle<Object>(reinterpret_cast<Object**>( | 160   return Handle<Object>(reinterpret_cast<Object**>( | 
| 161       Assembler::target_address_at(pc_, host_))); | 161       Assembler::target_address_at(pc_, host_))); | 
| 162 } | 162 } | 
| 163 | 163 | 
| 164 | 164 | 
| 165 void RelocInfo::set_target_object(Object* target, | 165 void RelocInfo::set_target_object(Object* target, | 
| 166                                   WriteBarrierMode write_barrier_mode, | 166                                   WriteBarrierMode write_barrier_mode, | 
| 167                                   ICacheFlushMode icache_flush_mode) { | 167                                   ICacheFlushMode icache_flush_mode) { | 
| 168   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 168   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 
| 169   Assembler::set_target_address_at(pc_, host_, | 169   Assembler::set_target_address_at(pc_, host_, | 
| 170                                    reinterpret_cast<Address>(target), | 170                                    reinterpret_cast<Address>(target), | 
| 171                                    icache_flush_mode); | 171                                    icache_flush_mode); | 
| 172   if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 172   if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 
| 173       host() != NULL && | 173       host() != NULL && | 
| 174       target->IsHeapObject()) { | 174       target->IsHeapObject()) { | 
| 175     host()->GetHeap()->incremental_marking()->RecordWrite( | 175     host()->GetHeap()->incremental_marking()->RecordWrite( | 
| 176         host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 176         host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 
| 177   } | 177   } | 
| 178 } | 178 } | 
| 179 | 179 | 
| 180 | 180 | 
| 181 Address RelocInfo::target_reference() { | 181 Address RelocInfo::target_reference() { | 
| 182   ASSERT(rmode_ == EXTERNAL_REFERENCE); | 182   DCHECK(rmode_ == EXTERNAL_REFERENCE); | 
| 183   return Assembler::target_address_at(pc_, host_); | 183   return Assembler::target_address_at(pc_, host_); | 
| 184 } | 184 } | 
| 185 | 185 | 
| 186 | 186 | 
| 187 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 187 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 
| 188   ASSERT(IsRuntimeEntry(rmode_)); | 188   DCHECK(IsRuntimeEntry(rmode_)); | 
| 189   return target_address(); | 189   return target_address(); | 
| 190 } | 190 } | 
| 191 | 191 | 
| 192 | 192 | 
| 193 void RelocInfo::set_target_runtime_entry(Address target, | 193 void RelocInfo::set_target_runtime_entry(Address target, | 
| 194                                          WriteBarrierMode write_barrier_mode, | 194                                          WriteBarrierMode write_barrier_mode, | 
| 195                                          ICacheFlushMode icache_flush_mode) { | 195                                          ICacheFlushMode icache_flush_mode) { | 
| 196   ASSERT(IsRuntimeEntry(rmode_)); | 196   DCHECK(IsRuntimeEntry(rmode_)); | 
| 197   if (target_address() != target) | 197   if (target_address() != target) | 
| 198     set_target_address(target, write_barrier_mode, icache_flush_mode); | 198     set_target_address(target, write_barrier_mode, icache_flush_mode); | 
| 199 } | 199 } | 
| 200 | 200 | 
| 201 | 201 | 
| 202 Handle<Cell> RelocInfo::target_cell_handle() { | 202 Handle<Cell> RelocInfo::target_cell_handle() { | 
| 203   ASSERT(rmode_ == RelocInfo::CELL); | 203   DCHECK(rmode_ == RelocInfo::CELL); | 
| 204   Address address = Memory::Address_at(pc_); | 204   Address address = Memory::Address_at(pc_); | 
| 205   return Handle<Cell>(reinterpret_cast<Cell**>(address)); | 205   return Handle<Cell>(reinterpret_cast<Cell**>(address)); | 
| 206 } | 206 } | 
| 207 | 207 | 
| 208 | 208 | 
| 209 Cell* RelocInfo::target_cell() { | 209 Cell* RelocInfo::target_cell() { | 
| 210   ASSERT(rmode_ == RelocInfo::CELL); | 210   DCHECK(rmode_ == RelocInfo::CELL); | 
| 211   return Cell::FromValueAddress(Memory::Address_at(pc_)); | 211   return Cell::FromValueAddress(Memory::Address_at(pc_)); | 
| 212 } | 212 } | 
| 213 | 213 | 
| 214 | 214 | 
| 215 void RelocInfo::set_target_cell(Cell* cell, | 215 void RelocInfo::set_target_cell(Cell* cell, | 
| 216                                 WriteBarrierMode write_barrier_mode, | 216                                 WriteBarrierMode write_barrier_mode, | 
| 217                                 ICacheFlushMode icache_flush_mode) { | 217                                 ICacheFlushMode icache_flush_mode) { | 
| 218   ASSERT(rmode_ == RelocInfo::CELL); | 218   DCHECK(rmode_ == RelocInfo::CELL); | 
| 219   Address address = cell->address() + Cell::kValueOffset; | 219   Address address = cell->address() + Cell::kValueOffset; | 
| 220   Memory::Address_at(pc_) = address; | 220   Memory::Address_at(pc_) = address; | 
| 221   if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 221   if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 
| 222     // TODO(1550) We are passing NULL as a slot because cell can never be on | 222     // TODO(1550) We are passing NULL as a slot because cell can never be on | 
| 223     // evacuation candidate. | 223     // evacuation candidate. | 
| 224     host()->GetHeap()->incremental_marking()->RecordWrite( | 224     host()->GetHeap()->incremental_marking()->RecordWrite( | 
| 225         host(), NULL, cell); | 225         host(), NULL, cell); | 
| 226   } | 226   } | 
| 227 } | 227 } | 
| 228 | 228 | 
| 229 | 229 | 
| 230 static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; | 230 static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; | 
| 231 | 231 | 
| 232 | 232 | 
| 233 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { | 233 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { | 
| 234   UNREACHABLE();  // This should never be reached on Arm. | 234   UNREACHABLE();  // This should never be reached on Arm. | 
| 235   return Handle<Object>(); | 235   return Handle<Object>(); | 
| 236 } | 236 } | 
| 237 | 237 | 
| 238 | 238 | 
| 239 Code* RelocInfo::code_age_stub() { | 239 Code* RelocInfo::code_age_stub() { | 
| 240   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 240   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 
| 241   return Code::GetCodeFromTargetAddress( | 241   return Code::GetCodeFromTargetAddress( | 
| 242       Memory::Address_at(pc_ + | 242       Memory::Address_at(pc_ + | 
| 243                          (kNoCodeAgeSequenceLength - Assembler::kInstrSize))); | 243                          (kNoCodeAgeSequenceLength - Assembler::kInstrSize))); | 
| 244 } | 244 } | 
| 245 | 245 | 
| 246 | 246 | 
| 247 void RelocInfo::set_code_age_stub(Code* stub, | 247 void RelocInfo::set_code_age_stub(Code* stub, | 
| 248                                   ICacheFlushMode icache_flush_mode) { | 248                                   ICacheFlushMode icache_flush_mode) { | 
| 249   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 249   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 
| 250   Memory::Address_at(pc_ + | 250   Memory::Address_at(pc_ + | 
| 251                      (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) = | 251                      (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) = | 
| 252       stub->instruction_start(); | 252       stub->instruction_start(); | 
| 253 } | 253 } | 
| 254 | 254 | 
| 255 | 255 | 
| 256 Address RelocInfo::call_address() { | 256 Address RelocInfo::call_address() { | 
| 257   // The 2 instructions offset assumes patched debug break slot or return | 257   // The 2 instructions offset assumes patched debug break slot or return | 
| 258   // sequence. | 258   // sequence. | 
| 259   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 259   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 
| 260          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 260          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 
| 261   return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); | 261   return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); | 
| 262 } | 262 } | 
| 263 | 263 | 
| 264 | 264 | 
| 265 void RelocInfo::set_call_address(Address target) { | 265 void RelocInfo::set_call_address(Address target) { | 
| 266   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 266   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 
| 267          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 267          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 
| 268   Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; | 268   Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; | 
| 269   if (host() != NULL) { | 269   if (host() != NULL) { | 
| 270     Object* target_code = Code::GetCodeFromTargetAddress(target); | 270     Object* target_code = Code::GetCodeFromTargetAddress(target); | 
| 271     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 271     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 
| 272         host(), this, HeapObject::cast(target_code)); | 272         host(), this, HeapObject::cast(target_code)); | 
| 273   } | 273   } | 
| 274 } | 274 } | 
| 275 | 275 | 
| 276 | 276 | 
| 277 Object* RelocInfo::call_object() { | 277 Object* RelocInfo::call_object() { | 
| 278   return *call_object_address(); | 278   return *call_object_address(); | 
| 279 } | 279 } | 
| 280 | 280 | 
| 281 | 281 | 
| 282 void RelocInfo::set_call_object(Object* target) { | 282 void RelocInfo::set_call_object(Object* target) { | 
| 283   *call_object_address() = target; | 283   *call_object_address() = target; | 
| 284 } | 284 } | 
| 285 | 285 | 
| 286 | 286 | 
| 287 Object** RelocInfo::call_object_address() { | 287 Object** RelocInfo::call_object_address() { | 
| 288   ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 288   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 
| 289          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 289          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 
| 290   return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 290   return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 
| 291 } | 291 } | 
| 292 | 292 | 
| 293 | 293 | 
| 294 void RelocInfo::WipeOut() { | 294 void RelocInfo::WipeOut() { | 
| 295   ASSERT(IsEmbeddedObject(rmode_) || | 295   DCHECK(IsEmbeddedObject(rmode_) || | 
| 296          IsCodeTarget(rmode_) || | 296          IsCodeTarget(rmode_) || | 
| 297          IsRuntimeEntry(rmode_) || | 297          IsRuntimeEntry(rmode_) || | 
| 298          IsExternalReference(rmode_)); | 298          IsExternalReference(rmode_)); | 
| 299   Assembler::set_target_address_at(pc_, host_, NULL); | 299   Assembler::set_target_address_at(pc_, host_, NULL); | 
| 300 } | 300 } | 
| 301 | 301 | 
| 302 | 302 | 
| 303 bool RelocInfo::IsPatchedReturnSequence() { | 303 bool RelocInfo::IsPatchedReturnSequence() { | 
| 304   Instr current_instr = Assembler::instr_at(pc_); | 304   Instr current_instr = Assembler::instr_at(pc_); | 
| 305   Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); | 305   Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); | 
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 439   //  ldr   ip, [pc, ip]  @ call address | 439   //  ldr   ip, [pc, ip]  @ call address | 
| 440   //  blx   ip | 440   //  blx   ip | 
| 441   //                      @ return address | 441   //                      @ return address | 
| 442   Address candidate = pc - 2 * Assembler::kInstrSize; | 442   Address candidate = pc - 2 * Assembler::kInstrSize; | 
| 443   Instr candidate_instr(Memory::int32_at(candidate)); | 443   Instr candidate_instr(Memory::int32_at(candidate)); | 
| 444   if (IsLdrPcImmediateOffset(candidate_instr) | | 444   if (IsLdrPcImmediateOffset(candidate_instr) | | 
| 445       IsLdrPpImmediateOffset(candidate_instr)) { | 445       IsLdrPpImmediateOffset(candidate_instr)) { | 
| 446     return candidate; | 446     return candidate; | 
| 447   } else if (IsLdrPpRegOffset(candidate_instr)) { | 447   } else if (IsLdrPpRegOffset(candidate_instr)) { | 
| 448     candidate = pc - 4 * Assembler::kInstrSize; | 448     candidate = pc - 4 * Assembler::kInstrSize; | 
| 449     ASSERT(IsMovW(Memory::int32_at(candidate)) && | 449     DCHECK(IsMovW(Memory::int32_at(candidate)) && | 
| 450            IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize))); | 450            IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize))); | 
| 451     return candidate; | 451     return candidate; | 
| 452   } else { | 452   } else { | 
| 453     candidate = pc - 3 * Assembler::kInstrSize; | 453     candidate = pc - 3 * Assembler::kInstrSize; | 
| 454     ASSERT(IsMovW(Memory::int32_at(candidate)) && | 454     DCHECK(IsMovW(Memory::int32_at(candidate)) && | 
| 455            IsMovT(Memory::int32_at(candidate + kInstrSize))); | 455            IsMovT(Memory::int32_at(candidate + kInstrSize))); | 
| 456     return candidate; | 456     return candidate; | 
| 457   } | 457   } | 
| 458 } | 458 } | 
| 459 | 459 | 
| 460 | 460 | 
| 461 Address Assembler::return_address_from_call_start(Address pc) { | 461 Address Assembler::return_address_from_call_start(Address pc) { | 
| 462   if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) | | 462   if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) | | 
| 463       IsLdrPpImmediateOffset(Memory::int32_at(pc))) { | 463       IsLdrPpImmediateOffset(Memory::int32_at(pc))) { | 
| 464     // Load from constant pool, small section. | 464     // Load from constant pool, small section. | 
| 465     return pc + kInstrSize * 2; | 465     return pc + kInstrSize * 2; | 
| 466   } else { | 466   } else { | 
| 467     ASSERT(IsMovW(Memory::int32_at(pc))); | 467     DCHECK(IsMovW(Memory::int32_at(pc))); | 
| 468     ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 468     DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); | 
| 469     if (IsLdrPpRegOffset(Memory::int32_at(pc + kInstrSize))) { | 469     if (IsLdrPpRegOffset(Memory::int32_at(pc + kInstrSize))) { | 
| 470       // Load from constant pool, extended section. | 470       // Load from constant pool, extended section. | 
| 471       return pc + kInstrSize * 4; | 471       return pc + kInstrSize * 4; | 
| 472     } else { | 472     } else { | 
| 473       // A movw / movt load immediate. | 473       // A movw / movt load immediate. | 
| 474       return pc + kInstrSize * 3; | 474       return pc + kInstrSize * 3; | 
| 475     } | 475     } | 
| 476   } | 476   } | 
| 477 } | 477 } | 
| 478 | 478 | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 491   return !Assembler::IsMovW(Memory::int32_at(pc)) || | 491   return !Assembler::IsMovW(Memory::int32_at(pc)) || | 
| 492          (FLAG_enable_ool_constant_pool && | 492          (FLAG_enable_ool_constant_pool && | 
| 493           Assembler::IsLdrPpRegOffset( | 493           Assembler::IsLdrPpRegOffset( | 
| 494               Memory::int32_at(pc + 2 * Assembler::kInstrSize))); | 494               Memory::int32_at(pc + 2 * Assembler::kInstrSize))); | 
| 495 } | 495 } | 
| 496 | 496 | 
| 497 | 497 | 
| 498 Address Assembler::constant_pool_entry_address( | 498 Address Assembler::constant_pool_entry_address( | 
| 499     Address pc, ConstantPoolArray* constant_pool) { | 499     Address pc, ConstantPoolArray* constant_pool) { | 
| 500   if (FLAG_enable_ool_constant_pool) { | 500   if (FLAG_enable_ool_constant_pool) { | 
| 501     ASSERT(constant_pool != NULL); | 501     DCHECK(constant_pool != NULL); | 
| 502     int cp_offset; | 502     int cp_offset; | 
| 503     if (IsMovW(Memory::int32_at(pc))) { | 503     if (IsMovW(Memory::int32_at(pc))) { | 
| 504       ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)) && | 504       DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) && | 
| 505              IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))); | 505              IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))); | 
| 506       // This is an extended constant pool lookup. | 506       // This is an extended constant pool lookup. | 
| 507       Instruction* movw_instr = Instruction::At(pc); | 507       Instruction* movw_instr = Instruction::At(pc); | 
| 508       Instruction* movt_instr = Instruction::At(pc + kInstrSize); | 508       Instruction* movt_instr = Instruction::At(pc + kInstrSize); | 
| 509       cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) | | 509       cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) | | 
| 510                   movw_instr->ImmedMovwMovtValue(); | 510                   movw_instr->ImmedMovwMovtValue(); | 
| 511     } else { | 511     } else { | 
| 512       // This is a small constant pool lookup. | 512       // This is a small constant pool lookup. | 
| 513       ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc))); | 513       DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc))); | 
| 514       cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc)); | 514       cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc)); | 
| 515     } | 515     } | 
| 516     return reinterpret_cast<Address>(constant_pool) + cp_offset; | 516     return reinterpret_cast<Address>(constant_pool) + cp_offset; | 
| 517   } else { | 517   } else { | 
| 518     ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc))); | 518     DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc))); | 
| 519     Instr instr = Memory::int32_at(pc); | 519     Instr instr = Memory::int32_at(pc); | 
| 520     return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta; | 520     return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta; | 
| 521   } | 521   } | 
| 522 } | 522 } | 
| 523 | 523 | 
| 524 | 524 | 
| 525 Address Assembler::target_address_at(Address pc, | 525 Address Assembler::target_address_at(Address pc, | 
| 526                                      ConstantPoolArray* constant_pool) { | 526                                      ConstantPoolArray* constant_pool) { | 
| 527   if (is_constant_pool_load(pc)) { | 527   if (is_constant_pool_load(pc)) { | 
| 528     // This is a constant pool lookup. Return the value in the constant pool. | 528     // This is a constant pool lookup. Return the value in the constant pool. | 
| 529     return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); | 529     return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); | 
| 530   } else { | 530   } else { | 
| 531     // This is an movw_movt immediate load. Return the immediate. | 531     // This is an movw_movt immediate load. Return the immediate. | 
| 532     ASSERT(IsMovW(Memory::int32_at(pc)) && | 532     DCHECK(IsMovW(Memory::int32_at(pc)) && | 
| 533            IsMovT(Memory::int32_at(pc + kInstrSize))); | 533            IsMovT(Memory::int32_at(pc + kInstrSize))); | 
| 534     Instruction* movw_instr = Instruction::At(pc); | 534     Instruction* movw_instr = Instruction::At(pc); | 
| 535     Instruction* movt_instr = Instruction::At(pc + kInstrSize); | 535     Instruction* movt_instr = Instruction::At(pc + kInstrSize); | 
| 536     return reinterpret_cast<Address>( | 536     return reinterpret_cast<Address>( | 
| 537         (movt_instr->ImmedMovwMovtValue() << 16) | | 537         (movt_instr->ImmedMovwMovtValue() << 16) | | 
| 538          movw_instr->ImmedMovwMovtValue()); | 538          movw_instr->ImmedMovwMovtValue()); | 
| 539   } | 539   } | 
| 540 } | 540 } | 
| 541 | 541 | 
| 542 | 542 | 
| 543 void Assembler::set_target_address_at(Address pc, | 543 void Assembler::set_target_address_at(Address pc, | 
| 544                                       ConstantPoolArray* constant_pool, | 544                                       ConstantPoolArray* constant_pool, | 
| 545                                       Address target, | 545                                       Address target, | 
| 546                                       ICacheFlushMode icache_flush_mode) { | 546                                       ICacheFlushMode icache_flush_mode) { | 
| 547   if (is_constant_pool_load(pc)) { | 547   if (is_constant_pool_load(pc)) { | 
| 548     // This is a constant pool lookup. Update the entry in the constant pool. | 548     // This is a constant pool lookup. Update the entry in the constant pool. | 
| 549     Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target; | 549     Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target; | 
| 550     // Intuitively, we would think it is necessary to always flush the | 550     // Intuitively, we would think it is necessary to always flush the | 
| 551     // instruction cache after patching a target address in the code as follows: | 551     // instruction cache after patching a target address in the code as follows: | 
| 552     //   CpuFeatures::FlushICache(pc, sizeof(target)); | 552     //   CpuFeatures::FlushICache(pc, sizeof(target)); | 
| 553     // However, on ARM, no instruction is actually patched in the case | 553     // However, on ARM, no instruction is actually patched in the case | 
| 554     // of embedded constants of the form: | 554     // of embedded constants of the form: | 
| 555     // ldr   ip, [pp, #...] | 555     // ldr   ip, [pp, #...] | 
| 556     // since the instruction accessing this address in the constant pool remains | 556     // since the instruction accessing this address in the constant pool remains | 
| 557     // unchanged. | 557     // unchanged. | 
| 558   } else { | 558   } else { | 
| 559     // This is an movw_movt immediate load. Patch the immediate embedded in the | 559     // This is an movw_movt immediate load. Patch the immediate embedded in the | 
| 560     // instructions. | 560     // instructions. | 
| 561     ASSERT(IsMovW(Memory::int32_at(pc))); | 561     DCHECK(IsMovW(Memory::int32_at(pc))); | 
| 562     ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 562     DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); | 
| 563     uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); | 563     uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); | 
| 564     uint32_t immediate = reinterpret_cast<uint32_t>(target); | 564     uint32_t immediate = reinterpret_cast<uint32_t>(target); | 
| 565     instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); | 565     instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); | 
| 566     instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); | 566     instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); | 
| 567     ASSERT(IsMovW(Memory::int32_at(pc))); | 567     DCHECK(IsMovW(Memory::int32_at(pc))); | 
| 568     ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 568     DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); | 
| 569     if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 569     if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 
| 570       CpuFeatures::FlushICache(pc, 2 * kInstrSize); | 570       CpuFeatures::FlushICache(pc, 2 * kInstrSize); | 
| 571     } | 571     } | 
| 572   } | 572   } | 
| 573 } | 573 } | 
| 574 | 574 | 
| 575 | 575 | 
| 576 } }  // namespace v8::internal | 576 } }  // namespace v8::internal | 
| 577 | 577 | 
| 578 #endif  // V8_ARM_ASSEMBLER_ARM_INL_H_ | 578 #endif  // V8_ARM_ASSEMBLER_ARM_INL_H_ | 
| OLD | NEW | 
|---|