Generalize bytecode fast-call dispatch

This commit is contained in:
Sergey Chernov 2026-04-21 13:09:50 +03:00
parent fc7d26ee4b
commit db3a780645
2 changed files with 23 additions and 11 deletions

View File

@ -3291,13 +3291,16 @@ class CmdCallDirect(
} }
} }
val result = if (PerfFlags.SCOPE_POOL) { val result = if (PerfFlags.SCOPE_POOL) {
frame.ensureScope().withChildFrame(args) { child -> callee.callOn(child) } frame.ensureScope().withChildFrame(args) { child ->
(callee as? BytecodeCallable)?.callOnFast(child) ?: callee.callOn(child)
}
} else { } else {
val scope = frame.ensureScope() val scope = frame.ensureScope()
if (callee is BytecodeLambdaCallable && callee.supportsDirectInvokeFastPath()) { if (callee is BytecodeLambdaCallable && callee.supportsDirectInvokeFastPath()) {
callee.invokeWithArgsFast(scope, args) ?: callee.invokeWithArgs(scope, args) callee.invokeWithArgsFast(scope, args) ?: callee.invokeWithArgs(scope, args)
} else { } else {
callee.callOn(scope.createChildScope(scope.pos, args = args)) val child = scope.createChildScope(scope.pos, args = args)
(callee as? BytecodeCallable)?.callOnFast(child) ?: callee.callOn(child)
} }
} }
frame.storeObjResult(dst, result) frame.storeObjResult(dst, result)
@ -3327,7 +3330,9 @@ class CmdCallSlot(
val args = frame.buildArguments(argBase, argCount) val args = frame.buildArguments(argBase, argCount)
val canPool = PerfFlags.SCOPE_POOL && callee !is Statement val canPool = PerfFlags.SCOPE_POOL && callee !is Statement
val result = if (canPool) { val result = if (canPool) {
frame.ensureScope().withChildFrame(args) { child -> callee.callOn(child) } frame.ensureScope().withChildFrame(args) { child ->
(callee as? BytecodeCallable)?.callOnFast(child) ?: callee.callOn(child)
}
} else { } else {
val scope = frame.ensureScope() val scope = frame.ensureScope()
if (callee is Statement) { if (callee is Statement) {
@ -3339,7 +3344,8 @@ class CmdCallSlot(
if (callee is BytecodeLambdaCallable && callee.supportsDirectInvokeFastPath()) { if (callee is BytecodeLambdaCallable && callee.supportsDirectInvokeFastPath()) {
callee.invokeWithArgsFast(scope, args) ?: callee.invokeWithArgs(scope, args) callee.invokeWithArgsFast(scope, args) ?: callee.invokeWithArgs(scope, args)
} else { } else {
callee.callOn(scope.createChildScope(scope.pos, args = args)) val child = scope.createChildScope(scope.pos, args = args)
(callee as? BytecodeCallable)?.callOnFast(child) ?: callee.callOn(child)
} }
} }
frame.storeObjResult(dst, result) frame.storeObjResult(dst, result)
@ -3429,7 +3435,8 @@ class CmdListFillInt(
callable.invokeWithArgsFast(scope, Arguments(ObjInt.of(i.toLong()))) callable.invokeWithArgsFast(scope, Arguments(ObjInt.of(i.toLong())))
?: callable.invokeWithArgs(scope, Arguments(ObjInt.of(i.toLong()))) ?: callable.invokeWithArgs(scope, Arguments(ObjInt.of(i.toLong())))
} else { } else {
callable.callOn(scope.createChildScope(scope.pos, args = Arguments(ObjInt.of(i.toLong())))) val child = scope.createChildScope(scope.pos, args = Arguments(ObjInt.of(i.toLong())))
(callable as? BytecodeCallable)?.callOnFast(child) ?: callable.callOn(child)
} }
val intValue = (value as? ObjInt)?.value ?: scope.raiseClassCastError("expected Int fill result") val intValue = (value as? ObjInt)?.value ?: scope.raiseClassCastError("expected Int fill result")
result.setIntAtFast(i, intValue) result.setIntAtFast(i, intValue)

View File

@ -18,6 +18,7 @@
package net.sergeych.lyng.obj package net.sergeych.lyng.obj
import net.sergeych.lyng.Arguments import net.sergeych.lyng.Arguments
import net.sergeych.lyng.BytecodeCallable
import net.sergeych.lyng.BytecodeBodyProvider import net.sergeych.lyng.BytecodeBodyProvider
import net.sergeych.lyng.Scope import net.sergeych.lyng.Scope
import net.sergeych.lyng.Statement import net.sergeych.lyng.Statement
@ -41,14 +42,16 @@ class ObjProperty(
val instanceScope = (instance as? ObjInstance)?.instanceScope ?: instance.autoInstanceScope(scope) val instanceScope = (instance as? ObjInstance)?.instanceScope ?: instance.autoInstanceScope(scope)
val execScope = scope.applyClosure(instanceScope).createChildScope(newThisObj = instance) val execScope = scope.applyClosure(instanceScope).createChildScope(newThisObj = instance)
execScope.currentClassCtx = declaringClass execScope.currentClassCtx = declaringClass
(g as? BytecodeCallable)?.callOnFast(execScope)?.let { return it }
return when (g) { return when (g) {
is BytecodeStatement -> executeBytecodeWithSeed(execScope, g, "property getter") is BytecodeStatement -> executeBytecodeWithSeed(execScope, g, "property getter")
is BytecodeBodyProvider -> { is BytecodeBodyProvider -> {
val body = g.bytecodeBody() val body = g.bytecodeBody()
if (body != null) executeBytecodeWithSeed(execScope, body, "property getter") else g.callOn(execScope) if (body != null) executeBytecodeWithSeed(execScope, body, "property getter")
else (g as? BytecodeCallable)?.callOnFast(execScope) ?: g.callOn(execScope)
} }
is Statement -> g.callOn(execScope) is Statement -> (g as? BytecodeCallable)?.callOnFast(execScope) ?: g.callOn(execScope)
else -> g.callOn(execScope) else -> (g as? BytecodeCallable)?.callOnFast(execScope) ?: g.callOn(execScope)
} }
} }
@ -59,14 +62,16 @@ class ObjProperty(
val instanceScope = (instance as? ObjInstance)?.instanceScope ?: instance.autoInstanceScope(scope) val instanceScope = (instance as? ObjInstance)?.instanceScope ?: instance.autoInstanceScope(scope)
val execScope = scope.applyClosure(instanceScope).createChildScope(args = Arguments(value), newThisObj = instance) val execScope = scope.applyClosure(instanceScope).createChildScope(args = Arguments(value), newThisObj = instance)
execScope.currentClassCtx = declaringClass execScope.currentClassCtx = declaringClass
(s as? BytecodeCallable)?.callOnFast(execScope)?.let { return }
when (s) { when (s) {
is BytecodeStatement -> executeBytecodeWithSeed(execScope, s, "property setter") is BytecodeStatement -> executeBytecodeWithSeed(execScope, s, "property setter")
is BytecodeBodyProvider -> { is BytecodeBodyProvider -> {
val body = s.bytecodeBody() val body = s.bytecodeBody()
if (body != null) executeBytecodeWithSeed(execScope, body, "property setter") else s.callOn(execScope) if (body != null) executeBytecodeWithSeed(execScope, body, "property setter")
else (s as? BytecodeCallable)?.callOnFast(execScope) ?: s.callOn(execScope)
} }
is Statement -> s.callOn(execScope) is Statement -> (s as? BytecodeCallable)?.callOnFast(execScope) ?: s.callOn(execScope)
else -> s.callOn(execScope) else -> (s as? BytecodeCallable)?.callOnFast(execScope) ?: s.callOn(execScope)
} }
} }