Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Some people think Apple's JIT restrictions standing up to the DMA is a given, but I heavily doubt that will be the case.

The DMA allows for security exceptions only when measures are "strictly necessary and proportionate", Article 6(4). Apple argues that this ban is crucial for security, yet Android permits JIT compilation and maintains robust security on that front for 99% of its user base without significant incidents.



>Apple argues that this ban is crucial for security

Foxes argue the ban on chicken wire is crucial for their security.


There are some tricks to make interpreters very fast.


the best i've been able to do with things like numpy, threaded interpretive forth, and ocamlc is about 15–20% of native performance. is that what you mean by 'very fast'? i wouldn't call that 'very fast' but it is an order of magnitude faster than cpython i guess

for example, this ocaml program runs 6× slower when compiled with ocamlc (which uses an excellent bytecode interpreter) than with ocamlopt

    let rec fib n = if n <= 2 then 1 else fib (n-1) + fib (n-2)
      and n = 40
        in Printf.printf "fib(%d) = %d\n" n (fib n) ;;
the ocamlopt-compiled version is about 5% slower than a handwritten assembly version (and orders of magnitudes slower than a version compiled with gcc, which is why i wrote the assembly version)


Well, we’re talking about emulation here, not a bytecode interpreter for a high level dynamically typed language. CPython is fairly slow, it’s written in C in a fairly understandable way, effectively using a large switch statement. There’s like three jumps or so per executed bytecode, it probably uses some jump table.

„All the tricks“ for an interpreter would mean 1 jump per interpreted instruction, or perhaps 0.5 for some of them. It would probably mean no explicit jump tables. It would probably mean the interpreter is set up pipelined like a real cpu - loading instructions on parallel with executing previous instructions. You can get perhaps 5-15% of native speed using for an interpreter all the tricks. QEMU can maybe get 20-50% (not sure these days actually, I haven’t followed improvements for a while). Rosetta can get close to 100%, using a JIT but also hardware that is specifically designed to aid emulation (memory accesses like on x86).

Given nowadays CPUs execute like 3-5 instructions per cycle, getting 5-15% performance for an interpreter would be very fast and very difficult to achieve, but possible - if designed from the ground up for performance.


i think it's unusual to hit 3-5 ipc sustained in normal code, but it seems like we're in broad agreement about quantitatively what kind of performance an interpreter can achieve. i mentioned three interpretive systems that do reach about 15% of native single-threaded performance with very different approaches: the ocaml bytecode interpreter, threaded interpretive code like gforth, and numpy

it's just that i call 15% of native performance 'very slow' and you call it 'very fast', because you're comparing the moped to the walker you're used to, and i'm comparing it to a sports car because that's what you're paying for

instruction set jitting getting a speedup instead of a slowdown goes back to last millennium with hp's dynamo https://dl.acm.org/doi/pdf/10.1145/349299.349303 and was central to transmeta's business plan. qemu's jit is sort of simpleminded to make it easier to maintain


A cpu emulator will only get to 15-20% with a lot of tricks. Usually a cpu interpreter would get like 5%. It’s not like Numpy, where you can increase performance by trying to offload as much execution as possible into native code. When emulating cpu instructions, the atomic instructions are tiny. But as I said, python is a poor comparison because the interpreter is very slow and there is a lot of overhead.


although i've written compilers and interpreters, i don't think i've ever written an emulator for a real cpu. i'm interested to hear about your experience


Those tricks are called compilation (whether that be AOT, JIT, or a mix of the two).


No, then it’s not an interpreter anymore.


Yes, that was the point.

The tricks to make interpreters fast are to make them not interpreters.

This one is already using just about all the tricks in the book to make a "fast" interpreter and it's performance is a drip compared to a JIT version.


QEMU interpreter uses all the tricks? Very much doubt that. QEMU is a JIT first, built around maximum flexibility, not performance.

A dedicated, optimized x86 on ARM interpreter could probably get 20% off the performance of QEMU Jit, if not more.


Do you actually have any experience with systems emulation, JIT/AOT compilation, Apple's x86->ARM hardware assistance that it's JIT interfaces offer, etc? Or are you just speaking off the cuff in a very general manner?

