/src/patches/jdk/inti.patch

https://github.com/ohpauleez/soymacchiato · Patch · 147 lines · 147 code · 0 blank · 0 comment · 0 complexity · 0bed255e4cf12475e1aa2b9bdab46738 MD5 · raw file

  1. diff --git a/src/share/classes/java/dyn/InterfaceImplementor.java b/src/share/classes/java/dyn/InterfaceImplementor.java
  2. new file mode 100644
  3. --- /dev/null
  4. +++ b/src/share/classes/java/dyn/InterfaceImplementor.java
  5. @@ -0,0 +1,38 @@
  6. +package java.dyn;
  7. +
  8. +import java.util.Map;
  9. +import java.util.HashMap;
  10. +
  11. +/**
  12. + * An interface implementor is used to provide the {@link MethodHandle}s that
  13. + * are required to implement an interface upon injection.
  14. + *
  15. + * @author Tobias Ivarsson (tobias@thobe.org)
  16. + */
  17. +public interface InterfaceImplementor {
  18. + public class DefaultImplementation implements InterfaceImplementor {
  19. + private final Map<String, MethodHandle> implementations =
  20. + new HashMap<String, MethodHandle>();
  21. +
  22. + public DefaultImplementation(String[] names, MethodHandle[] impls) {
  23. + if (names.length != impls.length) {
  24. + throw new IllegalArgumentException(
  25. + "Arrays not of matching lengths.");
  26. + }
  27. + for (int i = 0; i < names.length; i++) {
  28. + implementations.put(signature(names[i], impls[i].type()),
  29. + impls[i]);
  30. + }
  31. + }
  32. +
  33. + public MethodHandle getImplementation(String name, MethodType type) {
  34. + return implementations.get(signature(name, type));
  35. + }
  36. +
  37. + private String signature(String name, MethodType type) {
  38. + return name + type.toBytecodeString();
  39. + }
  40. + }
  41. +
  42. + MethodHandle getImplementation(String name, MethodType type);
  43. +}
  44. diff --git a/src/share/classes/java/dyn/InterfaceInjector.java b/src/share/classes/java/dyn/InterfaceInjector.java
  45. new file mode 100644
  46. --- /dev/null
  47. +++ b/src/share/classes/java/dyn/InterfaceInjector.java
  48. @@ -0,0 +1,99 @@
  49. +package java.dyn;
  50. +
  51. +/**
  52. + * An interface injector is the object used for injecting an interface into a
  53. + * {@link java.lang.Class}.
  54. + *
  55. + * @author Tobias Ivarsson (tobias@thobe.org)
  56. + */
  57. +public abstract class InterfaceInjector {
  58. + public abstract InterfaceImplementor inject(Class<?> iface, Class<?> target);
  59. +
  60. + public static void setInjector(InterfaceInjector injector) {
  61. + InjectorSetup current = setup.get();
  62. + if (current == null)
  63. + throw new IllegalStateException("Not called from interface class initializer.");
  64. + Class cc = sun.reflect.Reflection.getCallerClass(2);
  65. + if (cc != current.iface)
  66. + throw new IllegalStateException("Not called from interface class initializer.");
  67. + current.set(injector);
  68. + }
  69. +
  70. + // Implementation internals
  71. + private static class InjectorSetup {
  72. + private InterfaceInjector injector = null;
  73. + final Class<?> iface;
  74. + private final InjectorSetup last;
  75. + InjectorSetup(Class<?> iface) {
  76. + this.iface = iface;
  77. + this.last = setup.get();
  78. + }
  79. + void set(InterfaceInjector injector) {
  80. + if (this.injector != null)
  81. + throw new IllegalStateException("Injector already specified for " + iface);
  82. + this.injector = injector;
  83. + }
  84. + void pop(Class<?> iface) {
  85. + if (iface != this.iface) {
  86. + return last.pop(iface);
  87. + } else {
  88. + setup.set(last);
  89. + return injector;
  90. + }
  91. + }
  92. + }
  93. +
  94. + private static final ThreadLocal<InjectorSetup> setup =
  95. + new ThreadLocal<InjectorSetup>() {
  96. + @Override
  97. + protected InjectorSetup initialValue() {
  98. + return new InjectorSetup(null) {
  99. + @Override
  100. + void pop(Class<?> iface) {
  101. + setup.set(this)
  102. + }
  103. + };
  104. + }
  105. + };
  106. +
  107. + private MethodHandle getHandle(Class<?> target,
  108. + InterfaceImplementor implementor,
  109. + String name, MethodType type) {
  110. + MethodHandle result = MethodHandles.findVirtual(target, name, type);
  111. + if (result == null) {
  112. + result = implementor.getImplementation(name, type);
  113. + }
  114. + return result;
  115. + }
  116. +
  117. + // interface for the VM
  118. +
  119. + /* Called by the JVM to get the implementation for an injected interface. */
  120. + private MethodHandle[] performInjection(Class<?> target, Class<?> iface,
  121. + String[] names,MethodType[] types) {
  122. + System.out.println("Trying to inject " + iface " into " + taget);
  123. + // Pull based interface - only ask for the required methods
  124. + InterfaceImplementor implementor = inject(iface, target);
  125. + if (implementor == null) {
  126. + return null;
  127. + }
  128. + try {
  129. + MethodHandle[] result = new MethodHandle[types.length];
  130. + for (int i = 0; i < types.length; i++) {
  131. + MethodHandle handle = getHandle(target, implementor,
  132. + names[i], types[i]);
  133. + }
  134. + } catch(Throwable t) {
  135. + return null;
  136. + }
  137. + return null; // TODO
  138. + }
  139. + /* Called by the JVM before invoking <clinit> on an injectable interface. */
  140. + private static void beforeClassInit(Class<?> iface) {
  141. + setup.set(new InjectorSetup(iface));
  142. + }
  143. + /* Called by the JVM after invoking <clinit> on an injectable interface. */
  144. + private static InterfaceInjector afterClassInit(Class<?> iface) {
  145. + return setup.get().pop(iface);
  146. + }
  147. +}