yisaca / jvm

1 stars 0 forks source link

偏向锁撤销(InterpreterRuntime::monitorenter)流程 #1

Open yisaca opened 4 years ago

yisaca commented 4 years ago
#### 偏向锁撤销(InterpreterRuntime::monitorenter)流程

# 0 JVM使用偏向锁开关打开
    0.1 直接调用 ObjectSynchronizer::fast_enter
# 1 JVM使用偏向锁开关关闭
    0.1 直接调用 ObjectSynchronizer::slow_enter

#### ObjectSynchronizer::fast_enter

# 0 JVM使用偏向锁开关打开
    0.1 系统非处于safepoint,调用 revoke_and_rebias
        0.1.1 返回值是 BIAS_REVOKED_AND_REBIASED 直接退出,否则执行0.1.2
        0.1.2 执行slow_enter
    0.2 当前系统处于safepoint,执行revoke_at_safepoint,继续执行slow_enter
    0.3 到此步锁对象应该是非偏向模式,否则报错
# 1 JVM偏向锁开关关闭
    1.1 直接执行slow_enter

#### revoke_and_rebias 

# 注意:根据偏向锁获取逻辑,进入revoke_and_rebias会有多种case
    1 类关闭偏向情况 [LockRecord_addrss](竞争成功的线程已经将mark改为自己栈上的LockRecord地址)
    2 epoch过期情况 [suc_thread|epoch|age|*|101]
    3 偏向线程竞争情况 [suc_thread|epoch|age|*|101]
    1、2、3三种竞争情况都可以细化为:
        (a) 首次抢锁Thread_A和首次抢锁Thread_B同时竞争匿名线程的情况
        (b) 首次抢锁Thread_D遇到已经偏向曾经成功抢锁Thread_C的情况
    因此调用revoke_and_rebias的入参的mark情况比较多

# 1 如果对象匿名偏向且不需要尝试重偏向(匿名偏向[nothread|*|*|101] && attempt_rebias=false)
    1.1 尝试更新锁对象,将对象头hash置为0 & 锁状态置为无锁(001)& 分代年龄置为当前对象的分代[nohash|age|001]
    1.2 如果成成,返回BIAS_REVOKED(外层认为失败,会调用slow_eneter),否则执行0.3
    1.3 根据heuristic进行操作

# 2 如果对象是偏向模式(mark的最后三位101)
    2.1 类关闭偏向锁
        2.1.1 尝试直接将锁对象的mark替换为类的header
        2.1.2 不管是否成功都返回BIAS_REVOKED(外层认为失败,会调用slow_eneter),否则执行1.3
    2.2 对象epoch过期
        2.2.1 尝试重定向
            2.2.1.1 尝试更新锁对象,将线程更新为当前线程&分代为锁对象的分代&epoch为class的epoch 并且当前线程和上一轮竞争获胜线程一致 [当前thread|prototype的epoch|当前对象age|101]
            2.2.1.2 如果成功直接返回BIAS_REVOKED_AND_REBIASED(外层认为重定向成功),否则执行2.1.3
            2.2.1.3 根据heuristic进行操作
        2.2.2 不需要尝试重定向
            2.2.2.1 尝试更新锁对象,将对象头hash置为0 & 锁状态置为无锁(001)& 分代年龄置为锁对象的分代 [nohas|age|001]
            2.2.2.2 如果成功返回 BIAS_REVOKED(外层认为失败,会调用slow_eneter),否则执行2.2.3
            2.2.2.3 根据heuristic状态进行操作
...... 其他场景进入3

# 3 更新heuristic
    3.1 锁对象非偏向模式,返回 HR_NOT_BIASED
    3.2 如果之前批量重定向过&&经过比较长的时间才发生本次撤销&&撤销次数区间在(批量重定向阈值,批量撤销阈值]之间
        3.2.1 更新类的撤销次数复位为0
    3.3 如果更新后的撤销次数等于批量撤销阈值,返回 HR_BULK_REVOKE
    3.4 如果更新后的撤销次数等于批量重定向阈值,返回 HR_BULK_REBIAS
    3.5 返回HR_SINGLE_REVOKE

