Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
More optimized hashCode, wip
  • Loading branch information
bioball committed Mar 12, 2025
commit a8b8c03601dbed89c20a2e49a8826060f2388b94
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -64,6 +64,8 @@ protected static void loadModule(URI uri, VmTyped instance) {
// (stdlib module objects are statically shared singletons when running on JVM)
// and ensure compile-time evaluation in AOT mode
instance.force(false, true);
//noinspection ResultOfMethodCallIgnored
instance.hashCode();
})
.close();
}
Expand Down
2 changes: 1 addition & 1 deletion pkl-core/src/main/java/org/pkl/core/runtime/VmClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
return classInfo.hashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
return Double.hashCode(convertValueTo(DataSizeUnit.BYTES));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
return Double.hashCode(getValue(DurationUnit.NANOS));
}

Expand Down
15 changes: 10 additions & 5 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmDynamic.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.MaterializedFrame;
import java.util.Objects;
import java.util.Set;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.pkl.core.PClassInfo;
import org.pkl.core.PObject;
Expand Down Expand Up @@ -117,18 +116,25 @@ public boolean equals(Object obj) {
var value = cursor.getValue();
assert value != null;
var otherValue = other.getCachedValue(key);
if (!value.equals(otherValue)) return false;
if (value == this) {
if (otherValue != other) return false;
} else {
if (!value.equals(otherValue)) return false;
}
}

return true;
}

@Override
@TruffleBoundary
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
if (cachedHash != 0) return cachedHash;

force(false);
// Seed the cache s.t. we short-circuit when coming back to hash the same value.
// The cached hash will be updated again with the final hash code value.
cachedHash = -1;
var result = 0;
var cursor = cachedValues.getEntries();

Expand All @@ -138,8 +144,7 @@ int computeHashCode(Set<VmValue> seenValues) {

var value = cursor.getValue();
assert value != null;
result +=
VmUtils.computeHashCode(key, seenValues) ^ VmUtils.computeHashCode(value, seenValues);
result += key.hashCode() ^ value.hashCode();
}

cachedHash = result;
Expand Down
3 changes: 1 addition & 2 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.frame.MaterializedFrame;
import java.util.Set;
import java.util.function.BiFunction;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.pkl.core.ast.PklRootNode;
Expand Down Expand Up @@ -174,7 +173,7 @@ public boolean equals(Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
return System.identityHashCode(this);
}
}
3 changes: 1 addition & 2 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmIntSeq.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.oracle.truffle.api.CompilerDirectives.ValueType;
import java.util.NoSuchElementException;
import java.util.PrimitiveIterator;
import java.util.Set;
import org.pkl.core.util.Nullable;

// Some code copied from kotlin.ranges.Progressions, kotlin.ranges.ProgressionIterators,
Expand Down Expand Up @@ -115,7 +114,7 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
if (isEmpty()) return 1;

var result = 1;
Expand Down
5 changes: 2 additions & 3 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmList.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.organicdesign.fp.collections.RrbTree;
import org.organicdesign.fp.collections.RrbTree.ImRrbt;
import org.organicdesign.fp.collections.RrbTree.MutRrbt;
Expand Down Expand Up @@ -444,13 +443,13 @@ public boolean equals(@Nullable Object other) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
int ret = 1;

for (Object item : rrbt) {
ret *= 31;
if (item != null) {
ret += VmUtils.computeHashCode(item, seenValues);
ret += item.hashCode();
}
}

