v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
assembler-mips-inl.h
Go to the documentation of this file.
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 are
6 // 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 distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2012 the V8 project authors. All rights reserved.
34 
35 
36 #ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_
37 #define V8_MIPS_ASSEMBLER_MIPS_INL_H_
38 
39 #include "mips/assembler-mips.h"
40 
41 #include "cpu.h"
42 #include "debug.h"
43 
44 
45 namespace v8 {
46 namespace internal {
47 
48 // -----------------------------------------------------------------------------
49 // Operand and MemOperand.
50 
51 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) {
52  rm_ = no_reg;
53  imm32_ = immediate;
54  rmode_ = rmode;
55 }
56 
57 
58 Operand::Operand(const ExternalReference& f) {
59  rm_ = no_reg;
60  imm32_ = reinterpret_cast<int32_t>(f.address());
61  rmode_ = RelocInfo::EXTERNAL_REFERENCE;
62 }
63 
64 
65 Operand::Operand(Smi* value) {
66  rm_ = no_reg;
67  imm32_ = reinterpret_cast<intptr_t>(value);
68  rmode_ = RelocInfo::NONE;
69 }
70 
71 
72 Operand::Operand(Register rm) {
73  rm_ = rm;
74 }
75 
76 
77 bool Operand::is_reg() const {
78  return rm_.is_valid();
79 }
80 
81 
83  ASSERT(reg.code() % 2 == 0);
85  ASSERT(reg.is_valid());
86  ASSERT(!reg.is(kDoubleRegZero));
88  return (reg.code() / 2);
89 }
90 
91 
92 // -----------------------------------------------------------------------------
93 // RelocInfo.
94 
95 void RelocInfo::apply(intptr_t delta) {
96  if (IsCodeTarget(rmode_)) {
97  uint32_t scope1 = (uint32_t) target_address() & ~kImm28Mask;
98  uint32_t scope2 = reinterpret_cast<uint32_t>(pc_) & ~kImm28Mask;
99 
100  if (scope1 != scope2) {
102  }
103  }
104  if (IsInternalReference(rmode_)) {
105  // Absolute code pointer inside code object moves with the code object.
106  byte* p = reinterpret_cast<byte*>(pc_);
107  int count = Assembler::RelocateInternalReference(p, delta);
108  CPU::FlushICache(p, count * sizeof(uint32_t));
109  }
110 }
111 
112 
113 Address RelocInfo::target_address() {
114  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
115  return Assembler::target_address_at(pc_);
116 }
117 
118 
119 Address RelocInfo::target_address_address() {
120  ASSERT(IsCodeTarget(rmode_) ||
121  rmode_ == RUNTIME_ENTRY ||
122  rmode_ == EMBEDDED_OBJECT ||
123  rmode_ == EXTERNAL_REFERENCE);
124  // Read the address of the word containing the target_address in an
125  // instruction stream.
126  // The only architecture-independent user of this function is the serializer.
127  // The serializer uses it to find out how many raw bytes of instruction to
128  // output before the next target.
129  // For an instruction like LUI/ORI where the target bits are mixed into the
130  // instruction bits, the size of the target will be zero, indicating that the
131  // serializer should not step forward in memory after a target is resolved
132  // and written. In this case the target_address_address function should
133  // return the end of the instructions to be patched, allowing the
134  // deserializer to deserialize the instructions as raw bytes and put them in
135  // place, ready to be patched with the target. After jump optimization,
136  // that is the address of the instruction that follows J/JAL/JR/JALR
137  // instruction.
138  return reinterpret_cast<Address>(
140 }
141 
142 
143 int RelocInfo::target_address_size() {
145 }
146 
147 
148 void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
149  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
151  if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) {
152  Object* target_code = Code::GetCodeFromTargetAddress(target);
153  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
154  host(), this, HeapObject::cast(target_code));
155  }
156 }
157 
158 
160  return pc - kCallTargetAddressOffset;
161 }
162 
163 
164 Object* RelocInfo::target_object() {
165  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
166  return reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
167 }
168 
169 
170 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
171  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
172  return Handle<Object>(reinterpret_cast<Object**>(
174 }
175 
176 
177 Object** RelocInfo::target_object_address() {
178  // Provide a "natural pointer" to the embedded object,
179  // which can be de-referenced during heap iteration.
180  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
181  reconstructed_obj_ptr_ =
182  reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
183  return &reconstructed_obj_ptr_;
184 }
185 
186 
187 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
188  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
189  Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target));
190  if (mode == UPDATE_WRITE_BARRIER &&
191  host() != NULL &&
192  target->IsHeapObject()) {
193  host()->GetHeap()->incremental_marking()->RecordWrite(
194  host(), &Memory::Object_at(pc_), HeapObject::cast(target));
195  }
196 }
197 
198 
199 Address* RelocInfo::target_reference_address() {
200  ASSERT(rmode_ == EXTERNAL_REFERENCE);
201  reconstructed_adr_ptr_ = Assembler::target_address_at(pc_);
202  return &reconstructed_adr_ptr_;
203 }
204 
205 
206 Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
207  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
208  Address address = Memory::Address_at(pc_);
209  return Handle<JSGlobalPropertyCell>(
210  reinterpret_cast<JSGlobalPropertyCell**>(address));
211 }
212 
213 
214 JSGlobalPropertyCell* RelocInfo::target_cell() {
215  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
217 }
218 
219 
220 void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
221  WriteBarrierMode mode) {
222  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
223  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
224  Memory::Address_at(pc_) = address;
225  if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
226  // TODO(1550) We are passing NULL as a slot because cell can never be on
227  // evacuation candidate.
228  host()->GetHeap()->incremental_marking()->RecordWrite(
229  host(), NULL, cell);
230  }
231 }
232 
233 
234 Address RelocInfo::call_address() {
235  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
236  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
237  // The pc_ offset of 0 assumes mips patched return sequence per
238  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
239  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
240  return Assembler::target_address_at(pc_);
241 }
242 
243 
244 void RelocInfo::set_call_address(Address target) {
245  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
246  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
247  // The pc_ offset of 0 assumes mips patched return sequence per
248  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
249  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
251  if (host() != NULL) {
252  Object* target_code = Code::GetCodeFromTargetAddress(target);
253  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
254  host(), this, HeapObject::cast(target_code));
255  }
256 }
257 
258 
259 Object* RelocInfo::call_object() {
260  return *call_object_address();
261 }
262 
263 
264 Object** RelocInfo::call_object_address() {
265  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
266  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
267  return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
268 }
269 
270 
271 void RelocInfo::set_call_object(Object* target) {
272  *call_object_address() = target;
273 }
274 
275 
276 bool RelocInfo::IsPatchedReturnSequence() {
277  Instr instr0 = Assembler::instr_at(pc_);
278  Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
279  Instr instr2 = Assembler::instr_at(pc_ + 2 * Assembler::kInstrSize);
280  bool patched_return = ((instr0 & kOpcodeMask) == LUI &&
281  (instr1 & kOpcodeMask) == ORI &&
282  ((instr2 & kOpcodeMask) == JAL ||
283  ((instr2 & kOpcodeMask) == SPECIAL &&
284  (instr2 & kFunctionFieldMask) == JALR)));
285  return patched_return;
286 }
287 
288 
289 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
290  Instr current_instr = Assembler::instr_at(pc_);
291  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
292 }
293 
294 
295 void RelocInfo::Visit(ObjectVisitor* visitor) {
296  RelocInfo::Mode mode = rmode();
297  if (mode == RelocInfo::EMBEDDED_OBJECT) {
298  visitor->VisitEmbeddedPointer(this);
299  } else if (RelocInfo::IsCodeTarget(mode)) {
300  visitor->VisitCodeTarget(this);
301  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
302  visitor->VisitGlobalPropertyCell(this);
303  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
304  visitor->VisitExternalReference(this);
305 #ifdef ENABLE_DEBUGGER_SUPPORT
306  // TODO(isolates): Get a cached isolate below.
307  } else if (((RelocInfo::IsJSReturn(mode) &&
308  IsPatchedReturnSequence()) ||
309  (RelocInfo::IsDebugBreakSlot(mode) &&
310  IsPatchedDebugBreakSlotSequence())) &&
311  Isolate::Current()->debug()->has_break_points()) {
312  visitor->VisitDebugTarget(this);
313 #endif
314  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
315  visitor->VisitRuntimeEntry(this);
316  }
317 }
318 
319 
320 template<typename StaticVisitor>
321 void RelocInfo::Visit(Heap* heap) {
322  RelocInfo::Mode mode = rmode();
323  if (mode == RelocInfo::EMBEDDED_OBJECT) {
324  StaticVisitor::VisitEmbeddedPointer(heap, this);
325  } else if (RelocInfo::IsCodeTarget(mode)) {
326  StaticVisitor::VisitCodeTarget(heap, this);
327  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
328  StaticVisitor::VisitGlobalPropertyCell(heap, this);
329  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
330  StaticVisitor::VisitExternalReference(this);
331 #ifdef ENABLE_DEBUGGER_SUPPORT
332  } else if (heap->isolate()->debug()->has_break_points() &&
333  ((RelocInfo::IsJSReturn(mode) &&
334  IsPatchedReturnSequence()) ||
335  (RelocInfo::IsDebugBreakSlot(mode) &&
336  IsPatchedDebugBreakSlotSequence()))) {
337  StaticVisitor::VisitDebugTarget(heap, this);
338 #endif
339  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
340  StaticVisitor::VisitRuntimeEntry(this);
341  }
342 }
343 
344 
345 // -----------------------------------------------------------------------------
346 // Assembler.
347 
348 
349 void Assembler::CheckBuffer() {
350  if (buffer_space() <= kGap) {
351  GrowBuffer();
352  }
353 }
354 
355 
356 void Assembler::CheckTrampolinePoolQuick() {
357  if (pc_offset() >= next_buffer_check_) {
359  }
360 }
361 
362 
363 void Assembler::emit(Instr x) {
364  if (!is_buffer_growth_blocked()) {
365  CheckBuffer();
366  }
367  *reinterpret_cast<Instr*>(pc_) = x;
368  pc_ += kInstrSize;
369  CheckTrampolinePoolQuick();
370 }
371 
372 
373 } } // namespace v8::internal
374 
375 #endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_
byte * Address
Definition: globals.h:157
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
static int ToAllocationIndex(FPURegister reg)
static HeapObject * cast(Object *obj)
int int32_t
Definition: unicode.cc:47
bool is(FPURegister creg) const
#define ASSERT(condition)
Definition: checks.h:270
const int kFunctionFieldMask
bool is_buffer_growth_blocked() const
static void JumpLabelToJumpRegister(Address pc)
uint8_t byte
Definition: globals.h:156
#define kLithiumScratchDouble
static const int kSpecialTargetSize
const int kOpcodeMask
static Address & Address_at(Address addr)
Definition: v8memory.h:71
static void set_target_address_at(Address pc, Address target)
static const int kInstructionsFor32BitConstant
const Register pc
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:3559
const int kImm28Mask
static const int kCallTargetAddressOffset
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
static Address target_address_at(Address pc)
#define kDoubleRegZero
static JSGlobalPropertyCell * FromValueAddress(Address value)
Definition: objects.h:7993
static Address target_address_from_return_address(Address pc)
static int RelocateInternalReference(byte *pc, intptr_t pc_delta)
static const int kInstrSize
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
#define RUNTIME_ENTRY(name, nargs, ressize)
const Register no_reg
static const int kNumAllocatableRegisters
static void FlushICache(void *start, size_t size)