[JS IR] Implement MoveTemporaryVariableDeclarationToAssignment optimization

This commit is contained in:
Alexander Korepanov
2023-07-06 17:24:28 +02:00
committed by Space Team
parent 25f7b81d51
commit 524c475834
23 changed files with 929 additions and 25 deletions
@@ -17,12 +17,13 @@ import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
import org.jetbrains.kotlin.test.services.isKtFile
import java.io.File
class JsAstHandler(testServices: TestServices) : JsBinaryArtifactHandler(testServices) {
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
override fun processModule(module: TestModule, info: BinaryArtifacts.Js) {
val ktFiles = module.files.filter { it.isKtFile }.map { it.originalContent }
val ktFiles = module.files.filter { it.isKtFile }.associate { it.originalFile to it.originalContent }
val jsProgram = when (val artifact = info.unwrap()) {
is BinaryArtifacts.Js.OldJsArtifact -> (artifact.translationResult as TranslationResult.Success).program
is BinaryArtifacts.Js.JsIrArtifact -> artifact.compilerResult.outputs[TranslationMode.FULL_DEV]?.jsProgram ?: return
@@ -31,8 +32,8 @@ class JsAstHandler(testServices: TestServices) : JsBinaryArtifactHandler(testSer
processJsProgram(jsProgram, ktFiles, module.targetBackend!!)
}
private fun processJsProgram(program: JsProgram, psiFiles: List<String>, targetBackend: TargetBackend) {
psiFiles.forEach { DirectiveTestUtils.processDirectives(program, it, targetBackend) }
private fun processJsProgram(program: JsProgram, psiFiles: Map<File, String>, targetBackend: TargetBackend) {
psiFiles.forEach { DirectiveTestUtils.processDirectives(program, it.key, it.value, targetBackend) }
program.verifyAst(targetBackend)
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.testOld.optimizer
import org.junit.Test
class MoveTemporaryVariableDeclarationToAssignmentTest : BasicOptimizerTest("move-temporary-variable-declaration") {
@Test
fun sameBlock() = box()
@Test
fun innerBlock() = box()
@Test
fun siblingBlocks() = box()
@Test
fun notInitUsage() = box()
}
@@ -23,9 +23,11 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.inline.util.CollectUtilsKt;
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.junit.runners.model.MultipleFailureException;
import java.io.File;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -97,6 +99,18 @@ public class DirectiveTestUtils {
}
};
private static final DirectiveHandler EXPECT_GENERATED_JS = new DirectiveHandler("EXPECT_GENERATED_JS") {
@Override
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
String functionName = arguments.getNamedArgument("function");
String expected = arguments.getNamedArgument("expect");
File expectedFile = new File(arguments.sourceFile.getParentFile(), expected);
String code = AstSearchUtil.getFunction(ast, functionName).toString();
String msg = "Function '" + functionName + "' got different generated JS code";
KotlinTestUtils.assertEqualsToFile(msg, expectedFile, code);
}
};
private static final DirectiveHandler FUNCTION_EXISTS = new DirectiveHandler("CHECK_FUNCTION_EXISTS") {
@Override
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
@@ -481,6 +495,7 @@ public class DirectiveTestUtils {
};
private static final List<DirectiveHandler> DIRECTIVE_HANDLERS = Arrays.asList(
EXPECT_GENERATED_JS,
FUNCTION_CONTAINS_NO_CALLS,
FUNCTION_NOT_CALLED,
FUNCTION_CALLED_TIMES,
@@ -515,12 +530,13 @@ public class DirectiveTestUtils {
public static void processDirectives(
@NotNull JsNode ast,
@NotNull File sourceFile,
@NotNull String sourceCode,
@NotNull TargetBackend targetBackend
) throws Exception {
List<Throwable> assertionErrors = new ArrayList<>();
for (DirectiveHandler handler : DIRECTIVE_HANDLERS) {
handler.process(ast, sourceCode, targetBackend, assertionErrors);
handler.process(ast, sourceFile, sourceCode, targetBackend, assertionErrors);
}
MultipleFailureException.assertEmpty(assertionErrors);
}
@@ -651,13 +667,15 @@ public class DirectiveTestUtils {
*
* @see ArgumentsHelper for arguments format
*/
void process(@NotNull JsNode ast, @NotNull String sourceCode,
void process(@NotNull JsNode ast,
@NotNull File sourceFile,
@NotNull String sourceCode,
@NotNull TargetBackend targetBackend,
List<Throwable> assertionErrors
) throws Exception {
List<String> directiveEntries = findLinesWithPrefixesRemoved(sourceCode, directive);
for (String directiveEntry : directiveEntries) {
ArgumentsHelper arguments = new ArgumentsHelper(directiveEntry);
ArgumentsHelper arguments = new ArgumentsHelper(directiveEntry, sourceFile);
if (!containsBackend(targetBackend, TARGET_BACKENDS, arguments, true) ||
containsBackend(targetBackend, IGNORED_BACKENDS, arguments, false)) {
continue;
@@ -696,9 +714,10 @@ public class DirectiveTestUtils {
private final Map<String, String> namedArguments = new HashMap<>();
private final String entry;
private final Pattern argumentsPattern = Pattern.compile("[\\w$_;\\.]+(=((\".*?\")|[\\w$_;\\.]+))?");
ArgumentsHelper(@NotNull String directiveEntry) {
final File sourceFile;
ArgumentsHelper(@NotNull String directiveEntry, @NotNull File directiveSourceFile) {
entry = directiveEntry;
sourceFile = directiveSourceFile;
Matcher matcher = argumentsPattern.matcher(directiveEntry);