Because it very much sounds like the latter.

I have, quite extensively. I can assure you, that the source set they are using most definitely does use all the "tricks" (the chief two being threaded code [no, not that threading] and preoptimized jump tables). I can also assure you that losing the hardware acceleration offered by Apple's extensions and the general performance boost JIT/AOT offer is much more than 80%.

But, sure. For argument's sake, let's accept your (incorrect) premise. Taking a 1ghz potential emulated target processor down to 200mhz is a fairly drastic drop. Disallowing a whole slew of modern code/target OSes and verging the usability on nil.


i wouldn't describe sacrificing 80% of the machine's native performance as 'very fast'. a moped goes 40 km/hour; a ferrari goes 200 km/hour. you're paying for a ferrari but getting a moped


An interpreter that runs at 20% native speed would be considered a very fast interpreter. That would be an order of magnitude faster than a „trickle“.


what i'm saying is that, because an interpreter that runs at 20% native speed would be considered a very fast interpreter, which is still very slow, there are in most cases no tricks for making interpreters very fast


Apple built iOS with the assumption that apps can’t use JIT. They can migrate to a new set of constraints, but I’m sure they’re right that right now it’s necessary for security. It could take a while to patch all of the security holes from opening up JIT.


How does MacOS survive attacks while supporting JIT and a subsystem for running iOS/iPadOS apps?


It’s a different operating system.


https://en.wikipedia.org/wiki/Darwin_(operating_system)

  Darwin is the core Unix-like operating system of macOS (previously OS X and Mac OS X), iOS, watchOS, tvOS, iPadOS, audioOS, visionOS, and bridgeOS. It previously existed as an independent open-source operating system, first released by Apple Inc. in 2000. It is composed of code derived from NeXTSTEP, FreeBSD, other BSD operating systems, Mach, and other free software projects' code, as well as code developed by Apple.


I’m aware. They’re still different.


Kernel is largely what matters here


So somehow they managed to create shittier system despite having 30 years of OS building behind their belt is what you’re saying?


“Shittier” Is your word, not anyone else’s. Can you really not relate this to any experience you’ve had developing anything?

Different goals? Different system gets built. Different trade-offs. This isn’t hard to understand. You’re being overly harsh for ideological reasons.


> Different goals? Different system gets built. Different trade-offs. This isn’t hard to understand. You’re being overly harsh for ideological reasons.

Poor Apple with its virtually unlimited resources. Somehow Google, Microsoft, Linux and Apple themselves managed to make it work with JIT, but Apple can’t do it.


You are arguing about resources of a company that has an endless amount of it. The limitations mentioned could be changed/"fixed" with no time and effort.


Can you teach me how it’s meaningfully different in terms of securely running a JIT compiler? What components should I be learning about?


The no JIT rule is just a rule enforced through the app store review process, so it's not going to part of the security architecture. It could of make some static analysis fail, but there are plenty of ways to do that.


I doubt that's true because it goes against every modern OS security practice. Apple heavily practices defense-in-depth. Sandboxing, PAC, AMFID, etc. All those are even more onerous than Android. So no, giving away JIT privs wouldn't do much.

EDIT: What's with the downvoting?


My understanding comes from what jailbreakers say about the OS, what Apple says, as well as time spent working at Android where people that know what they’re talking about told me about iOS security.


Your misunderstanding comes from a group of misinformed individuals than. Or you've made them up.

Either way, you're wrong.


>Either way, you're wrong.

This claim is based on what expertise?


There are about a dozen other responders who agree with said assessment with technical reasonings embedded into their messages. Read those.

Suffice to say, I don't feel the need to rehash why the basic premise of "the OS wasn't built to handle JIT apps" is directly contradicted by it, you know, allowing JIT in all but one app.

If they offered something of a basic technical assessment or reasoning beyond "I know people", perhaps then I would bother to dig into some credentialed argument. So, in the same way it's not worth delving into "proving God doesn't exist", it's not worth proving how OP clearly has no idea what they're talking about. They bear the burden of their claims, not me.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: