Merge pull request #78 from Techcable/feature/asm-executors

Handle static event methods
This commit is contained in:
Zach 2016-03-12 12:20:35 -06:00
commit c231a1b9e9
2 changed files with 58 additions and 11 deletions

View file

@ -1,9 +1,9 @@
From 7e35c9c03a1fe023e8da7de1718f60e00298c6b5 Mon Sep 17 00:00:00 2001 From c1dc52ffb0997b633a552eb4fc6341de01a50e40 Mon Sep 17 00:00:00 2001
From: Techcable <Techcable@outlook.com> From: Techcable <Techcable@outlook.com>
Date: Thu, 3 Mar 2016 13:20:33 -0700 Date: Thu, 3 Mar 2016 13:20:33 -0700
Subject: [PATCH] Use ASM for event executors. Subject: [PATCH] Use ASM for event executors.
Uses method handles for private methods. Uses method handles for private or static methods.
diff --git a/pom.xml b/pom.xml diff --git a/pom.xml b/pom.xml
index 0b615b4..1ad108e 100644 index 0b615b4..1ad108e 100644
@ -68,6 +68,51 @@ index 0000000..9ff99e3
+ } + }
+ } + }
+} +}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
new file mode 100644
index 0000000..f60f010
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
@@ -0,0 +1,39 @@
+package com.destroystokyo.paper.event.executor;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import com.google.common.base.Preconditions;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.EventException;
+import org.bukkit.event.Listener;
+import org.bukkit.plugin.EventExecutor;
+
+public class StaticMethodHandleEventExecutor implements EventExecutor {
+ private final Class<? extends Event> eventClass;
+ private final MethodHandle handle;
+
+ public StaticMethodHandleEventExecutor(Class<? extends Event> eventClass, Method m) {
+ Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m);
+ this.eventClass = eventClass;
+ try {
+ m.setAccessible(true);
+ this.handle = MethodHandles.lookup().unreflect(m);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("Unable to set accessible", e);
+ }
+ }
+
+ @Override
+ public void execute(Listener listener, Event event) throws EventException {
+ if (!eventClass.isInstance(event)) return;
+ try {
+ handle.invoke(event);
+ } catch (Throwable t) {
+ throw new EventException(t);
+ }
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java
new file mode 100644 new file mode 100644
index 0000000..45c2330 index 0000000..45c2330
@ -264,10 +309,10 @@ index 0000000..62acbf8
+ } + }
+} +}
diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java
index 3b2c99e..7b92ce0 100644 index 3b2c99e..f9316d6 100644
--- a/src/main/java/org/bukkit/plugin/EventExecutor.java --- a/src/main/java/org/bukkit/plugin/EventExecutor.java
+++ b/src/main/java/org/bukkit/plugin/EventExecutor.java +++ b/src/main/java/org/bukkit/plugin/EventExecutor.java
@@ -4,9 +4,53 @@ import org.bukkit.event.Event; @@ -4,9 +4,55 @@ import org.bukkit.event.Event;
import org.bukkit.event.EventException; import org.bukkit.event.EventException;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@ -276,6 +321,7 @@ index 3b2c99e..7b92ce0 100644
+import java.lang.reflect.Modifier; +import java.lang.reflect.Modifier;
+ +
+import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor; +import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor;
+import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor;
+import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator; +import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator;
+import com.destroystokyo.paper.event.executor.asm.ClassDefiner; +import com.destroystokyo.paper.event.executor.asm.ClassDefiner;
+import com.google.common.base.Preconditions; +import com.google.common.base.Preconditions;
@ -292,9 +338,10 @@ index 3b2c99e..7b92ce0 100644
+ Preconditions.checkNotNull(m, "Null method"); + Preconditions.checkNotNull(m, "Null method");
+ Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); + Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount());
+ Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); + Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass);
+ Preconditions.checkArgument(!Modifier.isStatic(m.getModifiers()), "Static method %s", m.getName());
+ ClassDefiner definer = ClassDefiner.getInstance(); + ClassDefiner definer = ClassDefiner.getInstance();
+ if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { + if (Modifier.isStatic(m.getModifiers())) {
+ return new StaticMethodHandleEventExecutor(eventClass, m);
+ } if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) {
+ String name = ASMEventExecutorGenerator.generateName(); + String name = ASMEventExecutorGenerator.generateName();
+ byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name); + byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name);
+ Class<? extends EventExecutor> c = definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class); + Class<? extends EventExecutor> c = definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class);

View file

@ -1,4 +1,4 @@
From e6a7755229623e86993c9082866072172ce1801e Mon Sep 17 00:00:00 2001 From a069652a3ba0866cac4c632565af03258a99c17b Mon Sep 17 00:00:00 2001
From: DoctorDark <doctordark11@gmail.com> From: DoctorDark <doctordark11@gmail.com>
Date: Wed, 2 Mar 2016 01:17:06 -0600 Date: Wed, 2 Mar 2016 01:17:06 -0600
Subject: [PATCH] Configurable end credits when leaving the end Subject: [PATCH] Configurable end credits when leaving the end
@ -20,10 +20,10 @@ index 5504cfe..6dc7e4c 100644
+ } + }
} }
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index df58d6c..45b1ed8 100644 index 2ec82a2..59ea36d 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java --- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -526,9 +526,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -525,9 +525,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
public Entity c(int i) { public Entity c(int i) {
this.cj = true; this.cj = true;
@ -37,7 +37,7 @@ index df58d6c..45b1ed8 100644
this.viewingCredits = true; this.viewingCredits = true;
if (this.a(AchievementList.D)) { if (this.a(AchievementList.D)) {
this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(4, 0.0F)); this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(4, 0.0F));
@@ -546,7 +548,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -545,7 +547,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
} else { } else {
this.b((Statistic) AchievementList.y); this.b((Statistic) AchievementList.y);
} }
@ -47,7 +47,7 @@ index df58d6c..45b1ed8 100644
// CraftBukkit start // CraftBukkit start
TeleportCause cause = (this.dimension == 1 || i == 1) ? TeleportCause.END_PORTAL : TeleportCause.NETHER_PORTAL; TeleportCause cause = (this.dimension == 1 || i == 1) ? TeleportCause.END_PORTAL : TeleportCause.NETHER_PORTAL;
this.server.getPlayerList().changeDimension(this, i, cause); // PAIL: check all this this.server.getPlayerList().changeDimension(this, i, cause); // PAIL: check all this
@@ -557,6 +561,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -556,6 +560,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.cb = -1; this.cb = -1;
return this; return this;
} }