2
2
3
3
import org .objectweb .asm .Label ;
4
4
import org .objectweb .asm .MethodVisitor ;
5
- import org .perlonjava .astnode .BlockNode ;
6
- import org .perlonjava .astnode .Node ;
5
+ import org .perlonjava .astnode .*;
7
6
import org .perlonjava .astvisitor .EmitterVisitor ;
8
7
import org .perlonjava .runtime .RuntimeContextType ;
9
8
10
9
import java .util .List ;
11
10
12
11
public class EmitBlock {
12
+ // Blocks with too many statements are emitted as a separate subroutine
13
+ // in order to avoid "Method too large" error test: in t/re/pat.t
14
+ final static int LARGE_BLOCK = 16 ;
15
+
13
16
/**
14
17
* Emits bytecode for a block of statements.
15
18
*
@@ -19,6 +22,28 @@ public class EmitBlock {
19
22
public static void emitBlock (EmitterVisitor emitterVisitor , BlockNode node ) {
20
23
MethodVisitor mv = emitterVisitor .ctx .mv ;
21
24
25
+ // Check if we can emit this as a subroutine, to avoid "Method too large" error.
26
+ // TODO: Check for possible goto's, then don't move the block to subroutine
27
+ if (node .elements .size () > LARGE_BLOCK
28
+ && !emitterVisitor .ctx .javaClassInfo .gotoLabelStack .isEmpty ()
29
+ && !node .getBooleanAnnotation ("blockIsSubroutine" )) {
30
+ // Create sub {...}->()
31
+ int index = node .tokenIndex ;
32
+ BinaryOperatorNode subr = new BinaryOperatorNode (
33
+ "->" ,
34
+ new SubroutineNode (
35
+ null , null , null ,
36
+ new BlockNode (List .of (node ), index ),
37
+ false ,
38
+ index
39
+ ),
40
+ new ListNode (index ),
41
+ index
42
+ );
43
+ subr .accept (emitterVisitor );
44
+ return ;
45
+ }
46
+
22
47
emitterVisitor .ctx .logDebug ("generateCodeBlock start context:" + emitterVisitor .ctx .contextType );
23
48
int scopeIndex = emitterVisitor .ctx .symbolTable .enterScope ();
24
49
EmitterVisitor voidVisitor =
0 commit comments