WEBVTT

00:00.000 --> 00:11.520
Okay, everybody, my name is Konovat.

00:11.520 --> 00:18.520
I work on the Swift team at Apple, I focus on primarily concurrency in server use cases.

00:18.520 --> 00:23.840
You may remember me from my Java life, in which I worked on Akka or the reactive streams

00:23.840 --> 00:24.840
spec.

00:24.840 --> 00:29.560
And yeah, it's great to be back and working a little bit with the JVM.

00:29.560 --> 00:34.520
So I will introduce Swift a little bit, a quick show of guys who is aware of Swift,

00:34.520 --> 00:36.000
who has used Swift.

00:36.000 --> 00:38.240
Okay, not so bad.

00:38.240 --> 00:43.320
So Swift is an open source language, works in many platforms, anywhere from Linux, Windows,

00:43.320 --> 00:48.120
to embedded systems, in firmware, anything between also wasm, which I don't have on

00:48.120 --> 00:51.000
this line, slide, but I just remembered.

00:51.000 --> 00:55.720
And it's a natively compiled language, it has an explicit goal to feel familiar to people

00:55.720 --> 00:59.160
coming from other ecosystems, including Java.

00:59.160 --> 01:05.200
It has a memory safe by default, and has pretty cool features like concurrency safety, verified

01:05.200 --> 01:07.600
that compile plan as well.

01:07.600 --> 01:12.960
Since day one, Swift got an amazing C-eaten objective, C interrupt story, which is how it

01:12.960 --> 01:16.920
managed to slowly replace objective C on Apple platforms.

01:16.920 --> 01:22.600
And we since then added an amazing C++ interrupt, which is really cool, and today we're

01:22.600 --> 01:25.520
adding Java to that list.

01:25.520 --> 01:28.840
So why do we even care about this?

01:28.840 --> 01:32.880
But I'm merely because of memory safety, so why do we care about memory safety?

01:32.880 --> 01:39.080
Well, memory safety vulnerabilities of a number one security vulnerability.

01:39.080 --> 01:43.360
So if we want to reduce those, it would be great to adopt memory safe language as across

01:43.360 --> 01:45.240
the whole stack.

01:45.240 --> 01:50.080
And while Java is a good solution to that, you know, Java's memory safe, it's fine,

01:50.080 --> 01:54.640
but Java programs very often end up calling into native code at some point, and when

01:54.640 --> 01:56.240
you lose the safety.

01:56.240 --> 02:00.800
So it's our opinion that whenever you're writing native code, Swift should be the tool

02:00.800 --> 02:02.720
you should be using for that.

02:02.720 --> 02:08.480
So in order to facilitate that, we need to be supporting incremental adoption of Swift,

02:08.480 --> 02:14.040
and what also means, infertility with many languages, and making it both easy and efficient

02:14.040 --> 02:15.040
to do that.

02:15.040 --> 02:19.240
I call it dark early on in the main track, how they told me just about that.

02:19.240 --> 02:24.840
So we decade of moving more and more of an ecosystem into Swift and memory safety.

02:24.840 --> 02:29.400
So, you know, that was in the past already, but you can check the video.

02:29.400 --> 02:31.640
And where do we care about this?

02:31.640 --> 02:34.080
A great example is, of course, servers.

02:34.080 --> 02:38.760
So there's a lot of Java services out there, and we're increasing number of native code

02:38.760 --> 02:43.280
in libraries written in Swift, and we would like to be able to call them both efficiently

02:43.280 --> 02:45.200
and nicely.

02:45.200 --> 02:50.480
The other situation is that it's interesting for Java and native intro up is Android.

02:50.480 --> 02:54.720
The common thing that happens is people want to have a shared library that is the core

02:54.720 --> 02:59.600
of their apps, and maybe interesting algorithms, and they want to use it in the server,

02:59.600 --> 03:01.840
on vermobile apps, and anywhere already.

03:01.840 --> 03:06.440
So we think again, Swift is a good language to do that.

03:06.440 --> 03:13.040
Golds and directions here, this is a small distinction on the primarily written in some language,

