KJS: transform labeled blocks to labeled do-while
It's a workaround for JDK-8177691. Such code can appear during inline.
This commit is contained in:
committed by
Zalim Bashorov
parent
76fa6ad5c2
commit
678d2e7c21
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.inline.clean
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
|
object LabeledBlockToDoWhileTransformation {
|
||||||
|
fun apply(fragments: List<JsProgramFragment>) {
|
||||||
|
for (fragment in fragments) {
|
||||||
|
apply(fragment.declarationBlock)
|
||||||
|
apply(fragment.initializerBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun apply(root: JsNode) {
|
||||||
|
object : JsVisitorWithContextImpl() {
|
||||||
|
override fun endVisit(x: JsLabel, ctx: JsContext<JsNode>) {
|
||||||
|
if (x.statement is JsBlock) {
|
||||||
|
x.statement = JsDoWhile(JsLiteral.FALSE, x.statement)
|
||||||
|
}
|
||||||
|
|
||||||
|
super.endVisit(x, ctx)
|
||||||
|
}
|
||||||
|
}.accept(root)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,18 +17,18 @@
|
|||||||
package org.jetbrains.kotlin.js.test.optimizer
|
package org.jetbrains.kotlin.js.test.optimizer
|
||||||
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
|
||||||
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
|
||||||
import com.google.gwt.dev.js.rhino.CodePosition
|
import com.google.gwt.dev.js.rhino.CodePosition
|
||||||
import com.google.gwt.dev.js.rhino.ErrorReporter
|
import com.google.gwt.dev.js.rhino.ErrorReporter
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||||
import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor
|
import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor
|
||||||
import org.jetbrains.kotlin.js.parser.parse
|
import org.jetbrains.kotlin.js.parser.parse
|
||||||
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
||||||
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
||||||
import org.jetbrains.kotlin.js.test.createScriptEngine
|
import org.jetbrains.kotlin.js.test.createScriptEngine
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.rules.TestName
|
import org.junit.rules.TestName
|
||||||
@@ -60,18 +60,22 @@ abstract class BasicOptimizerTest(private var basePath: String) {
|
|||||||
updateMetadata(unoptimizedCode, unoptimizedAst)
|
updateMetadata(unoptimizedCode, unoptimizedAst)
|
||||||
|
|
||||||
for (statement in unoptimizedAst) {
|
for (statement in unoptimizedAst) {
|
||||||
object : RecursiveJsVisitor() {
|
process(statement)
|
||||||
override fun visitFunction(x: JsFunction) {
|
|
||||||
FunctionPostProcessor(x).apply()
|
|
||||||
super.visitFunction(x)
|
|
||||||
}
|
|
||||||
}.accept(statement)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val optimizedAst = parse(optimizedCode, errorReporter, parserScope)
|
val optimizedAst = parse(optimizedCode, errorReporter, parserScope)
|
||||||
Assert.assertEquals(astToString(optimizedAst), astToString(unoptimizedAst))
|
Assert.assertEquals(astToString(optimizedAst), astToString(unoptimizedAst))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun process(statement: JsStatement) {
|
||||||
|
object : RecursiveJsVisitor() {
|
||||||
|
override fun visitFunction(x: JsFunction) {
|
||||||
|
FunctionPostProcessor(x).apply()
|
||||||
|
super.visitFunction(x)
|
||||||
|
}
|
||||||
|
}.accept(statement)
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateMetadata(code: String, ast: List<JsStatement>) {
|
private fun updateMetadata(code: String, ast: List<JsStatement>) {
|
||||||
val comments = findSyntheticComments(code)
|
val comments = findSyntheticComments(code)
|
||||||
|
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.test.optimizer
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.JsStatement
|
||||||
|
import org.jetbrains.kotlin.js.inline.clean.LabeledBlockToDoWhileTransformation
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class LabeledBlockToDoWhileTransformationTest : BasicOptimizerTest("labeled-block-to-do-while") {
|
||||||
|
@Test fun simple() = box()
|
||||||
|
|
||||||
|
override fun process(statement: JsStatement) {
|
||||||
|
LabeledBlockToDoWhileTransformation.apply(statement)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.js.config.JsConfig;
|
|||||||
import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer;
|
import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer;
|
||||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
||||||
import org.jetbrains.kotlin.js.inline.JsInliner;
|
import org.jetbrains.kotlin.js.inline.JsInliner;
|
||||||
|
import org.jetbrains.kotlin.js.inline.clean.LabeledBlockToDoWhileTransformation;
|
||||||
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
||||||
import org.jetbrains.kotlin.js.inline.clean.ResolveTemporaryNamesKt;
|
import org.jetbrains.kotlin.js.inline.clean.ResolveTemporaryNamesKt;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult;
|
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult;
|
||||||
@@ -124,6 +125,8 @@ public final class K2JSTranslator {
|
|||||||
|
|
||||||
JsInliner.process(config, analysisResult.getBindingTrace(), translationResult.getInnerModuleName(), allFragments, newFragments);
|
JsInliner.process(config, analysisResult.getBindingTrace(), translationResult.getInnerModuleName(), allFragments, newFragments);
|
||||||
|
|
||||||
|
LabeledBlockToDoWhileTransformation.INSTANCE.apply(newFragments);
|
||||||
|
|
||||||
CoroutineTransformer coroutineTransformer = new CoroutineTransformer(translationResult.getProgram());
|
CoroutineTransformer coroutineTransformer = new CoroutineTransformer(translationResult.getProgram());
|
||||||
for (JsProgramFragment fragment : newFragments) {
|
for (JsProgramFragment fragment : newFragments) {
|
||||||
coroutineTransformer.accept(fragment.getDeclarationBlock());
|
coroutineTransformer.accept(fragment.getDeclarationBlock());
|
||||||
@@ -174,6 +177,7 @@ public final class K2JSTranslator {
|
|||||||
for (JsImportedModule module : translationResult.getImportedModuleList()) {
|
for (JsImportedModule module : translationResult.getImportedModuleList()) {
|
||||||
importedModules.add(module.getExternalName());
|
importedModules.add(module.getExternalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
||||||
moduleDescriptor, bindingTrace.getBindingContext(), metadataHeader, fileMap);
|
moduleDescriptor, bindingTrace.getBindingContext(), metadataHeader, fileMap);
|
||||||
}
|
}
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
var a = eval("true");
|
||||||
|
|
||||||
|
function box() {
|
||||||
|
var functions = [box1, box2, box3];
|
||||||
|
|
||||||
|
for (i in functions) {
|
||||||
|
var f = functions[i];
|
||||||
|
var result = f();
|
||||||
|
|
||||||
|
if (f.toString().indexOf("label: do {") < 0) {
|
||||||
|
// http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8177691
|
||||||
|
if (result === "OK") return "Looks like JDK-8177691 fixed for " + f;
|
||||||
|
if (result !== void 0) return "Result of function changed: " + f;
|
||||||
|
}
|
||||||
|
else if (result !== "OK") {
|
||||||
|
return "fail on " + f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
function box1() {
|
||||||
|
label: do {
|
||||||
|
try {
|
||||||
|
if (a) throw 1;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
break label;
|
||||||
|
}
|
||||||
|
throw 2;
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
|
||||||
|
function box2() {
|
||||||
|
label: do {
|
||||||
|
try {
|
||||||
|
if (a) throw 1;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
break label;
|
||||||
|
}
|
||||||
|
throw 2;
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
|
|
||||||
|
function box3() {
|
||||||
|
label: do {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
break label;
|
||||||
|
}
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
var a = eval("true");
|
||||||
|
|
||||||
|
function box() {
|
||||||
|
var functions = [box1, box2, box3];
|
||||||
|
|
||||||
|
for (i in functions) {
|
||||||
|
var f = functions[i];
|
||||||
|
var result = f();
|
||||||
|
|
||||||
|
if (f.toString().indexOf("label: do {") < 0) {
|
||||||
|
// See http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8177691
|
||||||
|
if (result === "OK") return "Looks like JDK-8177691 fixed for " + f;
|
||||||
|
if (result !== void 0) return "Result of function changed: " + f;
|
||||||
|
}
|
||||||
|
else if (result !== "OK") {
|
||||||
|
return "fail on " + f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
function box1() {
|
||||||
|
label: {
|
||||||
|
try {
|
||||||
|
if (a) throw 1;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
break label;
|
||||||
|
}
|
||||||
|
throw 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'OK';
|
||||||
|
};
|
||||||
|
|
||||||
|
function box2() {
|
||||||
|
label: {
|
||||||
|
try {
|
||||||
|
if (a) throw 1;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
break label;
|
||||||
|
}
|
||||||
|
throw 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
|
|
||||||
|
function box3() {
|
||||||
|
label: {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
break label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user