|
65 | 65 | import com.oracle.graal.python.nodes.PRaiseNode;
|
66 | 66 | import com.oracle.graal.python.nodes.SpecialMethodNames;
|
67 | 67 | import com.oracle.graal.python.nodes.bytecode.FrameInfo;
|
68 |
| -import com.oracle.graal.python.nodes.bytecode.GeneratorResult; |
| 68 | +import com.oracle.graal.python.nodes.bytecode.GeneratorReturnException; |
| 69 | +import com.oracle.graal.python.nodes.bytecode.GeneratorYieldResult; |
69 | 70 | import com.oracle.graal.python.nodes.call.CallTargetInvokeNode;
|
70 | 71 | import com.oracle.graal.python.nodes.call.GenericInvokeNode;
|
71 | 72 | import com.oracle.graal.python.nodes.call.special.LookupAndCallVarargsNode;
|
@@ -192,74 +193,79 @@ static Object genericAST(VirtualFrame frame, PGenerator self, Object sendValue,
|
192 | 193 | @Specialization(guards = {"self.usesBytecode()", "sameCallTarget(self.getCurrentCallTarget(), call.getCallTarget())"}, limit = "getCallSiteInlineCacheMaxDepth()")
|
193 | 194 | Object cached(VirtualFrame frame, PGenerator self, Object sendValue,
|
194 | 195 | @Cached("createDirectCall(self.getCurrentCallTarget())") CallTargetInvokeNode call,
|
195 |
| - @Cached ConditionProfile returnProfile, |
| 196 | + @Cached BranchProfile returnProfile, |
196 | 197 | @Cached IsBuiltinClassProfile errorProfile,
|
197 | 198 | @Cached PRaiseNode raiseNode) {
|
198 | 199 | self.setRunning(true);
|
199 | 200 | Object[] arguments = prepareArguments(self);
|
200 | 201 | if (sendValue != null) {
|
201 | 202 | PArguments.setSpecialArgument(arguments, sendValue);
|
202 | 203 | }
|
203 |
| - GeneratorResult result; |
| 204 | + GeneratorYieldResult result; |
204 | 205 | try {
|
205 |
| - result = (GeneratorResult) call.execute(frame, null, null, null, arguments); |
| 206 | + result = (GeneratorYieldResult) call.execute(frame, null, null, null, arguments); |
206 | 207 | } catch (PException e) {
|
207 |
| - self.markAsFinished(); |
208 |
| - // PEP 479 - StopIteration raised from generator body needs to be wrapped in |
209 |
| - // RuntimeError |
210 |
| - e.expectStopIteration(errorProfile); |
211 |
| - throw raiseNode.raise(RuntimeError, e.setCatchingFrameAndGetEscapedException(frame, this), ErrorMessages.GENERATOR_RAISED_STOPITER); |
| 208 | + throw handleException(frame, self, errorProfile, raiseNode, e); |
| 209 | + } catch (GeneratorReturnException e) { |
| 210 | + returnProfile.enter(); |
| 211 | + throw handleReturn(self, e, raiseNode); |
212 | 212 | } finally {
|
213 | 213 | self.setRunning(false);
|
214 | 214 | }
|
215 |
| - return handleResult(self, result, returnProfile, raiseNode); |
| 215 | + return handleResult(self, result); |
216 | 216 | }
|
217 | 217 |
|
218 | 218 | @Specialization(guards = "self.usesBytecode()", replaces = "cached")
|
219 | 219 | @Megamorphic
|
220 | 220 | Object generic(VirtualFrame frame, PGenerator self, Object sendValue,
|
221 | 221 | @Cached ConditionProfile hasFrameProfile,
|
222 | 222 | @Cached GenericInvokeNode call,
|
223 |
| - @Cached ConditionProfile returnProfile, |
| 223 | + @Cached BranchProfile returnProfile, |
224 | 224 | @Cached IsBuiltinClassProfile errorProfile,
|
225 | 225 | @Cached PRaiseNode raiseNode) {
|
226 | 226 | self.setRunning(true);
|
227 | 227 | Object[] arguments = prepareArguments(self);
|
228 | 228 | if (sendValue != null) {
|
229 | 229 | PArguments.setSpecialArgument(arguments, sendValue);
|
230 | 230 | }
|
231 |
| - GeneratorResult result; |
| 231 | + GeneratorYieldResult result; |
232 | 232 | try {
|
233 | 233 | if (hasFrameProfile.profile(frame != null)) {
|
234 |
| - result = (GeneratorResult) call.execute(frame, self.getCurrentCallTarget(), arguments); |
| 234 | + result = (GeneratorYieldResult) call.execute(frame, self.getCurrentCallTarget(), arguments); |
235 | 235 | } else {
|
236 |
| - result = (GeneratorResult) call.execute(self.getCurrentCallTarget(), arguments); |
| 236 | + result = (GeneratorYieldResult) call.execute(self.getCurrentCallTarget(), arguments); |
237 | 237 | }
|
238 | 238 | } catch (PException e) {
|
239 |
| - self.markAsFinished(); |
240 |
| - // PEP 479 - StopIteration raised from generator body needs to be wrapped in |
241 |
| - // RuntimeError |
242 |
| - e.expectStopIteration(errorProfile); |
243 |
| - throw raiseNode.raise(RuntimeError, e.setCatchingFrameAndGetEscapedException(frame, this), ErrorMessages.GENERATOR_RAISED_STOPITER); |
| 239 | + throw handleException(frame, self, errorProfile, raiseNode, e); |
| 240 | + } catch (GeneratorReturnException e) { |
| 241 | + returnProfile.enter(); |
| 242 | + throw handleReturn(self, e, raiseNode); |
244 | 243 | } finally {
|
245 | 244 | self.setRunning(false);
|
246 | 245 | }
|
247 |
| - return handleResult(self, result, returnProfile, raiseNode); |
| 246 | + return handleResult(self, result); |
248 | 247 | }
|
249 | 248 |
|
250 |
| - private Object handleResult(PGenerator self, GeneratorResult result, ConditionProfile returnProfile, PRaiseNode raiseNode) { |
251 |
| - if (returnProfile.profile(result.isReturn)) { |
252 |
| - self.markAsFinished(); |
253 |
| - Object returnValue = result.value; |
254 |
| - if (returnValue != PNone.NONE) { |
255 |
| - throw raiseNode.raise(StopIteration, new Object[]{returnValue}); |
256 |
| - } else { |
257 |
| - throw raiseNode.raise(StopIteration); |
258 |
| - } |
| 249 | + private PException handleException(VirtualFrame frame, PGenerator self, IsBuiltinClassProfile errorProfile, PRaiseNode raiseNode, PException e) { |
| 250 | + self.markAsFinished(); |
| 251 | + // PEP 479 - StopIteration raised from generator body needs to be wrapped in |
| 252 | + // RuntimeError |
| 253 | + e.expectStopIteration(errorProfile); |
| 254 | + throw raiseNode.raise(RuntimeError, e.setCatchingFrameAndGetEscapedException(frame, this), ErrorMessages.GENERATOR_RAISED_STOPITER); |
| 255 | + } |
| 256 | + |
| 257 | + private Object handleResult(PGenerator self, GeneratorYieldResult result) { |
| 258 | + self.handleResult(PythonLanguage.get(this), result); |
| 259 | + return result.yieldValue; |
| 260 | + } |
| 261 | + |
| 262 | + private static PException handleReturn(PGenerator self, GeneratorReturnException e, PRaiseNode raiseNode) { |
| 263 | + self.markAsFinished(); |
| 264 | + if (e.value != PNone.NONE) { |
| 265 | + throw raiseNode.raise(StopIteration, new Object[]{e.value}); |
259 | 266 | } else {
|
260 |
| - self.handleResult(PythonLanguage.get(this), result); |
| 267 | + throw raiseNode.raise(StopIteration); |
261 | 268 | }
|
262 |
| - return result.value; |
263 | 269 | }
|
264 | 270 |
|
265 | 271 | protected static CallTargetInvokeNode createDirectCall(CallTarget target) {
|
|
0 commit comments