OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2011-2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 28 #ifndef V8_SH4_MACRO_ASSEMBLER_SH4_H_ |
29 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 29 #define V8_SH4_MACRO_ASSEMBLER_SH4_H_ |
30 | 30 |
31 #include "assembler.h" | 31 #include "assembler.h" |
32 #include "frames.h" | 32 #include "frames.h" |
33 #include "v8globals.h" | 33 #include "v8globals.h" |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 // ---------------------------------------------------------------------------- | 38 // ---------------------------------------------------------------------------- |
39 // Static helper functions | 39 // Static helper functions |
40 | 40 |
41 // Generate a MemOperand for loading a field from an object. | 41 // Generate a MemOperand for loading a field from an object. |
42 inline MemOperand FieldMemOperand(Register object, int offset) { | 42 inline MemOperand FieldMemOperand(Register object, int offset) { |
43 return MemOperand(object, offset - kHeapObjectTag); | 43 return MemOperand(object, offset - kHeapObjectTag); |
44 } | 44 } |
45 | 45 |
46 | |
47 inline Operand SmiUntagOperand(Register object) { | |
48 return Operand(object, ASR, kSmiTagSize); | |
49 } | |
50 | |
51 | |
52 | |
53 // Give alias names to registers | |
54 const Register cp = { 8 }; // JavaScript context pointer | |
55 const Register kRootRegister = { 10 }; // Roots array pointer. | |
56 | |
57 // Flags used for the AllocateInNewSpace functions. | 46 // Flags used for the AllocateInNewSpace functions. |
58 enum AllocationFlags { | 47 enum AllocationFlags { |
59 // No special flags. | 48 // No special flags. |
60 NO_ALLOCATION_FLAGS = 0, | 49 NO_ALLOCATION_FLAGS = 0, |
61 // Return the pointer to the allocated already tagged as a heap object. | 50 // Return the pointer to the allocated already tagged as a heap object. |
62 TAG_OBJECT = 1 << 0, | 51 TAG_OBJECT = 1 << 0, |
63 // The content of the result register already contains the allocation top in | 52 // The content of the result register already contains the allocation top in |
64 // new space. | 53 // new space. |
65 RESULT_CONTAINS_TOP = 1 << 1, | 54 RESULT_CONTAINS_TOP = 1 << 1, |
66 // Specify that the requested size of the space to allocate is specified in | 55 // Specify that the requested size of the space to allocate is specified in |
67 // words instead of bytes. | 56 // words instead of bytes. |
68 SIZE_IN_WORDS = 1 << 2 | 57 SIZE_IN_WORDS = 1 << 2 |
69 }; | 58 }; |
70 | 59 |
71 // Flags used for AllocateHeapNumber | |
72 enum TaggingMode { | |
73 // Tag the result. | |
74 TAG_RESULT, | |
75 // Don't tag | |
76 DONT_TAG_RESULT | |
77 }; | |
78 | 60 |
79 // Flags used for the ObjectToDoubleVFPRegister function. | 61 // Flags used for the ObjectToDoubleVFPRegister function. |
80 enum ObjectToDoubleFlags { | 62 enum ObjectToDoubleFlags { |
81 // No special flags. | 63 // No special flags. |
82 NO_OBJECT_TO_DOUBLE_FLAGS = 0, | 64 NO_OBJECT_TO_DOUBLE_FLAGS = 0, |
83 // Object is known to be a non smi. | 65 // Object is known to be a non smi. |
84 OBJECT_NOT_SMI = 1 << 0, | 66 OBJECT_NOT_SMI = 1 << 0, |
85 // Don't load NaNs or infinities, branch to the non number case instead. | 67 // Don't load NaNs or infinities, branch to the non number case instead. |
86 AVOID_NANS_AND_INFINITIES = 1 << 1 | 68 AVOID_NANS_AND_INFINITIES = 1 << 1 |
87 }; | 69 }; |
88 | 70 |
89 | 71 |
90 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; | 72 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; |
91 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; | 73 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; |
92 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; | 74 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; |
93 | 75 |
94 | 76 |
95 #ifdef DEBUG | 77 #ifdef DEBUG |
96 bool AreAliased(Register reg1, | 78 bool AreAliased(Register reg1, |
97 Register reg2, | 79 Register reg2, |
98 Register reg3 = no_reg, | 80 Register reg3 = no_reg, |
99 Register reg4 = no_reg, | 81 Register reg4 = no_reg, |
100 Register reg5 = no_reg, | 82 Register reg5 = no_reg, |
101 Register reg6 = no_reg); | 83 Register reg6 = no_reg); |
102 #endif | 84 #endif |
103 | 85 |
104 | 86 |
105 enum TargetAddressStorageMode { | |
106 CAN_INLINE_TARGET_ADDRESS, | |
107 NEVER_INLINE_TARGET_ADDRESS | |
108 }; | |
109 | |
110 // MacroAssembler implements a collection of frequently used macros. | 87 // MacroAssembler implements a collection of frequently used macros. |
111 class MacroAssembler: public Assembler { | 88 class MacroAssembler: public Assembler { |
112 public: | 89 public: |
113 // The isolate parameter can be NULL if the macro assembler should | 90 // The isolate parameter can be NULL if the macro assembler should |
114 // not use isolate-dependent functionality. In this case, it's the | 91 // not use isolate-dependent functionality. In this case, it's the |
115 // responsibility of the caller to never invoke such function on the | 92 // responsibility of the caller to never invoke such function on the |
116 // macro assembler. | 93 // macro assembler. |
117 MacroAssembler(Isolate* isolate, void* buffer, int size); | 94 MacroAssembler(Isolate* isolate, void* buffer, int size); |
118 | 95 |
119 // Jump, Call, and Ret pseudo instructions implementing inter-working. | |
120 void Jump(Register target, Condition cond = al); | |
121 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al); | |
122 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); | |
123 static int CallSize(Register target, Condition cond = al); | |
124 void Call(Register target, Condition cond = al); | |
125 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al); | |
126 static int CallSizeNotPredictableCodeSize(Address target, | |
127 RelocInfo::Mode rmode, | |
128 Condition cond = al); | |
129 void Call(Address target, RelocInfo::Mode rmode, | |
130 Condition cond = al, | |
131 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS); | |
132 int CallSize(Handle<Code> code, | |
133 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, | |
134 TypeFeedbackId ast_id = TypeFeedbackId::None(), | |
135 Condition cond = al); | |
136 void Call(Handle<Code> code, | |
137 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, | |
138 TypeFeedbackId ast_id = TypeFeedbackId::None(), | |
139 Condition cond = al, | |
140 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS); | |
141 void Ret(Condition cond = al); | |
142 | |
143 // Emit code to discard a non-negative number of pointer-sized elements | |
144 // from the stack, clobbering only the sp register. | |
145 void Drop(int count, Condition cond = al); | |
146 | |
147 void Ret(int drop, Condition cond = al); | |
148 | |
149 // Swap two registers. If the scratch register is omitted then a slightly | |
150 // less efficient form using xor instead of mov is emitted. | |
151 void Swap(Register reg1, | |
152 Register reg2, | |
153 Register scratch = no_reg, | |
154 Condition cond = al); | |
155 | |
156 | |
157 void And(Register dst, Register src1, const Operand& src2, | |
158 Condition cond = al); | |
159 void Ubfx(Register dst, Register src, int lsb, int width, | |
160 Condition cond = al); | |
161 void Sbfx(Register dst, Register src, int lsb, int width, | |
162 Condition cond = al); | |
163 // The scratch register is not used for ARMv7. | |
164 // scratch can be the same register as src (in which case it is trashed), but | |
165 // not the same as dst. | |
166 void Bfi(Register dst, | |
167 Register src, | |
168 Register scratch, | |
169 int lsb, | |
170 int width, | |
171 Condition cond = al); | |
172 void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al); | |
173 void Usat(Register dst, int satpos, const Operand& src, | |
174 Condition cond = al); | |
175 | |
176 void Call(Label* target); | |
177 | |
178 // Register move. May do nothing if the registers are identical. | |
179 void Move(Register dst, Handle<Object> value); | |
180 void Move(Register dst, Register src, Condition cond = al); | |
181 void Move(DoubleRegister dst, DoubleRegister src); | |
182 | |
183 // Load an object from the root table. | 96 // Load an object from the root table. |
184 void LoadRoot(Register destination, | 97 void LoadRoot(Register destination, |
185 Heap::RootListIndex index, | 98 Heap::RootListIndex index); |
186 Condition cond = al); | |
187 // Store an object to the root table. | 99 // Store an object to the root table. |
188 void StoreRoot(Register source, | 100 void StoreRoot(Register source, |
189 Heap::RootListIndex index, | 101 Heap::RootListIndex index); |
190 Condition cond = al); | |
191 | 102 |
192 void LoadHeapObject(Register dst, Handle<HeapObject> object); | 103 void LoadHeapObject(Register dst, Handle<HeapObject> object); |
193 | 104 |
194 void LoadObject(Register result, Handle<Object> object) { | 105 void LoadObject(Register result, Handle<Object> object) { |
195 if (object->IsHeapObject()) { | 106 if (object->IsHeapObject()) { |
196 LoadHeapObject(result, Handle<HeapObject>::cast(object)); | 107 LoadHeapObject(result, Handle<HeapObject>::cast(object)); |
197 } else { | 108 } else { |
198 Move(result, object); | 109 Move(result, object); |
199 } | 110 } |
200 } | 111 } |
201 | 112 |
202 // --------------------------------------------------------------------------- | 113 // --------------------------------------------------------------------------- |
203 // GC Support | 114 // GC Support |
204 | 115 |
205 void IncrementalMarkingRecordWriteHelper(Register object, | |
206 Register value, | |
207 Register address); | |
208 | |
209 enum RememberedSetFinalAction { | 116 enum RememberedSetFinalAction { |
210 kReturnAtEnd, | 117 kReturnAtEnd, |
211 kFallThroughAtEnd | 118 kFallThroughAtEnd |
212 }; | 119 }; |
213 | 120 |
214 // Record in the remembered set the fact that we have a pointer to new space | 121 // Record in the remembered set the fact that we have a pointer to new space |
215 // at the address pointed to by the addr register. Only works if addr is not | 122 // at the address pointed to by the addr register. Only works if addr is not |
216 // in new space. | 123 // in new space. |
217 void RememberedSetHelper(Register object, // Used for debug code. | 124 void RememberedSetHelper(Register object, // Used for debug code. |
218 Register addr, | 125 Register addr, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 // then we just fall through, since it is already live. If it is white and | 166 // then we just fall through, since it is already live. If it is white and |
260 // we can determine that it doesn't need to be scanned, then we just mark it | 167 // we can determine that it doesn't need to be scanned, then we just mark it |
261 // black and fall through. For the rest we jump to the label so the | 168 // black and fall through. For the rest we jump to the label so the |
262 // incremental marker can fix its assumptions. | 169 // incremental marker can fix its assumptions. |
263 void EnsureNotWhite(Register object, | 170 void EnsureNotWhite(Register object, |
264 Register scratch1, | 171 Register scratch1, |
265 Register scratch2, | 172 Register scratch2, |
266 Register scratch3, | 173 Register scratch3, |
267 Label* object_is_white_and_not_data); | 174 Label* object_is_white_and_not_data); |
268 | 175 |
269 // Detects conservatively whether an object is data-only, i.e. it does need to | 176 // Check if object is in new space. |
270 // be scanned by the garbage collector. | 177 // scratch can be object itself, but it will be clobbered. |
271 void JumpIfDataObject(Register value, | 178 void InNewSpace(Register object, |
272 Register scratch, | 179 Register scratch, |
273 Label* not_data_object); | 180 // eq for "in new space?", ne for "not in new space?" |
| 181 Condition cond, |
| 182 Label* branch); |
274 | 183 |
275 // Notify the garbage collector that we wrote a pointer into an object. | 184 // Notify the garbage collector that we wrote a pointer into an object. |
276 // |object| is the object being stored into, |value| is the object being | 185 // |object| is the object being stored into, |value| is the object being |
277 // stored. value and scratch registers are clobbered by the operation. | 186 // stored. value and scratch registers are clobbered by the operation. |
278 // The offset is the offset from the start of the object, not the offset from | 187 // The offset is the offset from the start of the object, not the offset from |
279 // the tagged HeapObject pointer. For use with FieldOperand(reg, off). | 188 // the tagged HeapObject pointer. For use with FieldOperand(reg, off). |
280 void RecordWriteField( | 189 void RecordWriteField( |
281 Register object, | 190 Register object, |
282 int offset, | 191 int offset, |
283 Register value, | 192 Register value, |
(...skipping 29 matching lines...) Expand all Loading... |
313 // address registers are clobbered by the operation. | 222 // address registers are clobbered by the operation. |
314 void RecordWrite( | 223 void RecordWrite( |
315 Register object, | 224 Register object, |
316 Register address, | 225 Register address, |
317 Register value, | 226 Register value, |
318 LinkRegisterStatus lr_status, | 227 LinkRegisterStatus lr_status, |
319 SaveFPRegsMode save_fp, | 228 SaveFPRegsMode save_fp, |
320 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, | 229 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, |
321 SmiCheck smi_check = INLINE_SMI_CHECK); | 230 SmiCheck smi_check = INLINE_SMI_CHECK); |
322 | 231 |
323 // Push a handle. | 232 |
324 void Push(Handle<Object> handle); | 233 // Mark the register as dead. Put the pattern 0xFFFFFFDE into the register. |
| 234 void Dead(Register dead) { |
| 235 // Fit in a single SH4 mov_imm_ instruction |
| 236 mov(dead, Operand(static_cast<int>(0xFFFFFFDE))); |
| 237 } |
| 238 |
| 239 // Mark up to four registers dead at a time. |
| 240 void Dead(Register d1, Register d2, Register d3 = no_reg, |
| 241 Register d4 = no_reg) { |
| 242 Dead(d1); |
| 243 Dead(d2); |
| 244 if (d3.is_valid()) Dead(d3); |
| 245 if (d4.is_valid()) Dead(d4); |
| 246 } |
| 247 |
| 248 void Push(Handle<Object> handle) { push(Operand(handle), sh4_ip); } |
325 | 249 |
326 // Push two registers. Pushes leftmost register first (to highest address). | 250 // Push two registers. Pushes leftmost register first (to highest address). |
327 void Push(Register src1, Register src2, Condition cond = al) { | 251 void Push(Register src1, Register src2) { |
328 ASSERT(!src1.is(src2)); | 252 ASSERT(!src1.is(src2)); |
329 if (src1.code() > src2.code()) { | 253 push(src1); |
330 stm(db_w, sp, src1.bit() | src2.bit(), cond); | 254 push(src2); |
331 } else { | |
332 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | |
333 str(src2, MemOperand(sp, 4, NegPreIndex), cond); | |
334 } | |
335 } | 255 } |
336 | 256 |
337 // Push three registers. Pushes leftmost register first (to highest address). | 257 // Push three registers. Pushes leftmost register first (to highest address). |
338 void Push(Register src1, Register src2, Register src3, Condition cond = al) { | 258 void Push(Register src1, Register src2, Register src3) { |
339 ASSERT(!src1.is(src2)); | 259 ASSERT(!src1.is(src2)); |
340 ASSERT(!src2.is(src3)); | 260 ASSERT(!src2.is(src3)); |
341 ASSERT(!src1.is(src3)); | 261 ASSERT(!src1.is(src3)); |
342 if (src1.code() > src2.code()) { | 262 push(src1); |
343 if (src2.code() > src3.code()) { | 263 push(src2); |
344 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | 264 push(src3); |
345 } else { | |
346 stm(db_w, sp, src1.bit() | src2.bit(), cond); | |
347 str(src3, MemOperand(sp, 4, NegPreIndex), cond); | |
348 } | |
349 } else { | |
350 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | |
351 Push(src2, src3, cond); | |
352 } | |
353 } | 265 } |
354 | 266 |
355 // Push four registers. Pushes leftmost register first (to highest address). | 267 // Push four registers. Pushes leftmost register first (to highest address). |
356 void Push(Register src1, | 268 void Push(Register src1, Register src2, |
357 Register src2, | 269 Register src3, Register src4) { |
358 Register src3, | |
359 Register src4, | |
360 Condition cond = al) { | |
361 ASSERT(!src1.is(src2)); | 270 ASSERT(!src1.is(src2)); |
362 ASSERT(!src2.is(src3)); | 271 ASSERT(!src2.is(src3)); |
363 ASSERT(!src1.is(src3)); | 272 ASSERT(!src1.is(src3)); |
364 ASSERT(!src1.is(src4)); | 273 ASSERT(!src1.is(src4)); |
365 ASSERT(!src2.is(src4)); | 274 ASSERT(!src2.is(src4)); |
366 ASSERT(!src3.is(src4)); | 275 ASSERT(!src3.is(src4)); |
367 if (src1.code() > src2.code()) { | 276 push(src1); |
368 if (src2.code() > src3.code()) { | 277 push(src2); |
369 if (src3.code() > src4.code()) { | 278 push(src3); |
370 stm(db_w, | 279 push(src4); |
371 sp, | |
372 src1.bit() | src2.bit() | src3.bit() | src4.bit(), | |
373 cond); | |
374 } else { | |
375 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | |
376 str(src4, MemOperand(sp, 4, NegPreIndex), cond); | |
377 } | |
378 } else { | |
379 stm(db_w, sp, src1.bit() | src2.bit(), cond); | |
380 Push(src3, src4, cond); | |
381 } | |
382 } else { | |
383 str(src1, MemOperand(sp, 4, NegPreIndex), cond); | |
384 Push(src2, src3, src4, cond); | |
385 } | |
386 } | 280 } |
387 | 281 |
388 // Pop two registers. Pops rightmost register first (from lower address). | 282 // Pop two registers. Pops rightmost register first (from lower address). |
389 void Pop(Register src1, Register src2, Condition cond = al) { | 283 void Pop(Register src1, Register src2) { |
390 ASSERT(!src1.is(src2)); | 284 ASSERT(!src1.is(src2)); |
391 if (src1.code() > src2.code()) { | 285 pop(src2); |
392 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); | 286 pop(src1); |
393 } else { | |
394 ldr(src2, MemOperand(sp, 4, PostIndex), cond); | |
395 ldr(src1, MemOperand(sp, 4, PostIndex), cond); | |
396 } | |
397 } | 287 } |
398 | 288 |
399 // Pop three registers. Pops rightmost register first (from lower address). | 289 // Pop three registers. Pops rightmost register first (from lower address). |
400 void Pop(Register src1, Register src2, Register src3, Condition cond = al) { | 290 void Pop(Register src1, Register src2, Register src3) { |
401 ASSERT(!src1.is(src2)); | 291 ASSERT(!src1.is(src2)); |
402 ASSERT(!src2.is(src3)); | 292 ASSERT(!src2.is(src3)); |
403 ASSERT(!src1.is(src3)); | 293 ASSERT(!src1.is(src3)); |
404 if (src1.code() > src2.code()) { | 294 pop(src3); |
405 if (src2.code() > src3.code()) { | 295 pop(src2); |
406 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | 296 pop(src1); |
407 } else { | |
408 ldr(src3, MemOperand(sp, 4, PostIndex), cond); | |
409 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); | |
410 } | |
411 } else { | |
412 Pop(src2, src3, cond); | |
413 str(src1, MemOperand(sp, 4, PostIndex), cond); | |
414 } | |
415 } | 297 } |
416 | 298 |
417 // Pop four registers. Pops rightmost register first (from lower address). | 299 // Pop four registers. Pops rightmost register first (from lower address). |
418 void Pop(Register src1, | 300 void Pop(Register src1, Register src2, Register src3, Register src4) { |
419 Register src2, | |
420 Register src3, | |
421 Register src4, | |
422 Condition cond = al) { | |
423 ASSERT(!src1.is(src2)); | 301 ASSERT(!src1.is(src2)); |
424 ASSERT(!src2.is(src3)); | 302 ASSERT(!src2.is(src3)); |
425 ASSERT(!src1.is(src3)); | 303 ASSERT(!src1.is(src3)); |
426 ASSERT(!src1.is(src4)); | 304 ASSERT(!src1.is(src4)); |
427 ASSERT(!src2.is(src4)); | 305 ASSERT(!src2.is(src4)); |
428 ASSERT(!src3.is(src4)); | 306 ASSERT(!src3.is(src4)); |
429 if (src1.code() > src2.code()) { | 307 pop(src4); |
430 if (src2.code() > src3.code()) { | 308 pop(src3); |
431 if (src3.code() > src4.code()) { | 309 pop(src2); |
432 ldm(ia_w, | 310 pop(src1); |
433 sp, | |
434 src1.bit() | src2.bit() | src3.bit() | src4.bit(), | |
435 cond); | |
436 } else { | |
437 ldr(src4, MemOperand(sp, 4, PostIndex), cond); | |
438 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); | |
439 } | |
440 } else { | |
441 Pop(src3, src4, cond); | |
442 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); | |
443 } | |
444 } else { | |
445 Pop(src2, src3, src4, cond); | |
446 ldr(src1, MemOperand(sp, 4, PostIndex), cond); | |
447 } | |
448 } | 311 } |
449 | 312 |
450 // Push and pop the registers that can hold pointers, as defined by the | 313 // Push and pop the registers that can hold pointers, as defined by the |
451 // RegList constant kSafepointSavedRegisters. | 314 // RegList constant kSafepointSavedRegisters. |
452 void PushSafepointRegisters(); | 315 void PushSafepointRegisters(); |
453 void PopSafepointRegisters(); | 316 void PopSafepointRegisters(); |
454 void PushSafepointRegistersAndDoubles(); | 317 void PushSafepointRegistersAndDoubles(); |
455 void PopSafepointRegistersAndDoubles(); | 318 void PopSafepointRegistersAndDoubles(); |
456 // Store value in register src in the safepoint stack slot for | 319 // Store value in register src in the safepoint stack slot for |
457 // register dst. | 320 // register dst. |
458 void StoreToSafepointRegisterSlot(Register src, Register dst); | 321 void StoreToSafepointRegisterSlot(Register src, Register dst); |
459 void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst); | 322 void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst); |
460 // Load the value of the src register from its safepoint stack slot | 323 // Load the value of the src register from its safepoint stack slot |
461 // into register dst. | 324 // into register dst. |
462 void LoadFromSafepointRegisterSlot(Register dst, Register src); | 325 void LoadFromSafepointRegisterSlot(Register dst, Register src); |
463 | 326 |
464 // Load two consecutive registers with two consecutive memory locations. | 327 // Load two consecutive registers with two consecutive memory locations. |
465 void Ldrd(Register dst1, | 328 void Ldrd(Register dst1, |
466 Register dst2, | 329 Register dst2, |
467 const MemOperand& src, | 330 const MemOperand& src); |
468 Condition cond = al); | |
469 | 331 |
470 // Store two consecutive registers to two consecutive memory locations. | 332 // Store two consecutive registers to two consecutive memory locations. |
471 void Strd(Register src1, | 333 void Strd(Register src1, |
472 Register src2, | 334 Register src2, |
473 const MemOperand& dst, | 335 const MemOperand& dst); |
474 Condition cond = al); | |
475 | 336 |
476 // Clear specified FPSCR bits. | 337 void IsObjectJSStringType(Register object, |
477 void ClearFPSCRBits(const uint32_t bits_to_clear, | 338 Register scratch, |
478 const Register scratch, | 339 Label* fail); |
479 const Condition cond = al); | |
480 | 340 |
481 // Compare double values and move the result to the normal condition flags. | 341 #ifdef ENABLE_DEBUGGER_SUPPORT |
482 void VFPCompareAndSetFlags(const DwVfpRegister src1, | 342 // --------------------------------------------------------------------------- |
483 const DwVfpRegister src2, | 343 // Debugger Support |
484 const Condition cond = al); | |
485 void VFPCompareAndSetFlags(const DwVfpRegister src1, | |
486 const double src2, | |
487 const Condition cond = al); | |
488 | 344 |
489 // Compare double values and then load the fpscr flags to a register. | 345 void DebugBreak(); |
490 void VFPCompareAndLoadFlags(const DwVfpRegister src1, | 346 #endif |
491 const DwVfpRegister src2, | |
492 const Register fpscr_flags, | |
493 const Condition cond = al); | |
494 void VFPCompareAndLoadFlags(const DwVfpRegister src1, | |
495 const double src2, | |
496 const Register fpscr_flags, | |
497 const Condition cond = al); | |
498 | 347 |
499 void Vmov(const DwVfpRegister dst, | 348 // --------------------------------------------------------------------------- |
500 const double imm, | 349 // Support for marking unimplemented code generator function |
501 const Register scratch = no_reg, | 350 // Should be called with UNIMPLEMENTED_BREAK define below. |
502 const Condition cond = al); | 351 void UnimplementedBreak(const char *file, int line); |
| 352 #ifdef DEBUG |
| 353 #define UNIMPLEMENTED_BREAK() UnimplementedBreak(__FILE__, __LINE__) |
| 354 #else |
| 355 #define UNIMPLEMENTED_BREAK() UnimplementedBreak("", 0) |
| 356 #endif |
| 357 |
| 358 // --------------------------------------------------------------------------- |
| 359 // Activation frames |
| 360 |
| 361 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } |
| 362 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } |
| 363 |
| 364 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } |
| 365 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } |
| 366 |
| 367 // Expects object in r0 and returns map with validated enum cache |
| 368 // in r0. Assumes that any other register can be used as a scratch. |
| 369 void CheckEnumCache(Register null_value, Label* call_runtime); |
503 | 370 |
504 // Enter exit frame. | 371 // Enter exit frame. |
505 // stack_space - extra stack space, used for alignment before call to C. | 372 // stack_space - extra stack space, used for alignment before call to C. |
506 void EnterExitFrame(bool save_doubles, int stack_space = 0); | 373 void EnterExitFrame(bool save_doubles, int stack_space = 0, |
| 374 Register scratch = sh4_ip); |
507 | 375 |
508 // Leave the current exit frame. Expects the return value in r0. | 376 // Leave the current exit frame. Expects the return value in r0. |
509 // Expect the number of values, pushed prior to the exit frame, to | 377 // Expect the number of values, pushed prior to the exit frame, to |
510 // remove in a register (or no_reg, if there is nothing to remove). | 378 // remove in a register (or no_reg, if there is nothing to remove). |
511 void LeaveExitFrame(bool save_doubles, Register argument_count); | 379 void LeaveExitFrame(bool save_doubles, Register argument_count); |
512 | 380 |
513 // Get the actual activation frame alignment for target environment. | 381 void LoadContext(Register dst, int context_chain_length); |
514 static int ActivationFrameAlignment(); | |
515 | 382 |
516 void LoadContext(Register dst, int context_chain_length); | |
517 | 383 |
518 // Conditionally load the cached Array transitioned map of type | 384 // Conditionally load the cached Array transitioned map of type |
519 // transitioned_kind from the native context if the map in register | 385 // transitioned_kind from the native context if the map in register |
520 // map_in_out is the cached Array map in the native context of | 386 // map_in_out is the cached Array map in the native context of |
521 // expected_kind. | 387 // expected_kind. |
522 void LoadTransitionedArrayMapConditional( | 388 void LoadTransitionedArrayMapConditional( |
523 ElementsKind expected_kind, | 389 ElementsKind expected_kind, |
524 ElementsKind transitioned_kind, | 390 ElementsKind transitioned_kind, |
525 Register map_in_out, | 391 Register map_in_out, |
526 Register scratch, | 392 Register scratch, |
527 Label* no_map_match); | 393 Label* no_map_match); |
528 | 394 |
529 // Load the initial map for new Arrays from a JSFunction. | 395 // Load the initial map for new Arrays from a JSFunction. |
530 void LoadInitialArrayMap(Register function_in, | 396 void LoadInitialArrayMap(Register function_in, |
531 Register scratch, | 397 Register scratch, |
532 Register map_out, | 398 Register map_out, |
533 bool can_have_holes); | 399 bool can_have_holes); |
534 | 400 |
535 void LoadGlobalFunction(int index, Register function); | 401 void LoadGlobalFunction(int index, Register function); |
536 | 402 |
537 // Load the initial map from the global function. The registers | 403 // Load the initial map from the global function. The registers |
538 // function and map can be the same, function is then overwritten. | 404 // function and map can be the same, function is then overwritten. |
539 void LoadGlobalFunctionInitialMap(Register function, | 405 void LoadGlobalFunctionInitialMap(Register function, |
540 Register map, | 406 Register map, |
541 Register scratch); | 407 Register scratch); |
542 | 408 |
543 void InitializeRootRegister() { | 409 void InitializeRootRegister() { |
544 ExternalReference roots_array_start = | 410 ExternalReference roots_array_start = |
545 ExternalReference::roots_array_start(isolate()); | 411 ExternalReference::roots_array_start(isolate()); |
546 mov(kRootRegister, Operand(roots_array_start)); | 412 mov(roots, Operand(roots_array_start)); |
547 } | 413 } |
548 | 414 |
549 // --------------------------------------------------------------------------- | 415 // --------------------------------------------------------------------------- |
550 // JavaScript invokes | 416 // JavaScript invokes |
551 | 417 |
552 // Set up call kind marking in ecx. The method takes ecx as an | 418 // Set up call kind marking in ecx. The method takes ecx as an |
553 // explicit first parameter to make the code more readable at the | 419 // explicit first parameter to make the code more readable at the |
554 // call sites. | 420 // call sites. |
555 void SetCallKind(Register dst, CallKind kind); | 421 void SetCallKind(Register dst, CallKind kind); |
556 | 422 |
(...skipping 19 matching lines...) Expand all Loading... |
576 InvokeFlag flag, | 442 InvokeFlag flag, |
577 const CallWrapper& call_wrapper, | 443 const CallWrapper& call_wrapper, |
578 CallKind call_kind); | 444 CallKind call_kind); |
579 | 445 |
580 void InvokeFunction(Handle<JSFunction> function, | 446 void InvokeFunction(Handle<JSFunction> function, |
581 const ParameterCount& actual, | 447 const ParameterCount& actual, |
582 InvokeFlag flag, | 448 InvokeFlag flag, |
583 const CallWrapper& call_wrapper, | 449 const CallWrapper& call_wrapper, |
584 CallKind call_kind); | 450 CallKind call_kind); |
585 | 451 |
| 452 // Expression support |
| 453 void Set(Register dst, const Operand& x); |
| 454 void Set(const Operand& dst, const Operand& x); |
| 455 |
| 456 // Compare object type for heap object. |
| 457 // Incoming register is heap_object and outgoing register is map. |
| 458 void CmpObjectType(Register heap_object, InstanceType type, Register map); |
| 459 |
| 460 // Compare instance type for map. |
| 461 void CmpInstanceType(Register map, InstanceType type); |
| 462 |
| 463 // Check if the map of an object is equal to a specified map and branch to a |
| 464 // specified target if equal. Skip the smi check if not required (object is |
| 465 // known to be a heap object) |
| 466 void DispatchMap(Register obj, |
| 467 Register scratch, |
| 468 Handle<Map> map, |
| 469 Handle<Code> success, |
| 470 SmiCheckType smi_check_type); |
| 471 |
| 472 // Compare the object in a register to a value from the root list. |
| 473 // Uses the ip register as scratch. |
| 474 void CompareRoot(Register obj, Heap::RootListIndex index); |
| 475 |
| 476 // Check if a heap object's type is in the JSObject range, not including |
| 477 // JSFunction. The object's map will be loaded in the map register. |
| 478 // Any or all of the three registers may be the same. |
| 479 // The contents of the scratch register will always be overwritten. |
586 void IsObjectJSObjectType(Register heap_object, | 480 void IsObjectJSObjectType(Register heap_object, |
587 Register map, | 481 Register map, |
588 Register scratch, | 482 Register scratch, |
589 Label* fail); | 483 Label* fail); |
590 | 484 |
591 void IsInstanceJSObjectType(Register map, | 485 // The contents of the scratch register will be overwritten. |
592 Register scratch, | 486 void IsInstanceJSObjectType(Register map, Register scratch, Label* fail); |
593 Label* fail); | |
594 | 487 |
595 void IsObjectJSStringType(Register object, | 488 // --------------------------------------------------------------------------- |
596 Register scratch, | 489 // String utilities |
597 Label* fail); | |
598 | 490 |
599 #ifdef ENABLE_DEBUGGER_SUPPORT | 491 // Checks if both objects are sequential ASCII strings and jumps to label |
| 492 // if either is not. Assumes that neither object is a smi. |
| 493 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, |
| 494 Register object2, |
| 495 Register scratch1, |
| 496 Register scratch2, |
| 497 Label* failure); |
| 498 |
| 499 // Checks if both objects are sequential ASCII strings and jumps to label |
| 500 // if either is not. |
| 501 void JumpIfNotBothSequentialAsciiStrings(Register first, |
| 502 Register second, |
| 503 Register scratch1, |
| 504 Register scratch2, |
| 505 Label* not_flat_ascii_strings); |
| 506 |
| 507 // Checks if both instance types are sequential ASCII strings and jumps to |
| 508 // label if either is not. |
| 509 void JumpIfBothInstanceTypesAreNotSequentialAscii( |
| 510 Register first_object_instance_type, |
| 511 Register second_object_instance_type, |
| 512 Register scratch1, |
| 513 Register scratch2, |
| 514 Label* failure); |
| 515 |
| 516 // Check if instance type is sequential ASCII string and jump to label if |
| 517 // it is not. |
| 518 void JumpIfInstanceTypeIsNotSequentialAscii(Register type, |
| 519 Register scratch, |
| 520 Label* failure); |
| 521 |
| 522 // Abort execution if argument is not a number. Used in debug code. |
| 523 void AbortIfNotNumber(Register object); |
| 524 |
| 525 // Abort execution if argument is not a smi. Used in debug code. |
| 526 void AbortIfNotSmi(Register object); |
| 527 |
| 528 // Abort execution if argument is a smi. Used in debug code. |
| 529 void AbortIfSmi(Register object); |
| 530 |
| 531 // Abort execution if argument is a string. Used in debug code. |
| 532 void AbortIfNotString(Register object); |
| 533 |
| 534 // Abort execution if argument is not the root value with the given index. |
| 535 void AbortIfNotRootValue(Register src, |
| 536 Heap::RootListIndex root_value_index, |
| 537 const char* message); |
| 538 |
| 539 // Prints the value of the register to stdout. Use for debug only. |
| 540 void PrintRegisterValue(Register reg); |
| 541 |
600 // --------------------------------------------------------------------------- | 542 // --------------------------------------------------------------------------- |
601 // Debugger Support | 543 // Patching helpers. |
602 | 544 |
603 void DebugBreak(); | 545 // Get the location of a relocated constant (its address in the constant pool) |
604 #endif | 546 // from its load site. |
| 547 void GetRelocatedValueLocation(Register ldr_location, |
| 548 Register result); |
| 549 |
| 550 void LoadInstanceDescriptors(Register map, |
| 551 Register descriptors, |
| 552 Register scratch); |
| 553 void EnumLength(Register dst, Register map); |
| 554 void NumberOfOwnDescriptors(Register dst, Register map); |
| 555 |
| 556 template<typename Field> |
| 557 void DecodeField(Register reg) { |
| 558 static const int shift = Field::kShift; |
| 559 static const int mask = (Field::kMask >> shift) << kSmiTagSize; |
| 560 lsr(reg, reg, Operand(shift)); |
| 561 land(reg, reg, Operand(mask)); |
| 562 } |
| 563 |
| 564 |
| 565 |
| 566 // --------------------------------------------------------------------------- |
| 567 // HeapNumber utilities |
| 568 |
| 569 void JumpIfNotHeapNumber(Register object, |
| 570 Register heap_number_map, |
| 571 Register scratch, |
| 572 Label* on_not_heap_number); |
| 573 |
605 | 574 |
606 // --------------------------------------------------------------------------- | 575 // --------------------------------------------------------------------------- |
607 // Exception handling | 576 // Exception handling |
608 | 577 |
609 // Push a new try handler and link into try handler chain. | 578 // Push a new try handler and link into try handler chain. |
610 void PushTryHandler(StackHandler::Kind kind, int handler_index); | 579 void PushTryHandler(StackHandler::Kind kind, int handler_index); |
611 | 580 |
612 // Unlink the stack handler on top of the stack from the try handler chain. | 581 // Unlink the stack handler on top of the stack from the try handler chain. |
613 // Must preserve the result register. | 582 // Must preserve the result register. |
614 void PopTryHandler(); | 583 void PopTryHandler(); |
615 | 584 |
616 // Passes thrown value to the handler of top of the try handler chain. | 585 // Activate the top handler in the try hander chain. |
617 void Throw(Register value); | 586 void Throw(Register value); |
618 | 587 |
619 // Propagates an uncatchable exception to the top of the current JS stack's | 588 // Propagates an uncatchable exception to the top of the current JS stack's |
620 // handler chain. | 589 // handler chain. |
621 void ThrowUncatchable(Register value); | 590 void ThrowUncatchable(Register value); |
622 | 591 |
623 // --------------------------------------------------------------------------- | 592 // --------------------------------------------------------------------------- |
624 // Inline caching support | 593 // Inline caching support |
625 | 594 |
626 // Generate code for checking access rights - used for security checks | 595 // Generate code for checking access rights - used for security checks |
627 // on access to global objects across environments. The holder register | 596 // on access to global objects across environments. The holder register |
628 // is left untouched, whereas both scratch registers are clobbered. | 597 // is left untouched, whereas both scratch registers are clobbered. |
629 void CheckAccessGlobalProxy(Register holder_reg, | 598 void CheckAccessGlobalProxy(Register holder_reg, |
630 Register scratch, | 599 Register scratch, |
631 Label* miss); | 600 Label* miss); |
632 | 601 |
633 void GetNumberHash(Register t0, Register scratch); | 602 void GetNumberHash(Register t0, Register scratch); |
634 | 603 |
635 void LoadFromNumberDictionary(Label* miss, | 604 void LoadFromNumberDictionary(Label* miss, |
636 Register elements, | 605 Register elements, |
637 Register key, | 606 Register key, |
638 Register result, | 607 Register result, |
639 Register t0, | 608 Register t0, |
640 Register t1, | 609 Register t1, |
641 Register t2); | 610 Register t2); |
642 | 611 |
643 | |
644 inline void MarkCode(NopMarkerTypes type) { | |
645 nop(type); | |
646 } | |
647 | |
648 // Check if the given instruction is a 'type' marker. | |
649 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type)) | |
650 // These instructions are generated to mark special location in the code, | |
651 // like some special IC code. | |
652 static inline bool IsMarkedCode(Instr instr, int type) { | |
653 ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); | |
654 return IsNop(instr, type); | |
655 } | |
656 | |
657 | |
658 static inline int GetCodeMarker(Instr instr) { | |
659 int dst_reg_offset = 12; | |
660 int dst_mask = 0xf << dst_reg_offset; | |
661 int src_mask = 0xf; | |
662 int dst_reg = (instr & dst_mask) >> dst_reg_offset; | |
663 int src_reg = instr & src_mask; | |
664 uint32_t non_register_mask = ~(dst_mask | src_mask); | |
665 uint32_t mov_mask = al | 13 << 21; | |
666 | |
667 // Return <n> if we have a mov rn rn, else return -1. | |
668 int type = ((instr & non_register_mask) == mov_mask) && | |
669 (dst_reg == src_reg) && | |
670 (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER) | |
671 ? src_reg | |
672 : -1; | |
673 ASSERT((type == -1) || | |
674 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); | |
675 return type; | |
676 } | |
677 | |
678 | |
679 // --------------------------------------------------------------------------- | 612 // --------------------------------------------------------------------------- |
680 // Allocation support | 613 // Allocation support |
681 | 614 |
682 // Allocate an object in new space. The object_size is specified | 615 // Allocate an object in new space. If the new space is exhausted control |
683 // either in bytes or in words if the allocation flag SIZE_IN_WORDS | 616 // continues at the gc_required label. The allocated object is returned in |
684 // is passed. If the new space is exhausted control continues at the | 617 // result and end of the new object is returned in result_end. The register |
685 // gc_required label. The allocated object is returned in result. If | 618 // scratch can be passed as no_reg in which case an additional object |
686 // the flag tag_allocated_object is true the result is tagged as as | 619 // reference will be added to the reloc info. The returned pointers in result |
687 // a heap object. All registers are clobbered also when control | 620 // and result_end have not yet been tagged as heap objects. If |
688 // continues at the gc_required label. | 621 // result_contains_top_on_entry is true the content of result is known to be |
| 622 // the allocation top on entry (could be result_end from a previous call to |
| 623 // AllocateInNewSpace). If result_contains_top_on_entry is true scratch |
| 624 // should be no_reg as it is never used. |
689 void AllocateInNewSpace(int object_size, | 625 void AllocateInNewSpace(int object_size, |
690 Register result, | 626 Register result, |
691 Register scratch1, | 627 Register result_end, |
692 Register scratch2, | 628 Register scratch, |
693 Label* gc_required, | |
694 AllocationFlags flags); | |
695 void AllocateInNewSpace(Register object_size, | |
696 Register result, | |
697 Register scratch1, | |
698 Register scratch2, | |
699 Label* gc_required, | 629 Label* gc_required, |
700 AllocationFlags flags); | 630 AllocationFlags flags); |
701 | 631 |
| 632 void AllocateInNewSpace(int header_size, |
| 633 ScaleFactor element_size, |
| 634 Register element_count, |
| 635 Register result, |
| 636 Register result_end, |
| 637 Register scratch, |
| 638 Label* gc_required, |
| 639 AllocationFlags flags); |
| 640 |
| 641 void AllocateInNewSpace(Register object_size, |
| 642 Register result, |
| 643 Register result_end, |
| 644 Register scratch, |
| 645 Label* gc_required, |
| 646 AllocationFlags flags); |
| 647 |
702 // Undo allocation in new space. The object passed and objects allocated after | 648 // Undo allocation in new space. The object passed and objects allocated after |
703 // it will no longer be allocated. The caller must make sure that no pointers | 649 // it will no longer be allocated. The caller must make sure that no pointers |
704 // are left to the object(s) no longer allocated as they would be invalid when | 650 // are left to the object(s) no longer allocated as they would be invalid when |
705 // allocation is undone. | 651 // allocation is undone. |
706 void UndoAllocationInNewSpace(Register object, Register scratch); | 652 void UndoAllocationInNewSpace(Register object, Register scratch); |
707 | 653 |
708 | 654 |
| 655 // Allocate a heap number in new space with undefined value. The |
| 656 // register scratch2 can be passed as no_reg; the others must be |
| 657 // valid registers. Returns tagged pointer in result register, or |
| 658 // jumps to gc_required if new space is full. |
| 659 void AllocateHeapNumber(Register result, |
| 660 Register scratch1, |
| 661 Register scratch2, |
| 662 Register heap_number_map, |
| 663 Label* gc_required); |
| 664 |
| 665 // Allocate a sequential string. All the header fields of the string object |
| 666 // are initialized. |
709 void AllocateTwoByteString(Register result, | 667 void AllocateTwoByteString(Register result, |
710 Register length, | 668 Register length, |
711 Register scratch1, | 669 Register scratch1, |
712 Register scratch2, | 670 Register scratch2, |
713 Register scratch3, | 671 Register scratch3, |
714 Label* gc_required); | 672 Label* gc_required); |
715 void AllocateAsciiString(Register result, | 673 void AllocateAsciiString(Register result, |
716 Register length, | 674 Register length, |
717 Register scratch1, | 675 Register scratch1, |
718 Register scratch2, | 676 Register scratch2, |
719 Register scratch3, | 677 Register scratch3, |
720 Label* gc_required); | 678 Label* gc_required); |
| 679 void AllocateAsciiString(Register result, |
| 680 int length, |
| 681 Register scratch1, |
| 682 Register scratch2, |
| 683 Label* gc_required); |
| 684 |
| 685 // Allocate a raw cons string object. Only the map field of the result is |
| 686 // initialized. |
721 void AllocateTwoByteConsString(Register result, | 687 void AllocateTwoByteConsString(Register result, |
722 Register length, | 688 Register length, |
723 Register scratch1, | 689 Register scratch1, |
724 Register scratch2, | 690 Register scratch2, |
725 Label* gc_required); | 691 Label* gc_required); |
| 692 |
726 void AllocateAsciiConsString(Register result, | 693 void AllocateAsciiConsString(Register result, |
727 Register length, | 694 Register length, |
728 Register scratch1, | 695 Register scratch1, |
729 Register scratch2, | 696 Register scratch2, |
730 Label* gc_required); | 697 Label* gc_required); |
731 void AllocateTwoByteSlicedString(Register result, | 698 void AllocateTwoByteSlicedString(Register result, |
732 Register length, | 699 Register length, |
733 Register scratch1, | 700 Register scratch1, |
734 Register scratch2, | 701 Register scratch2, |
735 Label* gc_required); | 702 Label* gc_required); |
736 void AllocateAsciiSlicedString(Register result, | 703 void AllocateAsciiSlicedString(Register result, |
737 Register length, | 704 Register length, |
738 Register scratch1, | 705 Register scratch1, |
739 Register scratch2, | 706 Register scratch2, |
740 Label* gc_required); | 707 Label* gc_required); |
741 | 708 |
742 // Allocates a heap number or jumps to the gc_required label if the young | |
743 // space is full and a scavenge is needed. All registers are clobbered also | |
744 // when control continues at the gc_required label. | |
745 void AllocateHeapNumber(Register result, | |
746 Register scratch1, | |
747 Register scratch2, | |
748 Register heap_number_map, | |
749 Label* gc_required, | |
750 TaggingMode tagging_mode = TAG_RESULT); | |
751 void AllocateHeapNumberWithValue(Register result, | |
752 DwVfpRegister value, | |
753 Register scratch1, | |
754 Register scratch2, | |
755 Register heap_number_map, | |
756 Label* gc_required); | |
757 | |
758 // Copies a fixed number of fields of heap objects from src to dst. | 709 // Copies a fixed number of fields of heap objects from src to dst. |
759 void CopyFields(Register dst, Register src, RegList temps, int field_count); | 710 void CopyFields(Register dst, Register src, RegList temps, int field_count); |
760 | 711 |
761 // Copies a number of bytes from src to dst. All registers are clobbered. On | 712 // Copy memory, byte-by-byte, from source to destination. Not optimized for |
762 // exit src and dst will point to the place just after where the last byte was | 713 // long or aligned copies. |
763 // read or written and length will be zero. | 714 // The contents of index and scratch are destroyed. |
764 void CopyBytes(Register src, | 715 void CopyBytes(Register source, |
765 Register dst, | 716 Register destination, |
766 Register length, | 717 Register length, |
767 Register scratch); | 718 Register scratch); |
768 | 719 |
769 // Initialize fields with filler values. Fields starting at |start_offset| | 720 // Initialize fields with filler values. Fields starting at |start_offset| |
770 // not including end_offset are overwritten with the value in |filler|. At | 721 // not including end_offset are overwritten with the value in |filler|. At |
771 // the end the loop, |start_offset| takes the value of |end_offset|. | 722 // the end the loop, |start_offset| takes the value of |end_offset|. |
772 void InitializeFieldsWithFiller(Register start_offset, | 723 void InitializeFieldsWithFiller(Register start_offset, |
773 Register end_offset, | 724 Register end_offset, |
774 Register filler); | 725 Register filler); |
775 | 726 |
(...skipping 14 matching lines...) Expand all Loading... |
790 // Compare object type for heap object. heap_object contains a non-Smi | 741 // Compare object type for heap object. heap_object contains a non-Smi |
791 // whose object type should be compared with the given type. This both | 742 // whose object type should be compared with the given type. This both |
792 // sets the flags and leaves the object type in the type_reg register. | 743 // sets the flags and leaves the object type in the type_reg register. |
793 // It leaves the map in the map register (unless the type_reg and map register | 744 // It leaves the map in the map register (unless the type_reg and map register |
794 // are the same register). It leaves the heap object in the heap_object | 745 // are the same register). It leaves the heap object in the heap_object |
795 // register unless the heap_object register is the same register as one of the | 746 // register unless the heap_object register is the same register as one of the |
796 // other registers. | 747 // other registers. |
797 void CompareObjectType(Register heap_object, | 748 void CompareObjectType(Register heap_object, |
798 Register map, | 749 Register map, |
799 Register type_reg, | 750 Register type_reg, |
800 InstanceType type); | 751 InstanceType type, |
| 752 Condition cond); |
801 | 753 |
802 // Compare instance type in a map. map contains a valid map object whose | 754 // Compare instance type in a map. map contains a valid map object whose |
803 // object type should be compared with the given type. This both | 755 // object type should be compared with the given type. This both |
804 // sets the flags and leaves the object type in the type_reg register. | 756 // sets the flags and leaves the object type in the type_reg register. It |
| 757 // leaves the heap object in the heap_object register unless the heap_object |
| 758 // register is the same register as type_reg. |
805 void CompareInstanceType(Register map, | 759 void CompareInstanceType(Register map, |
806 Register type_reg, | 760 Register type_reg, |
807 InstanceType type); | 761 InstanceType type, |
808 | 762 Condition cond); |
809 | 763 |
810 // Check if a map for a JSObject indicates that the object has fast elements. | 764 // Check if a map for a JSObject indicates that the object has fast elements. |
811 // Jump to the specified label if it does not. | 765 // Jump to the specified label if it does not. |
812 void CheckFastElements(Register map, | 766 void CheckFastElements(Register map, |
813 Register scratch, | 767 Register scratch, |
814 Label* fail); | 768 Label* fail); |
815 | 769 |
816 // Check if a map for a JSObject indicates that the object can have both smi | 770 // Check if a map for a JSObject indicates that the object can have both smi |
817 // and HeapObject elements. Jump to the specified label if it does not. | 771 // and HeapObject elements. Jump to the specified label if it does not. |
818 void CheckFastObjectElements(Register map, | 772 void CheckFastObjectElements(Register map, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 CompareMapMode mode = REQUIRE_EXACT_MAP); | 823 CompareMapMode mode = REQUIRE_EXACT_MAP); |
870 | 824 |
871 | 825 |
872 void CheckMap(Register obj, | 826 void CheckMap(Register obj, |
873 Register scratch, | 827 Register scratch, |
874 Heap::RootListIndex index, | 828 Heap::RootListIndex index, |
875 Label* fail, | 829 Label* fail, |
876 SmiCheckType smi_check_type); | 830 SmiCheckType smi_check_type); |
877 | 831 |
878 | 832 |
879 // Check if the map of an object is equal to a specified map and branch to a | |
880 // specified target if equal. Skip the smi check if not required (object is | |
881 // known to be a heap object) | |
882 void DispatchMap(Register obj, | |
883 Register scratch, | |
884 Handle<Map> map, | |
885 Handle<Code> success, | |
886 SmiCheckType smi_check_type); | |
887 | |
888 | |
889 // Compare the object in a register to a value from the root list. | |
890 // Uses the ip register as scratch. | |
891 void CompareRoot(Register obj, Heap::RootListIndex index); | |
892 | |
893 | 833 |
894 // Load and check the instance type of an object for being a string. | 834 // Load and check the instance type of an object for being a string. |
895 // Loads the type into the second argument register. | 835 // Loads the type into the second argument register. |
896 // Returns a condition that will be enabled if the object was a string. | 836 // Returns a condition that will be enabled if the object was a string. |
897 Condition IsObjectStringType(Register obj, | 837 Condition IsObjectStringType(Register obj, |
898 Register type) { | 838 Register type) { |
899 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); | 839 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); |
900 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); | 840 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); |
901 tst(type, Operand(kIsNotStringMask)); | 841 tst(type, Operand(kIsNotStringMask)); |
902 ASSERT_EQ(0, kStringTag); | 842 ASSERT_EQ(0, kStringTag); |
903 return eq; | 843 return eq; |
904 } | 844 } |
905 | 845 |
906 | 846 |
907 // Generates code for reporting that an illegal operation has | 847 // Generates code for reporting that an illegal operation has |
908 // occurred. | 848 // occurred. |
909 void IllegalOperation(int num_arguments); | 849 void IllegalOperation(int num_arguments); |
910 | 850 |
911 // Picks out an array index from the hash field. | 851 // Picks out an array index from the hash field. |
912 // Register use: | 852 // Register use: |
913 // hash - holds the index's hash. Clobbered. | 853 // hash - holds the index's hash. Clobbered. |
914 // index - holds the overwritten index on exit. | 854 // index - holds the overwritten index on exit. |
915 void IndexFromHash(Register hash, Register index); | 855 void IndexFromHash(Register hash, Register index); |
916 | 856 |
917 // Get the number of least significant bits from a register | 857 // Get the number of least significant bits from a register |
918 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); | 858 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); |
919 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); | 859 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); |
920 | 860 |
921 // Uses VFP instructions to Convert a Smi to a double. | |
922 void IntegerToDoubleConversionWithVFP3(Register inReg, | |
923 Register outHighReg, | |
924 Register outLowReg); | |
925 | |
926 // Load the value of a number object into a VFP double register. If the object | |
927 // is not a number a jump to the label not_number is performed and the VFP | |
928 // double register is unchanged. | |
929 void ObjectToDoubleVFPRegister( | |
930 Register object, | |
931 DwVfpRegister value, | |
932 Register scratch1, | |
933 Register scratch2, | |
934 Register heap_number_map, | |
935 SwVfpRegister scratch3, | |
936 Label* not_number, | |
937 ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS); | |
938 | |
939 // Load the value of a smi object into a VFP double register. The register | |
940 // scratch1 can be the same register as smi in which case smi will hold the | |
941 // untagged value afterwards. | |
942 void SmiToDoubleVFPRegister(Register smi, | |
943 DwVfpRegister value, | |
944 Register scratch1, | |
945 SwVfpRegister scratch2); | |
946 | |
947 // Convert the HeapNumber pointed to by source to a 32bits signed integer | 861 // Convert the HeapNumber pointed to by source to a 32bits signed integer |
948 // dest. If the HeapNumber does not fit into a 32bits signed integer branch | 862 // dest. If the HeapNumber does not fit into a 32bits signed integer branch |
949 // to not_int32 label. If VFP3 is available double_scratch is used but not | 863 // to not_int32 label. If VFP3 is available double_scratch is used but not |
950 // scratch2. | 864 // scratch2. TODO: SH4, use fp reg. |
951 void ConvertToInt32(Register source, | 865 void ConvertToInt32(Register source, |
952 Register dest, | 866 Register dest, |
953 Register scratch, | 867 Register scratch, |
954 Register scratch2, | 868 Register scratch2, |
955 DwVfpRegister double_scratch, | 869 DwVfpRegister double_scratch, |
956 Label *not_int32); | 870 Label *not_int32); |
957 | 871 |
958 // Truncates a double using a specific rounding mode, and writes the value | 872 // Load the value of a smi object into a FPU double register. The register |
959 // to the result register. | 873 // scratch1 can be the same register as smi in which case smi will hold the |
| 874 // untagged value afterwards. |
| 875 void SmiToDoubleFPURegister(Register smi, |
| 876 DwVfpRegister value, |
| 877 Register scratch1); |
| 878 |
| 879 |
| 880 |
| 881 // Truncates a double using a specific rounding mode. |
960 // Clears the z flag (ne condition) if an overflow occurs. | 882 // Clears the z flag (ne condition) if an overflow occurs. |
961 // If kCheckForInexactConversion is passed, the z flag is also cleared if the | 883 // If exact_conversion is true, the z flag is also cleared if the conversion |
962 // conversion was inexact, i.e. if the double value could not be converted | 884 // was inexact, ie. if the double value could not be converted exactly |
963 // exactly to a 32-bit integer. | 885 // to a 32bit integer. |
964 void EmitVFPTruncate(VFPRoundingMode rounding_mode, | 886 void EmitFPUTruncate(FPURoundingMode rounding_mode, |
965 Register result, | 887 Register result, |
966 DwVfpRegister double_input, | 888 DwVfpRegister double_input, |
967 Register scratch, | 889 Register scratch, |
968 DwVfpRegister double_scratch, | |
969 CheckForInexactConversion check | 890 CheckForInexactConversion check |
970 = kDontCheckForInexactConversion); | 891 = kDontCheckForInexactConversion); |
971 | 892 |
972 // Helper for EmitECMATruncate. | 893 // Helper for EmitECMATruncate. |
973 // This will truncate a floating-point value outside of the signed 32bit | 894 // This will truncate a floating-point value outside of the singed 32bit |
974 // integer range to a 32bit signed integer. | 895 // integer range to a 32bit signed integer. |
975 // Expects the double value loaded in input_high and input_low. | 896 // Expects the double value loaded in input_high and input_low. |
976 // Exits with the answer in 'result'. | 897 // Exits with the answer in 'result'. |
977 // Note that this code does not work for values in the 32bit range! | 898 // Note that this code does not work for values in the 32bit range! |
978 void EmitOutOfInt32RangeTruncate(Register result, | 899 void EmitOutOfInt32RangeTruncate(Register result, |
979 Register input_high, | 900 Register input_high, |
980 Register input_low, | 901 Register input_low, |
981 Register scratch); | 902 Register scratch); |
982 | 903 |
983 // Performs a truncating conversion of a floating point number as used by | 904 // Performs a truncating conversion of a floating point number as used by |
(...skipping 12 matching lines...) Expand all Loading... |
996 // the source is clobbered. Source and zeros can also be the same in which | 917 // the source is clobbered. Source and zeros can also be the same in which |
997 // case scratch should be a different register. | 918 // case scratch should be a different register. |
998 void CountLeadingZeros(Register zeros, | 919 void CountLeadingZeros(Register zeros, |
999 Register source, | 920 Register source, |
1000 Register scratch); | 921 Register scratch); |
1001 | 922 |
1002 // --------------------------------------------------------------------------- | 923 // --------------------------------------------------------------------------- |
1003 // Runtime calls | 924 // Runtime calls |
1004 | 925 |
1005 // Call a code stub. | 926 // Call a code stub. |
1006 void CallStub(CodeStub* stub, Condition cond = al); | 927 void CallStub(CodeStub* stub); |
1007 | 928 |
1008 // Call a code stub. | 929 // Call a code stub. |
1009 void TailCallStub(CodeStub* stub, Condition cond = al); | 930 void TailCallStub(CodeStub* stub); |
1010 | 931 |
1011 // Call a runtime routine. | 932 // Call a runtime routine. |
1012 void CallRuntime(const Runtime::Function* f, int num_arguments); | 933 void CallRuntime(const Runtime::Function* f, int num_arguments); |
1013 void CallRuntimeSaveDoubles(Runtime::FunctionId id); | 934 void CallRuntimeSaveDoubles(Runtime::FunctionId id); |
1014 | 935 |
1015 // Convenience function: Same as above, but takes the fid instead. | 936 // Convenience function: Same as above, but takes the fid instead. |
1016 void CallRuntime(Runtime::FunctionId fid, int num_arguments); | 937 void CallRuntime(Runtime::FunctionId fid, int num_arguments); |
1017 | 938 |
1018 // Convenience function: call an external reference. | 939 // Convenience function: call an external reference. |
1019 void CallExternalReference(const ExternalReference& ext, | 940 void CallExternalReference(const ExternalReference& ext, |
(...skipping 23 matching lines...) Expand all Loading... |
1043 // Some compilers/platforms require the stack to be aligned when calling | 964 // Some compilers/platforms require the stack to be aligned when calling |
1044 // C++ code. | 965 // C++ code. |
1045 // Needs a scratch register to do some arithmetic. This register will be | 966 // Needs a scratch register to do some arithmetic. This register will be |
1046 // trashed. | 967 // trashed. |
1047 void PrepareCallCFunction(int num_reg_arguments, | 968 void PrepareCallCFunction(int num_reg_arguments, |
1048 int num_double_registers, | 969 int num_double_registers, |
1049 Register scratch); | 970 Register scratch); |
1050 void PrepareCallCFunction(int num_reg_arguments, | 971 void PrepareCallCFunction(int num_reg_arguments, |
1051 Register scratch); | 972 Register scratch); |
1052 | 973 |
1053 // There are two ways of passing double arguments on ARM, depending on | |
1054 // whether soft or hard floating point ABI is used. These functions | |
1055 // abstract parameter passing for the three different ways we call | |
1056 // C functions from generated code. | |
1057 void SetCallCDoubleArguments(DoubleRegister dreg); | |
1058 void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2); | |
1059 void SetCallCDoubleArguments(DoubleRegister dreg, Register reg); | |
1060 | |
1061 // Calls a C function and cleans up the space for arguments allocated | 974 // Calls a C function and cleans up the space for arguments allocated |
1062 // by PrepareCallCFunction. The called function is not allowed to trigger a | 975 // by PrepareCallCFunction. The called function is not allowed to trigger a |
1063 // garbage collection, since that might move the code and invalidate the | 976 // garbage collection, since that might move the code and invalidate the |
1064 // return address (unless this is somehow accounted for by the called | 977 // return address (unless this is somehow accounted for by the called |
1065 // function). | 978 // function). |
1066 void CallCFunction(ExternalReference function, int num_arguments); | 979 void CallCFunction(ExternalReference function, int num_reg_arguments, |
| 980 int num_double_arguments = 0); |
1067 void CallCFunction(Register function, int num_arguments); | 981 void CallCFunction(Register function, int num_arguments); |
1068 void CallCFunction(ExternalReference function, | |
1069 int num_reg_arguments, | |
1070 int num_double_arguments); | |
1071 void CallCFunction(Register function, | |
1072 int num_reg_arguments, | |
1073 int num_double_arguments); | |
1074 | |
1075 void GetCFunctionDoubleResult(const DoubleRegister dst); | |
1076 | 982 |
1077 // Calls an API function. Allocates HandleScope, extracts returned value | 983 // Calls an API function. Allocates HandleScope, extracts returned value |
1078 // from handle and propagates exceptions. Restores context. stack_space | 984 // from handle and propagates exceptions. Restores context. stack_space |
1079 // - space to be unwound on exit (includes the call JS arguments space and | 985 // - space to be unwound on exit (includes the call JS arguments space and |
1080 // the additional space allocated for the fast call). | 986 // the additional space allocated for the fast call). |
1081 void CallApiFunctionAndReturn(ExternalReference function, int stack_space); | 987 void CallApiFunctionAndReturn(ExternalReference function, int stack_space); |
1082 | 988 |
1083 // Jump to a runtime routine. | 989 // Jump to a runtime routine. |
1084 void JumpToExternalReference(const ExternalReference& builtin); | 990 void JumpToExternalReference(const ExternalReference& builtin); |
1085 | 991 |
1086 // Invoke specified builtin JavaScript function. Adds an entry to | 992 // Invoke specified builtin JavaScript function. Adds an entry to |
1087 // the unresolved list if the name does not resolve. | 993 // the unresolved list if the name does not resolve. |
1088 void InvokeBuiltin(Builtins::JavaScript id, | 994 void InvokeBuiltin(Builtins::JavaScript id, |
1089 InvokeFlag flag, | 995 InvokeFlag flag, |
1090 const CallWrapper& call_wrapper = NullCallWrapper()); | 996 const CallWrapper& call_wrapper = NullCallWrapper()); |
1091 | 997 |
1092 // Store the code object for the given builtin in the target register and | 998 // Store the code object for the given builtin in the target register and |
1093 // setup the function in r1. | 999 // setup the function in r1. |
1094 void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 1000 void GetBuiltinEntry(Register target, Builtins::JavaScript id); |
1095 | 1001 |
1096 // Store the function for the given builtin in the target register. | 1002 // Store the function for the given builtin in the target register. |
1097 void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 1003 void GetBuiltinFunction(Register target, Builtins::JavaScript id); |
1098 | 1004 |
| 1005 // --------------------------------------------------------------------------- |
| 1006 // Utilities |
| 1007 |
| 1008 void Ret(Condition cond = al); |
| 1009 |
| 1010 void Drop(int stack_elements); |
| 1011 void Ret(int drop); |
| 1012 |
| 1013 void Jump(Register target); |
| 1014 void Jump(intptr_t target, RelocInfo::Mode rmode); |
| 1015 void Jump(Handle<Code> code, RelocInfo::Mode rmode); |
| 1016 void Call(Label* target) { call(target); } |
| 1017 void Call(Handle<Code> code, |
| 1018 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, |
| 1019 TypeFeedbackId ast_id = TypeFeedbackId::None()); |
| 1020 |
| 1021 // Emit call to the code we are currently generating. |
| 1022 void CallSelf() { |
| 1023 UNIMPLEMENTED(); |
| 1024 } |
| 1025 |
| 1026 void Move(Register dst, Handle<Object> value); |
| 1027 // Move if the registers are not identical. |
| 1028 void Move(Register target, Register source); |
| 1029 |
| 1030 void Usat(Register dst, int satpos, Register src); |
| 1031 void Ubfx(Register dst, Register src, int lsb, int width); |
| 1032 void Sbfx(Register dst, Register src, int lsb, int width); |
| 1033 void Bfc(Register dst, int lsb, int width); |
| 1034 // scratch can be the same register as src (in which case it is trashed), but |
| 1035 // not the same as dst. |
| 1036 void Bfi(Register dst, |
| 1037 Register src, |
| 1038 Register scratch, |
| 1039 int lsb, |
| 1040 int width); |
| 1041 |
1099 Handle<Object> CodeObject() { | 1042 Handle<Object> CodeObject() { |
1100 ASSERT(!code_object_.is_null()); | 1043 ASSERT(!code_object_.is_null()); |
1101 return code_object_; | 1044 return code_object_; |
1102 } | 1045 } |
1103 | 1046 |
| 1047 // Record code generator line mapping through comments. |
| 1048 // Use -code_comments to enable. |
| 1049 MacroAssembler* RecordFunctionLine(const char* function, int line); |
1104 | 1050 |
1105 // --------------------------------------------------------------------------- | 1051 // --------------------------------------------------------------------------- |
1106 // StatsCounter support | 1052 // StatsCounter support |
1107 | 1053 |
1108 void SetCounter(StatsCounter* counter, int value, | 1054 void SetCounter(StatsCounter* counter, int value, |
1109 Register scratch1, Register scratch2); | 1055 Register scratch1, Register scratch2); |
1110 void IncrementCounter(StatsCounter* counter, int value, | 1056 void IncrementCounter(StatsCounter* counter, int value, |
1111 Register scratch1, Register scratch2); | 1057 Register scratch1, Register scratch2); |
1112 void DecrementCounter(StatsCounter* counter, int value, | 1058 void DecrementCounter(StatsCounter* counter, int value, |
1113 Register scratch1, Register scratch2); | 1059 Register scratch1, Register scratch2); |
1114 | 1060 |
1115 | 1061 |
1116 // --------------------------------------------------------------------------- | 1062 // --------------------------------------------------------------------------- |
1117 // Debugging | 1063 // Debugging |
1118 | 1064 |
1119 // Calls Abort(msg) if the condition cond is not satisfied. | 1065 // Calls Abort(msg) if the condition cond is not satisfied. |
1120 // Use --debug_code to enable. | 1066 // Use --debug_code to enable. |
1121 void Assert(Condition cond, const char* msg); | 1067 void Assert(Condition cond, const char* msg); |
1122 void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); | 1068 |
| 1069 void AssertRegisterIsRoot(Register reg, Register scratch, |
| 1070 Heap::RootListIndex index); |
1123 void AssertFastElements(Register elements); | 1071 void AssertFastElements(Register elements); |
1124 | 1072 |
1125 // Like Assert(), but always enabled. | 1073 // Like Assert(), but always enabled. |
1126 void Check(Condition cond, const char* msg); | 1074 void Check(Condition cond, const char* msg); |
1127 | 1075 |
1128 // Print a message to stdout and abort execution. | 1076 // Print a message to stdout and abort execution. |
1129 void Abort(const char* msg); | 1077 void Abort(const char* msg); |
1130 | 1078 |
| 1079 // Print an object to stdout. |
| 1080 void DebugPrint(Register obj); |
| 1081 |
| 1082 // Check that the stack is aligned. |
| 1083 void CheckStackAlignment(); |
| 1084 |
1131 // Verify restrictions about code generated in stubs. | 1085 // Verify restrictions about code generated in stubs. |
1132 void set_generating_stub(bool value) { generating_stub_ = value; } | 1086 void set_generating_stub(bool value) { generating_stub_ = value; } |
1133 bool generating_stub() { return generating_stub_; } | 1087 bool generating_stub() { return generating_stub_; } |
1134 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } | 1088 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } |
1135 bool allow_stub_calls() { return allow_stub_calls_; } | 1089 bool allow_stub_calls() { return allow_stub_calls_; } |
1136 void set_has_frame(bool value) { has_frame_ = value; } | 1090 void set_has_frame(bool value) { has_frame_ = value; } |
1137 bool has_frame() { return has_frame_; } | 1091 bool has_frame() { return has_frame_; } |
1138 inline bool AllowThisStubCall(CodeStub* stub); | 1092 inline bool AllowThisStubCall(CodeStub* stub); |
1139 | 1093 |
1140 // EABI variant for double arguments in use. | |
1141 bool use_eabi_hardfloat() { | |
1142 #if USE_EABI_HARDFLOAT | |
1143 return true; | |
1144 #else | |
1145 return false; | |
1146 #endif | |
1147 } | |
1148 | 1094 |
1149 // --------------------------------------------------------------------------- | 1095 // --------------------------------------------------------------------------- |
1150 // Number utilities | 1096 // Number utilities |
1151 | 1097 |
1152 // Check whether the value of reg is a power of two and not zero. If not | 1098 // Check whether the value of reg is a power of two and not zero. If not |
1153 // control continues at the label not_power_of_two. If reg is a power of two | 1099 // control continues at the label not_power_of_two. If reg is a power of two |
1154 // the register scratch contains the value of (reg - 1) when control falls | 1100 // the register scratch contains the value of (reg - 1) when control falls |
1155 // through. | 1101 // through. |
1156 void JumpIfNotPowerOfTwoOrZero(Register reg, | 1102 void JumpIfNotPowerOfTwoOrZero(Register reg, |
1157 Register scratch, | 1103 Register scratch, |
1158 Label* not_power_of_two_or_zero); | 1104 Label* not_power_of_two_or_zero); |
1159 // Check whether the value of reg is a power of two and not zero. | 1105 // Check whether the value of reg is a power of two and not zero. |
1160 // Control falls through if it is, with scratch containing the mask | 1106 // Control falls through if it is, with scratch containing the mask |
1161 // value (reg - 1). | 1107 // value (reg - 1). |
1162 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is | 1108 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is |
1163 // zero or negative, or jumps to the 'not_power_of_two' label if the value is | 1109 // zero or negative, or jumps to the 'not_power_of_two' label if the value is |
1164 // strictly positive but not a power of two. | 1110 // strictly positive but not a power of two. |
1165 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, | 1111 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, |
1166 Register scratch, | 1112 Register scratch, |
1167 Label* zero_and_neg, | 1113 Label* zero_and_neg, |
1168 Label* not_power_of_two); | 1114 Label* not_power_of_two); |
1169 | 1115 |
1170 // --------------------------------------------------------------------------- | 1116 // --------------------------------------------------------------------------- |
1171 // Smi utilities | 1117 // Smi utilities |
1172 | 1118 |
1173 void SmiTag(Register reg, SBit s = LeaveCC) { | 1119 void SmiTag(Register reg) { |
1174 add(reg, reg, Operand(reg), s); | 1120 add(reg, reg, reg); |
1175 } | 1121 } |
1176 void SmiTag(Register dst, Register src, SBit s = LeaveCC) { | 1122 void SmiTag(Register dst, Register src) { |
1177 add(dst, src, Operand(src), s); | 1123 add(dst, src, src); |
1178 } | 1124 } |
1179 | 1125 |
1180 // Try to convert int32 to smi. If the value is to large, preserve | 1126 // Try to convert int32 to smi. If the value is to large, preserve |
1181 // the original value and jump to not_a_smi. Destroys scratch and | 1127 // the original value and jump to not_a_smi. Destroys scratch and |
1182 // sets flags. | 1128 // sets flags. |
1183 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { | 1129 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { |
1184 mov(scratch, reg); | 1130 addv(scratch, reg, reg); |
1185 SmiTag(scratch, SetCC); | 1131 b(t, not_a_smi); |
1186 b(vs, not_a_smi); | |
1187 mov(reg, scratch); | 1132 mov(reg, scratch); |
1188 } | 1133 } |
1189 | 1134 |
1190 void SmiUntag(Register reg, SBit s = LeaveCC) { | 1135 void SmiUntag(Register reg) { |
1191 mov(reg, Operand(reg, ASR, kSmiTagSize), s); | 1136 asr(reg, reg, Operand(kSmiTagSize)); |
1192 } | 1137 } |
1193 void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { | 1138 void SmiUntag(Register dst, Register src) { |
1194 mov(dst, Operand(src, ASR, kSmiTagSize), s); | 1139 asr(dst, src, Operand(kSmiTagSize)); |
1195 } | 1140 } |
1196 | 1141 |
1197 // Untag the source value into destination and jump if source is a smi. | 1142 // Untag the source value into destination and jump if source is a smi. |
1198 // Souce and destination can be the same register. | 1143 // Souce and destination can be the same register. |
1199 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); | 1144 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); |
1200 | 1145 |
1201 // Untag the source value into destination and jump if source is not a smi. | 1146 // Untag the source value into destination and jump if source is not a smi. |
1202 // Souce and destination can be the same register. | 1147 // Souce and destination can be the same register. |
1203 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); | 1148 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); |
1204 | 1149 |
1205 // Jump the register contains a smi. | 1150 // Jump the register contains a smi. |
1206 inline void JumpIfSmi(Register value, Label* smi_label) { | 1151 inline void JumpIfSmi(Register value, Label* smi_label, |
| 1152 Label::Distance distance = Label::kFar) { |
1207 tst(value, Operand(kSmiTagMask)); | 1153 tst(value, Operand(kSmiTagMask)); |
1208 b(eq, smi_label); | 1154 if (distance == Label::kFar) |
| 1155 bt(smi_label); |
| 1156 else |
| 1157 bt_near(smi_label); |
1209 } | 1158 } |
1210 // Jump if either of the registers contain a non-smi. | 1159 // Jump if either of the registers contain a non-smi. |
1211 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { | 1160 inline void JumpIfNotSmi(Register value, Label* not_smi_label, |
| 1161 Label::Distance distance = Label::kFar) { |
1212 tst(value, Operand(kSmiTagMask)); | 1162 tst(value, Operand(kSmiTagMask)); |
1213 b(ne, not_smi_label); | 1163 if (distance == Label::kFar) |
1214 } | 1164 bf(not_smi_label); |
1215 // Jump if either of the registers contain a non-smi. | 1165 else |
1216 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); | 1166 bf_near(not_smi_label); |
1217 // Jump if either of the registers contain a smi. | |
1218 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); | |
1219 | |
1220 // Abort execution if argument is a smi, enabled via --debug-code. | |
1221 void AssertNotSmi(Register object); | |
1222 void AssertSmi(Register object); | |
1223 | |
1224 // Abort execution if argument is a string, enabled via --debug-code. | |
1225 void AssertString(Register object); | |
1226 | |
1227 // Abort execution if argument is not the root value with the given index, | |
1228 // enabled via --debug-code. | |
1229 void AssertRootValue(Register src, | |
1230 Heap::RootListIndex root_value_index, | |
1231 const char* message); | |
1232 | |
1233 // --------------------------------------------------------------------------- | |
1234 // HeapNumber utilities | |
1235 | |
1236 void JumpIfNotHeapNumber(Register object, | |
1237 Register heap_number_map, | |
1238 Register scratch, | |
1239 Label* on_not_heap_number); | |
1240 | |
1241 // --------------------------------------------------------------------------- | |
1242 // String utilities | |
1243 | |
1244 // Checks if both objects are sequential ASCII strings and jumps to label | |
1245 // if either is not. Assumes that neither object is a smi. | |
1246 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, | |
1247 Register object2, | |
1248 Register scratch1, | |
1249 Register scratch2, | |
1250 Label* failure); | |
1251 | |
1252 // Checks if both objects are sequential ASCII strings and jumps to label | |
1253 // if either is not. | |
1254 void JumpIfNotBothSequentialAsciiStrings(Register first, | |
1255 Register second, | |
1256 Register scratch1, | |
1257 Register scratch2, | |
1258 Label* not_flat_ascii_strings); | |
1259 | |
1260 // Checks if both instance types are sequential ASCII strings and jumps to | |
1261 // label if either is not. | |
1262 void JumpIfBothInstanceTypesAreNotSequentialAscii( | |
1263 Register first_object_instance_type, | |
1264 Register second_object_instance_type, | |
1265 Register scratch1, | |
1266 Register scratch2, | |
1267 Label* failure); | |
1268 | |
1269 // Check if instance type is sequential ASCII string and jump to label if | |
1270 // it is not. | |
1271 void JumpIfInstanceTypeIsNotSequentialAscii(Register type, | |
1272 Register scratch, | |
1273 Label* failure); | |
1274 | |
1275 | |
1276 // --------------------------------------------------------------------------- | |
1277 // Patching helpers. | |
1278 | |
1279 // Get the location of a relocated constant (its address in the constant pool) | |
1280 // from its load site. | |
1281 void GetRelocatedValueLocation(Register ldr_location, | |
1282 Register result); | |
1283 | |
1284 | |
1285 void ClampUint8(Register output_reg, Register input_reg); | |
1286 | |
1287 void ClampDoubleToUint8(Register result_reg, | |
1288 DoubleRegister input_reg, | |
1289 DoubleRegister temp_double_reg); | |
1290 | |
1291 | |
1292 void LoadInstanceDescriptors(Register map, Register descriptors); | |
1293 void EnumLength(Register dst, Register map); | |
1294 void NumberOfOwnDescriptors(Register dst, Register map); | |
1295 | |
1296 template<typename Field> | |
1297 void DecodeField(Register reg) { | |
1298 static const int shift = Field::kShift; | |
1299 static const int mask = (Field::kMask >> shift) << kSmiTagSize; | |
1300 mov(reg, Operand(reg, LSR, shift)); | |
1301 and_(reg, reg, Operand(mask)); | |
1302 } | 1167 } |
1303 | 1168 |
| 1169 // Jump if either of the registers contain a non-smi. |
| 1170 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi, |
| 1171 Label::Distance distance = Label::kFar); |
| 1172 // Jump if either of the registers contain a smi. |
| 1173 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi, |
| 1174 Label::Distance distance = Label::kFar); |
1304 // Activation support. | 1175 // Activation support. |
1305 void EnterFrame(StackFrame::Type type); | 1176 void EnterFrame(StackFrame::Type type); |
1306 void LeaveFrame(StackFrame::Type type); | 1177 void LeaveFrame(StackFrame::Type type); |
1307 | 1178 |
1308 // Expects object in r0 and returns map with validated enum cache | |
1309 // in r0. Assumes that any other register can be used as a scratch. | |
1310 void CheckEnumCache(Register null_value, Label* call_runtime); | |
1311 | 1179 |
1312 private: | 1180 private: |
1313 void CallCFunctionHelper(Register function, | 1181 void CallCFunctionHelper(Register function, |
1314 int num_reg_arguments, | 1182 int num_reg_arguments, |
1315 int num_double_arguments); | 1183 int num_double_arguments); |
1316 | 1184 |
1317 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); | |
1318 | 1185 |
1319 // Helper functions for generating invokes. | 1186 // Helper functions for generating invokes. |
1320 void InvokePrologue(const ParameterCount& expected, | 1187 void InvokePrologue(const ParameterCount& expected, |
1321 const ParameterCount& actual, | 1188 const ParameterCount& actual, |
1322 Handle<Code> code_constant, | 1189 Handle<Code> code_constant, |
1323 Register code_reg, | 1190 Register code_reg, |
1324 Label* done, | 1191 Label* done, |
1325 bool* definitely_mismatches, | 1192 bool* definitely_mismatches, |
1326 InvokeFlag flag, | 1193 InvokeFlag flag, |
1327 const CallWrapper& call_wrapper, | 1194 const CallWrapper& call_wrapper, |
1328 CallKind call_kind); | 1195 CallKind call_kind); |
1329 | 1196 |
| 1197 void LeaveExitFrameEpilogue(); |
| 1198 |
1330 void InitializeNewString(Register string, | 1199 void InitializeNewString(Register string, |
1331 Register length, | 1200 Register length, |
1332 Heap::RootListIndex map_index, | 1201 Heap::RootListIndex map_index, |
1333 Register scratch1, | 1202 Register scratch1, |
1334 Register scratch2); | 1203 Register scratch2); |
1335 | 1204 |
1336 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. | |
1337 void InNewSpace(Register object, | |
1338 Register scratch, | |
1339 Condition cond, // eq for new space, ne otherwise. | |
1340 Label* branch); | |
1341 | |
1342 // Helper for finding the mark bits for an address. Afterwards, the | 1205 // Helper for finding the mark bits for an address. Afterwards, the |
1343 // bitmap register points at the word with the mark bits and the mask | 1206 // bitmap register points at the word with the mark bits and the mask |
1344 // the position of the first bit. Leaves addr_reg unchanged. | 1207 // the position of the first bit. Leaves addr_reg unchanged. |
1345 inline void GetMarkBits(Register addr_reg, | 1208 inline void GetMarkBits(Register addr_reg, |
1346 Register bitmap_reg, | 1209 Register bitmap_reg, |
1347 Register mask_reg); | 1210 Register mask_reg); |
1348 | 1211 |
| 1212 // Allocation support helpers. |
| 1213 void LoadAllocationTopHelper(Register result, |
| 1214 Register scratch, |
| 1215 AllocationFlags flags); |
| 1216 void UpdateAllocationTopHelper(Register result_end, Register scratch); |
| 1217 |
| 1218 // Helper for PopHandleScope. Allowed to perform a GC and returns |
| 1219 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and |
| 1220 // possibly returns a failure object indicating an allocation failure. |
| 1221 MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved, |
| 1222 Register scratch, |
| 1223 bool gc_allowed); |
| 1224 |
1349 // Helper for throwing exceptions. Compute a handler address and jump to | 1225 // Helper for throwing exceptions. Compute a handler address and jump to |
1350 // it. See the implementation for register usage. | 1226 // it. See the implementation for register usage. |
1351 void JumpToHandlerEntry(); | 1227 void JumpToHandlerEntry(); |
1352 | 1228 |
1353 // Compute memory operands for safepoint stack slots. | 1229 // Compute memory operands for safepoint stack slots. |
1354 static int SafepointRegisterStackIndex(int reg_code); | 1230 static int SafepointRegisterStackIndex(int reg_code); |
1355 MemOperand SafepointRegisterSlot(Register reg); | 1231 MemOperand SafepointRegisterSlot(Register reg); |
1356 MemOperand SafepointRegistersAndDoublesSlot(Register reg); | 1232 MemOperand SafepointRegistersAndDoublesSlot(Register reg); |
1357 | 1233 |
1358 bool generating_stub_; | 1234 bool generating_stub_; |
(...skipping 14 matching lines...) Expand all Loading... |
1373 // relocation information. If any of these constraints are violated it causes | 1249 // relocation information. If any of these constraints are violated it causes |
1374 // an assertion to fail. | 1250 // an assertion to fail. |
1375 class CodePatcher { | 1251 class CodePatcher { |
1376 public: | 1252 public: |
1377 CodePatcher(byte* address, int instructions); | 1253 CodePatcher(byte* address, int instructions); |
1378 virtual ~CodePatcher(); | 1254 virtual ~CodePatcher(); |
1379 | 1255 |
1380 // Macro assembler to emit code. | 1256 // Macro assembler to emit code. |
1381 MacroAssembler* masm() { return &masm_; } | 1257 MacroAssembler* masm() { return &masm_; } |
1382 | 1258 |
1383 // Emit an instruction directly. | |
1384 void Emit(Instr instr); | |
1385 | |
1386 // Emit an address directly. | |
1387 void Emit(Address addr); | |
1388 | |
1389 // Emit the condition part of an instruction leaving the rest of the current | 1259 // Emit the condition part of an instruction leaving the rest of the current |
1390 // instruction unchanged. | 1260 // instruction unchanged. |
1391 void EmitCondition(Condition cond); | 1261 void EmitCondition(Condition cond); |
1392 | 1262 |
1393 private: | 1263 private: |
1394 byte* address_; // The address of the code being patched. | 1264 byte* address_; // The address of the code being patched. |
1395 int instructions_; // Number of instructions of the expected patch size. | 1265 int instructions_; // Number of instructions of the expected patch size. |
1396 int size_; // Number of bytes of the expected patch size. | 1266 int size_; // Number of bytes of the expected patch size. |
1397 MacroAssembler masm_; // Macro assembler used to generate the code. | 1267 MacroAssembler masm_; // Macro assembler used to generate the code. |
1398 }; | 1268 }; |
1399 | 1269 |
1400 | 1270 |
1401 // ----------------------------------------------------------------------------- | 1271 // ----------------------------------------------------------------------------- |
1402 // Static helper functions. | 1272 // Static helper functions. |
1403 | 1273 |
1404 inline MemOperand ContextOperand(Register context, int index) { | 1274 inline MemOperand ContextOperand(Register context, int index) { |
1405 return MemOperand(context, Context::SlotOffset(index)); | 1275 return MemOperand(context, Context::SlotOffset(index)); |
1406 } | 1276 } |
1407 | 1277 |
1408 | 1278 |
1409 inline MemOperand GlobalObjectOperand() { | 1279 inline MemOperand GlobalObjectOperand() { |
1410 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX); | 1280 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX); |
1411 } | 1281 } |
1412 | 1282 |
1413 | 1283 |
1414 #ifdef GENERATED_CODE_COVERAGE | 1284 #ifdef DEBUG |
1415 #define CODE_COVERAGE_STRINGIFY(x) #x | 1285 # define ACCESS_MASM(masm) masm->RecordFunctionLine(__FUNCTION__, __LINE__)-> |
1416 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) | |
1417 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | |
1418 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | |
1419 #else | 1286 #else |
1420 #define ACCESS_MASM(masm) masm-> | 1287 # define ACCESS_MASM(masm) masm-> |
1421 #endif | 1288 #endif |
1422 | 1289 |
1423 | 1290 |
1424 } } // namespace v8::internal | 1291 } } // namespace v8::internal |
1425 | 1292 |
1426 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 1293 #endif // V8_SH4_MACRO_ASSEMBLER_SH4_H_ |
OLD | NEW |