v8  3.11.10(node0.8.26)
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));
87  ASSERT(!reg.is(kLithiumScratchDouble));
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 
159 Object* RelocInfo::target_object() {
160  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
161  return reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
162 }
163 
164 
165 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
166  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
167  return Handle<Object>(reinterpret_cast<Object**>(
169 }
170 
171 
172 Object** RelocInfo::target_object_address() {
173  // Provide a "natural pointer" to the embedded object,
174  // which can be de-referenced during heap iteration.
175  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
176  reconstructed_obj_ptr_ =
177  reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
178  return &reconstructed_obj_ptr_;
179 }
180 
181 
182 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
183  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
184  Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target));
185  if (mode == UPDATE_WRITE_BARRIER &&
186  host() != NULL &&
187  target->IsHeapObject()) {
188  host()->GetHeap()->incremental_marking()->RecordWrite(
189  host(), &Memory::Object_at(pc_), HeapObject::cast(target));
190  }
191 }
192 
193 
194 Address* RelocInfo::target_reference_address() {
195  ASSERT(rmode_ == EXTERNAL_REFERENCE);
196  reconstructed_adr_ptr_ = Assembler::target_address_at(pc_);
197  return &reconstructed_adr_ptr_;
198 }
199 
200 
201 Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
202  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
203  Address address = Memory::Address_at(pc_);
204  return Handle<JSGlobalPropertyCell>(
205  reinterpret_cast<JSGlobalPropertyCell**>(address));
206 }
207 
208 
209 JSGlobalPropertyCell* RelocInfo::target_cell() {
210  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
211  Address address = Memory::Address_at(pc_);
214  return reinterpret_cast<JSGlobalPropertyCell*>(object);
215 }
216 
217 
218 void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
219  WriteBarrierMode mode) {
220  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
221  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
222  Memory::Address_at(pc_) = address;
223  if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
224  // TODO(1550) We are passing NULL as a slot because cell can never be on
225  // evacuation candidate.
226  host()->GetHeap()->incremental_marking()->RecordWrite(
227  host(), NULL, cell);
228  }
229 }
230 
231 
232 Address RelocInfo::call_address() {
233  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
234  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
235  // The pc_ offset of 0 assumes mips patched return sequence per
236  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
237  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
238  return Assembler::target_address_at(pc_);
239 }
240 
241 
242 void RelocInfo::set_call_address(Address target) {
243  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
244  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
245  // The pc_ offset of 0 assumes mips patched return sequence per
246  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
247  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
249  if (host() != NULL) {
250  Object* target_code = Code::GetCodeFromTargetAddress(target);
251  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
252  host(), this, HeapObject::cast(target_code));
253  }
254 }
255 
256 
257 Object* RelocInfo::call_object() {
258  return *call_object_address();
259 }
260 
261 
262 Object** RelocInfo::call_object_address() {
263  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
264  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
265  return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
266 }
267 
268 
269 void RelocInfo::set_call_object(Object* target) {
270  *call_object_address() = target;
271 }
272 
273 
274 bool RelocInfo::IsPatchedReturnSequence() {
275  Instr instr0 = Assembler::instr_at(pc_);
276  Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
277  Instr instr2 = Assembler::instr_at(pc_ + 2 * Assembler::kInstrSize);
278  bool patched_return = ((instr0 & kOpcodeMask) == LUI &&
279  (instr1 & kOpcodeMask) == ORI &&
280  ((instr2 & kOpcodeMask) == JAL ||
281  ((instr2 & kOpcodeMask) == SPECIAL &&
282  (instr2 & kFunctionFieldMask) == JALR)));
283  return patched_return;
284 }
285 
286 
287 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
288  Instr current_instr = Assembler::instr_at(pc_);
289  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
290 }
291 
292 
293 void RelocInfo::Visit(ObjectVisitor* visitor) {
294  RelocInfo::Mode mode = rmode();
295  if (mode == RelocInfo::EMBEDDED_OBJECT) {
296  visitor->VisitEmbeddedPointer(this);
297  } else if (RelocInfo::IsCodeTarget(mode)) {
298  visitor->VisitCodeTarget(this);
299  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
300  visitor->VisitGlobalPropertyCell(this);
301  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
302  visitor->VisitExternalReference(this);
303 #ifdef ENABLE_DEBUGGER_SUPPORT
304  // TODO(isolates): Get a cached isolate below.
305  } else if (((RelocInfo::IsJSReturn(mode) &&
306  IsPatchedReturnSequence()) ||
307  (RelocInfo::IsDebugBreakSlot(mode) &&
308  IsPatchedDebugBreakSlotSequence())) &&
309  Isolate::Current()->debug()->has_break_points()) {
310  visitor->VisitDebugTarget(this);
311 #endif
312  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
313  visitor->VisitRuntimeEntry(this);
314  }
315 }
316 
317 
318 template<typename StaticVisitor>
319 void RelocInfo::Visit(Heap* heap) {
320  RelocInfo::Mode mode = rmode();
321  if (mode == RelocInfo::EMBEDDED_OBJECT) {
322  StaticVisitor::VisitEmbeddedPointer(heap, this);
323  } else if (RelocInfo::IsCodeTarget(mode)) {
324  StaticVisitor::VisitCodeTarget(heap, this);
325  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
326  StaticVisitor::VisitGlobalPropertyCell(heap, this);
327  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
328  StaticVisitor::VisitExternalReference(this);
329 #ifdef ENABLE_DEBUGGER_SUPPORT
330  } else if (heap->isolate()->debug()->has_break_points() &&
331  ((RelocInfo::IsJSReturn(mode) &&
332  IsPatchedReturnSequence()) ||
333  (RelocInfo::IsDebugBreakSlot(mode) &&
334  IsPatchedDebugBreakSlotSequence()))) {
335  StaticVisitor::VisitDebugTarget(heap, this);
336 #endif
337  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
338  StaticVisitor::VisitRuntimeEntry(this);
339  }
340 }
341 
342 
343 // -----------------------------------------------------------------------------
344 // Assembler.
345 
346 
347 void Assembler::CheckBuffer() {
348  if (buffer_space() <= kGap) {
349  GrowBuffer();
350  }
351 }
352 
353 
354 void Assembler::CheckTrampolinePoolQuick() {
355  if (pc_offset() >= next_buffer_check_) {
357  }
358 }
359 
360 
361 void Assembler::emit(Instr x) {
362  if (!is_buffer_growth_blocked()) {
363  CheckBuffer();
364  }
365  *reinterpret_cast<Instr*>(pc_) = x;
366  pc_ += kInstrSize;
367  CheckTrampolinePoolQuick();
368 }
369 
370 
371 } } // namespace v8::internal
372 
373 #endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_
byte * Address
Definition: globals.h:172
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:171
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
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:3380
const int kImm28Mask
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
static Address target_address_at(Address pc)
#define kDoubleRegZero
static int RelocateInternalReference(byte *pc, intptr_t pc_delta)
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
static HeapObject * FromAddress(Address address)
Definition: objects-inl.h:1163
static const int kInstrSize
#define RUNTIME_ENTRY(name, nargs, ressize)
const Register no_reg
static const int kNumAllocatableRegisters
static void FlushICache(void *start, size_t size)