kaushiks
kaushiks on Hacker News
You can do this in Bash already (Ctrl x Ctrl e is bound to readline's edit-and-execute-command, which will open $EDITOR with the current command), but being able to do this everywhere is nice!
The only thing this page is missing is a marquee element :-)
The Thinkpad X1 Carbon or the T470p (which has a Quad i7 and supports upto 32GB of RAM).
This has nothing to do with memory. The x86_64 ABI returns values from functions in the RAX register.
You can also launch the TUI after-the-fact using the key sequence 'C-x o'. (It is no accident that it is the key sequence bound to other-window by default in Emacs).
Posted by
kaushiks on Wednesday July 13, 2016 @08:01PM
from the blogs.msdn.microsoft.com dept.
Posted by
kaushiks on Monday July 11, 2016 @11:43PM
from the preshing.com dept.
For the 16 byte (on x86_64) header (markOop, klass *).
I think this post misses the point. Having to enter the runtime in the first place is the problem (and making runtime code marginally faster is not the solution). Fast VMs for dynamically typed languages (Chakra, V8) design the object model and the runtime around being able to spend as much time in JITted code as possible - the "fast path".
You're missing the point. The original question (and hence my answer) isn't about whether or not it is a good idea to use finalizers. I'm merely pointing out that both in the case of RAII and a GC, only the lifetime of memory allocated is being managed. Not the resource contained in it. They use different mechanisms to let the developer deal with the resource. In the case of RAII the time at which clean up code is executed is deterministic (destructors), whereas with a GC, it is not (finalizers). Said mechanism, can be implemented, should a language choose to, regardless of whether or not the underlying memory allocation scheme is automatic (GC). (IDisposable is mostly a made up thing that C# has syntactic sugar for, that lets developers eagerly release resources (other than memory) when they're done with it. My point is, neither the language nor the runtime makes any effort to enforce its usage, like it does in the case of memory allocation.)
It might be, depending on exactly what you'd like to implement. There are two things at play here:
1. The memory that holds the resource.
2. The resource itself.
C++ RAII lets you control the lifetime of both. In a GCd language, the GC takes control over (1) but can't, over (2). Instead it gives you the ability to do 2 yourself (much like C++ does using custom destructors) using finalizers. Due to the way a GC works though, it is hard to be able to say when (or in the context of which thread) your finalizer would run. Now, the GC does what it does so it can guarantee that you are never able to hold a pointer to something that some other part of your application has deemed dead. While it is impossible to take over (1), you could imagine a world where (2), in a GCd environment is still up to the programmer, and is exposed (say) as a language destructor. In the presence of such a feature you run the risk of committing errors such as (say) closing a socket twice - but it isn't much different from say, code calling a poorly implemented Close (IDisposable) on an object twice.
While I agree that it'd be unusual for regular applications to have to resort to using SEGVs to implement features, low level systems code, especially VMs often do, for performance reasons. The Hotspot JVM for instance uses SEGVs to force a thread into a safepoint. The JIT inserts a read instruction, among other places, at backward branches, which tries to read from a page in memory called the polling page. Said page is mapped during normal operation of the application. When the VM needs to bring threads to a "safe point", say to perform a GC, it does so by unmapping the polling page. This causes each of the active threads to fault on the read and enter the SEGV handler, which notices that the faulting address falls within the polling page and executes appropriate "safe point" actions. Libc implementations use a similar technique to commit pages for a thread's stack lazily.
LGDT is an instruction that Loads the Global Descriptor Table [1].
The CPU doesn't know about the persistence of local state in that it doesn't know (in this case), the significance of anything that is being pushed onto / restored from a frame around a call. It knows that a "PUSH R9" writes the value of R9 onto the region in the stack being currently pointed to by the stack pointer (RSP). It however doesn't know that this is being done because, the current frame has a live value in R9, which, per the ABI, the function being called is allowed to trash, as it is considered a volatile, callee saved register. Like I'd said earlier, these are just agreed upon conventions that might even change across compilers.
I'd used the term "naked" the way the VC++ compiler uses it. A "naked" function is one without a prolog or an epilog [2].
[1] https://pdos.csail.mit.edu/6.828/2008/readings/i386/LGDT.htm
[2] https://msdn.microsoft.com/en-us/library/21d5kd3a.aspx
It generally doesn't matter how the machine code came to be. It is theoretically possible to write an operating system for (say) x86 in (say) Javascript. The reason people generally pick a "systems" language and drop down to assembly when necessary is due to two broad reasons:
1. As you'd pointed out, the language in question might not let you generate certain instructions. For instance how do you express LGDT in C? You can't. You'd instead write it in assembly (or inline assembly) and expose it to the C world as a function (or in a compiler that supports it, an intrinsic) that it can call.
2. A CPU's understanding of state is defined around the notion of registers and memory. A programming language however exposes a higher level abstraction. For instance, a function call in C is an abstraction that defines both transfer of control (which the CPU knows about) and persistence of local state (saving and restoring registers, stack pointer etc., which the CPU knows nothing about). This is called the ABI and is merely a previously agreed upon convention. Higher level languages (say Java) are able to provide richer abstractions than merely an ABI as their "agreed upon conventions" are defined at a much higher level than in terms of a CPU (registers and memory). Java, for instance even defines a virtual architecture in terms of which facilities offered in the language are defined. User code written in one of these higher level languages depends on these facilities being available to them at any time. This is what makes it unsuitable for writing certain sections of OS code. For instance, the CPU expects the OS to save and restore register state around an interrupt handler. If said handler was written in C (as a function) though, it'd expect its first six arguments in certain registers etc. - conventions, the CPU knows nothing about. You can think of the CPU as exposing its own, simple ABI which can only be implemented by writing certain sections of code in assembly (This is not entirely true though, as one might be able to mimic something like this in certain compilers, especially C compilers, that let the programmer write "naked" function bodies and custom prolog / epilog code). This is also why most parts of the OS, that don't directly interact with the CPU, can and are written in a higher level language. For e.g. The Singularity OS by MSR was written in C# and assembly.
C++ exception handling is implemented using SEH (so is CLR's IIRC, and Chakra's). SEH is implemented by the OS and is available to non-C++ code too (including C).
While RtlInstallFunctionTable callback was designed specifically for JIT compilers, RtlAddFunctionTable may also be used. The trick is to give every function its own function table. I wrote Chakra's P/XData handler and was surprised to find that they still haven't switched to function table callbacks [1], like the CLR has.
[1] https://github.com/Microsoft/ChakraCore/blob/7587147fac16654...
GNU/kWindows doesn't make any sense to begin with. Modern Windows OS is the NT kernel with the Windows user land. A more appropriate name would be GNU/NT.
Between more RAM and a bigger hard disk I'd always pick more RAM. On my development machine I have a very minimal setup (i3, no desktop environment, Emacs, compiler, debugger etc.) and not more than a couple of big repositories checked out (Linux, Hotspot). I can see why this might not work for other kinds of development setups though.
Lack of a 16GB RAM option on a "developer edition" machine is very disappointing. Looks like a Chromebook LS + Crouton is the best Linux development environment one could aspire for right now.
Much before I knew him from his FOSS work, I used to follow his column on a computer magazine called Computers@Home. Sad to learn he is no more.
Posted by
kaushiks on Monday October 01, 2012 @06:20AM
from the wadler.blogspot.com dept.
What does this example have to do with language design? Eval, for instance, introducing lexical bindings is bad language design. This is mereley an API with a poor contract.
For the interested reader - Linus' book "Just for fun" has a pretty detailed account of his meeting with Steve Jobs.