03:13.040 --> 03:18.000
where you can be primarily written in Swift, and maybe you need to call it Java library.

03:18.000 --> 03:19.000
And we do support that.

03:19.000 --> 03:23.560
We have some Swift macros and JNI wrappers, and you can kind of do that, but that's not

03:23.560 --> 03:25.560
what this talk is about.

03:25.560 --> 03:29.760
The second situation is when you have a primarily written in Java application, and you

03:29.760 --> 03:36.040
want to call it native code as the previous talk, gracefully explained with the new APIs

03:36.040 --> 03:38.520
that we just got with FFM.

03:38.520 --> 03:43.520
So this is what I will be talking about today.

03:43.560 --> 03:48.080
So Java and Swift, of course, have many differences, but you'll be surprised to find that

03:48.080 --> 03:51.880
there are actually a bit similar when you look deeper.

03:51.880 --> 03:56.000
Of course, Java is all about classes and objects, but it has primitives, and Valhalla

03:56.000 --> 03:59.040
is bringing value types to the JVM as well.

03:59.040 --> 04:04.200
Swift on the other hand has classes, but it's very much focused on rich value types.

04:04.200 --> 04:08.720
So again, something that the slogan of Valhalla that calls like a class works like an

04:08.720 --> 04:12.640
int, very much applies to Swift's value types.

04:12.640 --> 04:18.520
Of course, both are memory managed, so we have a GC here in the JVM and automatic reference

04:18.520 --> 04:19.520
counting.

04:19.520 --> 04:24.840
Yes, but it is a difference, but for the most part of a developer's day, it's a very similar

04:24.840 --> 04:26.440
user experience.

04:26.440 --> 04:30.280
And the generics, of course, have a slight difference as well, so the JVM is type of

04:30.280 --> 04:36.120
type of area at one time, and Swift has generics, but with fully reified types, that

04:36.120 --> 04:38.560
will be an interesting thing to dig into.

04:38.560 --> 04:42.520
There's smaller differences as well, so Swift has errors with your values versus exceptions

04:42.520 --> 04:48.640
with stack traces and the threading model, versus thread versus a single weight in actors,

04:48.640 --> 04:52.760
a bit different, but again, something we can work with.

04:52.760 --> 04:59.160
So a typical application, you will have some Swift sources, but either are from a library,

04:59.160 --> 05:03.280
or it's your Swift sources, and you will have some Java sources, but we'll want to use

05:03.280 --> 05:04.760
this native code.

05:04.760 --> 05:10.520
So we will build a dynamic library, depending on the platform you want to run it on, and

05:10.520 --> 05:12.200
here's the new things.

05:12.200 --> 05:16.760
We will have a tool that will generate Java sources that will make calling this native

05:16.760 --> 05:18.160
library easy.

05:18.160 --> 05:25.960
This is where we will be using the FFMAPIs for function interfaces to call down to this dynamic

05:25.960 --> 05:26.960
library.

05:26.960 --> 05:31.440
We will also have to generate a bit of Swift code, which is a bit unfortunate because

05:31.440 --> 05:36.600
with a plain C-style language, you wouldn't need to do that, and I would explain in depth

05:36.600 --> 05:40.680
why we have to do this bridging layer.

05:40.680 --> 05:45.120
At the end of the day, you put it in a jar, or in your ship for dynamic library separately,

05:45.120 --> 05:47.800
and you can just call these functions.

05:47.800 --> 05:51.720
So we do have a tool that is called JXTrack Swift.

05:51.720 --> 05:57.120
The name is very much inspired by the JXTrackStool, which is something from the JDK that

05:57.120 --> 06:02.360
takes C header files and turns it into these Java wrappers that you can use to call

06:02.360 --> 06:03.800
these C functions.

06:03.800 --> 06:09.280
So our tool is very much inspired on that, looks more or less like this, where instead

06:09.280 --> 06:14.280
of accepting C header files, we take Swift sources, and again, generate the Java code

06:14.280 --> 06:18.560
that it makes it possible and easy to call into these native functions.

