Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: src/ppc/macro-assembler-ppc.h

Issue 422063005: Contribution of PowerPC port. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: re-upload - catch up to 8/19 level Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 //
3 // Copyright IBM Corp. 2012, 2013. All rights reserved.
4 //
2 // Use of this source code is governed by a BSD-style license that can be 5 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 6 // found in the LICENSE file.
4 7
5 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ 8 #ifndef V8_PPC_MACRO_ASSEMBLER_PPC_H_
6 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ 9 #define V8_PPC_MACRO_ASSEMBLER_PPC_H_
7 10
8 #include "src/assembler.h" 11 #include "src/assembler.h"
9 #include "src/frames.h" 12 #include "src/frames.h"
10 #include "src/globals.h" 13 #include "src/globals.h"
11 14
12 namespace v8 { 15 namespace v8 {
13 namespace internal { 16 namespace internal {
14 17
15 // ---------------------------------------------------------------------------- 18 // ----------------------------------------------------------------------------
16 // Static helper functions 19 // Static helper functions
17 20
18 // Generate a MemOperand for loading a field from an object. 21 // Generate a MemOperand for loading a field from an object.
19 inline MemOperand FieldMemOperand(Register object, int offset) { 22 inline MemOperand FieldMemOperand(Register object, int offset) {
20 return MemOperand(object, offset - kHeapObjectTag); 23 return MemOperand(object, offset - kHeapObjectTag);
21 } 24 }
22 25
23 26
24 // Give alias names to registers
25 const Register cp = { kRegister_r7_Code }; // JavaScript context pointer.
26 const Register pp = { kRegister_r8_Code }; // Constant pool pointer.
27 const Register kRootRegister = { kRegister_r10_Code }; // Roots array pointer.
28
29 // Flags used for AllocateHeapNumber 27 // Flags used for AllocateHeapNumber
30 enum TaggingMode { 28 enum TaggingMode {
31 // Tag the result. 29 // Tag the result.
32 TAG_RESULT, 30 TAG_RESULT,
33 // Don't tag 31 // Don't tag
34 DONT_TAG_RESULT 32 DONT_TAG_RESULT
35 }; 33 };
36 34
37 35
38 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 36 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
39 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 37 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
40 enum PointersToHereCheck { 38 enum PointersToHereCheck {
41 kPointersToHereMaybeInteresting, 39 kPointersToHereMaybeInteresting,
42 kPointersToHereAreAlwaysInteresting 40 kPointersToHereAreAlwaysInteresting
43 }; 41 };
44 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; 42 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
45 43
46 44
47 Register GetRegisterThatIsNotOneOf(Register reg1, 45 Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2 = no_reg,
48 Register reg2 = no_reg,
49 Register reg3 = no_reg, 46 Register reg3 = no_reg,
50 Register reg4 = no_reg, 47 Register reg4 = no_reg,
51 Register reg5 = no_reg, 48 Register reg5 = no_reg,
52 Register reg6 = no_reg); 49 Register reg6 = no_reg);
53 50
54 51
55 #ifdef DEBUG 52 #ifdef DEBUG
56 bool AreAliased(Register reg1, 53 bool AreAliased(Register reg1, Register reg2, Register reg3 = no_reg,
57 Register reg2, 54 Register reg4 = no_reg, Register reg5 = no_reg,
58 Register reg3 = no_reg, 55 Register reg6 = no_reg, Register reg7 = no_reg,
59 Register reg4 = no_reg,
60 Register reg5 = no_reg,
61 Register reg6 = no_reg,
62 Register reg7 = no_reg,
63 Register reg8 = no_reg); 56 Register reg8 = no_reg);
64 #endif 57 #endif
65 58
59 // These exist to provide portability between 32 and 64bit
60 #if V8_TARGET_ARCH_PPC64
61 #define LoadPU ldu
62 #define LoadPX ldx
63 #define LoadPUX ldux
64 #define StorePU stdu
65 #define StorePX stdx
66 #define StorePUX stdux
67 #define ShiftLeftImm sldi
68 #define ShiftRightImm srdi
69 #define ClearLeftImm clrldi
70 #define ClearRightImm clrrdi
71 #define ShiftRightArithImm sradi
72 #define ShiftLeft sld
73 #define ShiftRight srd
74 #define ShiftRightArith srad
75 #define Mul mulld
76 #define Div divd
77 #else
78 #define LoadPU lwzu
79 #define LoadPX lwzx
80 #define LoadPUX lwzux
81 #define StorePU stwu
82 #define StorePX stwx
83 #define StorePUX stwux
84 #define ShiftLeftImm slwi
85 #define ShiftRightImm srwi
86 #define ClearLeftImm clrlwi
87 #define ClearRightImm clrrwi
88 #define ShiftRightArithImm srawi
89 #define ShiftLeft slw
90 #define ShiftRight srw
91 #define ShiftRightArith sraw
92 #define Mul mullw
93 #define Div divw
94 #endif
66 95
67 enum TargetAddressStorageMode {
68 CAN_INLINE_TARGET_ADDRESS,
69 NEVER_INLINE_TARGET_ADDRESS
70 };
71 96
72 // MacroAssembler implements a collection of frequently used macros. 97 // MacroAssembler implements a collection of frequently used macros.
73 class MacroAssembler: public Assembler { 98 class MacroAssembler : public Assembler {
74 public: 99 public:
75 // The isolate parameter can be NULL if the macro assembler should 100 // The isolate parameter can be NULL if the macro assembler should
76 // not use isolate-dependent functionality. In this case, it's the 101 // not use isolate-dependent functionality. In this case, it's the
77 // responsibility of the caller to never invoke such function on the 102 // responsibility of the caller to never invoke such function on the
78 // macro assembler. 103 // macro assembler.
79 MacroAssembler(Isolate* isolate, void* buffer, int size); 104 MacroAssembler(Isolate* isolate, void* buffer, int size);
80 105
81 106
82 // Returns the size of a call in instructions. Note, the value returned is 107 // Returns the size of a call in instructions. Note, the value returned is
83 // only valid as long as no entries are added to the constant pool between 108 // only valid as long as no entries are added to the constant pool between
84 // checking the call size and emitting the actual call. 109 // checking the call size and emitting the actual call.
85 static int CallSize(Register target, Condition cond = al); 110 static int CallSize(Register target, Condition cond = al);
86 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al); 111 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
87 int CallStubSize(CodeStub* stub, 112 static int CallSizeNotPredictableCodeSize(Address target,
88 TypeFeedbackId ast_id = TypeFeedbackId::None(),
89 Condition cond = al);
90 static int CallSizeNotPredictableCodeSize(Isolate* isolate,
91 Address target,
92 RelocInfo::Mode rmode, 113 RelocInfo::Mode rmode,
93 Condition cond = al); 114 Condition cond = al);
94 115
95 // Jump, Call, and Ret pseudo instructions implementing inter-working. 116 // Jump, Call, and Ret pseudo instructions implementing inter-working.
96 void Jump(Register target, Condition cond = al); 117 void Jump(Register target, Condition cond = al);
97 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al); 118 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al,
119 CRegister cr = cr7);
98 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); 120 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
99 void Call(Register target, Condition cond = al); 121 void Call(Register target, Condition cond = al);
100 void Call(Address target, RelocInfo::Mode rmode, 122 void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
101 Condition cond = al,
102 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
103 int CallSize(Handle<Code> code, 123 int CallSize(Handle<Code> code,
104 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 124 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
105 TypeFeedbackId ast_id = TypeFeedbackId::None(), 125 TypeFeedbackId ast_id = TypeFeedbackId::None(),
106 Condition cond = al); 126 Condition cond = al);
107 void Call(Handle<Code> code, 127 void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
108 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
109 TypeFeedbackId ast_id = TypeFeedbackId::None(), 128 TypeFeedbackId ast_id = TypeFeedbackId::None(),
110 Condition cond = al, 129 Condition cond = al);
111 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
112 void Ret(Condition cond = al); 130 void Ret(Condition cond = al);
113 131
114 // Emit code to discard a non-negative number of pointer-sized elements 132 // Emit code to discard a non-negative number of pointer-sized elements
115 // from the stack, clobbering only the sp register. 133 // from the stack, clobbering only the sp register.
116 void Drop(int count, Condition cond = al); 134 void Drop(int count, Condition cond = al);
117 135
118 void Ret(int drop, Condition cond = al); 136 void Ret(int drop, Condition cond = al);
119 137
120 // Swap two registers. If the scratch register is omitted then a slightly 138 void Call(Label* target);
121 // less efficient form using xor instead of mov is emitted.
122 void Swap(Register reg1,
123 Register reg2,
124 Register scratch = no_reg,
125 Condition cond = al);
126 139
127 void Mls(Register dst, Register src1, Register src2, Register srcA, 140 // Emit call to the code we are currently generating.
128 Condition cond = al); 141 void CallSelf() {
129 void And(Register dst, Register src1, const Operand& src2, 142 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
130 Condition cond = al); 143 Call(self, RelocInfo::CODE_TARGET);
131 void Ubfx(Register dst, Register src, int lsb, int width, 144 }
132 Condition cond = al);
133 void Sbfx(Register dst, Register src, int lsb, int width,
134 Condition cond = al);
135 // The scratch register is not used for ARMv7.
136 // scratch can be the same register as src (in which case it is trashed), but
137 // not the same as dst.
138 void Bfi(Register dst,
139 Register src,
140 Register scratch,
141 int lsb,
142 int width,
143 Condition cond = al);
144 void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al);
145 void Usat(Register dst, int satpos, const Operand& src,
146 Condition cond = al);
147
148 void Call(Label* target);
149 void Push(Register src) { push(src); }
150 void Pop(Register dst) { pop(dst); }
151 145
152 // Register move. May do nothing if the registers are identical. 146 // Register move. May do nothing if the registers are identical.
153 void Move(Register dst, Handle<Object> value); 147 void Move(Register dst, Handle<Object> value);
154 void Move(Register dst, Register src, Condition cond = al); 148 void Move(Register dst, Register src, Condition cond = al);
155 void Move(Register dst, const Operand& src, SBit sbit = LeaveCC, 149 void Move(DoubleRegister dst, DoubleRegister src);
156 Condition cond = al) {
157 if (!src.is_reg() || !src.rm().is(dst) || sbit != LeaveCC) {
158 mov(dst, src, sbit, cond);
159 }
160 }
161 void Move(DwVfpRegister dst, DwVfpRegister src);
162 150
163 void Load(Register dst, const MemOperand& src, Representation r); 151 void MultiPush(RegList regs);
164 void Store(Register src, const MemOperand& dst, Representation r); 152 void MultiPop(RegList regs);
165 153
166 // Load an object from the root table. 154 // Load an object from the root table.
167 void LoadRoot(Register destination, 155 void LoadRoot(Register destination, Heap::RootListIndex index,
168 Heap::RootListIndex index,
169 Condition cond = al); 156 Condition cond = al);
170 // Store an object to the root table. 157 // Store an object to the root table.
171 void StoreRoot(Register source, 158 void StoreRoot(Register source, Heap::RootListIndex index,
172 Heap::RootListIndex index,
173 Condition cond = al); 159 Condition cond = al);
174 160
175 // --------------------------------------------------------------------------- 161 // ---------------------------------------------------------------------------
176 // GC Support 162 // GC Support
177 163
178 void IncrementalMarkingRecordWriteHelper(Register object, 164 void IncrementalMarkingRecordWriteHelper(Register object, Register value,
179 Register value,
180 Register address); 165 Register address);
181 166
182 enum RememberedSetFinalAction { 167 enum RememberedSetFinalAction { kReturnAtEnd, kFallThroughAtEnd };
183 kReturnAtEnd,
184 kFallThroughAtEnd
185 };
186 168
187 // Record in the remembered set the fact that we have a pointer to new space 169 // Record in the remembered set the fact that we have a pointer to new space
188 // at the address pointed to by the addr register. Only works if addr is not 170 // at the address pointed to by the addr register. Only works if addr is not
189 // in new space. 171 // in new space.
190 void RememberedSetHelper(Register object, // Used for debug code. 172 void RememberedSetHelper(Register object, // Used for debug code.
191 Register addr, 173 Register addr, Register scratch,
192 Register scratch,
193 SaveFPRegsMode save_fp, 174 SaveFPRegsMode save_fp,
194 RememberedSetFinalAction and_then); 175 RememberedSetFinalAction and_then);
195 176
196 void CheckPageFlag(Register object, 177 void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
197 Register scratch,
198 int mask,
199 Condition cc,
200 Label* condition_met); 178 Label* condition_met);
201 179
202 void CheckMapDeprecated(Handle<Map> map, 180 void CheckMapDeprecated(Handle<Map> map, Register scratch,
203 Register scratch,
204 Label* if_deprecated); 181 Label* if_deprecated);
205 182
206 // Check if object is in new space. Jumps if the object is not in new space. 183 // Check if object is in new space. Jumps if the object is not in new space.
207 // The register scratch can be object itself, but scratch will be clobbered. 184 // The register scratch can be object itself, but scratch will be clobbered.
208 void JumpIfNotInNewSpace(Register object, 185 void JumpIfNotInNewSpace(Register object, Register scratch, Label* branch) {
209 Register scratch,
210 Label* branch) {
211 InNewSpace(object, scratch, ne, branch); 186 InNewSpace(object, scratch, ne, branch);
212 } 187 }
213 188
214 // Check if object is in new space. Jumps if the object is in new space. 189 // Check if object is in new space. Jumps if the object is in new space.
215 // The register scratch can be object itself, but it will be clobbered. 190 // The register scratch can be object itself, but it will be clobbered.
216 void JumpIfInNewSpace(Register object, 191 void JumpIfInNewSpace(Register object, Register scratch, Label* branch) {
217 Register scratch,
218 Label* branch) {
219 InNewSpace(object, scratch, eq, branch); 192 InNewSpace(object, scratch, eq, branch);
220 } 193 }
221 194
222 // Check if an object has a given incremental marking color. 195 // Check if an object has a given incremental marking color.
223 void HasColor(Register object, 196 void HasColor(Register object, Register scratch0, Register scratch1,
224 Register scratch0, 197 Label* has_color, int first_bit, int second_bit);
225 Register scratch1,
226 Label* has_color,
227 int first_bit,
228 int second_bit);
229 198
230 void JumpIfBlack(Register object, 199 void JumpIfBlack(Register object, Register scratch0, Register scratch1,
231 Register scratch0,
232 Register scratch1,
233 Label* on_black); 200 Label* on_black);
234 201
235 // Checks the color of an object. If the object is already grey or black 202 // Checks the color of an object. If the object is already grey or black
236 // then we just fall through, since it is already live. If it is white and 203 // then we just fall through, since it is already live. If it is white and
237 // we can determine that it doesn't need to be scanned, then we just mark it 204 // we can determine that it doesn't need to be scanned, then we just mark it
238 // black and fall through. For the rest we jump to the label so the 205 // black and fall through. For the rest we jump to the label so the
239 // incremental marker can fix its assumptions. 206 // incremental marker can fix its assumptions.
240 void EnsureNotWhite(Register object, 207 void EnsureNotWhite(Register object, Register scratch1, Register scratch2,
241 Register scratch1, 208 Register scratch3, Label* object_is_white_and_not_data);
242 Register scratch2,
243 Register scratch3,
244 Label* object_is_white_and_not_data);
245 209
246 // Detects conservatively whether an object is data-only, i.e. it does need to 210 // Detects conservatively whether an object is data-only, i.e. it does need to
247 // be scanned by the garbage collector. 211 // be scanned by the garbage collector.
248 void JumpIfDataObject(Register value, 212 void JumpIfDataObject(Register value, Register scratch,
249 Register scratch,
250 Label* not_data_object); 213 Label* not_data_object);
251 214
252 // Notify the garbage collector that we wrote a pointer into an object. 215 // Notify the garbage collector that we wrote a pointer into an object.
253 // |object| is the object being stored into, |value| is the object being 216 // |object| is the object being stored into, |value| is the object being
254 // stored. value and scratch registers are clobbered by the operation. 217 // stored. value and scratch registers are clobbered by the operation.
255 // The offset is the offset from the start of the object, not the offset from 218 // The offset is the offset from the start of the object, not the offset from
256 // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 219 // the tagged HeapObject pointer. For use with FieldOperand(reg, off).
257 void RecordWriteField( 220 void RecordWriteField(
258 Register object, 221 Register object, int offset, Register value, Register scratch,
259 int offset, 222 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
260 Register value,
261 Register scratch,
262 LinkRegisterStatus lr_status,
263 SaveFPRegsMode save_fp,
264 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 223 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
265 SmiCheck smi_check = INLINE_SMI_CHECK, 224 SmiCheck smi_check = INLINE_SMI_CHECK,
266 PointersToHereCheck pointers_to_here_check_for_value = 225 PointersToHereCheck pointers_to_here_check_for_value =
267 kPointersToHereMaybeInteresting); 226 kPointersToHereMaybeInteresting);
268 227
269 // As above, but the offset has the tag presubtracted. For use with 228 // As above, but the offset has the tag presubtracted. For use with
270 // MemOperand(reg, off). 229 // MemOperand(reg, off).
271 inline void RecordWriteContextSlot( 230 inline void RecordWriteContextSlot(
272 Register context, 231 Register context, int offset, Register value, Register scratch,
273 int offset, 232 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
274 Register value,
275 Register scratch,
276 LinkRegisterStatus lr_status,
277 SaveFPRegsMode save_fp,
278 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 233 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
279 SmiCheck smi_check = INLINE_SMI_CHECK, 234 SmiCheck smi_check = INLINE_SMI_CHECK,
280 PointersToHereCheck pointers_to_here_check_for_value = 235 PointersToHereCheck pointers_to_here_check_for_value =
281 kPointersToHereMaybeInteresting) { 236 kPointersToHereMaybeInteresting) {
282 RecordWriteField(context, 237 RecordWriteField(context, offset + kHeapObjectTag, value, scratch,
283 offset + kHeapObjectTag, 238 lr_status, save_fp, remembered_set_action, smi_check,
284 value,
285 scratch,
286 lr_status,
287 save_fp,
288 remembered_set_action,
289 smi_check,
290 pointers_to_here_check_for_value); 239 pointers_to_here_check_for_value);
291 } 240 }
292 241
293 void RecordWriteForMap( 242 void RecordWriteForMap(Register object, Register map, Register dst,
294 Register object, 243 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp);
295 Register map,
296 Register dst,
297 LinkRegisterStatus lr_status,
298 SaveFPRegsMode save_fp);
299 244
300 // For a given |object| notify the garbage collector that the slot |address| 245 // For a given |object| notify the garbage collector that the slot |address|
301 // has been written. |value| is the object being stored. The value and 246 // has been written. |value| is the object being stored. The value and
302 // address registers are clobbered by the operation. 247 // address registers are clobbered by the operation.
303 void RecordWrite( 248 void RecordWrite(
304 Register object, 249 Register object, Register address, Register value,
305 Register address, 250 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
306 Register value,
307 LinkRegisterStatus lr_status,
308 SaveFPRegsMode save_fp,
309 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 251 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
310 SmiCheck smi_check = INLINE_SMI_CHECK, 252 SmiCheck smi_check = INLINE_SMI_CHECK,
311 PointersToHereCheck pointers_to_here_check_for_value = 253 PointersToHereCheck pointers_to_here_check_for_value =
312 kPointersToHereMaybeInteresting); 254 kPointersToHereMaybeInteresting);
313 255
256 void Push(Register src) { push(src); }
257
314 // Push a handle. 258 // Push a handle.
315 void Push(Handle<Object> handle); 259 void Push(Handle<Object> handle);
316 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); } 260 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
317 261
318 // Push two registers. Pushes leftmost register first (to highest address). 262 // Push two registers. Pushes leftmost register first (to highest address).
319 void Push(Register src1, Register src2, Condition cond = al) { 263 void Push(Register src1, Register src2) {
320 DCHECK(!src1.is(src2)); 264 StorePU(src1, MemOperand(sp, -kPointerSize));
321 if (src1.code() > src2.code()) { 265 StorePU(src2, MemOperand(sp, -kPointerSize));
322 stm(db_w, sp, src1.bit() | src2.bit(), cond);
323 } else {
324 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
325 str(src2, MemOperand(sp, 4, NegPreIndex), cond);
326 }
327 } 266 }
328 267
329 // Push three registers. Pushes leftmost register first (to highest address). 268 // Push three registers. Pushes leftmost register first (to highest address).
330 void Push(Register src1, Register src2, Register src3, Condition cond = al) { 269 void Push(Register src1, Register src2, Register src3) {
331 DCHECK(!src1.is(src2)); 270 StorePU(src1, MemOperand(sp, -kPointerSize));
332 DCHECK(!src2.is(src3)); 271 StorePU(src2, MemOperand(sp, -kPointerSize));
333 DCHECK(!src1.is(src3)); 272 StorePU(src3, MemOperand(sp, -kPointerSize));
334 if (src1.code() > src2.code()) {
335 if (src2.code() > src3.code()) {
336 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
337 } else {
338 stm(db_w, sp, src1.bit() | src2.bit(), cond);
339 str(src3, MemOperand(sp, 4, NegPreIndex), cond);
340 }
341 } else {
342 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
343 Push(src2, src3, cond);
344 }
345 } 273 }
346 274
347 // Push four registers. Pushes leftmost register first (to highest address). 275 // Push four registers. Pushes leftmost register first (to highest address).
348 void Push(Register src1, 276 void Push(Register src1, Register src2, Register src3, Register src4) {
349 Register src2, 277 StorePU(src1, MemOperand(sp, -kPointerSize));
350 Register src3, 278 StorePU(src2, MemOperand(sp, -kPointerSize));
351 Register src4, 279 StorePU(src3, MemOperand(sp, -kPointerSize));
352 Condition cond = al) { 280 StorePU(src4, MemOperand(sp, -kPointerSize));
353 DCHECK(!src1.is(src2));
354 DCHECK(!src2.is(src3));
355 DCHECK(!src1.is(src3));
356 DCHECK(!src1.is(src4));
357 DCHECK(!src2.is(src4));
358 DCHECK(!src3.is(src4));
359 if (src1.code() > src2.code()) {
360 if (src2.code() > src3.code()) {
361 if (src3.code() > src4.code()) {
362 stm(db_w,
363 sp,
364 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
365 cond);
366 } else {
367 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
368 str(src4, MemOperand(sp, 4, NegPreIndex), cond);
369 }
370 } else {
371 stm(db_w, sp, src1.bit() | src2.bit(), cond);
372 Push(src3, src4, cond);
373 }
374 } else {
375 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
376 Push(src2, src3, src4, cond);
377 }
378 } 281 }
379 282
283 // Push five registers. Pushes leftmost register first (to highest address).
284 void Push(Register src1, Register src2, Register src3, Register src4,
285 Register src5) {
286 StorePU(src1, MemOperand(sp, -kPointerSize));
287 StorePU(src2, MemOperand(sp, -kPointerSize));
288 StorePU(src3, MemOperand(sp, -kPointerSize));
289 StorePU(src4, MemOperand(sp, -kPointerSize));
290 StorePU(src5, MemOperand(sp, -kPointerSize));
291 }
292
293 void Pop(Register dst) { pop(dst); }
294
380 // Pop two registers. Pops rightmost register first (from lower address). 295 // Pop two registers. Pops rightmost register first (from lower address).
381 void Pop(Register src1, Register src2, Condition cond = al) { 296 void Pop(Register src1, Register src2) {
382 DCHECK(!src1.is(src2)); 297 LoadP(src2, MemOperand(sp, 0));
383 if (src1.code() > src2.code()) { 298 LoadP(src1, MemOperand(sp, kPointerSize));
384 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 299 addi(sp, sp, Operand(2 * kPointerSize));
385 } else {
386 ldr(src2, MemOperand(sp, 4, PostIndex), cond);
387 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
388 }
389 } 300 }
390 301
391 // Pop three registers. Pops rightmost register first (from lower address). 302 // Pop three registers. Pops rightmost register first (from lower address).
392 void Pop(Register src1, Register src2, Register src3, Condition cond = al) { 303 void Pop(Register src1, Register src2, Register src3) {
393 DCHECK(!src1.is(src2)); 304 LoadP(src3, MemOperand(sp, 0));
394 DCHECK(!src2.is(src3)); 305 LoadP(src2, MemOperand(sp, kPointerSize));
395 DCHECK(!src1.is(src3)); 306 LoadP(src1, MemOperand(sp, 2 * kPointerSize));
396 if (src1.code() > src2.code()) { 307 addi(sp, sp, Operand(3 * kPointerSize));
397 if (src2.code() > src3.code()) {
398 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
399 } else {
400 ldr(src3, MemOperand(sp, 4, PostIndex), cond);
401 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
402 }
403 } else {
404 Pop(src2, src3, cond);
405 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
406 }
407 } 308 }
408 309
409 // Pop four registers. Pops rightmost register first (from lower address). 310 // Pop four registers. Pops rightmost register first (from lower address).
410 void Pop(Register src1, 311 void Pop(Register src1, Register src2, Register src3, Register src4) {
411 Register src2, 312 LoadP(src4, MemOperand(sp, 0));
412 Register src3, 313 LoadP(src3, MemOperand(sp, kPointerSize));
413 Register src4, 314 LoadP(src2, MemOperand(sp, 2 * kPointerSize));
414 Condition cond = al) { 315 LoadP(src1, MemOperand(sp, 3 * kPointerSize));
415 DCHECK(!src1.is(src2)); 316 addi(sp, sp, Operand(4 * kPointerSize));
416 DCHECK(!src2.is(src3));
417 DCHECK(!src1.is(src3));
418 DCHECK(!src1.is(src4));
419 DCHECK(!src2.is(src4));
420 DCHECK(!src3.is(src4));
421 if (src1.code() > src2.code()) {
422 if (src2.code() > src3.code()) {
423 if (src3.code() > src4.code()) {
424 ldm(ia_w,
425 sp,
426 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
427 cond);
428 } else {
429 ldr(src4, MemOperand(sp, 4, PostIndex), cond);
430 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
431 }
432 } else {
433 Pop(src3, src4, cond);
434 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
435 }
436 } else {
437 Pop(src2, src3, src4, cond);
438 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
439 }
440 } 317 }
441 318
442 // Push a fixed frame, consisting of lr, fp, constant pool (if 319 // Pop five registers. Pops rightmost register first (from lower address).
443 // FLAG_enable_ool_constant_pool), context and JS function / marker id if 320 void Pop(Register src1, Register src2, Register src3, Register src4,
444 // marker_reg is a valid register. 321 Register src5) {
322 LoadP(src5, MemOperand(sp, 0));
323 LoadP(src4, MemOperand(sp, kPointerSize));
324 LoadP(src3, MemOperand(sp, 2 * kPointerSize));
325 LoadP(src2, MemOperand(sp, 3 * kPointerSize));
326 LoadP(src1, MemOperand(sp, 4 * kPointerSize));
327 addi(sp, sp, Operand(5 * kPointerSize));
328 }
329
330 // Push a fixed frame, consisting of lr, fp, context and
331 // JS function / marker id if marker_reg is a valid register.
445 void PushFixedFrame(Register marker_reg = no_reg); 332 void PushFixedFrame(Register marker_reg = no_reg);
446 void PopFixedFrame(Register marker_reg = no_reg); 333 void PopFixedFrame(Register marker_reg = no_reg);
447 334
448 // Push and pop the registers that can hold pointers, as defined by the 335 // Push and pop the registers that can hold pointers, as defined by the
449 // RegList constant kSafepointSavedRegisters. 336 // RegList constant kSafepointSavedRegisters.
450 void PushSafepointRegisters(); 337 void PushSafepointRegisters();
451 void PopSafepointRegisters(); 338 void PopSafepointRegisters();
452 // Store value in register src in the safepoint stack slot for 339 // Store value in register src in the safepoint stack slot for
453 // register dst. 340 // register dst.
454 void StoreToSafepointRegisterSlot(Register src, Register dst); 341 void StoreToSafepointRegisterSlot(Register src, Register dst);
455 // Load the value of the src register from its safepoint stack slot 342 // Load the value of the src register from its safepoint stack slot
456 // into register dst. 343 // into register dst.
457 void LoadFromSafepointRegisterSlot(Register dst, Register src); 344 void LoadFromSafepointRegisterSlot(Register dst, Register src);
458 345
459 // Load two consecutive registers with two consecutive memory locations. 346 // Flush the I-cache from asm code. You should use CpuFeatures::FlushICache
460 void Ldrd(Register dst1, 347 // from C.
461 Register dst2, 348 // Does not handle errors.
462 const MemOperand& src, 349 void FlushICache(Register address, size_t size, Register scratch);
463 Condition cond = al);
464
465 // Store two consecutive registers to two consecutive memory locations.
466 void Strd(Register src1,
467 Register src2,
468 const MemOperand& dst,
469 Condition cond = al);
470
471 // Ensure that FPSCR contains values needed by JavaScript.
472 // We need the NaNModeControlBit to be sure that operations like
473 // vadd and vsub generate the Canonical NaN (if a NaN must be generated).
474 // In VFP3 it will be always the Canonical NaN.
475 // In VFP2 it will be either the Canonical NaN or the negative version
476 // of the Canonical NaN. It doesn't matter if we have two values. The aim
477 // is to be sure to never generate the hole NaN.
478 void VFPEnsureFPSCRState(Register scratch);
479 350
480 // If the value is a NaN, canonicalize the value else, do nothing. 351 // If the value is a NaN, canonicalize the value else, do nothing.
481 void VFPCanonicalizeNaN(const DwVfpRegister dst, 352 void CanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
482 const DwVfpRegister src, 353 void CanonicalizeNaN(const DoubleRegister value) {
483 const Condition cond = al); 354 CanonicalizeNaN(value, value);
484 void VFPCanonicalizeNaN(const DwVfpRegister value,
485 const Condition cond = al) {
486 VFPCanonicalizeNaN(value, value, cond);
487 } 355 }
488 356
489 // Compare double values and move the result to the normal condition flags. 357 // Converts the integer (untagged smi) in |src| to a double, storing
490 void VFPCompareAndSetFlags(const DwVfpRegister src1, 358 // the result to |double_dst|
491 const DwVfpRegister src2, 359 void ConvertIntToDouble(Register src, DoubleRegister double_dst);
492 const Condition cond = al);
493 void VFPCompareAndSetFlags(const DwVfpRegister src1,
494 const double src2,
495 const Condition cond = al);
496 360
497 // Compare double values and then load the fpscr flags to a register. 361 // Converts the unsigned integer (untagged smi) in |src| to
498 void VFPCompareAndLoadFlags(const DwVfpRegister src1, 362 // a double, storing the result to |double_dst|
499 const DwVfpRegister src2, 363 void ConvertUnsignedIntToDouble(Register src, DoubleRegister double_dst);
500 const Register fpscr_flags,
501 const Condition cond = al);
502 void VFPCompareAndLoadFlags(const DwVfpRegister src1,
503 const double src2,
504 const Register fpscr_flags,
505 const Condition cond = al);
506 364
507 void Vmov(const DwVfpRegister dst, 365 // Converts the integer (untagged smi) in |src| to
508 const double imm, 366 // a float, storing the result in |dst|
509 const Register scratch = no_reg); 367 // Warning: The value in |int_scrach| will be changed in the process!
368 void ConvertIntToFloat(const DoubleRegister dst, const Register src,
369 const Register int_scratch);
510 370
511 void VmovHigh(Register dst, DwVfpRegister src); 371 // Converts the double_input to an integer. Note that, upon return,
512 void VmovHigh(DwVfpRegister dst, Register src); 372 // the contents of double_dst will also hold the fixed point representation.
513 void VmovLow(Register dst, DwVfpRegister src); 373 void ConvertDoubleToInt64(const DoubleRegister double_input,
514 void VmovLow(DwVfpRegister dst, Register src); 374 #if !V8_TARGET_ARCH_PPC64
515 375 const Register dst_hi,
516 // Loads the number from object into dst register. 376 #endif
517 // If |object| is neither smi nor heap number, |not_number| is jumped to 377 const Register dst, const DoubleRegister double_dst,
518 // with |object| still intact. 378 FPRoundingMode rounding_mode = kRoundToZero);
519 void LoadNumber(Register object,
520 LowDwVfpRegister dst,
521 Register heap_number_map,
522 Register scratch,
523 Label* not_number);
524
525 // Loads the number from object into double_dst in the double format.
526 // Control will jump to not_int32 if the value cannot be exactly represented
527 // by a 32-bit integer.
528 // Floating point value in the 32-bit integer range that are not exact integer
529 // won't be loaded.
530 void LoadNumberAsInt32Double(Register object,
531 DwVfpRegister double_dst,
532 Register heap_number_map,
533 Register scratch,
534 LowDwVfpRegister double_scratch,
535 Label* not_int32);
536
537 // Loads the number from object into dst as a 32-bit integer.
538 // Control will jump to not_int32 if the object cannot be exactly represented
539 // by a 32-bit integer.
540 // Floating point value in the 32-bit integer range that are not exact integer
541 // won't be converted.
542 void LoadNumberAsInt32(Register object,
543 Register dst,
544 Register heap_number_map,
545 Register scratch,
546 DwVfpRegister double_scratch0,
547 LowDwVfpRegister double_scratch1,
548 Label* not_int32);
549 379
550 // Generates function and stub prologue code. 380 // Generates function and stub prologue code.
551 void StubPrologue(); 381 void StubPrologue();
552 void Prologue(bool code_pre_aging); 382 void Prologue(bool code_pre_aging);
553 383
554 // Enter exit frame. 384 // Enter exit frame.
555 // stack_space - extra stack space, used for alignment before call to C. 385 // stack_space - extra stack space, used for alignment before call to C.
556 void EnterExitFrame(bool save_doubles, int stack_space = 0); 386 void EnterExitFrame(bool save_doubles, int stack_space = 0);
557 387
558 // Leave the current exit frame. Expects the return value in r0. 388 // Leave the current exit frame. Expects the return value in r0.
559 // Expect the number of values, pushed prior to the exit frame, to 389 // Expect the number of values, pushed prior to the exit frame, to
560 // remove in a register (or no_reg, if there is nothing to remove). 390 // remove in a register (or no_reg, if there is nothing to remove).
561 void LeaveExitFrame(bool save_doubles, 391 void LeaveExitFrame(bool save_doubles, Register argument_count,
562 Register argument_count,
563 bool restore_context); 392 bool restore_context);
564 393
565 // Get the actual activation frame alignment for target environment. 394 // Get the actual activation frame alignment for target environment.
566 static int ActivationFrameAlignment(); 395 static int ActivationFrameAlignment();
567 396
568 void LoadContext(Register dst, int context_chain_length); 397 void LoadContext(Register dst, int context_chain_length);
569 398
570 // Conditionally load the cached Array transitioned map of type 399 // Conditionally load the cached Array transitioned map of type
571 // transitioned_kind from the native context if the map in register 400 // transitioned_kind from the native context if the map in register
572 // map_in_out is the cached Array map in the native context of 401 // map_in_out is the cached Array map in the native context of
573 // expected_kind. 402 // expected_kind.
574 void LoadTransitionedArrayMapConditional( 403 void LoadTransitionedArrayMapConditional(ElementsKind expected_kind,
575 ElementsKind expected_kind, 404 ElementsKind transitioned_kind,
576 ElementsKind transitioned_kind, 405 Register map_in_out,
577 Register map_in_out, 406 Register scratch,
578 Register scratch, 407 Label* no_map_match);
579 Label* no_map_match);
580 408
581 void LoadGlobalFunction(int index, Register function); 409 void LoadGlobalFunction(int index, Register function);
582 410
583 // Load the initial map from the global function. The registers 411 // Load the initial map from the global function. The registers
584 // function and map can be the same, function is then overwritten. 412 // function and map can be the same, function is then overwritten.
585 void LoadGlobalFunctionInitialMap(Register function, 413 void LoadGlobalFunctionInitialMap(Register function, Register map,
586 Register map,
587 Register scratch); 414 Register scratch);
588 415
589 void InitializeRootRegister() { 416 void InitializeRootRegister() {
590 ExternalReference roots_array_start = 417 ExternalReference roots_array_start =
591 ExternalReference::roots_array_start(isolate()); 418 ExternalReference::roots_array_start(isolate());
592 mov(kRootRegister, Operand(roots_array_start)); 419 mov(kRootRegister, Operand(roots_array_start));
593 } 420 }
594 421
422 // ----------------------------------------------------------------
423 // new PPC macro-assembler interfaces that are slightly higher level
424 // than assembler-ppc and may generate variable length sequences
425
426 // load a literal signed int value <value> to GPR <dst>
427 void LoadIntLiteral(Register dst, int value);
428
429 // load an SMI value <value> to GPR <dst>
430 void LoadSmiLiteral(Register dst, Smi* smi);
431
432 // load a literal double value <value> to FPR <result>
433 void LoadDoubleLiteral(DoubleRegister result, double value, Register scratch);
434
435 void LoadWord(Register dst, const MemOperand& mem, Register scratch,
436 bool updateForm = false);
437
438 void LoadWordArith(Register dst, const MemOperand& mem,
439 Register scratch = no_reg);
440
441 void StoreWord(Register src, const MemOperand& mem, Register scratch,
442 bool updateForm = false);
443
444 void LoadHalfWord(Register dst, const MemOperand& mem, Register scratch,
445 bool updateForm = false);
446
447 void StoreHalfWord(Register src, const MemOperand& mem, Register scratch,
448 bool updateForm = false);
449
450 void LoadByte(Register dst, const MemOperand& mem, Register scratch,
451 bool updateForm = false);
452
453 void StoreByte(Register src, const MemOperand& mem, Register scratch,
454 bool updateForm = false);
455
456 void LoadRepresentation(Register dst, const MemOperand& mem, Representation r,
457 Register scratch = no_reg);
458
459 void StoreRepresentation(Register src, const MemOperand& mem,
460 Representation r, Register scratch = no_reg);
461
462 // Move values between integer and floating point registers.
463 void MovIntToDouble(DoubleRegister dst, Register src, Register scratch);
464 void MovUnsignedIntToDouble(DoubleRegister dst, Register src,
465 Register scratch);
466 void MovInt64ToDouble(DoubleRegister dst,
467 #if !V8_TARGET_ARCH_PPC64
468 Register src_hi,
469 #endif
470 Register src);
471 #if V8_TARGET_ARCH_PPC64
472 void MovInt64ComponentsToDouble(DoubleRegister dst, Register src_hi,
473 Register src_lo, Register scratch);
474 #endif
475 void MovDoubleLowToInt(Register dst, DoubleRegister src);
476 void MovDoubleHighToInt(Register dst, DoubleRegister src);
477 void MovDoubleToInt64(
478 #if !V8_TARGET_ARCH_PPC64
479 Register dst_hi,
480 #endif
481 Register dst, DoubleRegister src);
482
483 void Add(Register dst, Register src, intptr_t value, Register scratch);
484 void Cmpi(Register src1, const Operand& src2, Register scratch,
485 CRegister cr = cr7);
486 void Cmpli(Register src1, const Operand& src2, Register scratch,
487 CRegister cr = cr7);
488 void Cmpwi(Register src1, const Operand& src2, Register scratch,
489 CRegister cr = cr7);
490 void Cmplwi(Register src1, const Operand& src2, Register scratch,
491 CRegister cr = cr7);
492 void And(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
493 void Or(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
494 void Xor(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
495
496 void AddSmiLiteral(Register dst, Register src, Smi* smi, Register scratch);
497 void SubSmiLiteral(Register dst, Register src, Smi* smi, Register scratch);
498 void CmpSmiLiteral(Register src1, Smi* smi, Register scratch,
499 CRegister cr = cr7);
500 void CmplSmiLiteral(Register src1, Smi* smi, Register scratch,
501 CRegister cr = cr7);
502 void AndSmiLiteral(Register dst, Register src, Smi* smi, Register scratch,
503 RCBit rc = LeaveRC);
504
505 // Set new rounding mode RN to FPSCR
506 void SetRoundingMode(FPRoundingMode RN);
507
508 // reset rounding mode to default (kRoundToNearest)
509 void ResetRoundingMode();
510
511 // These exist to provide portability between 32 and 64bit
512 void LoadP(Register dst, const MemOperand& mem, Register scratch = no_reg);
513 void StoreP(Register src, const MemOperand& mem, Register scratch = no_reg);
514
595 // --------------------------------------------------------------------------- 515 // ---------------------------------------------------------------------------
596 // JavaScript invokes 516 // JavaScript invokes
597 517
598 // Invoke the JavaScript function code by either calling or jumping. 518 // Invoke the JavaScript function code by either calling or jumping.
599 void InvokeCode(Register code, 519 void InvokeCode(Register code, const ParameterCount& expected,
600 const ParameterCount& expected, 520 const ParameterCount& actual, InvokeFlag flag,
601 const ParameterCount& actual,
602 InvokeFlag flag,
603 const CallWrapper& call_wrapper); 521 const CallWrapper& call_wrapper);
604 522
605 // Invoke the JavaScript function in the given register. Changes the 523 // Invoke the JavaScript function in the given register. Changes the
606 // current context to the context in the function before invoking. 524 // current context to the context in the function before invoking.
607 void InvokeFunction(Register function, 525 void InvokeFunction(Register function, const ParameterCount& actual,
608 const ParameterCount& actual, 526 InvokeFlag flag, const CallWrapper& call_wrapper);
609 InvokeFlag flag,
610 const CallWrapper& call_wrapper);
611 527
612 void InvokeFunction(Register function, 528 void InvokeFunction(Register function, const ParameterCount& expected,
613 const ParameterCount& expected, 529 const ParameterCount& actual, InvokeFlag flag,
614 const ParameterCount& actual,
615 InvokeFlag flag,
616 const CallWrapper& call_wrapper); 530 const CallWrapper& call_wrapper);
617 531
618 void InvokeFunction(Handle<JSFunction> function, 532 void InvokeFunction(Handle<JSFunction> function,
619 const ParameterCount& expected, 533 const ParameterCount& expected,
620 const ParameterCount& actual, 534 const ParameterCount& actual, InvokeFlag flag,
621 InvokeFlag flag,
622 const CallWrapper& call_wrapper); 535 const CallWrapper& call_wrapper);
623 536
624 void IsObjectJSObjectType(Register heap_object, 537 void IsObjectJSObjectType(Register heap_object, Register map,
625 Register map, 538 Register scratch, Label* fail);
626 Register scratch,
627 Label* fail);
628 539
629 void IsInstanceJSObjectType(Register map, 540 void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
630 Register scratch,
631 Label* fail);
632 541
633 void IsObjectJSStringType(Register object, 542 void IsObjectJSStringType(Register object, Register scratch, Label* fail);
634 Register scratch,
635 Label* fail);
636 543
637 void IsObjectNameType(Register object, 544 void IsObjectNameType(Register object, Register scratch, Label* fail);
638 Register scratch,
639 Label* fail);
640 545
641 // --------------------------------------------------------------------------- 546 // ---------------------------------------------------------------------------
642 // Debugger Support 547 // Debugger Support
643 548
644 void DebugBreak(); 549 void DebugBreak();
645 550
646 // --------------------------------------------------------------------------- 551 // ---------------------------------------------------------------------------
647 // Exception handling 552 // Exception handling
648 553
649 // Push a new try handler and link into try handler chain. 554 // Push a new try handler and link into try handler chain.
650 void PushTryHandler(StackHandler::Kind kind, int handler_index); 555 void PushTryHandler(StackHandler::Kind kind, int handler_index);
651 556
652 // Unlink the stack handler on top of the stack from the try handler chain. 557 // Unlink the stack handler on top of the stack from the try handler chain.
653 // Must preserve the result register. 558 // Must preserve the result register.
654 void PopTryHandler(); 559 void PopTryHandler();
655 560
656 // Passes thrown value to the handler of top of the try handler chain. 561 // Passes thrown value to the handler of top of the try handler chain.
657 void Throw(Register value); 562 void Throw(Register value);
658 563
659 // Propagates an uncatchable exception to the top of the current JS stack's 564 // Propagates an uncatchable exception to the top of the current JS stack's
660 // handler chain. 565 // handler chain.
661 void ThrowUncatchable(Register value); 566 void ThrowUncatchable(Register value);
662 567
663 // --------------------------------------------------------------------------- 568 // ---------------------------------------------------------------------------
664 // Inline caching support 569 // Inline caching support
665 570
666 // Generate code for checking access rights - used for security checks 571 // Generate code for checking access rights - used for security checks
667 // on access to global objects across environments. The holder register 572 // on access to global objects across environments. The holder register
668 // is left untouched, whereas both scratch registers are clobbered. 573 // is left untouched, whereas both scratch registers are clobbered.
669 void CheckAccessGlobalProxy(Register holder_reg, 574 void CheckAccessGlobalProxy(Register holder_reg, Register scratch,
670 Register scratch,
671 Label* miss); 575 Label* miss);
672 576
673 void GetNumberHash(Register t0, Register scratch); 577 void GetNumberHash(Register t0, Register scratch);
674 578
675 void LoadFromNumberDictionary(Label* miss, 579 void LoadFromNumberDictionary(Label* miss, Register elements, Register key,
676 Register elements, 580 Register result, Register t0, Register t1,
677 Register key,
678 Register result,
679 Register t0,
680 Register t1,
681 Register t2); 581 Register t2);
682 582
683 583
684 inline void MarkCode(NopMarkerTypes type) { 584 inline void MarkCode(NopMarkerTypes type) { nop(type); }
685 nop(type);
686 }
687 585
688 // Check if the given instruction is a 'type' marker. 586 // Check if the given instruction is a 'type' marker.
689 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type)) 587 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
690 // These instructions are generated to mark special location in the code, 588 // These instructions are generated to mark special location in the code,
691 // like some special IC code. 589 // like some special IC code.
692 static inline bool IsMarkedCode(Instr instr, int type) { 590 static inline bool IsMarkedCode(Instr instr, int type) {
693 DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); 591 DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
694 return IsNop(instr, type); 592 return IsNop(instr, type);
695 } 593 }
696 594
697 595
698 static inline int GetCodeMarker(Instr instr) { 596 static inline int GetCodeMarker(Instr instr) {
699 int dst_reg_offset = 12; 597 int dst_reg_offset = 12;
700 int dst_mask = 0xf << dst_reg_offset; 598 int dst_mask = 0xf << dst_reg_offset;
701 int src_mask = 0xf; 599 int src_mask = 0xf;
702 int dst_reg = (instr & dst_mask) >> dst_reg_offset; 600 int dst_reg = (instr & dst_mask) >> dst_reg_offset;
703 int src_reg = instr & src_mask; 601 int src_reg = instr & src_mask;
704 uint32_t non_register_mask = ~(dst_mask | src_mask); 602 uint32_t non_register_mask = ~(dst_mask | src_mask);
705 uint32_t mov_mask = al | 13 << 21; 603 uint32_t mov_mask = al | 13 << 21;
706 604
707 // Return <n> if we have a mov rn rn, else return -1. 605 // Return <n> if we have a mov rn rn, else return -1.
708 int type = ((instr & non_register_mask) == mov_mask) && 606 int type = ((instr & non_register_mask) == mov_mask) &&
709 (dst_reg == src_reg) && 607 (dst_reg == src_reg) && (FIRST_IC_MARKER <= dst_reg) &&
710 (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER) 608 (dst_reg < LAST_CODE_MARKER)
711 ? src_reg 609 ? src_reg
712 : -1; 610 : -1;
713 DCHECK((type == -1) || 611 DCHECK((type == -1) ||
714 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); 612 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
715 return type; 613 return type;
716 } 614 }
717 615
718 616
719 // --------------------------------------------------------------------------- 617 // ---------------------------------------------------------------------------
720 // Allocation support 618 // Allocation support
721 619
722 // Allocate an object in new space or old pointer space. The object_size is 620 // Allocate an object in new space or old pointer space. The object_size is
723 // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS 621 // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
724 // is passed. If the space is exhausted control continues at the gc_required 622 // is passed. If the space is exhausted control continues at the gc_required
725 // label. The allocated object is returned in result. If the flag 623 // label. The allocated object is returned in result. If the flag
726 // tag_allocated_object is true the result is tagged as as a heap object. 624 // tag_allocated_object is true the result is tagged as as a heap object.
727 // All registers are clobbered also when control continues at the gc_required 625 // All registers are clobbered also when control continues at the gc_required
728 // label. 626 // label.
729 void Allocate(int object_size, 627 void Allocate(int object_size, Register result, Register scratch1,
730 Register result, 628 Register scratch2, Label* gc_required, AllocationFlags flags);
731 Register scratch1,
732 Register scratch2,
733 Label* gc_required,
734 AllocationFlags flags);
735 629
736 void Allocate(Register object_size, 630 void Allocate(Register object_size, Register result, Register scratch1,
737 Register result, 631 Register scratch2, Label* gc_required, AllocationFlags flags);
738 Register scratch1,
739 Register scratch2,
740 Label* gc_required,
741 AllocationFlags flags);
742 632
743 // Undo allocation in new space. The object passed and objects allocated after 633 // Undo allocation in new space. The object passed and objects allocated after
744 // it will no longer be allocated. The caller must make sure that no pointers 634 // it will no longer be allocated. The caller must make sure that no pointers
745 // are left to the object(s) no longer allocated as they would be invalid when 635 // are left to the object(s) no longer allocated as they would be invalid when
746 // allocation is undone. 636 // allocation is undone.
747 void UndoAllocationInNewSpace(Register object, Register scratch); 637 void UndoAllocationInNewSpace(Register object, Register scratch);
748 638
749 639
750 void AllocateTwoByteString(Register result, 640 void AllocateTwoByteString(Register result, Register length,
751 Register length, 641 Register scratch1, Register scratch2,
752 Register scratch1, 642 Register scratch3, Label* gc_required);
753 Register scratch2, 643 void AllocateAsciiString(Register result, Register length, Register scratch1,
754 Register scratch3, 644 Register scratch2, Register scratch3,
755 Label* gc_required);
756 void AllocateAsciiString(Register result,
757 Register length,
758 Register scratch1,
759 Register scratch2,
760 Register scratch3,
761 Label* gc_required); 645 Label* gc_required);
762 void AllocateTwoByteConsString(Register result, 646 void AllocateTwoByteConsString(Register result, Register length,
763 Register length, 647 Register scratch1, Register scratch2,
764 Register scratch1,
765 Register scratch2,
766 Label* gc_required); 648 Label* gc_required);
767 void AllocateAsciiConsString(Register result, 649 void AllocateAsciiConsString(Register result, Register length,
768 Register length, 650 Register scratch1, Register scratch2,
769 Register scratch1,
770 Register scratch2,
771 Label* gc_required); 651 Label* gc_required);
772 void AllocateTwoByteSlicedString(Register result, 652 void AllocateTwoByteSlicedString(Register result, Register length,
773 Register length, 653 Register scratch1, Register scratch2,
774 Register scratch1,
775 Register scratch2,
776 Label* gc_required); 654 Label* gc_required);
777 void AllocateAsciiSlicedString(Register result, 655 void AllocateAsciiSlicedString(Register result, Register length,
778 Register length, 656 Register scratch1, Register scratch2,
779 Register scratch1,
780 Register scratch2,
781 Label* gc_required); 657 Label* gc_required);
782 658
783 // Allocates a heap number or jumps to the gc_required label if the young 659 // Allocates a heap number or jumps to the gc_required label if the young
784 // space is full and a scavenge is needed. All registers are clobbered also 660 // space is full and a scavenge is needed. All registers are clobbered also
785 // when control continues at the gc_required label. 661 // when control continues at the gc_required label.
786 void AllocateHeapNumber(Register result, 662 void AllocateHeapNumber(Register result, Register scratch1, Register scratch2,
787 Register scratch1, 663 Register heap_number_map, Label* gc_required,
788 Register scratch2,
789 Register heap_number_map,
790 Label* gc_required,
791 TaggingMode tagging_mode = TAG_RESULT, 664 TaggingMode tagging_mode = TAG_RESULT,
792 MutableMode mode = IMMUTABLE); 665 MutableMode mode = IMMUTABLE);
793 void AllocateHeapNumberWithValue(Register result, 666 void AllocateHeapNumberWithValue(Register result, DoubleRegister value,
794 DwVfpRegister value, 667 Register scratch1, Register scratch2,
795 Register scratch1,
796 Register scratch2,
797 Register heap_number_map, 668 Register heap_number_map,
798 Label* gc_required); 669 Label* gc_required);
799 670
800 // Copies a fixed number of fields of heap objects from src to dst. 671 // Copies a fixed number of fields of heap objects from src to dst.
801 void CopyFields(Register dst, 672 void CopyFields(Register dst, Register src, RegList temps, int field_count);
802 Register src,
803 LowDwVfpRegister double_scratch,
804 int field_count);
805 673
806 // Copies a number of bytes from src to dst. All registers are clobbered. On 674 // Copies a number of bytes from src to dst. All registers are clobbered. On
807 // exit src and dst will point to the place just after where the last byte was 675 // exit src and dst will point to the place just after where the last byte was
808 // read or written and length will be zero. 676 // read or written and length will be zero.
809 void CopyBytes(Register src, 677 void CopyBytes(Register src, Register dst, Register length, Register scratch);
810 Register dst, 678
811 Register length, 679 // Initialize fields with filler values. |count| fields starting at
812 Register scratch); 680 // |start_offset| are overwritten with the value in |filler|. At the end the
681 // loop, |start_offset| points at the next uninitialized field. |count| is
682 // assumed to be non-zero.
683 void InitializeNFieldsWithFiller(Register start_offset, Register count,
684 Register filler);
813 685
814 // Initialize fields with filler values. Fields starting at |start_offset| 686 // Initialize fields with filler values. Fields starting at |start_offset|
815 // not including end_offset are overwritten with the value in |filler|. At 687 // not including end_offset are overwritten with the value in |filler|. At
816 // the end the loop, |start_offset| takes the value of |end_offset|. 688 // the end the loop, |start_offset| takes the value of |end_offset|.
817 void InitializeFieldsWithFiller(Register start_offset, 689 void InitializeFieldsWithFiller(Register start_offset, Register end_offset,
818 Register end_offset,
819 Register filler); 690 Register filler);
820 691
821 // --------------------------------------------------------------------------- 692 // ---------------------------------------------------------------------------
822 // Support functions. 693 // Support functions.
823 694
824 // Try to get function prototype of a function and puts the value in 695 // Try to get function prototype of a function and puts the value in
825 // the result register. Checks that the function really is a 696 // the result register. Checks that the function really is a
826 // function and jumps to the miss label if the fast checks fail. The 697 // function and jumps to the miss label if the fast checks fail. The
827 // function register will be untouched; the other registers may be 698 // function register will be untouched; the other registers may be
828 // clobbered. 699 // clobbered.
829 void TryGetFunctionPrototype(Register function, 700 void TryGetFunctionPrototype(Register function, Register result,
830 Register result, 701 Register scratch, Label* miss,
831 Register scratch,
832 Label* miss,
833 bool miss_on_bound_function = false); 702 bool miss_on_bound_function = false);
834 703
835 // Compare object type for heap object. heap_object contains a non-Smi 704 // Compare object type for heap object. heap_object contains a non-Smi
836 // whose object type should be compared with the given type. This both 705 // whose object type should be compared with the given type. This both
837 // sets the flags and leaves the object type in the type_reg register. 706 // sets the flags and leaves the object type in the type_reg register.
838 // It leaves the map in the map register (unless the type_reg and map register 707 // It leaves the map in the map register (unless the type_reg and map register
839 // are the same register). It leaves the heap object in the heap_object 708 // are the same register). It leaves the heap object in the heap_object
840 // register unless the heap_object register is the same register as one of the 709 // register unless the heap_object register is the same register as one of the
841 // other registers. 710 // other registers.
842 // Type_reg can be no_reg. In that case ip is used. 711 // Type_reg can be no_reg. In that case ip is used.
843 void CompareObjectType(Register heap_object, 712 void CompareObjectType(Register heap_object, Register map, Register type_reg,
844 Register map,
845 Register type_reg,
846 InstanceType type); 713 InstanceType type);
847 714
848 // Compare object type for heap object. Branch to false_label if type 715 // Compare object type for heap object. Branch to false_label if type
849 // is lower than min_type or greater than max_type. 716 // is lower than min_type or greater than max_type.
850 // Load map into the register map. 717 // Load map into the register map.
851 void CheckObjectTypeRange(Register heap_object, 718 void CheckObjectTypeRange(Register heap_object, Register map,
852 Register map, 719 InstanceType min_type, InstanceType max_type,
853 InstanceType min_type,
854 InstanceType max_type,
855 Label* false_label); 720 Label* false_label);
856 721
857 // Compare instance type in a map. map contains a valid map object whose 722 // Compare instance type in a map. map contains a valid map object whose
858 // object type should be compared with the given type. This both 723 // object type should be compared with the given type. This both
859 // sets the flags and leaves the object type in the type_reg register. 724 // sets the flags and leaves the object type in the type_reg register.
860 void CompareInstanceType(Register map, 725 void CompareInstanceType(Register map, Register type_reg, InstanceType type);
861 Register type_reg,
862 InstanceType type);
863 726
864 727
865 // Check if a map for a JSObject indicates that the object has fast elements. 728 // Check if a map for a JSObject indicates that the object has fast elements.
866 // Jump to the specified label if it does not. 729 // Jump to the specified label if it does not.
867 void CheckFastElements(Register map, 730 void CheckFastElements(Register map, Register scratch, Label* fail);
868 Register scratch,
869 Label* fail);
870 731
871 // Check if a map for a JSObject indicates that the object can have both smi 732 // Check if a map for a JSObject indicates that the object can have both smi
872 // and HeapObject elements. Jump to the specified label if it does not. 733 // and HeapObject elements. Jump to the specified label if it does not.
873 void CheckFastObjectElements(Register map, 734 void CheckFastObjectElements(Register map, Register scratch, Label* fail);
874 Register scratch,
875 Label* fail);
876 735
877 // Check if a map for a JSObject indicates that the object has fast smi only 736 // Check if a map for a JSObject indicates that the object has fast smi only
878 // elements. Jump to the specified label if it does not. 737 // elements. Jump to the specified label if it does not.
879 void CheckFastSmiElements(Register map, 738 void CheckFastSmiElements(Register map, Register scratch, Label* fail);
880 Register scratch,
881 Label* fail);
882 739
883 // Check to see if maybe_number can be stored as a double in 740 // Check to see if maybe_number can be stored as a double in
884 // FastDoubleElements. If it can, store it at the index specified by key in 741 // FastDoubleElements. If it can, store it at the index specified by key in
885 // the FastDoubleElements array elements. Otherwise jump to fail. 742 // the FastDoubleElements array elements. Otherwise jump to fail.
886 void StoreNumberToDoubleElements(Register value_reg, 743 void StoreNumberToDoubleElements(Register value_reg, Register key_reg,
887 Register key_reg, 744 Register elements_reg, Register scratch1,
888 Register elements_reg, 745 DoubleRegister double_scratch, Label* fail,
889 Register scratch1,
890 LowDwVfpRegister double_scratch,
891 Label* fail,
892 int elements_offset = 0); 746 int elements_offset = 0);
893 747
894 // Compare an object's map with the specified map and its transitioned 748 // Compare an object's map with the specified map and its transitioned
895 // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are 749 // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
896 // set with result of map compare. If multiple map compares are required, the 750 // set with result of map compare. If multiple map compares are required, the
897 // compare sequences branches to early_success. 751 // compare sequences branches to early_success.
898 void CompareMap(Register obj, 752 void CompareMap(Register obj, Register scratch, Handle<Map> map,
899 Register scratch,
900 Handle<Map> map,
901 Label* early_success); 753 Label* early_success);
902 754
903 // As above, but the map of the object is already loaded into the register 755 // As above, but the map of the object is already loaded into the register
904 // which is preserved by the code generated. 756 // which is preserved by the code generated.
905 void CompareMap(Register obj_map, 757 void CompareMap(Register obj_map, Handle<Map> map, Label* early_success);
906 Handle<Map> map,
907 Label* early_success);
908 758
909 // Check if the map of an object is equal to a specified map and branch to 759 // Check if the map of an object is equal to a specified map and branch to
910 // label if not. Skip the smi check if not required (object is known to be a 760 // label if not. Skip the smi check if not required (object is known to be a
911 // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 761 // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
912 // against maps that are ElementsKind transition maps of the specified map. 762 // against maps that are ElementsKind transition maps of the specified map.
913 void CheckMap(Register obj, 763 void CheckMap(Register obj, Register scratch, Handle<Map> map, Label* fail,
914 Register scratch,
915 Handle<Map> map,
916 Label* fail,
917 SmiCheckType smi_check_type); 764 SmiCheckType smi_check_type);
918 765
919 766
920 void CheckMap(Register obj, 767 void CheckMap(Register obj, Register scratch, Heap::RootListIndex index,
921 Register scratch, 768 Label* fail, SmiCheckType smi_check_type);
922 Heap::RootListIndex index,
923 Label* fail,
924 SmiCheckType smi_check_type);
925 769
926 770
927 // Check if the map of an object is equal to a specified map and branch to a 771 // Check if the map of an object is equal to a specified map and branch to a
928 // specified target if equal. Skip the smi check if not required (object is 772 // specified target if equal. Skip the smi check if not required (object is
929 // known to be a heap object) 773 // known to be a heap object)
930 void DispatchMap(Register obj, 774 void DispatchMap(Register obj, Register scratch, Handle<Map> map,
931 Register scratch, 775 Handle<Code> success, SmiCheckType smi_check_type);
932 Handle<Map> map,
933 Handle<Code> success,
934 SmiCheckType smi_check_type);
935 776
936 777
937 // Compare the object in a register to a value from the root list. 778 // Compare the object in a register to a value from the root list.
938 // Uses the ip register as scratch. 779 // Uses the ip register as scratch.
939 void CompareRoot(Register obj, Heap::RootListIndex index); 780 void CompareRoot(Register obj, Heap::RootListIndex index);
940 781
941 782
942 // Load and check the instance type of an object for being a string. 783 // Load and check the instance type of an object for being a string.
943 // Loads the type into the second argument register. 784 // Loads the type into the second argument register.
944 // Returns a condition that will be enabled if the object was a string 785 // Returns a condition that will be enabled if the object was a string.
945 // and the passed-in condition passed. If the passed-in condition failed 786 Condition IsObjectStringType(Register obj, Register type) {
946 // then flags remain unchanged. 787 LoadP(type, FieldMemOperand(obj, HeapObject::kMapOffset));
947 Condition IsObjectStringType(Register obj, 788 lbz(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
948 Register type, 789 andi(r0, type, Operand(kIsNotStringMask));
949 Condition cond = al) {
950 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond);
951 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond);
952 tst(type, Operand(kIsNotStringMask), cond);
953 DCHECK_EQ(0, kStringTag); 790 DCHECK_EQ(0, kStringTag);
954 return eq; 791 return eq;
955 } 792 }
956 793
957 794
958 // Picks out an array index from the hash field. 795 // Picks out an array index from the hash field.
959 // Register use: 796 // Register use:
960 // hash - holds the index's hash. Clobbered. 797 // hash - holds the index's hash. Clobbered.
961 // index - holds the overwritten index on exit. 798 // index - holds the overwritten index on exit.
962 void IndexFromHash(Register hash, Register index); 799 void IndexFromHash(Register hash, Register index);
963 800
964 // Get the number of least significant bits from a register 801 // Get the number of least significant bits from a register
965 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 802 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
966 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 803 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
967 804
968 // Load the value of a smi object into a double register. 805 // Load the value of a smi object into a double register.
969 // The register value must be between d0 and d15. 806 void SmiToDouble(DoubleRegister value, Register smi);
970 void SmiToDouble(LowDwVfpRegister value, Register smi);
971 807
972 // Check if a double can be exactly represented as a signed 32-bit integer. 808 // Check if a double can be exactly represented as a signed 32-bit integer.
973 // Z flag set to one if true. 809 // CR_EQ in cr7 is set if true.
974 void TestDoubleIsInt32(DwVfpRegister double_input, 810 void TestDoubleIsInt32(DoubleRegister double_input, Register scratch1,
975 LowDwVfpRegister double_scratch); 811 Register scratch2, DoubleRegister double_scratch);
976 812
977 // Try to convert a double to a signed 32-bit integer. 813 // Try to convert a double to a signed 32-bit integer.
978 // Z flag set to one and result assigned if the conversion is exact. 814 // CR_EQ in cr7 is set and result assigned if the conversion is exact.
979 void TryDoubleToInt32Exact(Register result, 815 void TryDoubleToInt32Exact(Register result, DoubleRegister double_input,
980 DwVfpRegister double_input, 816 Register scratch, DoubleRegister double_scratch);
981 LowDwVfpRegister double_scratch);
982 817
983 // Floor a double and writes the value to the result register. 818 // Floor a double and writes the value to the result register.
984 // Go to exact if the conversion is exact (to be able to test -0), 819 // Go to exact if the conversion is exact (to be able to test -0),
985 // fall through calling code if an overflow occurred, else go to done. 820 // fall through calling code if an overflow occurred, else go to done.
986 // In return, input_high is loaded with high bits of input. 821 // In return, input_high is loaded with high bits of input.
987 void TryInt32Floor(Register result, 822 void TryInt32Floor(Register result, DoubleRegister double_input,
988 DwVfpRegister double_input, 823 Register input_high, Register scratch,
989 Register input_high, 824 DoubleRegister double_scratch, Label* done, Label* exact);
990 LowDwVfpRegister double_scratch,
991 Label* done,
992 Label* exact);
993 825
994 // Performs a truncating conversion of a floating point number as used by 826 // Performs a truncating conversion of a floating point number as used by
995 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it 827 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
996 // succeeds, otherwise falls through if result is saturated. On return 828 // succeeds, otherwise falls through if result is saturated. On return
997 // 'result' either holds answer, or is clobbered on fall through. 829 // 'result' either holds answer, or is clobbered on fall through.
998 // 830 //
999 // Only public for the test code in test-code-stubs-arm.cc. 831 // Only public for the test code in test-code-stubs-arm.cc.
1000 void TryInlineTruncateDoubleToI(Register result, 832 void TryInlineTruncateDoubleToI(Register result, DoubleRegister input,
1001 DwVfpRegister input,
1002 Label* done); 833 Label* done);
1003 834
1004 // Performs a truncating conversion of a floating point number as used by 835 // Performs a truncating conversion of a floating point number as used by
1005 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 836 // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
1006 // Exits with 'result' holding the answer. 837 // Exits with 'result' holding the answer.
1007 void TruncateDoubleToI(Register result, DwVfpRegister double_input); 838 void TruncateDoubleToI(Register result, DoubleRegister double_input);
1008 839
1009 // Performs a truncating conversion of a heap number as used by 840 // Performs a truncating conversion of a heap number as used by
1010 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input' 841 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
1011 // must be different registers. Exits with 'result' holding the answer. 842 // must be different registers. Exits with 'result' holding the answer.
1012 void TruncateHeapNumberToI(Register result, Register object); 843 void TruncateHeapNumberToI(Register result, Register object);
1013 844
1014 // Converts the smi or heap number in object to an int32 using the rules 845 // Converts the smi or heap number in object to an int32 using the rules
1015 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated 846 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
1016 // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be 847 // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
1017 // different registers. 848 // different registers.
1018 void TruncateNumberToI(Register object, 849 void TruncateNumberToI(Register object, Register result,
1019 Register result, 850 Register heap_number_map, Register scratch1,
1020 Register heap_number_map,
1021 Register scratch1,
1022 Label* not_int32); 851 Label* not_int32);
1023 852
1024 // Check whether d16-d31 are available on the CPU. The result is given by the 853 // Overflow handling functions.
1025 // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise. 854 // Usage: call the appropriate arithmetic function and then call one of the
1026 void CheckFor32DRegs(Register scratch); 855 // flow control functions with the corresponding label.
1027 856
1028 // Does a runtime check for 16/32 FP registers. Either way, pushes 32 double 857 // Compute dst = left + right, setting condition codes. dst may be same as
1029 // values to location, saving [d0..(d15|d31)]. 858 // either left or right (or a unique register). left and right must not be
1030 void SaveFPRegs(Register location, Register scratch); 859 // the same register.
860 void AddAndCheckForOverflow(Register dst, Register left, Register right,
861 Register overflow_dst, Register scratch = r0);
1031 862
1032 // Does a runtime check for 16/32 FP registers. Either way, pops 32 double 863 // Compute dst = left - right, setting condition codes. dst may be same as
1033 // values to location, restoring [d0..(d15|d31)]. 864 // either left or right (or a unique register). left and right must not be
1034 void RestoreFPRegs(Register location, Register scratch); 865 // the same register.
866 void SubAndCheckForOverflow(Register dst, Register left, Register right,
867 Register overflow_dst, Register scratch = r0);
868
869 void BranchOnOverflow(Label* label) { blt(label, cr0); }
870
871 void BranchOnNoOverflow(Label* label) { bge(label, cr0); }
872
873 void RetOnOverflow(void) {
874 Label label;
875
876 blt(&label, cr0);
877 Ret();
878 bind(&label);
879 }
880
881 void RetOnNoOverflow(void) {
882 Label label;
883
884 bge(&label, cr0);
885 Ret();
886 bind(&label);
887 }
888
889 // Pushes <count> double values to <location>, starting from d<first>.
890 void SaveFPRegs(Register location, int first, int count);
891
892 // Pops <count> double values from <location>, starting from d<first>.
893 void RestoreFPRegs(Register location, int first, int count);
1035 894
1036 // --------------------------------------------------------------------------- 895 // ---------------------------------------------------------------------------
1037 // Runtime calls 896 // Runtime calls
1038 897
1039 // Call a code stub. 898 // Call a code stub.
1040 void CallStub(CodeStub* stub, 899 void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None(),
1041 TypeFeedbackId ast_id = TypeFeedbackId::None(),
1042 Condition cond = al); 900 Condition cond = al);
1043 901
1044 // Call a code stub. 902 // Call a code stub.
1045 void TailCallStub(CodeStub* stub, Condition cond = al); 903 void TailCallStub(CodeStub* stub, Condition cond = al);
1046 904
1047 // Call a runtime routine. 905 // Call a runtime routine.
1048 void CallRuntime(const Runtime::Function* f, 906 void CallRuntime(const Runtime::Function* f, int num_arguments,
1049 int num_arguments,
1050 SaveFPRegsMode save_doubles = kDontSaveFPRegs); 907 SaveFPRegsMode save_doubles = kDontSaveFPRegs);
1051 void CallRuntimeSaveDoubles(Runtime::FunctionId id) { 908 void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
1052 const Runtime::Function* function = Runtime::FunctionForId(id); 909 const Runtime::Function* function = Runtime::FunctionForId(id);
1053 CallRuntime(function, function->nargs, kSaveFPRegs); 910 CallRuntime(function, function->nargs, kSaveFPRegs);
1054 } 911 }
1055 912
1056 // Convenience function: Same as above, but takes the fid instead. 913 // Convenience function: Same as above, but takes the fid instead.
1057 void CallRuntime(Runtime::FunctionId id, 914 void CallRuntime(Runtime::FunctionId id, int num_arguments,
1058 int num_arguments,
1059 SaveFPRegsMode save_doubles = kDontSaveFPRegs) { 915 SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1060 CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles); 916 CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
1061 } 917 }
1062 918
1063 // Convenience function: call an external reference. 919 // Convenience function: call an external reference.
1064 void CallExternalReference(const ExternalReference& ext, 920 void CallExternalReference(const ExternalReference& ext, int num_arguments);
1065 int num_arguments);
1066 921
1067 // Tail call of a runtime routine (jump). 922 // Tail call of a runtime routine (jump).
1068 // Like JumpToExternalReference, but also takes care of passing the number 923 // Like JumpToExternalReference, but also takes care of passing the number
1069 // of parameters. 924 // of parameters.
1070 void TailCallExternalReference(const ExternalReference& ext, 925 void TailCallExternalReference(const ExternalReference& ext,
1071 int num_arguments, 926 int num_arguments, int result_size);
1072 int result_size);
1073 927
1074 // Convenience function: tail call a runtime routine (jump). 928 // Convenience function: tail call a runtime routine (jump).
1075 void TailCallRuntime(Runtime::FunctionId fid, 929 void TailCallRuntime(Runtime::FunctionId fid, int num_arguments,
1076 int num_arguments,
1077 int result_size); 930 int result_size);
1078 931
1079 int CalculateStackPassedWords(int num_reg_arguments, 932 int CalculateStackPassedWords(int num_reg_arguments,
1080 int num_double_arguments); 933 int num_double_arguments);
1081 934
1082 // Before calling a C-function from generated code, align arguments on stack. 935 // Before calling a C-function from generated code, align arguments on stack.
1083 // After aligning the frame, non-register arguments must be stored in 936 // After aligning the frame, non-register arguments must be stored in
1084 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments 937 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
1085 // are word sized. If double arguments are used, this function assumes that 938 // are word sized. If double arguments are used, this function assumes that
1086 // all double arguments are stored before core registers; otherwise the 939 // all double arguments are stored before core registers; otherwise the
1087 // correct alignment of the double values is not guaranteed. 940 // correct alignment of the double values is not guaranteed.
1088 // Some compilers/platforms require the stack to be aligned when calling 941 // Some compilers/platforms require the stack to be aligned when calling
1089 // C++ code. 942 // C++ code.
1090 // Needs a scratch register to do some arithmetic. This register will be 943 // Needs a scratch register to do some arithmetic. This register will be
1091 // trashed. 944 // trashed.
1092 void PrepareCallCFunction(int num_reg_arguments, 945 void PrepareCallCFunction(int num_reg_arguments, int num_double_registers,
1093 int num_double_registers,
1094 Register scratch); 946 Register scratch);
1095 void PrepareCallCFunction(int num_reg_arguments, 947 void PrepareCallCFunction(int num_reg_arguments, Register scratch);
1096 Register scratch);
1097 948
1098 // There are two ways of passing double arguments on ARM, depending on 949 // There are two ways of passing double arguments on ARM, depending on
1099 // whether soft or hard floating point ABI is used. These functions 950 // whether soft or hard floating point ABI is used. These functions
1100 // abstract parameter passing for the three different ways we call 951 // abstract parameter passing for the three different ways we call
1101 // C functions from generated code. 952 // C functions from generated code.
1102 void MovToFloatParameter(DwVfpRegister src); 953 void MovToFloatParameter(DoubleRegister src);
1103 void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2); 954 void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
1104 void MovToFloatResult(DwVfpRegister src); 955 void MovToFloatResult(DoubleRegister src);
1105 956
1106 // Calls a C function and cleans up the space for arguments allocated 957 // Calls a C function and cleans up the space for arguments allocated
1107 // by PrepareCallCFunction. The called function is not allowed to trigger a 958 // by PrepareCallCFunction. The called function is not allowed to trigger a
1108 // garbage collection, since that might move the code and invalidate the 959 // garbage collection, since that might move the code and invalidate the
1109 // return address (unless this is somehow accounted for by the called 960 // return address (unless this is somehow accounted for by the called
1110 // function). 961 // function).
1111 void CallCFunction(ExternalReference function, int num_arguments); 962 void CallCFunction(ExternalReference function, int num_arguments);
1112 void CallCFunction(Register function, int num_arguments); 963 void CallCFunction(Register function, int num_arguments);
1113 void CallCFunction(ExternalReference function, 964 void CallCFunction(ExternalReference function, int num_reg_arguments,
1114 int num_reg_arguments,
1115 int num_double_arguments); 965 int num_double_arguments);
1116 void CallCFunction(Register function, 966 void CallCFunction(Register function, int num_reg_arguments,
1117 int num_reg_arguments,
1118 int num_double_arguments); 967 int num_double_arguments);
1119 968
1120 void MovFromFloatParameter(DwVfpRegister dst); 969 void MovFromFloatParameter(DoubleRegister dst);
1121 void MovFromFloatResult(DwVfpRegister dst); 970 void MovFromFloatResult(DoubleRegister dst);
1122 971
1123 // Calls an API function. Allocates HandleScope, extracts returned value 972 // Calls an API function. Allocates HandleScope, extracts returned value
1124 // from handle and propagates exceptions. Restores context. stack_space 973 // from handle and propagates exceptions. Restores context. stack_space
1125 // - space to be unwound on exit (includes the call JS arguments space and 974 // - space to be unwound on exit (includes the call JS arguments space and
1126 // the additional space allocated for the fast call). 975 // the additional space allocated for the fast call).
1127 void CallApiFunctionAndReturn(Register function_address, 976 void CallApiFunctionAndReturn(Register function_address,
1128 ExternalReference thunk_ref, 977 ExternalReference thunk_ref, int stack_space,
1129 int stack_space,
1130 MemOperand return_value_operand, 978 MemOperand return_value_operand,
1131 MemOperand* context_restore_operand); 979 MemOperand* context_restore_operand);
1132 980
1133 // Jump to a runtime routine. 981 // Jump to a runtime routine.
1134 void JumpToExternalReference(const ExternalReference& builtin); 982 void JumpToExternalReference(const ExternalReference& builtin);
1135 983
1136 // Invoke specified builtin JavaScript function. Adds an entry to 984 // Invoke specified builtin JavaScript function. Adds an entry to
1137 // the unresolved list if the name does not resolve. 985 // the unresolved list if the name does not resolve.
1138 void InvokeBuiltin(Builtins::JavaScript id, 986 void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag,
1139 InvokeFlag flag,
1140 const CallWrapper& call_wrapper = NullCallWrapper()); 987 const CallWrapper& call_wrapper = NullCallWrapper());
1141 988
1142 // Store the code object for the given builtin in the target register and 989 // Store the code object for the given builtin in the target register and
1143 // setup the function in r1. 990 // setup the function in r1.
1144 void GetBuiltinEntry(Register target, Builtins::JavaScript id); 991 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
1145 992
1146 // Store the function for the given builtin in the target register. 993 // Store the function for the given builtin in the target register.
1147 void GetBuiltinFunction(Register target, Builtins::JavaScript id); 994 void GetBuiltinFunction(Register target, Builtins::JavaScript id);
1148 995
1149 Handle<Object> CodeObject() { 996 Handle<Object> CodeObject() {
1150 DCHECK(!code_object_.is_null()); 997 DCHECK(!code_object_.is_null());
1151 return code_object_; 998 return code_object_;
1152 } 999 }
1153 1000
1154 1001
1155 // Emit code for a truncating division by a constant. The dividend register is 1002 // Emit code for a truncating division by a constant. The dividend register is
1156 // unchanged and ip gets clobbered. Dividend and result must be different. 1003 // unchanged and ip gets clobbered. Dividend and result must be different.
1157 void TruncatingDiv(Register result, Register dividend, int32_t divisor); 1004 void TruncatingDiv(Register result, Register dividend, int32_t divisor);
1158 1005
1159 // --------------------------------------------------------------------------- 1006 // ---------------------------------------------------------------------------
1160 // StatsCounter support 1007 // StatsCounter support
1161 1008
1162 void SetCounter(StatsCounter* counter, int value, 1009 void SetCounter(StatsCounter* counter, int value, Register scratch1,
1163 Register scratch1, Register scratch2); 1010 Register scratch2);
1164 void IncrementCounter(StatsCounter* counter, int value, 1011 void IncrementCounter(StatsCounter* counter, int value, Register scratch1,
1165 Register scratch1, Register scratch2); 1012 Register scratch2);
1166 void DecrementCounter(StatsCounter* counter, int value, 1013 void DecrementCounter(StatsCounter* counter, int value, Register scratch1,
1167 Register scratch1, Register scratch2); 1014 Register scratch2);
1168 1015
1169 1016
1170 // --------------------------------------------------------------------------- 1017 // ---------------------------------------------------------------------------
1171 // Debugging 1018 // Debugging
1172 1019
1173 // Calls Abort(msg) if the condition cond is not satisfied. 1020 // Calls Abort(msg) if the condition cond is not satisfied.
1174 // Use --debug_code to enable. 1021 // Use --debug_code to enable.
1175 void Assert(Condition cond, BailoutReason reason); 1022 void Assert(Condition cond, BailoutReason reason, CRegister cr = cr7);
1176 void AssertFastElements(Register elements); 1023 void AssertFastElements(Register elements);
1177 1024
1178 // Like Assert(), but always enabled. 1025 // Like Assert(), but always enabled.
1179 void Check(Condition cond, BailoutReason reason); 1026 void Check(Condition cond, BailoutReason reason, CRegister cr = cr7);
1180 1027
1181 // Print a message to stdout and abort execution. 1028 // Print a message to stdout and abort execution.
1182 void Abort(BailoutReason msg); 1029 void Abort(BailoutReason reason);
1183 1030
1184 // Verify restrictions about code generated in stubs. 1031 // Verify restrictions about code generated in stubs.
1185 void set_generating_stub(bool value) { generating_stub_ = value; } 1032 void set_generating_stub(bool value) { generating_stub_ = value; }
1186 bool generating_stub() { return generating_stub_; } 1033 bool generating_stub() { return generating_stub_; }
1187 void set_has_frame(bool value) { has_frame_ = value; } 1034 void set_has_frame(bool value) { has_frame_ = value; }
1188 bool has_frame() { return has_frame_; } 1035 bool has_frame() { return has_frame_; }
1189 inline bool AllowThisStubCall(CodeStub* stub); 1036 inline bool AllowThisStubCall(CodeStub* stub);
1190 1037
1191 // EABI variant for double arguments in use.
1192 bool use_eabi_hardfloat() {
1193 #ifdef __arm__
1194 return base::OS::ArmUsingHardFloat();
1195 #elif USE_EABI_HARDFLOAT
1196 return true;
1197 #else
1198 return false;
1199 #endif
1200 }
1201
1202 // --------------------------------------------------------------------------- 1038 // ---------------------------------------------------------------------------
1203 // Number utilities 1039 // Number utilities
1204 1040
1205 // Check whether the value of reg is a power of two and not zero. If not 1041 // Check whether the value of reg is a power of two and not zero. If not
1206 // control continues at the label not_power_of_two. If reg is a power of two 1042 // control continues at the label not_power_of_two. If reg is a power of two
1207 // the register scratch contains the value of (reg - 1) when control falls 1043 // the register scratch contains the value of (reg - 1) when control falls
1208 // through. 1044 // through.
1209 void JumpIfNotPowerOfTwoOrZero(Register reg, 1045 void JumpIfNotPowerOfTwoOrZero(Register reg, Register scratch,
1210 Register scratch,
1211 Label* not_power_of_two_or_zero); 1046 Label* not_power_of_two_or_zero);
1212 // Check whether the value of reg is a power of two and not zero. 1047 // Check whether the value of reg is a power of two and not zero.
1213 // Control falls through if it is, with scratch containing the mask 1048 // Control falls through if it is, with scratch containing the mask
1214 // value (reg - 1). 1049 // value (reg - 1).
1215 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is 1050 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
1216 // zero or negative, or jumps to the 'not_power_of_two' label if the value is 1051 // zero or negative, or jumps to the 'not_power_of_two' label if the value is
1217 // strictly positive but not a power of two. 1052 // strictly positive but not a power of two.
1218 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, 1053 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, Register scratch,
1219 Register scratch,
1220 Label* zero_and_neg, 1054 Label* zero_and_neg,
1221 Label* not_power_of_two); 1055 Label* not_power_of_two);
1222 1056
1223 // --------------------------------------------------------------------------- 1057 // ---------------------------------------------------------------------------
1224 // Smi utilities 1058 // Bit testing/extraction
1059 //
1060 // Bit numbering is such that the least significant bit is bit 0
1061 // (for consistency between 32/64-bit).
1225 1062
1226 void SmiTag(Register reg, SBit s = LeaveCC) { 1063 // Extract consecutive bits (defined by rangeStart - rangeEnd) from src
1227 add(reg, reg, Operand(reg), s); 1064 // and place them into the least significant bits of dst.
1228 } 1065 inline void ExtractBitRange(Register dst, Register src, int rangeStart,
1229 void SmiTag(Register dst, Register src, SBit s = LeaveCC) { 1066 int rangeEnd, RCBit rc = LeaveRC) {
1230 add(dst, src, Operand(src), s); 1067 DCHECK(rangeStart >= rangeEnd && rangeStart < kBitsPerPointer);
1068 int rotate = (rangeEnd == 0) ? 0 : kBitsPerPointer - rangeEnd;
1069 int width = rangeStart - rangeEnd + 1;
1070 #if V8_TARGET_ARCH_PPC64
1071 rldicl(dst, src, rotate, kBitsPerPointer - width, rc);
1072 #else
1073 rlwinm(dst, src, rotate, kBitsPerPointer - width, kBitsPerPointer - 1, rc);
1074 #endif
1231 } 1075 }
1232 1076
1233 // Try to convert int32 to smi. If the value is to large, preserve 1077 inline void ExtractBit(Register dst, Register src, uint32_t bitNumber,
1234 // the original value and jump to not_a_smi. Destroys scratch and 1078 RCBit rc = LeaveRC) {
1235 // sets flags. 1079 ExtractBitRange(dst, src, bitNumber, bitNumber, rc);
1236 void TrySmiTag(Register reg, Label* not_a_smi) {
1237 TrySmiTag(reg, reg, not_a_smi);
1238 } 1080 }
1239 void TrySmiTag(Register reg, Register src, Label* not_a_smi) { 1081
1240 SmiTag(ip, src, SetCC); 1082 // Extract consecutive bits (defined by mask) from src and place them
1241 b(vs, not_a_smi); 1083 // into the least significant bits of dst.
1242 mov(reg, ip); 1084 inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
1085 RCBit rc = LeaveRC) {
1086 int start = kBitsPerPointer - 1;
1087 int end;
1088 uintptr_t bit = (1L << start);
1089
1090 while (bit && (mask & bit) == 0) {
1091 start--;
1092 bit >>= 1;
1093 }
1094 end = start;
1095 bit >>= 1;
1096
1097 while (bit && (mask & bit)) {
1098 end--;
1099 bit >>= 1;
1100 }
1101
1102 // 1-bits in mask must be contiguous
1103 DCHECK(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
1104
1105 ExtractBitRange(dst, src, start, end, rc);
1106 }
1107
1108 // Test single bit in value.
1109 inline void TestBit(Register value, int bitNumber, Register scratch = r0) {
1110 ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC);
1111 }
1112
1113 // Test consecutive bit range in value. Range is defined by
1114 // rangeStart - rangeEnd.
1115 inline void TestBitRange(Register value, int rangeStart, int rangeEnd,
1116 Register scratch = r0) {
1117 ExtractBitRange(scratch, value, rangeStart, rangeEnd, SetRC);
1118 }
1119
1120 // Test consecutive bit range in value. Range is defined by mask.
1121 inline void TestBitMask(Register value, uintptr_t mask,
1122 Register scratch = r0) {
1123 ExtractBitMask(scratch, value, mask, SetRC);
1243 } 1124 }
1244 1125
1245 1126
1246 void SmiUntag(Register reg, SBit s = LeaveCC) { 1127 // ---------------------------------------------------------------------------
1247 mov(reg, Operand::SmiUntag(reg), s); 1128 // Smi utilities
1129
1130 // Shift left by 1
1131 void SmiTag(Register reg, RCBit rc = LeaveRC) { SmiTag(reg, reg, rc); }
1132 void SmiTag(Register dst, Register src, RCBit rc = LeaveRC) {
1133 ShiftLeftImm(dst, src, Operand(kSmiShift), rc);
1248 } 1134 }
1249 void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { 1135
1250 mov(dst, Operand::SmiUntag(src), s); 1136 #if !V8_TARGET_ARCH_PPC64
1137 // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
1138 void SmiTagCheckOverflow(Register reg, Register overflow);
1139 void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
1140
1141 inline void JumpIfNotSmiCandidate(Register value, Register scratch,
1142 Label* not_smi_label) {
1143 // High bits must be identical to fit into an Smi
1144 addis(scratch, value, Operand(0x40000000u >> 16));
1145 cmpi(scratch, Operand::Zero());
1146 blt(not_smi_label);
1147 }
1148 #endif
1149 inline void TestUnsignedSmiCandidate(Register value, Register scratch) {
1150 // The test is different for unsigned int values. Since we need
1151 // the value to be in the range of a positive smi, we can't
1152 // handle any of the high bits being set in the value.
1153 TestBitRange(value, kBitsPerPointer - 1, kBitsPerPointer - 1 - kSmiShift,
1154 scratch);
1155 }
1156 inline void JumpIfNotUnsignedSmiCandidate(Register value, Register scratch,
1157 Label* not_smi_label) {
1158 TestUnsignedSmiCandidate(value, scratch);
1159 bne(not_smi_label, cr0);
1160 }
1161
1162 void SmiUntag(Register reg, RCBit rc = LeaveRC) { SmiUntag(reg, reg, rc); }
1163
1164 void SmiUntag(Register dst, Register src, RCBit rc = LeaveRC) {
1165 ShiftRightArithImm(dst, src, kSmiShift, rc);
1166 }
1167
1168 void SmiToPtrArrayOffset(Register dst, Register src) {
1169 #if V8_TARGET_ARCH_PPC64
1170 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kPointerSizeLog2);
1171 ShiftRightArithImm(dst, src, kSmiShift - kPointerSizeLog2);
1172 #else
1173 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kPointerSizeLog2);
1174 ShiftLeftImm(dst, src, Operand(kPointerSizeLog2 - kSmiShift));
1175 #endif
1176 }
1177
1178 void SmiToByteArrayOffset(Register dst, Register src) { SmiUntag(dst, src); }
1179
1180 void SmiToShortArrayOffset(Register dst, Register src) {
1181 #if V8_TARGET_ARCH_PPC64
1182 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 1);
1183 ShiftRightArithImm(dst, src, kSmiShift - 1);
1184 #else
1185 STATIC_ASSERT(kSmiTag == 0 && kSmiShift == 1);
1186 if (!dst.is(src)) {
1187 mr(dst, src);
1188 }
1189 #endif
1190 }
1191
1192 void SmiToIntArrayOffset(Register dst, Register src) {
1193 #if V8_TARGET_ARCH_PPC64
1194 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 2);
1195 ShiftRightArithImm(dst, src, kSmiShift - 2);
1196 #else
1197 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < 2);
1198 ShiftLeftImm(dst, src, Operand(2 - kSmiShift));
1199 #endif
1200 }
1201
1202 #define SmiToFloatArrayOffset SmiToIntArrayOffset
1203
1204 void SmiToDoubleArrayOffset(Register dst, Register src) {
1205 #if V8_TARGET_ARCH_PPC64
1206 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kDoubleSizeLog2);
1207 ShiftRightArithImm(dst, src, kSmiShift - kDoubleSizeLog2);
1208 #else
1209 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kDoubleSizeLog2);
1210 ShiftLeftImm(dst, src, Operand(kDoubleSizeLog2 - kSmiShift));
1211 #endif
1212 }
1213
1214 void SmiToArrayOffset(Register dst, Register src, int elementSizeLog2) {
1215 if (kSmiShift < elementSizeLog2) {
1216 ShiftLeftImm(dst, src, Operand(elementSizeLog2 - kSmiShift));
1217 } else if (kSmiShift > elementSizeLog2) {
1218 ShiftRightArithImm(dst, src, kSmiShift - elementSizeLog2);
1219 } else if (!dst.is(src)) {
1220 mr(dst, src);
1221 }
1222 }
1223
1224 void IndexToArrayOffset(Register dst, Register src, int elementSizeLog2,
1225 bool isSmi) {
1226 if (isSmi) {
1227 SmiToArrayOffset(dst, src, elementSizeLog2);
1228 } else {
1229 ShiftLeftImm(dst, src, Operand(elementSizeLog2));
1230 }
1251 } 1231 }
1252 1232
1253 // Untag the source value into destination and jump if source is a smi. 1233 // Untag the source value into destination and jump if source is a smi.
1254 // Souce and destination can be the same register. 1234 // Souce and destination can be the same register.
1255 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); 1235 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1256 1236
1257 // Untag the source value into destination and jump if source is not a smi. 1237 // Untag the source value into destination and jump if source is not a smi.
1258 // Souce and destination can be the same register. 1238 // Souce and destination can be the same register.
1259 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); 1239 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
1260 1240
1261 // Test if the register contains a smi (Z == 0 (eq) if true). 1241 inline void TestIfSmi(Register value, Register scratch) {
1262 inline void SmiTst(Register value) { 1242 TestBit(value, 0, scratch); // tst(value, Operand(kSmiTagMask));
1263 tst(value, Operand(kSmiTagMask));
1264 } 1243 }
1265 inline void NonNegativeSmiTst(Register value) { 1244
1266 tst(value, Operand(kSmiTagMask | kSmiSignMask)); 1245 inline void TestIfPositiveSmi(Register value, Register scratch) {
1246 STATIC_ASSERT((kSmiTagMask | kSmiSignMask) ==
1247 (intptr_t)(1UL << (kBitsPerPointer - 1) | 1));
1248 #if V8_TARGET_ARCH_PPC64
1249 rldicl(scratch, value, 1, kBitsPerPointer - 2, SetRC);
1250 #else
1251 rlwinm(scratch, value, 1, kBitsPerPointer - 2, kBitsPerPointer - 1, SetRC);
1252 #endif
1267 } 1253 }
1268 // Jump if the register contains a smi. 1254
1255 // Jump the register contains a smi.
1269 inline void JumpIfSmi(Register value, Label* smi_label) { 1256 inline void JumpIfSmi(Register value, Label* smi_label) {
1270 tst(value, Operand(kSmiTagMask)); 1257 TestIfSmi(value, r0);
1271 b(eq, smi_label); 1258 beq(smi_label, cr0); // branch if SMI
1272 } 1259 }
1273 // Jump if either of the registers contain a non-smi. 1260 // Jump if either of the registers contain a non-smi.
1274 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { 1261 inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
1275 tst(value, Operand(kSmiTagMask)); 1262 TestIfSmi(value, r0);
1276 b(ne, not_smi_label); 1263 bne(not_smi_label, cr0);
1277 } 1264 }
1278 // Jump if either of the registers contain a non-smi. 1265 // Jump if either of the registers contain a non-smi.
1279 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 1266 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
1280 // Jump if either of the registers contain a smi. 1267 // Jump if either of the registers contain a smi.
1281 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); 1268 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1282 1269
1283 // Abort execution if argument is a smi, enabled via --debug-code. 1270 // Abort execution if argument is a smi, enabled via --debug-code.
1284 void AssertNotSmi(Register object); 1271 void AssertNotSmi(Register object);
1285 void AssertSmi(Register object); 1272 void AssertSmi(Register object);
1286 1273
1274
1275 #if V8_TARGET_ARCH_PPC64
1276 inline void TestIfInt32(Register value, Register scratch1, Register scratch2,
1277 CRegister cr = cr7) {
1278 // High bits must be identical to fit into an 32-bit integer
1279 srawi(scratch1, value, 31);
1280 sradi(scratch2, value, 32);
1281 cmp(scratch1, scratch2, cr);
1282 }
1283 #else
1284 inline void TestIfInt32(Register hi_word, Register lo_word, Register scratch,
1285 CRegister cr = cr7) {
1286 // High bits must be identical to fit into an 32-bit integer
1287 srawi(scratch, lo_word, 31);
1288 cmp(scratch, hi_word, cr);
1289 }
1290 #endif
1291
1287 // Abort execution if argument is not a string, enabled via --debug-code. 1292 // Abort execution if argument is not a string, enabled via --debug-code.
1288 void AssertString(Register object); 1293 void AssertString(Register object);
1289 1294
1290 // Abort execution if argument is not a name, enabled via --debug-code. 1295 // Abort execution if argument is not a name, enabled via --debug-code.
1291 void AssertName(Register object); 1296 void AssertName(Register object);
1292 1297
1293 // Abort execution if argument is not undefined or an AllocationSite, enabled 1298 // Abort execution if argument is not undefined or an AllocationSite, enabled
1294 // via --debug-code. 1299 // via --debug-code.
1295 void AssertUndefinedOrAllocationSite(Register object, Register scratch); 1300 void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1296 1301
1297 // Abort execution if reg is not the root value with the given index, 1302 // Abort execution if reg is not the root value with the given index,
1298 // enabled via --debug-code. 1303 // enabled via --debug-code.
1299 void AssertIsRoot(Register reg, Heap::RootListIndex index); 1304 void AssertIsRoot(Register reg, Heap::RootListIndex index);
1300 1305
1301 // --------------------------------------------------------------------------- 1306 // ---------------------------------------------------------------------------
1302 // HeapNumber utilities 1307 // HeapNumber utilities
1303 1308
1304 void JumpIfNotHeapNumber(Register object, 1309 void JumpIfNotHeapNumber(Register object, Register heap_number_map,
1305 Register heap_number_map, 1310 Register scratch, Label* on_not_heap_number);
1306 Register scratch,
1307 Label* on_not_heap_number);
1308 1311
1309 // --------------------------------------------------------------------------- 1312 // ---------------------------------------------------------------------------
1310 // String utilities 1313 // String utilities
1311 1314
1312 // Generate code to do a lookup in the number string cache. If the number in 1315 // Generate code to do a lookup in the number string cache. If the number in
1313 // the register object is found in the cache the generated code falls through 1316 // the register object is found in the cache the generated code falls through
1314 // with the result in the result register. The object and the result register 1317 // with the result in the result register. The object and the result register
1315 // can be the same. If the number is not found in the cache the code jumps to 1318 // can be the same. If the number is not found in the cache the code jumps to
1316 // the label not_found with only the content of register object unchanged. 1319 // the label not_found with only the content of register object unchanged.
1317 void LookupNumberStringCache(Register object, 1320 void LookupNumberStringCache(Register object, Register result,
1318 Register result, 1321 Register scratch1, Register scratch2,
1319 Register scratch1, 1322 Register scratch3, Label* not_found);
1320 Register scratch2,
1321 Register scratch3,
1322 Label* not_found);
1323 1323
1324 // Checks if both objects are sequential ASCII strings and jumps to label 1324 // Checks if both objects are sequential ASCII strings and jumps to label
1325 // if either is not. Assumes that neither object is a smi. 1325 // if either is not. Assumes that neither object is a smi.
1326 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, 1326 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
1327 Register object2, 1327 Register object2,
1328 Register scratch1, 1328 Register scratch1,
1329 Register scratch2, 1329 Register scratch2,
1330 Label* failure); 1330 Label* failure);
1331 1331
1332 // Checks if both objects are sequential ASCII strings and jumps to label 1332 // Checks if both objects are sequential ASCII strings and jumps to label
1333 // if either is not. 1333 // if either is not.
1334 void JumpIfNotBothSequentialAsciiStrings(Register first, 1334 void JumpIfNotBothSequentialAsciiStrings(Register first, Register second,
1335 Register second, 1335 Register scratch1, Register scratch2,
1336 Register scratch1,
1337 Register scratch2,
1338 Label* not_flat_ascii_strings); 1336 Label* not_flat_ascii_strings);
1339 1337
1340 // Checks if both instance types are sequential ASCII strings and jumps to 1338 // Checks if both instance types are sequential ASCII strings and jumps to
1341 // label if either is not. 1339 // label if either is not.
1342 void JumpIfBothInstanceTypesAreNotSequentialAscii( 1340 void JumpIfBothInstanceTypesAreNotSequentialAscii(
1343 Register first_object_instance_type, 1341 Register first_object_instance_type, Register second_object_instance_type,
1344 Register second_object_instance_type, 1342 Register scratch1, Register scratch2, Label* failure);
1345 Register scratch1,
1346 Register scratch2,
1347 Label* failure);
1348 1343
1349 // Check if instance type is sequential ASCII string and jump to label if 1344 // Check if instance type is sequential ASCII string and jump to label if
1350 // it is not. 1345 // it is not.
1351 void JumpIfInstanceTypeIsNotSequentialAscii(Register type, 1346 void JumpIfInstanceTypeIsNotSequentialAscii(Register type, Register scratch,
1352 Register scratch,
1353 Label* failure); 1347 Label* failure);
1354 1348
1355 void JumpIfNotUniqueName(Register reg, Label* not_unique_name); 1349 void JumpIfNotUniqueName(Register reg, Label* not_unique_name);
1356 1350
1357 void EmitSeqStringSetCharCheck(Register string, 1351 void EmitSeqStringSetCharCheck(Register string, Register index,
1358 Register index, 1352 Register value, uint32_t encoding_mask);
1359 Register value,
1360 uint32_t encoding_mask);
1361 1353
1362 // --------------------------------------------------------------------------- 1354 // ---------------------------------------------------------------------------
1363 // Patching helpers. 1355 // Patching helpers.
1364 1356
1365 // Get the location of a relocated constant (its address in the constant pool) 1357 // Retrieve/patch the relocated value (lis/ori pair or constant pool load).
1366 // from its load site. 1358 void GetRelocatedValue(Register location, Register result, Register scratch);
1367 void GetRelocatedValueLocation(Register ldr_location, Register result, 1359 void SetRelocatedValue(Register location, Register scratch,
1368 Register scratch); 1360 Register new_value);
1369
1370 1361
1371 void ClampUint8(Register output_reg, Register input_reg); 1362 void ClampUint8(Register output_reg, Register input_reg);
1372 1363
1373 void ClampDoubleToUint8(Register result_reg, 1364 // Saturate a value into 8-bit unsigned integer
1374 DwVfpRegister input_reg, 1365 // if input_value < 0, output_value is 0
1375 LowDwVfpRegister double_scratch); 1366 // if input_value > 255, output_value is 255
1367 // otherwise output_value is the (int)input_value (round to nearest)
1368 void ClampDoubleToUint8(Register result_reg, DoubleRegister input_reg,
1369 DoubleRegister temp_double_reg);
1376 1370
1377 1371
1378 void LoadInstanceDescriptors(Register map, Register descriptors); 1372 void LoadInstanceDescriptors(Register map, Register descriptors);
1379 void EnumLength(Register dst, Register map); 1373 void EnumLength(Register dst, Register map);
1380 void NumberOfOwnDescriptors(Register dst, Register map); 1374 void NumberOfOwnDescriptors(Register dst, Register map);
1381 1375
1382 template<typename Field> 1376 template <typename Field>
1383 void DecodeField(Register dst, Register src) { 1377 void DecodeField(Register dst, Register src) {
1384 Ubfx(dst, src, Field::kShift, Field::kSize); 1378 ExtractBitRange(dst, src, Field::kShift + Field::kSize - 1, Field::kShift);
1385 } 1379 }
1386 1380
1387 template<typename Field> 1381 template <typename Field>
1388 void DecodeField(Register reg) { 1382 void DecodeField(Register reg) {
1389 DecodeField<Field>(reg, reg); 1383 DecodeField<Field>(reg, reg);
1390 } 1384 }
1391 1385
1392 template<typename Field> 1386 template <typename Field>
1393 void DecodeFieldToSmi(Register dst, Register src) { 1387 void DecodeFieldToSmi(Register dst, Register src) {
1394 static const int shift = Field::kShift; 1388 #if V8_TARGET_ARCH_PPC64
1395 static const int mask = Field::kMask >> shift << kSmiTagSize; 1389 DecodeField<Field>(dst, src);
1396 STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0); 1390 SmiTag(dst);
1397 STATIC_ASSERT(kSmiTag == 0); 1391 #else
1398 if (shift < kSmiTagSize) { 1392 // 32-bit can do this in one instruction:
1399 mov(dst, Operand(src, LSL, kSmiTagSize - shift)); 1393 int start = Field::kSize + kSmiShift - 1;
1400 and_(dst, dst, Operand(mask)); 1394 int end = kSmiShift;
1401 } else if (shift > kSmiTagSize) { 1395 int rotate = kSmiShift - Field::kShift;
1402 mov(dst, Operand(src, LSR, shift - kSmiTagSize)); 1396 if (rotate < 0) {
1403 and_(dst, dst, Operand(mask)); 1397 rotate += kBitsPerPointer;
1404 } else {
1405 and_(dst, src, Operand(mask));
1406 } 1398 }
1399 rlwinm(dst, src, rotate, kBitsPerPointer - start - 1,
1400 kBitsPerPointer - end - 1);
1401 #endif
1407 } 1402 }
1408 1403
1409 template<typename Field> 1404 template <typename Field>
1410 void DecodeFieldToSmi(Register reg) { 1405 void DecodeFieldToSmi(Register reg) {
1411 DecodeField<Field>(reg, reg); 1406 DecodeFieldToSmi<Field>(reg, reg);
1412 } 1407 }
1413 1408
1414 // Activation support. 1409 // Activation support.
1415 void EnterFrame(StackFrame::Type type, bool load_constant_pool = false); 1410 void EnterFrame(StackFrame::Type type, bool load_constant_pool = false);
1416 // Returns the pc offset at which the frame ends. 1411 // Returns the pc offset at which the frame ends.
1417 int LeaveFrame(StackFrame::Type type); 1412 int LeaveFrame(StackFrame::Type type);
1418 1413
1419 // Expects object in r0 and returns map with validated enum cache 1414 // Expects object in r0 and returns map with validated enum cache
1420 // in r0. Assumes that any other register can be used as a scratch. 1415 // in r0. Assumes that any other register can be used as a scratch.
1421 void CheckEnumCache(Register null_value, Label* call_runtime); 1416 void CheckEnumCache(Register null_value, Label* call_runtime);
1422 1417
1423 // AllocationMemento support. Arrays may have an associated 1418 // AllocationMemento support. Arrays may have an associated
1424 // AllocationMemento object that can be checked for in order to pretransition 1419 // AllocationMemento object that can be checked for in order to pretransition
1425 // to another type. 1420 // to another type.
1426 // On entry, receiver_reg should point to the array object. 1421 // On entry, receiver_reg should point to the array object.
1427 // scratch_reg gets clobbered. 1422 // scratch_reg gets clobbered.
1428 // If allocation info is present, condition flags are set to eq. 1423 // If allocation info is present, condition flags are set to eq.
1429 void TestJSArrayForAllocationMemento(Register receiver_reg, 1424 void TestJSArrayForAllocationMemento(Register receiver_reg,
1430 Register scratch_reg, 1425 Register scratch_reg,
1431 Label* no_memento_found); 1426 Label* no_memento_found);
1432 1427
1433 void JumpIfJSArrayHasAllocationMemento(Register receiver_reg, 1428 void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
1434 Register scratch_reg, 1429 Register scratch_reg,
1435 Label* memento_found) { 1430 Label* memento_found) {
1436 Label no_memento_found; 1431 Label no_memento_found;
1437 TestJSArrayForAllocationMemento(receiver_reg, scratch_reg, 1432 TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
1438 &no_memento_found); 1433 &no_memento_found);
1439 b(eq, memento_found); 1434 beq(memento_found);
1440 bind(&no_memento_found); 1435 bind(&no_memento_found);
1441 } 1436 }
1442 1437
1443 // Jumps to found label if a prototype map has dictionary elements. 1438 // Jumps to found label if a prototype map has dictionary elements.
1444 void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0, 1439 void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
1445 Register scratch1, Label* found); 1440 Register scratch1, Label* found);
1446 1441
1447 private: 1442 private:
1448 void CallCFunctionHelper(Register function, 1443 static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1449 int num_reg_arguments, 1444
1445 void CallCFunctionHelper(Register function, int num_reg_arguments,
1450 int num_double_arguments); 1446 int num_double_arguments);
1451 1447
1452 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 1448 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al,
1449 CRegister cr = cr7);
1453 1450
1454 // Helper functions for generating invokes. 1451 // Helper functions for generating invokes.
1455 void InvokePrologue(const ParameterCount& expected, 1452 void InvokePrologue(const ParameterCount& expected,
1456 const ParameterCount& actual, 1453 const ParameterCount& actual, Handle<Code> code_constant,
1457 Handle<Code> code_constant, 1454 Register code_reg, Label* done,
1458 Register code_reg, 1455 bool* definitely_mismatches, InvokeFlag flag,
1459 Label* done,
1460 bool* definitely_mismatches,
1461 InvokeFlag flag,
1462 const CallWrapper& call_wrapper); 1456 const CallWrapper& call_wrapper);
1463 1457
1464 void InitializeNewString(Register string, 1458 void InitializeNewString(Register string, Register length,
1465 Register length, 1459 Heap::RootListIndex map_index, Register scratch1,
1466 Heap::RootListIndex map_index,
1467 Register scratch1,
1468 Register scratch2); 1460 Register scratch2);
1469 1461
1470 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 1462 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1471 void InNewSpace(Register object, 1463 void InNewSpace(Register object, Register scratch,
1472 Register scratch,
1473 Condition cond, // eq for new space, ne otherwise. 1464 Condition cond, // eq for new space, ne otherwise.
1474 Label* branch); 1465 Label* branch);
1475 1466
1476 // Helper for finding the mark bits for an address. Afterwards, the 1467 // Helper for finding the mark bits for an address. Afterwards, the
1477 // bitmap register points at the word with the mark bits and the mask 1468 // bitmap register points at the word with the mark bits and the mask
1478 // the position of the first bit. Leaves addr_reg unchanged. 1469 // the position of the first bit. Leaves addr_reg unchanged.
1479 inline void GetMarkBits(Register addr_reg, 1470 inline void GetMarkBits(Register addr_reg, Register bitmap_reg,
1480 Register bitmap_reg,
1481 Register mask_reg); 1471 Register mask_reg);
1482 1472
1483 // Helper for throwing exceptions. Compute a handler address and jump to 1473 // Helper for throwing exceptions. Compute a handler address and jump to
1484 // it. See the implementation for register usage. 1474 // it. See the implementation for register usage.
1485 void JumpToHandlerEntry(); 1475 void JumpToHandlerEntry();
1486 1476
1487 // Compute memory operands for safepoint stack slots. 1477 // Compute memory operands for safepoint stack slots.
1488 static int SafepointRegisterStackIndex(int reg_code); 1478 static int SafepointRegisterStackIndex(int reg_code);
1489 MemOperand SafepointRegisterSlot(Register reg); 1479 MemOperand SafepointRegisterSlot(Register reg);
1490 MemOperand SafepointRegistersAndDoublesSlot(Register reg); 1480 MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1491 1481
1492 // Loads the constant pool pointer (pp) register. 1482 #if V8_OOL_CONSTANT_POOL
1483 // Loads the constant pool pointer (kConstantPoolRegister).
1493 void LoadConstantPoolPointerRegister(); 1484 void LoadConstantPoolPointerRegister();
1485 #endif
1494 1486
1495 bool generating_stub_; 1487 bool generating_stub_;
1496 bool has_frame_; 1488 bool has_frame_;
1497 // This handle will be patched with the code object on installation. 1489 // This handle will be patched with the code object on installation.
1498 Handle<Object> code_object_; 1490 Handle<Object> code_object_;
1499 1491
1500 // Needs access to SafepointRegisterStackIndex for compiled frame 1492 // Needs access to SafepointRegisterStackIndex for compiled frame
1501 // traversal. 1493 // traversal.
1502 friend class StandardFrame; 1494 friend class StandardFrame;
1503 }; 1495 };
1504 1496
1505 1497
1506 // The code patcher is used to patch (typically) small parts of code e.g. for 1498 // The code patcher is used to patch (typically) small parts of code e.g. for
1507 // debugging and other types of instrumentation. When using the code patcher 1499 // debugging and other types of instrumentation. When using the code patcher
1508 // the exact number of bytes specified must be emitted. It is not legal to emit 1500 // the exact number of bytes specified must be emitted. It is not legal to emit
1509 // relocation information. If any of these constraints are violated it causes 1501 // relocation information. If any of these constraints are violated it causes
1510 // an assertion to fail. 1502 // an assertion to fail.
1511 class CodePatcher { 1503 class CodePatcher {
1512 public: 1504 public:
1513 enum FlushICache { 1505 enum FlushICache { FLUSH, DONT_FLUSH };
1514 FLUSH,
1515 DONT_FLUSH
1516 };
1517 1506
1518 CodePatcher(byte* address, 1507 CodePatcher(byte* address, int instructions, FlushICache flush_cache = FLUSH);
1519 int instructions,
1520 FlushICache flush_cache = FLUSH);
1521 virtual ~CodePatcher(); 1508 virtual ~CodePatcher();
1522 1509
1523 // Macro assembler to emit code. 1510 // Macro assembler to emit code.
1524 MacroAssembler* masm() { return &masm_; } 1511 MacroAssembler* masm() { return &masm_; }
1525 1512
1526 // Emit an instruction directly. 1513 // Emit an instruction directly.
1527 void Emit(Instr instr); 1514 void Emit(Instr instr);
1528 1515
1529 // Emit an address directly.
1530 void Emit(Address addr);
1531
1532 // Emit the condition part of an instruction leaving the rest of the current 1516 // Emit the condition part of an instruction leaving the rest of the current
1533 // instruction unchanged. 1517 // instruction unchanged.
1534 void EmitCondition(Condition cond); 1518 void EmitCondition(Condition cond);
1535 1519
1536 private: 1520 private:
1537 byte* address_; // The address of the code being patched. 1521 byte* address_; // The address of the code being patched.
1538 int size_; // Number of bytes of the expected patch size. 1522 int size_; // Number of bytes of the expected patch size.
1539 MacroAssembler masm_; // Macro assembler used to generate the code. 1523 MacroAssembler masm_; // Macro assembler used to generate the code.
1540 FlushICache flush_cache_; // Whether to flush the I cache after patching. 1524 FlushICache flush_cache_; // Whether to flush the I cache after patching.
1541 }; 1525 };
1542 1526
1543 1527
1528 #if V8_OOL_CONSTANT_POOL
1544 class FrameAndConstantPoolScope { 1529 class FrameAndConstantPoolScope {
1545 public: 1530 public:
1546 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type) 1531 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
1547 : masm_(masm), 1532 : masm_(masm),
1548 type_(type), 1533 type_(type),
1549 old_has_frame_(masm->has_frame()), 1534 old_has_frame_(masm->has_frame()),
1550 old_constant_pool_available_(masm->is_constant_pool_available()) { 1535 old_constant_pool_available_(masm->is_constant_pool_available()) {
1551 // We only want to enable constant pool access for non-manual frame scopes 1536 // We only want to enable constant pool access for non-manual frame scopes
1552 // to ensure the constant pool pointer is valid throughout the scope. 1537 // to ensure the constant pool pointer is valid throughout the scope.
1553 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); 1538 DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
1554 masm->set_has_frame(true); 1539 masm->set_has_frame(true);
1555 masm->set_constant_pool_available(true); 1540 masm->set_constant_pool_available(true);
1556 masm->EnterFrame(type, !old_constant_pool_available_); 1541 masm->EnterFrame(type, !old_constant_pool_available_);
1557 } 1542 }
1558 1543
1559 ~FrameAndConstantPoolScope() { 1544 ~FrameAndConstantPoolScope() {
1560 masm_->LeaveFrame(type_); 1545 masm_->LeaveFrame(type_);
(...skipping 12 matching lines...) Expand all
1573 } 1558 }
1574 1559
1575 private: 1560 private:
1576 MacroAssembler* masm_; 1561 MacroAssembler* masm_;
1577 StackFrame::Type type_; 1562 StackFrame::Type type_;
1578 bool old_has_frame_; 1563 bool old_has_frame_;
1579 bool old_constant_pool_available_; 1564 bool old_constant_pool_available_;
1580 1565
1581 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope); 1566 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
1582 }; 1567 };
1568 #else
1569 #define FrameAndConstantPoolScope FrameScope
1570 #endif
1583 1571
1584 1572
1573 #if V8_OOL_CONSTANT_POOL
1585 // Class for scoping the the unavailability of constant pool access. 1574 // Class for scoping the the unavailability of constant pool access.
1586 class ConstantPoolUnavailableScope { 1575 class ConstantPoolUnavailableScope {
1587 public: 1576 public:
1588 explicit ConstantPoolUnavailableScope(MacroAssembler* masm) 1577 explicit ConstantPoolUnavailableScope(MacroAssembler* masm)
1589 : masm_(masm), 1578 : masm_(masm),
1590 old_constant_pool_available_(masm->is_constant_pool_available()) { 1579 old_constant_pool_available_(masm->is_constant_pool_available()) {
1591 if (FLAG_enable_ool_constant_pool) { 1580 if (FLAG_enable_ool_constant_pool) {
1592 masm_->set_constant_pool_available(false); 1581 masm_->set_constant_pool_available(false);
1593 } 1582 }
1594 } 1583 }
1595 ~ConstantPoolUnavailableScope() { 1584 ~ConstantPoolUnavailableScope() {
1596 if (FLAG_enable_ool_constant_pool) { 1585 if (FLAG_enable_ool_constant_pool) {
1597 masm_->set_constant_pool_available(old_constant_pool_available_); 1586 masm_->set_constant_pool_available(old_constant_pool_available_);
1598 } 1587 }
1599 } 1588 }
1600 1589
1601 private: 1590 private:
1602 MacroAssembler* masm_; 1591 MacroAssembler* masm_;
1603 int old_constant_pool_available_; 1592 int old_constant_pool_available_;
1604 1593
1605 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope); 1594 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
1606 }; 1595 };
1596 #endif
1607 1597
1608 1598
1609 // ----------------------------------------------------------------------------- 1599 // -----------------------------------------------------------------------------
1610 // Static helper functions. 1600 // Static helper functions.
1611 1601
1612 inline MemOperand ContextOperand(Register context, int index) { 1602 inline MemOperand ContextOperand(Register context, int index) {
1613 return MemOperand(context, Context::SlotOffset(index)); 1603 return MemOperand(context, Context::SlotOffset(index));
1614 } 1604 }
1615 1605
1616 1606
1617 inline MemOperand GlobalObjectOperand() { 1607 inline MemOperand GlobalObjectOperand() {
1618 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX); 1608 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX);
1619 } 1609 }
1620 1610
1621 1611
1622 #ifdef GENERATED_CODE_COVERAGE 1612 #ifdef GENERATED_CODE_COVERAGE
1623 #define CODE_COVERAGE_STRINGIFY(x) #x 1613 #define CODE_COVERAGE_STRINGIFY(x) #x
1624 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 1614 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1625 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 1615 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1626 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> 1616 #define ACCESS_MASM(masm) \
1617 masm->stop(__FILE_LINE__); \
1618 masm->
1627 #else 1619 #else
1628 #define ACCESS_MASM(masm) masm-> 1620 #define ACCESS_MASM(masm) masm->
1629 #endif 1621 #endif
1622 }
1623 } // namespace v8::internal
1630 1624
1631 1625 #endif // V8_PPC_MACRO_ASSEMBLER_PPC_H_
1632 } } // namespace v8::internal
1633
1634 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698