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);
     }
 }