06:18.560 --> 06:23.440
The tool is split up in a few phases, or some analysis phase, so Swift is a very explicit

06:23.440 --> 06:24.440
language.

06:24.440 --> 06:29.960
For example, you can have extensions on types located in other modules or sources, so we

06:29.960 --> 06:35.600
have to do a little bit of analysis to figure out what's type has, what's which method.

06:35.600 --> 06:39.840
And now later on, of course, this is the source generation step.

06:39.840 --> 06:43.840
Today we use the foreign function in memory APIs.

06:43.840 --> 06:49.120
We could have a source generation step that would use the legacy, you know, JNI APIs for

06:49.120 --> 06:52.840
platforms that just don't have the FAM yet.

06:52.840 --> 06:56.360
And we do generate these Swift function as well.

06:56.360 --> 07:00.160
And so how does it look like when we extract some source?

07:00.160 --> 07:02.960
Let's say we want to extract a Swift class.

07:02.960 --> 07:07.960
Swift class is imported as this, we're about and we implement this with KeepObject.

07:07.960 --> 07:12.160
We use this primarily to know that Aha, this object has to be referenced counted because

07:12.160 --> 07:17.280
we will try to do the right thing on the Java side as well as we import these types.

07:17.280 --> 07:22.440
When we extract a struct, we implement this with value, which again is a signal for us

07:22.440 --> 07:28.440
but okay, we will be copying this Swift value around rather than reference counting.

07:28.440 --> 07:33.920
Next we will be generating all of this for in foreign function descriptors.

07:33.920 --> 07:39.120
The previous talk very much explained, so we generate those, so we don't have to write,

07:39.120 --> 07:42.160
you know, the function signatures by your hand, by hand.

07:42.160 --> 07:47.360
And we finally generate the actual methods that Java developers will call, which kind

07:47.360 --> 07:51.640
of mirror the native shapes of the methods will be calling.

07:51.640 --> 07:57.680
An interesting thing here is, at the bottom one, you can see that these types can have

07:57.680 --> 08:03.400
other imported types, so I'm passing a my Swift struct in the Java side of things.

08:03.400 --> 08:11.080
And yes, this will be wrapping a Swift struct and we can just call a collection of Swift libraries

08:11.080 --> 08:17.000
without doing weird dances, we can just use them more and it all fits together.

08:17.000 --> 08:21.600
So I did say that we are using Swift sources, I feel that I have to explain the

08:21.600 --> 08:28.200
fact that for Swift, it is typical to use Swift sources as packet distribution mechanism.

08:28.200 --> 08:32.200
So when you publish a package, it's a get repository, you get for sources, so we always

08:32.200 --> 08:34.360
have resources available.

08:34.360 --> 08:38.040
But if you don't have the sources available, for example, you're using an operating system

08:38.040 --> 08:43.280
provided library or just close source code, the same tool will actually work the same way

08:43.280 --> 08:49.120
because Swift does have something alike header files, which is the Swift interface files,

08:49.120 --> 08:55.440
which are basically Swift source files, but except having extra bodies and implementations,

08:55.440 --> 08:57.560
it just could out without the bodies.

08:57.560 --> 09:03.560
So the same tool works the same way with those source or operating system provided library

09:03.560 --> 09:04.560
libraries.

09:04.560 --> 09:10.720
Okay, let's dive in and we will start from an interesting point which is initializers

09:10.720 --> 09:16.320
because they will lead us to some interesting discoveries I want to talk about today.

09:16.320 --> 09:21.880
So let's say I want to extract from this Swift source file, so it's an initializer, it takes

09:21.880 --> 09:27.080
a length and it takes a capacity, the capacity is another value type and I want to import

09:27.080 --> 09:30.000
that into Java.

09:30.000 --> 09:35.240
So of course we generate the function descriptor as you can see here, it will return a Swift

09:35.240 --> 09:41.760
pointer which is the initialized object and we accept the length and we accept the capacity

09:41.760 --> 09:46.720
as a pointer to that struct and oh wait what's that?

09:46.720 --> 09:53.080
We didn't see that in the Swift signature, it's another parameter here that is the Swift type.

