407 boolean hasFinally(JCTree target, Env<GenContext> env) {
408 while (env.tree != target) {
409 if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
410 return true;
411 env = env.next;
412 }
413 return false;
414 }
415
416 /* ************************************************************************
417 * Normalizing class-members.
418 *************************************************************************/
419
420 /** Distribute member initializer code into constructors and {@code <clinit>}
421 * method.
422 * @param defs The list of class member declarations.
423 * @param c The enclosing class.
424 */
425 List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
426 ListBuffer<JCStatement> initCode = new ListBuffer<>();
427 ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
428 ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
429 ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
430 ListBuffer<JCTree> methodDefs = new ListBuffer<>();
431 // Sort definitions into three listbuffers:
432 // - initCode for instance initializers
433 // - clinitCode for class initializers
434 // - methodDefs for method definitions
435 for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
436 JCTree def = l.head;
437 switch (def.getTag()) {
438 case BLOCK:
439 JCBlock block = (JCBlock)def;
440 if ((block.flags & STATIC) != 0)
441 clinitCode.append(block);
442 else if ((block.flags & SYNTHETIC) == 0)
443 initCode.append(block);
444 break;
445 case METHODDEF:
446 methodDefs.append(def);
447 break;
448 case VARDEF:
449 JCVariableDecl vdef = (JCVariableDecl) def;
450 VarSymbol sym = vdef.sym;
451 checkDimension(vdef.pos(), sym.type);
452 if (vdef.init != null) {
453 if ((sym.flags() & STATIC) == 0) {
454 // Always initialize instance variables.
455 JCStatement init = make.at(vdef.pos()).
456 Assignment(sym, vdef.init);
457 initCode.append(init);
458 endPosTable.replaceTree(vdef, init);
459 initTAs.addAll(getAndRemoveNonFieldTAs(sym));
460 } else if (sym.getConstValue() == null) {
461 // Initialize class (static) variables only if
462 // they are not compile-time constants.
463 JCStatement init = make.at(vdef.pos).
464 Assignment(sym, vdef.init);
465 clinitCode.append(init);
466 endPosTable.replaceTree(vdef, init);
467 clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
468 } else {
469 checkStringConstant(vdef.init.pos(), sym.getConstValue());
470 /* if the init contains a reference to an external class, add it to the
471 * constant's pool
472 */
473 vdef.init.accept(classReferenceVisitor);
474 }
475 }
476 break;
477 default:
478 Assert.error();
479 }
480 }
481 // Insert any instance initializers into all constructors.
482 if (initCode.length() != 0) {
483 List<JCStatement> inits = initCode.toList();
484 initTAs.addAll(c.getInitTypeAttributes());
485 List<Attribute.TypeCompound> initTAlist = initTAs.toList();
486 for (JCTree t : methodDefs) {
487 normalizeMethod((JCMethodDecl)t, inits, initTAlist);
488 }
489 }
490 // If there are class initializers, create a <clinit> method
491 // that contains them as its body.
492 if (clinitCode.length() != 0) {
493 MethodSymbol clinit = new MethodSymbol(
494 STATIC | (c.flags() & STRICTFP),
495 names.clinit,
496 new MethodType(
497 List.nil(), syms.voidType,
498 List.nil(), syms.methodClass),
499 c);
500 c.members().enter(clinit);
501 List<JCStatement> clinitStats = clinitCode.toList();
502 JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
503 block.endpos = TreeInfo.endPos(clinitStats.last());
504 methodDefs.append(make.MethodDef(clinit, block));
505
506 if (!clinitTAs.isEmpty())
507 clinit.appendUniqueTypeAttributes(clinitTAs.toList());
524 nonfieldTAs.add(ta);
525 }
526 }
527 sym.setTypeAttributes(fieldTAs.toList());
528 return nonfieldTAs.toList();
529 }
530
531 /** Check a constant value and report if it is a string that is
532 * too large.
533 */
534 private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
535 if (nerrs != 0 || // only complain about a long string once
536 constValue == null ||
537 !(constValue instanceof String str) ||
538 str.length() < PoolWriter.MAX_STRING_LENGTH)
539 return;
540 log.error(pos, Errors.LimitString);
541 nerrs++;
542 }
543
544 /** Insert instance initializer code into initial constructor.
545 * @param md The tree potentially representing a
546 * constructor's definition.
547 * @param initCode The list of instance initializer statements.
548 * @param initTAs Type annotations from the initializer expression.
549 */
550 void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
551 if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
552 // We are seeing a constructor that does not call another
553 // constructor of the same class.
554 List<JCStatement> stats = md.body.stats;
555 ListBuffer<JCStatement> newstats = new ListBuffer<>();
556
557 if (stats.nonEmpty()) {
558 // Copy initializers of synthetic variables generated in
559 // the translation of inner classes.
560 while (TreeInfo.isSyntheticInit(stats.head)) {
561 newstats.append(stats.head);
562 stats = stats.tail;
563 }
564 // Copy superclass constructor call
565 newstats.append(stats.head);
566 stats = stats.tail;
567 // Copy remaining synthetic initializers.
568 while (stats.nonEmpty() &&
569 TreeInfo.isSyntheticInit(stats.head)) {
570 newstats.append(stats.head);
571 stats = stats.tail;
572 }
573 // Now insert the initializer code.
574 newstats.appendList(initCode);
575 // And copy all remaining statements.
576 while (stats.nonEmpty()) {
577 newstats.append(stats.head);
578 stats = stats.tail;
579 }
580 }
581 md.body.stats = newstats.toList();
582 if (md.body.endpos == Position.NOPOS)
583 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
584
585 md.sym.appendUniqueTypeAttributes(initTAs);
586 }
587 }
588
589 /* ************************************************************************
590 * Traversal methods
591 *************************************************************************/
592
593 /** Visitor argument: The current environment.
594 */
595 Env<GenContext> env;
596
597 /** Visitor argument: The expected type (prototype).
598 */
599 Type pt;
600
601 /** Visitor result: The item representing the computed value.
602 */
603 Item result;
604
605 /** Visitor method: generate code for a definition, catching and reporting
606 * any completion failures.
607 * @param tree The definition to be visited.
608 * @param env The environment current at the definition.
1077 code.pendingStackMap = false;
1078
1079 return startpcCrt;
1080 }
1081
1082 public void visitVarDef(JCVariableDecl tree) {
1083 VarSymbol v = tree.sym;
1084 if (tree.init != null) {
1085 checkStringConstant(tree.init.pos(), v.getConstValue());
1086 if (v.getConstValue() == null || varDebugInfo) {
1087 Assert.check(code.isStatementStart());
1088 code.newLocal(v);
1089 genExpr(tree.init, v.erasure(types)).load();
1090 items.makeLocalItem(v).store();
1091 Assert.check(code.isStatementStart());
1092 }
1093 } else {
1094 code.newLocal(v);
1095 }
1096 checkDimension(tree.pos(), v.type);
1097 }
1098
1099 public void visitSkip(JCSkip tree) {
1100 }
1101
1102 public void visitBlock(JCBlock tree) {
1103 if (tree.patternMatchingCatch != null) {
1104 Set<JCMethodInvocation> prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch;
1105 ListBuffer<int[]> prevRanges = patternMatchingInvocationRanges;
1106 State startState = code.state.dup();
1107 try {
1108 invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle();
1109 patternMatchingInvocationRanges = new ListBuffer<>();
1110 doVisitBlock(tree);
1111 } finally {
1112 Chain skipCatch = code.branch(goto_);
1113 JCCatch handler = tree.patternMatchingCatch.handler();
1114 code.entryPoint(startState, handler.param.sym.type);
1115 genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList());
1116 code.resolve(skipCatch);
2344 items.makeThisItem().load();
2345 sym = binaryQualifier(sym, env.enclClass.type);
2346 result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2347 }
2348 }
2349
2350 //where
2351 private boolean nonVirtualForPrivateAccess(Symbol sym) {
2352 boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2353 !disableVirtualizedPrivateInvoke;
2354 return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2355 }
2356
2357 public void visitSelect(JCFieldAccess tree) {
2358 Symbol sym = tree.sym;
2359
2360 if (tree.name == names._class) {
2361 code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
2362 result = items.makeStackItem(pt);
2363 return;
2364 }
2365
2366 Symbol ssym = TreeInfo.symbol(tree.selected);
2367
2368 // Are we selecting via super?
2369 boolean selectSuper =
2370 ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2371
2372 // Are we accessing a member of the superclass in an access method
2373 // resulting from a qualified super?
2374 boolean accessSuper = isAccessSuper(env.enclMethod);
2375
2376 Item base = (selectSuper)
2377 ? items.makeSuperItem()
2378 : genExpr(tree.selected, tree.selected.type);
2379
2380 if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2381 // We are seeing a variable that is constant but its selecting
2382 // expression is not.
2383 if ((sym.flags() & STATIC) != 0) {
2384 if (!selectSuper && (ssym == null || ssym.kind != TYP))
|
407 boolean hasFinally(JCTree target, Env<GenContext> env) {
408 while (env.tree != target) {
409 if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
410 return true;
411 env = env.next;
412 }
413 return false;
414 }
415
416 /* ************************************************************************
417 * Normalizing class-members.
418 *************************************************************************/
419
420 /** Distribute member initializer code into constructors and {@code <clinit>}
421 * method.
422 * @param defs The list of class member declarations.
423 * @param c The enclosing class.
424 */
425 List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
426 ListBuffer<JCStatement> initCode = new ListBuffer<>();
427 // only used for value classes
428 ListBuffer<JCStatement> initBlocks = new ListBuffer<>();
429 ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
430 ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
431 ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
432 ListBuffer<JCTree> methodDefs = new ListBuffer<>();
433 // Sort definitions into three listbuffers:
434 // - initCode for instance initializers
435 // - clinitCode for class initializers
436 // - methodDefs for method definitions
437 for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
438 JCTree def = l.head;
439 switch (def.getTag()) {
440 case BLOCK:
441 JCBlock block = (JCBlock)def;
442 if ((block.flags & STATIC) != 0)
443 clinitCode.append(block);
444 else if ((block.flags & SYNTHETIC) == 0) {
445 if (c.isValueClass()) {
446 initBlocks.append(block);
447 } else {
448 initCode.append(block);
449 }
450 }
451 break;
452 case METHODDEF:
453 methodDefs.append(def);
454 break;
455 case VARDEF:
456 JCVariableDecl vdef = (JCVariableDecl) def;
457 VarSymbol sym = vdef.sym;
458 checkDimension(vdef.pos(), sym.type);
459 if (vdef.init != null) {
460 if ((sym.flags() & STATIC) == 0) {
461 // Always initialize instance variables.
462 JCStatement init = make.at(vdef.pos()).
463 Assignment(sym, vdef.init);
464 initCode.append(init);
465 endPosTable.replaceTree(vdef, init);
466 initTAs.addAll(getAndRemoveNonFieldTAs(sym));
467 } else if (sym.getConstValue() == null) {
468 // Initialize class (static) variables only if
469 // they are not compile-time constants.
470 JCStatement init = make.at(vdef.pos).
471 Assignment(sym, vdef.init);
472 clinitCode.append(init);
473 endPosTable.replaceTree(vdef, init);
474 clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
475 } else {
476 checkStringConstant(vdef.init.pos(), sym.getConstValue());
477 /* if the init contains a reference to an external class, add it to the
478 * constant's pool
479 */
480 vdef.init.accept(classReferenceVisitor);
481 }
482 }
483 break;
484 default:
485 Assert.error();
486 }
487 }
488 // Insert any instance initializers into all constructors.
489 if (initCode.length() != 0 || initBlocks.length() != 0) {
490 initTAs.addAll(c.getInitTypeAttributes());
491 List<Attribute.TypeCompound> initTAlist = initTAs.toList();
492 for (JCTree t : methodDefs) {
493 normalizeMethod((JCMethodDecl)t, initCode.toList(), initBlocks.toList(), initTAlist);
494 }
495 }
496 // If there are class initializers, create a <clinit> method
497 // that contains them as its body.
498 if (clinitCode.length() != 0) {
499 MethodSymbol clinit = new MethodSymbol(
500 STATIC | (c.flags() & STRICTFP),
501 names.clinit,
502 new MethodType(
503 List.nil(), syms.voidType,
504 List.nil(), syms.methodClass),
505 c);
506 c.members().enter(clinit);
507 List<JCStatement> clinitStats = clinitCode.toList();
508 JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
509 block.endpos = TreeInfo.endPos(clinitStats.last());
510 methodDefs.append(make.MethodDef(clinit, block));
511
512 if (!clinitTAs.isEmpty())
513 clinit.appendUniqueTypeAttributes(clinitTAs.toList());
530 nonfieldTAs.add(ta);
531 }
532 }
533 sym.setTypeAttributes(fieldTAs.toList());
534 return nonfieldTAs.toList();
535 }
536
537 /** Check a constant value and report if it is a string that is
538 * too large.
539 */
540 private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
541 if (nerrs != 0 || // only complain about a long string once
542 constValue == null ||
543 !(constValue instanceof String str) ||
544 str.length() < PoolWriter.MAX_STRING_LENGTH)
545 return;
546 log.error(pos, Errors.LimitString);
547 nerrs++;
548 }
549
550 /** Insert instance initializer code into constructors prior to the super() call.
551 * @param md The tree potentially representing a
552 * constructor's definition.
553 * @param initCode The list of instance initializer statements.
554 * @param initTAs Type annotations from the initializer expression.
555 */
556 void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<JCStatement> initBlocks, List<TypeCompound> initTAs) {
557 if (TreeInfo.isConstructor(md) && TreeInfo.hasConstructorCall(md, names._super)) {
558 // We are seeing a constructor that has a super() call.
559 // Find the super() invocation and append the given initializer code.
560 if (md.sym.owner.isValueClass()) {
561 rewriteInitializersIfNeeded(md, initCode);
562 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.append(supercall).appendList(initBlocks)));
563 } else {
564 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));
565 }
566
567 if (md.body.endpos == Position.NOPOS)
568 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
569
570 md.sym.appendUniqueTypeAttributes(initTAs);
571 }
572 }
573
574 void rewriteInitializersIfNeeded(JCMethodDecl md, List<JCStatement> initCode) {
575 if (lower.initializerOuterThis.containsKey(md.sym.owner)) {
576 InitializerVisitor initializerVisitor = new InitializerVisitor(md, lower.initializerOuterThis.get(md.sym.owner));
577 for (JCStatement init : initCode) {
578 initializerVisitor.scan(init);
579 }
580 }
581 }
582
583 class InitializerVisitor extends TreeScanner {
584 JCMethodDecl md;
585 Set<JCExpression> exprSet;
586
587 InitializerVisitor(JCMethodDecl md, Set<JCExpression> exprSet) {
588 this.md = md;
589 this.exprSet = exprSet;
590 }
591
592 @Override
593 public void visitTree(JCTree tree) {}
594
595 @Override
596 public void visitIdent(JCIdent tree) {
597 if (exprSet.contains(tree)) {
598 for (JCVariableDecl param: md.params) {
599 if (param.name == tree.name &&
600 ((param.sym.flags_field & (MANDATED | NOOUTERTHIS)) == (MANDATED | NOOUTERTHIS))) {
601 tree.sym = param.sym;
602 }
603 }
604 }
605 }
606 }
607
608 /* ************************************************************************
609 * Traversal methods
610 *************************************************************************/
611
612 /** Visitor argument: The current environment.
613 */
614 Env<GenContext> env;
615
616 /** Visitor argument: The expected type (prototype).
617 */
618 Type pt;
619
620 /** Visitor result: The item representing the computed value.
621 */
622 Item result;
623
624 /** Visitor method: generate code for a definition, catching and reporting
625 * any completion failures.
626 * @param tree The definition to be visited.
627 * @param env The environment current at the definition.
1096 code.pendingStackMap = false;
1097
1098 return startpcCrt;
1099 }
1100
1101 public void visitVarDef(JCVariableDecl tree) {
1102 VarSymbol v = tree.sym;
1103 if (tree.init != null) {
1104 checkStringConstant(tree.init.pos(), v.getConstValue());
1105 if (v.getConstValue() == null || varDebugInfo) {
1106 Assert.check(code.isStatementStart());
1107 code.newLocal(v);
1108 genExpr(tree.init, v.erasure(types)).load();
1109 items.makeLocalItem(v).store();
1110 Assert.check(code.isStatementStart());
1111 }
1112 } else {
1113 code.newLocal(v);
1114 }
1115 checkDimension(tree.pos(), v.type);
1116 Type localType = v.erasure(types);
1117 if (localType.requiresPreload(env.enclClass.sym)) {
1118 poolWriter.enterPreloadClass((ClassSymbol) localType.tsym);
1119 }
1120 }
1121
1122 public void visitSkip(JCSkip tree) {
1123 }
1124
1125 public void visitBlock(JCBlock tree) {
1126 if (tree.patternMatchingCatch != null) {
1127 Set<JCMethodInvocation> prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch;
1128 ListBuffer<int[]> prevRanges = patternMatchingInvocationRanges;
1129 State startState = code.state.dup();
1130 try {
1131 invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle();
1132 patternMatchingInvocationRanges = new ListBuffer<>();
1133 doVisitBlock(tree);
1134 } finally {
1135 Chain skipCatch = code.branch(goto_);
1136 JCCatch handler = tree.patternMatchingCatch.handler();
1137 code.entryPoint(startState, handler.param.sym.type);
1138 genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList());
1139 code.resolve(skipCatch);
2367 items.makeThisItem().load();
2368 sym = binaryQualifier(sym, env.enclClass.type);
2369 result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2370 }
2371 }
2372
2373 //where
2374 private boolean nonVirtualForPrivateAccess(Symbol sym) {
2375 boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2376 !disableVirtualizedPrivateInvoke;
2377 return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2378 }
2379
2380 public void visitSelect(JCFieldAccess tree) {
2381 Symbol sym = tree.sym;
2382
2383 if (tree.name == names._class) {
2384 code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
2385 result = items.makeStackItem(pt);
2386 return;
2387 }
2388
2389 Symbol ssym = TreeInfo.symbol(tree.selected);
2390
2391 // Are we selecting via super?
2392 boolean selectSuper =
2393 ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2394
2395 // Are we accessing a member of the superclass in an access method
2396 // resulting from a qualified super?
2397 boolean accessSuper = isAccessSuper(env.enclMethod);
2398
2399 Item base = (selectSuper)
2400 ? items.makeSuperItem()
2401 : genExpr(tree.selected, tree.selected.type);
2402
2403 if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2404 // We are seeing a variable that is constant but its selecting
2405 // expression is not.
2406 if ((sym.flags() & STATIC) != 0) {
2407 if (!selectSuper && (ssym == null || ssym.kind != TYP))
|