From ffae98f7e06507cc09a20b6ed88dcf7cd96bb7e0 Mon Sep 17 00:00:00 2001 From: Ilya Matveev Date: Wed, 28 Feb 2018 15:00:20 +0300 Subject: [PATCH] [js-interop] Include JS interop into stdlib --- Interop/JsRuntime/build.gradle | 51 +++++---------- Interop/JsRuntime/src/main/js/jsinterop.js | 15 +++++ .../JsRuntime/src/main/kotlin/jsinterop.kt | 26 +++++++- backend.native/build.gradle | 4 +- build.gradle | 6 +- runtime/src/launcher/js/launcher.js | 2 +- runtime/src/main/cpp/DoubleConversions.h | 63 +++++++++++++++++++ runtime/src/main/cpp/JSInterop.cpp | 62 ++++++++++++++++++ runtime/src/main/cpp/Operator.cpp | 41 ++---------- runtime/src/main/cpp/Types.h | 6 ++ 10 files changed, 201 insertions(+), 75 deletions(-) create mode 100644 runtime/src/main/cpp/DoubleConversions.h create mode 100644 runtime/src/main/cpp/JSInterop.cpp diff --git a/Interop/JsRuntime/build.gradle b/Interop/JsRuntime/build.gradle index 9852e405464..98573164071 100644 --- a/Interop/JsRuntime/build.gradle +++ b/Interop/JsRuntime/build.gradle @@ -1,39 +1,20 @@ -import org.jetbrains.kotlin.KlibInstall - -apply plugin: 'konan' +/* + * 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. + */ buildscript { - repositories { - mavenCentral() - maven { - url kotlinCompilerRepo - } - } - - - dependencies { - classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin" - } - - ext.konanHome = distDir.absolutePath - ext.jvmArgs = project.findProperty("platformLibsJvmArgs") ?: "-Xmx3G" - ext.setProperty("konan.home", konanHome) - ext.setProperty("konan.jvmArgs", jvmArgs) -} - -konan.targets = [ 'wasm32' ] - -konanArtifacts { - library("jsinterop") { - dependsOn ':wasm32CrossDist' // our plugin runs konanc, so make sure it is already there. - extraOpts '-includeBinary', project.file('src/main/js/jsinterop.js') - } -} - -task installJsRuntime(type: KlibInstall) { - dependsOn konanArtifacts.jsinterop.wasm32 - klib = konanArtifacts.jsinterop.wasm32.artifact - repo = file("$konanHome/klib/platform/wasm32") - it.target = 'wasm32' + apply from: "$rootDir/gradle/kotlinGradlePlugin.gradle" } diff --git a/Interop/JsRuntime/src/main/js/jsinterop.js b/Interop/JsRuntime/src/main/js/jsinterop.js index 81a72e3c8e6..050b4a7bcf7 100644 --- a/Interop/JsRuntime/src/main/js/jsinterop.js +++ b/Interop/JsRuntime/src/main/js/jsinterop.js @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2018 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. + */ konan.libraries.push ({ arenas: new Map(), diff --git a/Interop/JsRuntime/src/main/kotlin/jsinterop.kt b/Interop/JsRuntime/src/main/kotlin/jsinterop.kt index 40c3f59d8ad..7183661c975 100644 --- a/Interop/JsRuntime/src/main/kotlin/jsinterop.kt +++ b/Interop/JsRuntime/src/main/kotlin/jsinterop.kt @@ -1,3 +1,19 @@ +/* + * Copyright 2010-2018 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 kotlinx.wasm.jsinterop import konan.internal.ExportForCppRuntime @@ -26,9 +42,13 @@ external public fun pushIntToArena(arena: Arena, value: Int) const val upperWord = 0xffffffff.toLong() shl 32 +@Used +@ExportForCppRuntime fun doubleUpper(value: Double): Int = ((value.toBits() and upperWord) ushr 32) .toInt() +@Used +@ExportForCppRuntime fun doubleLower(value: Double): Int = (value.toBits() and 0x00000000ffffffff) .toInt() @@ -61,7 +81,7 @@ fun runLambda(pointer: Int, argumentsArena: Arena, argumentsArenaSize: Int): Int val previousArena = ArenaManager.currentArena ArenaManager.currentArena = argumentsArena // TODO: LP64 unsafe: wasm32 passes Int, not Long. - val func = StableRef.fromValue(pointer.toLong().toCPointer()!!).get() as KtFunction + val func = pointer.toLong().toCPointer()!!.asStableRef>().get() val result = func(arguments) ArenaManager.currentArena = previousArena @@ -124,3 +144,7 @@ object ArenaManager { val globalArena = allocateArena() var currentArena = globalArena } + +@Used +@ExportForCppRuntime("Konan_js_getCurrentArena") +internal fun getCurrentArena() = ArenaManager.currentArena \ No newline at end of file diff --git a/backend.native/build.gradle b/backend.native/build.gradle index 2b388e96625..cfb2efcf501 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. + * Copyright 2010-2018 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. @@ -192,10 +192,12 @@ targetList.each { target -> '-produce', 'library', '-module_name', 'stdlib', project(':Interop:Runtime').file('src/main/kotlin'), project(':Interop:Runtime').file('src/native/kotlin'), + project(':Interop:JsRuntime').file('src/main/kotlin'), project(':runtime').file('src/main/kotlin')] inputs.dir(project(':runtime').file('src/main/kotlin')) inputs.dir(project(':Interop:Runtime').file('src/main/kotlin')) inputs.dir(project(':Interop:Runtime').file('src/native/kotlin')) + inputs.dir(project(':Interop:JsRuntime').file('src/main/kotlin')) outputs.dir(project(':runtime').file("build/${target}Stdlib")) dependsOn ":runtime:${target}Runtime" diff --git a/build.gradle b/build.gradle index 69da559f9d1..26c7043b2a8 100644 --- a/build.gradle +++ b/build.gradle @@ -291,8 +291,10 @@ targetList.each { target -> into("konan/targets/$target/native") } if (target == 'wasm32') { - from(project(':runtime').file('src/launcher/js')) { - into("$stdlib/targets/wasm32/included") + into("$stdlib/targets/wasm32/included") { + from(project(':runtime').file('src/main/js')) + from(project(':runtime').file('src/launcher/js')) + from(project(':Interop:JsRuntime').file('src/main/js')) } } } diff --git a/runtime/src/launcher/js/launcher.js b/runtime/src/launcher/js/launcher.js index b2e9d9432b6..01212fa4169 100644 --- a/runtime/src/launcher/js/launcher.js +++ b/runtime/src/launcher/js/launcher.js @@ -1,5 +1,5 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. + * Copyright 2010-2018 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. diff --git a/runtime/src/main/cpp/DoubleConversions.h b/runtime/src/main/cpp/DoubleConversions.h new file mode 100644 index 00000000000..0fe6a5c5380 --- /dev/null +++ b/runtime/src/main/cpp/DoubleConversions.h @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 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. + */ + +#ifndef RUNTIME_DOUBLECONVERSIONS_H +#define RUNTIME_DOUBLECONVERSIONS_H + +#include "Types.h" + +namespace { + +typedef union { + KLong l; + KDouble d; +} DoubleAlias; + +typedef union { + KInt i; + KFloat f; +} FloatAlias; + +} + +inline KDouble bitsToDouble(KLong bits) { + DoubleAlias alias; + alias.l = bits; + return alias.d; +} + +inline KLong doubleToBits(KDouble value) { + DoubleAlias alias; + alias.d = value; + return alias.l; +} + +inline KFloat bitsToFloat(KInt bits) { + FloatAlias alias; + alias.i = bits; + return alias.f; +} + +inline KInt floatToBits(KFloat value) { + FloatAlias alias; + alias.f = value; + return alias.i; +} + +extern "C" KInt doubleUpper(KDouble value); +extern "C" KInt doubleLower(KDouble value); + +#endif // RUNTIME_DOUBLECONVERSIONS_H diff --git a/runtime/src/main/cpp/JSInterop.cpp b/runtime/src/main/cpp/JSInterop.cpp new file mode 100644 index 00000000000..669305db45f --- /dev/null +++ b/runtime/src/main/cpp/JSInterop.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 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. + */ + +#include "Types.h" + +#ifndef KONAN_WASM + +extern "C" { + +// These functions are implemented in JS file for WASM and are not available on other platforms. +RUNTIME_NORETURN JS::Arena Konan_js_allocateArena() { + RuntimeAssert(false, "JavaScript interop is disabled"); +} + +RUNTIME_NORETURN void Konan_js_freeArena(JS::Arena arena) { + RuntimeAssert(false, "JavaScript interop is disabled"); +} + +RUNTIME_NORETURN void Konan_js_pushIntToArena(JS::Arena arena, KInt value) { + RuntimeAssert(false, "JavaScript interop is disabled"); +} + +RUNTIME_NORETURN KInt Konan_js_getProperty(JS::Arena arena, + JS::Object obj, + JS::Pointer propertyPtr, + KInt propertyLen) { + RuntimeAssert(false, "JavaScript interop is disabled"); +} + +RUNTIME_NORETURN void Konan_js_setFunction(JS::Arena arena, + JS::Object obj, + JS::Pointer propertyName, + KInt propertyLength, + KInt function) { + RuntimeAssert(false, "JavaScript interop is disabled"); +} + +RUNTIME_NORETURN void Konan_js_setString(JS::Arena arena, + JS::Object obj, + JS::Pointer propertyName, + KInt propertyLength, + JS::Pointer stringPtr, + KInt stringLength) { + RuntimeAssert(false, "JavaScript interop is disabled"); +} + +}; // extern "C" + +#endif // #ifndef KONAN_WASM diff --git a/runtime/src/main/cpp/Operator.cpp b/runtime/src/main/cpp/Operator.cpp index 4183fd8c6b0..c42373a37a0 100644 --- a/runtime/src/main/cpp/Operator.cpp +++ b/runtime/src/main/cpp/Operator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. + * Copyright 2010-2018 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. @@ -17,6 +17,7 @@ #include #include +#include "DoubleConversions.h" #include "Natives.h" #include "Exceptions.h" @@ -381,23 +382,8 @@ KDouble Kotlin_Float_toDouble (KFloat a ) { return a; } KByte Kotlin_Float_toByte (KFloat a ) { return (KByte) Kotlin_Float_toInt(a); } KShort Kotlin_Float_toShort (KFloat a ) { return (KShort) Kotlin_Float_toInt(a); } -KInt Kotlin_Float_bits (KFloat a) { - union { - KFloat f; - KInt i; - } alias; - alias.f = a; - return alias.i; -} - -KFloat Kotlin_Float_fromBits (KInt a) { - union { - KFloat f; - KInt i; - } alias; - alias.i = a; - return alias.f; -} +KInt Kotlin_Float_bits (KFloat a ) { return floatToBits(a); } +KFloat Kotlin_Float_fromBits (KInt a ) { return bitsToFloat(a); } KBoolean Kotlin_Float_isNaN (KFloat a) { return isnan(a); } KBoolean Kotlin_Float_isInfinite (KFloat a) { return isinf(a); } @@ -461,23 +447,8 @@ KLong Kotlin_Double_toLong (KDouble a ) { KFloat Kotlin_Double_toFloat (KDouble a ) { return a; } KDouble Kotlin_Double_toDouble (KDouble a ) { return a; } -KLong Kotlin_Double_bits (KDouble a) { - union { - KDouble d; - KLong l; - } alias; - alias.d = a; - return alias.l; -} - -KDouble Kotlin_Double_fromBits (KLong a) { - union { - KDouble d; - KLong l; - } alias; - alias.l = a; - return alias.d; -} +KLong Kotlin_Double_bits (KDouble a ) { return doubleToBits(a); } +KDouble Kotlin_Double_fromBits (KLong a ) { return bitsToDouble(a); } KBoolean Kotlin_Double_isNaN (KDouble a) { return isnan(a); } KBoolean Kotlin_Double_isInfinite (KDouble a) { return isinf(a); } diff --git a/runtime/src/main/cpp/Types.h b/runtime/src/main/cpp/Types.h index 850f19ef586..561a21d7e08 100644 --- a/runtime/src/main/cpp/Types.h +++ b/runtime/src/main/cpp/Types.h @@ -50,6 +50,12 @@ typedef ObjHeader* KRef; typedef const ObjHeader* KConstRef; typedef const ArrayHeader* KString; +namespace JS { +typedef KInt Arena; +typedef KInt Object; +typedef KInt Pointer; +} + // Definitions of STL classes used inside Konan runtime. typedef std::basic_string, KonanAllocator> KStdString;