1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2008-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20 /*
21 * Stack walking helpers for native stack GC procedures.
22 * Generic RISC version.
23 */
24 #ifndef HIPE_RISC_GC_H
25 #define HIPE_RISC_GC_H
26
27 /* arch wrapper includes hipe_${arch}_asm.h to define NR_ARG_REGS */
28
29 struct nstack_walk_state {
30 const struct hipe_sdesc *sdesc0; /* .sdesc0 must be a pointer rvalue */
31 };
32
nstack_walk_init_check(const Process * p)33 static inline int nstack_walk_init_check(const Process *p)
34 {
35 return p->hipe.nra ? 1 : 0;
36 }
37
nstack_walk_nsp_begin(const Process * p)38 static inline Eterm *nstack_walk_nsp_begin(const Process *p)
39 {
40 unsigned int nstkarity = p->hipe.narity - NR_ARG_REGS;
41 if ((int)nstkarity < 0)
42 nstkarity = 0;
43 return p->hipe.nsp + nstkarity;
44 }
45
46 static inline const struct hipe_sdesc*
nstack_walk_init_sdesc(const Process * p,struct nstack_walk_state * state)47 nstack_walk_init_sdesc(const Process *p, struct nstack_walk_state *state)
48 {
49 const struct hipe_sdesc *sdesc = hipe_find_sdesc((unsigned long)p->hipe.nra);
50 state->sdesc0 = sdesc;
51 return sdesc;
52 }
53
54 static inline const struct hipe_sdesc*
nstack_walk_init_sdesc_ignore_trap(const Process * p,struct nstack_walk_state * state)55 nstack_walk_init_sdesc_ignore_trap(const Process *p,
56 struct nstack_walk_state *state)
57 {
58 unsigned long ra = (unsigned long)p->hipe.nra;
59 const struct hipe_sdesc *sdesc;
60 if (ra == (unsigned long)&nbif_stack_trap_ra)
61 ra = (unsigned long)p->hipe.ngra;
62 sdesc = hipe_find_sdesc(ra);
63 state->sdesc0 = sdesc;
64 return sdesc;
65 }
66
nstack_walk_update_trap(Process * p,const struct hipe_sdesc * sdesc0)67 static inline void nstack_walk_update_trap(Process *p, const struct hipe_sdesc *sdesc0)
68 {
69 Eterm *nsp = p->hipe.nsp;
70 p->hipe.nsp = nstack_walk_nsp_begin(p);
71 hipe_update_stack_trap(p, sdesc0);
72 p->hipe.nsp = nsp;
73 }
74
nstack_walk_nsp_end(const Process * p)75 static inline Eterm *nstack_walk_nsp_end(const Process *p)
76 {
77 return p->hipe.nstend - 1;
78 }
79
nstack_walk_kill_trap(Process * p,Eterm * nsp_end)80 static inline void nstack_walk_kill_trap(Process *p, Eterm *nsp_end)
81 {
82 /* remove gray/white boundary trap */
83 if ((unsigned long)p->hipe.nra == (unsigned long)&nbif_stack_trap_ra) {
84 p->hipe.nra = p->hipe.ngra;
85 } else {
86 for (;;) {
87 --nsp_end;
88 if (nsp_end[0] == (unsigned long)&nbif_stack_trap_ra) {
89 nsp_end[0] = (unsigned long)p->hipe.ngra;
90 break;
91 }
92 }
93 }
94 }
95
nstack_walk_gray_passed_black(const Eterm * gray,const Eterm * black)96 static inline int nstack_walk_gray_passed_black(const Eterm *gray, const Eterm *black)
97 {
98 return gray > black;
99 }
100
nstack_walk_nsp_reached_end(const Eterm * nsp,const Eterm * nsp_end)101 static inline int nstack_walk_nsp_reached_end(const Eterm *nsp, const Eterm *nsp_end)
102 {
103 return nsp >= nsp_end;
104 }
105
nstack_walk_frame_size(const struct hipe_sdesc * sdesc)106 static inline unsigned int nstack_walk_frame_size(const struct hipe_sdesc *sdesc)
107 {
108 return sdesc_fsize(sdesc) + 1 + sdesc_arity(sdesc);
109 }
110
nstack_walk_frame_index(Eterm * nsp,unsigned int i)111 static inline Eterm *nstack_walk_frame_index(Eterm *nsp, unsigned int i)
112 {
113 return &nsp[i];
114 }
115
116 static inline unsigned long
nstack_walk_frame_ra(const Eterm * nsp,const struct hipe_sdesc * sdesc)117 nstack_walk_frame_ra(const Eterm *nsp, const struct hipe_sdesc *sdesc)
118 {
119 return nsp[sdesc_fsize(sdesc)];
120 }
121
nstack_walk_next_frame(Eterm * nsp,unsigned int sdesc_size)122 static inline Eterm *nstack_walk_next_frame(Eterm *nsp, unsigned int sdesc_size)
123 {
124 return nsp + sdesc_size;
125 }
126
127 #endif /* HIPE_RISC_GC_H */
128