Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/asm/Assembler.java
38918 views
1
/*
2
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.tools.asm;
27
28
import sun.tools.java.*;
29
import java.util.Enumeration;
30
import java.io.IOException;
31
import java.io.DataOutputStream;
32
import java.io.PrintStream;
33
import java.util.Vector;
34
// JCOV
35
import sun.tools.javac.*;
36
import java.io.File;
37
import java.io.BufferedInputStream;
38
import java.io.DataInputStream;
39
import java.io.FileInputStream;
40
import java.io.FileNotFoundException;
41
import java.io.FileOutputStream;
42
import java.lang.String;
43
// end JCOV
44
45
/**
46
* This class is used to assemble the bytecode instructions for a method.
47
*
48
* WARNING: The contents of this source file are not part of any
49
* supported API. Code that depends on them does so at its own risk:
50
* they are subject to change or removal without notice.
51
*
52
* @author Arthur van Hoff
53
*/
54
public final
55
class Assembler implements Constants {
56
static final int NOTREACHED = 0;
57
static final int REACHED = 1;
58
static final int NEEDED = 2;
59
60
Label first = new Label();
61
Instruction last = first;
62
int maxdepth;
63
int maxvar;
64
int maxpc;
65
66
/**
67
* Add an instruction
68
*/
69
public void add(Instruction inst) {
70
if (inst != null) {
71
last.next = inst;
72
last = inst;
73
}
74
}
75
public void add(long where, int opc) {
76
add(new Instruction(where, opc, null));
77
}
78
public void add(long where, int opc, Object obj) {
79
add(new Instruction(where, opc, obj));
80
}
81
// JCOV
82
public void add(long where, int opc, Object obj, boolean flagCondInverted) {
83
add(new Instruction(where, opc, obj, flagCondInverted));
84
}
85
86
public void add(boolean flagNoCovered, long where, int opc, Object obj) {
87
add(new Instruction(flagNoCovered, where, opc, obj));
88
}
89
90
public void add(long where, int opc, boolean flagNoCovered) {
91
add(new Instruction(where, opc, flagNoCovered));
92
}
93
94
static Vector<String> SourceClassList = new Vector<>();
95
96
static Vector<String> TmpCovTable = new Vector<>();
97
98
static int[] JcovClassCountArray = new int[CT_LAST_KIND + 1];
99
100
static String JcovMagicLine = "JCOV-DATA-FILE-VERSION: 2.0";
101
static String JcovClassLine = "CLASS: ";
102
static String JcovSrcfileLine = "SRCFILE: ";
103
static String JcovTimestampLine = "TIMESTAMP: ";
104
static String JcovDataLine = "DATA: ";
105
static String JcovHeadingLine = "#kind\tcount";
106
107
static int[] arrayModifiers =
108
{M_PUBLIC, M_PRIVATE, M_PROTECTED, M_ABSTRACT, M_FINAL, M_INTERFACE};
109
static int[] arrayModifiersOpc =
110
{PUBLIC, PRIVATE, PROTECTED, ABSTRACT, FINAL, INTERFACE};
111
//end JCOV
112
113
/**
114
* Optimize instructions and mark those that can be reached
115
*/
116
void optimize(Environment env, Label lbl) {
117
lbl.pc = REACHED;
118
119
for (Instruction inst = lbl.next ; inst != null ; inst = inst.next) {
120
switch (inst.pc) {
121
case NOTREACHED:
122
inst.optimize(env);
123
inst.pc = REACHED;
124
break;
125
case REACHED:
126
return;
127
case NEEDED:
128
break;
129
}
130
131
switch (inst.opc) {
132
case opc_label:
133
case opc_dead:
134
if (inst.pc == REACHED) {
135
inst.pc = NOTREACHED;
136
}
137
break;
138
139
case opc_ifeq:
140
case opc_ifne:
141
case opc_ifgt:
142
case opc_ifge:
143
case opc_iflt:
144
case opc_ifle:
145
case opc_if_icmpeq:
146
case opc_if_icmpne:
147
case opc_if_icmpgt:
148
case opc_if_icmpge:
149
case opc_if_icmplt:
150
case opc_if_icmple:
151
case opc_if_acmpeq:
152
case opc_if_acmpne:
153
case opc_ifnull:
154
case opc_ifnonnull:
155
optimize(env, (Label)inst.value);
156
break;
157
158
case opc_goto:
159
optimize(env, (Label)inst.value);
160
return;
161
162
case opc_jsr:
163
optimize(env, (Label)inst.value);
164
break;
165
166
case opc_ret:
167
case opc_return:
168
case opc_ireturn:
169
case opc_lreturn:
170
case opc_freturn:
171
case opc_dreturn:
172
case opc_areturn:
173
case opc_athrow:
174
return;
175
176
case opc_tableswitch:
177
case opc_lookupswitch: {
178
SwitchData sw = (SwitchData)inst.value;
179
optimize(env, sw.defaultLabel);
180
for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {
181
optimize(env, e.nextElement());
182
}
183
return;
184
}
185
186
case opc_try: {
187
TryData td = (TryData)inst.value;
188
td.getEndLabel().pc = NEEDED;
189
for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {
190
CatchData cd = e.nextElement();
191
optimize(env, cd.getLabel());
192
}
193
break;
194
}
195
}
196
}
197
}
198
199
/**
200
* Eliminate instructions that are not reached
201
*/
202
boolean eliminate() {
203
boolean change = false;
204
Instruction prev = first;
205
206
for (Instruction inst = first.next ; inst != null ; inst = inst.next) {
207
if (inst.pc != NOTREACHED) {
208
prev.next = inst;
209
prev = inst;
210
inst.pc = NOTREACHED;
211
} else {
212
change = true;
213
}
214
}
215
first.pc = NOTREACHED;
216
prev.next = null;
217
return change;
218
}
219
220
/**
221
* Optimize the byte codes
222
*/
223
public void optimize(Environment env) {
224
//listing(System.out);
225
do {
226
// Figure out which instructions are reached
227
optimize(env, first);
228
229
// Eliminate instructions that are not reached
230
} while (eliminate() && env.opt());
231
}
232
233
/**
234
* Collect all constants into the constant table
235
*/
236
public void collect(Environment env, MemberDefinition field, ConstantPool tab) {
237
// Collect constants for arguments only
238
// if a local variable table is generated
239
if ((field != null) && env.debug_vars()) {
240
@SuppressWarnings("unchecked")
241
Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();
242
if (v != null) {
243
for (Enumeration<MemberDefinition> e = v.elements() ; e.hasMoreElements() ;) {
244
MemberDefinition f = e.nextElement();
245
tab.put(f.getName().toString());
246
tab.put(f.getType().getTypeSignature());
247
}
248
}
249
}
250
251
// Collect constants from the instructions
252
for (Instruction inst = first ; inst != null ; inst = inst.next) {
253
inst.collect(tab);
254
}
255
}
256
257
/**
258
* Determine stack size, count local variables
259
*/
260
void balance(Label lbl, int depth) {
261
for (Instruction inst = lbl ; inst != null ; inst = inst.next) {
262
//Environment.debugOutput(inst.toString() + ": " + depth + " => " +
263
// (depth + inst.balance()));
264
depth += inst.balance();
265
if (depth < 0) {
266
throw new CompilerError("stack under flow: " + inst.toString() + " = " + depth);
267
}
268
if (depth > maxdepth) {
269
maxdepth = depth;
270
}
271
switch (inst.opc) {
272
case opc_label:
273
lbl = (Label)inst;
274
if (inst.pc == REACHED) {
275
if (lbl.depth != depth) {
276
throw new CompilerError("stack depth error " +
277
depth + "/" + lbl.depth +
278
": " + inst.toString());
279
}
280
return;
281
}
282
lbl.pc = REACHED;
283
lbl.depth = depth;
284
break;
285
286
case opc_ifeq:
287
case opc_ifne:
288
case opc_ifgt:
289
case opc_ifge:
290
case opc_iflt:
291
case opc_ifle:
292
case opc_if_icmpeq:
293
case opc_if_icmpne:
294
case opc_if_icmpgt:
295
case opc_if_icmpge:
296
case opc_if_icmplt:
297
case opc_if_icmple:
298
case opc_if_acmpeq:
299
case opc_if_acmpne:
300
case opc_ifnull:
301
case opc_ifnonnull:
302
balance((Label)inst.value, depth);
303
break;
304
305
case opc_goto:
306
balance((Label)inst.value, depth);
307
return;
308
309
case opc_jsr:
310
balance((Label)inst.value, depth + 1);
311
break;
312
313
case opc_ret:
314
case opc_return:
315
case opc_ireturn:
316
case opc_lreturn:
317
case opc_freturn:
318
case opc_dreturn:
319
case opc_areturn:
320
case opc_athrow:
321
return;
322
323
case opc_iload:
324
case opc_fload:
325
case opc_aload:
326
case opc_istore:
327
case opc_fstore:
328
case opc_astore: {
329
int v = ((inst.value instanceof Number)
330
? ((Number)inst.value).intValue()
331
: ((LocalVariable)inst.value).slot) + 1;
332
if (v > maxvar)
333
maxvar = v;
334
break;
335
}
336
337
case opc_lload:
338
case opc_dload:
339
case opc_lstore:
340
case opc_dstore: {
341
int v = ((inst.value instanceof Number)
342
? ((Number)inst.value).intValue()
343
: ((LocalVariable)inst.value).slot) + 2;
344
if (v > maxvar)
345
maxvar = v;
346
break;
347
}
348
349
case opc_iinc: {
350
int v = ((int[])inst.value)[0] + 1;
351
if (v > maxvar)
352
maxvar = v + 1;
353
break;
354
}
355
356
case opc_tableswitch:
357
case opc_lookupswitch: {
358
SwitchData sw = (SwitchData)inst.value;
359
balance(sw.defaultLabel, depth);
360
for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {
361
balance(e.nextElement(), depth);
362
}
363
return;
364
}
365
366
case opc_try: {
367
TryData td = (TryData)inst.value;
368
for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {
369
CatchData cd = e.nextElement();
370
balance(cd.getLabel(), depth + 1);
371
}
372
break;
373
}
374
}
375
}
376
}
377
378
/**
379
* Generate code
380
*/
381
public void write(Environment env, DataOutputStream out,
382
MemberDefinition field, ConstantPool tab)
383
throws IOException {
384
//listing(System.out);
385
386
if ((field != null) && field.getArguments() != null) {
387
int sum = 0;
388
@SuppressWarnings("unchecked")
389
Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();
390
for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {
391
MemberDefinition f = e.nextElement();
392
sum += f.getType().stackSize();
393
}
394
maxvar = sum;
395
}
396
397
// Make sure the stack balances. Also calculate maxvar and maxstack
398
try {
399
balance(first, 0);
400
} catch (CompilerError e) {
401
System.out.println("ERROR: " + e);
402
listing(System.out);
403
throw e;
404
}
405
406
// Assign PCs
407
int pc = 0, nexceptions = 0;
408
for (Instruction inst = first ; inst != null ; inst = inst.next) {
409
inst.pc = pc;
410
int sz = inst.size(tab);
411
if (pc<65536 && (pc+sz)>=65536) {
412
env.error(inst.where, "warn.method.too.long");
413
}
414
pc += sz;
415
416
if (inst.opc == opc_try) {
417
nexceptions += ((TryData)inst.value).catches.size();
418
}
419
}
420
421
// Write header
422
out.writeShort(maxdepth);
423
out.writeShort(maxvar);
424
out.writeInt(maxpc = pc);
425
426
// Generate code
427
for (Instruction inst = first.next ; inst != null ; inst = inst.next) {
428
inst.write(out, tab);
429
}
430
431
// write exceptions
432
out.writeShort(nexceptions);
433
if (nexceptions > 0) {
434
//listing(System.out);
435
writeExceptions(env, out, tab, first, last);
436
}
437
}
438
439
/**
440
* Write the exceptions table
441
*/
442
void writeExceptions(Environment env, DataOutputStream out, ConstantPool tab, Instruction first, Instruction last) throws IOException {
443
for (Instruction inst = first ; inst != last.next ; inst = inst.next) {
444
if (inst.opc == opc_try) {
445
TryData td = (TryData)inst.value;
446
writeExceptions(env, out, tab, inst.next, td.getEndLabel());
447
for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {
448
CatchData cd = e.nextElement();
449
//System.out.println("EXCEPTION: " + env.getSource() + ", pc=" + inst.pc + ", end=" + td.getEndLabel().pc + ", hdl=" + cd.getLabel().pc + ", tp=" + cd.getType());
450
out.writeShort(inst.pc);
451
out.writeShort(td.getEndLabel().pc);
452
out.writeShort(cd.getLabel().pc);
453
if (cd.getType() != null) {
454
out.writeShort(tab.index(cd.getType()));
455
} else {
456
out.writeShort(0);
457
}
458
}
459
inst = td.getEndLabel();
460
}
461
}
462
}
463
464
//JCOV
465
/**
466
* Write the coverage table
467
*/
468
public void writeCoverageTable(Environment env, ClassDefinition c, DataOutputStream out, ConstantPool tab, long whereField) throws IOException {
469
Vector<Cover> TableLot = new Vector<>(); /* Coverage table */
470
boolean begseg = false;
471
boolean begmeth = false;
472
@SuppressWarnings("deprecation")
473
long whereClass = ((SourceClass)c).getWhere();
474
Vector<Long> whereTry = new Vector<>();
475
int numberTry = 0;
476
int count = 0;
477
478
for (Instruction inst = first ; inst != null ; inst = inst.next) {
479
long n = (inst.where >> WHEREOFFSETBITS);
480
if (n > 0 && inst.opc != opc_label) {
481
if (!begmeth) {
482
if ( whereClass == inst.where)
483
TableLot.addElement(new Cover(CT_FIKT_METHOD, whereField, inst.pc));
484
else
485
TableLot.addElement(new Cover(CT_METHOD, whereField, inst.pc));
486
count++;
487
begmeth = true;
488
}
489
if (!begseg && !inst.flagNoCovered ) {
490
boolean findTry = false;
491
for (Enumeration<Long> e = whereTry.elements(); e.hasMoreElements();) {
492
if (e.nextElement().longValue() == inst.where) {
493
findTry = true;
494
break;
495
}
496
}
497
if (!findTry) {
498
TableLot.addElement(new Cover(CT_BLOCK, inst.where, inst.pc));
499
count++;
500
begseg = true;
501
}
502
}
503
}
504
switch (inst.opc) {
505
case opc_label:
506
begseg = false;
507
break;
508
case opc_ifeq:
509
case opc_ifne:
510
case opc_ifnull:
511
case opc_ifnonnull:
512
case opc_ifgt:
513
case opc_ifge:
514
case opc_iflt:
515
case opc_ifle:
516
case opc_if_icmpeq:
517
case opc_if_icmpne:
518
case opc_if_icmpgt:
519
case opc_if_icmpge:
520
case opc_if_icmplt:
521
case opc_if_icmple:
522
case opc_if_acmpeq:
523
case opc_if_acmpne: {
524
if ( inst.flagCondInverted ) {
525
TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));
526
TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));
527
} else {
528
TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));
529
TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));
530
}
531
count += 2;
532
begseg = false;
533
break;
534
}
535
536
case opc_goto: {
537
begseg = false;
538
break;
539
}
540
541
case opc_ret:
542
case opc_return:
543
case opc_ireturn:
544
case opc_lreturn:
545
case opc_freturn:
546
case opc_dreturn:
547
case opc_areturn:
548
case opc_athrow: {
549
break;
550
}
551
552
case opc_try: {
553
whereTry.addElement(Long.valueOf(inst.where));
554
begseg = false;
555
break;
556
}
557
558
case opc_tableswitch: {
559
SwitchData sw = (SwitchData)inst.value;
560
for (int i = sw.minValue; i <= sw.maxValue; i++) {
561
TableLot.addElement(new Cover(CT_CASE, sw.whereCase(new Integer(i)), inst.pc));
562
count++;
563
}
564
if (!sw.getDefault()) {
565
TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));
566
count++;
567
} else {
568
TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));
569
count++;
570
}
571
begseg = false;
572
break;
573
}
574
case opc_lookupswitch: {
575
SwitchData sw = (SwitchData)inst.value;
576
for (Enumeration<Integer> e = sw.sortedKeys(); e.hasMoreElements() ; ) {
577
Integer v = e.nextElement();
578
TableLot.addElement(new Cover(CT_CASE, sw.whereCase(v), inst.pc));
579
count++;
580
}
581
if (!sw.getDefault()) {
582
TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));
583
count++;
584
} else {
585
TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));
586
count++;
587
}
588
begseg = false;
589
break;
590
}
591
}
592
}
593
Cover Lot;
594
long ln, pos;
595
596
out.writeShort(count);
597
for (int i = 0; i < count; i++) {
598
Lot = TableLot.elementAt(i);
599
ln = (Lot.Addr >> WHEREOFFSETBITS);
600
pos = (Lot.Addr << (64 - WHEREOFFSETBITS)) >> (64 - WHEREOFFSETBITS);
601
out.writeShort(Lot.NumCommand);
602
out.writeShort(Lot.Type);
603
out.writeInt((int)ln);
604
out.writeInt((int)pos);
605
606
if ( !(Lot.Type == CT_CASE && Lot.Addr == 0) ) {
607
JcovClassCountArray[Lot.Type]++;
608
}
609
}
610
611
}
612
613
/*
614
* Increase count of methods for native methods
615
*/
616
617
public void addNativeToJcovTab(Environment env, ClassDefinition c) {
618
JcovClassCountArray[CT_METHOD]++;
619
}
620
621
/*
622
* Create class jcov element
623
*/
624
625
private String createClassJcovElement(Environment env, ClassDefinition c) {
626
String SourceClass = (Type.mangleInnerType((c.getClassDeclaration()).getName())).toString();
627
String ConvSourceClass;
628
String classJcovLine;
629
630
SourceClassList.addElement(SourceClass);
631
ConvSourceClass = SourceClass.replace('.', '/');
632
classJcovLine = JcovClassLine + ConvSourceClass;
633
634
classJcovLine = classJcovLine + " [";
635
String blank = "";
636
637
for (int i = 0; i < arrayModifiers.length; i++ ) {
638
if ((c.getModifiers() & arrayModifiers[i]) != 0) {
639
classJcovLine = classJcovLine + blank + opNames[arrayModifiersOpc[i]];
640
blank = " ";
641
}
642
}
643
classJcovLine = classJcovLine + "]";
644
645
return classJcovLine;
646
}
647
648
/*
649
* generate coverage data
650
*/
651
652
public void GenVecJCov(Environment env, ClassDefinition c, long Time) {
653
@SuppressWarnings("deprecation")
654
String SourceFile = ((SourceClass)c).getAbsoluteName();
655
656
TmpCovTable.addElement(createClassJcovElement(env, c));
657
TmpCovTable.addElement(JcovSrcfileLine + SourceFile);
658
TmpCovTable.addElement(JcovTimestampLine + Time);
659
TmpCovTable.addElement(JcovDataLine + "A"); // data format
660
TmpCovTable.addElement(JcovHeadingLine);
661
662
for (int i = CT_FIRST_KIND; i <= CT_LAST_KIND; i++) {
663
if (JcovClassCountArray[i] != 0) {
664
TmpCovTable.addElement(new String(i + "\t" + JcovClassCountArray[i]));
665
JcovClassCountArray[i] = 0;
666
}
667
}
668
}
669
670
671
/*
672
* generate file of coverage data
673
*/
674
675
@SuppressWarnings("deprecation") // for JCovd.readLine() calls
676
public void GenJCov(Environment env) {
677
678
try {
679
File outFile = env.getcovFile();
680
if( outFile.exists()) {
681
DataInputStream JCovd = new DataInputStream(
682
new BufferedInputStream(
683
new FileInputStream(outFile)));
684
String CurrLine = null;
685
boolean first = true;
686
String Class;
687
688
CurrLine = JCovd.readLine();
689
if ((CurrLine != null) && CurrLine.startsWith(JcovMagicLine)) {
690
// this is a good Jcov file
691
692
while((CurrLine = JCovd.readLine()) != null ) {
693
if ( CurrLine.startsWith(JcovClassLine) ) {
694
first = true;
695
for(Enumeration<String> e = SourceClassList.elements(); e.hasMoreElements();) {
696
String clsName = CurrLine.substring(JcovClassLine.length());
697
int idx = clsName.indexOf(' ');
698
699
if (idx != -1) {
700
clsName = clsName.substring(0, idx);
701
}
702
Class = e.nextElement();
703
if ( Class.compareTo(clsName) == 0) {
704
first = false;
705
break;
706
}
707
}
708
}
709
if (first) // re-write old class
710
TmpCovTable.addElement(CurrLine);
711
}
712
}
713
JCovd.close();
714
}
715
PrintStream CovFile = new PrintStream(new DataOutputStream(new FileOutputStream(outFile)));
716
CovFile.println(JcovMagicLine);
717
for(Enumeration<String> e = TmpCovTable.elements(); e.hasMoreElements();) {
718
CovFile.println(e.nextElement());
719
}
720
CovFile.close();
721
}
722
catch (FileNotFoundException e) {
723
System.out.println("ERROR: " + e);
724
}
725
catch (IOException e) {
726
System.out.println("ERROR: " + e);
727
}
728
}
729
// end JCOV
730
731
732
/**
733
* Write the linenumber table
734
*/
735
public void writeLineNumberTable(Environment env, DataOutputStream out, ConstantPool tab) throws IOException {
736
long ln = -1;
737
int count = 0;
738
739
for (Instruction inst = first ; inst != null ; inst = inst.next) {
740
long n = (inst.where >> WHEREOFFSETBITS);
741
if ((n > 0) && (ln != n)) {
742
ln = n;
743
count++;
744
}
745
}
746
747
ln = -1;
748
out.writeShort(count);
749
for (Instruction inst = first ; inst != null ; inst = inst.next) {
750
long n = (inst.where >> WHEREOFFSETBITS);
751
if ((n > 0) && (ln != n)) {
752
ln = n;
753
out.writeShort(inst.pc);
754
out.writeShort((int)ln);
755
//System.out.println("pc = " + inst.pc + ", ln = " + ln);
756
}
757
}
758
}
759
760
/**
761
* Figure out when registers contain a legal value. This is done
762
* using a simple data flow algorithm. This information is later used
763
* to generate the local variable table.
764
*/
765
void flowFields(Environment env, Label lbl, MemberDefinition locals[]) {
766
if (lbl.locals != null) {
767
// Been here before. Erase any conflicts.
768
MemberDefinition f[] = lbl.locals;
769
for (int i = 0 ; i < maxvar ; i++) {
770
if (f[i] != locals[i]) {
771
f[i] = null;
772
}
773
}
774
return;
775
}
776
777
// Remember the set of active registers at this point
778
lbl.locals = new MemberDefinition[maxvar];
779
System.arraycopy(locals, 0, lbl.locals, 0, maxvar);
780
781
MemberDefinition newlocals[] = new MemberDefinition[maxvar];
782
System.arraycopy(locals, 0, newlocals, 0, maxvar);
783
locals = newlocals;
784
785
for (Instruction inst = lbl.next ; inst != null ; inst = inst.next) {
786
switch (inst.opc) {
787
case opc_istore: case opc_istore_0: case opc_istore_1:
788
case opc_istore_2: case opc_istore_3:
789
case opc_fstore: case opc_fstore_0: case opc_fstore_1:
790
case opc_fstore_2: case opc_fstore_3:
791
case opc_astore: case opc_astore_0: case opc_astore_1:
792
case opc_astore_2: case opc_astore_3:
793
case opc_lstore: case opc_lstore_0: case opc_lstore_1:
794
case opc_lstore_2: case opc_lstore_3:
795
case opc_dstore: case opc_dstore_0: case opc_dstore_1:
796
case opc_dstore_2: case opc_dstore_3:
797
if (inst.value instanceof LocalVariable) {
798
LocalVariable v = (LocalVariable)inst.value;
799
locals[v.slot] = v.field;
800
}
801
break;
802
803
case opc_label:
804
flowFields(env, (Label)inst, locals);
805
return;
806
807
case opc_ifeq: case opc_ifne: case opc_ifgt:
808
case opc_ifge: case opc_iflt: case opc_ifle:
809
case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:
810
case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:
811
case opc_if_acmpeq: case opc_if_acmpne:
812
case opc_ifnull: case opc_ifnonnull:
813
case opc_jsr:
814
flowFields(env, (Label)inst.value, locals);
815
break;
816
817
case opc_goto:
818
flowFields(env, (Label)inst.value, locals);
819
return;
820
821
case opc_return: case opc_ireturn: case opc_lreturn:
822
case opc_freturn: case opc_dreturn: case opc_areturn:
823
case opc_athrow: case opc_ret:
824
return;
825
826
case opc_tableswitch:
827
case opc_lookupswitch: {
828
SwitchData sw = (SwitchData)inst.value;
829
flowFields(env, sw.defaultLabel, locals);
830
for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {
831
flowFields(env, e.nextElement(), locals);
832
}
833
return;
834
}
835
836
case opc_try: {
837
Vector<CatchData> catches = ((TryData)inst.value).catches;
838
for (Enumeration<CatchData> e = catches.elements(); e.hasMoreElements();) {
839
CatchData cd = e.nextElement();
840
flowFields(env, cd.getLabel(), locals);
841
}
842
break;
843
}
844
}
845
}
846
}
847
848
/**
849
* Write the local variable table. The necessary constants have already been
850
* added to the constant table by the collect() method. The flowFields method
851
* is used to determine which variables are alive at each pc.
852
*/
853
public void writeLocalVariableTable(Environment env, MemberDefinition field, DataOutputStream out, ConstantPool tab) throws IOException {
854
MemberDefinition locals[] = new MemberDefinition[maxvar];
855
int i = 0;
856
857
// Initialize arguments
858
if ((field != null) && (field.getArguments() != null)) {
859
int reg = 0;
860
@SuppressWarnings("unchecked")
861
Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();
862
for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {
863
MemberDefinition f = e.nextElement();
864
locals[reg] = f;
865
reg += f.getType().stackSize();
866
}
867
}
868
869
flowFields(env, first, locals);
870
LocalVariableTable lvtab = new LocalVariableTable();
871
872
// Initialize arguments again
873
for (i = 0; i < maxvar; i++)
874
locals[i] = null;
875
if ((field != null) && (field.getArguments() != null)) {
876
int reg = 0;
877
@SuppressWarnings("unchecked")
878
Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();
879
for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {
880
MemberDefinition f = e.nextElement();
881
locals[reg] = f;
882
lvtab.define(f, reg, 0, maxpc);
883
reg += f.getType().stackSize();
884
}
885
}
886
887
int pcs[] = new int[maxvar];
888
889
for (Instruction inst = first ; inst != null ; inst = inst.next) {
890
switch (inst.opc) {
891
case opc_istore: case opc_istore_0: case opc_istore_1:
892
case opc_istore_2: case opc_istore_3: case opc_fstore:
893
case opc_fstore_0: case opc_fstore_1: case opc_fstore_2:
894
case opc_fstore_3:
895
case opc_astore: case opc_astore_0: case opc_astore_1:
896
case opc_astore_2: case opc_astore_3:
897
case opc_lstore: case opc_lstore_0: case opc_lstore_1:
898
case opc_lstore_2: case opc_lstore_3:
899
case opc_dstore: case opc_dstore_0: case opc_dstore_1:
900
case opc_dstore_2: case opc_dstore_3:
901
if (inst.value instanceof LocalVariable) {
902
LocalVariable v = (LocalVariable)inst.value;
903
int pc = (inst.next != null) ? inst.next.pc : inst.pc;
904
if (locals[v.slot] != null) {
905
lvtab.define(locals[v.slot], v.slot, pcs[v.slot], pc);
906
}
907
pcs[v.slot] = pc;
908
locals[v.slot] = v.field;
909
}
910
break;
911
912
case opc_label: {
913
// flush previous labels
914
for (i = 0 ; i < maxvar ; i++) {
915
if (locals[i] != null) {
916
lvtab.define(locals[i], i, pcs[i], inst.pc);
917
}
918
}
919
// init new labels
920
int pc = inst.pc;
921
MemberDefinition[] labelLocals = ((Label)inst).locals;
922
if (labelLocals == null) { // unreachable code??
923
for (i = 0; i < maxvar; i++)
924
locals[i] = null;
925
} else {
926
System.arraycopy(labelLocals, 0, locals, 0, maxvar);
927
}
928
for (i = 0 ; i < maxvar ; i++) {
929
pcs[i] = pc;
930
}
931
break;
932
}
933
}
934
}
935
936
// flush remaining labels
937
for (i = 0 ; i < maxvar ; i++) {
938
if (locals[i] != null) {
939
lvtab.define(locals[i], i, pcs[i], maxpc);
940
}
941
}
942
943
// write the local variable table
944
lvtab.write(env, out, tab);
945
}
946
947
/**
948
* Return true if empty
949
*/
950
public boolean empty() {
951
return first == last;
952
}
953
954
/**
955
* Print the byte codes
956
*/
957
public void listing(PrintStream out) {
958
out.println("-- listing --");
959
for (Instruction inst = first ; inst != null ; inst = inst.next) {
960
out.println(inst.toString());
961
}
962
}
963
}
964
965