09:53.080 --> 10:00.480
So somehow we will have to find out at runtime the Swift type metadata that we have to pass

10:00.480 --> 10:05.880
to this native function initializer to be able to call it.

10:05.880 --> 10:09.080
So how can we find that?

10:09.080 --> 10:13.560
Luckily we can just ask Swift to give us the type.

10:13.560 --> 10:18.760
So on the Java side we generate a little call that will basically down call into Swift using

10:18.760 --> 10:24.760
a well known function name and on the Swift side it's very simple because we just write

10:24.760 --> 10:27.640
the type and we just return it.

10:27.640 --> 10:32.320
I'll talk about the details of these functions a bit later, but basically I'm just returning

10:32.320 --> 10:35.760
the value out of Swift back into Java.

10:36.000 --> 10:40.920
This should feel familiar because on the JVM we have a class object and the type metadata

10:40.920 --> 10:41.920
is exactly what it's.

10:41.920 --> 10:46.880
It's very equivalent of a class object, it describes, hey this type is this and that.

10:46.880 --> 10:50.760
The type is immortal so I don't have to worry about retaining it or anything like that,

10:50.760 --> 10:53.440
I can just return it like that, let's find it.

10:53.440 --> 10:58.240
We've installed that on the Java side and we're ready to call initialize it directly,

10:58.240 --> 10:59.240
very cool.

10:59.280 --> 11:05.720
This way I can literally do a down call and I get back a Swift instance but I now have

11:05.720 --> 11:10.000
a reference to in the Java side.

11:10.000 --> 11:14.760
What about value types which is I think we've spent most of the talk because they're

11:14.760 --> 11:20.040
more interesting and value types are interesting because of course on the Swift side

11:20.040 --> 11:23.680
they will be stack allocated, that's the reason you want to have value types, they can be

11:23.680 --> 11:27.400
stack allocated and they're nice and efficient to pass around.

11:27.400 --> 11:32.080
So if we were to just return the same way as we did with the class, point to that would

11:32.080 --> 11:38.960
be pointing to a stack which could very easily be not valid anymore as I use it in Java.

11:38.960 --> 11:45.160
So instead what we do is we create a small allocation of your exact right size that the

11:45.160 --> 11:49.160
Swift initializer will fill in with the data of the struct.

11:49.160 --> 11:54.440
Now the question becomes, well I don't know the size of the struct in Java, how do I find

11:54.440 --> 11:55.440
out?

11:55.440 --> 12:01.120
And we have an analysis phase so maybe I can do that, maybe I can use the analysis to

12:01.120 --> 12:04.600
just do the math and figure out the size of the struct.

12:04.600 --> 12:11.000
We can do that, if that's an integer that's two eight bytes then okay I know that my Swift

12:11.000 --> 12:16.840
class is a class, it's a pointer again eight bytes and then it's a struct I have to look

12:16.840 --> 12:22.440
at that struct and recursively keep descending to figure out the size of that and eventually

12:22.440 --> 12:25.760
I can find that out.

12:25.760 --> 12:31.520
I could also ask the Swift content to just tell me, so the Swift runtime, the Swift API called

12:31.520 --> 12:35.320
memory layout, you can give it a type and ask these kinds of questions so you get the

12:35.320 --> 12:42.240
size, the stride, the stride is just the size plus any necessary padding to align it properly.

12:42.240 --> 12:44.760
And so we could ask Swift as well.

12:44.760 --> 12:49.480
But before we do that I want to explain why we have to do that.

12:49.480 --> 12:52.800
So what is the size of this struct?

12:52.800 --> 12:59.200
It's the same struct but now we're value and object types are generic, I know nothing

12:59.200 --> 13:04.040
about them and more interestingly when they could be reference types they could be value

13:04.040 --> 13:05.040
types.

13:05.040 --> 13:12.080
So the size of this struct at runtime really depends on how exactly it was used and I don't

13:12.080 --> 13:15.080
know by looking at this type declaration at all.

13:15.080 --> 13:18.080
So I don't know how to generate this initializer.

