Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,12 @@ private static void handleExistsSubroutine(EmitterVisitor emitterVisitor, String
private static void handleExistsSubroutine(EmitterVisitor emitterVisitor, String operator, OperatorNode operatorNode) {
// exists &{"sub"}
operatorNode.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
emitterVisitor.pushCurrentPackage();
emitterVisitor.ctx.mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
"org/perlonjava/runtime/runtimetypes/GlobalVariable",
operator + "GlobalCodeRefAsScalar",
"(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;",
"(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;Ljava/lang/String;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;",
false);
EmitOperator.handleVoidContext(emitterVisitor);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ static void handleLocal(EmitterVisitor emitterVisitor, OperatorNode node) {
&& binNode.left instanceof OperatorNode sigNode && sigNode.operator.equals("$")
&& sigNode.operand instanceof IdentifierNode) {
Dereference.handleHashElementOperator(emitterVisitor.with(lvalueContext), binNode, "getForLocal");
} else if (varToLocal instanceof BinaryOperatorNode binNode && binNode.operator.equals("{")
&& binNode.left instanceof OperatorNode sigNode && sigNode.operator.equals("@")) {
Dereference.handleHashElementOperator(emitterVisitor.with(lvalueContext), binNode, "getForLocal");
} else if (varToLocal instanceof BinaryOperatorNode binNode && binNode.operator.equals("->")
&& binNode.right instanceof HashLiteralNode) {
// For arrow hash dereference (local $ref->{key}), use getForLocal via arrow deref path.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ public static RuntimeScalar findMethodInHierarchy(String methodName, String perl

if (GlobalVariable.existsGlobalCodeRef(normalizedClassMethodName)) {
RuntimeScalar codeRef = GlobalVariable.getGlobalCodeRef(normalizedClassMethodName);
if (!codeRef.getDefinedBoolean()) {
if (!RuntimeCode.isCodeDefined(codeRef)) {
continue;
}
cacheMethod(cacheKey, codeRef);
Expand All @@ -400,7 +400,7 @@ public static RuntimeScalar findMethodInHierarchy(String methodName, String perl
String autoloadName = (effectiveClassName.endsWith("::") ? effectiveClassName : effectiveClassName + "::") + "AUTOLOAD";
if (GlobalVariable.existsGlobalCodeRef(autoloadName)) {
RuntimeScalar autoload = GlobalVariable.getGlobalCodeRef(autoloadName);
if (autoload.getDefinedBoolean()) {
if (RuntimeCode.isCodeDefined(autoload)) {
// Use the AUTOLOAD sub's CvSTASH (packageName) for $AUTOLOAD,
// not the glob's package. Perl sets $AUTOLOAD in the package
// where the AUTOLOAD sub was compiled, which matters for closures
Expand Down Expand Up @@ -429,4 +429,4 @@ public enum MROAlgorithm {
C3,
DFS
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -454,11 +454,11 @@ private static String tryUserDefinedProperty(String property, Set<String> recurs
return userPropertyCache.get(subName);
}

// Look up the subroutine
RuntimeScalar codeRef = GlobalVariable.getGlobalCodeRef(subName);
if (codeRef == null || !codeRef.getDefinedBoolean()) {
// Look up the subroutine without autovivifying an empty CODE slot.
if (!GlobalVariable.isGlobalCodeRefDefined(subName)) {
return null;
}
RuntimeScalar codeRef = GlobalVariable.getGlobalCodeRef(subName);

try {
// Call the subroutine with an empty argument list
Expand Down Expand Up @@ -835,4 +835,4 @@ private static boolean isBlockProperty(String property) {
}
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -755,14 +755,16 @@ public static boolean isGlobalCodeRefDefined(String key) {
return false;
}

private static boolean codeSlotExists(RuntimeScalar var) {
return var != null
&& var.type == RuntimeScalarType.CODE
&& var.value instanceof RuntimeCode runtimeCode
&& (runtimeCode.defined() || runtimeCode.isDeclared);
}

public static RuntimeScalar existsGlobalCodeRefAsScalar(String key) {
RuntimeScalar var = globalCodeRefs.get(key);
if (var != null && var.type == RuntimeScalarType.CODE && var.value instanceof RuntimeCode runtimeCode) {
// Use the RuntimeCode.defined() method to check if the subroutine actually exists
// This checks methodHandle, constantValue, and compilerSupplier
return runtimeCode.defined() ? scalarTrue : scalarFalse;
}
return scalarFalse;
return codeSlotExists(var) ? scalarTrue : scalarFalse;
}

public static RuntimeScalar existsGlobalCodeRefAsScalar(RuntimeScalar key) {
Expand All @@ -772,8 +774,7 @@ public static RuntimeScalar existsGlobalCodeRefAsScalar(RuntimeScalar key) {
}
// Handle RuntimeCode objects by extracting the subroutine name
if (key.type == RuntimeScalarType.CODE && key.value instanceof RuntimeCode runtimeCode) {
// Use the RuntimeCode.defined() method to check if the subroutine actually exists
return runtimeCode.defined() ? scalarTrue : scalarFalse;
return (runtimeCode.defined() || runtimeCode.isDeclared) ? scalarTrue : scalarFalse;
}
return existsGlobalCodeRefAsScalar(key.toString());
}
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/org/perlonjava/runtime/runtimetypes/Overload.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static RuntimeScalar stringify(RuntimeScalar runtimeScalar) {
try {
// Prepare overload context and check if object is eligible for overloading
int blessId = RuntimeScalarType.blessedId(runtimeScalar);
if (blessId < 0) {
if (blessId != 0) {
OverloadContext ctx = OverloadContext.prepare(blessId);
if (ctx != null) {
// Try primary overload method
Expand Down Expand Up @@ -116,13 +116,13 @@ public static RuntimeScalar numify(RuntimeScalar runtimeScalar) {
System.err.println(" Input scalar: " + runtimeScalar);
System.err.println(" Input type: " + runtimeScalar.type);
System.err.println(" blessId: " + blessId);
if (blessId < 0) {
if (blessId != 0) {
System.err.println(" Blessed as: " + NameNormalizer.getBlessStr(blessId));
}
System.err.flush();
}

if (blessId < 0) {
if (blessId != 0) {
OverloadContext ctx = OverloadContext.prepare(blessId);

if (TRACE_OVERLOAD) {
Expand Down Expand Up @@ -182,7 +182,7 @@ public static RuntimeScalar numify(RuntimeScalar runtimeScalar) {
public static RuntimeScalar boolify(RuntimeScalar runtimeScalar) {
// Prepare overload context and check if object is eligible for overloading
int blessId = RuntimeScalarType.blessedId(runtimeScalar);
if (blessId < 0) {
if (blessId != 0) {
OverloadContext ctx = OverloadContext.prepare(blessId);
if (ctx != null) {
// Try primary overload method
Expand Down Expand Up @@ -211,7 +211,7 @@ public static RuntimeScalar boolify(RuntimeScalar runtimeScalar) {
public static RuntimeScalar bool_not(RuntimeScalar runtimeScalar) {
// Prepare overload context and check if object is eligible for overloading
int blessId = RuntimeScalarType.blessedId(runtimeScalar);
if (blessId < 0) {
if (blessId != 0) {
OverloadContext ctx = OverloadContext.prepare(blessId);
if (ctx != null) {
// Try primary overload method
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,7 @@ public boolean allowsFallbackAutogen() {
* @return OverloadContext instance if overloading is enabled, null otherwise
*/
public static OverloadContext prepare(int blessId) {
// Fast path: positive blessIds are non-overloaded classes (set at bless time)
// Negative blessIds indicate classes with overloads
// This saves ~10-20ns HashMap lookup per hash access
if (blessId > 0) {
if (blessId == 0) {
return null;
}

Expand Down
Loading
Loading