Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Suspicious Dish posted:

LLVM doesn't make a good JIT. It is, in fact, a ridiculously bad JIT.

It's good as a

poo poo where am i

its good as a second-tier jit if ur runtime/abi isnt too asm-hacky, or for srs workloads that ur planning to run the hell out of like a shader, but yeah, it is hopeless as a primary execution engine for run-once, loopless code lol

it is def. heavyweight enough that U have to bias hard against it, like the old hotspot server jit

but if U actually care about producing static-compiler-quality code at runtime it is pretty peerless

its a tool is what i'm sayin

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
compilers are gross, but p-lang implementations are all disgusting, too

because there are three cases

in the first, somebody has cared enough to write a jit, and jits are universally disgusting. also literally every principle of software development has been actively ripped out and shat on in pursuit of a .2% parse time win. if you switch the order of two functions, you will inexplicably cause a 100% reproducible 6% regression on dune2-render.rb and earn the eternal scorn of the entire contributor base

in the second, there ought to have been a jit years ago, but the existing non-jit implementation is so disgustingly convoluted and has so many tendrils absolutely everywhere that nobody can make a jit that doesn't break literally everything, and also guido is a moron

in the third, nobody has ever given a poo poo about your pathetic little p-lang, so it is probably still using a loving recursive descent interpreter and nobody ever actually finished the GC or made it sub-exponential, and you just went ahead and ported it to ARM you heartless bastard and you probably didn't even compile with optimization enabled because it crashes in runtime initialization when you do and some goddamn user is out there wondering if he needs to buy a new phone because his battery suddenly can't hold a charge anymore and he will never, ever connect that with the date that he installed that hilarious app that's like a normal shopping list except it makes fun of his lovely taste in organic fruit-inspired exercise bars, and i hate you you disgusting person i will find you

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Cybernetic Vermin posted:

we might as well argue theology at that point though for all the practical relevance this has

no, compilers have actually made a lot of progress in terms of convincing programmers to fix their broken poo poo

gcc deserves a ton of credit for making c people more serious about code quality: undefined behavior, warnings, standards comformance, etc.

even if they also mishandled some stuff like strict aliasing

these days, even idiots and kernel hackers can be convinced that they should probably use volatile for whatever batshit memory trick they're doing today

that is serious progress

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Malcolm XML posted:

c calling convention keeping the tail called functions down :negative:

you can tail-recurse in basically any imaginable calling convention

as long as the stack arguments area is the same size between the calls, which it is when you're recursing to (at least) something with the same formal signature, and which is ofc much more generally true in a decent god-fearing convention that uses registers

ofc if you're directly recursing then the compiler should just turn your function into a loop

the main obstacle that c presents for tco is that the compiler has to prove that the function doesn't depend on the enclosing stack frame still existing

i.e. that no addresses of local variables have escaped or are passed to the call

which ofc is more frequently unprovable in c++

anyway callee-pop conventions are terrible and get way more complicated in real life where you care about stack alignment

and it turns out that functions with so many arguments that they run out of argument registers in a sensible convention tend not to be tail-callable very often anyway

but if you've got a language requirement to do tco then you gotta do what you gotta do

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

hackbunny posted:

how do you recurse in an anonymous function then? :confused:

e: how is getting a function pointer going to interfere with jit? :confused: it's type metadata, not code
e2: genuinely curious, I love compiler design & theory

it doesnt block jitting

the arguments array makes it basically impossible to do data flow analysis involving parameter variables, because anything that could cause a call to user code (i.e. basically everything) could reflectively modify the arguments array, which iirc is specced to alias the parameters

and the callee stuff blocks you from doing any useful call-graph or escape analysis, e.g. to try to help with the above

so you can have something like function(x,y,z) { return x+y+z } which you might think would be really easy to prove a lot of things about

but the implicit conversions as part of the first plus could invoke user code that does thisFunction.callee.arguments[2]++ or something like that

or just stash the callee somewhere so now you cant prove anything about all the known callers or something

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Suspicious Dish posted:

Hm, are you sure? I thought Function.prototype.arguments was flat out removed in ES5.

who the gently caress cares what the loving ecmascript standards committee did

maybe that poo poo matters if you agonize over putting all of your javascript code in pretty little precisely-versioned script tags

go gently caress yoursefl

