Software Development

Correcting The Future

Leaders and Conformists

Now that the reddit fanfare is over, I can better explain what I was talking about. I find it strange that saying system level languages are best is so controversial. You actually get demodded for this kind of thought. Though it was nowhere as bad as I thought. I think it was both because of confusion and that there are still a lot of system level programmers out there.

First off, when I say creating a new framework or doing a rewrite is best in a system level language, I'm not saying you can't use other languages. I'm also not saying that the entire rewrite be done in a system level language. If you want to port software, go ahead and use whatever you like. If a particular language is adequate for your needs, go ahead and use that. This is NOT what I'm talking about.

What I'm saying is that no language can be a perfect fit for what you are doing. Not at design time and not at runtime. Here's the punch line. System level languages are the only languages that do not force any pre-existing decisions upon you at runtime. So if you truly want to break free of other people's decisions and have something that truly fits your particular needs, this is your best shot at doing that... with system level languages.

And in case some haven't noticed, this is EXACTLY the strategy used with VM's and interpreters. Ironic? No, it's common sense. If it's good enough for them, why not you?

It's not about what you like or if a particular platform is good enough. It's about creating one that's exactly right for your needs where no one else can possibly force you to use their design strategies. If you use Lisp, you must formulate your code, even at runtime, as Lisp. So that's out. Notice the difference. If Lisp happens to exactly fit your needs, great. That's not what this is about. You're adapting your problem set to Lisp. Realistically, you'd want to adapt to your problem set instead. If you don't see the difference. Think about it some more.

With system level languages, it's the only time you are really free from other people's decisions at runtime. Yes, you still use the OS and other tools. But the core is created by you and you chose what parts to include in your framework. You made other things adapt to you, not the other way around. In contrast, when you write code with interpreters and VM's, you adapt to that environment. You extend it. It uses your code when it should be the other way around.

At design time, you are of course adapting to the way the system language works. But not at runtime. At runtime, anything goes. No trace of the language will remain at runtime unless you choose to have it so.

Why is this important if you can just use Java or Lisp to solve your problems? It depends if you're a conformist or a leader. If you're a conformist, then you have no problem adapting yourself to other's way of doing things. You're extending what's there. Most code is written like this. Even leaders must do this. When you write any kind of web code, you're extending the web. When you're writing plugins, you're extending that particular app. When you write mods for a game, you're extending the game. As I said, most code is like this. What unfortunately happened is that it's thought to be ok to be a conformist 100% of the time and if you want to be a leader, it's bad programming practice. I say that's completely wrong. Not only wrong, but dangerous.

A leader is one who decides and hopefully makes good and valid decisions. If you chose to use a VM, you may well consider this a decision. But it's more like inverted delegation where you delegate your services to this external entity. Think of it this way. Say you need a distribution system for packages in the real world. So you don't create it yourself. Instead, you call up a shipping company and let them do it. Ok, that's fine in the real world because the shipping company is not part of your immediate infrastructure. With programming, if you use a VM, you're including the entire shipping company within your application and you then assist and do things according to what this shipping company says. You're no longer the leader. Instead, you have to work around this colossal entity that has intruded your workplace.

If you're only interested in creating small apps and you're ok with using other people's decisions and are comfortable in them, again this is fine. Just realise it won't be the best possible solution. It may well be the most cost-effective though. This is why people do it. In the long run, it won't be. It can't. It's not a perfect fit and eventually, it won't be sustainable if it requires a lot of maintenance and updates and changes.

Some people also believe that a VM or interpreter is like a machine. Not so. It's software. I understand the point trying to be made, but it's purely imaginary. If you decide on something because of a POV, you've essentially been had. There's no such thing as "if you look at it this way". Either it is or it isn't. People have difficulty with this. Someone may think of a VM as a machine while I think of it as a tool that is butting in where I don't need it to. Someone may think of an interpreter as a machine while I think it's something stopping me from doing certain things.

Why is it wrong for me to decide anymore? Where has this frame of mind that we must all be conformists come from? I want to create. I want to build things. My way. The best way. For the task at hand.

Here's how I see the computing world. Everywhere I go on the web, I see everything being the same. Like this.



Sure, every house can be customised a little. There are different families in each so they'll decorate the place in their own unique way. But it's all the same. The road network should be accessible to everyone, but what's happened is that the road has expanded to the houses, to the web pages. More and more, others are making decisions for us and we don't even see it. Every piece of software should be an island totally under your control, but where the travel lanes are open. Today, your island has been taken over and you don't even know it. There is no sand under your feet. And the grass is artificial.

This move towards interpreters and VM's... Who do you think really has your best interest? Them or you? I say again that there is ZERO need for interpreters and VM's and that you can still have access to all the power found in them. Actually, you will have WAY more power. Here too, the C++ community had a real chance to make advances, but they really blew it with STL. It was the right direction. Just badly implemented. Not the code, the strategy and the looks of it. It almost makes Lisp look good.

