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