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