JS: fix inline cycle reporting
This commit is contained in:
@@ -57,41 +57,36 @@ class InlinerCycleReporter(
|
||||
}
|
||||
|
||||
fun processInlineFunction(definition: FunctionWithWrapper, call: JsInvocation?, doProcess: () -> Unit) {
|
||||
|
||||
when (functionVisitingState[definition.function]) {
|
||||
VisitedState.IN_PROCESS -> {
|
||||
reportInlineCycle(call, definition.function)
|
||||
return
|
||||
}
|
||||
VisitedState.PROCESSED -> return
|
||||
}
|
||||
|
||||
val function = definition.function
|
||||
|
||||
functionVisitingState[function] = VisitedState.IN_PROCESS
|
||||
|
||||
val result = withFunction(function, doProcess)
|
||||
|
||||
functionVisitingState[function] = VisitedState.PROCESSED
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
fun <T> inlineCall(call: JsInvocation, doInline: () -> T): T {
|
||||
currentNamedFunction?.let {
|
||||
inlineCallInfos.add(JsCallInfo(call, it))
|
||||
}
|
||||
|
||||
val result = doInline()
|
||||
|
||||
if (!inlineCallInfos.isEmpty()) {
|
||||
if (inlineCallInfos.last.call == call) {
|
||||
inlineCallInfos.removeLast()
|
||||
if (call != null) {
|
||||
currentNamedFunction?.let {
|
||||
inlineCallInfos.add(JsCallInfo(call, it))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
try {
|
||||
when (functionVisitingState[definition.function]) {
|
||||
VisitedState.IN_PROCESS -> {
|
||||
reportInlineCycle(call, definition.function)
|
||||
return
|
||||
}
|
||||
VisitedState.PROCESSED -> return
|
||||
}
|
||||
|
||||
functionVisitingState[function] = VisitedState.IN_PROCESS
|
||||
|
||||
withFunction(function, doProcess)
|
||||
|
||||
functionVisitingState[function] = VisitedState.PROCESSED
|
||||
|
||||
} finally {
|
||||
if (!inlineCallInfos.isEmpty()) {
|
||||
if (inlineCallInfos.last.call == call) {
|
||||
inlineCallInfos.removeLast()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportInlineCycle(call: JsInvocation?, calledFunction: JsFunction) {
|
||||
|
||||
@@ -60,21 +60,18 @@ class JsInliner(
|
||||
fun inline(scope: InliningScope, call: JsInvocation, currentStatement: JsStatement?): InlineableResult {
|
||||
val definition = functionContext.getFunctionDefinition(call, scope)
|
||||
|
||||
return cycleReporter.inlineCall(call) {
|
||||
val function = scope.importFunctionDefinition(definition)
|
||||
|
||||
val function = scope.importFunctionDefinition(definition)
|
||||
val inliningContext = InliningContext(currentStatement)
|
||||
|
||||
val inliningContext = InliningContext(currentStatement)
|
||||
val (inlineableBody, resultExpression) = FunctionInlineMutator.getInlineableCallReplacement(call, function, inliningContext)
|
||||
|
||||
val (inlineableBody, resultExpression) = FunctionInlineMutator.getInlineableCallReplacement(call, function, inliningContext)
|
||||
// body of inline function can contain call to lambdas that need to be inlined
|
||||
scope.process(inlineableBody)
|
||||
|
||||
// body of inline function can contain call to lambdas that need to be inlined
|
||||
scope.process(inlineableBody)
|
||||
// TODO shouldn't we process the resultExpression qualifier along with the lambda inlining?
|
||||
resultExpression?.synthetic = true
|
||||
|
||||
// TODO shouldn't we process the resultExpression qualifier along with the lambda inlining?
|
||||
resultExpression?.synthetic = true
|
||||
|
||||
InlineableResult(JsBlock(inliningContext.previousStatements + inlineableBody), resultExpression)
|
||||
}
|
||||
return InlineableResult(JsBlock(inliningContext.previousStatements + inlineableBody), resultExpression)
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ class FunctionContext(
|
||||
|
||||
fun scopeForFragment(fragment: JsProgramFragment) = if (fragment in newFragments) {
|
||||
inliningScopeCache.computeIfAbsent(fragment) {
|
||||
loadFragment(fragment)
|
||||
ProgramFragmentInliningScope(fragment)
|
||||
}
|
||||
} else null
|
||||
@@ -75,8 +76,7 @@ class FunctionContext(
|
||||
*/
|
||||
private fun getFunctionDefinitionImpl(call: JsInvocation, scope: InliningScope): InlineFunctionDefinition? {
|
||||
// Ensure we have the local function information
|
||||
// TODO is this necessary?
|
||||
loadFragment(scope.fragment)
|
||||
assert(scope.fragment in inliningScopeCache)
|
||||
|
||||
return lookUpFunctionDirect(call) ?: lookUpFunctionIndirect(call, scope) ?: lookUpFunctionExternal(call, scope.fragment)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user