out in the real loving world deprecation is meaningless and browsers will support this poo poo forever

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Suspicious Dish posted:

Sure, you have to support the old code, but you can just give it lovely performance. Browsers are already killing fancy JIT optimizations for non-strict-mode code.

who is doing this

i see people doing more optimizations that are enabled only in strict mode

great, that is what strict mode does, it enables stuff with stronger guarantees

but who is disabling existing optimizations because "lol clearly the web is predominantly strict mode now"

it's pretty loving easy to check whether a web page uses it because it literally has to contain those ten characters somewhere in its content

google.com has two loving functions that use strict mode

google loving news has none

but oh man, somebodys lovely html5 tech demo raytracer uses it, let's go pessimize nytimes.com

which actually seems to use it a lot but still only on like half their code

because of course nobody dares enable it globally

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Deus Rex posted:

can you even enable it globally? I thought it was just per-script at most.

sorry, thats what i meant, i don't actually do web crap, i just worked on an engine once

but iiuc everybody is terrified of putting it at the top of a script because of the concatenation problem

also that benchmark does absolutely nothing that would be optimized by use strict

but the performance impact is indeed somewhat overstated

mostly because everybody puts the effort in to make non-strict code fast anyway

like iirc webkit handles the caller arguments crap by optimistically assuming it doesnt happen and then retroactively turning back to the interpreter if it dynamically does

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Deus Rex posted:

not everything has total equality, e.g. NaN != NaN is false, NaN == NaN is also false

NaN != NaN is true

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
yes but sbrk is really hard to use guys

would you rather use sbrk or this beautiful gc

actually one of these four beautiful completely reimplemented gc algorithms

one of which may actually leak everything that escapes the young generation

and one that might not be quite stable yet

something about boots, i dunno

but its totally parallel

just dont have too many boots whatever that means

but if its this or sbrk man you gotta ask yourself

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
yes sbrk is a really terrible way to run a heap

i was subtly implying that most arguments about gc were born in a simpler age

a dumber age

and that people tend to contrast gc with explicit malloc/free as if there were literally no intermediate positions

and as if C++ programmers literally spend all their time chasing down use-after-free errors

but i was very subtle about my implications

subtle

ofc i say all this having just spent a few hours chasing down a use-after-free error

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Otto Skorzeny posted:

it;s me i'm the guy who only ever uses a pool allocator

it actually was pool-allocated

but we were removing it from lists and calling destructors anyway because we detected that it was "unused"

in fact it would still have been a bug in a gc language because the original bug was a byproduct of the inconsistency, not of memory corruption

and the memory corruption associated with the object was a really obvious clue about what was going wrong

so in some ways it was easier to debug because it wasnt a gc language

because deinitialization implicitly signals object invalidation like nothing else ever could

but i wanted to be nice to the gc fans

because someone has to

and its not going to be me

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

jooky posted:

why do you make posts in this format

inadequate exposure to philosophical marxism in my youth

Dicky B posted:

i read it like a really fat dude taking a raspy breath after each newline

p. much accurate

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Cybernetic Vermin posted:

the perfection of gc is one of those slightly annoying nerd myths that i think mostly exists because people like absolutes, when very few absolutes exist. gc is deeply flawed, and has the very distinct downside of being an all-or-nothing proposition if it is to work well and be easy to work with. pretty clearly desirable for robust software, but a source of many problems and often not at all desirable.

i sort of hold that a lot of the runtime design (and the languages built on its assumptions) today operates on a slightly incorrect level, in that any application using an appreciable amount of memory (from say 200 megs and up) will have a small number of different classes/types, living in a fairly small number of collections (possibly implicit collections in the form of object graphs), but will still be treated as units, carrying their own tagging/vtables/metadata. the baseline assumption really should be that atomic pieces of data are owned by a collection, which carries the common metadata, and lifetime-manages, its contents. ideally every piece of data is only referred to from one place, and very commonly this is easy to achieve, and makes a lot of management superfluous. the relative minority of objects that are not numerous belong to a singleton collection, which is more overhead than they would otherwise have, but averages better across a reasonably sized application

unfortunately that type of thing is extremely unlikely to be brought about, since displacing existing design thought of an object graph of entirely independent tiny pieces of data would be a monumental undertaking

