Starting release 0.7.0
[parrot.git] / src / cpu_dep.c
blobd5505ec28c571f3dc306fa534aa97053e9731305
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/cpu_dep.c - CPU-dependent functions
9 =head1 DESCRIPTION
11 These functions setup a trace of the current processor context and the
12 system stack. The trace is set up here in C<trace_system_areas>. This
13 function gets the current processor context and either traces it
14 directly or stores it on the system stack. C<trace_system_stack>
15 sets up a trace of the system stack using two marker addresses as
16 boundaries. The code to actually perform the trace of a memory block
17 between two boundaries is located in C<src/gc/dod.c:trace_mem_block>.
19 =head2 Functions
21 =over 4
23 =cut
27 #include "parrot/parrot.h"
29 /* HEADERIZER HFILE: include/parrot/dod.h */
31 /* HEADERIZER BEGIN: static */
32 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
34 static void trace_system_stack(PARROT_INTERP)
35 __attribute__nonnull__(1);
37 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
38 /* HEADERIZER END: static */
40 #ifdef __ia64__
42 # include <ucontext.h>
43 extern void *flush_reg_store(void);
44 # define BACKING_STORE_BASE 0x80000fff80000000
46 #endif
50 =item C<void trace_system_areas>
52 Initiates a trace of the system stack, looking for pointers which are being
53 used by functions in the call chain, but which might not be marked as alive
54 in any other way. Setting the trace up, which involves storing the processor
55 context onto the stack, is highly system dependent. However, once stored,
56 tracing the stack is very straightforward.
58 =cut
62 void
63 trace_system_areas(PARROT_INTERP)
65 #if defined(__sparc)
66 /* Flush the register windows. For sparc systems, we use hand-coded
67 assembly language to create a small function that flushes the
68 register windows. Store the code in a union with a double to
69 ensure proper memory alignment. */
70 static union {
71 unsigned int insns[4];
72 double align_hack[2];
73 } u = { {
74 # ifdef __sparcv9
75 0x81580000, /* flushw */
76 # else
77 0x91d02003, /* ta ST_FLUSH_WINDOWS */
78 # endif
79 0x81c3e008, /* retl */
80 0x01000000 /* nop */
81 } };
83 /* Turn the array of machine code values above into a function pointer.
84 Call the new function pointer to flush the register windows. */
85 static void (*fn_ptr)(void) = (void (*)(void))&u.align_hack[0];
86 fn_ptr();
88 #elif defined(__ia64__)
90 /* On IA64 systems, we use the function getcontext() to get the current
91 processor context. This function is located in <ucontext.h>, included
92 above. */
93 struct ucontext ucp;
94 void *current_regstore_top;
96 getcontext(&ucp);
98 /* flush_reg_store() is defined in config/gen/platforms/ia64/asm.s.
99 it calls the flushrs opcode to perform the register flush, and
100 returns the address of the register backing stack. */
101 current_regstore_top = flush_reg_store();
103 /* Trace the memory block for the register backing stack, which
104 is separate from the normal system stack. The register backing
105 stack starts at memory address 0x80000FFF80000000 and ends at
106 current_regstore_top. */
107 trace_mem_block(interp, 0x80000fff80000000,
108 (size_t)current_regstore_top);
109 #else
111 # ifdef PARROT_HAS_HEADER_SETJMP
112 /* A jump buffer that is used to store the current processor context.
113 local variables like this are created on the stack. */
114 Parrot_jump_buff env;
116 /* Zero the Parrot_jump_buff, otherwise you will trace stale objects.
117 Plus, optimizing compilers won't be so quick to optimize the data
118 away if we're passing pointers around. */
119 memset(&env, 0, sizeof (env));
121 /* this should put registers in env, which then get marked in
122 * trace_system_stack below
124 setjmp(env);
125 # endif
127 #endif
129 /* With the processor context accounted for above, we can trace the
130 system stack here. */
131 trace_system_stack(interp);
136 =item C<static void trace_system_stack>
138 Traces the memory block starting at C<< interp->lo_var_ptr >>. This should be
139 the address of a local variable which has been created on the stack early in
140 the interpreter's lifecycle. We trace until the address of another local stack
141 variable in this function, which should be at the "top" of the stack.
143 =cut
147 static void
148 trace_system_stack(PARROT_INTERP)
150 /* Create a local variable on the system stack. This represents the
151 "top" of the stack. A value stored in interp->lo_var_ptr represents
152 the "bottom" of the stack. We must trace the entire area between the
153 top and bottom. */
154 const size_t lo_var_ptr = (size_t)interp->lo_var_ptr;
156 trace_mem_block(interp, (size_t)lo_var_ptr,
157 (size_t)&lo_var_ptr);
162 =back
164 =head1 SEE ALSO
166 F<src/gc/dod.c> and F<include/parrot/dod.h>.
168 =cut
174 * Local variables:
175 * c-file-style: "parrot"
176 * End:
177 * vim: expandtab shiftwidth=4: