blob: a7534cbd47bf2c8ac796a1af2420e7db92d8287d [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_IA32_MACRO_ASSEMBLER_IA32_H_
29#define V8_IA32_MACRO_ASSEMBLER_IA32_H_
30
31#include "assembler.h"
Iain Merrick75681382010-08-19 15:07:18 +010032#include "type-info.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033
34namespace v8 {
35namespace internal {
36
Kristian Monsen25f61362010-05-21 11:50:48 +010037// Flags used for the AllocateInNewSpace functions.
38enum AllocationFlags {
39 // No special flags.
40 NO_ALLOCATION_FLAGS = 0,
41 // Return the pointer to the allocated already tagged as a heap object.
42 TAG_OBJECT = 1 << 0,
43 // The content of the result register already contains the allocation top in
44 // new space.
45 RESULT_CONTAINS_TOP = 1 << 1
46};
47
Leon Clarkee46be812010-01-19 14:06:41 +000048// Convenience for platform-independent signatures. We do not normally
49// distinguish memory operands from other operands on ia32.
50typedef Operand MemOperand;
51
Steve Blocka7e24c12009-10-30 11:49:00 +000052// Forward declaration.
53class JumpTarget;
54
Steve Blocka7e24c12009-10-30 11:49:00 +000055// MacroAssembler implements a collection of frequently used macros.
56class MacroAssembler: public Assembler {
57 public:
58 MacroAssembler(void* buffer, int size);
59
60 // ---------------------------------------------------------------------------
61 // GC Support
62
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010063 // For page containing |object| mark region covering |addr| dirty.
64 // RecordWriteHelper only works if the object is not in new
Steve Block6ded16b2010-05-10 14:33:55 +010065 // space.
66 void RecordWriteHelper(Register object,
67 Register addr,
68 Register scratch);
69
70 // Check if object is in new space.
71 // scratch can be object itself, but it will be clobbered.
72 void InNewSpace(Register object,
73 Register scratch,
74 Condition cc, // equal for new space, not_equal otherwise.
75 Label* branch);
76
Steve Block8defd9f2010-07-08 12:39:36 +010077 // For page containing |object| mark region covering [object+offset]
78 // dirty. |object| is the object being stored into, |value| is the
79 // object being stored. If offset is zero, then the scratch register
80 // contains the array index into the elements array represented as a
81 // Smi. All registers are clobbered by the operation. RecordWrite
82 // filters out smis so it does not update the write barrier if the
83 // value is a smi.
Steve Blocka7e24c12009-10-30 11:49:00 +000084 void RecordWrite(Register object,
85 int offset,
86 Register value,
87 Register scratch);
88
Steve Block8defd9f2010-07-08 12:39:36 +010089 // For page containing |object| mark region covering |address|
90 // dirty. |object| is the object being stored into, |value| is the
91 // object being stored. All registers are clobbered by the
92 // operation. RecordWrite filters out smis so it does not update the
93 // write barrier if the value is a smi.
94 void RecordWrite(Register object,
95 Register address,
96 Register value);
97
Steve Blocka7e24c12009-10-30 11:49:00 +000098#ifdef ENABLE_DEBUGGER_SUPPORT
99 // ---------------------------------------------------------------------------
100 // Debugger Support
101
Andrei Popescu402d9372010-02-26 13:31:12 +0000102 void DebugBreak();
Steve Blocka7e24c12009-10-30 11:49:00 +0000103#endif
104
105 // ---------------------------------------------------------------------------
Steve Blockd0582a62009-12-15 09:54:21 +0000106 // Stack limit support
107
108 // Do simple test for stack overflow. This doesn't handle an overflow.
109 void StackLimitCheck(Label* on_stack_limit_hit);
110
111 // ---------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000112 // Activation frames
113
114 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
115 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
116
117 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
118 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
119
Steve Blockd0582a62009-12-15 09:54:21 +0000120 // Enter specific kind of exit frame; either in normal or debug mode.
121 // Expects the number of arguments in register eax and
Steve Blocka7e24c12009-10-30 11:49:00 +0000122 // sets up the number of arguments in register edi and the pointer
123 // to the first argument in register esi.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100124 void EnterExitFrame();
Steve Blockd0582a62009-12-15 09:54:21 +0000125
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100126 void EnterApiExitFrame(int stack_space, int argc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000127
128 // Leave the current exit frame. Expects the return value in
129 // register eax:edx (untouched) and the pointer to the first
130 // argument in register esi.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100131 void LeaveExitFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000132
Steve Blockd0582a62009-12-15 09:54:21 +0000133 // Find the function context up the context chain.
134 void LoadContext(Register dst, int context_chain_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000135
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100136 // Load the global function with the given index.
137 void LoadGlobalFunction(int index, Register function);
138
139 // Load the initial map from the global function. The registers
140 // function and map can be the same.
141 void LoadGlobalFunctionInitialMap(Register function, Register map);
142
Steve Blocka7e24c12009-10-30 11:49:00 +0000143 // ---------------------------------------------------------------------------
144 // JavaScript invokes
145
146 // Invoke the JavaScript function code by either calling or jumping.
147 void InvokeCode(const Operand& code,
148 const ParameterCount& expected,
149 const ParameterCount& actual,
150 InvokeFlag flag);
151
152 void InvokeCode(Handle<Code> code,
153 const ParameterCount& expected,
154 const ParameterCount& actual,
155 RelocInfo::Mode rmode,
156 InvokeFlag flag);
157
158 // Invoke the JavaScript function in the given register. Changes the
159 // current context to the context in the function before invoking.
160 void InvokeFunction(Register function,
161 const ParameterCount& actual,
162 InvokeFlag flag);
163
Andrei Popescu402d9372010-02-26 13:31:12 +0000164 void InvokeFunction(JSFunction* function,
165 const ParameterCount& actual,
166 InvokeFlag flag);
167
Steve Blocka7e24c12009-10-30 11:49:00 +0000168 // Invoke specified builtin JavaScript function. Adds an entry to
169 // the unresolved list if the name does not resolve.
170 void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
171
Steve Block791712a2010-08-27 10:21:07 +0100172 // Store the function for the given builtin in the target register.
173 void GetBuiltinFunction(Register target, Builtins::JavaScript id);
174
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 // Store the code object for the given builtin in the target register.
176 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
177
178 // Expression support
179 void Set(Register dst, const Immediate& x);
180 void Set(const Operand& dst, const Immediate& x);
181
182 // Compare object type for heap object.
183 // Incoming register is heap_object and outgoing register is map.
184 void CmpObjectType(Register heap_object, InstanceType type, Register map);
185
186 // Compare instance type for map.
187 void CmpInstanceType(Register map, InstanceType type);
188
Andrei Popescu31002712010-02-23 13:46:05 +0000189 // Check if the map of an object is equal to a specified map and
190 // branch to label if not. Skip the smi check if not required
191 // (object is known to be a heap object)
192 void CheckMap(Register obj,
193 Handle<Map> map,
194 Label* fail,
195 bool is_heap_object);
196
Leon Clarkee46be812010-01-19 14:06:41 +0000197 // Check if the object in register heap_object is a string. Afterwards the
198 // register map contains the object map and the register instance_type
199 // contains the instance_type. The registers map and instance_type can be the
200 // same in which case it contains the instance type afterwards. Either of the
201 // registers map and instance_type can be the same as heap_object.
202 Condition IsObjectStringType(Register heap_object,
203 Register map,
204 Register instance_type);
205
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100206 // Check if a heap object's type is in the JSObject range, not including
207 // JSFunction. The object's map will be loaded in the map register.
208 // Any or all of the three registers may be the same.
209 // The contents of the scratch register will always be overwritten.
210 void IsObjectJSObjectType(Register heap_object,
211 Register map,
212 Register scratch,
213 Label* fail);
214
215 // The contents of the scratch register will be overwritten.
216 void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
217
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 // FCmp is similar to integer cmp, but requires unsigned
219 // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
220 void FCmp();
221
Leon Clarkee46be812010-01-19 14:06:41 +0000222 // Smi tagging support.
223 void SmiTag(Register reg) {
224 ASSERT(kSmiTag == 0);
Steve Block6ded16b2010-05-10 14:33:55 +0100225 ASSERT(kSmiTagSize == 1);
226 add(reg, Operand(reg));
Leon Clarkee46be812010-01-19 14:06:41 +0000227 }
228 void SmiUntag(Register reg) {
229 sar(reg, kSmiTagSize);
230 }
231
Iain Merrick75681382010-08-19 15:07:18 +0100232 // Modifies the register even if it does not contain a Smi!
233 void SmiUntag(Register reg, TypeInfo info, Label* non_smi) {
234 ASSERT(kSmiTagSize == 1);
235 sar(reg, kSmiTagSize);
236 if (info.IsSmi()) {
237 ASSERT(kSmiTag == 0);
238 j(carry, non_smi);
239 }
240 }
241
242 // Modifies the register even if it does not contain a Smi!
243 void SmiUntag(Register reg, Label* is_smi) {
244 ASSERT(kSmiTagSize == 1);
245 sar(reg, kSmiTagSize);
246 ASSERT(kSmiTag == 0);
247 j(not_carry, is_smi);
248 }
249
250 // Assumes input is a heap object.
251 void JumpIfNotNumber(Register reg, TypeInfo info, Label* on_not_number);
252
253 // Assumes input is a heap number. Jumps on things out of range. Also jumps
254 // on the min negative int32. Ignores frational parts.
255 void ConvertToInt32(Register dst,
256 Register src, // Can be the same as dst.
257 Register scratch, // Can be no_reg or dst, but not src.
258 TypeInfo info,
259 Label* on_not_int32);
260
Andrei Popescu402d9372010-02-26 13:31:12 +0000261 // Abort execution if argument is not a number. Used in debug code.
Steve Block6ded16b2010-05-10 14:33:55 +0100262 void AbortIfNotNumber(Register object);
263
264 // Abort execution if argument is not a smi. Used in debug code.
265 void AbortIfNotSmi(Register object);
Andrei Popescu402d9372010-02-26 13:31:12 +0000266
Iain Merrick75681382010-08-19 15:07:18 +0100267 // Abort execution if argument is a smi. Used in debug code.
268 void AbortIfSmi(Register object);
269
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100270 // Abort execution if argument is a string. Used in debug code.
271 void AbortIfNotString(Register object);
272
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 // ---------------------------------------------------------------------------
274 // Exception handling
275
276 // Push a new try handler and link into try handler chain. The return
277 // address must be pushed before calling this helper.
278 void PushTryHandler(CodeLocation try_location, HandlerType type);
279
Leon Clarkee46be812010-01-19 14:06:41 +0000280 // Unlink the stack handler on top of the stack from the try handler chain.
281 void PopTryHandler();
Steve Blocka7e24c12009-10-30 11:49:00 +0000282
283 // ---------------------------------------------------------------------------
284 // Inline caching support
285
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 // Generate code for checking access rights - used for security checks
287 // on access to global objects across environments. The holder register
288 // is left untouched, but the scratch register is clobbered.
289 void CheckAccessGlobalProxy(Register holder_reg,
290 Register scratch,
291 Label* miss);
292
293
294 // ---------------------------------------------------------------------------
295 // Allocation support
296
297 // Allocate an object in new space. If the new space is exhausted control
298 // continues at the gc_required label. The allocated object is returned in
299 // result and end of the new object is returned in result_end. The register
300 // scratch can be passed as no_reg in which case an additional object
301 // reference will be added to the reloc info. The returned pointers in result
302 // and result_end have not yet been tagged as heap objects. If
Steve Blockd0582a62009-12-15 09:54:21 +0000303 // result_contains_top_on_entry is true the content of result is known to be
Steve Blocka7e24c12009-10-30 11:49:00 +0000304 // the allocation top on entry (could be result_end from a previous call to
305 // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
306 // should be no_reg as it is never used.
307 void AllocateInNewSpace(int object_size,
308 Register result,
309 Register result_end,
310 Register scratch,
311 Label* gc_required,
312 AllocationFlags flags);
313
314 void AllocateInNewSpace(int header_size,
315 ScaleFactor element_size,
316 Register element_count,
317 Register result,
318 Register result_end,
319 Register scratch,
320 Label* gc_required,
321 AllocationFlags flags);
322
323 void AllocateInNewSpace(Register object_size,
324 Register result,
325 Register result_end,
326 Register scratch,
327 Label* gc_required,
328 AllocationFlags flags);
329
330 // Undo allocation in new space. The object passed and objects allocated after
331 // it will no longer be allocated. Make sure that no pointers are left to the
332 // object(s) no longer allocated as they would be invalid when allocation is
333 // un-done.
334 void UndoAllocationInNewSpace(Register object);
335
Steve Block3ce2e202009-11-05 08:53:23 +0000336 // Allocate a heap number in new space with undefined value. The
337 // register scratch2 can be passed as no_reg; the others must be
338 // valid registers. Returns tagged pointer in result register, or
339 // jumps to gc_required if new space is full.
340 void AllocateHeapNumber(Register result,
341 Register scratch1,
342 Register scratch2,
343 Label* gc_required);
344
Steve Blockd0582a62009-12-15 09:54:21 +0000345 // Allocate a sequential string. All the header fields of the string object
346 // are initialized.
347 void AllocateTwoByteString(Register result,
348 Register length,
349 Register scratch1,
350 Register scratch2,
351 Register scratch3,
352 Label* gc_required);
353 void AllocateAsciiString(Register result,
354 Register length,
355 Register scratch1,
356 Register scratch2,
357 Register scratch3,
358 Label* gc_required);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100359 void AllocateAsciiString(Register result,
360 int length,
361 Register scratch1,
362 Register scratch2,
363 Label* gc_required);
Steve Blockd0582a62009-12-15 09:54:21 +0000364
365 // Allocate a raw cons string object. Only the map field of the result is
366 // initialized.
367 void AllocateConsString(Register result,
368 Register scratch1,
369 Register scratch2,
370 Label* gc_required);
371 void AllocateAsciiConsString(Register result,
372 Register scratch1,
373 Register scratch2,
374 Label* gc_required);
375
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 // ---------------------------------------------------------------------------
377 // Support functions.
378
379 // Check if result is zero and op is negative.
380 void NegativeZeroTest(Register result, Register op, Label* then_label);
381
382 // Check if result is zero and op is negative in code using jump targets.
383 void NegativeZeroTest(CodeGenerator* cgen,
384 Register result,
385 Register op,
386 JumpTarget* then_target);
387
388 // Check if result is zero and any of op1 and op2 are negative.
389 // Register scratch is destroyed, and it must be different from op2.
390 void NegativeZeroTest(Register result, Register op1, Register op2,
391 Register scratch, Label* then_label);
392
393 // Try to get function prototype of a function and puts the value in
394 // the result register. Checks that the function really is a
395 // function and jumps to the miss label if the fast checks fail. The
396 // function register will be untouched; the other registers may be
397 // clobbered.
398 void TryGetFunctionPrototype(Register function,
399 Register result,
400 Register scratch,
401 Label* miss);
402
403 // Generates code for reporting that an illegal operation has
404 // occurred.
405 void IllegalOperation(int num_arguments);
406
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100407 // Picks out an array index from the hash field.
408 // Register use:
409 // hash - holds the index's hash. Clobbered.
410 // index - holds the overwritten index on exit.
411 void IndexFromHash(Register hash, Register index);
412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 // ---------------------------------------------------------------------------
414 // Runtime calls
415
Leon Clarkee46be812010-01-19 14:06:41 +0000416 // Call a code stub. Generate the code if necessary.
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 void CallStub(CodeStub* stub);
418
Leon Clarkee46be812010-01-19 14:06:41 +0000419 // Call a code stub and return the code object called. Try to generate
420 // the code if necessary. Do not perform a GC but instead return a retry
421 // after GC failure.
422 Object* TryCallStub(CodeStub* stub);
423
424 // Tail call a code stub (jump). Generate the code if necessary.
Steve Blockd0582a62009-12-15 09:54:21 +0000425 void TailCallStub(CodeStub* stub);
426
Leon Clarkee46be812010-01-19 14:06:41 +0000427 // Tail call a code stub (jump) and return the code object called. Try to
428 // generate the code if necessary. Do not perform a GC but instead return
429 // a retry after GC failure.
430 Object* TryTailCallStub(CodeStub* stub);
431
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 // Return from a code stub after popping its arguments.
433 void StubReturn(int argc);
434
435 // Call a runtime routine.
Steve Blocka7e24c12009-10-30 11:49:00 +0000436 void CallRuntime(Runtime::Function* f, int num_arguments);
437
Leon Clarke4515c472010-02-03 11:58:03 +0000438 // Call a runtime function, returning the CodeStub object called.
Leon Clarkee46be812010-01-19 14:06:41 +0000439 // Try to generate the stub code if necessary. Do not perform a GC
440 // but instead return a retry after GC failure.
441 Object* TryCallRuntime(Runtime::Function* f, int num_arguments);
442
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 // Convenience function: Same as above, but takes the fid instead.
444 void CallRuntime(Runtime::FunctionId id, int num_arguments);
445
Leon Clarkee46be812010-01-19 14:06:41 +0000446 // Convenience function: Same as above, but takes the fid instead.
447 Object* TryCallRuntime(Runtime::FunctionId id, int num_arguments);
448
Ben Murdochbb769b22010-08-11 14:56:33 +0100449 // Convenience function: call an external reference.
450 void CallExternalReference(ExternalReference ref, int num_arguments);
451
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 // Tail call of a runtime routine (jump).
Steve Block6ded16b2010-05-10 14:33:55 +0100453 // Like JumpToExternalReference, but also takes care of passing the number
454 // of parameters.
455 void TailCallExternalReference(const ExternalReference& ext,
456 int num_arguments,
457 int result_size);
458
459 // Convenience function: tail call a runtime routine (jump).
460 void TailCallRuntime(Runtime::FunctionId fid,
Steve Blocka7e24c12009-10-30 11:49:00 +0000461 int num_arguments,
462 int result_size);
463
Steve Block6ded16b2010-05-10 14:33:55 +0100464 // Before calling a C-function from generated code, align arguments on stack.
465 // After aligning the frame, arguments must be stored in esp[0], esp[4],
466 // etc., not pushed. The argument count assumes all arguments are word sized.
467 // Some compilers/platforms require the stack to be aligned when calling
468 // C++ code.
469 // Needs a scratch register to do some arithmetic. This register will be
470 // trashed.
471 void PrepareCallCFunction(int num_arguments, Register scratch);
472
473 // Calls a C function and cleans up the space for arguments allocated
474 // by PrepareCallCFunction. The called function is not allowed to trigger a
475 // garbage collection, since that might move the code and invalidate the
476 // return address (unless this is somehow accounted for by the called
477 // function).
478 void CallCFunction(ExternalReference function, int num_arguments);
479 void CallCFunction(Register function, int num_arguments);
480
Steve Blockd0582a62009-12-15 09:54:21 +0000481 void PushHandleScope(Register scratch);
482
483 // Pops a handle scope using the specified scratch register and
Ben Murdochbb769b22010-08-11 14:56:33 +0100484 // ensuring that saved register is left unchanged.
Steve Blockd0582a62009-12-15 09:54:21 +0000485 void PopHandleScope(Register saved, Register scratch);
486
Leon Clarkee46be812010-01-19 14:06:41 +0000487 // As PopHandleScope, but does not perform a GC. Instead, returns a
488 // retry after GC failure object if GC is necessary.
489 Object* TryPopHandleScope(Register saved, Register scratch);
490
Steve Blocka7e24c12009-10-30 11:49:00 +0000491 // Jump to a runtime routine.
Steve Block6ded16b2010-05-10 14:33:55 +0100492 void JumpToExternalReference(const ExternalReference& ext);
Steve Blocka7e24c12009-10-30 11:49:00 +0000493
494
495 // ---------------------------------------------------------------------------
496 // Utilities
497
498 void Ret();
499
Leon Clarkee46be812010-01-19 14:06:41 +0000500 // Emit code to discard a non-negative number of pointer-sized elements
501 // from the stack, clobbering only the esp register.
502 void Drop(int element_count);
503
504 void Call(Label* target) { call(target); }
505
506 void Move(Register target, Handle<Object> value);
507
Steve Blocka7e24c12009-10-30 11:49:00 +0000508 Handle<Object> CodeObject() { return code_object_; }
509
510
511 // ---------------------------------------------------------------------------
512 // StatsCounter support
513
514 void SetCounter(StatsCounter* counter, int value);
515 void IncrementCounter(StatsCounter* counter, int value);
516 void DecrementCounter(StatsCounter* counter, int value);
Leon Clarked91b9f72010-01-27 17:25:45 +0000517 void IncrementCounter(Condition cc, StatsCounter* counter, int value);
518 void DecrementCounter(Condition cc, StatsCounter* counter, int value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000519
520
521 // ---------------------------------------------------------------------------
522 // Debugging
523
524 // Calls Abort(msg) if the condition cc is not satisfied.
525 // Use --debug_code to enable.
526 void Assert(Condition cc, const char* msg);
527
Iain Merrick75681382010-08-19 15:07:18 +0100528 void AssertFastElements(Register elements);
529
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 // Like Assert(), but always enabled.
531 void Check(Condition cc, const char* msg);
532
533 // Print a message to stdout and abort execution.
534 void Abort(const char* msg);
535
Steve Block6ded16b2010-05-10 14:33:55 +0100536 // Check that the stack is aligned.
537 void CheckStackAlignment();
538
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 // Verify restrictions about code generated in stubs.
540 void set_generating_stub(bool value) { generating_stub_ = value; }
541 bool generating_stub() { return generating_stub_; }
542 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
543 bool allow_stub_calls() { return allow_stub_calls_; }
544
Leon Clarked91b9f72010-01-27 17:25:45 +0000545 // ---------------------------------------------------------------------------
546 // String utilities.
547
Andrei Popescu402d9372010-02-26 13:31:12 +0000548 // Check whether the instance type represents a flat ascii string. Jump to the
549 // label if not. If the instance type can be scratched specify same register
550 // for both instance type and scratch.
551 void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
552 Register scratch,
Steve Block6ded16b2010-05-10 14:33:55 +0100553 Label* on_not_flat_ascii_string);
Andrei Popescu402d9372010-02-26 13:31:12 +0000554
Leon Clarked91b9f72010-01-27 17:25:45 +0000555 // Checks if both objects are sequential ASCII strings, and jumps to label
556 // if either is not.
557 void JumpIfNotBothSequentialAsciiStrings(Register object1,
558 Register object2,
559 Register scratch1,
560 Register scratch2,
Steve Block6ded16b2010-05-10 14:33:55 +0100561 Label* on_not_flat_ascii_strings);
Leon Clarked91b9f72010-01-27 17:25:45 +0000562
Steve Blocka7e24c12009-10-30 11:49:00 +0000563 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 bool generating_stub_;
565 bool allow_stub_calls_;
Andrei Popescu31002712010-02-23 13:46:05 +0000566 // This handle will be patched with the code object on installation.
567 Handle<Object> code_object_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000568
569 // Helper functions for generating invokes.
570 void InvokePrologue(const ParameterCount& expected,
571 const ParameterCount& actual,
572 Handle<Code> code_constant,
573 const Operand& code_operand,
574 Label* done,
575 InvokeFlag flag);
576
Steve Blocka7e24c12009-10-30 11:49:00 +0000577 // Activation support.
578 void EnterFrame(StackFrame::Type type);
579 void LeaveFrame(StackFrame::Type type);
580
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100581 void EnterExitFramePrologue();
582 void EnterExitFrameEpilogue(int argc);
Steve Blockd0582a62009-12-15 09:54:21 +0000583
Steve Blocka7e24c12009-10-30 11:49:00 +0000584 // Allocation support helpers.
585 void LoadAllocationTopHelper(Register result,
586 Register result_end,
587 Register scratch,
588 AllocationFlags flags);
589 void UpdateAllocationTopHelper(Register result_end, Register scratch);
Leon Clarkee46be812010-01-19 14:06:41 +0000590
591 // Helper for PopHandleScope. Allowed to perform a GC and returns
592 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
593 // possibly returns a failure object indicating an allocation failure.
594 Object* PopHandleScopeHelper(Register saved,
595 Register scratch,
596 bool gc_allowed);
Steve Blocka7e24c12009-10-30 11:49:00 +0000597};
598
599
600// The code patcher is used to patch (typically) small parts of code e.g. for
601// debugging and other types of instrumentation. When using the code patcher
602// the exact number of bytes specified must be emitted. Is not legal to emit
603// relocation information. If any of these constraints are violated it causes
604// an assertion.
605class CodePatcher {
606 public:
607 CodePatcher(byte* address, int size);
608 virtual ~CodePatcher();
609
610 // Macro assembler to emit code.
611 MacroAssembler* masm() { return &masm_; }
612
613 private:
614 byte* address_; // The address of the code being patched.
615 int size_; // Number of bytes of the expected patch size.
616 MacroAssembler masm_; // Macro assembler used to generate the code.
617};
618
619
620// -----------------------------------------------------------------------------
621// Static helper functions.
622
623// Generate an Operand for loading a field from an object.
624static inline Operand FieldOperand(Register object, int offset) {
625 return Operand(object, offset - kHeapObjectTag);
626}
627
628
629// Generate an Operand for loading an indexed field from an object.
630static inline Operand FieldOperand(Register object,
631 Register index,
632 ScaleFactor scale,
633 int offset) {
634 return Operand(object, index, scale, offset - kHeapObjectTag);
635}
636
637
638#ifdef GENERATED_CODE_COVERAGE
639extern void LogGeneratedCodeCoverage(const char* file_line);
640#define CODE_COVERAGE_STRINGIFY(x) #x
641#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
642#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
643#define ACCESS_MASM(masm) { \
644 byte* ia32_coverage_function = \
645 reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
646 masm->pushfd(); \
647 masm->pushad(); \
648 masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \
649 masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY); \
650 masm->pop(eax); \
651 masm->popad(); \
652 masm->popfd(); \
653 } \
654 masm->
655#else
656#define ACCESS_MASM(masm) masm->
657#endif
658
659
660} } // namespace v8::internal
661
662#endif // V8_IA32_MACRO_ASSEMBLER_IA32_H_