You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by bl...@apache.org on 2016/10/09 16:26:47 UTC
groovy git commit: MOP2: first step in implementing the constant meta
class and facade
Repository: groovy
Updated Branches:
refs/heads/master 9e25a9a4a -> 7285ffcfe
MOP2: first step in implementing the constant meta class and facade
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/7285ffcf
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/7285ffcf
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/7285ffcf
Branch: refs/heads/master
Commit: 7285ffcfe5efbac1f47a59b1417bf7cf72b75606
Parents: 9e25a9a
Author: Jochen Theodorou <bl...@gmx.org>
Authored: Sun Oct 9 18:23:07 2016 +0200
Committer: Jochen Theodorou <bl...@gmx.org>
Committed: Sun Oct 9 18:23:32 2016 +0200
----------------------------------------------------------------------
.../internal/metaclass/MetaClassConstant.java | 50 +++++++++++
.../apache/groovy/internal/util/Function.java | 31 +++++++
.../internal/util/ReevaluatingReference.java | 88 ++++++++++++++++++++
.../apache/groovy/internal/util/Supplier.java | 31 +++++++
.../groovy/internal/util/UncheckedThrow.java | 1 +
.../org/apache/groovy/metaclass/MetaClass.java | 41 +++++++++
src/main/org/apache/groovy/metaclass/Realm.java | 51 ++++++++----
7 files changed, 278 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/7285ffcf/src/main/org/apache/groovy/internal/metaclass/MetaClassConstant.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/internal/metaclass/MetaClassConstant.java b/src/main/org/apache/groovy/internal/metaclass/MetaClassConstant.java
new file mode 100644
index 0000000..df5a7ec
--- /dev/null
+++ b/src/main/org/apache/groovy/internal/metaclass/MetaClassConstant.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.groovy.internal.metaclass;
+
+import groovy.lang.MetaClassImpl;
+import groovy.lang.MetaMethod;
+import org.apache.groovy.lang.annotation.Incubating;
+
+import java.lang.invoke.SwitchPoint;
+
+/**
+ * The one and only implementation of a meta class.
+ * INTERNAL USE ONLY.
+ */
+@Incubating
+public final class MetaClassConstant<T> {
+ private final SwitchPoint switchPoint = new SwitchPoint();
+ //TODO Joche: replace with real implementation
+ private final MetaClassImpl impl;
+
+ public MetaClassConstant(Class<T> clazz) {
+ impl = new MetaClassImpl(clazz);
+ }
+
+ public SwitchPoint getSwitchPoint() {
+ return switchPoint;
+ }
+
+ // TODO Jochen: replace with new MetaMethod
+ public MetaMethod getMethod(String name, Class[] parameters) {
+ return impl.pickMethod(name, parameters);
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/7285ffcf/src/main/org/apache/groovy/internal/util/Function.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/internal/util/Function.java b/src/main/org/apache/groovy/internal/util/Function.java
new file mode 100644
index 0000000..3a4fea5
--- /dev/null
+++ b/src/main/org/apache/groovy/internal/util/Function.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.groovy.internal.util;
+
+import org.apache.groovy.lang.annotation.Incubating;
+
+/**
+ * Backport of Java8 Function.
+ * INTERNAL USE ONLY.
+ */
+@Incubating
+public interface Function<T, R> {
+ R apply(T t);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/groovy/blob/7285ffcf/src/main/org/apache/groovy/internal/util/ReevaluatingReference.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/internal/util/ReevaluatingReference.java b/src/main/org/apache/groovy/internal/util/ReevaluatingReference.java
new file mode 100644
index 0000000..feeeea8
--- /dev/null
+++ b/src/main/org/apache/groovy/internal/util/ReevaluatingReference.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.groovy.internal.util;
+
+import org.apache.groovy.lang.annotation.Incubating;
+import org.codehaus.groovy.GroovyBugError;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
+import java.lang.ref.WeakReference;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * This class represents a reference to the most actual incarnation of a Metaclass.
+ * INTERNAL USE ONLY.
+ */
+@Incubating
+public class ReevaluatingReference<T> {
+ private static final MethodHandle FALLBACK_HANDLE;
+ static {
+ try {
+ //TODO Jochen: move the findSpecial to a central place together with others to easy security configuration
+ FALLBACK_HANDLE = AccessController.doPrivileged(new PrivilegedExceptionAction<MethodHandle>() {
+ @Override
+ public MethodHandle run() throws Exception {
+ return MethodHandles.lookup().findSpecial(
+ ReevaluatingReference.class, "replacePayLoad",
+ MethodType.methodType(Object.class),
+ ReevaluatingReference.class);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new GroovyBugError(e);
+ }
+ }
+
+ private final Supplier<T> valueSupplier;
+ private final Function<T, SwitchPoint> validationSupplier;
+ private final WeakReference<Class<T>> clazzRef;
+ private MethodHandle returnRef;
+
+
+ public ReevaluatingReference(Class clazz, Supplier<T> valueSupplier, Function<T, SwitchPoint> validationSupplier) {
+ this.valueSupplier = valueSupplier;
+ this.validationSupplier = validationSupplier;
+ clazzRef = new WeakReference<Class<T>>(clazz);
+ replacePayLoad();
+ }
+
+ private T replacePayLoad() {
+ T payload = valueSupplier.get();
+ MethodHandle ref = MethodHandles.constant(clazzRef.get(), payload);
+ SwitchPoint sp = validationSupplier.apply(payload);
+ returnRef = sp.guardWithTest(ref, FALLBACK_HANDLE);
+ return payload;
+ }
+
+ public T getPayload() {
+ T ref = null;
+ try {
+ ref = (T) returnRef.invokeExact();
+ } catch (Throwable throwable) {
+ UncheckedThrow.rethrow(throwable);
+ }
+ return ref;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/7285ffcf/src/main/org/apache/groovy/internal/util/Supplier.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/internal/util/Supplier.java b/src/main/org/apache/groovy/internal/util/Supplier.java
new file mode 100644
index 0000000..3a01785
--- /dev/null
+++ b/src/main/org/apache/groovy/internal/util/Supplier.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.groovy.internal.util;
+
+import org.apache.groovy.lang.annotation.Incubating;
+
+/**
+ * Backport of Java8 Supplier.
+ * INTERNAL USE ONLY.
+ */
+@Incubating
+public interface Supplier<T> {
+ T get();
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/7285ffcf/src/main/org/apache/groovy/internal/util/UncheckedThrow.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/internal/util/UncheckedThrow.java b/src/main/org/apache/groovy/internal/util/UncheckedThrow.java
index 75f2071..7f6cc8a 100644
--- a/src/main/org/apache/groovy/internal/util/UncheckedThrow.java
+++ b/src/main/org/apache/groovy/internal/util/UncheckedThrow.java
@@ -23,6 +23,7 @@ import org.apache.groovy.lang.annotation.Incubating;
/**
* Allows to throw a checked exception unchecked.
+ * INTERNAL USE ONLY.
*/
@Incubating
public class UncheckedThrow {
http://git-wip-us.apache.org/repos/asf/groovy/blob/7285ffcf/src/main/org/apache/groovy/metaclass/MetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/metaclass/MetaClass.java b/src/main/org/apache/groovy/metaclass/MetaClass.java
new file mode 100644
index 0000000..6ebe4fc
--- /dev/null
+++ b/src/main/org/apache/groovy/metaclass/MetaClass.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.groovy.metaclass;
+
+import groovy.lang.MetaMethod;
+import org.apache.groovy.internal.metaclass.MetaClassConstant;
+import org.apache.groovy.internal.util.ReevaluatingReference;
+import org.apache.groovy.lang.annotation.Incubating;
+
+/**
+ * A MetaClass within Groovy defines the behaviour of any given Groovy or Java class
+ */
+@Incubating
+public final class MetaClass<T> {
+ private final ReevaluatingReference<MetaClassConstant<T>> implRef;
+
+ MetaClass(ReevaluatingReference<MetaClassConstant<T>> implRef) {
+ this.implRef = implRef;
+ }
+
+ public MetaMethod getMethod(String name, Class[] parameters) {
+ return implRef.getPayload().getMethod(name, parameters);
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/7285ffcf/src/main/org/apache/groovy/metaclass/Realm.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/metaclass/Realm.java b/src/main/org/apache/groovy/metaclass/Realm.java
index 53b097a..d398c1c 100644
--- a/src/main/org/apache/groovy/metaclass/Realm.java
+++ b/src/main/org/apache/groovy/metaclass/Realm.java
@@ -19,30 +19,29 @@
package org.apache.groovy.metaclass;
-import groovy.lang.GroovySystem;
-import groovy.lang.MetaClass;
-import groovy.lang.MetaClassImpl;
-import groovy.lang.MetaClassRegistry;
+import org.apache.groovy.internal.metaclass.MetaClassConstant;
+import org.apache.groovy.internal.util.Function;
+import org.apache.groovy.internal.util.ReevaluatingReference;
+import org.apache.groovy.internal.util.Supplier;
import org.apache.groovy.lang.annotation.Incubating;
-import java.lang.ref.WeakReference;
-import java.util.Map;
+import java.lang.invoke.SwitchPoint;
import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
/**
* A Realm is the representation of a metaclass layer in a tree of realm objects.
*/
@Incubating
public final class Realm {
- public final static Realm ROOT = new Realm("Root", null);
+ private final static Realm ROOT = new Realm("ROOT", null);
private final String name;
private final Realm parent;
- private final ClassValue<MetaClass> cv = new ClassValue<MetaClass>() {
+ private final ClassValue<MetaClassConstant<?>> cv = new ClassValue<MetaClassConstant<?>>() {
@Override
- protected MetaClass computeValue(Class type) {
- return new MetaClassImpl(type);
+ @SuppressWarnings("unchecked")
+ protected MetaClassConstant<?> computeValue(Class<?> type) {
+ return new MetaClassConstant(type);
}
};
@@ -51,9 +50,13 @@ public final class Realm {
this.parent = parent;
}
- public Realm createRealm(String name) {
+ public static Realm newRealm(String name, Realm parent) {
Objects.requireNonNull(name, "missing realm name");
- return new Realm(name, this);
+ if (parent == null) {
+ return new Realm(name, ROOT);
+ } else {
+ return new Realm(name, parent);
+ }
}
@Override
@@ -64,7 +67,25 @@ public final class Realm {
'}';
}
- public MetaClass getMetaClass(Class<?> theClass) {
- return cv.get(theClass);
+ public <T> MetaClass<T> getMetaClass(final Class<T> theClass) {
+ Supplier<MetaClassConstant<T>> valueSupplier = new Supplier<MetaClassConstant<T>>() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public MetaClassConstant<T> get() {
+ return (MetaClassConstant<T>) cv.get(theClass);
+ }
+ };
+ Function<MetaClassConstant<T>, SwitchPoint> validationSupplier = new Function<MetaClassConstant<T>, SwitchPoint>() {
+ @Override
+ public SwitchPoint apply(MetaClassConstant<T> metaClassImpl) {
+ return metaClassImpl.getSwitchPoint();
+ }
+ };
+ ReevaluatingReference<MetaClassConstant<T>> ref = new ReevaluatingReference<>(
+ MetaClassConstant.class,
+ valueSupplier,
+ validationSupplier
+ );
+ return new MetaClass<>(ref);
}
}