Skip to content
This repository has been archived by the owner on Dec 10, 2022. It is now read-only.

Relooper.2018 #291

Open
wants to merge 61 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
1678d02
Added @JTranscRelooper annotation to manual control relooping
soywiz Jan 14, 2018
565962a
Some unfinished work
soywiz Jan 14, 2018
aef4ecf
Merge branch 'master' of github.com:jtransc/jtransc into relooper.2018
soywiz Jan 15, 2018
8092d1c
Not working: Some work on new relooper
soywiz Jan 15, 2018
6e7aba8
Small fix in relooper
soywiz Jan 15, 2018
30c3c28
More work on relooper
soywiz Jan 15, 2018
ad07e44
Some more work on relooper
soywiz Jan 15, 2018
39d89b7
Some more work on relooper
soywiz Jan 15, 2018
ba7e03d
Some Relooper adjustments
soywiz Jan 15, 2018
404e005
Some more work on relooper
soywiz Jan 15, 2018
8ca8e22
Some more work on relooper
soywiz Jan 15, 2018
3ec897c
Some more work on relooper
soywiz Jan 15, 2018
5ff3685
Some more work on relooper
soywiz Jan 15, 2018
ecd691b
Some more work on relooper
soywiz Jan 15, 2018
3f1c637
Some more work on relooper
soywiz Jan 15, 2018
19f8ee1
Some more work on relooper
soywiz Jan 15, 2018
c7ed617
Some more work on relooper
soywiz Jan 16, 2018
1f5e449
Some more work on relooper
soywiz Jan 16, 2018
829393d
Remove old annotations
soywiz Jan 16, 2018
887797b
Output jtransc version with JS for convenience
soywiz Jan 16, 2018
ca3697f
Old comment
soywiz Jan 16, 2018
0f6ece9
Add a flag for generators to specify if they support labels (most of …
soywiz Jan 16, 2018
61d9b81
Optimize DO_WHILE + if continue + break externally
soywiz Jan 16, 2018
f384cd0
Some more work on relooper
soywiz Jan 16, 2018
91b2168
Supported white and for loops
soywiz Jan 16, 2018
f1faab9
Enable relooper in benchmark
soywiz Jan 16, 2018
ce878e2
This PR will start 0.7 branch
soywiz Jan 16, 2018
84a323c
Inline errors
soywiz Jan 16, 2018
009e53d
Added failing test case using relooper + test code generator when deb…
soywiz Jan 16, 2018
dd4dd2e
Remove empty nodes, that were making the strong component contract (t…
soywiz Jan 16, 2018
1679db2
Do not create additional exit node if not required
soywiz Jan 16, 2018
ae6db58
Revert previos: we need end node for this to work properly
soywiz Jan 16, 2018
1e4c067
Fixed some relooper cases
soywiz Jan 16, 2018
90b2fc1
Some loop optimizations
soywiz Jan 16, 2018
fa640a7
Updated version
soywiz Jan 16, 2018
bc1c646
Detects if && chains
soywiz Jan 17, 2018
26b5b0d
Detects if || chains
soywiz Jan 17, 2018
2932f7e
Small fixes
soywiz Jan 17, 2018
2f13dd0
ConcurrentModification fix
soywiz Jan 17, 2018
fea7cf9
Convert recursive functions into normal queues
soywiz Jan 17, 2018
0a1611f
Optimize IF_ELSE with return on both sides
soywiz Jan 17, 2018
d1bf5d4
Optimize some IF_ELSE to act as guard clauses
soywiz Jan 17, 2018
7dd53ef
Kotlin 1.2.20
soywiz Jan 17, 2018
f39d87c
Fixed a problematic bug related to indices not matching in Relooper
soywiz Jan 17, 2018
3bd4e7a
org.gradle.caching=true
soywiz Jan 17, 2018
e7627df
Throw statements can be also guard clauses
soywiz Jan 17, 2018
8e80373
Remove exit node cycle
soywiz Jan 17, 2018
29f92a8
Detect some ifs leading to the exit point (return and throws)
soywiz Jan 17, 2018
7707735
Prepare to support switches in relooper
soywiz Jan 17, 2018
a083765
Some more work on supporting switch on relooper
soywiz Jan 17, 2018
4b04237
First switch implementation with ifs
soywiz Jan 17, 2018
9cbd1bb
Compact else-if chains to reduce indentation
soywiz Jan 17, 2018
b98197f
Disable switch in relooper temporarily
soywiz Jan 17, 2018
2e84278
Some work on fixing switches with a new/better conversor to basic Stm…
soywiz Jan 17, 2018
d1b3f37
switch fixes
soywiz Jan 17, 2018
34521b8
Some switch fixes
soywiz Jan 17, 2018
10a5ed4
Proper switch working (common node finding still requires some work t…
soywiz Jan 17, 2018
4159fcf
Prefer break/continue over return/throw as guard clauses
soywiz Jan 17, 2018
28699bc
Proper generate switch
soywiz Jan 17, 2018
6ef715c
Fix floating point comparisons
soywiz Jan 18, 2018
a8ebb76
Update badges to represent master instead of last build
soywiz Jan 18, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ JTRANSC
![JTransc](extra/logo-256.png)

[![Maven Version](https://img.shields.io/github/tag/jtransc/jtransc.svg?style=flat&label=maven)](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22jtransc-maven-plugin%22)
[![Build Status](https://secure.travis-ci.org/jtransc/jtransc.svg)](http://travis-ci.org/jtransc/jtransc)
[![Build status](https://ci.appveyor.com/api/projects/status/qnd0g966t1b54q4a?svg=true)](https://ci.appveyor.com/project/soywiz/jtransc)
[![Code coverage](https://codecov.io/gh/jtransc/jtransc/branch/master/graph/badge.svg)](https://codecov.io/gh/jtransc/jtransc)
[![Build Status](https://secure.travis-ci.org/jtransc/jtransc.svg?branch=master)](http://travis-ci.org/jtransc/jtransc)
[![Build status](https://ci.appveyor.com/api/projects/status/qnd0g966t1b54q4a?svg=true&branch=master)](https://ci.appveyor.com/project/soywiz/jtransc)
[![gitter](https://img.shields.io/gitter/room/jtransc/general.svg)](https://gitter.im/jtransc/general)

# Documentation
Expand Down
1 change: 1 addition & 0 deletions benchmark/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jtransc {
//minimizeNames = true
minimizeNames = false
treeshaking = true
relooper = true

// Call ./gradlew -Pjs_enable_async=true runJs
if (rootProject.findProperty("js_enable_async")?.toString()?.toBoolean() ?: false) {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
jtranscVersion=0.6.9-SNAPSHOT
jtranscVersion=0.7.0-SNAPSHOT
6 changes: 4 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
jtranscVersion=0.6.9-SNAPSHOT
kotlinVersion=1.2.10
jtranscVersion=0.7.0-SNAPSHOT
kotlinVersion=1.2.20
file.encoding=UTF-8
kotlin.incremental=true
org.gradle.daemon=true
org.gradle.daemon.idleTimeout=3600000
org.gradle.jvmargs=-Xmx512m -XX:MaxPermSize=128m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
kotlin.incremental.usePreciseJavaTracking=true
org.gradle.caching=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.jtransc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Overrides enabling/disabling relooper for specific method
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface JTranscRelooper {
boolean value() default true;
boolean debug() default false;
int method() default 0; // 1 = experimental method
}

This file was deleted.

11 changes: 0 additions & 11 deletions jtransc-annotations/src/com/jtransc/annotation/KeepFields.java

This file was deleted.

11 changes: 0 additions & 11 deletions jtransc-annotations/src/com/jtransc/annotation/KeepMethods.java

This file was deleted.

9 changes: 8 additions & 1 deletion jtransc-core/src/com/jtransc/ast/AstTransformer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ open class AstTransformer {
is AstStm.IF -> transform(stm)
is AstStm.IF_ELSE -> transform(stm)
is AstStm.WHILE -> transform(stm)
is AstStm.DO_WHILE -> transform(stm)
is AstStm.RETURN -> transform(stm)
is AstStm.RETURN_VOID -> transform(stm)
is AstStm.THROW -> transform(stm)
Expand Down Expand Up @@ -199,7 +200,13 @@ open class AstTransformer {

open fun transform(stm: AstStm.WHILE): AstStm {
transform(stm.cond)
transform(stm.iter)
transform(stm.body)
return stm
}

open fun transform(stm: AstStm.DO_WHILE): AstStm {
transform(stm.body)
transform(stm.cond)
return stm
}

Expand Down
8 changes: 7 additions & 1 deletion jtransc-core/src/com/jtransc/ast/AstVisitor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ open class AstVisitor {
is AstStm.IF -> visit(stm)
is AstStm.IF_ELSE -> visit(stm)
is AstStm.WHILE -> visit(stm)
is AstStm.DO_WHILE -> visit(stm)
is AstStm.RETURN -> visit(stm)
is AstStm.RETURN_VOID -> visit(stm)
is AstStm.THROW -> visit(stm)
Expand Down Expand Up @@ -203,7 +204,12 @@ open class AstVisitor {

open fun visit(stm: AstStm.WHILE) {
visit(stm.cond)
visit(stm.iter)
visit(stm.body)
}

open fun visit(stm: AstStm.DO_WHILE) {
visit(stm.body)
visit(stm.cond)
}

open fun visit(stm: AstStm.RETURN) {
Expand Down
4 changes: 4 additions & 0 deletions jtransc-core/src/com/jtransc/ast/ast.kt
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,10 @@ class AstMethod constructor(
fun getParamsWithAnnotations(args: List<AstExpr>) = methodType.args.zip(args).map { AstArgumentCallWithAnnotations(it.first, parameterAnnotationsList[it.first.index], it.second) }
fun getParamsWithAnnotationsBox(args: List<AstExpr.Box>) = methodType.args.zip(args).map { AstArgumentCallWithAnnotations(it.first, parameterAnnotationsList.getOrNull(it.first.index), it.second.value) }

val relooper by lazy { annotationsList.getTyped<JTranscRelooper>() }
val relooperEnabled: Boolean? by lazy { relooper?.value }
val relooperDebug by lazy { relooper?.debug ?: false }

init {
if (id < 0) {
println("Invalid method id: $id")
Expand Down
53 changes: 45 additions & 8 deletions jtransc-core/src/com/jtransc/ast/ast_body.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.jtransc.ast
import com.jtransc.ds.cast
import com.jtransc.error.invalidOp
import com.jtransc.error.noImpl
import com.jtransc.gen.TargetName
import kotlin.reflect.KProperty

data class AstBody constructor(
Expand Down Expand Up @@ -203,9 +202,15 @@ sealed class AstStm : AstElement, Cloneable<AstStm> {
val sfalse = sfalse.box
}

class WHILE(cond: AstExpr, iter: AstStm) : AstStm() {
class WHILE(val name: String, cond: AstExpr, body: AstStm) : AstStm() {
val cond = cond.box
val iter = iter.box
val body = body.box
}

// Basic back jump
class DO_WHILE(val name: String, cond: AstExpr, body: AstStm) : AstStm() {
val cond = cond.box
val body = body.box
}

class RETURN(retval: AstExpr) : AstStm() {
Expand All @@ -227,8 +232,8 @@ sealed class AstStm : AstElement, Cloneable<AstStm> {
val catch = catch.box
}

class BREAK() : AstStm()
class CONTINUE() : AstStm()
class BREAK(val name: String) : AstStm()
class CONTINUE(val name: String) : AstStm()

// SwitchFeature
class SWITCH(subject: AstExpr, default: AstStm, cases: List<Pair<List<Int>, AstStm>>) : AstStm() {
Expand Down Expand Up @@ -272,6 +277,24 @@ fun AstStm.isEmpty() = when (this) {
else -> false
}

fun AstStm.normalizeWithoutNopsOrLines(): AstStm {
if (this is AstStm.STMS) {
val st = this.stms.unboxed
.flatMap { if (it is AstStm.STMS) it.stmsUnboxed else listOf(it) }
.filter { !it.isNopOrLine() }
return if (st.size == 1) st[0] else st.stms
}
return this
}

fun AstStm.isNop(): Boolean = this is AstStm.NOP
fun AstStm.isLine(): Boolean = this is AstStm.LINE
fun AstStm.isNopOrLine(): Boolean = isNop() || isLine()

fun AstStm.isContinue(name: String): Boolean = this is AstStm.CONTINUE && this.name == name
fun AstStm.isBreak(name: String): Boolean = this is AstStm.BREAK && this.name == name
fun AstStm.isReturnValue(): Boolean = this is AstStm.RETURN

fun AstStm.isSingleStm(): Boolean {
if (this is AstStm.STMS) return (this.stms.count() == 1) && this.stms.last().value.isSingleStm()
return true
Expand All @@ -282,6 +305,8 @@ fun AstStm.lastStm(): AstStm {
return this
}

val Iterable<AstStm.Box>.unboxed get() = this.map { it.value }

fun AstStm.expand(): List<AstStm> {
return when (this) {
is AstStm.STMS -> this.stms.flatMap { it.value.expand() }
Expand Down Expand Up @@ -364,7 +389,9 @@ abstract class AstExpr : AstElement, Cloneable<AstExpr> {
//var ahead: Boolean = false
}

class RAW(override val type: AstType, val content: String) : AstExpr()
class RAW(override val type: AstType, val content: String) : AstExpr() {
override fun toString(): String = "RAW($content)"
}

class PARAM(val argument: AstArgument) : LocalExpr() {
override val name: String get() = argument.name
Expand Down Expand Up @@ -553,9 +580,12 @@ abstract class AstExpr : AstElement, Cloneable<AstExpr> {
infix fun lt(that: AstExpr) = AstExpr.BINOP(AstType.BOOL, this, AstBinop.LT, that)
infix fun le(that: AstExpr) = AstExpr.BINOP(AstType.BOOL, this, AstBinop.LE, that)
infix fun band(that: AstExpr) = AstExpr.BINOP(AstType.BOOL, this, AstBinop.BAND, that)
infix fun bor(that: AstExpr) = AstExpr.BINOP(AstType.BOOL, this, AstBinop.BOR, that)
infix fun and(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBinop.AND, that)
infix fun instanceof(that: AstType.REF) = AstExpr.INSTANCE_OF(this, that)

//infix fun AND(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBinop.AND, that)

class TERNARY(val cond: AstExpr, val etrue: AstExpr, val efalse: AstExpr, val types: AstTypes) : AstExpr() {
override val type: AstType = types.unify(etrue.type, efalse.type)
}
Expand Down Expand Up @@ -583,6 +613,11 @@ fun List<AstStm>.stm() = when (this.size) {
}

fun AstExpr.Box.isPure(): Boolean = this.value.isPure()
fun AstExpr.Box.isLiteral(value: Any?): Boolean = this.value.isLiteral(value)
fun AstExpr.Box.isLiteral(): Boolean = this.value.isLiteral()

fun AstExpr.isLiteral(value: Any?): Boolean = (this is AstExpr.LITERAL) && this.value == value
fun AstExpr.isLiteral(): Boolean = (this is AstExpr.LITERAL)

fun AstExpr.isPure(): Boolean = when (this) {
is AstExpr.ARRAY_ACCESS -> this.array.isPure() && this.index.isPure() // Can cause null pointer/out of bounds
Expand Down Expand Up @@ -792,6 +827,8 @@ operator fun AstExpr.minus(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBi
operator fun AstExpr.times(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBinop.MUL, that)
infix fun AstExpr.eq(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBinop.EQ, that)
infix fun AstExpr.ne(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBinop.NE, that)
fun AstExpr.inv() = AstExpr.UNOP(AstUnop.INV, this)
//fun AstExpr.not() = AstExpr.UNOP(AstUnop.NOT, this)

operator fun AstMethod.invoke(vararg exprs: AstExpr) = AstExpr.CALL_STATIC(this.ref, exprs.toList())
operator fun AstMethodRef.invoke(vararg exprs: AstExpr) = AstExpr.CALL_STATIC(this.ref, exprs.toList())
Expand Down Expand Up @@ -882,8 +919,8 @@ class AstBuilder2(types: AstTypes, val ctx: AstBuilderBodyCtx) : BuilderBase(typ
return IfElseBuilder(IF, IF_INDEX, stms, types, ctx)
}

inline fun WHILE(cond: AstExpr, callback: AstBuilder2.() -> Unit) {
stms += AstStm.WHILE(cond, AstBuilder2(types, ctx).apply(callback).genstm())
inline fun WHILE(name: String, cond: AstExpr, callback: AstBuilder2.() -> Unit) {
stms += AstStm.WHILE(name, cond, AstBuilder2(types, ctx).apply(callback).genstm())
}

inline fun FOR(local: AstLocal, start: Int, until: Int, callback: AstBuilder2.() -> Unit) {
Expand Down
45 changes: 35 additions & 10 deletions jtransc-core/src/com/jtransc/ast/ast_dump.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.jtransc.ast
import com.jtransc.error.invalidOp
import com.jtransc.error.noImpl
import com.jtransc.text.Indenter
import com.jtransc.text.Indenter.Companion

//fun AstBody.dump() = dump(this)

Expand All @@ -18,8 +17,22 @@ fun dump(types: AstTypes, body: AstBody): Indenter {
}
}

fun dump(types: AstTypes, expr: AstStm.Box?): Indenter {
return dump(types, expr?.value)
fun dump(types: AstTypes, stm: AstStm.Box?): Indenter {
return dump(types, stm?.value)
}

fun dumpCollapse(types: AstTypes, stm: AstStm.Box?): Indenter {
val s = stm?.value
if (s is AstStm.STMS) {
return Indenter {
for (ss in s.stmsUnboxed) {
if (ss is AstStm.NOP) continue
line(dumpCollapse(types, ss.box))
}
}
} else {
return dump(types, s)
}
}

fun dump(types: AstTypes, stm: AstStm?): Indenter {
Expand Down Expand Up @@ -55,17 +68,22 @@ fun dump(types: AstTypes, stm: AstStm?): Indenter {
//line("LINE(${stm.line})")
}
is AstStm.NOP -> line("NOP(${stm.reason})")
is AstStm.CONTINUE -> line("continue;")
is AstStm.BREAK -> line("break;")
is AstStm.CONTINUE -> line("continue ${stm.name};")
is AstStm.BREAK -> line("break ${stm.name};")
is AstStm.THROW -> line("throw ${dump(types, stm.exception)};")
is AstStm.IF -> line("if (${dump(types, stm.cond)})") { line(dump(types, stm.strue)) }
is AstStm.IF -> line("if (${dump(types, stm.cond)})") { line(dumpCollapse(types, stm.strue)) }
is AstStm.IF_ELSE -> {
line("if (${dump(types, stm.cond)})") { line(dump(types, stm.strue)) }
line("else") { line(dump(types, stm.sfalse)) }
line("if (${dump(types, stm.cond)})") { line(dumpCollapse(types, stm.strue)) }
line("else") { line(dumpCollapse(types, stm.sfalse)) }
}
is AstStm.WHILE -> {
line("while (${dump(types, stm.cond)})") {
line(dump(types, stm.iter))
line("${stm.name}: while (${dump(types, stm.cond)})") {
line(dumpCollapse(types, stm.body))
}
}
is AstStm.DO_WHILE -> {
line("${stm.name}: do", after2 = " while (${dump(types, stm.cond)});") {
line(dumpCollapse(types, stm.body))
}
}
is AstStm.SWITCH -> {
Expand Down Expand Up @@ -94,7 +112,10 @@ fun dump(types: AstTypes, expr: AstExpr.Box?): String {
fun AstExpr?.exprDump(types: AstTypes) = dump(types, this)

fun List<AstStm>.dump(types: AstTypes) = dump(types, this.stm())
fun List<AstStm>.dumpCollapse(types: AstTypes) = dumpCollapse(types, this.stms.box)
fun AstStm.dump(types: AstTypes) = dump(types, this)
fun AstStm.dumpCollapse(types: AstTypes) = dumpCollapse(types, this.box)

fun AstExpr.dump(types: AstTypes) = dump(types, this)

fun dump(types: AstTypes, expr: AstExpr?): String {
Expand Down Expand Up @@ -136,6 +157,10 @@ fun dump(types: AstTypes, expr: AstExpr?): String {
is AstExpr.INVOKE_DYNAMIC_METHOD -> {
"invokeDynamic(${expr.extraArgCount}, ${expr.methodInInterfaceRef}, ${expr.methodToConvertRef})(${expr.startArgs.map { dump(types, it) }.joinToString(", ")})"
}
is AstExpr.CONCAT_STRING -> {
"''" + expr.args.map { it.dump(types) }.joinToString { "+" }
}
is AstExpr.RAW -> "${expr.content}"
else -> noImpl("$expr")
}
}
Expand Down
2 changes: 1 addition & 1 deletion jtransc-core/src/com/jtransc/ast/dependency/analyzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ object AstDependencyAnalyzer {
}
is AstStm.WHILE -> {
flow()
ana(stm.cond); ana(stm.iter)
ana(stm.cond); ana(stm.body)
}

else -> noImpl("Not implemented STM $stm")
Expand Down
Loading