/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReflectionGetCallerClassNode.java

https://github.com/openjdk/jdk · Java · 115 lines · 66 code · 14 blank · 35 comment · 10 complexity · 92d98b93662627f57d13f2c3f1f17548 MD5 · raw file

  1. /*
  2. * Copyright (c) 2013, 2020, 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.
  8. *
  9. * This code is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * version 2 for more details (a copy is included in the LICENSE file that
  13. * accompanied this code).
  14. *
  15. * You should have received a copy of the GNU General Public License version
  16. * 2 along with this work; if not, write to the Free Software Foundation,
  17. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20. * or visit www.oracle.com if you need additional information or have any
  21. * questions.
  22. */
  23. package org.graalvm.compiler.replacements.nodes;
  24. import org.graalvm.compiler.debug.GraalError;
  25. import org.graalvm.compiler.graph.Node;
  26. import org.graalvm.compiler.graph.NodeClass;
  27. import org.graalvm.compiler.graph.spi.Canonicalizable;
  28. import org.graalvm.compiler.graph.spi.CanonicalizerTool;
  29. import org.graalvm.compiler.nodeinfo.NodeInfo;
  30. import org.graalvm.compiler.nodes.ConstantNode;
  31. import org.graalvm.compiler.nodes.FrameState;
  32. import org.graalvm.compiler.nodes.InvokeNode;
  33. import org.graalvm.compiler.nodes.spi.Lowerable;
  34. import org.graalvm.compiler.nodes.spi.LoweringTool;
  35. import jdk.vm.ci.meta.ConstantReflectionProvider;
  36. import jdk.vm.ci.meta.MetaAccessProvider;
  37. import jdk.vm.ci.meta.ResolvedJavaMethod;
  38. import jdk.vm.ci.meta.ResolvedJavaType;
  39. @NodeInfo
  40. public abstract class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable {
  41. public static final NodeClass<ReflectionGetCallerClassNode> TYPE = NodeClass.create(ReflectionGetCallerClassNode.class);
  42. protected ReflectionGetCallerClassNode(NodeClass<? extends ReflectionGetCallerClassNode> c, MacroParams p) {
  43. super(c, p);
  44. }
  45. @Override
  46. public Node canonical(CanonicalizerTool tool) {
  47. ConstantNode callerClassNode = getCallerClassNode(tool.getMetaAccess(), tool.getConstantReflection());
  48. if (callerClassNode != null) {
  49. return callerClassNode;
  50. }
  51. return this;
  52. }
  53. @Override
  54. public void lower(LoweringTool tool) {
  55. ConstantNode callerClassNode = getCallerClassNode(tool.getMetaAccess(), tool.getConstantReflection());
  56. if (callerClassNode != null) {
  57. graph().replaceFixedWithFloating(this, graph().addOrUniqueWithInputs(callerClassNode));
  58. } else {
  59. InvokeNode invoke = createInvoke();
  60. graph().replaceFixedWithFixed(this, invoke);
  61. invoke.lower(tool);
  62. }
  63. }
  64. /**
  65. * If inlining is deep enough this method returns a {@link ConstantNode} of the caller class by
  66. * walking the stack.
  67. *
  68. * @param metaAccess
  69. * @return ConstantNode of the caller class, or null
  70. */
  71. private ConstantNode getCallerClassNode(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
  72. // Walk back up the frame states to find the caller at the required depth.
  73. FrameState state = stateAfter();
  74. // Cf. JVM_GetCallerClass
  75. // NOTE: Start the loop at depth 1 because the current frame state does
  76. // not include the Reflection.getCallerClass() frame.
  77. for (int n = 1; state != null; state = state.outerFrameState(), n++) {
  78. ResolvedJavaMethod method = state.getMethod();
  79. switch (n) {
  80. case 0:
  81. throw GraalError.shouldNotReachHere("current frame state does not include the Reflection.getCallerClass frame");
  82. case 1:
  83. // Frame 0 and 1 must be caller sensitive (see JVM_GetCallerClass).
  84. if (!isCallerSensitive(method)) {
  85. return null; // bail-out; let JVM_GetCallerClass do the work
  86. }
  87. break;
  88. default:
  89. if (!ignoredBySecurityStackWalk(method)) {
  90. // We have reached the desired frame; return the holder class.
  91. ResolvedJavaType callerClass = method.getDeclaringClass();
  92. return ConstantNode.forConstant(constantReflection.asJavaClass(callerClass), metaAccess);
  93. }
  94. break;
  95. }
  96. }
  97. return null; // bail-out; let JVM_GetCallerClass do the work
  98. }
  99. protected abstract boolean isCallerSensitive(ResolvedJavaMethod method);
  100. protected abstract boolean ignoredBySecurityStackWalk(ResolvedJavaMethod method);
  101. }