13:18.080 --> 13:24.280
So another cool thing about that is you may know if you've looked at a Valhalla which

13:24.280 --> 13:32.200
is we can produce tightly packed arrays and other structures using these kinds of mechanisms.

13:32.200 --> 13:37.080
But again we have to know the exact type at runtime at moments we're trying to initialize

13:37.080 --> 13:38.080
the thing.

13:38.080 --> 13:40.440
So how could we do that?

13:40.440 --> 13:44.360
We already have the type metadata and okay if the type metadata doesn't actually have

13:44.360 --> 13:48.760
this information but we can calculate a simple offset and jump to something called

13:48.760 --> 13:51.040
the value witness table.

13:51.040 --> 13:57.160
So the value witness table is something that contains a lot of interesting both functions

13:57.160 --> 14:00.520
and values that we'll be using to work with value types.

14:00.520 --> 14:06.480
Specifically how to initialize how to copy how to destroy these values and great we

14:06.480 --> 14:12.920
have the size and all the data we need to do our initial allocation for.

14:12.920 --> 14:14.600
How can I use that?

14:14.600 --> 14:20.480
So that is actually a C struct so I can just describe it using the memory layout, struct layout.

14:20.480 --> 14:24.880
I literally just layout okay this is this field, this is that field I know this is an integer

14:24.880 --> 14:30.480
this user addresses and as I'm done with that I can get a Valhalla at the appropriate

14:30.480 --> 14:39.280
offset for a given value witness table because I have that I can get the size of any swift

14:39.280 --> 14:43.360
metadata that I press.

14:43.360 --> 14:49.080
So now we're able to not only just get oh I got the size we can go a bit nicer and get

14:49.080 --> 14:52.880
the entire memory layout description based on these information.

14:52.880 --> 14:58.240
So I get the size, write or calculate the padding and I can return a struct layout that

14:58.240 --> 15:04.440
it has the proper name that describes the swift type name and today at least it's going

15:04.440 --> 15:10.560
to look a little bit like this from the previous perspective it's you know native memory

15:10.560 --> 15:12.160
layout and it's a blob.

15:12.160 --> 15:16.360
At least it's the right size of blob so we're happy because we can initialize and copy

15:16.360 --> 15:21.640
it using the value witness functions but maybe we could do that a little bit better in

15:21.640 --> 15:26.360
the future today we don't have that metadata we could do that and then we could describe

15:26.360 --> 15:31.400
exactly oh I know this is an int and this is an int and we could do the absolute correct

15:31.400 --> 15:37.080
metadata and then even do direct access to the offsets rather than going to rather than

15:37.080 --> 15:39.320
doing down course.

15:39.320 --> 15:43.720
Okay so we can check that if I got that right I can implement for initializer for

15:43.720 --> 15:50.000
a value type at all before because I just passed the value layout as we do for arena allocation

15:50.000 --> 15:52.800
and then we initialize that using the initializer.

15:52.800 --> 15:57.760
As you can see we can just print that on the JavaScript and it always has the right amount

15:57.760 --> 16:00.520
of bytes we need to be passing around.

16:00.920 --> 16:06.080
It's really cool we just taught Java to understand the layouts of native Swift objects.

16:07.080 --> 16:11.720
Now let's actually call some methods on things and this will be also interesting.

16:11.720 --> 16:17.720
Let's have a again my struct and I want to call a method called capacity on it.

16:17.720 --> 16:24.920
Capacity is another value type so first thing first I describe the function the function

16:24.920 --> 16:30.040
is a member function so we need to pass this the self as we call it in Swift.

16:30.040 --> 16:34.440
Let's say I pass it as the first parameter here and when we describe the rest of the function

16:34.440 --> 16:39.040
it's going to return again indirectly because it's a value type as we talked before

16:39.040 --> 16:44.200
in initializers I do the dance with getting the value layout, allocate that do the

16:44.200 --> 16:48.880
down core and they return I wrap it again with the appropriate wrapper type.

16:48.880 --> 16:52.280
Now how do I make this call?