Expand Down
8 changes: 5 additions & 3 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmListing.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.oracle.truffle.api.frame.MaterializedFrame;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.pkl.core.ast.member.ListingOrMappingTypeCastNode;
import org.pkl.core.ast.member.ObjectMember;
Expand Down Expand Up @@ -138,10 +137,13 @@ public boolean equals(@Nullable Object obj) {

@Override
@TruffleBoundary
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
if (cachedHash != 0) return cachedHash;

force(false);
// Seed the cache s.t. we short-circuit when coming back to hash the same value.
// The cached hash will be updated again with the final hash code value.
cachedHash = -1;
var result = 0;
var cursor = cachedValues.getEntries();

Expand All @@ -151,7 +153,7 @@ int computeHashCode(Set<VmValue> seenValues) {

var value = cursor.getValue();
assert value != null;
result = 31 * result + VmUtils.computeHashCode(value, seenValues);
result = 31 * result + value.hashCode();
}

cachedHash = result;
Expand Down
6 changes: 2 additions & 4 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import org.organicdesign.fp.collections.ImMap;
import org.organicdesign.fp.collections.MutMap;
Expand Down Expand Up @@ -280,13 +279,12 @@ public boolean equals(@Nullable Object other) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
var result = 0;
for (var entry : map) {
var key = entry.getKey();
var value = entry.getValue();
result +=
VmUtils.computeHashCode(key, seenValues) ^ VmUtils.computeHashCode(value, seenValues);
result += key.hashCode() ^ value.hashCode();
}
return result;
}
Expand Down
9 changes: 5 additions & 4 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.MaterializedFrame;
import java.util.Map;
import java.util.Set;
import javax.annotation.concurrent.GuardedBy;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.pkl.core.ast.member.ListingOrMappingTypeCastNode;
Expand Down Expand Up @@ -142,10 +141,13 @@ public boolean equals(Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
if (cachedHash != 0) return cachedHash;

force(false);
// Seed the cache s.t. we short-circuit when coming back to hash the same value.
// The cached hash will be updated again with the final hash code value.
cachedHash = -1;
var result = 0;
var cursor = cachedValues.getEntries();

Expand All @@ -155,8 +157,7 @@ int computeHashCode(Set<VmValue> seenValues) {

var value = cursor.getValue();
assert value != null;
result +=
VmUtils.computeHashCode(key, seenValues) ^ VmUtils.computeHashCode(value, seenValues);
result += key.hashCode() ^ value.hashCode();
}

cachedHash = result;
Expand Down
3 changes: 1 addition & 2 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmNull.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.pkl.core.runtime;

import com.oracle.truffle.api.CompilerDirectives.ValueType;
import java.util.Set;
import org.pkl.core.PNull;
import org.pkl.core.util.Nullable;

Expand Down Expand Up @@ -83,7 +82,7 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
return 0;
}

Expand Down
6 changes: 6 additions & 0 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ public final boolean iterateMembers(BiFunction<Object, ObjectMember, Boolean> co
}
return true;
}

protected boolean doEquals(VmObject other, Set<VmValue> seenValues) {
if (seenValues.contains(this)) {

}
}

/** Evaluates this object's members. Skips local, hidden, and external members. */
@Override
Expand Down
6 changes: 2 additions & 4 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmPair.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.oracle.truffle.api.CompilerDirectives.ValueType;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import org.pkl.core.Pair;
import org.pkl.core.util.Nullable;

Expand Down Expand Up @@ -108,9 +107,8 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
return VmUtils.computeHashCode(first, seenValues) * 31
+ VmUtils.computeHashCode(second, seenValues);
public int hashCode() {
return first.hashCode() * 31 + second.hashCode();
}

@Override
Expand Down
3 changes: 1 addition & 2 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmRegex.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.CompilerDirectives.ValueType;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.pkl.core.ValueFormatter;
Expand Down Expand Up @@ -73,7 +72,7 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
return pattern.pattern().hashCode();
}

Expand Down
4 changes: 2 additions & 2 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,13 @@ public boolean equals(@Nullable Object other) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
int ret = 1;

for (Object item : set) {
ret *= 31;
if (item != null) {
ret += VmUtils.computeHashCode(item, seenValues);
ret += item.hashCode();
}
}

Expand Down
3 changes: 1 addition & 2 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmTypeAlias.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import com.oracle.truffle.api.source.SourceSection;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.concurrent.GuardedBy;
import org.pkl.core.Member.SourceLocation;
import org.pkl.core.PObject;
Expand Down Expand Up @@ -272,7 +271,7 @@ public boolean equals(Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
return qualifiedName.hashCode();
}

Expand Down
8 changes: 5 additions & 3 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmTyped.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.MaterializedFrame;
import java.util.Set;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.pkl.core.Composite;
Expand Down Expand Up @@ -196,16 +195,19 @@ public boolean equals(@Nullable Object obj) {
}

@Override
int computeHashCode(Set<VmValue> seenValues) {
public int hashCode() {
if (cachedHash != 0) return cachedHash;
// Seed the cache s.t. we short-circuit when coming back to hash the same value.
// The cached hash will be updated again with the final hash code value.
force(false);
cachedHash = -1;

var result = 0;

for (var key : clazz.getAllRegularPropertyNames()) {
var value = getCachedValue(key);
assert value != null;
result = 31 * result + VmUtils.computeHashCode(value, seenValues);
result = 31 * result + value.hashCode();
}

cachedHash = result;
Expand Down
15 changes: 0 additions & 15 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -913,19 +913,4 @@ public static boolean shouldRunTypeCheck(VirtualFrame frame) {
return frame.getArguments().length != 4
|| frame.getArguments()[3] != VmUtils.SKIP_TYPECHECK_MARKER;
}

public static int computeHashCode(Object value, Set<VmValue> seenValues) {
if (value instanceof VmValue vmValue) {
if (seenValues.contains(vmValue)) {
return System.identityHashCode(value);
} else {
seenValues.add(vmValue);
var result = vmValue.computeHashCode(seenValues);
seenValues.remove(vmValue);
return result;
}
} else {
return value.hashCode();
}
}
}
Loading