People think the web is going to take over desktop apps. This is why it hasn't happened. Everything I've mentioned here. Your computer is your island. The Internet is the travel network. No matter how big the web gets, anyone can toss all that away, create their own way of doing things, and THEN link into the web and the Internet in any way that is best suited for their needs. NOT THE OTHER WAY AROUND! With Web 2.0, take a close look at who will get the control. Will it run on your server or theirs? Will you be able to use it locally where you can make all the decisions or will you have to send it your data? Right now, who has your e-mail? Who hosts your pictures? Who is hosting my blog? I've been looking into changing this for a while and most bloggers recommend having your own server for a reason. This same reason extends to code. No matter how big the web gets, it'll always be built for conformists.

Code Rewrite - YesProject V: Status Update

Comments

Unregistered user Thursday, September 27, 2007 4:59:39 AM

Anonymous writes: What is it that you are doing that you need to rely on the hardware so much? You say that you gain freedom using a systems-level language, but what is it that you are gaining from a concrete, practical perspective? Examples? Where does FFI fit in? I agree with you on the web stuff: I have no idea why people are so excited about scattering their personal data across all these throw away web apps. Think how easy it would be to create a "Web 2.0 Lifestyle App", get it popularized by posting a link to Reddit, Hacker News, Digg, etc, then just farm passwords or other personal data. Cheers for following your own lead.

Unregistered user Thursday, September 27, 2007 5:29:38 AM

mind writes: while i agree with most of what you say, especially the last paragraph, i disagree about VMs VMs define a common object format which lets different languages clearly communicate without glue. furthermore, a VM allows you to execute untrusted code, and be able to easily export parts of your program that can be accessed by the untrusted code. furthermore, this code has a portable environment on each host. getting that kind of functionality without a general purpose VM would take a lot of code, and by definition, extension code would be written in a different environment than your application code, and since it's a custom environment, you'd be lacking tools (/libraries). or maybe i'm trying to convince myself (i'm having trouble deciding between something jvm based and giving up and using D and worrying about untrusted code later. i really want a vm, but the java platform is lacking decent languages, and i don't want to tie myself to the cinder block known as .net. scala, while having lots of nifty features, still lacks many. *shrug*)

Vorlath Thursday, September 27, 2007 6:37:29 AM

The tools issue is real. I'll grant you that. That's a very serious concern. This is why I said C++ really missed the boat there. However, C++ is something from the early 80's and looking at what Bjarne has been saying, you could tell back then this was going to be a problem. He refuses to even consider properties. And poor man's closures are a nightmare to simulate. No way even closures that remember their object will be implemented.

To the first commentor, it's not that I need to rely on hardware. It's more about control. There are two different kinds of tools. Ones that have control and those that don't. There can only be ONE "tool" that has control. Everything else is a delegate. BTW, this is why applications and libraries are different. This is why you cannot use an application as a library. Libraries are written as delegates. Applications are written to control the action.

With me so far? So if you want to write something where you need that control, but you're on a platform that retains this control... where you can only write delegate code (as it is with VM's and interpreters), then you're out of luck. It means that your code that runs on interpreters and VM's sit on another layer above from native code and it's almost impossible to cross that boundary either upwards or downwards. It causes all sorts of incompatibilities, even within itself.

