blob: c9ffde89812da915f62bcc356e6f0a72e074beb6 [file] [log] [blame]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001// Copyright 2010 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
ager@chromium.org5ec48922009-05-05 07:25:34 +000028#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
29#define V8_ARM_MACRO_ASSEMBLER_ARM_H_
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030
31#include "assembler.h"
32
kasperl@chromium.org71affb52009-05-26 05:44:31 +000033namespace v8 {
34namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000036// Forward declaration.
37class PostCallGenerator;
38
ager@chromium.org5c838252010-02-19 08:53:10 +000039// ----------------------------------------------------------------------------
40// Static helper functions
41
42// Generate a MemOperand for loading a field from an object.
43static inline MemOperand FieldMemOperand(Register object, int offset) {
44 return MemOperand(object, offset - kHeapObjectTag);
45}
46
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000047
48// Give alias names to registers
ager@chromium.orgeadaf222009-06-16 09:43:10 +000049const Register cp = { 8 }; // JavaScript context pointer
ager@chromium.org5c838252010-02-19 08:53:10 +000050const Register roots = { 10 }; // Roots array pointer.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052enum InvokeJSFlags {
53 CALL_JS,
54 JUMP_JS
55};
56
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000057
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000058// Flags used for the AllocateInNewSpace functions.
59enum AllocationFlags {
60 // No special flags.
61 NO_ALLOCATION_FLAGS = 0,
62 // Return the pointer to the allocated already tagged as a heap object.
63 TAG_OBJECT = 1 << 0,
64 // The content of the result register already contains the allocation top in
65 // new space.
66 RESULT_CONTAINS_TOP = 1 << 1,
67 // Specify that the requested size of the space to allocate is specified in
68 // words instead of bytes.
69 SIZE_IN_WORDS = 1 << 2
70};
71
72
lrn@chromium.org32d961d2010-06-30 09:09:34 +000073// Flags used for the ObjectToDoubleVFPRegister function.
74enum ObjectToDoubleFlags {
75 // No special flags.
76 NO_OBJECT_TO_DOUBLE_FLAGS = 0,
77 // Object is known to be a non smi.
78 OBJECT_NOT_SMI = 1 << 0,
79 // Don't load NaNs or infinities, branch to the non number case instead.
80 AVOID_NANS_AND_INFINITIES = 1 << 1
81};
82
83
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084// MacroAssembler implements a collection of frequently used macros.
85class MacroAssembler: public Assembler {
86 public:
87 MacroAssembler(void* buffer, int size);
88
ager@chromium.org5c838252010-02-19 08:53:10 +000089 // Jump, Call, and Ret pseudo instructions implementing inter-working.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090 void Jump(Register target, Condition cond = al);
ager@chromium.org236ad962008-09-25 09:45:57 +000091 void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al);
92 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000093 void Call(Register target, Condition cond = al);
ager@chromium.org236ad962008-09-25 09:45:57 +000094 void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
95 void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000096 void Ret(Condition cond = al);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000097
98 // Emit code to discard a non-negative number of pointer-sized elements
99 // from the stack, clobbering only the sp register.
100 void Drop(int count, Condition cond = al);
101
whesse@chromium.org023421e2010-12-21 12:19:12 +0000102 void Ret(int drop, Condition cond = al);
ager@chromium.org357bf652010-04-12 11:30:10 +0000103
104 // Swap two registers. If the scratch register is omitted then a slightly
105 // less efficient form using xor instead of mov is emitted.
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000106 void Swap(Register reg1,
107 Register reg2,
108 Register scratch = no_reg,
109 Condition cond = al);
ager@chromium.org357bf652010-04-12 11:30:10 +0000110
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000111
112 void And(Register dst, Register src1, const Operand& src2,
113 Condition cond = al);
114 void Ubfx(Register dst, Register src, int lsb, int width,
115 Condition cond = al);
116 void Sbfx(Register dst, Register src, int lsb, int width,
117 Condition cond = al);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000118 void Bfc(Register dst, int lsb, int width, Condition cond = al);
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000119 void Usat(Register dst, int satpos, const Operand& src,
120 Condition cond = al);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000121
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000122 void Call(Label* target);
123 void Move(Register dst, Handle<Object> value);
ager@chromium.org357bf652010-04-12 11:30:10 +0000124 // May do nothing if the registers are identical.
125 void Move(Register dst, Register src);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000126 // Jumps to the label at the index given by the Smi in "index".
127 void SmiJumpTable(Register index, Vector<Label*> targets);
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000128 // Load an object from the root table.
129 void LoadRoot(Register destination,
130 Heap::RootListIndex index,
131 Condition cond = al);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000132 // Store an object to the root table.
133 void StoreRoot(Register source,
134 Heap::RootListIndex index,
135 Condition cond = al);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000136
ager@chromium.orgac091b72010-05-05 07:34:42 +0000137
138 // Check if object is in new space.
139 // scratch can be object itself, but it will be clobbered.
140 void InNewSpace(Register object,
141 Register scratch,
ager@chromium.org378b34e2011-01-28 08:04:38 +0000142 Condition cond, // eq for new space, ne otherwise
ager@chromium.orgac091b72010-05-05 07:34:42 +0000143 Label* branch);
144
145
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000146 // For the page containing |object| mark the region covering [address]
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000147 // dirty. The object address must be in the first 8K of an allocated page.
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000148 void RecordWriteHelper(Register object,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000149 Register address,
150 Register scratch);
ager@chromium.orgac091b72010-05-05 07:34:42 +0000151
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000152 // For the page containing |object| mark the region covering
153 // [object+offset] dirty. The object address must be in the first 8K
154 // of an allocated page. The 'scratch' registers are used in the
155 // implementation and all 3 registers are clobbered by the
156 // operation, as well as the ip register. RecordWrite updates the
157 // write barrier even when storing smis.
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000158 void RecordWrite(Register object,
159 Operand offset,
160 Register scratch0,
161 Register scratch1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000163 // For the page containing |object| mark the region covering
164 // [address] dirty. The object address must be in the first 8K of an
165 // allocated page. All 3 registers are clobbered by the operation,
166 // as well as the ip register. RecordWrite updates the write barrier
167 // even when storing smis.
168 void RecordWrite(Register object,
169 Register address,
170 Register scratch);
171
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000172 // Push two registers. Pushes leftmost register first (to highest address).
173 void Push(Register src1, Register src2, Condition cond = al) {
174 ASSERT(!src1.is(src2));
175 if (src1.code() > src2.code()) {
176 stm(db_w, sp, src1.bit() | src2.bit(), cond);
177 } else {
178 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
179 str(src2, MemOperand(sp, 4, NegPreIndex), cond);
180 }
181 }
182
183 // Push three registers. Pushes leftmost register first (to highest address).
184 void Push(Register src1, Register src2, Register src3, Condition cond = al) {
185 ASSERT(!src1.is(src2));
186 ASSERT(!src2.is(src3));
187 ASSERT(!src1.is(src3));
188 if (src1.code() > src2.code()) {
189 if (src2.code() > src3.code()) {
190 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
191 } else {
192 stm(db_w, sp, src1.bit() | src2.bit(), cond);
193 str(src3, MemOperand(sp, 4, NegPreIndex), cond);
194 }
195 } else {
196 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
197 Push(src2, src3, cond);
198 }
199 }
200
201 // Push four registers. Pushes leftmost register first (to highest address).
202 void Push(Register src1, Register src2,
203 Register src3, Register src4, Condition cond = al) {
204 ASSERT(!src1.is(src2));
205 ASSERT(!src2.is(src3));
206 ASSERT(!src1.is(src3));
207 ASSERT(!src1.is(src4));
208 ASSERT(!src2.is(src4));
209 ASSERT(!src3.is(src4));
210 if (src1.code() > src2.code()) {
211 if (src2.code() > src3.code()) {
212 if (src3.code() > src4.code()) {
213 stm(db_w,
214 sp,
215 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
216 cond);
217 } else {
218 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
219 str(src4, MemOperand(sp, 4, NegPreIndex), cond);
220 }
221 } else {
222 stm(db_w, sp, src1.bit() | src2.bit(), cond);
223 Push(src3, src4, cond);
224 }
225 } else {
226 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
227 Push(src2, src3, src4, cond);
228 }
229 }
230
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000231 // Push and pop the registers that can hold pointers, as defined by the
232 // RegList constant kSafepointSavedRegisters.
233 void PushSafepointRegisters();
234 void PopSafepointRegisters();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000235 void PushSafepointRegistersAndDoubles();
236 void PopSafepointRegistersAndDoubles();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000237 void StoreToSafepointRegisterSlot(Register reg);
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000238 void StoreToSafepointRegistersAndDoublesSlot(Register reg);
239 void LoadFromSafepointRegisterSlot(Register reg);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000240 static int SafepointRegisterStackIndex(int reg_code);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000241 static MemOperand SafepointRegisterSlot(Register reg);
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000242 static MemOperand SafepointRegistersAndDoublesSlot(Register reg);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000243
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000244 // Load two consecutive registers with two consecutive memory locations.
245 void Ldrd(Register dst1,
246 Register dst2,
247 const MemOperand& src,
248 Condition cond = al);
249
250 // Store two consecutive registers to two consecutive memory locations.
251 void Strd(Register src1,
252 Register src2,
253 const MemOperand& dst,
254 Condition cond = al);
255
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000256 // Clear specified FPSCR bits.
257 void ClearFPSCRBits(const uint32_t bits_to_clear,
258 const Register scratch,
259 const Condition cond = al);
260
261 // Compare double values and move the result to the normal condition flags.
262 void VFPCompareAndSetFlags(const DwVfpRegister src1,
263 const DwVfpRegister src2,
264 const Condition cond = al);
265 void VFPCompareAndSetFlags(const DwVfpRegister src1,
266 const double src2,
267 const Condition cond = al);
268
269 // Compare double values and then load the fpscr flags to a register.
270 void VFPCompareAndLoadFlags(const DwVfpRegister src1,
271 const DwVfpRegister src2,
272 const Register fpscr_flags,
273 const Condition cond = al);
274 void VFPCompareAndLoadFlags(const DwVfpRegister src1,
275 const double src2,
276 const Register fpscr_flags,
277 const Condition cond = al);
278
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000279
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000280 // ---------------------------------------------------------------------------
281 // Activation frames
282
ager@chromium.org7c537e22008-10-16 08:43:32 +0000283 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
284 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
285
286 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
287 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
ager@chromium.org236ad962008-09-25 09:45:57 +0000288
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000289 // Enter exit frame.
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000290 // stack_space - extra stack space, used for alignment before call to C.
291 void EnterExitFrame(bool save_doubles, int stack_space = 0);
ager@chromium.org236ad962008-09-25 09:45:57 +0000292
293 // Leave the current exit frame. Expects the return value in r0.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000294 void LeaveExitFrame(bool save_doubles);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000295
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000296 // Get the actual activation frame alignment for target environment.
297 static int ActivationFrameAlignment();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000298
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000299 void LoadContext(Register dst, int context_chain_length);
300
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000301 void LoadGlobalFunction(int index, Register function);
302
303 // Load the initial map from the global function. The registers
304 // function and map can be the same, function is then overwritten.
305 void LoadGlobalFunctionInitialMap(Register function,
306 Register map,
307 Register scratch);
308
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000309 // ---------------------------------------------------------------------------
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000310 // JavaScript invokes
311
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000312 // Invoke the JavaScript function code by either calling or jumping.
313 void InvokeCode(Register code,
314 const ParameterCount& expected,
315 const ParameterCount& actual,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000316 InvokeFlag flag,
317 PostCallGenerator* post_call_generator = NULL);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000318
319 void InvokeCode(Handle<Code> code,
320 const ParameterCount& expected,
321 const ParameterCount& actual,
ager@chromium.org236ad962008-09-25 09:45:57 +0000322 RelocInfo::Mode rmode,
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000323 InvokeFlag flag);
324
325 // Invoke the JavaScript function in the given register. Changes the
326 // current context to the context in the function before invoking.
327 void InvokeFunction(Register function,
328 const ParameterCount& actual,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000329 InvokeFlag flag,
330 PostCallGenerator* post_call_generator = NULL);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000331
ager@chromium.org5c838252010-02-19 08:53:10 +0000332 void InvokeFunction(JSFunction* function,
333 const ParameterCount& actual,
334 InvokeFlag flag);
335
whesse@chromium.org023421e2010-12-21 12:19:12 +0000336 void IsObjectJSObjectType(Register heap_object,
337 Register map,
338 Register scratch,
339 Label* fail);
340
341 void IsInstanceJSObjectType(Register map,
342 Register scratch,
343 Label* fail);
344
345 void IsObjectJSStringType(Register object,
346 Register scratch,
347 Label* fail);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000348
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000349#ifdef ENABLE_DEBUGGER_SUPPORT
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000350 // ---------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351 // Debugger Support
352
ager@chromium.org5c838252010-02-19 08:53:10 +0000353 void DebugBreak();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000354#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355
356 // ---------------------------------------------------------------------------
357 // Exception handling
358
359 // Push a new try handler and link into try handler chain.
360 // The return address must be passed in register lr.
361 // On exit, r0 contains TOS (code slot).
362 void PushTryHandler(CodeLocation try_location, HandlerType type);
363
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000364 // Unlink the stack handler on top of the stack from the try handler chain.
365 // Must preserve the result register.
366 void PopTryHandler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000367
368 // ---------------------------------------------------------------------------
369 // Inline caching support
370
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371 // Generate code for checking access rights - used for security checks
372 // on access to global objects across environments. The holder register
373 // is left untouched, whereas both scratch registers are clobbered.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000374 void CheckAccessGlobalProxy(Register holder_reg,
375 Register scratch,
376 Label* miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000377
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000378 inline void MarkCode(NopMarkerTypes type) {
379 nop(type);
380 }
381
382 // Check if the given instruction is a 'type' marker.
383 // ie. check if is is a mov r<type>, r<type> (referenced as nop(type))
384 // These instructions are generated to mark special location in the code,
385 // like some special IC code.
386 static inline bool IsMarkedCode(Instr instr, int type) {
387 ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
388 return IsNop(instr, type);
389 }
390
391
392 static inline int GetCodeMarker(Instr instr) {
393 int dst_reg_offset = 12;
394 int dst_mask = 0xf << dst_reg_offset;
395 int src_mask = 0xf;
396 int dst_reg = (instr & dst_mask) >> dst_reg_offset;
397 int src_reg = instr & src_mask;
398 uint32_t non_register_mask = ~(dst_mask | src_mask);
399 uint32_t mov_mask = al | 13 << 21;
400
401 // Return <n> if we have a mov rn rn, else return -1.
402 int type = ((instr & non_register_mask) == mov_mask) &&
403 (dst_reg == src_reg) &&
404 (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
405 ? src_reg
406 : -1;
407 ASSERT((type == -1) ||
408 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
409 return type;
410 }
411
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000412
413 // ---------------------------------------------------------------------------
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000414 // Allocation support
415
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000416 // Allocate an object in new space. The object_size is specified
417 // either in bytes or in words if the allocation flag SIZE_IN_WORDS
418 // is passed. If the new space is exhausted control continues at the
419 // gc_required label. The allocated object is returned in result. If
420 // the flag tag_allocated_object is true the result is tagged as as
421 // a heap object. All registers are clobbered also when control
422 // continues at the gc_required label.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000423 void AllocateInNewSpace(int object_size,
424 Register result,
425 Register scratch1,
426 Register scratch2,
427 Label* gc_required,
428 AllocationFlags flags);
429 void AllocateInNewSpace(Register object_size,
430 Register result,
431 Register scratch1,
432 Register scratch2,
433 Label* gc_required,
434 AllocationFlags flags);
ager@chromium.orga1645e22009-09-09 19:27:10 +0000435
436 // Undo allocation in new space. The object passed and objects allocated after
437 // it will no longer be allocated. The caller must make sure that no pointers
438 // are left to the object(s) no longer allocated as they would be invalid when
439 // allocation is undone.
440 void UndoAllocationInNewSpace(Register object, Register scratch);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000441
ager@chromium.org5c838252010-02-19 08:53:10 +0000442
443 void AllocateTwoByteString(Register result,
444 Register length,
445 Register scratch1,
446 Register scratch2,
447 Register scratch3,
448 Label* gc_required);
449 void AllocateAsciiString(Register result,
450 Register length,
451 Register scratch1,
452 Register scratch2,
453 Register scratch3,
454 Label* gc_required);
455 void AllocateTwoByteConsString(Register result,
456 Register length,
457 Register scratch1,
458 Register scratch2,
459 Label* gc_required);
460 void AllocateAsciiConsString(Register result,
461 Register length,
462 Register scratch1,
463 Register scratch2,
464 Label* gc_required);
465
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000466 // Allocates a heap number or jumps to the gc_required label if the young
467 // space is full and a scavenge is needed. All registers are clobbered also
468 // when control continues at the gc_required label.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000469 void AllocateHeapNumber(Register result,
470 Register scratch1,
471 Register scratch2,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000472 Register heap_number_map,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000473 Label* gc_required);
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000474 void AllocateHeapNumberWithValue(Register result,
475 DwVfpRegister value,
476 Register scratch1,
477 Register scratch2,
478 Register heap_number_map,
479 Label* gc_required);
480
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +0000481 // Copies a fixed number of fields of heap objects from src to dst.
482 void CopyFields(Register dst, Register src, RegList temps, int field_count);
ager@chromium.org5c838252010-02-19 08:53:10 +0000483
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000484 // ---------------------------------------------------------------------------
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000485 // Support functions.
486
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000487 // Try to get function prototype of a function and puts the value in
488 // the result register. Checks that the function really is a
489 // function and jumps to the miss label if the fast checks fail. The
490 // function register will be untouched; the other registers may be
491 // clobbered.
492 void TryGetFunctionPrototype(Register function,
493 Register result,
494 Register scratch,
495 Label* miss);
496
497 // Compare object type for heap object. heap_object contains a non-Smi
498 // whose object type should be compared with the given type. This both
499 // sets the flags and leaves the object type in the type_reg register.
500 // It leaves the map in the map register (unless the type_reg and map register
501 // are the same register). It leaves the heap object in the heap_object
502 // register unless the heap_object register is the same register as one of the
ager@chromium.orga1645e22009-09-09 19:27:10 +0000503 // other registers.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000504 void CompareObjectType(Register heap_object,
505 Register map,
506 Register type_reg,
507 InstanceType type);
508
ager@chromium.orga1645e22009-09-09 19:27:10 +0000509 // Compare instance type in a map. map contains a valid map object whose
510 // object type should be compared with the given type. This both
511 // sets the flags and leaves the object type in the type_reg register. It
512 // leaves the heap object in the heap_object register unless the heap_object
513 // register is the same register as type_reg.
514 void CompareInstanceType(Register map,
515 Register type_reg,
516 InstanceType type);
517
ager@chromium.org5c838252010-02-19 08:53:10 +0000518
ager@chromium.org2cc82ae2010-06-14 07:35:38 +0000519 // Check if the map of an object is equal to a specified map (either
520 // given directly or as an index into the root list) and branch to
521 // label if not. Skip the smi check if not required (object is known
522 // to be a heap object)
ager@chromium.org5c838252010-02-19 08:53:10 +0000523 void CheckMap(Register obj,
524 Register scratch,
525 Handle<Map> map,
526 Label* fail,
527 bool is_heap_object);
528
ager@chromium.org2cc82ae2010-06-14 07:35:38 +0000529 void CheckMap(Register obj,
530 Register scratch,
531 Heap::RootListIndex index,
532 Label* fail,
533 bool is_heap_object);
534
535
ager@chromium.org5c838252010-02-19 08:53:10 +0000536 // Load and check the instance type of an object for being a string.
537 // Loads the type into the second argument register.
538 // Returns a condition that will be enabled if the object was a string.
539 Condition IsObjectStringType(Register obj,
540 Register type) {
541 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset));
542 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
543 tst(type, Operand(kIsNotStringMask));
544 ASSERT_EQ(0, kStringTag);
545 return eq;
546 }
547
548
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000549 // Generates code for reporting that an illegal operation has
550 // occurred.
551 void IllegalOperation(int num_arguments);
552
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000553 // Picks out an array index from the hash field.
554 // Register use:
555 // hash - holds the index's hash. Clobbered.
556 // index - holds the overwritten index on exit.
557 void IndexFromHash(Register hash, Register index);
558
ager@chromium.org5c838252010-02-19 08:53:10 +0000559 // Get the number of least significant bits from a register
560 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
561
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000562 // Uses VFP instructions to Convert a Smi to a double.
563 void IntegerToDoubleConversionWithVFP3(Register inReg,
564 Register outHighReg,
565 Register outLowReg);
566
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000567 // Load the value of a number object into a VFP double register. If the object
568 // is not a number a jump to the label not_number is performed and the VFP
569 // double register is unchanged.
570 void ObjectToDoubleVFPRegister(
571 Register object,
572 DwVfpRegister value,
573 Register scratch1,
574 Register scratch2,
575 Register heap_number_map,
576 SwVfpRegister scratch3,
577 Label* not_number,
578 ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
579
580 // Load the value of a smi object into a VFP double register. The register
581 // scratch1 can be the same register as smi in which case smi will hold the
582 // untagged value afterwards.
583 void SmiToDoubleVFPRegister(Register smi,
584 DwVfpRegister value,
585 Register scratch1,
586 SwVfpRegister scratch2);
587
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000588 // Convert the HeapNumber pointed to by source to a 32bits signed integer
589 // dest. If the HeapNumber does not fit into a 32bits signed integer branch
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000590 // to not_int32 label. If VFP3 is available double_scratch is used but not
591 // scratch2.
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000592 void ConvertToInt32(Register source,
593 Register dest,
594 Register scratch,
595 Register scratch2,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000596 DwVfpRegister double_scratch,
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000597 Label *not_int32);
598
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000599 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz
600 // instruction. On pre-ARM5 hardware this routine gives the wrong answer
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000601 // for 0 (31 instead of 32). Source and scratch can be the same in which case
602 // the source is clobbered. Source and zeros can also be the same in which
603 // case scratch should be a different register.
604 void CountLeadingZeros(Register zeros,
605 Register source,
606 Register scratch);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000607
608 // ---------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000609 // Runtime calls
610
611 // Call a code stub.
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000612 void CallStub(CodeStub* stub, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000613
ager@chromium.org5c838252010-02-19 08:53:10 +0000614 // Call a code stub.
615 void TailCallStub(CodeStub* stub, Condition cond = al);
616
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000617 // Tail call a code stub (jump) and return the code object called. Try to
618 // generate the code if necessary. Do not perform a GC but instead return
619 // a retry after GC failure.
620 MUST_USE_RESULT MaybeObject* TryTailCallStub(CodeStub* stub,
621 Condition cond = al);
622
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000623 // Call a runtime routine.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000624 void CallRuntime(Runtime::Function* f, int num_arguments);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000625 void CallRuntimeSaveDoubles(Runtime::FunctionId id);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000626
627 // Convenience function: Same as above, but takes the fid instead.
628 void CallRuntime(Runtime::FunctionId fid, int num_arguments);
629
ager@chromium.org5c838252010-02-19 08:53:10 +0000630 // Convenience function: call an external reference.
631 void CallExternalReference(const ExternalReference& ext,
632 int num_arguments);
633
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000634 // Tail call of a runtime routine (jump).
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000635 // Like JumpToExternalReference, but also takes care of passing the number
mads.s.ager31e71382008-08-13 09:32:07 +0000636 // of parameters.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000637 void TailCallExternalReference(const ExternalReference& ext,
638 int num_arguments,
639 int result_size);
640
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000641 // Tail call of a runtime routine (jump). Try to generate the code if
642 // necessary. Do not perform a GC but instead return a retry after GC
643 // failure.
644 MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
645 const ExternalReference& ext, int num_arguments, int result_size);
646
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000647 // Convenience function: tail call a runtime routine (jump).
648 void TailCallRuntime(Runtime::FunctionId fid,
ager@chromium.orga1645e22009-09-09 19:27:10 +0000649 int num_arguments,
650 int result_size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000651
ager@chromium.org357bf652010-04-12 11:30:10 +0000652 // Before calling a C-function from generated code, align arguments on stack.
653 // After aligning the frame, non-register arguments must be stored in
654 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
655 // are word sized.
656 // Some compilers/platforms require the stack to be aligned when calling
657 // C++ code.
658 // Needs a scratch register to do some arithmetic. This register will be
659 // trashed.
660 void PrepareCallCFunction(int num_arguments, Register scratch);
661
662 // Calls a C function and cleans up the space for arguments allocated
663 // by PrepareCallCFunction. The called function is not allowed to trigger a
664 // garbage collection, since that might move the code and invalidate the
665 // return address (unless this is somehow accounted for by the called
666 // function).
667 void CallCFunction(ExternalReference function, int num_arguments);
668 void CallCFunction(Register function, int num_arguments);
669
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000670 // Calls an API function. Allocates HandleScope, extracts returned value
671 // from handle and propagates exceptions. Restores context.
672 // stack_space - space to be unwound on exit (includes the call js
673 // arguments space and the additional space allocated for the fast call).
674 MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function,
675 int stack_space);
676
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000677 // Jump to a runtime routine.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000678 void JumpToExternalReference(const ExternalReference& builtin);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000679
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000680 MaybeObject* TryJumpToExternalReference(const ExternalReference& ext);
681
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000682 // Invoke specified builtin JavaScript function. Adds an entry to
683 // the unresolved list if the name does not resolve.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000684 void InvokeBuiltin(Builtins::JavaScript id,
685 InvokeJSFlags flags,
686 PostCallGenerator* post_call_generator = NULL);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000687
688 // Store the code object for the given builtin in the target register and
689 // setup the function in r1.
690 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000691
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000692 // Store the function for the given builtin in the target register.
693 void GetBuiltinFunction(Register target, Builtins::JavaScript id);
694
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000695 Handle<Object> CodeObject() { return code_object_; }
696
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000697
698 // ---------------------------------------------------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000699 // StatsCounter support
700
701 void SetCounter(StatsCounter* counter, int value,
702 Register scratch1, Register scratch2);
703 void IncrementCounter(StatsCounter* counter, int value,
704 Register scratch1, Register scratch2);
705 void DecrementCounter(StatsCounter* counter, int value,
706 Register scratch1, Register scratch2);
707
708
709 // ---------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000710 // Debugging
711
ager@chromium.org378b34e2011-01-28 08:04:38 +0000712 // Calls Abort(msg) if the condition cond is not satisfied.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713 // Use --debug_code to enable.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000714 void Assert(Condition cond, const char* msg);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000715 void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000716 void AssertFastElements(Register elements);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717
718 // Like Assert(), but always enabled.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000719 void Check(Condition cond, const char* msg);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000720
721 // Print a message to stdout and abort execution.
722 void Abort(const char* msg);
723
724 // Verify restrictions about code generated in stubs.
725 void set_generating_stub(bool value) { generating_stub_ = value; }
726 bool generating_stub() { return generating_stub_; }
kasper.lund7276f142008-07-30 08:49:36 +0000727 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
728 bool allow_stub_calls() { return allow_stub_calls_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000729
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000730 // ---------------------------------------------------------------------------
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000731 // Number utilities
732
733 // Check whether the value of reg is a power of two and not zero. If not
734 // control continues at the label not_power_of_two. If reg is a power of two
735 // the register scratch contains the value of (reg - 1) when control falls
736 // through.
737 void JumpIfNotPowerOfTwoOrZero(Register reg,
738 Register scratch,
739 Label* not_power_of_two_or_zero);
740
741 // ---------------------------------------------------------------------------
ager@chromium.org5c838252010-02-19 08:53:10 +0000742 // Smi utilities
743
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000744 void SmiTag(Register reg, SBit s = LeaveCC) {
745 add(reg, reg, Operand(reg), s);
746 }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000747 void SmiTag(Register dst, Register src, SBit s = LeaveCC) {
748 add(dst, src, Operand(src), s);
749 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000750
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000751 // Try to convert int32 to smi. If the value is to large, preserve
752 // the original value and jump to not_a_smi. Destroys scratch and
753 // sets flags.
754 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) {
755 mov(scratch, reg);
756 SmiTag(scratch, SetCC);
757 b(vs, not_a_smi);
758 mov(reg, scratch);
759 }
760
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000761 void SmiUntag(Register reg) {
762 mov(reg, Operand(reg, ASR, kSmiTagSize));
763 }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000764 void SmiUntag(Register dst, Register src) {
765 mov(dst, Operand(src, ASR, kSmiTagSize));
766 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000767
ager@chromium.org378b34e2011-01-28 08:04:38 +0000768 // Jump the register contains a smi.
769 inline void JumpIfSmi(Register value, Label* smi_label) {
770 tst(value, Operand(kSmiTagMask));
771 b(eq, smi_label);
772 }
773 // Jump if either of the registers contain a non-smi.
774 inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
775 tst(value, Operand(kSmiTagMask));
776 b(ne, not_smi_label);
777 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000778 // Jump if either of the registers contain a non-smi.
779 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
780 // Jump if either of the registers contain a smi.
781 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
782
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000783 // Abort execution if argument is a smi. Used in debug code.
784 void AbortIfSmi(Register object);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000785 void AbortIfNotSmi(Register object);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000786
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000787 // Abort execution if argument is not the root value with the given index.
788 void AbortIfNotRootValue(Register src,
789 Heap::RootListIndex root_value_index,
790 const char* message);
791
ager@chromium.org5c838252010-02-19 08:53:10 +0000792 // ---------------------------------------------------------------------------
ager@chromium.org378b34e2011-01-28 08:04:38 +0000793 // HeapNumber utilities
794
795 void JumpIfNotHeapNumber(Register object,
796 Register heap_number_map,
797 Register scratch,
798 Label* on_not_heap_number);
799
800 // ---------------------------------------------------------------------------
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000801 // String utilities
802
803 // Checks if both objects are sequential ASCII strings and jumps to label
804 // if either is not. Assumes that neither object is a smi.
805 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
806 Register object2,
807 Register scratch1,
808 Register scratch2,
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000809 Label* failure);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000810
811 // Checks if both objects are sequential ASCII strings and jumps to label
812 // if either is not.
813 void JumpIfNotBothSequentialAsciiStrings(Register first,
814 Register second,
815 Register scratch1,
816 Register scratch2,
817 Label* not_flat_ascii_strings);
818
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000819 // Checks if both instance types are sequential ASCII strings and jumps to
820 // label if either is not.
821 void JumpIfBothInstanceTypesAreNotSequentialAscii(
822 Register first_object_instance_type,
823 Register second_object_instance_type,
824 Register scratch1,
825 Register scratch2,
826 Label* failure);
827
828 // Check if instance type is sequential ASCII string and jump to label if
829 // it is not.
830 void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
831 Register scratch,
832 Label* failure);
833
834
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000835 // ---------------------------------------------------------------------------
836 // Patching helpers.
837
838 // Get the location of a relocated constant (its address in the constant pool)
839 // from its load site.
840 void GetRelocatedValueLocation(Register ldr_location,
841 Register result);
842
843
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844 private:
ager@chromium.org5c838252010-02-19 08:53:10 +0000845 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
846 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000847
848 // Helper functions for generating invokes.
849 void InvokePrologue(const ParameterCount& expected,
850 const ParameterCount& actual,
851 Handle<Code> code_constant,
852 Register code_reg,
853 Label* done,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000854 InvokeFlag flag,
855 PostCallGenerator* post_call_generator = NULL);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000856
ager@chromium.org7c537e22008-10-16 08:43:32 +0000857 // Activation support.
858 void EnterFrame(StackFrame::Type type);
859 void LeaveFrame(StackFrame::Type type);
ager@chromium.org5c838252010-02-19 08:53:10 +0000860
ager@chromium.orgac091b72010-05-05 07:34:42 +0000861 void InitializeNewString(Register string,
862 Register length,
863 Heap::RootListIndex map_index,
864 Register scratch1,
865 Register scratch2);
866
ager@chromium.org5c838252010-02-19 08:53:10 +0000867 bool generating_stub_;
868 bool allow_stub_calls_;
869 // This handle will be patched with the code object on installation.
870 Handle<Object> code_object_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871};
872
873
ager@chromium.org4af710e2009-09-15 12:20:11 +0000874#ifdef ENABLE_DEBUGGER_SUPPORT
875// The code patcher is used to patch (typically) small parts of code e.g. for
876// debugging and other types of instrumentation. When using the code patcher
877// the exact number of bytes specified must be emitted. It is not legal to emit
878// relocation information. If any of these constraints are violated it causes
879// an assertion to fail.
880class CodePatcher {
881 public:
882 CodePatcher(byte* address, int instructions);
883 virtual ~CodePatcher();
884
885 // Macro assembler to emit code.
886 MacroAssembler* masm() { return &masm_; }
887
888 // Emit an instruction directly.
889 void Emit(Instr x);
890
891 // Emit an address directly.
892 void Emit(Address addr);
893
894 private:
895 byte* address_; // The address of the code being patched.
896 int instructions_; // Number of instructions of the expected patch size.
897 int size_; // Number of bytes of the expected patch size.
898 MacroAssembler masm_; // Macro assembler used to generate the code.
899};
900#endif // ENABLE_DEBUGGER_SUPPORT
901
902
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000903// Helper class for generating code or data associated with the code
904// right after a call instruction. As an example this can be used to
905// generate safepoint data after calls for crankshaft.
906class PostCallGenerator {
907 public:
908 PostCallGenerator() { }
909 virtual ~PostCallGenerator() { }
910 virtual void Generate() = 0;
911};
912
913
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000914// -----------------------------------------------------------------------------
915// Static helper functions.
916
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000917static MemOperand ContextOperand(Register context, int index) {
918 return MemOperand(context, Context::SlotOffset(index));
919}
920
921
922static inline MemOperand GlobalObjectOperand() {
923 return ContextOperand(cp, Context::GLOBAL_INDEX);
924}
925
926
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000927#ifdef GENERATED_CODE_COVERAGE
928#define CODE_COVERAGE_STRINGIFY(x) #x
929#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
930#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
931#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
932#else
933#define ACCESS_MASM(masm) masm->
934#endif
935
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000936
937} } // namespace v8::internal
938
ager@chromium.org5ec48922009-05-05 07:25:34 +0000939#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_