16:52.280 --> 16:57.840
As as any of our non-seal language would today which is I have to generate a small

16:57.840 --> 17:02.480
function that we'll be calling using the C calling convention and we make sure using

17:02.480 --> 17:07.760
the C declarative use on the Swift side that okay this has to use the C calling convention

17:07.760 --> 17:12.320
and you know don't use features that C wouldn't understand like generic and you know other

17:12.320 --> 17:14.760
things that Swift has.

17:14.760 --> 17:19.840
This function doesn't really do much except cast the things to appropriate types and

17:19.840 --> 17:24.720
down core into the actual Swift function using the Swift convention because it Swift

17:24.720 --> 17:26.400
is calling Swift.

17:26.400 --> 17:32.160
Now in an ideal word we wouldn't do any of that and just call directly right with interaction

17:32.160 --> 17:37.680
costs as both build complexity I have to generate these things build times I have to compile

17:37.680 --> 17:42.800
them and of course performance because the yet another interaction in the way that would

17:42.800 --> 17:49.160
be cool if we could call directly and you know maybe to explain even more so why do we

17:49.160 --> 17:54.320
even need this interaction well Swift actually has its own calling convention and

17:54.320 --> 18:00.200
that's because it's you know optimized to patterns and invocation invocations that

18:00.200 --> 18:05.840
it often does and one of those optimizations in this API is that self must be passed in

18:05.840 --> 18:11.920
register so it's not like passed in a parameter it must be passed in a register but Swift

18:11.920 --> 18:17.360
has a stable API so we can easily find out where we should be passing it so the

18:17.360 --> 18:22.000
API is stable on some platforms it's well described you can check it out here so specifically

18:22.000 --> 18:31.440
on this register on x86 in this one cool so can we fix the JDK to use the Swift calling

18:31.440 --> 18:37.440
convention so I can get my magical dreamland version of directly calling yes and no I believe

18:37.440 --> 18:41.920
the code is very well structured and we have an opportunity to do that it would be here in

18:41.920 --> 18:47.200
the color range of a specific platform or maybe the calling sequence builder which would you

18:47.200 --> 18:52.720
know we would maybe tell it hey this parameter is special so that's a good news the bad news

18:52.720 --> 18:57.920
is these types are JDK internal so that's not something we did today but it's certainly

18:57.920 --> 19:03.600
possibility and other one times like dot net runtime inversion 9 have actually explored that

19:03.600 --> 19:09.840
a bit and that's a PR that implements parts of Swift's calling convention again to be able

19:09.920 --> 19:16.880
to call directly rather than from some sea shims and finally a little bit of object lifetime

19:16.880 --> 19:24.480
discussion because object lifetimes and memory safety is kind of the core of our goal here right

19:24.480 --> 19:31.920
we want to have this integration have a nice and safe so how do we do that but before I say how

19:31.920 --> 19:37.120
I need to explain what's really destroying a value means in Swiftland because it's actually a

19:37.280 --> 19:43.040
little bit different than on the JVM so again value types may have a value type code container

19:43.040 --> 19:49.680
it contains a number core primitive a person and the person is a reference type so if I create

19:49.680 --> 19:55.920
this container and then assign it to it because we're a reference content you know the ways with works

19:55.920 --> 20:02.240
this will be then this will call destroy on this value type from our good friend the value

20:02.240 --> 20:07.600
within stable this will then go through all the fields and call destroy on them or if it's a

20:07.600 --> 20:16.800
reference type eventually just release a retain come release on it if that gets zero we have to run

20:16.800 --> 20:22.080
we didn't the initializer and we're gonna run we didn't the initializer right now and noted

20:22.080 --> 20:27.840
some later point like it would be we finalize some of the JVM so developers expect this to work

20:27.920 --> 20:37.040
like this so what do we do to make it work with this we actually got inspired from the arena's API

20:37.040 --> 20:42.800
and we offer something called a Swift Arena in the you know support library that comes with all of

20:42.800 --> 20:49.680
us and yes it's a segment allocator same as arena's in the JDK but we also when we do initializers

20:49.680 --> 20:57.680
of return types we register them with the Swift Arena now we register them of course to manage