# 4 根据更新heuristic的结果进行处理
    4.1 如果更新heuristic返回 HR_NOT_BIASED,则向外层返回 NOT_BIASED(外层认为失败,会调用slow_eneter)
    4.2 如果如果更新heuristic返回 HR_SINGLE_REVOKE
        4.2.1 如果锁对象的thread是当前线程&&锁对象epoch没过期,直接调用 revoke_bias 并返回结果到外层,否则执行4.2.2
        4.2.2 VMThread执行撤销 revoke并返回结果到外层
    4.3 如果如果更新heuristic返回HR_BULK_REVOKE或者HR_BULK_REBIAS,VMThread执行撤销 bulk_revoke并返回结果到外层

#### revoke_bias (函数签名BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread))
# 0 锁对象的mark不是偏向锁模式(最后三位不是101),返回 NOT_BIASED
# 1 如果锁对象是匿名偏向
    1.1 如果 revoke_bias的方法入参不允许重偏向(allow_rebias),修改锁对象为非偏向模式(nohash|当前对象age|001)
    1.2 返回 BIAS_REVOKED
# 2 如果锁对象偏向的线程非存活状态
    2.1 如果revoke_bias的方法入参允许重偏向(allow_rebias),修改锁对象为可偏向模式(nothread|当前对象age|101)
    2.2 如果revoke_bias的方法入参不允许重偏向(allow_rebias),修改锁对象为非偏向模式(nohash|当前对象age|001)
    2.3 返回 BIAS_REVOKED
# 3 如果锁对象偏向线程存活
    3.1 找到偏向线程的栈上所有objectRef指向锁对象的LockRecord,将所有找到的LockRecord的displaced_header值置为NULL
        3.1.1 如果3.1中找到最早获取锁的LockRecord
            3.1.1.1 LockRecord的header置为非偏向模式(nohash|当前对象age|001)
            3.1.1.2 锁对象的mark置为LockRecord的指针
        3.1.2 如果3.1中没有找到最早获取锁的LockRecord
            3.1.2.1 如果revoke_bias的方法入参允许重偏向(allow_rebias),修改锁对象为可偏向模式(nothread|当前对象age|101)
            3.1.2.2 如果revoke_bias的方法入参不允许重偏向(allow_rebias),修改锁对象为非偏向模式(nohash|当前对象age|001)
        3.2 返回 BIAS_REVOKED

#### bulk_revoke_or_rebias_at_safepoint (oop o, bool bulk_rebias, bool attempt_rebias_of_object,JavaThread* requesting_thread)

//主要是对所属类修改epoch以及已经发生偏向的对象的epoch,对于已经构造好但是还没有被作为锁使用的同类对象,会出现实例和类epoch不一致情况
# 1 如果是批量重偏向
    1.1 如果锁对象所属类没有关闭偏向模式
        1.1.1 获取prev_epoch,批量重偏向会对类的epoch加1,获取cur_epoch
        1.1.2 遍历所有线程的所有栈,找到属于(当前锁对象所属类)的其他锁对象
            1.1.2.1 如果其他锁对象是偏向模式(mark最后三位101),修改其他对象的epoch为cur_epoch
            1.1.2.2 如果其他锁对象不是偏向模式,什么都不做
    1.2 如果锁对象所属类已经关闭偏向模式,什么都不做

    1.3 对当前锁对象执行 revoke_bias(入参allow_rebais == 锁对象所属类是偏向模式&&方法入口入参attempt_rebias_of_object期望尝试重偏向)
// 1 和 2 互斥
# 2 如果是批量撤销
    2.1 更新锁对象所属类为非偏向模式([nohash|age|001])
    2.2 遍历所有线程栈,找到属于(当前锁对象所属类)的其他锁对象
        2.2.1 如果如果其他锁对象是偏向模式(mark最后三位101),调用revoke_bias,其中入参allow_rebais默认为false
        2.2.2 如果其他锁对象不是偏向模式,什么都不做
    2.3 对当前锁对象执行 revoke_bias,入参allow_rebais指定为false
# 3 初始化 status_code = BiasedLocking::BIAS_REVOKED
# 4 如果当前锁对象是偏向模式 && 锁对象所属类是偏向模式
    4.1 锁对象的mark更新为[当前线程id|当前对象age|类的epoch|101]
    4.2 更新status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED
# 5 返回 status_code
yisaca commented 4 years ago

add some example entry cases to revoke_and_rebais

yisaca commented 4 years ago

add "bulk_revoke_or_rebias_at_safepoint" part