the situation you call out as ideal — monomorphic data referenced from a unique location — has most of the guarantees necessary to inline storage into the "container", which is (1) generally a superior design for performance and (2) a feature of quite a number of languages already. external tagging alone can be done in a slightly broader set of cases because inlined storage requires a non-recursive type, but i think you'd agree that that's not in the interesting subset

it's very difficult to do even external tagging implicitly in most OO languages, though, because you have to prove that the object is never used polymorphically (including by the GC if applicable, and designing the GC metadata to express specific types instead of just object/non-object makes GC much more expensive). you can do it with user annotations that say that the type isn't polymorphic, ofc, but once you've got that, you should really just go the step further and make the annotations inline the storage

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
it's actually semantically different in JavaScript

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
real assemblers are actually somewhat sophisticated tools with non-trivial (if still simple) expression grammars and macro expansion rules, but they are ultimately kindof designed to not have any really interesting problems; the semantics are intentionally geared towards being able to do all interesting layout in a single pass, followed by a second pass to actually put the right offsets in place in memory

depending on the machine language, there can be some interesting code-size optimization problems around things like jump offsets

and there are some somewhat interesting diagnostic problems like recognizing that something in the output is not position-independent

but yes, the pos is correct that it's ultimately a pretty well-understood and self-contained problem

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

JewKiller 3000 posted:

wow that almost sounds like a recruiter who is good at his job. i wonder what those are like

precious and few

i heard whispered rumors of one once

back in reality we had to fight the recruiters to shut up stop doing anything just give us every single loving resume jesus christ you know nothing about what we're looking for and can just gently caress off

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Suspicious Dish posted:

I have no idea what --porcelain does. All the commands that you use on a daily basis are porcelain commands.

there's a weird overload of terminology; git porcelain commands are the user-facing ones, but many commands also have a --porcelain option which specifically requests a stable text format in case you want to use them from... another layer of porcelain, i guess

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Otto Skorzeny posted:

quick q: why did the 32 bit unicode standard go with separate codepoints for combining characters

you have a bit over four billion codepoints to work with. can't we make a-mit-umlaut, u-mit-umlaut and o-mit-umlaut etc their own characters and have truly fixed width text instead of having a sequence of a|u|o followed by an umlaut and saving a few codepoints at the expense of having to break people of otherwise reasonable assumptions of how text works

but there are o-mit-umlaut characters etc. :science:

welcome to the awesome world of unicode normalization

the reason unicode does combining characters is that there are scripts where you can apply multiple marks to a single character, and providing a code point for every possible combination actually would be massively wasteful

i don't off-hand know why they thought it was a good idea to add combining characters for diacritics that they already had unified code points for, but it's probably related to the fact that they keep finding scripts that use diacritics on characters they weren't expecting, like Ӱ

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

pseudorandom name posted:

unicode is a 20 bit encoding, not 32.

~21, but yes. UTF-8 and UTF-32 could have supported much larger ranges of characters, but the UTF-16 surrogate pair scheme cannot, and they'd already sold everybody on UCS-2, so...

check out the regional indicators for some of the terrible poo poo that Unicode is pulling now out of concern for their code space

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

ComradeCosmobot posted:

its okay tho since theres a link to that site at the bottom of the page at on the apple dev site for the language and as we all know that makes this totally legit

we talked to them and worked something out, i don't know the details other than that they wanted to keep the domain and for us to link them from our site, which is honestly pretty reasonable as a condition of giving up a trademark

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

suffix posted:

so ARC is just normal refererence counting, right?

i somehow got the impression that it was using some clever new design from the hubbub when it came out, but i can't find anything special about it

the basic idea of a compiler doing automatic reference counting is pretty obvious and had been done a million times before, most notably in visual basic. and it's supposed to be really easy. if you're designing an environment around automatic reference counting, then you're going to set up all the obvious sensible invariants and transfer rules, like "a variable always owns a +1 on the object it references" and "return values are transferred at +1"