You wanted an example. Here's one. Write me a new VM or custom code of any kind, but it must handle concurrency in some controllable manner. Do you really think that this world of PC's everywhere is going to last forever? Multi-cores are coming out. The VM's you use today are wholly inadequate for this purpose. There are no tools to properly handle concurrency today (please don't mention Erlang). At the very least, we should be able to build our own solutions to solve our problems. Project V (if you've heard of my project) is impossible to implement on any VM or interpreter without changing that VM or interpreter or having access to the OS. In fact, the OS gets in my way in some cases.

Not everyone is writing a platform? Actually, you should be. Every large project should be a unique platform designed specifically to solve the task at hand. I actually promote having its own high level language specifically tailored for your platform. At this point, if you want to add other VM's and interpreters, go for it. Or even use the VM as the high level language, go for it. Add some bindings to internal objects and functionality and off you go. I'm not sure how you would add bindings, but if VM's were smart, they'd allow it. So I'd go for that rather than FFI. But calling external functions is fine. Co-existance is good too.

Also, VM's cannot do portability. What you mention is emulation. While some don't make a difference, I hope you understand my meaning. What can actually happen is that software should be able to automatically use the best features of whatever platform they are on, even VM's. So VM's are actually redundant if software can adapt. Explaining how to do this would take some time and is discussed throughout in my blog. Unfortunately, I could never get into too many advanced topics without being called a lunatic (while a handful of others around the world are actively working on their own similar projects).

Vorlath Thursday, September 27, 2007 6:43:15 AM

This got reddit'd again, didn't it?

Unregistered user Friday, September 28, 2007 3:33:47 AM

Sean Conner writes: It's turtles all the way down. Sure, I can spit the following C code: while (*d++ = *s++) ; through a compiler and get: again: move.b (a0)+,(a1)+ bne again which the CPU can run. But what, exactly, is the CPU doing? It's interpreting a byte code. The 68k (which is what the example is) had microcoded instructions, which meant that the "machine code" above is broken down (inside the CPU) into even simpler instructions. Pentiums nowadays convert the x86 instruction stream into a simpler, more RISC-like instructions for internal consumption which you don't even get access to. So in a way, the x86 assembly code you write is a type of VM. And running in user-mode, you are restricted in what you can do. Such technology is old—IBM has been using VMs since the 60s (I think they were the first to really implement and use VM technology in their mainstream offerings). Used to using an IBM 360? You might not even be programming an IBM 360. It might something completely different. Same with their AS400 line where the underlying "hardware" might change radically between models, yet you can still run your "compiled code". You might also want to read up on the PERQ. It's an interesting workstation from the early 80s.

Vorlath Friday, September 28, 2007 7:19:45 AM

Yeah, but that generated code is yours. You've decided. That's exactly my point. Yes, I can't go lower into hardware because it's well, hardware. But that's besides the point. With hardware, it says here's what I can do, now go. I hand over control to you. With VM's, that's not what happens. It says "I'll take control thank you." And your code is not code, but data.

Many have tried to say that VM's list a bunch of opcodes just like the machine does. But that's the point. I can bypass the VM. There's all this power there. And you can do everything a VM can without needing a VM. I don't understand why one would want to limit what they can do in this fashion.

Here's an analogy. Say there are two shopkeepers side by side. Call them A and B. A sells 10 items and B sells 5 different items that he actually makes from parts bought from A. While B does provide some nice items, there's no reason to limit yourself if there are other items available. Not only that, but B will not let you handle the items directly. No, he'll take your requests and then he'll have someone else do it. If you only shop at B, you can do almost anything you want, right? You miss out on a few items, but they're not critical. You can recreate them in a roundabout way with the 5 items that B provides. This is the argument most people have.

Here's the real deal. At some point, a customer will come along and say, "I need to build my own shop. I want to provide some different services." He cannot shop at B. He must go to A. (Just like I have to do with Project V) And frankly, there's no reason to ever go at B. Here's why. Shop C, once setup, will offer the exact same items as B, but will not restrict you in any way. You'll be able to mix and match items from both A and C. And even B. But if you start off at B, you're limited to what B offers when there's no reason at all.

Now let me go back to what C said: "I want to provide some different services." That's the critical point. Your framework should provide its own set of services.

Another point is that if you think hardware is another kind of VM, then that's a self-defeating argument. If you have opcodes X provided by hardware and opcodes Y provided by software, everything Y provides is available through X. So why would you limit yourself? Y is just a competing and inferior set of opcodes.

Unregistered user Monday, October 1, 2007 9:35:50 PM

Sean Conner writes: How can you tell if the opcodes you are using are actually implemented in hardware? An extreme case, I can run an Amiga emulator on my PC. On that Amiga emulator, I'm running a program that emulates an Apple ][e so I can play a favorite game of mine, Castle Wolfenstein. As far as the program Castle Wolfenstein goes, it's running on an Apple ][e based off the 6502, but in reality the hardware (opcodes if you will) are purely software based, running on a program written in 68000. But yet, that program isn't running on the hardware opcodes of a 68000 but a software emulation of said, running on the Intel x86 platform. So I have opcodes X provided in hardware, and opcodes Y provided in software. And yes, everything I can do in Y I can do in X. But why use Y? Because I can change Y easier than I can X. And if you think the opcodes in the x86 are better than what you get on the Java VM, then you've probably not seen the VAX assembly, which is way better than what you get on either (although nowadays, I'll have to use a software version of the VAX if I want to play around with it). One other point. Serial communication. The Tandy Color Computer has two one-bit ports used to implement serial communications (one one-bit input port, and one one-bit output port). To do so, I need to write the code to hold the output line at a certain level for a certain amount of time (the baud rate) for a certain number of repetitions (the number of bits I want to transfer). Sure, it's a pain, but I can implement any number of protocols I want, from say, a standard 9600-8n1 to a 10,000 baud 2bit protocol. The standard PC though, comes with a hardware based UART (nowadays, based on the 16550 if I remember correctly). Easier to code, and doesn't burden the CPU with timing, framing and other messiness of serial communications. But I'm limited to a set number of baud rates, with protocols going from 5 bits to 8 bits at a time. That's it. Useless for my 10000 baud 2bit protocol. Now, which one is better? The software serial port on the Color Computer, or the hardware serial port on the PC? The software one has more adaptable than the hardware one. On the other hand, the hardware one is easier on the CPU side of things. And not to put too fine a point on it, the code generated by the C compiler isn't *my* code. It's the compiler's code, a translation if you will. The assembly output just I presented just happens to come from a particularly skillful translator. I've seen compiler output of that same fragment looking like: again: move.l s,a0 move.b (a0),d0 addq.l #1,a0 move.l a0,s move.l d,a0 move.b d0,(a0) addq.l #1,a0 move.l a0,d cmpq.l #0,d0 bne.s again And yes, in those instances, I reach for the assembler, because that's certainly not the code *I* envisioned.

Vorlath Monday, October 1, 2007 10:25:01 PM

If you can't tell you're on hardware, then it means you are on hardware or have no choice in the matter. Your examples all talk about emulators, so I don't see the point. This actually goes against VM's because if you can just use an emulator, what's a VM give you?

About the rest, those are tools and have nothing to do with the point I was trying to make. You're free to use either software or hardware and that's exactly my point.

Unregistered user Tuesday, October 2, 2007 2:28:36 AM

Sean Conner writes: Trying to post a reply here ...

Sean Connerspc476 Tuesday, October 2, 2007 2:48:39 AM

There we go, got an account here to reply without problems.

Anyway.

So, what exactly, is the difference between a VM and an emulator? Both provide a virtual machine in software. And to get back to the Java VM for a second, it has been implemented in hardware.

I don't make a distinction between a VM and an emulator, because for the most part, they're the same thing. And what I'm saying is, even if you think you're writing to the metal, you may not be. You also state that using a VM gets in the way, that all manner of decisions have already been made for you, and you are forced to work within the limitations (or framework) of that particular VM.

But we're already IN a VM. The x86 opcodes? Just a set of popular opcodes sitting in front of several different RISC processors (Intel, AMD, Transmeta, etc.) which sticks you with 8 general purpose registers and a segmentation scheme that no one I know even bothers to use. And a two level paging scheme (whereas the Motorola uses a variable two-to-five level scheme).

Now please, don't get me wrong---I do happen to agree with what you are saying with respect to control (I run my own webserver, but it's a virtual machine don't you know. But that's okay, because if the hardware takes a dump, I can just move the latest backup to another virtual machine and be back up and running in minutes).

Vorlath Tuesday, October 2, 2007 4:55:56 AM

That a VM is like an emulator is my argument. So I'm not sure what you're getting at. edit: Oh, there's a difference between an emulator that emulates hardware vs. creating a completely new set of instructions though... just to be clear.

About seeing x86 as a VM, there's just one problem with that argument. If EVERYONE was using the same VM, I'd agree with you that VM's don't matter because there's nothing you can do about it. So that should answer your question about anything put into hardware. But as far as things like Java or .NET, by YOUR argument, this is a VM on top of a VM. What's the point of two VM's one on top of the other? It makes no sense. Pick one and be done with it. And the one we MUST use is the hardware one (again, by your definition). Then build your software tools around that. And we have these tools. There's nothing a software VM can provide that HAS to be in a VM. It's software. So there's no reason you can't remain at the system level. Any feature available at the VM level can be had at the system level.

And I'm kinda glad you like to retain control and that's my main point with VM's. They take control away when you consider that there's another layer available. If you could call and use things in a VM from an external source, I'm not that resistant to the idea. This is only a personal extreme dislike of mine because there should be no reason to go into a VM in the first place.

Sean Connerspc476 Tuesday, October 2, 2007 10:08:43 PM

Would you care to write a program, it can be a simple one, that opens up a window and presents a few menu options to select from, for Windows (I've done some programming under Windows), the Amgia (a lot of programming for this platform---quite a fun platform actually) and the Mac. A window is a window right? A rectagular region (although Windows and the Mac allow non-rectagular windows, whereas the Amiga doesn't---or at least the version of AmigaOS I last worked on didn't) with a title bar with a few controls (minimize, maximize, close) and a menu bar.

Only the menu bar on Windows appear below the title bar of the window it's attached to. On the Mac, the menu bar for the application appears at the top of the screen, while on the Amiga it doesn't appear at all until the right-mouse button is select on the mouse, at which point the menu for the application appears at the top of the screen. How the menu is declared differs from system to system as well. Under Windows, you create the menu using a resource editor, and that information is packed into the executable as part of the build process. On the Amiga, you have to write code to declare the menu structure and call a few routines to get it installed. I have no idea how it's done on the Mac (Classic or OS-X). On the Amiga, you can use any font for the menu bar and menus. On Windows, I think you're stuck with a predefined font for the menu bar, but the menus themselves can use any font, and I suspect the same is true for the Mac. I know that on the Amiga, a menu item doesn't have to be text---it can be an image.

Also, the event loops work differently. On Windows, you get I think four integers passed as an "event"---one describing the event (say, WM_MENUSELECTED) and up to three "parameters" of various meanings, depending upon the event. On the Amiga, you create a message port to which the GUI sends actual messages (structures) to be handled. Again, I don't know how the Mac does it, but it's either a message based event loop, or registering a series of callbacks.

So, write me a program that will compile and run on all three systems.

You'll end up with one of three solutions: 1) you have three separate code bases that are maintained separately but in parallel. 2) you have a common codebase that interfaces with the native components using some abstract concept of "windows" and "menus" that implements a common sub-set among all three (say, QT from TrollTech), which to me, seems to be a mapping of one set of "opcodes" (windows, menu items, events) to another set of "opcodes" to extract common functionality between different systems. Or 3) scrap all that go with a pre-defined VM that does GUI, like Java.

And if you say the program can just "adapt" to the system it's on, well ... we're not quite there yet, are we?

How about a real-world example of a program on a VM (the Java VM) on top of a VM (the x86 architecture). kLoOge (http://www.kloogeinc.com/) is a program written in Java to help manage role playing games (the game master runs the server, the players the client; it provides a chat feature, plus a mapping feature and handles combat and character sheets). The company that makes kLoOge is literally a one-man operation and he makes his living by writing and supporting the program.

Now he could have targetted a particular hardware platform, say Windows. That would give him a large enough audience, but in the market he's targetting (gamers) there is still a significant portion that use other platforms like the Mac or Linux. And kLoOge, being written to the Java VM, will run on any platform that runs the Java VM, which includes multiple levels of Windows (95, 98, ME, 2k, 2003, XP and Vista) as well as various Unix variants (like Linux, Solaris, AIX, etc). He just increased his market share quite a bit with that move (and I personally have used the program under Windows 2k, Windows XP, Windows Vista, Linux and Mac OS-X). kLoOge only has to provide a single distribution of the program, not multiple variants.

Sean Connerspc476 Tuesday, October 2, 2007 10:13:36 PM

One futher comment---not only am I trying to understand what you are attempting, but I'm also arguing with myself. I don't care for interpreted languages, yet it dawned on me (relatively recently actually) that there's nothing really special about compiled languages since the resulting object code is "interpreted" by the CPU, hence my statement of it being "turtles all the way down." Why do I prefer compiled languages over interpreted languages? Am I guilty of "premature optimization"? Do I really gain anything?

I have the same questions about dynamically typed languages (I prefer statically typed languages personally).

Vorlath Tuesday, October 2, 2007 10:55:15 PM

Actually, anything that does something within the JVM is dependent on that VM. So it's not just about distributing the software, but the JVM as well. Also, the VM in question is built in such a way that make you THINK you must use the VM. There's no such reason to do so, except that the people who designed the VM want a lock in. Some people really disliked the lockin that MS did with native apps, but the VM does the exact same thing. You'd have to be really naive not to see it. In an ironic twist, they suggest that a VM is portable when native code can be MORE portable that any VM can ever dream of being. We haven't seen it? I agree with you. But this is no reason to say that VM's can do X and Y when native code can do the same. Because the VM is itself native code.

If you want to talk about advantages of compiled code, I'm more in the camp of why use anything else when it does the job anything else can. As you correctly point out, there is a lack of tools. This has produced an incorrect view in the mainstream that Java can run on several platforms (even with its defiencies in certain areas). At least it's far better than native code, right? This is what everyone thinks. But it's a lie. The lack of tools does not mean that it's not doable.

The reason that VM's popped up is because it can lock you in. With native code, you can do anything you please, so it's even easier to lock people in, but it's not necessary. In fact, there's no reason you can't have a toolkit that allows you to use any platform. Instead, what do you have? A VM that takes control and decides what features can be used. I say screw that.

I'm building Project V and it will adapt to any platform and will be native code. I'll have a runtime for those that want it (because it's hard to change popular beliefs as seen here), but by no means will it be able to do anything that native code cannot. Also, even if there is a runtime engine, you can use it as an external component. You decide if you want to use it or not and can replace it anytime you wish. Now replace the VM and part of your Java software. Not so easy, is it? If you decide to use TWO VM's, who's in control? Where do you place your "main" software? Who is the controller and who is the subordinate? That's the question I'm interested in.

Note too that if you're writing small programs or there are programs that exist in these VM's that can do what you need for cheap, hey, go for it. But that's a matter of what exists. Not about "best" way for your software. I believe I specified quite clearly that I was not talking about the money aspect. At least I know I did in the last article. So it's important to ask yourself from what viewpoint you are approaching the issue.

Sean Connerspc476 Wednesday, October 3, 2007 8:12:21 AM

Anything you do on the "System" is dependent on that "System." It doesn't matter of the "System" is the Java VM, or Windows, or Unix. Even a program as simple as:

int main(void)
{
printf("hello world\n");
return(0);
}

is dependent upon the Standard C Library existing. I write a Windows program, I'm just as locked into needing Windows as needing the Java JVM for any software I write in Java. You yourself just said "Some people really disliked the lockin that MS did with native apps, but the VM does the exact same thing." So if you can get lockin with native apps, why can't you *not* get lockin with a VM? There are very few programs available that don't require an operating system to run under---it's a very small subset in fact.

If I write a program targeted for the Java JVM, I need to do things the Java way. If I write a program targeted for Windows, then I need to do things the Windows way. Sure, I can write the Windows program in x86 Assembly just as easily as in C (well, maybe not *quite* as easily) but that doesn't mean I can take the resulting program and run it on my Linux system---no, for that, I need to install Windows (which is much the same as requiring I install the Java JVM to run Java programs).

Also, how are using two VMs any different than using a multiprocessor box? You might argue that the CPUs in a multiprocessor box are the same, but that doesn't have to be the case (any number of products over the year, from cards with Z80s running CP/M being plugged into Apple IIs using a 6502, to cards with 80286s running MS-DOS being plugged into Amigas using the 68000). Or if you feel better about it, a distributed program running across a heterogeneous network. Who's the master and who's the slave? Why not peer-to-peer? Or both masters and slaves, depending upon what's being done?

As I've said before, VMs are nothing new. Did you know that the Apple II supported two different VMs? Two different VMs on a 6502, and if you've ever programmed a 6502 you'll know just how crappy a CPU that is. The first was SWEET16, written by Steve Wozniac (you know, the creator of the Apple I and II) to make 16-bit arithmetic easier to program (the 6502 only works on 8-bit quantities, has no multiply nor divide instruction, nor does it have an unconditional JMP instruction---like I said, it's a horrible CPU to use for general purposes). You could also mix regular 6502 opcodes and SWEET16 opcodes in the same program. The Apple II also supported UCSD Pascal, which was Java for the 80s, only Pascal, and implemented on 8-bit CPUs (or I should say, UCSD Pascal was implemented for the Apple II, along with several other 8-bit computers at the time).

Just because the current crop of VMs are bad doesn't mean that VMs are bad in general. Heck, Infocom made millions off a VM---just lookup the Z-machine.

Sean Connerspc476 Wednesday, October 3, 2007 8:40:27 AM

But see, C has *already* forced some design decisions for me. Limited gotos (only within a function, and yes, there is setjmp() and longjmp() but those are defined within the Standard C library and have some very strict restrictions on what can and can't be done using those two functions). Multibyte arithmetic, trivial on a lot of CPUs, becomes very cumbersome in C (since one does not have access to the Carry Flag). Floating point operations are internally defined as being done on doubles. I can't nest function definitions (at least, not with ANSI C---some compilers might support extensions though). Alignment of structures are left up to the compiler, as well as the layout of local variables on the stack (that is, if the C compiler uses a stack and doesn't allocate activation records off a heap). Even the size of integers can change from compiler to compiler on the same system! (A stock 68000 is 32-bit internally, but has a 16-bit external bus. A C compiler from vendor A can therefore rationally pick a 16-bit int size, while a C compiler from vendor B can rationally pick a 32-bit int size).

But yes, you are free to ignore the Standard C library entirely if you need to.

Vorlath Thursday, October 4, 2007 9:31:16 PM

I've programmed the 6510 on the C64 and its disk drive. Kinda weird that the disk drive was its own computer. I actually quite like the 6510.

Your C example above is not dependant on anything unless you choose to be dependant on it. That's the point most people miss. There's an open door if you need it. Most people are content saying they'll never need that door. I dunno. I've never written a piece of code that didn't need it. You know why? The only way I wouldn't need it is if I was writting something that's already been done. And that bores me. If others do it, fine. Maybe I just come from a different walk of life.

The analogy with dual core or multiprocessing does not fit. If it did, then it's be ok to ask "what's the client and what's the server with your main() routine and the C standard library?" Everyone knows the answer. And that's why the analogy falls apart. With multi-core, you don't know who's in charge. This is exactly what I was saying with two or more VM's. If you use two of them, who's the boss? You don't know. It's arbitrary. And it need not be because it isn't multiprocessing. It's on the same damn processor. Heck, it's part of the same software.

About your second comment, everything in C is configurable. True that things like alignment aren't part of the language unless the compiler has extensions, but all compilers support pragmas or some method of doing this. I agree that this is ugly though. But at least you have the choice. VM's come nowhere near anything you talk about and flags are going off in my head.

Regardless, I still stand by my main point that you could have Java, C#, perl, php, Ruby and whatever else in native code. The invention of the VM can only be attributed to laziness or lack of imagination. There is nothing it can provide that native code cannot. Sometimes it's nice being a backseat driver. But more often than not, I like to take the wheel.

Vorlath Thursday, October 4, 2007 9:40:41 PM

I though I should add this little gem. C and other system level languages (Pascal for example) have been used by other software all over the place in every conceivable manner by VM's, OS's, languages and everything else. When's the last time you heard a VM being used this way? NEVER! I'm trying to explain exactly why this is so.

"I saw some great code in Ruby and used it in my C++ software" - Mr. NeverGonnaHappen

Heck, substitute C++ with Perl, Java, VB... and substitute Ruby with Perl, Java, VB etc... making sure they are mutually exclusive. Yet doing this with system level code is common. The entire Unix OS is based on it.

Sean Connerspc476 Friday, October 5, 2007 12:35:44 AM

The C64 wasn't unique in having intelligent peripherals. Every IBM mainframe comes with peripherals that are otherwise computers in and of themselves. The Amiga had a sub-processor to program the video display (granted, the processor of the video display had only three instructions, but you could still write programs for it). SCSI devices were all intelligent.

And yes, it is right to ask about what's the server and what's the client in my C example: it's my code that's the client to the Standard C Library. No, really. Try the following (I used Linux):

#include <stdio.h>
int _start(void)
{
printf("hello world\n");
return(0);
}

% gcc -c tt.c
% ld -static -o tt tt.o -e _start -lc
% ./tt
hello world
Segmentation fault (core dumped)
%

Hmm ... why is that? (rhetorical question actually. The answer is---"_start", as provided by the system, initializes the Standard C Library and then calls main(). Here, we skip all the Standard C Library initialization, and there's nothing to return to. Yes, we can change the last line to read "_exit(0);" and in this case, the program won't dump core, but the Standard C Library is in an undefined state so anything more complex might not run properly)

But now I'm really confused by your statement "[w]ith multi-core, you don't know who's in charge," because you yourself are trying to write a system to take advantage of the coming wave of multicore machines, yet you are decrying multiple VMs because you don't know who's in charge. Let's see:

multiple-VMs---don't know who's in charge
multiple-cores---don't know who's in charge

yet you dislike VMs (and especially multiple VMs) because you don't know who's in charge. But you just stated that with multiple-cores you still don't know who's in charge, yet you seem to like (or accept) multicore machines.

Sean Connerspc476 Friday, October 5, 2007 12:49:27 AM

And I'll share this little gem---Unix doesn't go far enough in multilanguage linkage.

OS-9 (nothing to do with the Macintosh) is an operating system, designed in the early 80s that had a similar feature to Unix's #! line (for running scripts or interpreted languages) but not limited to just "programs". A "module" in OS-9 could be an entire program, a subroutine, data, device driver, kernel extension, or user defined. As part of the module definition, for said modules that contained code, was the language type, whether it was simple data, CPU object code, BASIC09 I-code (a type of VM), PASCAL P-code (another type of VM, based off the UCSD Pascal VM don't 'cha know) or COBOL I-code (yet a third type of VM). (Those are the ones listed in my documentation from the mid-80s---as time progressed, they may have added more)

So, I could take a cool BASIC09 subroutine I found, and maybe some cool Pascal routines I found somewhere else, and write some C code (which produced CPU object code) that used both subroutines written in different languages. I run my program, and the system would not only load and execute it, but load and start up the BASIC09 VM and the PASCAL VM. Dynamic linking at its finest.

And one more thing---embedding Ruby in C++. Perhaps not as elegant as doing this on OS-9 though ...

Vorlath Friday, October 5, 2007 3:26:02 AM

I owned both a C64 and Amiga (two of them A500 and A1200). I knew how to program them all inside and out. But I wasn't trying to make a point with them. I just said I liked the 6510.

About your C example, I have no idea what point you're trying to make. In both cases, your C program has control. The standard library doesn't do anything without your permission once your code gain that control. Not so in VM's. Besides, it's initialisation. There are plenty of different kinds of startup routines you can use. I'm using Borland C++ Builder and it has like 6 of them at least. You can write your own and still use whatever features you want. Again, I have no idea what your point is.

With the question of who's in charge in multicores and multiples VM's, I want to say that your argument doesn't hold water. With dual VM's, both will want to be in charge. They'll both eat up as much memory as they can and they'll both use whatever resources they can. With multicore, I can make them act in any way I want. I can use client/server. I can use a P2P style. I can do whatever. No so with VM's. The VM's have already decided for you. Memory, resources, execution, everything.

That Ruby example is cool though it looks like it hasn't been worked on since 2003. Note too what it says about the way Ruby wants to do things and the difficulty working around those design decisions. However, this is a cool tool for anyone wanting Ruby as part of their software to control and use their core services. Likewise, I've used a few C and C++ scripting versions of the language in a few of my projects for the high level language.

And I've been using a lot of C++ lately and there is almost no need to use pointers anymore. I use them occasionally because I know what I'm doing (memory and speed tweaks). But there is no risk of memory leaks or unsafe structures. While C++ leaves everything there for anyone to use, there's no reason that another language seen in VM's can't be implemented at the system level with zero loss of features. So I still don't get why VM's exist in the first place (other than proof of concept for the language).

Sean Connerspc476 Friday, October 5, 2007 4:54:46 AM

I don't know where you get the concept of VMs taking as much resources as possible. Perhaps by default, but as far as Java goes on Linux, you can set the initial Java heap size, the maximum Java heap size, the Java thread stack size, mixed mode ("just in time" compilation I'm guessing) or purely interpretive mode. So it looks to me like I can control the Java VM.

But let's say I do use C. Normally, I still dont' have control since I'm running under an operating system. Same goes for Java. And how about that program that opens up a simple window with a few menu options under Windows, AmigaOS and the Mac? That's one reason why people write in Java. They have to support a program under vastly different systems. Sure, writing in Java gives up low level control, but there are gains as well—the ability to write a single code base and have it run anywhere the VM is supported (and to be truthful, I haven't had to install the Java VM on Windows, Linux or the Mac—it's already pre-installed). I compile once. I don't have to compile for Windows (and if it's written carefully enough, one executable can run under all the flavors of Windows), Linux RedHat, Linux Debian, Linux Suse and Linux Ubuntu (because each has different locations and/or different versions of various libraries I might use) or Mac OS-X 10.2, 10.3 or 10.4 (although, if I'm careful enough, I might be able to again, get a single executable to run on all these). Okay, at worse, I might have to supply a version for Java 1.4 and 1.5, but that's easier to arrange than a Windows, Linux and Mac version, assuming I can even have a single codebase.




Vorlath Saturday, October 6, 2007 5:56:53 PM

Maybe you can tweak Java settings, but tell me... how many people actually know how to do this? You're asking regular users to do this? C'mon!

The OS doesn't run the opcode. The hardware does. So again, your analogy is flawed. The OS is more of a tool than a VM. Sure, it can ask the hardware to do stuff your software can't. But that's because we need an arbitrator. Multitasking and all that. Before multitasking, an application took over the system even though there was an OS. At least, it was common practice. VM's on the other hand hog everything in sight and don't play nice.

Afterwards, you're talking about the availability of something. That's the trap I keep talking about. How do you think it got to that point? Marketing. Also, your attempt to put OS and VM's in the same category is self-defeating. If a VM is an OS, then why one more? Why not just use what's there already? Instead of everyone using a VM, why doesn't everyone use the same OS? It's a VM too, no? That's what you're saying? See, that argument makes no sense. Java is something you have to conform to. OS's let you use their tools. There's a BIG difference. There are cross-platform GUI tools. Also, it's not that big a deal to split out the functionality from the GUI. In case you haven't noticed, no one uses GUI's from Java. If they do, they make sure it looks like a native app. And there's no reason this can't be done in native code and there are actually toolkits that let you do just that. Go figure.

Sean Connerspc476 Saturday, October 6, 2007 11:52:26 PM

And how many regular users know how tweak their operating system? C'mon!

Sean Connerspc476 Saturday, October 6, 2007 11:55:46 PM

You also seem to be missing my argument, which is that Java allows a programmer to compile their program once, and have it run on any system that supports Java. The same can't be said for a native program, regardless of cross-platform GUI tools. Unless you are saying that once I compile a native executable under a Mac it will automagically work (without recompiling) under Windows and Linux.

Vorlath Sunday, October 7, 2007 4:38:14 AM

Well? Tell me. How many regular users know how to tweak their OS? Most can't even set up their email. Unthinkable to programmers, but that's the norm.

"You also seem to be missing my argument, which is that Java allows a programmer to compile their program once, and have it run on any system that supports Java."

This is self-defeating. Sorry for being blunt. Here is my reply:

"You also seem to be missing my argument, which is that Windows allows a programmer to compile their program once, and have it run on any system that supports Windows."

WOW! Isn't that amazing? It has the same powers as Java.

"Unless you are saying that once I compile a native executable under a Mac it will automagically work (without recompiling) under Windows and Linux."

Again, same faulty logic.

"Unless you are saying that once I compile a Java executable under the JVM it will automagically work (without recompiling) under a machine that has no JVM."

Your argument is about AVAILABILITY. My argument is about functionality. There is NOTHING about VM's that you need. NOTHING!

Sean Connerspc476 Monday, October 8, 2007 7:14:37 AM

Well, now that we have that cleared up, I have one more comment about system languages not imposing any design decisions on you.

I found one that does.

C. On the MIPS platform.

The MIPS is a RISC based architecture. It has 32 32-bit general purpose registers, and 16 general purpose floating point registers (there's also a program counter and two other registers that deal with integer multiplication and division, but aren't programmer accessible). The only restriction the hardware imposes on register usage is that r0 is always 0 (makes sense in context of the CPU instruction set) and r31 contains the return address when you make a subroutine call (otherwise, you can use it as you use any other register). That's it for hardware restrictions.

The assembler claims r1 for its own use, and is not available for programmer use. Also, registers r26 and r27 are set aside for the kernel (Unix, Windows NT, etc) to use, and again, are not for use by the programmer (yet more restrictions!)

The C compiler imposes further restrictions on register usage. r2 and r3 are used to return values (and languages like Pascal or Ada, which allow the use of nested functions, use r3 to handle this). r4 through r7 are used to pass in up to four parameters. There are eight registers (r16 .. r23 and r30) that are saved across subroutine calls. r28 points to global variables, r29 is used as a stack pointer, leaving nine registers (r8 .. r15, r24, r25) that don't have to be preserved across subroutine calls.

The C compiler also imposes similar restrictions on the 16 floating point registers (some are used as parameters, some saved, some not).

All these restrictions are imposed by the system level languages, *not* the hardware itself.

So much for pre-existing decisions upon you at runtime.

Vorlath Monday, October 8, 2007 7:22:00 PM

You're talking about an ABI, not C. Sorry, better luck next time. I've looked at this a while back too.

Write a comment

New comments have been disabled for this post.

June 2012
S M T W T F S
May 2012July 2012
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30