blob: 517d4adab08ead0c3d49abf4d054617181618075 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001
Andrei Popescu31002712010-02-23 13:46:05 +00002// Copyright (c) 1994-2006 Sun Microsystems Inc.
3// All Rights Reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// - Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11//
12// - Redistribution in binary form must reproduce the above copyright
13// notice, this list of conditions and the following disclaimer in the
14// documentation and/or other materials provided with the 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 "AS
21// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32// The original source code covered by the above license above has been
33// modified significantly by Google Inc.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010034// Copyright 2012 the V8 project authors. All rights reserved.
Andrei Popescu31002712010-02-23 13:46:05 +000035
36
37#ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_
38#define V8_MIPS_ASSEMBLER_MIPS_INL_H_
39
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040#include "src/mips/assembler-mips.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +010041
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042#include "src/assembler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043#include "src/debug/debug.h"
Andrei Popescu31002712010-02-23 13:46:05 +000044
45
46namespace v8 {
47namespace internal {
48
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049
50bool CpuFeatures::SupportsCrankshaft() { return IsSupported(FPU); }
51
52
Andrei Popescu31002712010-02-23 13:46:05 +000053// -----------------------------------------------------------------------------
Ben Murdoch257744e2011-11-30 15:57:28 +000054// Operand and MemOperand.
Andrei Popescu31002712010-02-23 13:46:05 +000055
56Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) {
57 rm_ = no_reg;
58 imm32_ = immediate;
59 rmode_ = rmode;
60}
61
Steve Block44f0eee2011-05-26 01:26:41 +010062
Andrei Popescu31002712010-02-23 13:46:05 +000063Operand::Operand(const ExternalReference& f) {
64 rm_ = no_reg;
65 imm32_ = reinterpret_cast<int32_t>(f.address());
66 rmode_ = RelocInfo::EXTERNAL_REFERENCE;
67}
68
Andrei Popescu31002712010-02-23 13:46:05 +000069
70Operand::Operand(Smi* value) {
71 rm_ = no_reg;
72 imm32_ = reinterpret_cast<intptr_t>(value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 rmode_ = RelocInfo::NONE32;
Andrei Popescu31002712010-02-23 13:46:05 +000074}
75
Steve Block44f0eee2011-05-26 01:26:41 +010076
Andrei Popescu31002712010-02-23 13:46:05 +000077Operand::Operand(Register rm) {
78 rm_ = rm;
79}
80
Steve Block44f0eee2011-05-26 01:26:41 +010081
Andrei Popescu31002712010-02-23 13:46:05 +000082bool Operand::is_reg() const {
83 return rm_.is_valid();
84}
85
86
Andrei Popescu31002712010-02-23 13:46:05 +000087// -----------------------------------------------------------------------------
Ben Murdoch257744e2011-11-30 15:57:28 +000088// RelocInfo.
Andrei Popescu31002712010-02-23 13:46:05 +000089
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090void RelocInfo::apply(intptr_t delta) {
91 if (IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000092 // Absolute code pointer inside code object moves with the code object.
93 byte* p = reinterpret_cast<byte*>(pc_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 int count = Assembler::RelocateInternalReference(rmode_, p, delta);
95 Assembler::FlushICache(isolate_, p, count * sizeof(uint32_t));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000096 }
Andrei Popescu31002712010-02-23 13:46:05 +000097}
98
99
100Address RelocInfo::target_address() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
102 return Assembler::target_address_at(pc_, host_);
Andrei Popescu31002712010-02-23 13:46:05 +0000103}
104
Ben Murdochda12d292016-06-02 14:46:10 +0100105Address RelocInfo::wasm_memory_reference() {
106 DCHECK(IsWasmMemoryReference(rmode_));
107 return Assembler::target_address_at(pc_, host_);
108}
Andrei Popescu31002712010-02-23 13:46:05 +0000109
110Address RelocInfo::target_address_address() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111 DCHECK(IsCodeTarget(rmode_) ||
112 IsRuntimeEntry(rmode_) ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100113 rmode_ == EMBEDDED_OBJECT ||
114 rmode_ == EXTERNAL_REFERENCE);
115 // Read the address of the word containing the target_address in an
116 // instruction stream.
117 // The only architecture-independent user of this function is the serializer.
118 // The serializer uses it to find out how many raw bytes of instruction to
119 // output before the next target.
120 // For an instruction like LUI/ORI where the target bits are mixed into the
121 // instruction bits, the size of the target will be zero, indicating that the
122 // serializer should not step forward in memory after a target is resolved
123 // and written. In this case the target_address_address function should
124 // return the end of the instructions to be patched, allowing the
125 // deserializer to deserialize the instructions as raw bytes and put them in
126 // place, ready to be patched with the target. After jump optimization,
127 // that is the address of the instruction that follows J/JAL/JR/JALR
128 // instruction.
129 return reinterpret_cast<Address>(
130 pc_ + Assembler::kInstructionsFor32BitConstant * Assembler::kInstrSize);
Steve Block44f0eee2011-05-26 01:26:41 +0100131}
132
133
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134Address RelocInfo::constant_pool_entry_address() {
135 UNREACHABLE();
136 return NULL;
137}
138
139
Steve Block44f0eee2011-05-26 01:26:41 +0100140int RelocInfo::target_address_size() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100141 return Assembler::kSpecialTargetSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000142}
143
144
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145void RelocInfo::set_target_address(Address target,
146 WriteBarrierMode write_barrier_mode,
147 ICacheFlushMode icache_flush_mode) {
148 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 Assembler::set_target_address_at(isolate_, pc_, host_, target,
150 icache_flush_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151 if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
152 host() != NULL && IsCodeTarget(rmode_)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100153 Object* target_code = Code::GetCodeFromTargetAddress(target);
154 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
155 host(), this, HeapObject::cast(target_code));
156 }
Andrei Popescu31002712010-02-23 13:46:05 +0000157}
158
Ben Murdochda12d292016-06-02 14:46:10 +0100159void RelocInfo::update_wasm_memory_reference(
160 Address old_base, Address new_base, size_t old_size, size_t new_size,
161 ICacheFlushMode icache_flush_mode) {
162 DCHECK(IsWasmMemoryReference(rmode_));
163 DCHECK(old_base <= wasm_memory_reference() &&
164 wasm_memory_reference() < old_base + old_size);
165 Address updated_reference = new_base + (wasm_memory_reference() - old_base);
166 DCHECK(new_base <= updated_reference &&
167 updated_reference < new_base + new_size);
168 Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
169 icache_flush_mode);
170}
Andrei Popescu31002712010-02-23 13:46:05 +0000171
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000172Address Assembler::target_address_from_return_address(Address pc) {
173 return pc - kCallTargetAddressOffset;
174}
175
176
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177void Assembler::set_target_internal_reference_encoded_at(Address pc,
178 Address target) {
Ben Murdochda12d292016-06-02 14:46:10 +0100179 Instr instr1 = Assembler::instr_at(pc + 0 * Assembler::kInstrSize);
180 Instr instr2 = Assembler::instr_at(pc + 1 * Assembler::kInstrSize);
181 DCHECK(Assembler::IsLui(instr1));
182 DCHECK(Assembler::IsOri(instr2) || Assembler::IsJicOrJialc(instr2));
183 instr1 &= ~kImm16Mask;
184 instr2 &= ~kImm16Mask;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 int32_t imm = reinterpret_cast<int32_t>(target);
186 DCHECK((imm & 3) == 0);
Ben Murdochda12d292016-06-02 14:46:10 +0100187 if (Assembler::IsJicOrJialc(instr2)) {
188 // Encoded internal references are lui/jic load of 32-bit absolute address.
189 uint32_t lui_offset_u, jic_offset_u;
190 Assembler::UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u);
191
192 Assembler::instr_at_put(pc + 0 * Assembler::kInstrSize,
193 instr1 | lui_offset_u);
194 Assembler::instr_at_put(pc + 1 * Assembler::kInstrSize,
195 instr2 | jic_offset_u);
196 } else {
197 // Encoded internal references are lui/ori load of 32-bit absolute address.
198 Assembler::instr_at_put(pc + 0 * Assembler::kInstrSize,
199 instr1 | ((imm >> kLuiShift) & kImm16Mask));
200 Assembler::instr_at_put(pc + 1 * Assembler::kInstrSize,
201 instr2 | (imm & kImm16Mask));
202 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203
204 // Currently used only by deserializer, and all code will be flushed
205 // after complete deserialization, no need to flush on each reference.
206}
207
208
209void Assembler::deserialization_set_target_internal_reference_at(
210 Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) {
211 if (mode == RelocInfo::INTERNAL_REFERENCE_ENCODED) {
212 DCHECK(IsLui(instr_at(pc)));
213 set_target_internal_reference_encoded_at(pc, target);
214 } else {
215 DCHECK(mode == RelocInfo::INTERNAL_REFERENCE);
216 Memory::Address_at(pc) = target;
217 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218}
219
220
Andrei Popescu31002712010-02-23 13:46:05 +0000221Object* RelocInfo::target_object() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
223 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
Andrei Popescu31002712010-02-23 13:46:05 +0000224}
225
226
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100227Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
Andrei Popescu31002712010-02-23 13:46:05 +0000229 return Handle<Object>(reinterpret_cast<Object**>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 Assembler::target_address_at(pc_, host_)));
Andrei Popescu31002712010-02-23 13:46:05 +0000231}
232
233
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234void RelocInfo::set_target_object(Object* target,
235 WriteBarrierMode write_barrier_mode,
236 ICacheFlushMode icache_flush_mode) {
237 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 Assembler::set_target_address_at(isolate_, pc_, host_,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 reinterpret_cast<Address>(target),
240 icache_flush_mode);
241 if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100242 host() != NULL &&
243 target->IsHeapObject()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100244 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
245 host(), this, HeapObject::cast(target));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100246 }
Andrei Popescu31002712010-02-23 13:46:05 +0000247}
248
249
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250Address RelocInfo::target_external_reference() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251 DCHECK(rmode_ == EXTERNAL_REFERENCE);
252 return Assembler::target_address_at(pc_, host_);
Steve Block44f0eee2011-05-26 01:26:41 +0100253}
254
255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256Address RelocInfo::target_internal_reference() {
257 if (rmode_ == INTERNAL_REFERENCE) {
258 return Memory::Address_at(pc_);
259 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100260 // Encoded internal references are lui/ori or lui/jic load of 32-bit
261 // absolute address.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 DCHECK(rmode_ == INTERNAL_REFERENCE_ENCODED);
Ben Murdochda12d292016-06-02 14:46:10 +0100263 Instr instr1 = Assembler::instr_at(pc_ + 0 * Assembler::kInstrSize);
264 Instr instr2 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
265 DCHECK(Assembler::IsLui(instr1));
266 DCHECK(Assembler::IsOri(instr2) || Assembler::IsJicOrJialc(instr2));
267 if (Assembler::IsJicOrJialc(instr2)) {
268 return reinterpret_cast<Address>(
269 Assembler::CreateTargetAddress(instr1, instr2));
270 }
271 int32_t imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
272 imm |= (instr2 & static_cast<int32_t>(kImm16Mask));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273 return reinterpret_cast<Address>(imm);
274 }
275}
276
277
278Address RelocInfo::target_internal_reference_address() {
279 DCHECK(rmode_ == INTERNAL_REFERENCE || rmode_ == INTERNAL_REFERENCE_ENCODED);
280 return reinterpret_cast<Address>(pc_);
281}
282
283
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284Address RelocInfo::target_runtime_entry(Assembler* origin) {
285 DCHECK(IsRuntimeEntry(rmode_));
286 return target_address();
287}
288
289
290void RelocInfo::set_target_runtime_entry(Address target,
291 WriteBarrierMode write_barrier_mode,
292 ICacheFlushMode icache_flush_mode) {
293 DCHECK(IsRuntimeEntry(rmode_));
294 if (target_address() != target)
295 set_target_address(target, write_barrier_mode, icache_flush_mode);
296}
297
298
299Handle<Cell> RelocInfo::target_cell_handle() {
300 DCHECK(rmode_ == RelocInfo::CELL);
Steve Block44f0eee2011-05-26 01:26:41 +0100301 Address address = Memory::Address_at(pc_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 return Handle<Cell>(reinterpret_cast<Cell**>(address));
Steve Block44f0eee2011-05-26 01:26:41 +0100303}
304
305
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306Cell* RelocInfo::target_cell() {
307 DCHECK(rmode_ == RelocInfo::CELL);
308 return Cell::FromValueAddress(Memory::Address_at(pc_));
Steve Block44f0eee2011-05-26 01:26:41 +0100309}
310
311
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312void RelocInfo::set_target_cell(Cell* cell,
313 WriteBarrierMode write_barrier_mode,
314 ICacheFlushMode icache_flush_mode) {
315 DCHECK(rmode_ == RelocInfo::CELL);
316 Address address = cell->address() + Cell::kValueOffset;
Steve Block44f0eee2011-05-26 01:26:41 +0100317 Memory::Address_at(pc_) = address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100319 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
320 cell);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100321 }
Andrei Popescu31002712010-02-23 13:46:05 +0000322}
323
324
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325static const int kNoCodeAgeSequenceLength = 7 * Assembler::kInstrSize;
326
327
328Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
329 UNREACHABLE(); // This should never be reached on Arm.
330 return Handle<Object>();
331}
332
333
334Code* RelocInfo::code_age_stub() {
335 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
336 return Code::GetCodeFromTargetAddress(
337 Assembler::target_address_at(pc_ + Assembler::kInstrSize, host_));
338}
339
340
341void RelocInfo::set_code_age_stub(Code* stub,
342 ICacheFlushMode icache_flush_mode) {
343 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 Assembler::set_target_address_at(isolate_, pc_ + Assembler::kInstrSize, host_,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 stub->instruction_start());
346}
347
348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349Address RelocInfo::debug_call_address() {
350 // The pc_ offset of 0 assumes patched debug break slot or return
351 // sequence.
352 DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 return Assembler::target_address_at(pc_, host_);
Andrei Popescu31002712010-02-23 13:46:05 +0000354}
355
356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357void RelocInfo::set_debug_call_address(Address target) {
358 DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
359 // The pc_ offset of 0 assumes patched debug break slot or return
360 // sequence.
361 Assembler::set_target_address_at(isolate_, pc_, host_, target);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100362 if (host() != NULL) {
363 Object* target_code = Code::GetCodeFromTargetAddress(target);
364 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
365 host(), this, HeapObject::cast(target_code));
366 }
Andrei Popescu31002712010-02-23 13:46:05 +0000367}
368
369
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370void RelocInfo::WipeOut() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
372 IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
373 IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_));
374 if (IsInternalReference(rmode_)) {
375 Memory::Address_at(pc_) = NULL;
376 } else if (IsInternalReferenceEncoded(rmode_)) {
377 Assembler::set_target_internal_reference_encoded_at(pc_, nullptr);
378 } else {
379 Assembler::set_target_address_at(isolate_, pc_, host_, NULL);
380 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381}
382
383
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
Steve Block44f0eee2011-05-26 01:26:41 +0100385 RelocInfo::Mode mode = rmode();
386 if (mode == RelocInfo::EMBEDDED_OBJECT) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100387 visitor->VisitEmbeddedPointer(this);
Steve Block44f0eee2011-05-26 01:26:41 +0100388 } else if (RelocInfo::IsCodeTarget(mode)) {
389 visitor->VisitCodeTarget(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390 } else if (mode == RelocInfo::CELL) {
391 visitor->VisitCell(this);
Steve Block44f0eee2011-05-26 01:26:41 +0100392 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100393 visitor->VisitExternalReference(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394 } else if (mode == RelocInfo::INTERNAL_REFERENCE ||
395 mode == RelocInfo::INTERNAL_REFERENCE_ENCODED) {
396 visitor->VisitInternalReference(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 } else if (RelocInfo::IsCodeAgeSequence(mode)) {
398 visitor->VisitCodeAgeSequence(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 } else if (RelocInfo::IsDebugBreakSlot(mode) &&
400 IsPatchedDebugBreakSlotSequence()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100401 visitor->VisitDebugTarget(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 } else if (RelocInfo::IsRuntimeEntry(mode)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100403 visitor->VisitRuntimeEntry(this);
404 }
405}
406
407
408template<typename StaticVisitor>
409void RelocInfo::Visit(Heap* heap) {
410 RelocInfo::Mode mode = rmode();
411 if (mode == RelocInfo::EMBEDDED_OBJECT) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100412 StaticVisitor::VisitEmbeddedPointer(heap, this);
Steve Block44f0eee2011-05-26 01:26:41 +0100413 } else if (RelocInfo::IsCodeTarget(mode)) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000414 StaticVisitor::VisitCodeTarget(heap, this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415 } else if (mode == RelocInfo::CELL) {
416 StaticVisitor::VisitCell(heap, this);
Steve Block44f0eee2011-05-26 01:26:41 +0100417 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100418 StaticVisitor::VisitExternalReference(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 } else if (mode == RelocInfo::INTERNAL_REFERENCE ||
420 mode == RelocInfo::INTERNAL_REFERENCE_ENCODED) {
421 StaticVisitor::VisitInternalReference(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 } else if (RelocInfo::IsCodeAgeSequence(mode)) {
423 StaticVisitor::VisitCodeAgeSequence(heap, this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 } else if (RelocInfo::IsDebugBreakSlot(mode) &&
425 IsPatchedDebugBreakSlotSequence()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000426 StaticVisitor::VisitDebugTarget(heap, this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 } else if (RelocInfo::IsRuntimeEntry(mode)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100428 StaticVisitor::VisitRuntimeEntry(this);
429 }
Andrei Popescu31002712010-02-23 13:46:05 +0000430}
431
432
433// -----------------------------------------------------------------------------
Ben Murdoch257744e2011-11-30 15:57:28 +0000434// Assembler.
Andrei Popescu31002712010-02-23 13:46:05 +0000435
436
437void Assembler::CheckBuffer() {
438 if (buffer_space() <= kGap) {
439 GrowBuffer();
440 }
441}
442
443
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444void Assembler::CheckTrampolinePoolQuick(int extra_instructions) {
445 if (pc_offset() >= next_buffer_check_ - extra_instructions * kInstrSize) {
Steve Block44f0eee2011-05-26 01:26:41 +0100446 CheckTrampolinePool();
447 }
448}
449
450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451void Assembler::CheckForEmitInForbiddenSlot() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000452 if (!is_buffer_growth_blocked()) {
453 CheckBuffer();
454 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 if (IsPrevInstrCompactBranch()) {
456 // Nop instruction to preceed a CTI in forbidden slot:
457 Instr nop = SPECIAL | SLL;
458 *reinterpret_cast<Instr*>(pc_) = nop;
459 pc_ += kInstrSize;
460
461 ClearCompactBranchState();
462 }
463}
464
465
466void Assembler::EmitHelper(Instr x, CompactBranchType is_compact_branch) {
467 if (IsPrevInstrCompactBranch()) {
468 if (Instruction::IsForbiddenAfterBranchInstr(x)) {
469 // Nop instruction to preceed a CTI in forbidden slot:
470 Instr nop = SPECIAL | SLL;
471 *reinterpret_cast<Instr*>(pc_) = nop;
472 pc_ += kInstrSize;
473 }
474 ClearCompactBranchState();
475 }
Andrei Popescu31002712010-02-23 13:46:05 +0000476 *reinterpret_cast<Instr*>(pc_) = x;
477 pc_ += kInstrSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 if (is_compact_branch == CompactBranchType::COMPACT_BRANCH) {
479 EmittedCompactBranchInstruction();
480 }
Steve Block44f0eee2011-05-26 01:26:41 +0100481 CheckTrampolinePoolQuick();
Andrei Popescu31002712010-02-23 13:46:05 +0000482}
483
484
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485template <typename T>
486void Assembler::EmitHelper(T x) {
487 *reinterpret_cast<T*>(pc_) = x;
488 pc_ += sizeof(x);
489 CheckTrampolinePoolQuick();
490}
491
492
493void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
494 if (!is_buffer_growth_blocked()) {
495 CheckBuffer();
496 }
497 EmitHelper(x, is_compact_branch);
498}
499
500
501} // namespace internal
502} // namespace v8
Andrei Popescu31002712010-02-23 13:46:05 +0000503
504#endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_