13
13
14
14
package org .aspectj .runtime .reflect ;
15
15
16
+ import java .util .Stack ;
17
+
16
18
import org .aspectj .lang .JoinPoint ;
17
19
import org .aspectj .lang .ProceedingJoinPoint ;
18
20
import org .aspectj .lang .Signature ;
@@ -134,47 +136,73 @@ public final String toLongString() {
134
136
return staticPart .toLongString ();
135
137
}
136
138
137
- // To proceed we need a closure to proceed on
138
- private AroundClosure arc ;
139
+ // To proceed we need a closure to proceed on. Generated code
140
+ // will either be using arc or arcs but not both. arcs being non-null
141
+ // indicates it is in use (even if an empty stack)
142
+ private AroundClosure arc = null ;
143
+ private Stack <AroundClosure > arcs = null ;
139
144
140
145
public void set$AroundClosure (AroundClosure arc ) {
141
146
this .arc = arc ;
142
147
}
143
148
149
+ public void stack$AroundClosure (AroundClosure arc ) {
150
+ // If input parameter arc is null this is the 'unlink' call from AroundClosure
151
+ if (arcs == null ) {
152
+ arcs = new Stack <AroundClosure >();
153
+ }
154
+ if (arc ==null ) {
155
+ this .arcs .pop ();
156
+ } else {
157
+ this .arcs .push (arc );
158
+ }
159
+ }
160
+
144
161
public Object proceed () throws Throwable {
145
162
// when called from a before advice, but be a no-op
146
- if (arc == null )
147
- return null ;
148
- else
149
- return arc .run (arc .getState ());
163
+ if (arcs == null ) {
164
+ if (arc == null ) {
165
+ return null ;
166
+ } else {
167
+ return arc .run (arc .getState ());
168
+ }
169
+ } else {
170
+ return arcs .peek ().run (arcs .peek ().getState ());
171
+ }
150
172
}
151
173
152
174
public Object proceed (Object [] adviceBindings ) throws Throwable {
153
175
// when called from a before advice, but be a no-op
154
- if (arc == null )
176
+ AroundClosure ac = null ;
177
+ if (arcs == null ) {
178
+ ac = arc ;
179
+ } else {
180
+ ac = arcs .peek ();
181
+ }
182
+
183
+ if (ac == null ) {
155
184
return null ;
156
- else {
157
-
185
+ } else {
158
186
// Based on the bit flags in the AroundClosure we can determine what to
159
187
// expect in the adviceBindings array. We may or may not be expecting
160
188
// the first value to be a new this or a new target... (see pr126167)
161
- int flags = arc .getFlags ();
189
+ int flags = ac .getFlags ();
162
190
boolean unset = (flags & 0x100000 ) != 0 ;
163
191
boolean thisTargetTheSame = (flags & 0x010000 ) != 0 ;
164
192
boolean hasThis = (flags & 0x001000 ) != 0 ;
165
193
boolean bindsThis = (flags & 0x000100 ) != 0 ;
166
194
boolean hasTarget = (flags & 0x000010 ) != 0 ;
167
195
boolean bindsTarget = (flags & 0x000001 ) != 0 ;
168
-
196
+
169
197
// state is always consistent with caller?,callee?,formals...,jp
170
- Object [] state = arc .getState ();
171
-
198
+ Object [] state = ac .getState ();
199
+
172
200
// these next two numbers can differ because some join points have a this and
173
201
// target that are the same (eg. call) - and yet you can bind this and target
174
202
// separately.
175
-
203
+
176
204
// In the state array, [0] may be this, [1] may be target
177
-
205
+
178
206
int firstArgumentIndexIntoAdviceBindings = 0 ;
179
207
int firstArgumentIndexIntoState = 0 ;
180
208
firstArgumentIndexIntoState += (hasThis ? 1 : 0 );
@@ -202,8 +230,8 @@ public Object proceed(Object[] adviceBindings) throws Throwable {
202
230
// This previous variant doesn't seem to cope with only binding target at a joinpoint
203
231
// which has both this and target. It forces you to supply this even if you didn't bind
204
232
// it.
205
- // firstArgumentIndexIntoAdviceBindings = (hasThis ? 1 : 0) + 1;
206
- // state[hasThis ? 1 : 0] = adviceBindings[hasThis ? 1 : 0];
233
+ // firstArgumentIndexIntoAdviceBindings = (hasThis ? 1 : 0) + 1;
234
+ // state[hasThis ? 1 : 0] = adviceBindings[hasThis ? 1 : 0];
207
235
208
236
int targetPositionInAdviceBindings = (hasThis && bindsThis ) ? 1 : 0 ;
209
237
firstArgumentIndexIntoAdviceBindings = ((hasThis &&bindsThis )?1 :0 )+((hasTarget &&bindsTarget &&!thisTargetTheSame )?1 :0 );
@@ -213,20 +241,20 @@ public Object proceed(Object[] adviceBindings) throws Throwable {
213
241
// leave state[0]/state[1] alone, they are OK
214
242
}
215
243
}
216
-
244
+
217
245
// copy the rest across
218
246
for (int i = firstArgumentIndexIntoAdviceBindings ; i < adviceBindings .length ; i ++) {
219
247
state [firstArgumentIndexIntoState + (i - firstArgumentIndexIntoAdviceBindings )] = adviceBindings [i ];
220
248
}
221
-
249
+
222
250
// old code that did this, didnt allow this/target overriding
223
251
// for (int i = state.length-2; i >= 0; i--) {
224
252
// int formalIndex = (adviceBindings.length - 1) - (state.length-2) + i;
225
253
// if (formalIndex >= 0 && formalIndex < adviceBindings.length) {
226
254
// state[i] = adviceBindings[formalIndex];
227
255
// }
228
256
// }
229
- return arc .run (state );
257
+ return ac .run (state );
230
258
}
231
259
}
232
260
0 commit comments