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

Fixes java8 default methods in C++ target + add missing java.util.Map default methods + output jtransc-rt reports at travis #258

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ before_script:
- dmd --version || true
- "./gradlew --version"
script:
- "./gradlew -s -i check install"
- "./gradlew -s -i check install report"
- pushd jtransc-main-run/example
- "./run"
- popd
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +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)
[![Build Status](https://travis-ci.org/jtransc/jtransc.svg?branch=master)](https://travis-ci.org/jtransc/jtransc)
[![Build status](https://ci.appveyor.com/api/projects/status/qnd0g966t1b54q4a/branch/master?svg=true)](https://ci.appveyor.com/project/soywiz/jtransc/branch/master)
[![Code coverage](https://codecov.io/gh/jtransc/jtransc/branch/master/graph/badge.svg)](https://codecov.io/gh/jtransc/jtransc)
[![gitter](https://img.shields.io/gitter/room/jtransc/general.svg)](https://gitter.im/jtransc/general)

Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
12 changes: 6 additions & 6 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Sat Aug 05 17:26:11 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-bin.zip
#Sat Aug 26 21:50:50 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
6 changes: 3 additions & 3 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
warn () {
echo "$*"
}

die ( ) {
die () {
echo
echo "$*"
echo
Expand Down Expand Up @@ -155,7 +155,7 @@ if $cygwin ; then
fi

# Escape application args
save ( ) {
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
Expand Down
13 changes: 11 additions & 2 deletions jtransc-core/src/com/jtransc/ast/ast.kt
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,13 @@ inline fun <reified T : Any, R> KMutableProperty1<T, R>.locate(program: AstProgr

fun AstProgram.containsMethod(fqname: FqName, name: String) = this.getOrNull(fqname)?.getMethodWithoutOverrides(name) != null

enum class AstVisibility { PUBLIC, PROTECTED, PRIVATE }
enum class AstVisibility {
PUBLIC, PROTECTED, PRIVATE;

val isPublic get() = this == PUBLIC
val isProtected get() = this == PROTECTED
val isPrivate get() = this == PRIVATE
}
enum class AstClassType { CLASS, ABSTRACT, INTERFACE }

class UniqueNames {
Expand Down Expand Up @@ -344,7 +350,8 @@ class AstClass(
val extending: FqName? = null,
val implementing: List<FqName> = listOf(),
annotations: List<AstAnnotation> = listOf(),
val classId: Int = program.lastClassId++
val classId: Int = program.lastClassId++,
val comment: String = ""
) : AstAnnotatedElement(program, name.ref, annotations), IUserData by UserData(), WithAstModifiersClass {
val types get() = program.types

Expand Down Expand Up @@ -748,6 +755,8 @@ class AstMethod constructor(
}
val hasBody: Boolean get() = body != null

fun getActualBody(program: AstProgram): AstBody? = body ?: bodyRef?.let { program[it]?.body }

fun replaceBody(stmGen: () -> AstStm) {
this.generateBody = { AstBody(types, stmGen(), methodType, ref) }
calculatedBodyDependencies = null
Expand Down
111 changes: 61 additions & 50 deletions jtransc-core/src/com/jtransc/ast/ast_body.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,19 @@ data class AstBody constructor(
) {
private var _locals: List<AstLocal>? = null

val locals: List<AstLocal> get() {
if (_locals == null) {
val locals = hashSetOf<AstLocal>()
(object : AstVisitor() {
override fun visit(local: AstLocal) {
locals += local
}
}).visit(stm)
_locals = locals.toList()
val locals: List<AstLocal>
get() {
if (_locals == null) {
val locals = hashSetOf<AstLocal>()
(object : AstVisitor() {
override fun visit(local: AstLocal) {
locals += local
}
}).visit(stm)
_locals = locals.toList()
}
return _locals!!
}
return _locals!!
}

fun invalidateLocals() {
_locals = null
Expand Down Expand Up @@ -526,8 +527,11 @@ abstract class AstExpr : AstElement, Cloneable<AstExpr> {
val methodInInterfaceRef: AstMethodRef,
val methodToConvertRef: AstMethodRef,
var extraArgCount: Int,
var startArgs: List<AstExpr.Box> = listOf<AstExpr.Box>()
val kind: AstMethodHandle.Kind,
var startArgs: List<AstExpr.Box> = listOf<AstExpr.Box>(),
var thisArgs: List<AstExpr.Box> = listOf<AstExpr.Box>()
) : AstExpr() {
val isStatic: Boolean get() = kind.isStatic
override val type = AstType.REF(methodInInterfaceRef.containingClass)
}

Expand Down Expand Up @@ -658,35 +662,36 @@ object AstExprUtils {
}

fun INVOKE_DYNAMIC(generatedMethodRef: AstMethodWithoutClassRef, bootstrapMethodRef: AstMethodRef, bootstrapArgs: List<AstExpr>): AstExpr {
if (bootstrapMethodRef.containingClass.fqname == "java.lang.invoke.LambdaMetafactory"
) {
when (bootstrapMethodRef.name) {
"metafactory" -> {
val literals = bootstrapArgs.cast<AstExpr.LiteralExpr>()
val interfaceMethodType = literals[0].value as AstType.METHOD
val methodHandle = literals[1].value as AstMethodHandle
val methodType = literals[2].type

val interfaceToGenerate = generatedMethodRef.type.ret as AstType.REF
val methodToConvertRef = methodHandle.methodRef

val methodFromRef = AstMethodRef(interfaceToGenerate.name, generatedMethodRef.name, interfaceMethodType)

return AstExpr.INVOKE_DYNAMIC_METHOD(
methodFromRef,
methodToConvertRef,
methodToConvertRef.type.argCount - methodFromRef.type.argCount
)
when (bootstrapMethodRef.containingClass.fqname) {
"java.lang.invoke.LambdaMetafactory" ->
when (bootstrapMethodRef.name) {
"metafactory", "altMetafactory" -> {
val literals = bootstrapArgs.cast<AstExpr.LiteralExpr>()
val interfaceMethodType = literals[0].value as AstType.METHOD
val methodHandle = literals[1].value as AstMethodHandle
val methodType = literals[2].type

val interfaceToGenerate = generatedMethodRef.type.ret as AstType.REF
val methodToConvertRef = methodHandle.methodRef

val methodFromRef = AstMethodRef(interfaceToGenerate.name, generatedMethodRef.name, interfaceMethodType)

//val hasThis = !methodHandle.kind.isStatic
//val thisCount = if (hasThis) 1 else 0

return AstExpr.INVOKE_DYNAMIC_METHOD(
methodFromRef,
methodToConvertRef,
(methodToConvertRef.type.argCount - methodFromRef.type.argCount),
kind = methodHandle.kind
)
}
else -> {
noImpl("Unknown DynamicInvoke with LambdaMetafactory.${bootstrapMethodRef.name}!")
}
}
"altMetafactory" -> {
noImpl("Not supported DynamicInvoke with LambdaMetafactory.altMetafactory yet!")
}
else -> {
noImpl("Unknown DynamicInvoke with LambdaMetafactory.${bootstrapMethodRef.name}!")
}
}
} else {
noImpl("Not supported DynamicInvoke without LambdaMetafactory yet for class ${bootstrapMethodRef.containingClass.fqname}!")
else ->
noImpl("Not supported DynamicInvoke without LambdaMetafactory yet for class ${bootstrapMethodRef.containingClass.fqname}!")
}
}

Expand Down Expand Up @@ -776,25 +781,29 @@ operator fun AstExpr.times(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBi
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)

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())
operator fun MethodRef.invoke(vararg exprs: AstExpr) = AstExpr.CALL_STATIC(this.ref, exprs.toList())
operator fun MethodRef.invoke(exprs: List<AstExpr>) = AstExpr.CALL_STATIC(this.ref, exprs)

fun MethodRef.invokeInstance(obj: AstExpr, vararg exprs: AstExpr) = AstExpr.CALL_INSTANCE(obj, this.ref, exprs.toList())
fun MethodRef.invokeInstance(obj: AstExpr, exprs: List<AstExpr>) = AstExpr.CALL_INSTANCE(obj, this.ref, exprs)

operator fun AstMethod.invoke(exprs: List<AstExpr>) = AstExpr.CALL_STATIC(this.ref, exprs)
operator fun AstMethodRef.invoke(exprs: List<AstExpr>) = AstExpr.CALL_STATIC(this.ref, exprs)
fun MethodRef.invokeStatic(vararg exprs: AstExpr) = AstExpr.CALL_STATIC(this.ref, exprs.toList())
fun MethodRef.invokeStatic(exprs: List<AstExpr>) = AstExpr.CALL_STATIC(this.ref, exprs)

operator fun AstExpr.get(field: AstField) = AstExpr.FIELD_INSTANCE_ACCESS(field.ref, this)
operator fun AstExpr.get(field: AstFieldRef) = AstExpr.FIELD_INSTANCE_ACCESS(field, this)

operator fun AstExpr.get(method: MethodRef) = MethodWithRef(this, method.ref)
operator fun AstLocal.get(method: MethodRef) = MethodWithRef(this.expr, method.ref)

val AstStm.stms: List<AstStm> get() {
return if (this is AstStm.STMS) {
this.stms.map { it.value }
} else {
listOf(this)
val AstStm.stms: List<AstStm>
get() {
return if (this is AstStm.STMS) {
this.stms.map { it.value }
} else {
listOf(this)
}
}
}

val Iterable<AstStm>.stms: AstStm get() = this.toList().stm()
fun AstExpr.not() = AstExpr.UNOP(AstUnop.NOT, this)
Expand Down Expand Up @@ -917,6 +926,8 @@ class AstMethodHandle(val type: AstType.METHOD, val methodRef: AstMethodRef, val
REF_newInvokeSpecial(8),
REF_invokeInterface(9);

val isStatic: Boolean get() = (this == REF_invokeStatic) || (this == REF_getStatic) || (this == REF_putStatic)

companion object {
private val table = values().map { it.id to it }.toMap()
fun fromId(id: Int) = table[id]!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class UndeterministicParameterEvaluationFeature : AstMethodFeature() {
}
is AstExpr.INVOKE_DYNAMIC_METHOD -> {
val args = expr.startArgs.map { it.processExpr(stms).box }
AstExpr.INVOKE_DYNAMIC_METHOD(expr.methodInInterfaceRef, expr.methodToConvertRef, expr.extraArgCount, args)
AstExpr.INVOKE_DYNAMIC_METHOD(expr.methodInInterfaceRef, expr.methodToConvertRef, expr.extraArgCount, expr.kind, args)
}
is AstExpr.NEW_WITH_CONSTRUCTOR -> {
val args = expr.args.map { it.processExpr(stms) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,30 @@ class LambdaProgramFeature : AstProgramFeature() {
method.transformInplace {
when (it) {
is AstExpr.INVOKE_DYNAMIC_METHOD -> {
val methodInInterfaceRef = it.methodInInterfaceRef
val methodToConvertRef = it.methodToConvertRef
val startArgs = it.startArgs
val startArgsTypes = it.startArgs.map { it.type }
val invoke = it
val methodInInterfaceRef = invoke.methodInInterfaceRef
val methodToConvertRef = invoke.methodToConvertRef
val startArgs = invoke.startArgs
val thisArgs = invoke.thisArgs
val startAndThisArgs = startArgs + thisArgs
val startArgTypesAndThis = startAndThisArgs.map { it.type }

//val className = methodToConvertRef.classRef.fqname + "\$Lambda\$" + lambdaId++
val className = "L\$${lambdaId++}"
val lambdaClass = program.createClass(className.fqname, "java.lang.Object".fqname, listOf(methodInInterfaceRef.classRef.name))
val lambdaClass = program.createClass(className.fqname, "java.lang.Object".fqname, listOf(methodInInterfaceRef.classRef.name), comment = "INVOKE_DYNAMIC_METHOD(method=$method, methodInInterfaceRef=$methodInInterfaceRef, methodToConvertRef=$methodToConvertRef)")
val THIS = AstExpr.THIS(lambdaClass.name)

val storedFields = startArgsTypes.withIndex().map {
val storedFields = startArgTypesAndThis.withIndex().map {
val (index, type) = it
lambdaClass.createField("f$index", type)
}
val thisField = if (invoke.isStatic) null else storedFields.lastOrNull()
val storedFieldExprs = storedFields.map { AstExpr.FIELD_INSTANCE_ACCESS(it.ref, THIS) }

// If not static add this reference
val lambdaClassConstructor = lambdaClass.createConstructor(AstType.METHOD(AstType.VOID, startArgsTypes)) {
val lambdaClassConstructor = lambdaClass.createConstructor(AstType.METHOD(AstType.VOID, startArgTypesAndThis)) {
for ((index, field) in storedFields.withIndex()) {
val arg = AstArgument(index, startArgsTypes[index])
val arg = AstArgument(index, startArgTypesAndThis[index])
STM(AstStm.SET_FIELD_INSTANCE(field.ref, THIS, arg.expr))
}
}
Expand All @@ -47,15 +52,18 @@ class LambdaProgramFeature : AstProgramFeature() {
val startArgsExpr = storedFieldExprs.zip(argsStartTo).map { it.first.castTo(it.second) }
val argsExpr = argsFrom.zip(argsTo).map { it.first.expr.castTo(it.second) }

val call = methodToCall(startArgsExpr + argsExpr)
val call = when {
invoke.isStatic -> methodToCall.invokeStatic(startArgsExpr + argsExpr)
else -> methodToCall.invokeInstance(THIS[thisField!!], startArgsExpr + argsExpr)
}
if (methodInInterfaceRef.type.retVoid) {
STM(call)
} else {
RETURN(call.castTo(methodInInterfaceRef.type.ret))
}
}

AstExpr.NEW_WITH_CONSTRUCTOR(lambdaClassConstructor.ref, startArgs.exprs)
AstExpr.NEW_WITH_CONSTRUCTOR(lambdaClassConstructor.ref, startAndThisArgs.exprs)
}
else -> it
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ private class BasicBlockBuilder(
if (dynamicResult is AstExpr.INVOKE_DYNAMIC_METHOD) {
// dynamicResult.startArgs = stackPopToLocalsCount(dynamicResult.extraArgCount).map { AstExpr.LOCAL(it) }.reversed()
dynamicResult.startArgs = (0 until dynamicResult.extraArgCount).map { stackPop().box }.reversed()
dynamicResult.thisArgs = if (dynamicResult.isStatic) listOf() else listOf(stackPop().castTo(clazz).box)
}
stackPush(dynamicResult)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package com.jtransc.plugin.reflection

import com.jtransc.ast.*

fun AstProgram.createClass(name: FqName, parent: FqName? = "java.lang.Object".fqname, interfaces: List<FqName> = listOf(), gen: AstClass.() -> Unit = { }): AstClass {
fun AstProgram.createClass(name: FqName, parent: FqName? = "java.lang.Object".fqname, interfaces: List<FqName> = listOf(), comment: String = "", gen: AstClass.() -> Unit = { }): AstClass {
val program = this
val clazz = AstClass("source", program, name, AstModifiers.withFlags(AstModifiers.ACC_PUBLIC), parent, interfaces)
val clazz = AstClass(name.internalFqname + ".java.generated", program, name, AstModifiers.withFlags(AstModifiers.ACC_PUBLIC), parent, interfaces, comment = comment)
clazz.gen()
program.add(clazz)
return clazz
Expand Down
10 changes: 6 additions & 4 deletions jtransc-gen-common-tests/src/big/BigTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ import javatest.sort.CharCharMapTest
import javatest.sort.ComparableTimSortTest
import javatest.time.PeriodTest
import javatest.utils.*
import javatest.utils.Base64Test
import javatest.utils.CopyTest
import javatest.utils.DateTest
import javatest.utils.FillTest
import javaxtest.sound.SimpleSoundTest
import jtransc.WrappedTest
import jtransc.bug.*
import jtransc.java8.InnerLambdaTest
import jtransc.java8.Java8Test
import jtransc.java8.LambdaTest
import jtransc.jtransc.FastMemoryTest
import jtransc.jtransc.SimdTest
import jtransc.rt.test.*
Expand Down Expand Up @@ -105,6 +103,8 @@ object BigTest {
//JTranscClinitNotStatic.main(args)
//DefaultMethodsTest.main(args)
Java8Test.main(args)
LambdaTest.main(args)
InnerLambdaTest.main(args)

// Misc
Base64Test.main(args)
Expand Down Expand Up @@ -158,6 +158,8 @@ object BigTest {

JTranscBug244.main(args)
PeriodTest.main(args)

MapTest.main(args)
}

private fun servicesTest() {
Expand Down
Loading