Step 24D: bytecode closure scope
This commit is contained in:
parent
1271f347bd
commit
c14c7d43d9
@ -102,9 +102,9 @@ Goal: migrate the compiler so all values live in frames/bytecode, keeping JVM te
|
|||||||
- [x] Keep Scope creation only for reflection/Kotlin interop paths.
|
- [x] Keep Scope creation only for reflection/Kotlin interop paths.
|
||||||
- [x] JVM tests must be green before commit.
|
- [x] JVM tests must be green before commit.
|
||||||
- [x] Step 24D: Eliminate `ClosureScope` usage on bytecode execution paths.
|
- [x] Step 24D: Eliminate `ClosureScope` usage on bytecode execution paths.
|
||||||
- [ ] Avoid `ClosureScope` in bytecode-related call paths (Block/Lambda/ObjDynamic/ObjProperty).
|
- [x] Avoid `ClosureScope` in bytecode-related call paths (Block/Lambda/ObjDynamic/ObjProperty).
|
||||||
- [ ] Keep interpreter path using `ClosureScope` until interpreter removal.
|
- [x] Keep interpreter path using `ClosureScope` until interpreter removal.
|
||||||
- [ ] JVM tests must be green before commit.
|
- [x] JVM tests must be green before commit.
|
||||||
- [x] Step 24E: Isolate interpreter-only capture logic.
|
- [x] Step 24E: Isolate interpreter-only capture logic.
|
||||||
- [ ] Mark `resolveCaptureRecord` paths as interpreter-only.
|
- [ ] Mark `resolveCaptureRecord` paths as interpreter-only.
|
||||||
- [ ] Guard or delete any bytecode path that tries to sync captures into scopes.
|
- [ ] Guard or delete any bytecode path that tries to sync captures into scopes.
|
||||||
|
|||||||
@ -84,6 +84,32 @@ class ClosureScope(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytecode-oriented closure scope that keeps the call scope parent chain for stack traces
|
||||||
|
* while carrying the lexical closure for `this` variants and module resolution.
|
||||||
|
* Unlike [ClosureScope], it does not override name lookup.
|
||||||
|
*/
|
||||||
|
class BytecodeClosureScope(
|
||||||
|
val callScope: Scope,
|
||||||
|
val closureScope: Scope,
|
||||||
|
private val preferredThisType: String? = null
|
||||||
|
) :
|
||||||
|
Scope(callScope, callScope.args, thisObj = closureScope.thisObj) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
val desired = preferredThisType?.let { typeName ->
|
||||||
|
callScope.thisVariants.firstOrNull { it.objClass.className == typeName }
|
||||||
|
}
|
||||||
|
val primaryThis = closureScope.thisObj
|
||||||
|
val merged = ArrayList<Obj>(callScope.thisVariants.size + closureScope.thisVariants.size + 1)
|
||||||
|
desired?.let { merged.add(it) }
|
||||||
|
merged.addAll(callScope.thisVariants)
|
||||||
|
merged.addAll(closureScope.thisVariants)
|
||||||
|
setThisVariants(primaryThis, merged)
|
||||||
|
this.currentClassCtx = closureScope.currentClassCtx ?: callScope.currentClassCtx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ApplyScope(val callScope: Scope, val applied: Scope) :
|
class ApplyScope(val callScope: Scope, val applied: Scope) :
|
||||||
Scope(callScope, thisObj = applied.thisObj) {
|
Scope(callScope, thisObj = applied.thisObj) {
|
||||||
|
|
||||||
|
|||||||
@ -6929,8 +6929,15 @@ class Compiler(
|
|||||||
// restore closure where the function was defined, and making a copy of it
|
// restore closure where the function was defined, and making a copy of it
|
||||||
// for local space. If there is no closure, we are in, say, class context where
|
// for local space. If there is no closure, we are in, say, class context where
|
||||||
// the closure is in the class initialization and we needn't more:
|
// the closure is in the class initialization and we needn't more:
|
||||||
val context = closureBox.closure?.let { ClosureScope(callerContext, it) }
|
val context = closureBox.closure?.let { closure ->
|
||||||
?: callerContext
|
if (fnStatements is BytecodeStatement) {
|
||||||
|
callerContext.applyClosureForBytecode(closure).also {
|
||||||
|
it.args = callerContext.args
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ClosureScope(callerContext, closure)
|
||||||
|
}
|
||||||
|
} ?: callerContext
|
||||||
|
|
||||||
// Capacity hint: parameters + declared locals + small overhead
|
// Capacity hint: parameters + declared locals + small overhead
|
||||||
val capacityHint = paramNames.size + fnLocalDecls + 4
|
val capacityHint = paramNames.size + fnLocalDecls + 4
|
||||||
|
|||||||
@ -192,7 +192,14 @@ internal suspend fun executeFunctionDecl(scope: Scope, spec: FunctionDeclSpec):
|
|||||||
override val pos: Pos = spec.startPos
|
override val pos: Pos = spec.startPos
|
||||||
override suspend fun execute(scope: Scope): Obj {
|
override suspend fun execute(scope: Scope): Obj {
|
||||||
val result = (scope.thisObj as? ObjInstance)?.let { i ->
|
val result = (scope.thisObj as? ObjInstance)?.let { i ->
|
||||||
compiledFnBody.execute(ClosureScope(scope, i.instanceScope))
|
val execScope = if (compiledFnBody is net.sergeych.lyng.bytecode.BytecodeStatement) {
|
||||||
|
scope.applyClosureForBytecode(i.instanceScope).also {
|
||||||
|
it.args = scope.args
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ClosureScope(scope, i.instanceScope)
|
||||||
|
}
|
||||||
|
compiledFnBody.execute(execScope)
|
||||||
} ?: compiledFnBody.execute(scope.thisObj.autoInstanceScope(scope))
|
} ?: compiledFnBody.execute(scope.thisObj.autoInstanceScope(scope))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@ -836,17 +836,7 @@ open class Scope(
|
|||||||
ClosureScope(this, closure, preferredThisType)
|
ClosureScope(this, closure, preferredThisType)
|
||||||
|
|
||||||
internal fun applyClosureForBytecode(closure: Scope, preferredThisType: String? = null): Scope {
|
internal fun applyClosureForBytecode(closure: Scope, preferredThisType: String? = null): Scope {
|
||||||
val context = createChildScope(newThisObj = closure.thisObj)
|
return BytecodeClosureScope(this, closure, preferredThisType)
|
||||||
val desired = preferredThisType?.let { typeName ->
|
|
||||||
thisVariants.firstOrNull { it.objClass.className == typeName }
|
|
||||||
}
|
|
||||||
val merged = ArrayList<Obj>(thisVariants.size + closure.thisVariants.size + 1)
|
|
||||||
desired?.let { merged.add(it) }
|
|
||||||
merged.addAll(thisVariants)
|
|
||||||
merged.addAll(closure.thisVariants)
|
|
||||||
context.setThisVariants(closure.thisObj, merged)
|
|
||||||
context.currentClassCtx = closure.currentClassCtx ?: currentClassCtx
|
|
||||||
return context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -2004,6 +2004,8 @@ class CmdFrame(
|
|||||||
current.parent?.let { queue.add(it) }
|
current.parent?.let { queue.add(it) }
|
||||||
if (current is ClosureScope) {
|
if (current is ClosureScope) {
|
||||||
queue.add(current.closureScope)
|
queue.add(current.closureScope)
|
||||||
|
} else if (current is BytecodeClosureScope) {
|
||||||
|
queue.add(current.closureScope)
|
||||||
} else if (current is ApplyScope) {
|
} else if (current is ApplyScope) {
|
||||||
queue.add(current.applied)
|
queue.add(current.applied)
|
||||||
}
|
}
|
||||||
@ -2023,6 +2025,28 @@ class CmdFrame(
|
|||||||
current.parent?.let { queue.add(it) }
|
current.parent?.let { queue.add(it) }
|
||||||
if (current is ClosureScope) {
|
if (current is ClosureScope) {
|
||||||
queue.add(current.closureScope)
|
queue.add(current.closureScope)
|
||||||
|
} else if (current is BytecodeClosureScope) {
|
||||||
|
queue.add(current.closureScope)
|
||||||
|
} else if (current is ApplyScope) {
|
||||||
|
queue.add(current.applied)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findScopeWithRecord(scope: Scope, name: String): Scope? {
|
||||||
|
val visited = HashSet<Scope>(16)
|
||||||
|
val queue = ArrayDeque<Scope>()
|
||||||
|
queue.add(scope)
|
||||||
|
while (queue.isNotEmpty()) {
|
||||||
|
val current = queue.removeFirst()
|
||||||
|
if (!visited.add(current)) continue
|
||||||
|
if (current.getLocalRecordDirect(name) != null) return current
|
||||||
|
current.parent?.let { queue.add(it) }
|
||||||
|
if (current is ClosureScope) {
|
||||||
|
queue.add(current.closureScope)
|
||||||
|
} else if (current is BytecodeClosureScope) {
|
||||||
|
queue.add(current.closureScope)
|
||||||
} else if (current is ApplyScope) {
|
} else if (current is ApplyScope) {
|
||||||
queue.add(current.applied)
|
queue.add(current.applied)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user