blob: 2ec7a39eab9d241f67215b18ac5192efa501556d [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
2// 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
28#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
29#define V8_ARM_MACRO_ASSEMBLER_ARM_H_
30
31#include "assembler.h"
32
33namespace v8 {
34namespace internal {
35
Andrei Popescu31002712010-02-23 13:46:05 +000036// ----------------------------------------------------------------------------
37// Static helper functions
38
39// Generate a MemOperand for loading a field from an object.
40static inline MemOperand FieldMemOperand(Register object, int offset) {
41 return MemOperand(object, offset - kHeapObjectTag);
42}
43
Steve Blocka7e24c12009-10-30 11:49:00 +000044
45// Give alias names to registers
46const Register cp = { 8 }; // JavaScript context pointer
Andrei Popescu31002712010-02-23 13:46:05 +000047const Register roots = { 10 }; // Roots array pointer.
Steve Blocka7e24c12009-10-30 11:49:00 +000048
49enum InvokeJSFlags {
50 CALL_JS,
51 JUMP_JS
52};
53
54
55// MacroAssembler implements a collection of frequently used macros.
56class MacroAssembler: public Assembler {
57 public:
58 MacroAssembler(void* buffer, int size);
59
Andrei Popescu31002712010-02-23 13:46:05 +000060 // Jump, Call, and Ret pseudo instructions implementing inter-working.
Steve Blocka7e24c12009-10-30 11:49:00 +000061 void Jump(Register target, Condition cond = al);
62 void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al);
63 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
64 void Call(Register target, Condition cond = al);
65 void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
66 void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
67 void Ret(Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +000068
69 // Emit code to discard a non-negative number of pointer-sized elements
70 // from the stack, clobbering only the sp register.
71 void Drop(int count, Condition cond = al);
72
Steve Block6ded16b2010-05-10 14:33:55 +010073
74 // Swap two registers. If the scratch register is omitted then a slightly
75 // less efficient form using xor instead of mov is emitted.
76 void Swap(Register reg1, Register reg2, Register scratch = no_reg);
77
Leon Clarkee46be812010-01-19 14:06:41 +000078 void Call(Label* target);
79 void Move(Register dst, Handle<Object> value);
Steve Block6ded16b2010-05-10 14:33:55 +010080 // May do nothing if the registers are identical.
81 void Move(Register dst, Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +000082 // Jumps to the label at the index given by the Smi in "index".
83 void SmiJumpTable(Register index, Vector<Label*> targets);
84 // Load an object from the root table.
85 void LoadRoot(Register destination,
86 Heap::RootListIndex index,
87 Condition cond = al);
88
Steve Block6ded16b2010-05-10 14:33:55 +010089
90 // Check if object is in new space.
91 // scratch can be object itself, but it will be clobbered.
92 void InNewSpace(Register object,
93 Register scratch,
94 Condition cc, // eq for new space, ne otherwise
95 Label* branch);
96
97
98 // Set the remebered set bit for an offset into an
99 // object. RecordWriteHelper only works if the object is not in new
100 // space.
101 void RecordWriteHelper(Register object, Register offset, Register scracth);
102
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 // Sets the remembered set bit for [address+offset], where address is the
104 // address of the heap object 'object'. The address must be in the first 8K
105 // of an allocated page. The 'scratch' register is used in the
106 // implementation and all 3 registers are clobbered by the operation, as
107 // well as the ip register.
108 void RecordWrite(Register object, Register offset, Register scratch);
109
Steve Block6ded16b2010-05-10 14:33:55 +0100110 // Push two registers. Pushes leftmost register first (to highest address).
111 void Push(Register src1, Register src2, Condition cond = al) {
112 ASSERT(!src1.is(src2));
113 if (src1.code() > src2.code()) {
114 stm(db_w, sp, src1.bit() | src2.bit(), cond);
115 } else {
116 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
117 str(src2, MemOperand(sp, 4, NegPreIndex), cond);
118 }
119 }
120
121 // Push three registers. Pushes leftmost register first (to highest address).
122 void Push(Register src1, Register src2, Register src3, Condition cond = al) {
123 ASSERT(!src1.is(src2));
124 ASSERT(!src2.is(src3));
125 ASSERT(!src1.is(src3));
126 if (src1.code() > src2.code()) {
127 if (src2.code() > src3.code()) {
128 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
129 } else {
130 stm(db_w, sp, src1.bit() | src2.bit(), cond);
131 str(src3, MemOperand(sp, 4, NegPreIndex), cond);
132 }
133 } else {
134 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
135 Push(src2, src3, cond);
136 }
137 }
138
139 // Push four registers. Pushes leftmost register first (to highest address).
140 void Push(Register src1, Register src2,
141 Register src3, Register src4, Condition cond = al) {
142 ASSERT(!src1.is(src2));
143 ASSERT(!src2.is(src3));
144 ASSERT(!src1.is(src3));
145 ASSERT(!src1.is(src4));
146 ASSERT(!src2.is(src4));
147 ASSERT(!src3.is(src4));
148 if (src1.code() > src2.code()) {
149 if (src2.code() > src3.code()) {
150 if (src3.code() > src4.code()) {
151 stm(db_w,
152 sp,
153 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
154 cond);
155 } else {
156 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
157 str(src4, MemOperand(sp, 4, NegPreIndex), cond);
158 }
159 } else {
160 stm(db_w, sp, src1.bit() | src2.bit(), cond);
161 Push(src3, src4, cond);
162 }
163 } else {
164 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
165 Push(src2, src3, src4, cond);
166 }
167 }
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 // ---------------------------------------------------------------------------
Steve Blockd0582a62009-12-15 09:54:21 +0000170 // Stack limit support
171
172 void StackLimitCheck(Label* on_stack_limit_hit);
173
174 // ---------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 // Activation frames
176
177 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
178 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
179
180 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
181 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
182
Steve Blockd0582a62009-12-15 09:54:21 +0000183 // Enter specific kind of exit frame; either normal or debug mode.
184 // Expects the number of arguments in register r0 and
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 // the builtin function to call in register r1. Exits with argc in
186 // r4, argv in r6, and and the builtin function to call in r5.
Steve Blockd0582a62009-12-15 09:54:21 +0000187 void EnterExitFrame(ExitFrame::Mode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000188
189 // Leave the current exit frame. Expects the return value in r0.
Steve Blockd0582a62009-12-15 09:54:21 +0000190 void LeaveExitFrame(ExitFrame::Mode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000191
Steve Block6ded16b2010-05-10 14:33:55 +0100192 // Get the actual activation frame alignment for target environment.
193 static int ActivationFrameAlignment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000194
Steve Blockd0582a62009-12-15 09:54:21 +0000195 void LoadContext(Register dst, int context_chain_length);
196
Steve Blocka7e24c12009-10-30 11:49:00 +0000197 // ---------------------------------------------------------------------------
198 // JavaScript invokes
199
200 // Invoke the JavaScript function code by either calling or jumping.
201 void InvokeCode(Register code,
202 const ParameterCount& expected,
203 const ParameterCount& actual,
204 InvokeFlag flag);
205
206 void InvokeCode(Handle<Code> code,
207 const ParameterCount& expected,
208 const ParameterCount& actual,
209 RelocInfo::Mode rmode,
210 InvokeFlag flag);
211
212 // Invoke the JavaScript function in the given register. Changes the
213 // current context to the context in the function before invoking.
214 void InvokeFunction(Register function,
215 const ParameterCount& actual,
216 InvokeFlag flag);
217
Andrei Popescu402d9372010-02-26 13:31:12 +0000218 void InvokeFunction(JSFunction* function,
219 const ParameterCount& actual,
220 InvokeFlag flag);
221
Steve Blocka7e24c12009-10-30 11:49:00 +0000222
223#ifdef ENABLE_DEBUGGER_SUPPORT
224 // ---------------------------------------------------------------------------
225 // Debugger Support
226
227 void SaveRegistersToMemory(RegList regs);
228 void RestoreRegistersFromMemory(RegList regs);
229 void CopyRegistersFromMemoryToStack(Register base, RegList regs);
230 void CopyRegistersFromStackToMemory(Register base,
231 Register scratch,
232 RegList regs);
Andrei Popescu402d9372010-02-26 13:31:12 +0000233 void DebugBreak();
Steve Blocka7e24c12009-10-30 11:49:00 +0000234#endif
235
236 // ---------------------------------------------------------------------------
237 // Exception handling
238
239 // Push a new try handler and link into try handler chain.
240 // The return address must be passed in register lr.
241 // On exit, r0 contains TOS (code slot).
242 void PushTryHandler(CodeLocation try_location, HandlerType type);
243
Leon Clarkee46be812010-01-19 14:06:41 +0000244 // Unlink the stack handler on top of the stack from the try handler chain.
245 // Must preserve the result register.
246 void PopTryHandler();
Steve Blocka7e24c12009-10-30 11:49:00 +0000247
248 // ---------------------------------------------------------------------------
249 // Inline caching support
250
251 // Generates code that verifies that the maps of objects in the
252 // prototype chain of object hasn't changed since the code was
253 // generated and branches to the miss label if any map has. If
254 // necessary the function also generates code for security check
255 // in case of global object holders. The scratch and holder
256 // registers are always clobbered, but the object register is only
257 // clobbered if it the same as the holder register. The function
258 // returns a register containing the holder - either object_reg or
259 // holder_reg.
Steve Block6ded16b2010-05-10 14:33:55 +0100260 // The function can optionally (when save_at_depth !=
261 // kInvalidProtoDepth) save the object at the given depth by moving
262 // it to [sp].
Steve Blocka7e24c12009-10-30 11:49:00 +0000263 Register CheckMaps(JSObject* object, Register object_reg,
264 JSObject* holder, Register holder_reg,
Steve Block6ded16b2010-05-10 14:33:55 +0100265 Register scratch,
266 int save_at_depth,
267 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000268
269 // Generate code for checking access rights - used for security checks
270 // on access to global objects across environments. The holder register
271 // is left untouched, whereas both scratch registers are clobbered.
272 void CheckAccessGlobalProxy(Register holder_reg,
273 Register scratch,
274 Label* miss);
275
276
277 // ---------------------------------------------------------------------------
278 // Allocation support
279
280 // Allocate an object in new space. The object_size is specified in words (not
281 // bytes). If the new space is exhausted control continues at the gc_required
282 // label. The allocated object is returned in result. If the flag
283 // tag_allocated_object is true the result is tagged as as a heap object.
284 void AllocateInNewSpace(int object_size,
285 Register result,
286 Register scratch1,
287 Register scratch2,
288 Label* gc_required,
289 AllocationFlags flags);
290 void AllocateInNewSpace(Register object_size,
291 Register result,
292 Register scratch1,
293 Register scratch2,
294 Label* gc_required,
295 AllocationFlags flags);
296
297 // Undo allocation in new space. The object passed and objects allocated after
298 // it will no longer be allocated. The caller must make sure that no pointers
299 // are left to the object(s) no longer allocated as they would be invalid when
300 // allocation is undone.
301 void UndoAllocationInNewSpace(Register object, Register scratch);
302
Andrei Popescu31002712010-02-23 13:46:05 +0000303
304 void AllocateTwoByteString(Register result,
305 Register length,
306 Register scratch1,
307 Register scratch2,
308 Register scratch3,
309 Label* gc_required);
310 void AllocateAsciiString(Register result,
311 Register length,
312 Register scratch1,
313 Register scratch2,
314 Register scratch3,
315 Label* gc_required);
316 void AllocateTwoByteConsString(Register result,
317 Register length,
318 Register scratch1,
319 Register scratch2,
320 Label* gc_required);
321 void AllocateAsciiConsString(Register result,
322 Register length,
323 Register scratch1,
324 Register scratch2,
325 Label* gc_required);
326
Steve Block6ded16b2010-05-10 14:33:55 +0100327 // Allocates a heap number or jumps to the need_gc label if the young space
328 // is full and a scavenge is needed.
329 void AllocateHeapNumber(Register result,
330 Register scratch1,
331 Register scratch2,
332 Label* gc_required);
Andrei Popescu31002712010-02-23 13:46:05 +0000333
Steve Blocka7e24c12009-10-30 11:49:00 +0000334 // ---------------------------------------------------------------------------
335 // Support functions.
336
337 // Try to get function prototype of a function and puts the value in
338 // the result register. Checks that the function really is a
339 // function and jumps to the miss label if the fast checks fail. The
340 // function register will be untouched; the other registers may be
341 // clobbered.
342 void TryGetFunctionPrototype(Register function,
343 Register result,
344 Register scratch,
345 Label* miss);
346
347 // Compare object type for heap object. heap_object contains a non-Smi
348 // whose object type should be compared with the given type. This both
349 // sets the flags and leaves the object type in the type_reg register.
350 // It leaves the map in the map register (unless the type_reg and map register
351 // are the same register). It leaves the heap object in the heap_object
352 // register unless the heap_object register is the same register as one of the
353 // other registers.
354 void CompareObjectType(Register heap_object,
355 Register map,
356 Register type_reg,
357 InstanceType type);
358
359 // Compare instance type in a map. map contains a valid map object whose
360 // object type should be compared with the given type. This both
361 // sets the flags and leaves the object type in the type_reg register. It
362 // leaves the heap object in the heap_object register unless the heap_object
363 // register is the same register as type_reg.
364 void CompareInstanceType(Register map,
365 Register type_reg,
366 InstanceType type);
367
Andrei Popescu31002712010-02-23 13:46:05 +0000368
369 // Check if the map of an object is equal to a specified map and
370 // branch to label if not. Skip the smi check if not required
371 // (object is known to be a heap object)
372 void CheckMap(Register obj,
373 Register scratch,
374 Handle<Map> map,
375 Label* fail,
376 bool is_heap_object);
377
378 // Load and check the instance type of an object for being a string.
379 // Loads the type into the second argument register.
380 // Returns a condition that will be enabled if the object was a string.
381 Condition IsObjectStringType(Register obj,
382 Register type) {
383 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset));
384 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
385 tst(type, Operand(kIsNotStringMask));
386 ASSERT_EQ(0, kStringTag);
387 return eq;
388 }
389
390
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 inline void BranchOnSmi(Register value, Label* smi_label) {
392 tst(value, Operand(kSmiTagMask));
393 b(eq, smi_label);
394 }
395
396 inline void BranchOnNotSmi(Register value, Label* not_smi_label) {
397 tst(value, Operand(kSmiTagMask));
398 b(ne, not_smi_label);
399 }
400
401 // Generates code for reporting that an illegal operation has
402 // occurred.
403 void IllegalOperation(int num_arguments);
404
Andrei Popescu31002712010-02-23 13:46:05 +0000405 // Get the number of least significant bits from a register
406 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
407
Steve Blockd0582a62009-12-15 09:54:21 +0000408 // Uses VFP instructions to Convert a Smi to a double.
409 void IntegerToDoubleConversionWithVFP3(Register inReg,
410 Register outHighReg,
411 Register outLowReg);
412
Steve Block6ded16b2010-05-10 14:33:55 +0100413 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz
414 // instruction. On pre-ARM5 hardware this routine gives the wrong answer
415 // for 0 (31 instead of 32).
416 void CountLeadingZeros(Register source,
417 Register scratch,
418 Register zeros);
Steve Blocka7e24c12009-10-30 11:49:00 +0000419
420 // ---------------------------------------------------------------------------
421 // Runtime calls
422
423 // Call a code stub.
424 void CallStub(CodeStub* stub, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000425
Andrei Popescu31002712010-02-23 13:46:05 +0000426 // Call a code stub.
427 void TailCallStub(CodeStub* stub, Condition cond = al);
428
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 // Return from a code stub after popping its arguments.
430 void StubReturn(int argc);
431
432 // Call a runtime routine.
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 void CallRuntime(Runtime::Function* f, int num_arguments);
434
435 // Convenience function: Same as above, but takes the fid instead.
436 void CallRuntime(Runtime::FunctionId fid, int num_arguments);
437
Andrei Popescu402d9372010-02-26 13:31:12 +0000438 // Convenience function: call an external reference.
439 void CallExternalReference(const ExternalReference& ext,
440 int num_arguments);
441
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 // Tail call of a runtime routine (jump).
Steve Block6ded16b2010-05-10 14:33:55 +0100443 // Like JumpToExternalReference, but also takes care of passing the number
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 // of parameters.
Steve Block6ded16b2010-05-10 14:33:55 +0100445 void TailCallExternalReference(const ExternalReference& ext,
446 int num_arguments,
447 int result_size);
448
449 // Convenience function: tail call a runtime routine (jump).
450 void TailCallRuntime(Runtime::FunctionId fid,
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 int num_arguments,
452 int result_size);
453
Steve Block6ded16b2010-05-10 14:33:55 +0100454 // Before calling a C-function from generated code, align arguments on stack.
455 // After aligning the frame, non-register arguments must be stored in
456 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
457 // are word sized.
458 // Some compilers/platforms require the stack to be aligned when calling
459 // C++ code.
460 // Needs a scratch register to do some arithmetic. This register will be
461 // trashed.
462 void PrepareCallCFunction(int num_arguments, Register scratch);
463
464 // Calls a C function and cleans up the space for arguments allocated
465 // by PrepareCallCFunction. The called function is not allowed to trigger a
466 // garbage collection, since that might move the code and invalidate the
467 // return address (unless this is somehow accounted for by the called
468 // function).
469 void CallCFunction(ExternalReference function, int num_arguments);
470 void CallCFunction(Register function, int num_arguments);
471
Steve Blocka7e24c12009-10-30 11:49:00 +0000472 // Jump to a runtime routine.
Steve Block6ded16b2010-05-10 14:33:55 +0100473 void JumpToExternalReference(const ExternalReference& builtin);
Steve Blocka7e24c12009-10-30 11:49:00 +0000474
475 // Invoke specified builtin JavaScript function. Adds an entry to
476 // the unresolved list if the name does not resolve.
477 void InvokeBuiltin(Builtins::JavaScript id, InvokeJSFlags flags);
478
479 // Store the code object for the given builtin in the target register and
480 // setup the function in r1.
481 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
482
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 Handle<Object> CodeObject() { return code_object_; }
484
485
486 // ---------------------------------------------------------------------------
487 // StatsCounter support
488
489 void SetCounter(StatsCounter* counter, int value,
490 Register scratch1, Register scratch2);
491 void IncrementCounter(StatsCounter* counter, int value,
492 Register scratch1, Register scratch2);
493 void DecrementCounter(StatsCounter* counter, int value,
494 Register scratch1, Register scratch2);
495
496
497 // ---------------------------------------------------------------------------
498 // Debugging
499
500 // Calls Abort(msg) if the condition cc is not satisfied.
501 // Use --debug_code to enable.
502 void Assert(Condition cc, const char* msg);
503
504 // Like Assert(), but always enabled.
505 void Check(Condition cc, const char* msg);
506
507 // Print a message to stdout and abort execution.
508 void Abort(const char* msg);
509
510 // Verify restrictions about code generated in stubs.
511 void set_generating_stub(bool value) { generating_stub_ = value; }
512 bool generating_stub() { return generating_stub_; }
513 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
514 bool allow_stub_calls() { return allow_stub_calls_; }
515
Leon Clarked91b9f72010-01-27 17:25:45 +0000516 // ---------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000517 // Smi utilities
518
519 // Jump if either of the registers contain a non-smi.
520 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
521 // Jump if either of the registers contain a smi.
522 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
523
524 // ---------------------------------------------------------------------------
Leon Clarked91b9f72010-01-27 17:25:45 +0000525 // String utilities
526
527 // Checks if both objects are sequential ASCII strings and jumps to label
528 // if either is not. Assumes that neither object is a smi.
529 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
530 Register object2,
531 Register scratch1,
532 Register scratch2,
Steve Block6ded16b2010-05-10 14:33:55 +0100533 Label* failure);
Leon Clarked91b9f72010-01-27 17:25:45 +0000534
535 // Checks if both objects are sequential ASCII strings and jumps to label
536 // if either is not.
537 void JumpIfNotBothSequentialAsciiStrings(Register first,
538 Register second,
539 Register scratch1,
540 Register scratch2,
541 Label* not_flat_ascii_strings);
542
Steve Block6ded16b2010-05-10 14:33:55 +0100543 // Checks if both instance types are sequential ASCII strings and jumps to
544 // label if either is not.
545 void JumpIfBothInstanceTypesAreNotSequentialAscii(
546 Register first_object_instance_type,
547 Register second_object_instance_type,
548 Register scratch1,
549 Register scratch2,
550 Label* failure);
551
552 // Check if instance type is sequential ASCII string and jump to label if
553 // it is not.
554 void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
555 Register scratch,
556 Label* failure);
557
558
Steve Blocka7e24c12009-10-30 11:49:00 +0000559 private:
Andrei Popescu31002712010-02-23 13:46:05 +0000560 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
561 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000562
563 // Helper functions for generating invokes.
564 void InvokePrologue(const ParameterCount& expected,
565 const ParameterCount& actual,
566 Handle<Code> code_constant,
567 Register code_reg,
568 Label* done,
569 InvokeFlag flag);
570
Steve Blocka7e24c12009-10-30 11:49:00 +0000571 // Activation support.
572 void EnterFrame(StackFrame::Type type);
573 void LeaveFrame(StackFrame::Type type);
Andrei Popescu31002712010-02-23 13:46:05 +0000574
Steve Block6ded16b2010-05-10 14:33:55 +0100575 void InitializeNewString(Register string,
576 Register length,
577 Heap::RootListIndex map_index,
578 Register scratch1,
579 Register scratch2);
580
Andrei Popescu31002712010-02-23 13:46:05 +0000581 bool generating_stub_;
582 bool allow_stub_calls_;
583 // This handle will be patched with the code object on installation.
584 Handle<Object> code_object_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000585};
586
587
588#ifdef ENABLE_DEBUGGER_SUPPORT
589// The code patcher is used to patch (typically) small parts of code e.g. for
590// debugging and other types of instrumentation. When using the code patcher
591// the exact number of bytes specified must be emitted. It is not legal to emit
592// relocation information. If any of these constraints are violated it causes
593// an assertion to fail.
594class CodePatcher {
595 public:
596 CodePatcher(byte* address, int instructions);
597 virtual ~CodePatcher();
598
599 // Macro assembler to emit code.
600 MacroAssembler* masm() { return &masm_; }
601
602 // Emit an instruction directly.
603 void Emit(Instr x);
604
605 // Emit an address directly.
606 void Emit(Address addr);
607
608 private:
609 byte* address_; // The address of the code being patched.
610 int instructions_; // Number of instructions of the expected patch size.
611 int size_; // Number of bytes of the expected patch size.
612 MacroAssembler masm_; // Macro assembler used to generate the code.
613};
614#endif // ENABLE_DEBUGGER_SUPPORT
615
616
617// -----------------------------------------------------------------------------
618// Static helper functions.
619
Steve Blocka7e24c12009-10-30 11:49:00 +0000620#ifdef GENERATED_CODE_COVERAGE
621#define CODE_COVERAGE_STRINGIFY(x) #x
622#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
623#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
624#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
625#else
626#define ACCESS_MASM(masm) masm->
627#endif
628
629
630} } // namespace v8::internal
631
632#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_