Skip to content

Commit

Permalink
Use object self lock for object fields locking
Browse files Browse the repository at this point in the history
  • Loading branch information
warunalakshitha committed Mar 6, 2025
1 parent 24b6fe6 commit 26841f0
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
* Class that keep Ballerina locks based on lock name.
* Class that keep Ballerina locks based on lock name. Used for codegen.
*
* @since 1.2.0
*/
@SuppressWarnings("unused")
public class BLockStore {

/**
Expand All @@ -47,7 +48,7 @@ public BLockStore() {
}

/*
This is code generated method to get Ballerina lock and lock.
This is code generated method to get Ballerina global lock from lock name and lock.
*/
@SuppressWarnings("unused")
public void lock(Strand strand, String lockName) {
Expand All @@ -61,7 +62,21 @@ public void lock(Strand strand, String lockName) {
}

/*
This is code generated method to get Ballerina lock and unlock.
This is code generated method to get Ballerina object lock and lock.
*/
@SuppressWarnings("unused")
public void lock(Strand strand, ReentrantLock lock) {
try {
strand.yield();
lock.lock();
strand.acquiredLockCount++;
} finally {
strand.resume();
}
}

/*
This is code generated method to get Ballerina global lock from lock name and unlock.
*/
@SuppressWarnings("unused")
public void unlock(Strand strand, String lockName) {
Expand All @@ -74,6 +89,19 @@ public void unlock(Strand strand, String lockName) {
}
}

/*
This is code generated method to get Ballerina object lock and unlock.
*/
@SuppressWarnings("unused")
public void unlock(Strand strand, ReentrantLock lock) {
try {
strand.yield();
lock.unlock();
strand.acquiredLockCount--;
} finally {
strand.resume();
}
}

/*
This is code generated method check and panic before async call if strand is in lock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ public final class JvmConstants {
public static final String HASH_MAP = "java/util/HashMap";
public static final String PATH = "java/nio/file/Path";
public static final String SYSTEM = "java/lang/System";
public static final String REENTRANT_LOCK = "java/util/concurrent/locks/ReentrantLock";

// service objects, annotation processing related classes
public static final String ANNOTATION_UTILS = "io/ballerina/runtime/internal/utils/AnnotationUtils";
Expand Down Expand Up @@ -359,6 +360,7 @@ public final class JvmConstants {
public static final String CREATE_TYPES_METHOD = "$createTypes";
public static final String CREATE_TYPE_CONSTANTS_METHOD = "$createTypeConstants";
public static final String CREATE_TYPE_INSTANCES_METHOD = "$createTypeInstances";
public static final String CLASS_LOCK_VAR_NAME = "$lock";
public static final String GLOBAL_LOCK_NAME = "lock";
public static final String SERVICE_EP_AVAILABLE = "$serviceEPAvailable";
public static final String BAL_RUNTIME_VAR_NAME = "$balRuntime";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.OPTION;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.PATH;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.READONLY_TYPE;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REENTRANT_LOCK;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REG_EXP_ASSERTION;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REG_EXP_ATOM_QUANTIFIER;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REG_EXP_CAPTURING_GROUP;
Expand Down Expand Up @@ -360,6 +361,7 @@ public final class JvmSignatures {
public static final String LOAD_HANDLE_TYPE = "L" + HANDLE_TYPE + ";";
public static final String LOAD_INTEGER_TYPE = "L" + INTEGER_TYPE + ";";
public static final String LOAD_JSON_TYPE = "L" + JSON_TYPE + ";";
public static final String LOAD_LOCK = "L" + REENTRANT_LOCK + ";";
public static final String LOAD_NEVER_TYPE = "L" + NEVER_TYPE + ";";
public static final String LOAD_NULL_TYPE = "L" + NULL_TYPE + ";";
public static final String LOAD_OBJECT_TYPE = "L" + OBJECT_TYPE + ";";
Expand Down Expand Up @@ -402,6 +404,7 @@ public final class JvmSignatures {
public static final String PASS_OBJECT_RETURN_SAME_TYPE = "(L" + OBJECT + ";)TV;";
public static final String PASS_STRAND = "(L" + STRAND_CLASS + ";)V";
public static final String PASS_STRAND_AND_LOCK_NAME = "(L" + STRAND_CLASS + ";L" + STRING_VALUE + ";)V";
public static final String PASS_STRAND_AND_REENTRANT_LOCK = "(L" + STRAND_CLASS + ";L" + REENTRANT_LOCK + ";)V";
public static final String POPULATE_ATTACHED_FUNCTION = "([L" + METHOD_TYPE_IMPL + ";)V";
public static final String POPULATE_CONFIG_DATA = "(L" + BAL_RUNTIME + ";)[L" + VARIABLE_KEY + ";";
public static final String POPULATE_INITIAL_VALUES = "([L" + B_MAPPING_INITIAL_VALUE_ENTRY + ";)V";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.wso2.ballerinalang.compiler.bir.codegen.model.JIMethodCall;
import org.wso2.ballerinalang.compiler.bir.codegen.model.JTerminator;
import org.wso2.ballerinalang.compiler.bir.codegen.model.JavaMethodCall;
import org.wso2.ballerinalang.compiler.bir.codegen.split.JvmConstantsGen;
import org.wso2.ballerinalang.compiler.bir.model.BIRNode;
import org.wso2.ballerinalang.compiler.bir.model.BIROperand;
import org.wso2.ballerinalang.compiler.bir.model.BIRTerminator;
Expand All @@ -50,6 +49,7 @@
import org.wso2.ballerinalang.compiler.util.Name;
import org.wso2.ballerinalang.compiler.util.TypeTags;
import org.wso2.ballerinalang.compiler.util.Unifier;
import org.wso2.ballerinalang.util.Flags;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -93,6 +93,7 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.BAL_ENV_CLASS;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.BAL_EXTENSION;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_OBJECT;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CLASS_LOCK_VAR_NAME;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CURRENT_MODULE_VAR_NAME;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.DEFAULT_STRAND_DISPATCHER;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.DEFAULT_STRAND_NAME;
Expand Down Expand Up @@ -147,12 +148,14 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_ANYDATA_ARRAY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_BAL_ENV;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.LOAD_ARRAY_TYPE;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.LOAD_LOCK;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.MAP_PUT;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.MODULE_INITIALIZER;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.MULTIPLE_RECEIVE_CALL;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PASS_OBJECT_RETURN_OBJECT;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PASS_STRAND;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PASS_STRAND_AND_LOCK_NAME;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PASS_STRAND_AND_REENTRANT_LOCK;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RECEIVE_DATA;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RETURN_OBJECT;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SCHEDULE_CALL;
Expand Down Expand Up @@ -186,8 +189,7 @@ public class JvmTerminatorGen {
public JvmTerminatorGen(MethodVisitor mv, BIRVarToJVMIndexMap indexMap, LabelGenerator labelGen,
JvmErrorGen errorGen, PackageID packageID, JvmInstructionGen jvmInstructionGen,
JvmPackageGen jvmPackageGen, JvmTypeGen jvmTypeGen,
JvmCastGen jvmCastGen, JvmConstantsGen jvmConstantsGen,
AsyncDataCollector asyncDataCollector) {
JvmCastGen jvmCastGen, AsyncDataCollector asyncDataCollector) {

this.mv = mv;
this.indexMap = indexMap;
Expand All @@ -205,10 +207,9 @@ public JvmTerminatorGen(MethodVisitor mv, BIRVarToJVMIndexMap indexMap, LabelGen
this.asyncDataCollector = asyncDataCollector;
}

public void genTerminator(BIRTerminator terminator, BIRNode.BIRFunction func,
String funcName, int localVarOffset, int returnVarRefIndex,
BType attachedType, int channelMapVarIndex, int sendWorkerChannelNamesVar,
int receiveWorkerChannelNamesVar) {
public void genTerminator(BIRTerminator terminator, String moduleClassName, BIRNode.BIRFunction func,
String funcName, int localVarOffset, int returnVarRefIndex, BType attachedType,
int channelMapVarIndex, int sendWorkerChannelNamesVar, int receiveWorkerChannelNamesVar) {
switch (terminator.kind) {
case GOTO -> {
this.genGoToTerm((BIRTerminator.GOTO) terminator, funcName);
Expand Down Expand Up @@ -254,11 +255,11 @@ public void genTerminator(BIRTerminator terminator, BIRNode.BIRFunction func,
return;
}
case LOCK -> {
this.genLockTerm((BIRTerminator.Lock) terminator, funcName, localVarOffset);
this.genLockTerm((BIRTerminator.Lock) terminator, moduleClassName, func, funcName, localVarOffset);
return;
}
case UNLOCK -> {
this.genUnlockTerm((BIRTerminator.Unlock) terminator, funcName, localVarOffset);
this.genUnlockTerm((BIRTerminator.Unlock) terminator, moduleClassName, func, funcName, localVarOffset);
return;
}
case WK_SEND -> {
Expand Down Expand Up @@ -327,25 +328,35 @@ private void genCall(BIRTerminator.Call callIns, PackageID packageID, int localV
}
}

private void genLockTerm(BIRTerminator.Lock lockIns, String funcName, int localVarOffset) {
private void genLockTerm(BIRTerminator.Lock lockIns, String moduleClassName, BIRNode.BIRFunction func,
String funcName, int localVarOffset) {
Label gotoLabel = this.labelGen.getLabel(funcName + lockIns.lockedBB.id.value);
String initClassName = jvmPackageGen.lookupGlobalVarClassName(this.currentPackageName, LOCK_STORE_VAR_NAME);
String lockName = GLOBAL_LOCK_NAME + lockIns.lockId;
this.mv.visitFieldInsn(GETSTATIC, initClassName, LOCK_STORE_VAR_NAME, GET_LOCK_STORE);
this.mv.visitFieldInsn(GETSTATIC, this.moduleInitClass, LOCK_STORE_VAR_NAME, GET_LOCK_STORE);
this.mv.visitVarInsn(ALOAD, localVarOffset);
this.mv.visitLdcInsn(lockName);
this.mv.visitMethodInsn(INVOKEVIRTUAL, LOCK_STORE, "lock", PASS_STRAND_AND_LOCK_NAME, false);
if ((func.flags & Flags.ATTACHED) == Flags.ATTACHED && lockIns.lockVariables.isEmpty()) {
mv.visitVarInsn(ALOAD, 0);
this.mv.visitFieldInsn(GETFIELD, moduleClassName, CLASS_LOCK_VAR_NAME, LOAD_LOCK);
this.mv.visitMethodInsn(INVOKEVIRTUAL, LOCK_STORE, "lock", PASS_STRAND_AND_REENTRANT_LOCK, false);
} else {
this.mv.visitLdcInsn(GLOBAL_LOCK_NAME + lockIns.lockId);
this.mv.visitMethodInsn(INVOKEVIRTUAL, LOCK_STORE, "lock", PASS_STRAND_AND_LOCK_NAME, false);
}
this.mv.visitJumpInsn(GOTO, gotoLabel);
}

private void genUnlockTerm(BIRTerminator.Unlock unlockIns, String funcName, int localVarOffset) {
private void genUnlockTerm(BIRTerminator.Unlock unlockIns, String moduleClassName, BIRNode.BIRFunction func,
String funcName, int localVarOffset) {
Label gotoLabel = this.labelGen.getLabel(funcName + unlockIns.unlockBB.id.value);
String lockName = GLOBAL_LOCK_NAME + unlockIns.relatedLock.lockId;
String initClassName = jvmPackageGen.lookupGlobalVarClassName(this.currentPackageName, LOCK_STORE_VAR_NAME);
this.mv.visitFieldInsn(GETSTATIC, initClassName, LOCK_STORE_VAR_NAME, GET_LOCK_STORE);
this.mv.visitFieldInsn(GETSTATIC, this.moduleInitClass, LOCK_STORE_VAR_NAME, GET_LOCK_STORE);
this.mv.visitVarInsn(ALOAD, localVarOffset);
this.mv.visitLdcInsn(lockName);
this.mv.visitMethodInsn(INVOKEVIRTUAL, LOCK_STORE, "unlock", PASS_STRAND_AND_LOCK_NAME, false);
if ((func.flags & Flags.ATTACHED) == Flags.ATTACHED && unlockIns.relatedLock.lockVariables.isEmpty()) {
mv.visitVarInsn(ALOAD, 0);
this.mv.visitFieldInsn(GETFIELD, moduleClassName, CLASS_LOCK_VAR_NAME, LOAD_LOCK);
this.mv.visitMethodInsn(INVOKEVIRTUAL, LOCK_STORE, "unlock", PASS_STRAND_AND_REENTRANT_LOCK, false);
} else {
this.mv.visitLdcInsn(GLOBAL_LOCK_NAME + unlockIns.relatedLock.lockId);
this.mv.visitMethodInsn(INVOKEVIRTUAL, LOCK_STORE, "unlock", PASS_STRAND_AND_LOCK_NAME, false);
}
this.mv.visitJumpInsn(GOTO, gotoLabel);
}

Expand All @@ -363,7 +374,7 @@ private void genPlatformIns(JTerminator terminator, BType attachedType, int loca
BIRNode.BIRFunction func) {
switch (terminator.jTermKind) {
case J_METHOD_CALL -> this.genJCallTerm((JavaMethodCall) terminator, attachedType, localVarOffset);
case JI_METHOD_CALL -> this.genJICallTerm((JIMethodCall) terminator, localVarOffset, func, attachedType);
case JI_METHOD_CALL -> this.genJICallTerm((JIMethodCall) terminator, localVarOffset, func);
case JI_CONSTRUCTOR_CALL -> this.genJIConstructorTerm((JIConstructorCall) terminator);
case JI_METHOD_CLI_CALL -> this.genJICLICallTerm((JIMethodCLICall) terminator, localVarOffset);
default -> throw new BLangCompilerException("JVM generation is not supported for terminator instruction " +
Expand Down Expand Up @@ -425,7 +436,7 @@ private void genJCallTerm(JavaMethodCall callIns, BType attachedType, int localV
}
}

private void genJICallTerm(JIMethodCall callIns, int localVarOffset, BIRNode.BIRFunction func, BType attachedType) {
private void genJICallTerm(JIMethodCall callIns, int localVarOffset, BIRNode.BIRFunction func) {
boolean isInterface = callIns.invocationType == INVOKEINTERFACE;
int argIndex = 0;
if (callIns.invocationType == INVOKEVIRTUAL || isInterface) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.BAL_OPTIONAL;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_OBJECT;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CLASS_FILE_SUFFIX;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CLASS_LOCK_VAR_NAME;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.INSTANTIATE_FUNCTION;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.JVM_INIT_METHOD;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MAP_VALUE;
Expand All @@ -84,6 +85,7 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.OBJECT;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.POPULATE_INITIAL_VALUES_METHOD;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.RECORD_INIT_WRAPPER_NAME;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REENTRANT_LOCK;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.SPLIT_CLASS_SUFFIX;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.TYPEDESC_CLASS_PREFIX;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.TYPEDESC_VALUE;
Expand All @@ -99,6 +101,7 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_TYPEDESC;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INSTANTIATE;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INSTANTIATE_WITH_INITIAL_VALUES;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.LOAD_LOCK;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.OBJECT_TYPE_IMPL_INIT;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.POPULATE_INITIAL_VALUES;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RECORD_VALUE_CLASS;
Expand Down Expand Up @@ -475,7 +478,7 @@ private void createObjectValueClasses(BObjectType objectType, String className,
jvmConstantsGen, asyncDataCollector);
}

this.createObjectInit(cw);
this.createObjectInit(cw, className);
jvmObjectGen.createAndSplitCallMethod(cw, attachedFuncs, className, jvmCastGen);
jvmObjectGen.createAndSplitGetMethod(cw, fields, className, jvmCastGen);
jvmObjectGen.createAndSplitSetMethod(cw, fields, className, jvmCastGen);
Expand All @@ -492,6 +495,9 @@ private void createObjectFields(ClassWriter cw, Map<String, BField> fields) {
FieldVisitor fvb = cw.visitField(0, field.name.value, getTypeDesc(field.type), null, null);
fvb.visitEnd();
}
// visit object self lock field.
FieldVisitor fv = cw.visitField(ACC_PUBLIC, CLASS_LOCK_VAR_NAME, LOAD_LOCK, null, null);
fv.visitEnd();
}

private void createObjectMethods(ClassWriter cw, List<BIRFunction> attachedFuncs, String moduleClassName,
Expand Down Expand Up @@ -549,20 +555,25 @@ private void createObjectMethodsWithSplitClasses(ClassWriter cw, List<BIRFunctio
}
}

private void createObjectInit(ClassWriter cw) {

private void createObjectInit(ClassWriter cw, String className) {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, JVM_INIT_METHOD, OBJECT_TYPE_IMPL_INIT, null,
null);
mv.visitCode();

// load super
mv.visitVarInsn(ALOAD, 0);
// load type
mv.visitVarInsn(ALOAD, 1);
// invoke super(type);
mv.visitMethodInsn(INVOKESPECIAL, ABSTRACT_OBJECT_VALUE, JVM_INIT_METHOD, OBJECT_TYPE_IMPL_INIT, false);

// create object self lock
mv.visitVarInsn(ALOAD, 0);
mv.visitTypeInsn(NEW, REENTRANT_LOCK);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, REENTRANT_LOCK, JVM_INIT_METHOD, VOID_METHOD_DESC, false);
mv.visitFieldInsn(PUTFIELD, className, CLASS_LOCK_VAR_NAME, LOAD_LOCK);
mv.visitInsn(RETURN);
mv.visitMaxs(5, 5);
mv.visitMaxs(0, 0);
mv.visitEnd();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ static void genJFieldForInteropField(JFieldBIRFunction birFunc, ClassWriter clas
JvmErrorGen errorGen = new JvmErrorGen(mv, indexMap, instGen);
LabelGenerator labelGen = new LabelGenerator();
JvmTerminatorGen termGen = new JvmTerminatorGen(mv, indexMap, labelGen, errorGen, birModule, instGen,
jvmPackageGen, jvmTypeGen, jvmCastGen, jvmConstantsGen, asyncDataCollector);
jvmPackageGen, jvmTypeGen, jvmCastGen, asyncDataCollector);
mv.visitCode();

Label paramLoadLabel = labelGen.getLabel("param_load");
Expand Down
Loading

0 comments on commit 26841f0

Please sign in to comment.