objective-c didn't have reference counting to start with; you called alloc, got an object back which you owned and eventually called dealloc on it. no shared ownership at all. if you were passed something and didn't own it, you were supposed to copy it. they eventually realized that this was causing massive performance problems from all the unnecessary copies just to get uniquely-owned objects, so they added reference counting. but it's manual reference counting, and programmers don't want to clutter their code with manual +1s (retains) and -1s (releases), so the convention is to only return +1 when you're returning a new object. somebody eventually wants to return a new object via an interface that doesn't expect it, so let's add an "autorelease pool", a thread-local collection of objects to be released at some safe point later. okay, now we want to take a bunch of APIs and have them return an error back, indirectly. is it really a good idea to trust the caller to do memory management correctly in an error case? better autorelease it instead so they don't have to think about it. eventually people realize they can use autorelease pools to let callers be lazy even with methods that are always expected to return new objects, because the autorelease pool removes the caller's need to remember to release it. oh and you can identify methods that return new objects using their names, except for all the exceptions.

basically, everything interesting about ARC is because the automatic reference counting was added years after the fact to a system that had gone absolutely batshit insane

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Malcolm XML posted:

Also no true data generic programming, so i have to write poo poo like description and json serialization and other boilerplate crap

Scrap your boilerplate is the best thing about haskell; rust grabbed the deriving mechanism but idk if it got the generics via anything but macros

we'll get there, we know and love this stuff too

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
i am not the "main designer" of swift

i am also not quite that ignorant, i am quite aware of normalization. i was just under the impression that unicode also had a locale-dependent notion of string equivalence, and it does, sortof, but it's not close enough to the PL notion of identifier equality to be worth pursuing.

also the idea that this poo poo is in any way important to PL design is hilarious. i am not designing the string type

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Monkeyseesaw posted:

what's a c constructor and destructor

code that runs before main begins / immediately before process exit, respectively

the concept is both necessary for implementing C++ and pretty useful for implementing any other sort of library, although it's also the kind of thing where every library author thinks they're king poo poo and sets up global constructors and then the program takes twenty minutes to launch so that some random operation can bypass a lazy-initialization check and run fifteen cycles faster when the user triggers the program's patented Share This On The Network feature which nobody actually uses in practice but it's still got its tendrils in every possible subsystem, waiting, watching

the application to C is part of a general trend which is much worse on unix but still present on windows where anything that introduces any sort of actually novel language expressivity has to be available to c programmers. on unix this is mostly the fault of the remarkably persistent but deeply incorrect belief that c++ can be implemented as a sort of pre-translation on top of c, and if that means that literally every new linker/runtime feature required by c++ has to be somehow exposed in c then so be it

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
there might be a bunch of wasteful copying for other reasons, because this is C++, but basically everybody does at least that much NRVO. &table == &dongs

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Otto Skorzeny posted:

this is the only place where the "as-if" rule is violated, right?

copy-elision in general, yes. everything else weird is rooted in a no-undefined-behavior assumption

copy-elision would also be basically useless if you had to audit the copy constructor and destructor for side-effects and prove that the memory allocation/initialization patterns produced a totally equivalent object, because that analysis is basically impossible outside of trivial cases

copy-elision and NRVO are enabled at -O0 in every compiler i know of (unless you turn them off, lol, have fun testing code-generation paths that nobody else has ever triggered before)

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

tef posted:

see, if you were on a cray, this is an instruction :3:

the llvm teams here ask this question a lot, and pointing out that some ISAs provide it natively is considered an excellent response (but then they make you work through it anyway)

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

dragon enthusiast posted:

wouldn't that just be the same as polymorphism though

or does md also extend to primitives or something like that

here, have an effort post

normal oo dispatch is special-cased to the object argument (this/self); multiple dispatch applies to multiple arguments at once. what that ends up meaning depends on the language/library

you can easily do multiple dispatch by picking the best match on one argument, then another, and so on. this is a straightforward model, and it's fairly efficient to implement on top of normal oo dispatch, but it also doesn't have huge expressivity gains over just doing dynamic type checks / visitor pattern stuff

the more sophisticated thing to do is to pick the best match possible, considering all arguments simultaneously. this introduces some ambiguity problems, e.g. if foo(Animal,Dog) and foo(Dog,Animal) both exist, which your language model may or may not provide obvious ways to resolve or even detect, e.g. by saying that the first supremal overload wins. in practice you can usually handwave this as the programmer's problem. also, performing the actual dispatch gets a lot more complicated (and expensive), especially if there isn't a compilation stage that knows all possible overloads. but it's definitely more uniquely expressive

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
if the CLR made that guarantee then it would have to use green threads on any architecture except x86, because otherwise every heap load/store would have to do a read/write barrier respectively

