From af06b9d9a6a034a595b4ee471eb2df568a4437e3 Mon Sep 17 00:00:00 2001 From: Heshan Padmasiri Date: Sun, 4 Feb 2024 18:19:28 +0530 Subject: [PATCH 1/4] Cache repeated type calculations --- .../io/ballerina/runtime/api/types/Type.java | 36 +++++++++++++++++++ .../runtime/api/utils/TypeUtils.java | 23 +++++++++--- .../runtime/internal/types/BType.java | 17 +++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java index 54f15bf537a3..c1d4fbdadfe4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java @@ -31,6 +31,42 @@ */ public interface Type { + /** + * Set the referred type for this type once it has been calculated. This must be called the first time this + * calculation is done in order for {@code Type#getReferredTypeCache()} to work properly. This is non-blocking and + * will become eventually consistent. Expect {@code TypeUtils#getReferredType(Type)} tobe referentially transparent. + * + * @param type Type referred by this type. For non-reference types, this is the same type. + */ + void setReferredTypeCache(Type type); + + /** + * Get the type referred by this type if it has been already calculated. If it has not been already calculated will + * return null. For non-reference types, this will return the same type. This is non-blocking and will become + * eventually consistent. Expect {@code TypeUtils#getReferredType(Type)} tobe referentially transparent. + * + * @return Referred type of the type + */ + Type getReferredTypeCache(); + + /** + * Set the implied type for this type once it has been calculated. This must be called the first time this + * calculation is done in order for {@code Type#getImpliedTypeCache()} to work properly. This is non-blocking and + * will become eventually consistent. Expect {@code TypeUtils#getImpliedType(Type)} tobe referentially transparent. + * + * @param type Type implied by this type. For non-intersection types, this is the same type. + */ + void setImpliedTypeCache(Type type); + + /** + * Get the type implied by this type if it has been already calculated. If it has not been already calculated will + * return null. For non-intersection types, this will return the same type. This is non-blocking and will become + * eventually consistent. Expect {@code TypeUtils#getImpliedType(Type)} tobe referentially transparent. + * + * @return Implied type of the type + */ + Type getImpliedTypeCache(); + /** * Get the default value of the type. This is the value of an uninitialized variable of this type. * For value types, this is same as the value get from {@code BType#getInitValue()}. diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java index 9485472eafcf..0d9a30030a34 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java @@ -152,10 +152,17 @@ public static boolean isSameType(Type sourceType, Type targetType) { * @return the referred type if provided with a type reference type, else returns the original type */ public static Type getReferredType(Type type) { + Type referredType = type.getReferredTypeCache(); + if (referredType != null) { + return referredType; + } if (type.getTag() == TypeTags.TYPE_REFERENCED_TYPE_TAG) { - return getReferredType(((ReferenceType) type).getReferredType()); + referredType = getReferredType(((ReferenceType) type).getReferredType()); + } else { + referredType = type; } - return type; + type.setReferredTypeCache(referredType); + return referredType; } /** @@ -167,12 +174,18 @@ public static Type getReferredType(Type type) { * else returns the original type */ public static Type getImpliedType(Type type) { + Type impliedType = type.getImpliedTypeCache(); + if (impliedType != null) { + return impliedType; + } type = getReferredType(type); if (type.getTag() == TypeTags.INTERSECTION_TAG) { - return getImpliedType(((IntersectionType) type).getEffectiveType()); + impliedType = getImpliedType(((IntersectionType) type).getEffectiveType()); + } else { + impliedType = type; } - - return type; + type.setImpliedTypeCache(impliedType); + return impliedType; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java index d83b84517f7f..211b7a990758 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java @@ -42,6 +42,8 @@ public abstract class BType implements Type { protected Module pkg; protected Class valueClass; private int hashCode; + private Type referredTypeCache = null; + private Type impliedType = null; protected BType(String typeName, Module pkg, Class valueClass) { this.typeName = typeName; @@ -195,4 +197,19 @@ public long getFlags() { return 0; } + public void setReferredTypeCache(Type type) { + this.referredTypeCache = type; + } + + public Type getReferredTypeCache() { + return this.referredTypeCache; + } + + public void setImpliedTypeCache(Type type) { + this.impliedType = type; + } + + public Type getImpliedTypeCache() { + return this.impliedType; + } } From fa96700914fec788938336065702e26cd19674a1 Mon Sep 17 00:00:00 2001 From: Heshan Padmasiri Date: Mon, 5 Feb 2024 09:17:39 +0530 Subject: [PATCH 2/4] Add default implementations for type caches --- .../io/ballerina/runtime/api/types/Type.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java index c1d4fbdadfe4..24cd32c1386b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java @@ -31,6 +31,7 @@ */ public interface Type { + // TODO: remove default implementations when standard library types are updated /** * Set the referred type for this type once it has been calculated. This must be called the first time this * calculation is done in order for {@code Type#getReferredTypeCache()} to work properly. This is non-blocking and @@ -38,8 +39,8 @@ public interface Type { * * @param type Type referred by this type. For non-reference types, this is the same type. */ - void setReferredTypeCache(Type type); - + default void setReferredTypeCache(Type type) { + } /** * Get the type referred by this type if it has been already calculated. If it has not been already calculated will * return null. For non-reference types, this will return the same type. This is non-blocking and will become @@ -47,7 +48,9 @@ public interface Type { * * @return Referred type of the type */ - Type getReferredTypeCache(); + default Type getReferredTypeCache() { + return null; + } /** * Set the implied type for this type once it has been calculated. This must be called the first time this @@ -56,7 +59,8 @@ public interface Type { * * @param type Type implied by this type. For non-intersection types, this is the same type. */ - void setImpliedTypeCache(Type type); + default void setImpliedTypeCache(Type type) { + } /** * Get the type implied by this type if it has been already calculated. If it has not been already calculated will @@ -65,7 +69,9 @@ public interface Type { * * @return Implied type of the type */ - Type getImpliedTypeCache(); + default Type getImpliedTypeCache() { + return null; + } /** * Get the default value of the type. This is the value of an uninitialized variable of this type. From c0c17f82b23240c289fabbbb9ebf5b9c894cd4aa Mon Sep 17 00:00:00 2001 From: Heshan Padmasiri Date: Wed, 7 Feb 2024 07:00:35 +0530 Subject: [PATCH 3/4] Fix accessor names --- .../io/ballerina/runtime/api/types/Type.java | 8 ++++---- .../runtime/api/utils/TypeUtils.java | 8 ++++---- .../runtime/internal/types/BType.java | 20 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java index 24cd32c1386b..d035b0ce090d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java @@ -39,7 +39,7 @@ public interface Type { * * @param type Type referred by this type. For non-reference types, this is the same type. */ - default void setReferredTypeCache(Type type) { + default void setCachedReferredType(Type type) { } /** * Get the type referred by this type if it has been already calculated. If it has not been already calculated will @@ -48,7 +48,7 @@ default void setReferredTypeCache(Type type) { * * @return Referred type of the type */ - default Type getReferredTypeCache() { + default Type getCachedReferredType() { return null; } @@ -59,7 +59,7 @@ default Type getReferredTypeCache() { * * @param type Type implied by this type. For non-intersection types, this is the same type. */ - default void setImpliedTypeCache(Type type) { + default void setCachedImpliedType(Type type) { } /** @@ -69,7 +69,7 @@ default void setImpliedTypeCache(Type type) { * * @return Implied type of the type */ - default Type getImpliedTypeCache() { + default Type getCachedImpliedType() { return null; } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java index 0d9a30030a34..731b73b35e2d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/TypeUtils.java @@ -152,7 +152,7 @@ public static boolean isSameType(Type sourceType, Type targetType) { * @return the referred type if provided with a type reference type, else returns the original type */ public static Type getReferredType(Type type) { - Type referredType = type.getReferredTypeCache(); + Type referredType = type.getCachedReferredType(); if (referredType != null) { return referredType; } @@ -161,7 +161,7 @@ public static Type getReferredType(Type type) { } else { referredType = type; } - type.setReferredTypeCache(referredType); + type.setCachedReferredType(referredType); return referredType; } @@ -174,7 +174,7 @@ public static Type getReferredType(Type type) { * else returns the original type */ public static Type getImpliedType(Type type) { - Type impliedType = type.getImpliedTypeCache(); + Type impliedType = type.getCachedImpliedType(); if (impliedType != null) { return impliedType; } @@ -185,7 +185,7 @@ public static Type getImpliedType(Type type) { } else { impliedType = type; } - type.setImpliedTypeCache(impliedType); + type.setCachedImpliedType(impliedType); return impliedType; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java index 211b7a990758..866432570c59 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java @@ -42,8 +42,8 @@ public abstract class BType implements Type { protected Module pkg; protected Class valueClass; private int hashCode; - private Type referredTypeCache = null; - private Type impliedType = null; + private Type cachedReferredType = null; + private Type cachedImpliedType = null; protected BType(String typeName, Module pkg, Class valueClass) { this.typeName = typeName; @@ -197,19 +197,19 @@ public long getFlags() { return 0; } - public void setReferredTypeCache(Type type) { - this.referredTypeCache = type; + public void setCachedReferredType(Type type) { + this.cachedReferredType = type; } - public Type getReferredTypeCache() { - return this.referredTypeCache; + public Type getCachedReferredType() { + return this.cachedReferredType; } - public void setImpliedTypeCache(Type type) { - this.impliedType = type; + public void setCachedImpliedType(Type type) { + this.cachedImpliedType = type; } - public Type getImpliedTypeCache() { - return this.impliedType; + public Type getCachedImpliedType() { + return this.cachedImpliedType; } } From b044eba099c61bc50430d0d749b7f22294a984c3 Mon Sep 17 00:00:00 2001 From: Heshan Padmasiri Date: Mon, 12 Feb 2024 13:20:02 +0530 Subject: [PATCH 4/4] Fix wording in doc comments Co-authored-by: Hinduja Balasubramaniyam <28644893+HindujaB@users.noreply.github.com> --- .../io/ballerina/runtime/api/types/Type.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java index d035b0ce090d..6d1abcd9e60b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/Type.java @@ -34,17 +34,18 @@ public interface Type { // TODO: remove default implementations when standard library types are updated /** * Set the referred type for this type once it has been calculated. This must be called the first time this - * calculation is done in order for {@code Type#getReferredTypeCache()} to work properly. This is non-blocking and - * will become eventually consistent. Expect {@code TypeUtils#getReferredType(Type)} tobe referentially transparent. + * calculation is done for {@code Type#getReferredTypeCache()} to work properly. This is non-blocking and + * will eventually become consistent. Expect {@code TypeUtils#getReferredType(Type)} to be referentially + * transparent. * * @param type Type referred by this type. For non-reference types, this is the same type. */ default void setCachedReferredType(Type type) { } /** - * Get the type referred by this type if it has been already calculated. If it has not been already calculated will - * return null. For non-reference types, this will return the same type. This is non-blocking and will become - * eventually consistent. Expect {@code TypeUtils#getReferredType(Type)} tobe referentially transparent. + * Get the type referred by this type if it has been already calculated. If it has not been already calculated, it + * will return null. For non-reference types, this will return the same type. This is non-blocking and will + * eventually become consistent. Expect {@code TypeUtils#getReferredType(Type)} to be referentially transparent. * * @return Referred type of the type */ @@ -54,8 +55,8 @@ default Type getCachedReferredType() { /** * Set the implied type for this type once it has been calculated. This must be called the first time this - * calculation is done in order for {@code Type#getImpliedTypeCache()} to work properly. This is non-blocking and - * will become eventually consistent. Expect {@code TypeUtils#getImpliedType(Type)} tobe referentially transparent. + * calculation is done for {@code Type#getImpliedTypeCache()} to work properly. This is non-blocking and + * will eventually become consistent. Expect {@code TypeUtils#getImpliedType(Type)} to be referentially transparent. * * @param type Type implied by this type. For non-intersection types, this is the same type. */ @@ -63,9 +64,9 @@ default void setCachedImpliedType(Type type) { } /** - * Get the type implied by this type if it has been already calculated. If it has not been already calculated will - * return null. For non-intersection types, this will return the same type. This is non-blocking and will become - * eventually consistent. Expect {@code TypeUtils#getImpliedType(Type)} tobe referentially transparent. + * Get the type implied by this type if it has been already calculated. If it has not been already calculated, it + * will return null. For non-intersection types, this will return the same type. This is non-blocking and will + * eventually become consistent. Expect {@code TypeUtils#getImpliedType(Type)} to be referentially transparent. * * @return Implied type of the type */