20:57.680 --> 21:04.080
for lifetimes so as I have registered for example in a Swift Arena of confined style which is

21:04.080 --> 21:10.320
again inspired by open JDK arena at the end of this scope we will call destroy on all the types

21:10.320 --> 21:16.480
that were registered with it again that is why we'll do the right thing here the same pattern

21:16.640 --> 21:20.800
applies for reference types you can just register them create them in this scope and we will just

21:20.800 --> 21:27.440
reference comes down on them today if we read if we don't read reference comes zero here we assert

21:28.080 --> 21:34.240
but I think you could totally see valid use cases for maybe you want to assert if it didn't get

21:34.240 --> 21:38.880
released and destroyed at the end of the scope or maybe you do actually want to you know just keep

21:38.880 --> 21:45.600
this style for maintaining reference counting so this is something we can do and we also try to

21:45.600 --> 21:52.880
guard against programmer errors so on the Java side you could make a mistake and unsafe he escaped

21:52.880 --> 21:58.320
a value created during this scope and you try to escape it outside of it so of course after

21:58.320 --> 22:02.480
this scope this value would have been destroyed it would be pointing its tail of the marine so on

22:02.480 --> 22:08.960
the Java side as we do with the choice we mark them so we don't try to down core into memory

22:08.960 --> 22:16.240
that was already the allocated again or then the name of safety so we don't the bad things here

22:16.880 --> 22:23.040
now we do have an auto arena as well again inspired by open gdk where we use phantom references

22:23.040 --> 22:28.800
and a cleaner thread to clean up these objects eventually I think it's great for prototyping if you

22:28.800 --> 22:34.800
want to show you know evry Java or swive developer hey please give us a go think that's a good one to

22:34.880 --> 22:40.800
start and there may be other situations where you want to rely just on the gc to these things as well of

22:40.800 --> 22:46.800
course it's less predictable than so for swive developers this would be a bit can be a bit surprising

22:48.720 --> 22:54.160
as you can see this is a very deep integration we're not just saying hey you can call

22:54.160 --> 22:59.600
simple functions now we're shooting for integration of both a programming model and 2020 you

22:59.600 --> 23:07.200
would safety as well as you know making it a pleasant thing to use and with the end goal of being

23:07.200 --> 23:13.680
able to import really most if not all swift code we have laying around so if you walk away from

23:13.680 --> 23:19.920
this talk I'd like to remember I'd like you to remember one thing but on goal is here to have memory

23:19.920 --> 23:25.360
safety all the way we don't have to lose memory safety as we cross into native land and if we

23:25.360 --> 23:31.760
collaborate from both sides with the AVM and the native language you know enforcing each

23:31.760 --> 23:38.560
other's patterns then we can pull that off swift and if a family PI's really worked well together

23:38.560 --> 23:45.440
I didn't show super crazy advanced cases but we can integrate them very deeply even with you know

23:45.440 --> 23:51.040
more in generics and use cases I didn't show today and you know value types are the core of swift

23:51.120 --> 23:56.400
and we can actually deal with them pretty well in Java which has been great so there's ongoing

23:56.400 --> 24:01.840
work on direct-track swift if you're interested in you know integration between languages like that

24:01.840 --> 24:08.960
please let us know and whatever like upcoming next steps we can look into of course performance

24:08.960 --> 24:15.200
if you're interested in performance let's say never ending story here of course we'd like to

24:15.200 --> 24:20.240
challenge a little bit of the generics because we want to support optionals and connections

24:20.320 --> 24:25.520
and then we will have to handle generics as well as swift closures and you know passing a

24:25.520 --> 24:30.800
closure to a swift function and then calling that on the swift side we can implement using up

24:30.800 --> 24:37.840
course into the AVM as well and you know express swift closures as function interfaces and you know

24:37.840 --> 24:44.880
those other calling convention differences for example for errors or async code and last but not least

24:44.880 --> 24:53.760
integration so that's all I had if you have questions please check me outside later on and thank you very much

25:14.880 --> 25:16.880
you

