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/javac/SourceMember.java
38918 views
1
/*
2
* Copyright (c) 1994, 2004, 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.javac;
27
28
import sun.tools.java.*;
29
import sun.tools.tree.*;
30
import sun.tools.asm.*;
31
import java.util.Vector;
32
import java.util.Enumeration;
33
import java.util.Hashtable;
34
import java.io.PrintStream;
35
36
/**
37
* A Source Member
38
*
39
* WARNING: The contents of this source file are not part of any
40
* supported API. Code that depends on them does so at its own risk:
41
* they are subject to change or removal without notice.
42
*/
43
@Deprecated
44
public
45
class SourceMember extends MemberDefinition implements Constants {
46
/**
47
* The argument names (if it is a method)
48
*/
49
Vector args;
50
51
// set to the MemberDefinition in the interface if we have this field because
52
// it has been forced on us
53
MemberDefinition abstractSource;
54
55
/**
56
* The status of the field
57
*/
58
int status;
59
60
static final int PARSED = 0;
61
static final int CHECKING = 1;
62
static final int CHECKED = 2;
63
static final int INLINING = 3;
64
static final int INLINED = 4;
65
static final int ERROR = 5;
66
67
public Vector getArguments() {
68
return args;
69
}
70
71
/**
72
* Constructor
73
* @param argNames a vector of IdentifierToken
74
*/
75
public SourceMember(long where, ClassDefinition clazz,
76
String doc, int modifiers, Type type,
77
Identifier name, Vector argNames,
78
IdentifierToken exp[], Node value) {
79
super(where, clazz, modifiers, type, name, exp, value);
80
this.documentation = doc;
81
this.args = argNames; // for the moment
82
// not until type names are resolved: createArgumentFields(argNames);
83
84
if (ClassDefinition.containsDeprecated(documentation)) {
85
this.modifiers |= M_DEPRECATED;
86
}
87
}
88
89
void createArgumentFields(Vector argNames) {
90
// Create a list of arguments
91
if (isMethod()) {
92
args = new Vector();
93
94
if (isConstructor() || !(isStatic() || isInitializer())) {
95
args.addElement(((SourceClass)clazz).getThisArgument());
96
}
97
98
if (argNames != null) {
99
Enumeration e = argNames.elements();
100
Type argTypes[] = getType().getArgumentTypes();
101
for (int i = 0 ; i < argTypes.length ; i++) {
102
Object x = e.nextElement();
103
if (x instanceof LocalMember) {
104
// This should not happen, but it does
105
// in cases of vicious cyclic inheritance.
106
args = argNames;
107
return;
108
}
109
Identifier id;
110
int mod;
111
long where;
112
if (x instanceof Identifier) {
113
// allow argNames to be simple Identifiers (deprecated!)
114
id = (Identifier)x;
115
mod = 0;
116
where = getWhere();
117
} else {
118
IdentifierToken token = (IdentifierToken)x;
119
id = token.getName();
120
mod = token.getModifiers();
121
where = token.getWhere();
122
}
123
args.addElement(new LocalMember(where, clazz, mod,
124
argTypes[i], id));
125
}
126
}
127
}
128
}
129
130
// The methods addOuterThis() and addUplevelArguments() were
131
// both originally part of a single method called addUplevelArguments()
132
// which took a single boolean parameter describing which of the
133
// two behaviors it wanted.
134
//
135
// The original addUplevelArguments() claimed to keep the arguments in
136
// the following order:
137
//
138
// (1) <this> <early outer this> <uplevel arguments...> <true arguments...>
139
//
140
// (By <early outer this> I am referring to the clientOuterField added
141
// to some constructors when they are created. If an outer this is
142
// added later, on demand, then this is mixed in with the rest of the
143
// uplevel arguments and is added by addUplevelArguments.)
144
//
145
// In reality, the `args' Vector was generated in this order, but the
146
// Type array `argTypes' was generated as:
147
//
148
// (2) <this> <uplevel arguments...> <early outer this> <true arguments...>
149
//
150
// This didn't make a difference in the common case -- that is, when
151
// a class had an <outer.this> or <uplevel arguments...> but not both.
152
// Both can happen in the case that a member class is declared inside
153
// of a local class. It seems that the calling sequences, generated
154
// in places like NewInstanceExpression.codeCommon(), use order (2),
155
// so I have changed the code below to stick with that order. Since
156
// the only time this happens is in classes which are insideLocal, no
157
// one should be able to tell the difference between these orders.
158
// (bug number 4085633)
159
160
LocalMember outerThisArg = null;
161
162
/**
163
* Get outer instance link, or null if none.
164
*/
165
166
public LocalMember getOuterThisArg() {
167
return outerThisArg;
168
}
169
170
/**
171
* Add the outer.this argument to the list of arguments for this
172
* constructor. This is called from resolveTypeStructure. Any
173
* additional uplevel arguments get added later by addUplevelArguments().
174
*/
175
176
void addOuterThis() {
177
UplevelReference refs = clazz.getReferences();
178
179
// See if we have a client outer field.
180
while (refs != null &&
181
!refs.isClientOuterField()) {
182
refs = refs.getNext();
183
}
184
185
// There is no outer this argument. Quit.
186
if (refs == null) {
187
return;
188
}
189
190
// Get the old arg types.
191
Type oldArgTypes[] = type.getArgumentTypes();
192
193
// And make an array for the new ones with space for one more.
194
Type argTypes[] = new Type[oldArgTypes.length + 1];
195
196
LocalMember arg = refs.getLocalArgument();
197
outerThisArg = arg;
198
199
// args is our list of arguments. It contains a `this', so
200
// we insert at position 1. The list of types does not have a
201
// this, so we insert at position 0.
202
args.insertElementAt(arg, 1);
203
argTypes[0] = arg.getType();
204
205
// Add on the rest of the constructor arguments.
206
for (int i = 0; i < oldArgTypes.length; i++) {
207
argTypes[i + 1] = oldArgTypes[i];
208
}
209
210
type = Type.tMethod(type.getReturnType(), argTypes);
211
}
212
213
/**
214
* Prepend argument names and argument types for local variable references.
215
* This information is never seen by the type-check phase,
216
* but it affects code generation, which is the earliest moment
217
* we have comprehensive information on uplevel references.
218
* The code() methods tweaks the constructor calls, prepending
219
* the proper values to the argument list.
220
*/
221
void addUplevelArguments() {
222
UplevelReference refs = clazz.getReferences();
223
clazz.getReferencesFrozen();
224
225
// Count how many uplevels we have to add.
226
int count = 0;
227
for (UplevelReference r = refs; r != null; r = r.getNext()) {
228
if (!r.isClientOuterField()) {
229
count += 1;
230
}
231
}
232
233
if (count == 0) {
234
// None to add, quit.
235
return;
236
}
237
238
// Get the old argument types.
239
Type oldArgTypes[] = type.getArgumentTypes();
240
241
// Make an array with enough room for the new.
242
Type argTypes[] = new Type[oldArgTypes.length + count];
243
244
// Add all of the late uplevel references to args and argTypes.
245
// Note that they are `off-by-one' because of the `this'.
246
int ins = 0;
247
for (UplevelReference r = refs; r != null; r = r.getNext()) {
248
if (!r.isClientOuterField()) {
249
LocalMember arg = r.getLocalArgument();
250
251
args.insertElementAt(arg, 1 + ins);
252
argTypes[ins] = arg.getType();
253
254
ins++;
255
}
256
}
257
258
// Add the rest of the old arguments.
259
for (int i = 0; i < oldArgTypes.length; i++) {
260
argTypes[ins + i] = oldArgTypes[i];
261
}
262
263
type = Type.tMethod(type.getReturnType(), argTypes);
264
}
265
266
/**
267
* Constructor for an inner class.
268
*/
269
public SourceMember(ClassDefinition innerClass) {
270
super(innerClass);
271
}
272
273
/**
274
* Constructor.
275
* Used only to generate an abstract copy of a method that a class
276
* inherits from an interface
277
*/
278
public SourceMember(MemberDefinition f, ClassDefinition c, Environment env) {
279
this(f.getWhere(), c, f.getDocumentation(),
280
f.getModifiers() | M_ABSTRACT, f.getType(), f.getName(), null,
281
f.getExceptionIds(), null);
282
this.args = f.getArguments();
283
this.abstractSource = f;
284
this.exp = f.getExceptions(env);
285
}
286
287
/**
288
* Get exceptions
289
*/
290
public ClassDeclaration[] getExceptions(Environment env) {
291
if ((!isMethod()) || (exp != null)) {
292
return exp;
293
}
294
if (expIds == null) {
295
// (should not happen)
296
exp = new ClassDeclaration[0];
297
return exp;
298
}
299
// be sure to get the imports right:
300
env = ((SourceClass)getClassDefinition()).setupEnv(env);
301
exp = new ClassDeclaration[expIds.length];
302
for (int i = 0; i < exp.length; i++) {
303
Identifier e = expIds[i].getName();
304
Identifier rexp = getClassDefinition().resolveName(env, e);
305
exp[i] = env.getClassDeclaration(rexp);
306
}
307
return exp;
308
}
309
310
/**
311
* Set array of name-resolved exceptions directly, e.g., for access methods.
312
*/
313
public void setExceptions(ClassDeclaration[] exp) {
314
this.exp = exp;
315
}
316
317
/**
318
* Resolve types in a field, after parsing.
319
* @see ClassDefinition.resolveTypeStructure
320
*/
321
322
public boolean resolved = false;
323
324
public void resolveTypeStructure(Environment env) {
325
if (tracing) env.dtEnter("SourceMember.resolveTypeStructure: " + this);
326
327
// A member should only be resolved once. For a constructor, it is imperative
328
// that 'addOuterThis' be called only once, else the outer instance argument may
329
// be inserted into the argument list multiple times.
330
331
if (resolved) {
332
if (tracing) env.dtEvent("SourceMember.resolveTypeStructure: OK " + this);
333
// This case shouldn't be happening. It is the responsibility
334
// of our callers to avoid attempting multiple resolutions of a member.
335
// *** REMOVE FOR SHIPMENT? ***
336
throw new CompilerError("multiple member type resolution");
337
//return;
338
} else {
339
if (tracing) env.dtEvent("SourceMember.resolveTypeStructure: RESOLVING " + this);
340
resolved = true;
341
}
342
343
super.resolveTypeStructure(env);
344
if (isInnerClass()) {
345
ClassDefinition nc = getInnerClass();
346
if (nc instanceof SourceClass && !nc.isLocal()) {
347
((SourceClass)nc).resolveTypeStructure(env);
348
}
349
type = innerClass.getType();
350
} else {
351
// Expand all class names in 'type', including those that are not
352
// fully-qualified or refer to inner classes, into fully-qualified
353
// names. Local and anonymous classes get synthesized names here,
354
// corresponding to the class files that will be generated. This is
355
// currently the only place where 'resolveNames' is used.
356
type = env.resolveNames(getClassDefinition(), type, isSynthetic());
357
358
// do the throws also:
359
getExceptions(env);
360
361
if (isMethod()) {
362
Vector argNames = args; args = null;
363
createArgumentFields(argNames);
364
// Add outer instance argument for constructors.
365
if (isConstructor()) {
366
addOuterThis();
367
}
368
}
369
}
370
if (tracing) env.dtExit("SourceMember.resolveTypeStructure: " + this);
371
}
372
373
/**
374
* Get the class declaration in which the field is actually defined
375
*/
376
public ClassDeclaration getDefiningClassDeclaration() {
377
if (abstractSource == null)
378
return super.getDefiningClassDeclaration();
379
else
380
return abstractSource.getDefiningClassDeclaration();
381
}
382
383
/**
384
* A source field never reports deprecation, since the compiler
385
* allows access to deprecated features that are being compiled
386
* in the same job.
387
*/
388
public boolean reportDeprecated(Environment env) {
389
return false;
390
}
391
392
/**
393
* Check this field.
394
* <p>
395
* This is the method which requests checking.
396
* The real work is done by
397
* <tt>Vset check(Environment, Context, Vset)</tt>.
398
*/
399
public void check(Environment env) throws ClassNotFound {
400
if (tracing) env.dtEnter("SourceMember.check: " +
401
getName() + ", status = " + status);
402
// rely on the class to check all fields in the proper order
403
if (status == PARSED) {
404
if (isSynthetic() && getValue() == null) {
405
// break a big cycle for small synthetic variables
406
status = CHECKED;
407
if (tracing)
408
env.dtExit("SourceMember.check: BREAKING CYCLE");
409
return;
410
}
411
if (tracing) env.dtEvent("SourceMember.check: CHECKING CLASS");
412
clazz.check(env);
413
if (status == PARSED) {
414
if (getClassDefinition().getError()) {
415
status = ERROR;
416
} else {
417
if (tracing)
418
env.dtExit("SourceMember.check: CHECK FAILED");
419
throw new CompilerError("check failed");
420
}
421
}
422
}
423
if (tracing) env.dtExit("SourceMember.check: DONE " +
424
getName() + ", status = " + status);
425
}
426
427
/**
428
* Check a field.
429
* @param vset tells which uplevel variables are definitely assigned
430
* The vset is also used to track the initialization of blank finals
431
* by whichever fields which are relevant to them.
432
*/
433
public Vset check(Environment env, Context ctx, Vset vset) throws ClassNotFound {
434
if (tracing) env.dtEvent("SourceMember.check: MEMBER " +
435
getName() + ", status = " + status);
436
if (status == PARSED) {
437
if (isInnerClass()) {
438
// some classes are checked separately
439
ClassDefinition nc = getInnerClass();
440
if (nc instanceof SourceClass && !nc.isLocal()
441
&& nc.isInsideLocal()) {
442
status = CHECKING;
443
vset = ((SourceClass)nc).checkInsideClass(env, ctx, vset);
444
}
445
status = CHECKED;
446
return vset;
447
}
448
if (env.dump()) {
449
System.out.println("[check field " + getClassDeclaration().getName() + "." + getName() + "]");
450
if (getValue() != null) {
451
getValue().print(System.out);
452
System.out.println();
453
}
454
}
455
env = new Environment(env, this);
456
457
// This is where all checking of names appearing within the type
458
// of the member is done. Includes return type and argument types.
459
// Since only one location ('where') for error messages is provided,
460
// localization of errors is poor. Throws clauses are handled below.
461
env.resolve(where, getClassDefinition(), getType());
462
463
// Make sure that all the classes that we claim to throw really
464
// are subclasses of Throwable, and are classes that we can reach
465
if (isMethod()) {
466
ClassDeclaration throwable =
467
env.getClassDeclaration(idJavaLangThrowable);
468
ClassDeclaration exp[] = getExceptions(env);
469
for (int i = 0 ; i < exp.length ; i++) {
470
ClassDefinition def;
471
long where = getWhere();
472
if (expIds != null && i < expIds.length) {
473
where = IdentifierToken.getWhere(expIds[i], where);
474
}
475
try {
476
def = exp[i].getClassDefinition(env);
477
478
// Validate access for all inner-class components
479
// of a qualified name, not just the last one, which
480
// is checked below. Yes, this is a dirty hack...
481
// Part of fix for 4094658.
482
env.resolveByName(where, getClassDefinition(), def.getName());
483
484
} catch (ClassNotFound e) {
485
env.error(where, "class.not.found", e.name, "throws");
486
break;
487
}
488
def.noteUsedBy(getClassDefinition(), where, env);
489
if (!getClassDefinition().
490
canAccess(env, def.getClassDeclaration())) {
491
env.error(where, "cant.access.class", def);
492
} else if (!def.subClassOf(env, throwable)) {
493
env.error(where, "throws.not.throwable", def);
494
}
495
}
496
}
497
498
status = CHECKING;
499
500
if (isMethod() && args != null) {
501
int length = args.size();
502
outer_loop:
503
for (int i = 0; i < length; i++) {
504
LocalMember lf = (LocalMember)(args.elementAt(i));
505
Identifier name_i = lf.getName();
506
for (int j = i + 1; j < length; j++) {
507
LocalMember lf2 = (LocalMember)(args.elementAt(j));
508
Identifier name_j = lf2.getName();
509
if (name_i.equals(name_j)) {
510
env.error(lf2.getWhere(), "duplicate.argument",
511
name_i);
512
break outer_loop;
513
}
514
}
515
}
516
}
517
518
if (getValue() != null) {
519
ctx = new Context(ctx, this);
520
521
if (isMethod()) {
522
Statement s = (Statement)getValue();
523
// initialize vset, indication that each of the arguments
524
// to the function has a value
525
526
for (Enumeration e = args.elements(); e.hasMoreElements();){
527
LocalMember f = (LocalMember)e.nextElement();
528
vset.addVar(ctx.declare(env, f));
529
}
530
531
if (isConstructor()) {
532
// Undefine "this" in some constructors, until after
533
// the super constructor has been called.
534
vset.clearVar(ctx.getThisNumber());
535
536
// If the first thing in the definition isn't a call
537
// to either super() or this(), then insert one.
538
Expression supCall = s.firstConstructor();
539
if ((supCall == null)
540
&& (getClassDefinition().getSuperClass() != null)) {
541
supCall = getDefaultSuperCall(env);
542
Statement scs = new ExpressionStatement(where,
543
supCall);
544
s = Statement.insertStatement(scs, s);
545
setValue(s);
546
}
547
}
548
549
//System.out.println("VSET = " + vset);
550
ClassDeclaration exp[] = getExceptions(env);
551
int htsize = (exp.length > 3) ? 17 : 7;
552
Hashtable thrown = new Hashtable(htsize);
553
554
vset = s.checkMethod(env, ctx, vset, thrown);
555
556
ClassDeclaration ignore1 =
557
env.getClassDeclaration(idJavaLangError);
558
ClassDeclaration ignore2 =
559
env.getClassDeclaration(idJavaLangRuntimeException);
560
561
for (Enumeration e = thrown.keys(); e.hasMoreElements();) {
562
ClassDeclaration c = (ClassDeclaration)e.nextElement();
563
ClassDefinition def = c.getClassDefinition(env);
564
if (def.subClassOf(env, ignore1)
565
|| def.subClassOf(env, ignore2)) {
566
continue;
567
}
568
569
boolean ok = false;
570
if (!isInitializer()) {
571
for (int i = 0 ; i < exp.length ; i++) {
572
if (def.subClassOf(env, exp[i])) {
573
ok = true;
574
}
575
}
576
}
577
if (!ok) {
578
Node n = (Node)thrown.get(c);
579
long where = n.getWhere();
580
String errorMsg;
581
582
if (isConstructor()) {
583
if (where ==
584
getClassDefinition().getWhere()) {
585
586
// If this message is being generated for
587
// a default constructor, we should give
588
// a different error message. Currently
589
// we check for this by seeing if the
590
// constructor has the same "where" as
591
// its class. This is a bit kludgy, but
592
// works. (bug id 4034836)
593
errorMsg = "def.constructor.exception";
594
} else {
595
// Constructor with uncaught exception.
596
errorMsg = "constructor.exception";
597
}
598
} else if (isInitializer()) {
599
// Initializer with uncaught exception.
600
errorMsg = "initializer.exception";
601
} else {
602
// Method with uncaught exception.
603
errorMsg = "uncaught.exception";
604
}
605
env.error(where, errorMsg, c.getName());
606
}
607
}
608
} else {
609
Hashtable thrown = new Hashtable(3); // small & throw-away
610
Expression val = (Expression)getValue();
611
612
vset = val.checkInitializer(env, ctx, vset,
613
getType(), thrown);
614
setValue(val.convert(env, ctx, getType(), val));
615
616
// Complain about static final members of inner classes that
617
// do not have an initializer that is a constant expression.
618
// In general, static members are not permitted for inner
619
// classes, but an exception is made for named constants.
620
// Other cases of static members, including non-final ones,
621
// are handled in 'SourceClass'. Part of fix for 4095568.
622
if (isStatic() && isFinal() && !clazz.isTopLevel()) {
623
if (!((Expression)getValue()).isConstant()) {
624
env.error(where, "static.inner.field", getName(), this);
625
setValue(null);
626
}
627
}
628
629
630
// Both RuntimeExceptions and Errors should be
631
// allowed in initializers. Fix for bug 4102541.
632
ClassDeclaration except =
633
env.getClassDeclaration(idJavaLangThrowable);
634
ClassDeclaration ignore1 =
635
env.getClassDeclaration(idJavaLangError);
636
ClassDeclaration ignore2 =
637
env.getClassDeclaration(idJavaLangRuntimeException);
638
639
for (Enumeration e = thrown.keys(); e.hasMoreElements(); ) {
640
ClassDeclaration c = (ClassDeclaration)e.nextElement();
641
ClassDefinition def = c.getClassDefinition(env);
642
643
if (!def.subClassOf(env, ignore1)
644
&& !def.subClassOf(env, ignore2)
645
&& def.subClassOf(env, except)) {
646
Node n = (Node)thrown.get(c);
647
env.error(n.getWhere(),
648
"initializer.exception", c.getName());
649
}
650
}
651
}
652
if (env.dump()) {
653
getValue().print(System.out);
654
System.out.println();
655
}
656
}
657
status = getClassDefinition().getError() ? ERROR : CHECKED;
658
}
659
660
661
// Initializers (static and instance) must be able to complete normally.
662
if (isInitializer() && vset.isDeadEnd()) {
663
env.error(where, "init.no.normal.completion");
664
vset = vset.clearDeadEnd();
665
}
666
667
return vset;
668
}
669
670
// helper to check(): synthesize a missing super() call
671
private Expression getDefaultSuperCall(Environment env) {
672
Expression se = null;
673
ClassDefinition sclass = getClassDefinition().getSuperClass().getClassDefinition();
674
// does the superclass constructor require an enclosing instance?
675
ClassDefinition reqc = (sclass == null) ? null
676
: sclass.isTopLevel() ? null
677
: sclass.getOuterClass();
678
ClassDefinition thisc = getClassDefinition();
679
if (reqc != null && !Context.outerLinkExists(env, reqc, thisc)) {
680
se = new SuperExpression(where, new NullExpression(where));
681
env.error(where, "no.default.outer.arg", reqc, getClassDefinition());
682
}
683
if (se == null) {
684
se = new SuperExpression(where);
685
}
686
return new MethodExpression(where, se, idInit, new Expression[0]);
687
}
688
689
/**
690
* Inline the field
691
*/
692
void inline(Environment env) throws ClassNotFound {
693
switch (status) {
694
case PARSED:
695
check(env);
696
inline(env);
697
break;
698
699
case CHECKED:
700
if (env.dump()) {
701
System.out.println("[inline field " + getClassDeclaration().getName() + "." + getName() + "]");
702
}
703
status = INLINING;
704
env = new Environment(env, this);
705
706
if (isMethod()) {
707
if ((!isNative()) && (!isAbstract())) {
708
Statement s = (Statement)getValue();
709
Context ctx = new Context((Context)null, this);
710
for (Enumeration e = args.elements() ; e.hasMoreElements() ;) {
711
LocalMember local = (LocalMember)e.nextElement();
712
ctx.declare(env, local);
713
}
714
setValue(s.inline(env, ctx));
715
}
716
} else if (isInnerClass()) {
717
// some classes are checked and inlined separately
718
ClassDefinition nc = getInnerClass();
719
if (nc instanceof SourceClass && !nc.isLocal()
720
&& nc.isInsideLocal()) {
721
status = INLINING;
722
((SourceClass)nc).inlineLocalClass(env);
723
}
724
status = INLINED;
725
break;
726
} else {
727
if (getValue() != null) {
728
Context ctx = new Context((Context)null, this);
729
if (!isStatic()) {
730
// Cf. "thisArg" in SourceClass.checkMembers().
731
Context ctxInst = new Context(ctx, this);
732
LocalMember thisArg =
733
((SourceClass)clazz).getThisArgument();
734
ctxInst.declare(env, thisArg);
735
setValue(((Expression)getValue())
736
.inlineValue(env, ctxInst));
737
} else {
738
setValue(((Expression)getValue())
739
.inlineValue(env, ctx));
740
}
741
}
742
}
743
if (env.dump()) {
744
System.out.println("[inlined field " + getClassDeclaration().getName() + "." + getName() + "]");
745
if (getValue() != null) {
746
getValue().print(System.out);
747
System.out.println();
748
} else {
749
System.out.println("<empty>");
750
}
751
}
752
status = INLINED;
753
break;
754
}
755
}
756
757
/**
758
* Get the value of the field (or null if the value can't be determined)
759
*/
760
public Node getValue(Environment env) throws ClassNotFound {
761
Node value = getValue();
762
if (value != null && status != INLINED) {
763
// be sure to get the imports right:
764
env = ((SourceClass)clazz).setupEnv(env);
765
inline(env);
766
value = (status == INLINED) ? getValue() : null;
767
}
768
return value;
769
}
770
771
public boolean isInlineable(Environment env, boolean fromFinal) throws ClassNotFound {
772
if (super.isInlineable(env, fromFinal)) {
773
getValue(env);
774
return (status == INLINED) && !getClassDefinition().getError();
775
}
776
return false;
777
}
778
779
780
/**
781
* Get the initial value of the field
782
*/
783
public Object getInitialValue() {
784
if (isMethod() || (getValue() == null) || (!isFinal()) || (status != INLINED)) {
785
return null;
786
}
787
return ((Expression)getValue()).getValue();
788
}
789
790
/**
791
* Generate code
792
*/
793
public void code(Environment env, Assembler asm) throws ClassNotFound {
794
switch (status) {
795
case PARSED:
796
check(env);
797
code(env, asm);
798
return;
799
800
case CHECKED:
801
inline(env);
802
code(env, asm);
803
return;
804
805
case INLINED:
806
// Actually generate code
807
if (env.dump()) {
808
System.out.println("[code field " + getClassDeclaration().getName() + "." + getName() + "]");
809
}
810
if (isMethod() && (!isNative()) && (!isAbstract())) {
811
env = new Environment(env, this);
812
Context ctx = new Context((Context)null, this);
813
Statement s = (Statement)getValue();
814
815
for (Enumeration e = args.elements() ; e.hasMoreElements() ; ) {
816
LocalMember f = (LocalMember)e.nextElement();
817
ctx.declare(env, f);
818
//ctx.declare(env, (LocalMember)e.nextElement());
819
}
820
821
/*
822
if (isConstructor() && ((s == null) || (s.firstConstructor() == null))) {
823
ClassDeclaration c = getClassDefinition().getSuperClass();
824
if (c != null) {
825
MemberDefinition field = c.getClassDefinition(env).matchMethod(env, getClassDefinition(), idInit);
826
asm.add(getWhere(), opc_aload, new Integer(0));
827
asm.add(getWhere(), opc_invokespecial, field);
828
asm.add(getWhere(), opc_pop);
829
}
830
831
// Output initialization code
832
for (MemberDefinition f = getClassDefinition().getFirstMember() ; f != null ; f = f.getNextMember()) {
833
if (!f.isStatic()) {
834
f.codeInit(env, ctx, asm);
835
}
836
}
837
}
838
*/
839
if (s != null) {
840
s.code(env, ctx, asm);
841
}
842
if (getType().getReturnType().isType(TC_VOID) && !isInitializer()) {
843
asm.add(getWhere(), opc_return, true);
844
}
845
}
846
return;
847
}
848
}
849
850
public void codeInit(Environment env, Context ctx, Assembler asm) throws ClassNotFound {
851
if (isMethod()) {
852
return;
853
}
854
switch (status) {
855
case PARSED:
856
check(env);
857
codeInit(env, ctx, asm);
858
return;
859
860
case CHECKED:
861
inline(env);
862
codeInit(env, ctx, asm);
863
return;
864
865
case INLINED:
866
// Actually generate code
867
if (env.dump()) {
868
System.out.println("[code initializer " + getClassDeclaration().getName() + "." + getName() + "]");
869
}
870
if (getValue() != null) {
871
Expression e = (Expression)getValue();
872
// The JLS Section 8.5 specifies that static (non-final)
873
// initializers should be executed in textual order. Eliding
874
// initializations to default values can interfere with this,
875
// so the tests for !e.equalsDefault() have been eliminated,
876
// below.
877
if (isStatic()) {
878
if (getInitialValue() == null) {
879
// removed: && !e.equalsDefault()) {
880
e.codeValue(env, ctx, asm);
881
asm.add(getWhere(), opc_putstatic, this);
882
}
883
} else { // removed: if (!e.equalsDefault()) {
884
// This code doesn't appear to be reached for
885
// instance initializers. Code for these is generated
886
// in the makeVarInits() method of the class
887
// MethodExpression.
888
asm.add(getWhere(), opc_aload, new Integer(0));
889
e.codeValue(env, ctx, asm);
890
asm.add(getWhere(), opc_putfield, this);
891
}
892
}
893
return;
894
}
895
}
896
897
/**
898
* Print for debugging
899
*/
900
public void print(PrintStream out) {
901
super.print(out);
902
if (getValue() != null) {
903
getValue().print(out);
904
out.println();
905
}
906
}
907
}
908
909