ARM makes a really neat memory ordering guarantee about address dependence that enables a lot of lock-free algorithms to avoid barriers on the read side, but it is not at all sufficient to emulate x86-style guarantees about store reordering

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

FamDav posted:

so is it like they're taking the swift approach to elevating certain novel types to special syntax within the language? i dont like that

we've gone back and forth with swift about exactly how special Optional is. we really want covariance of optionals (T < U => T? < U?), and not having implicit injection into optionals creates huge usability problems (although adding it also introduces a few problems). essentially we do see optionals as structural types worthy of special language support along the same lines as tuples, which similarly have a lot of special behavior for subtyping, pattern-matching, etc. you could in principle model these things with more sophisticated user-defined conversions --- for example, you could support pattern-matching being able to implicitly reverse optionality by adding a notion of a reversible conversion --- but we've actually been moving in the opposite direction, towards eliminating user-defined conversions entirely

certainly we've considered letting arbitrary types opt into the 'if let' syntax via a special protocol, the same way we do a lot of other syntax. but the more we think about what that protocol would look like ("given a value, check whether it's true-ish; if so, extract a value and bind it to this variable; otherwise throw the whole thing away"), the less interesting it actually seems to generalize it. you could imagine using it with a weighted Either type for error handling, but weighted Either is a really lovely language design for error handling unless you're working in an Either monad (i.e. unless you implicitly propagate errors), in which case 'if let' is not normally going to working with the weighted Either type anyway

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

tef posted:

tbh the whole x! style arguments seems like a very nice hack, iirc.

thank you. i spent a lot of time working out how they'd work, and then a whole lot more time justifying that to everybody else, and then it went Above My Pay Grade for a while, and then finally the official blessing came back down from the heavens, and some muscles i didn't know i had got to unclench for the first time in three months

i did give them really awful syntax at start, though

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Vanadium posted:

There's a (seemingly fairly haskell-inspired) dude in the rust community who has almost but not quite proposed that Rust do checked exceptions where the whole thing is isomorphic to having your checked-exception-throwing function return what I think rjmccall just called weighter Either, it's kinda wild.

this looks neat, i'll take a closer look

by "weighted Either" i just mean a type that's structurally an Either type, except reserved/designed for value-or-error instead of reusing the normal Either type. i.e. the type gives semantic weight to the options. so one, it's a different type and you can't accidentally use a normal Either value as a monadic computation or vice-versa, and two, the constructor names can be something meaningful like Success/Failure instead of Right/Left

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
i devoted a minute or so of my wwdc talk this year to telling people not to go crazy with custom operators and the like

in my first draft, the slides for this section were basically "god dammit c++" and "god loving dammit haskell"

decided to stay classy, tho

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
if we had one, you would be able to overload it, but i would reserve the right to track you down and make you watch that wwdc talk until you felt bad and/or understood dave abrahams' memoization functor

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
basically the only swift operators you can't overload are:

  • binary = (assignment), which is justifiably special
  • prefix & (pass-by-reference), which i think is also justifiably special, but which i think it is possible to hook into on the receiver side
  • postfix ! (optional force), which we made builtin for reasons that no longer exist, and which will eventually become a library operator again
  • postfix ? (monadic optional evaluation), which is not just a normal unary operator; we could allow this to be hooked via a protocol, but that protocol would be quite complex and would rely on type-system features we don't have
  • ternary ? :, which we could easily make overloadable except it's such a weird special case in the grammar, which is basically the same reason it's not overloadable in c++

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
hey, i did research six years ago in a language that let you reflect arbitrary dependent information into the type system and hence express ordering bounds on data structures to statically enforce invariants

it's frustrating and a waste of time

welp, that's my story about grad school

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Otto Skorzeny posted:

are you doing moon power rankings this year btw?

moon power rankings?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
i have power rankings, they go

gently caress the goddamn seahawks
the glorious forty-niners
the broncos i guess
...
nc state
...
gently caress the motherfucking new york football giants forever

i don't need an algorithm for this tho

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

tef posted:

i recall it going something like this

i agree with this timeline, with the addition that cmu was teaching python in freshman physics (for majors) as early as 2000. there was a lot of interest in having a more approachable language for science and science education around then, and you could make python integrate with graphics libraries and so on pretty painlessly

the bioinformatics people got screwed because they wanted their more approachable language earlier and ended up with perl

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply