Re: How Powerful Is Parrot? (A Few More Questions)
so please note that destruction is not collection and they are and can be separately controlled. you have to stop thinking c++ (which will probably NOT be directly supported by parrot) and think perlish (or as other dynamic langs) more. perl doesn't have a delete thing and doesn't need one. it can detect DoD on its own and then let parrot GC them later. memory usage and objects are not the same. Well, I'm not really interested in Perl at all. If all Parrot can do is allow me to write a languge that is basically Perl, then I'm not interested in Parrot either. I think it may be a good idea to wait until the Parrot folks have their product and web site a little better documented and aren't under such stress. Dave Uri Guttman uri@stemsyste To: [EMAIL PROTECTED] ms.com cc: [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] Subject: Re: How Powerful Is Parrot? (A Few More Questions) 01/25/02 11:49 PM Please respond to Uri Guttman DL == David Leeper [EMAIL PROTECTED] writes: DL If I know what I want to destroy and when, can I just turn off Parrot's DL automatic garbage collector/memory compactor and send it instructons on DL what I want deleted? i have to jump in here because i am seeing the classic discussion of A and B and they are not the same things. in parrot, GC is separated from DoD. you seem to always conflate the two. in general destruction is not related to GC, it is used to clean up stuff like file handles, complex objects, deal with persistance etc. a destroyed object may have its space reclaimed at some future time. destruction is more of a language feature and GC is more of a VM feature. they are not the same thing and you shouldn't keep talking about them as if they are con-joined twins. you can cause object destruction when you want in most langs that parrot will support. and you can probably initiate a GC pass from most langs if they have an API to get into parrot's GC. but you don't have to do one to do the other. many heap allocated things won't be objects (buffers, strings, etc.) and will be purely GC'ed as needed. some objects can be destroyed simply when their context exits (e.g. leaving a block and destroying any my'ed objects which are dead). those will then be marked for later GC. so please note that destruction is not collection and they are and can be separately controlled. you have to stop thinking c++ (which will probably NOT be directly supported by parrot) and think perlish (or as other dynamic langs) more. perl doesn't have a delete thing and doesn't need one. it can detect DoD on its own and then let parrot GC them later. memory usage and objects are not the same. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com -- Stem is an Open Source Network Development Toolkit and Application Suite - - Stem and Perl Development, Systems Architecture, Design and Coding Search or Offer Perl Jobs http://jobs.perl.org
Re: How Powerful Is Parrot? (A Few More Questions)
Thanks to everyone for their information on Parrot. A couple more questions have come to mind. 1) Does Parrot support multiple inheritance? 2) Does Parrot support stack variables or is everything allocated on the heap? Thanks again. Dave
Re: CPP Namespace pollution
I don't have a specific proposal at the moment, but would invite others to think creatively about ways to minimize cpp pollution while still keeping the source readable and maintainable. One possibility would be to change code like this #define XYZ 123 to this... namespace _PARROT { const int XYZ = 123; } By placing code in namespaces and not using CPP at all, name clashes are completely avoided. This requires the use of C++, rather than C. Also, where the CPP #define is nothing more than text substitution done at compile time, use of constants in C++ consumes runtine stack space. Dave Andy Dougherty doughera@lafa To: Perl6 Internals [EMAIL PROTECTED] yette.edu cc: Subject: CPP Namespace pollution 01/25/02 10:14 AM One problem noted recently on the p5p list is that if you do #include perl.h in your program, it exposes a *lot* of CPP #defines to your program, whether you want them or not. This is particularly a problem if you wish to embed perl or use it with an extensive 3rd-party library. For parrot, we'd ideally like to make it a lot safer to #include parrot/parrot.h Here's a status check on where we are currently: #include parrot/parrot.h currently #defines 198 global CPP symbols. If you take away the autoconf-ish HAS_HEADER_* and the proabably-quite-safe PARROT_* entries, that leaves 107 entries. Although it's impossible to predict what vendors and third-party software writers will do with the CPP namespace, the following 5 entries seem particularly likely to cause mischief at some point somewhere: Very general names: UNUSED INVALID_CHARACTER IO_ERROR KEY_NOT_FOUND Possible conflict with system headers: SSIZE_MAX This is #defined in parrot/io.h as 8192, but it's also possibly defined in the system headers as the maximum size of the Posix ssize_t type, typically INT_MAX or LONG_MAX. Since it's not used in parrot, I'm unsure of the intent. I don't have a specific proposal at the moment, but would invite others to think creatively about ways to minimize cpp pollution while still keeping the source readable and maintainable. -- Andy Dougherty [EMAIL PROTECTED] Dept. of Physics Lafayette College, Easton PA 18042
Re: CPP Namespace pollution
This requires the use of C++, rather than C. See the FAQ. Where would the FAQ be? Dave Simon Cozens simon@netthin To: [EMAIL PROTECTED] k.co.uk cc: Perl6 Internals [EMAIL PROTECTED] Subject: Re: CPP Namespace pollution 01/25/02 10:52 AM On Fri, Jan 25, 2002 at 10:30:01AM -0500, [EMAIL PROTECTED] wrote: This requires the use of C++, rather than C. See the FAQ. -- The most effective debugging tool is still careful thought, coupled with judiciously placed print statements. -Kernighan, 1978
Re: How Powerful Is Parrot? (A Few More Questions)
From what I've seen, supporting both garbage collection and true stack variables is a difficult task. Why is that? Because stack variables can refer to heap variables and heap variables can refer to stack variables. The garbage collector needs to be smart enough to handle all cases correctly. For example, let's say we have the following two classes... class A { public B b_member; } class B { public A a_member; } and the following declarations and function... B global_b; // Creates an instance of B with an A member, both on the stack. B global_b2;// Creates an instance of B with an A member, both on the stack. void f() { A a; // Creates an instance of A with a B member, both on the stack. B b = new B(); // Creates an instance of B with an A member, both on the heap. // 4 objects have now been created in this function, an A and B on the stack, and an A and B on the heap. a.b_member = b; // Stack variable a now references heap variable b. b.a_member = a; // Heap variable b now references stack variable a. global_b.a_member = a; // Stack variable global_b now references stack variable a. global_b2 = b; // Stack variable global_b2 now references heap variable b. // What happens to the six objects we've created when we leave the scope of f()? } This implies several things. 1) Garbage collection is optional because stack variables are not garbage collected. 2) Garbage collection knows every object created, how every object was created (stack or heap), and how every object is referenced by other objects. 3) The stack interacts seemlessly with garbage collection. When we leave f () in the above example, referencing global_b.a_member needs to produce an error or exception. 4) Garbage collection interacts seemlessly with the stack. In the above example, b can never be garbage collected for the life of the program because the stack variable global_b2 references it and global_b2 never goes out of scope. It's not impossible to write a garbage collector that can handle this, I've done it myself. This is why I've been asking these questions about Parrot. I want to know if I can use Parrot as a VM for a language I've designed. I'm currently generating C++ code. I'd like to use Parot, but I need true stack variables and 100% deterministic garbage collection. I don't know of any language that has these features. Java doesn't. C++ doesn't (unless you roll your own and restrict what programmers can do), C# doesn't. Dave Melvin Smith [EMAIL PROTECTED] To: [EMAIL PROTECTED] m.com cc: [EMAIL PROTECTED], Simon Cozens [EMAIL PROTECTED] Subject: Re: How Powerful Is Parrot? (A Few More Questions) 01/25/02 12:00 PM From what I've seen, supporting both garbage collection and true stack variables is a difficult task. Why is that? -Melvin Smith IBM :: Atlanta Innovation Center [EMAIL PROTECTED] :: 770-835-6984
Re: How Powerful Is Parrot? (A Few More Questions)
Thanks for the nice example, except I understand the issue you are speaking of, I was basically asking what parts of it do you think are more difficult to implement than any other major construct? I believe the main difficulty comes from heading into uncharted waters. For example, once you've decided to make garbage collection optional, what does the following line of code mean? delete x; Does it mean anything at all? Is it even a legal statement? Is garbage collection optional for all variables, or simply not used for stack variables, but always used for heap variables? Or, for example, are the side effects of the following two functions different? void f1() { // On the stack MyClass o; } void f2() { // On the heap MyClass o = new MyClass(); } If garbage collection is not 100% deterministic, these two functions could produce very different results because we do not know when or if the destructor for MyClass will execute in the case of f2(). The same would be true when exceptions are thrown from a function. If garbage collection is not 100% deterministic (and Mark and Sweep is not), we need extra language features, such as Java's finally block, to ensure things can be cleaned up, and extra training to ensure programmers are smart enough to know how to use finally blocks correctly. So, as I see it, the choice of garbage collections schemes ripples throughout the entire language. It effects what statements are legal and the semantics of even the simplest pieces of code. The point to all my questions is this: I'm thinking about basing my language on the Parrot VM. If I do that, what does the call to f2() mean? What happens to my language when I use the Parrot VM? Dave Melvin Smith [EMAIL PROTECTED] To: [EMAIL PROTECTED] m.com cc: [EMAIL PROTECTED], Simon Cozens [EMAIL PROTECTED] Subject: Re: How Powerful Is Parrot? (A Few More Questions) 01/25/02 01:13 PM Thanks for the nice example, except I understand the issue you are speaking of, I was basically asking what parts of it do you think are more difficult to implement than any other major construct? There are several ways to address the example you just gave (my computer science is getting rusty here) but let me think... a.b_member = b; // Stack variable a now references heap variable b. I see no problem here. b.a_member = a; // Heap variable b now references stack variable a. global_b.a_member = a; // Stack variable global_b now references stack variable a. global_b2 = b; // Stack variable global_b2 now references heap variable b. // What happens to the six objects we've created when we leave the scope of f()? One approach is stack = stack (reference) stack = heap (reference) heap = heap (reference) heap = stack (copy) -Melvin Smith IBM :: Atlanta Innovation Center [EMAIL PROTECTED] :: 770-835-6984 David.Leeper@bisy s.comTo: Melvin Smith/ATLANTA/Contr/IBM@IBMUS cc: [EMAIL PROTECTED], Simon Cozens [EMAIL PROTECTED] 01/25/2002 12:45 Subject: Re: How Powerful Is Parrot? (A Few More Questions) PM From what I've seen, supporting both garbage collection and true stack variables is a difficult task. Why is that? Because stack variables can refer to heap variables and heap variables can refer to stack variables. The garbage collector needs to be smart enough to handle all cases correctly. For example, let's say we have the following two classes... class A { public B b_member; } class B { public A a_member; } .and the following declarations and function... B global_b; // Creates an instance of B with an A member, both on the stack. B global_b2;// Creates an instance of B with an A member, both on the stack. void f() { A a; // Creates an instance of A with a B member, both on the stack. B b = new B(); // Creates an instance of B with an A member, both on the heap. // 4 objects have now been created in
Re: How Powerful Is Parrot? (A Few More Questions)
Parrot supports deterministic destruction at the language level. If your language wants 'o' to be destroyed at the exit from f2(), then 'o' will be destroyed in whatever manner MyClass destruction means to your language. Resources allocated strictly by the internal representation responsible for MyClass (e.g. Leeper_Object) may not be collected at that point, but that's mostly independent of the language. (You could also trigger a GC run yourself.) I believe I understand now. I think that what this means to me is that if I want 100% deterministic destruction, I will have to implement my own garbage collector. This garbage collector will call object destructors and free all language-specific resources of the object. Once I've finished using the object, the Parrot garbage collector will free Parrot resources associated with the object at some undetermined time in the future. I think that's acceptable. Thanks Bryan. Dave Bryan C. Warnock To: [EMAIL PROTECTED] bwarnock@capi cc: [EMAIL PROTECTED] ta.com Subject: Re: How Powerful Is Parrot? (A Few More Questions) 01/25/02 02:10 PM Please respond to bwarnock On Friday 25 January 2002 13:50, [EMAIL PROTECTED] wrote: Thanks for the nice example, except I understand the issue you are speaking of, I was basically asking what parts of it do you think are more difficult to implement than any other major construct? I believe the main difficulty comes from heading into uncharted waters. For example, once you've decided to make garbage collection optional, what does the following line of code mean? delete x; Does it mean anything at all? Is it even a legal statement? Is garbage collection optional for all variables, or simply not used for stack variables, but always used for heap variables? Or, for example, are the side effects of the following two functions different? void f1() { // On the stack MyClass o; } void f2() { // On the heap MyClass o = new MyClass(); } If garbage collection is not 100% deterministic, these two functions could produce very different results because we do not know when or if the destructor for MyClass will execute in the case of f2(). The same would be true when exceptions are thrown from a function. If garbage collection is not 100% deterministic (and Mark and Sweep is not), we need extra language features, such as Java's finally block, to ensure things can be cleaned up, and extra training to ensure programmers are smart enough to know how to use finally blocks correctly. So, as I see it, the choice of garbage collections schemes ripples throughout the entire language. It effects what statements are legal and the semantics of even the simplest pieces of code. The point to all my questions is this: I'm thinking about basing my language on the Parrot VM. If I do that, what does the call to f2() mean? What happens to my language when I use the Parrot VM? GC (at the Parrot level) isn't finalization (at the language level). In your last several posts, it hasn't been clear at what level you're trying to address. Parrot supports deterministic destruction at the language level. If your language wants 'o' to be destroyed at the exit from f2(), then 'o' will be destroyed in whatever manner MyClass destruction means to your language. Resources allocated strictly by the internal representation responsible for MyClass (e.g. Leeper_Object) may not be collected at that point, but that's mostly independent of the language. (You could also trigger a GC run yourself.) Consider, for a moment, a C++ object that is dependent on some kernel resource. C++ makes the determination of when and how that object is destroyed and finalized, releasing both program memory, user-space resources,
RE: How Powerful Is Parrot? (A Few More Questions)
That is exactly the case for C++. In your above code f1(), the C++ compiler already (behind the scene) inserts finally block for o destructor. That is why the destructor of stack allocated objects is called even when exception happens. The only difference is that the memory deallocation is dis-associated with object destruction. Summary: the object destruction with GC is as deterministic as C++ heap allocated object, i.e. you have to call delete x (in C++), x.close() (in Java), x.dispose (in C#), otherwise is 0% deterministic, period. No, there is a difference. The difference is you do not know when the Java garbage collector will call an object's finalize() method, and in fact Java does not even guarentee it will be called at all. C#'s garbage collector is nondeterministic as well. The garbage collector in these languages are usually implemented to run on a low priority thread. This thread gets processor time based on system load, which means objects are collected and finalized based on thread scheduling, the number of active threads, and other factors that have nothing to do with a function going out of scope and which cannot be predicted prior to run time. In C++, when operator delete is called, the object's destructor is invoked as part of the call right away, not at some point in the future, by some other thread, maybe as with Java. This changes the way a programmer writes code. A C++ class and function that uses the class looks like this: class A { public: A(){...grab some resources...} ~A(){...release the resources...} } void f() { A a; ... use a's resources ... } looks like this in Java... class A { public: A(){...grab some resources...} } void f() { try { A a; ... use a's resources ... } finally { ...release the resources... } } because we do not know when or if Java will finalize the a object. And everywhere the programmer uses the class A he must write the finally block as well. Also note that both examples behave correctly in the face of exceptions thrown during the execution of f(). Dave Hong Zhang Hong.Zhang@corp To: .palm.com cc: [EMAIL PROTECTED] Subject: RE: How Powerful Is Parrot? (A Few More Questions) 01/25/02 03:05 PM I believe the main difficulty comes from heading into uncharted waters. For example, once you've decided to make garbage collection optional, what does the following line of code mean? delete x; If the above code is compiled to Parrot, it probably equivalent to x-~Destructor(); i.e., the destructor is called, but the memory is left to GC, which most likely handle free at a later time. Or, for example, are the side effects of the following two functions different? void f1() { // On the stack MyClass o; } void f2() { // On the heap MyClass o = new MyClass(); } If garbage collection is not 100% deterministic, these two functions could produce very different results because we do not know when or if the destructor for MyClass will execute in the case of f2(). This is exactly the same case for C++. When you compile f2 with gcc, how can you tell when the destructor is called. Even the following code does not work. void f3() { MyClass o = new MyClass(); ... delete o; } If there is an exception happens within (...), the destructor will not be called. If garbage collection is not 100% deterministic (and Mark and Sweep is not), we need extra language features, such as Java's finally block, to ensure things can be cleaned up, and extra training to ensure programmers are smart enough to know how to use finally blocks correctly. That is exactly the case for C++. In your above code f1(), the C++ compiler already (behind the scene) inserts finally block for o destructor. That is why the destructor of stack allocated objects is called even when exception happens. The only difference is that the memory deallocation is dis-associated with object destruction. Summary: the object
Re: How Powerful Is Parrot? (A Few More Questions)
In neither case do you have any control over the order that memory is compacted, or dead objects with destructors have their destructors called. If you must force some sort of order you need to do so within the objects destructor. Alternately if your program knows what order objects should be destroyed in your may explicitly call objects destructors. This is outside the GC/DOD system however as it happens from within your mainline code. (When the DOD later runs it won't do anything with those objects as you've already destroyed them and thus left nothing for the DOD sweep to do) If I know what I want to destroy and when, can I just turn off Parrot's automatic garbage collector/memory compactor and send it instructons on what I want deleted? Dave Dan Sugalski [EMAIL PROTECTED] To: [EMAIL PROTECTED], [EMAIL PROTECTED] cc: [EMAIL PROTECTED] Subject: Re: How Powerful Is Parrot? (A Few More Questions) 01/25/02 03:43 PM At 2:46 PM -0500 1/25/02, [EMAIL PROTECTED] wrote: Parrot supports deterministic destruction at the language level. If your language wants 'o' to be destroyed at the exit from f2(), then 'o' will be destroyed in whatever manner MyClass destruction means to your language. Resources allocated strictly by the internal representation responsible for MyClass (e.g. Leeper_Object) may not be collected at that point, but that's mostly independent of the language. (You could also trigger a GC run yourself.) I believe I understand now. I think that what this means to me is that if I want 100% deterministic destruction, I will have to implement my own garbage collector. This garbage collector will call object destructors and free all language-specific resources of the object. Once I've finished using the object, the Parrot garbage collector will free Parrot resources associated with the object at some undetermined time in the future. I think you're getting confused a bit here--I apologize for not jumping in earlier. As far as Parrot's concerned, Garbage Collection is just the reclamation of unused memory and unused interpreter structures. This will happen when the interpreter deems it necessary, and you can force or block a GC run if you need to. The heap may be compacted when this happens, but variables can be marked as non-moveable if this is necessary. (for those cases when absolute memory addresses are referenced outside of the interpreter as well) Dead Object Detection is the phase where the interpreter determines which objects are reachable from the root set, and which aren't. Any objects that aren't reachable *and* are marked as having an active destructor (and most won't, there's no need in 90% of the cases) will have their destructor called and the objects can clean up as need be. Once again this happens when the interpreter deems it necessary and you may also force or block a DOD run. In neither case do you have any control over the order that memory is compacted, or dead objects with destructors have their destructors called. If you must force some sort of order you need to do so within the objects destructor. Alternately if your program knows what order objects should be destroyed in your may explicitly call objects destructors. This is outside the GC/DOD system however as it happens from within your mainline code. (When the DOD later runs it won't do anything with those objects as you've already destroyed them and thus left nothing for the DOD sweep to do) Bryan C. Warnock To: [EMAIL PROTECTED] bwarnock@capi cc: [EMAIL PROTECTED] ta.com Subject: Re: How Powerful Is Parrot? (A Few More Questions) 01/25/02 02:10 PM Please respond to bwarnock On Friday 25 January 2002 13:50, [EMAIL PROTECTED] wrote: Thanks for the nice example, except I understand the issue you are speaking of, I was basically asking what parts of it do you think are more difficult to implement than any other major construct? I
How Powerful Is Parrot?
I've been watching the Parrot development with interest and have a few questions about Parrots capabilities. Will Parrot support templates (also known as generics)? Will Parrot support operator overloading? Do Parrot classes have constructors and destructors? Does Parrot have garbage collection? When a Parrot class is garbage collected or otherwise destroyed, is its destructor executed? If so, when? In other words, is object destruction 100% deterministic in Parrot? Does Parrot memory allocation support placement? In other words, can I supply a Parrot memory allocation routine with the address of a variable and the desired size to allocate and expect Parrot to allocate a block of the given size starting at the address I provided? How hard would it be to implement memory pools of objects in Parrot? Does Parrot support threads? Does Parrot support exceptions? Can I invoke routines written in other languages, such as C or C++, from Parrot? Thanks in advance for your help. Dave
RE: How Powerful Is Parrot?
Thanks Brent. # #Does Parrot have garbage collection? # Not yet, but it will. When it does, I'd ask that there be some sort of option on what type of garbage collection is used. This is because different methods of garbage collection have very different characteristics. For example, reference counting can't handle circular references and the garbage collector therefore leaks memory. Mark and Sweep is not 100% deterministic and there is no way to know when or if a garbage collected object will have it destructor executed. This is a big reason why Java has a finally keyword, so the programmer can execute code that would normally go in a destructor in a 100% deterministic language. I have a garbage collector written in C++ that handles circular references, is 100% deterministic, and is fast. When it comes time to implement garbage collection in Parrot, I'd be happy to provide the source if the Parrot community feels it'd be worthwhile. I currently own the copyright, but have no problem making it open source. Dave Brent Dax brentdax@cpan To: [EMAIL PROTECTED], [EMAIL PROTECTED] .orgcc: Subject: RE: How Powerful Is Parrot? 01/24/02 03:35 PM [EMAIL PROTECTED]: # I've been watching the Parrot development with interest and have a few # questions about Parrots capabilities. # #Will Parrot support templates (also known as generics)? If you mean like C++ templates, then the answer is that it's up to the language. There won't be anything in Parrot that will prevent it. #Will Parrot support operator overloading? Yup, that's what vtables are all about. At the Parrot level, you just overlaod the 'add' vtable entry (and its variants) to implement +; at the language level you do whatever you want. #Do Parrot classes have constructors and destructors? Yes. #Does Parrot have garbage collection? Not yet, but it will. #When a Parrot class is garbage collected or otherwise # destroyed, is its #destructor executed? If so, when? In other words, is # object destruction #100% deterministic in Parrot? Depends on the language, but Parrot will support deterministic destruction. #Does Parrot memory allocation support placement? In other # words, can I #supply a Parrot memory allocation routine with the address # of a variable #and the desired size to allocate and expect Parrot to # allocate a block #of the given size starting at the address I provided? Dunno, that's not my department. #How hard would it be to implement memory pools of objects # in Parrot? . #Does Parrot support threads? Not yet, but it will. #Does Parrot support exceptions? Not yet, but it will. #Can I invoke routines written in other languages, such as # C or C++, from #Parrot? Yes--you'll just have to write opcodes to wrap them. # Thanks in advance for your help. You're quite welcome. --Brent Dax [EMAIL PROTECTED] Parrot Configure pumpking and regex hacker obra . hawt sysadmin chx0rs lathos This is sad. I know of *a* hawt sysamin chx0r. obra I know more than a few. lathos obra: There are two? Are you sure it's not the same one?