sablevm-developer Mailing List for SableVM (Page 55)
Brought to you by:
egagnon
You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(27) |
Aug
(22) |
Sep
(1) |
Oct
|
Nov
(1) |
Dec
(30) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
(32) |
Oct
|
Nov
|
Dec
|
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(69) |
Sep
(10) |
Oct
(31) |
Nov
(15) |
Dec
(58) |
2003 |
Jan
(33) |
Feb
(81) |
Mar
(85) |
Apr
(24) |
May
(15) |
Jun
(14) |
Jul
(6) |
Aug
(9) |
Sep
(101) |
Oct
(59) |
Nov
(142) |
Dec
(34) |
2004 |
Jan
(107) |
Feb
(164) |
Mar
(181) |
Apr
(96) |
May
(81) |
Jun
(71) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Etienne M. G. <eti...@uq...> - 2002-12-05 17:20:49
|
On Wed, Dec 04, 2002 at 10:29:27PM -0700, Gunda Domlur wrote: > I think so. I will check again. I had to do one thing out of the ordinary > though. Jikes did not compile on our system (arm/linux), mostly because we > don't a working C++ compiler :-( Ah! A good reason for writing the VM and class libraries in plain C. :-) > and The sablevm-class library was built on a > P4/Linux machine and then the whole /usr/local/lib/sablevm/classes-1.0.5 > contents were ftp'ed to the arm/linux system to the same path. This step > shouldn't affect anything I think. Let me know if I got anything wrong. It should be OK. > >Also, why are you specifying: -c "/usr/local/lib/sablevm/classes-1.0.5" ? > > I thought this was the way to tell the sablevm the class path. How does the > vm know where to look for the class libraries ? The default "boot class path" is hardcoded in the VM (value given by the GNU configure stuff), but can be dynamically specified on the command-line using "--property". The command-line options are documented in an appendix of my thesis(to be made public very soon). The "application" class path defaults to "." and can be changed using the --classpath command-line parameter. "boot" and "application" class path are managed separately, which simplifies users life a lot. (Usually, a user should't play with the booclasspath). So, you could write: sablevm --property "sablevm.boot.class.path=/usr/local/lib/sablevm/classes-1.0.5" --classpath .:$HOME/classes HelloWorld For frequently used properties, you can put the into either /etc/sablevm or $HOME/.sablevm like this: # beginning of file property = sablevm.boot.class.path=/usr/local/lib/sablevm/classes-1.0.5 # end of file > OK I can help with part (a). > > I don't fully understand part (b). After I get the basic interpreter going > I intend to work on the inlining part too. I will bug you again on that. > Meanwhile if you can elaborate on the "inlinability" that would get me > started thinking ... Chapter 2 of my thesis should help you there. FYI. I usually use gdb (or more specifically ddd) to debug sablevm. You should definitely build sablevm with: ./configure --enable-debuggin-features This will make debugging much easier, as the normal build puts a "segfault" (which is then catched through a signal habdler) on the normal execution path of VM bootstrap... This can be somewhat unsettling for new developers trying to understand what's happening. ;-) Have fun! Etienne -- Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Gunda D. <sab...@ho...> - 2002-12-05 05:29:57
|
>Have you correctly compiled and installed all of sablevm, >sablevm-native-library, sablevm-class-library? SableVM seems not to >find "java.lang.Object" while bootstrapping. I think so. I will check again. I had to do one thing out of the ordinary though. Jikes did not compile on our system (arm/linux), mostly because we don't a working C++ compiler :-( The sablevm-class library was built on a P4/Linux machine and then the whole /usr/local/lib/sablevm/classes-1.0.5 contents were ftp'ed to the arm/linux system to the same path. This step shouldn't affect anything I think. Let me know if I got anything wrong. > >Also, why are you specifying: -c "/usr/local/lib/sablevm/classes-1.0.5" ? I thought this was the way to tell the sablevm the class path. How does the vm know where to look for the class libraries ? Is it thru an environment variable ? After compiling and installing according to your scripts is there anything else I need to set ? > > > PS: Etienne: When you said "The fun part (let say not before January) >will > > be to make the inline-threaded engine functional on ARM" what did you >mean > > ? Is there something that will prevent it from working on ARM ? > > >Getting inline-threading to work on a specific platform requires >(a) understanding how its caches behave (including data AND instruction >caches). It also involves (b) testing the various bytecode >implementations for "inlinability". > >The (a) part requires finding the relevant information, and clearly >understanding it. The (b) part will require some minor rethinking of >how the "inlinability" is encoded in SableVM, so that it becomes easy >to manage this property on an architecture/compiler basis, ideally in >independent files, one per platform. OK I can help with part (a). I don't fully understand part (b). After I get the basic interpreter going I intend to work on the inlining part too. I will bug you again on that. Meanwhile if you can elaborate on the "inlinability" that would get me started thinking ... > >So, yes this will be fun (at least for me), as I will learn a lot >about all these exotic systems! [I do not have any idea what the ARM >architecture is!] > >The main difficulty is that to be more productive, I will need to >have access to such systems. I hear that becoming an official Debian >developer to gain access to various systems (of different >architectures) requires many months. I will have trouble to be >effective without access to such systems to make tests... > >Of course, ideally contributors (with access to such systems) should >be in charge, but it's always fun to land a hand when you're the main >system designer, and people need help... Hmm.. let me think about this for a while. Thanks. -Gunda _________________________________________________________________ The new MSN 8: smart spam protection and 2 months FREE* http://join.msn.com/?page=features/junkmail |
From: Etienne M. G. <eti...@uq...> - 2002-12-05 01:31:25
|
On Wed, Dec 04, 2002 at 04:29:26PM -0700, Gunda Domlur wrote: > Thanks for all the advice you guys gave me. I finally got everything > compiled and ready to go. Super! > When I ran the Hello World program, unfortunately sablevm failed. Here is > the invocation I did > > sablevm -vsgj -c "/usr/local/lib/sablevm/classes-1.0.5" Hello.class > > The relevant output I got was > > [verbose jni: JNI_CreateJavaVM] > [verbose gc: allocating initial heap (16777216 bytes)] > [verbose class: loading "java/lang/Object"] > sablevm: cannot create vm Have you correctly compiled and installed all of sablevm, sablevm-native-library, sablevm-class-library? SableVM seems not to find "java.lang.Object" while bootstrapping. Also, why are you specifying: -c "/usr/local/lib/sablevm/classes-1.0.5" ? > PS: Etienne: When you said "The fun part (let say not before January) will > be to make the inline-threaded engine functional on ARM" what did you mean > ? Is there something that will prevent it from working on ARM ? Getting inline-threading to work on a specific platform requires (a) understanding how its caches behave (including data AND instruction caches). It also involves (b) testing the various bytecode implementations for "inlinability". The (a) part requires finding the relevant information, and clearly understanding it. The (b) part will require some minor rethinking of how the "inlinability" is encoded in SableVM, so that it becomes easy to manage this property on an architecture/compiler basis, ideally in independent files, one per platform. So, yes this will be fun (at least for me), as I will learn a lot about all these exotic systems! [I do not have any idea what the ARM architecture is!] The main difficulty is that to be more productive, I will need to have access to such systems. I hear that becoming an official Debian developer to gain access to various systems (of different architectures) requires many months. I will have trouble to be effective without access to such systems to make tests... Of course, ideally contributors (with access to such systems) should be in charge, but it's always fun to land a hand when you're the main system designer, and people need help... Etienne -- Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Gunda D. <sab...@ho...> - 2002-12-04 23:32:36
|
Etienne/Grzegorz, Thanks for all the advice you guys gave me. I finally got everything compiled and ready to go. When I ran the Hello World program, unfortunately sablevm failed. Here is the invocation I did sablevm -vsgj -c "/usr/local/lib/sablevm/classes-1.0.5" Hello.class The relevant output I got was [verbose jni: JNI_CreateJavaVM] [verbose gc: allocating initial heap (16777216 bytes)] [verbose class: loading "java/lang/Object"] sablevm: cannot create vm What went wrong ? Any help would be appreciated. After some testing I will post the diffs. Thanks. -Gunda PS: Etienne: When you said "The fun part (let say not before January) will be to make the inline-threaded engine functional on ARM" what did you mean ? Is there something that will prevent it from working on ARM ? >From: Grzegorz Prokopski <ga...@de...> >To: Gunda Domlur <sab...@ho...> >CC: SableVM-devel ML <sab...@li...> >Subject: Re: [Sablevm-developer] Porting SableVM to ARM: Questions >Date: 03 Dec 2002 23:59:34 +0100 > >W li¶cie z wto, 03-12-2002, godz. 22:36, Gunda Domlur pisze: > > Hi, > > > > I am trying to port sableVM for ARM linux (netwinder). After looking >thru > > the archives, I already made the following changes > > > > system.c: iflush and compare_and_swap ported to ARM > > system.h: The correct typedefs are in place > > jni_system_specific.h: Necessary changes are done. >Great! >Could you please send the diff? > > > Am I missing anything else ? >If it doesn't work by now - I can't say not looking at your changes. > > > Proabably a stupid question, where does the cpu type definitions (e.g. > > __ia64__) defined ? Is it part of the configure ? Is it in the generated > > Makefiles ? The reason is that after defining the new cpu type as >__arm__ I > > get a error "unknown system" generated from the jni_system_specific.h >file > > when I try to make. Is there a way to force the build to use a >particular > > target type ? >Hmm... I belive that these defines are set by build environment and we >shouldn't need to wory about who exactly is responsible for setting >them. The mechanism is probably a bit complicated - just imagine >crosscompilations and the like. > >But getting back to your problem - AFAIK __arm__ should be defined >while you're doing build for arm. > > > An early reply will be appreciated :-) >Usually You can try to catch me at #debian-devel at irc.debian.org >I am interested in helping you even _now_. > >You're welcomed > > Grzegorz B. Prokopski > > ><< signature.asc >> _________________________________________________________________ Help STOP SPAM with the new MSN 8 and get 2 months FREE* http://join.msn.com/?page=features/junkmail |
From: Etienne M. G. <eti...@uq...> - 2002-12-04 14:32:39
|
Grzegorz Prokopski wrote: > I just wanted to ask you about electronic version of your PhD. I am > sure it'll be very interesting reading. I'll make both my thesis and the slides of my Ph.D. defense public (electronic versions) as soon as the final submission is made in a very few days. There aren't many slides, as the presentation part of the defense only lasts 20 mimutes! [20 minutes to present 10 chapters was really challenging]. The second par of the defense was approximately 1 hours and 20 minutes of oral questions by five committee members. Unfortunately, there is no transcript of the second part. > BTW: When does UQAM finish the term? And when are the exams? For students, the term finishes on Friday December 13th. I give my last exam on that day. So, I'll have corrections to do in the following days. Now, given the incredibly exhausting term I had, this Fall, I will take real vacations away from my computer (as much as possible) until the beginning of the Winter term on Jabuary 6, 2003. I really need these vacations. The good thing: I have minimal teaching to do in the Winter term; most of my time is reserved for research (e.g. SableVM/SableCC development). :-) > BTW: Have you tried gcc 3.X Etienne? It says so in the README file;-) > I am a bit worried that it can > break inline threading engine on every arch (only i386 currently). Inline-threading does work with gcc 2.95.x and with gcc (3.0,3.1,3.2). I have tested it on all these versions. Have you tried the little inline-threaded interpreter (of the INRIA web site) on ia64? > A thing to be checked. Has been checked. :-) Have fun! Etienne -- Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Grzegorz P. <ga...@de...> - 2002-12-03 23:43:40
|
W li=B6cie z wto, 03-12-2002, godz. 23:53, Etienne M. Gagnon pisze:=20 > Gunda Domlur wrote: > > Hi, > >=20 > > I am trying to port sableVM for ARM linux (netwinder). After looking=20 > > thru the archives, I already made the following changes > >=20 > > system.c: iflush and compare_and_swap ported to ARM > > system.h: The correct typedefs are in place > > jni_system_specific.h: Necessary changes are done. > >=20 > > Am I missing anything else ? > No. The fun part (let say not before January) will be to make the=20 > inline-threaded engine functional on ARM. Yup, I hope to have some more time next week and get it working for ia64 also (or at least push it forward a bit). > For the benefit of all subscribers: I am currently making the *final* lit= tle=20 > modifications to my thesis (as requested by the Ph.D. committee; little=20 > typos...) which I should be publishing on the Internet in a few days. Ye= p, I=20 > have successfully [:-)] passed both the written Thesis evaluation and the= oral=20 > Ph.D. defense. I already sent you congratulations... I just wanted to ask you about electronic version of your PhD. I am sure it'll be very interesting reading. I hope now you will be able to be a remove items from the TODO list one by one? :-) (by solving them of course) BTW: When does UQAM finish the term? And when are the exams? Right after new year I'd suspect? (I expect you to be busy at that time) > > Proabably a stupid question, where does the cpu type definitions (e.g. = =20 > > __ia64__) defined ?=20 > I don't know for sure, but I think it is internally generated by GCC. I = looked=20 > through config.guess and found: > #if defined (__arm) ... > You might want to try that, just in case it works. ;-) Look at that: http://lists.debian.org/debian-arm/2001/debian-arm-200102/msg00157.html <quoted piece> This fails on a modern GCC, as 'arm' and '__arm' defines aren't set. Adding '|| defined(__arm__)' in the correct place fixes things. </quoted piece> Wonder what's your compiler? However it can be that 2.95 uses __arm and __i386 as for ex. in ./src/libsablevm/system.h:67 there is: #if defined (__i386) But if the above quote is correct, then we should change it to __i386__ We should do that at least because Debian and other distros will/already have switch(ed) to gcc 3.X branch as the basic compiler. BTW: Have you tried gcc 3.X Etienne? I am a bit worried that it can break inline threading engine on every arch (only i386 currently). A thing to be checked. That's all for now, cheers... Grzegorz B. Prokopski PS: My IRC nickname is "gadek" of course. |
From: Etienne M. G. <eti...@uq...> - 2002-12-03 23:01:54
|
Gunda Domlur wrote: > Hi, > > I am trying to port sableVM for ARM linux (netwinder). After looking > thru the archives, I already made the following changes > > system.c: iflush and compare_and_swap ported to ARM > system.h: The correct typedefs are in place > jni_system_specific.h: Necessary changes are done. > > Am I missing anything else ? No. The fun part (let say not before January) will be to make the inline-threaded engine functional on ARM. For the benefit of all subscribers: I am currently making the *final* little modifications to my thesis (as requested by the Ph.D. committee; little typos...) which I should be publishing on the Internet in a few days. Yep, I have successfully [:-)] passed both the written Thesis evaluation and the oral Ph.D. defense. > Proabably a stupid question, where does the cpu type definitions (e.g. > __ia64__) defined ? I don't know for sure, but I think it is internally generated by GCC. I looked through config.guess and found: #if defined (__arm) ... You might want to try that, just in case it works. ;-) Otherwise, we can play tricks in configure.ac (as long as the configure magic correctly detects ARM), and add a test to define a constant when ARM architecture is detected. Etienne -- Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Grzegorz P. <ga...@de...> - 2002-12-03 23:01:03
|
W li=B6cie z wto, 03-12-2002, godz. 22:36, Gunda Domlur pisze:=20 > Hi, >=20 > I am trying to port sableVM for ARM linux (netwinder). After looking thru= =20 > the archives, I already made the following changes >=20 > system.c: iflush and compare_and_swap ported to ARM > system.h: The correct typedefs are in place > jni_system_specific.h: Necessary changes are done. Great! Could you please send the diff? > Am I missing anything else ? If it doesn't work by now - I can't say not looking at your changes. > Proabably a stupid question, where does the cpu type definitions (e.g. =20 > __ia64__) defined ? Is it part of the configure ? Is it in the generated=20 > Makefiles ? The reason is that after defining the new cpu type as __arm__= I=20 > get a error "unknown system" generated from the jni_system_specific.h fil= e=20 > when I try to make. Is there a way to force the build to use a particular= =20 > target type ? Hmm... I belive that these defines are set by build environment and we shouldn't need to wory about who exactly is responsible for setting them. The mechanism is probably a bit complicated - just imagine crosscompilations and the like. But getting back to your problem - AFAIK __arm__ should be defined while you're doing build for arm. > An early reply will be appreciated :-) Usually You can try to catch me at #debian-devel at irc.debian.org I am interested in helping you even _now_. You're welcomed Grzegorz B. Prokopski |
From: Gunda D. <sab...@ho...> - 2002-12-03 21:36:35
|
Hi, I am trying to port sableVM for ARM linux (netwinder). After looking thru the archives, I already made the following changes system.c: iflush and compare_and_swap ported to ARM system.h: The correct typedefs are in place jni_system_specific.h: Necessary changes are done. Am I missing anything else ? Proabably a stupid question, where does the cpu type definitions (e.g. __ia64__) defined ? Is it part of the configure ? Is it in the generated Makefiles ? The reason is that after defining the new cpu type as __arm__ I get a error "unknown system" generated from the jni_system_specific.h file when I try to make. Is there a way to force the build to use a particular target type ? Thanks in advance. An early reply will be appreciated :-) Thanks. -Gunda _________________________________________________________________ STOP MORE SPAM with the new MSN 8 and get 2 months FREE* http://join.msn.com/?page=features/junkmail |
From: Etienne M. G. <eti...@uq...> - 2002-11-22 14:31:57
|
Hi Grzegorz, Regarding the #include <linux/types.h> suggestion. What is the license of <linux/types.h> ? If it is the GPL, then we're ou= t of=20 luck, as it would force us to GPL the whole SableVM code, and probably th= e class=20 libraries too (making the Classpath exception useless). I really hope it= is the=20 LGPL... Did you investigate whether GNU libc had a similar include file? GNU lib= c is=20 LGPLed, and would cause no license related problems. I know, these license things can seem quite annoying, but it's the right = of the=20 copyright holder to determine the license terms on the code they write. Etienne Grzegorz Prokopski wrote: > W li=B6cie z wto, 19-11-2002, godz. 18:23, Grzegorz Prokopski pisze:=20 >=20 >>Hi! >=20 > I was a bit in a hurry, so see the corections below. >=20 > (below paragraph is about already compiled binary version > of sablevm which should survive upgrade of glibc, gcc etc.) >=20 >>It's even more complicated if we link to that symbol and it's >>definition changes. On i386 (and most of the arches) we're >>_staticly_ linked to libgcc2 library (which contains the symbol). >>Thus - we don't have to worry about gcc upgrades etc. >>However on some arches, like m68k >=20 > this lib (libgcc2) is dynamically linked with every program >=20 >>- or so I was told >=20 > =20 >=20 >>I personally would vote that we use this symbol in one of next >>versions, after my old "every arch" patch is applied. >=20 > Not sure yet, but it would be possible to use > #include <linux/types.h> > when available and fallback to autodetection when it fails. >=20 > BTW: I was yet unable to actually test that __clear_cache > function (sorry), because it does nothing for i386 and Bdale > is very busy today so we haven't managed to test that for ia64 > yet :-/ >=20 > (I have assembler version for ia64 ready for another test anyway) >=20 > GBP >=20 >=20 --=20 Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Etienne M. G. <eti...@uq...> - 2002-11-22 05:18:37
|
On Thu, Nov 21, 2002 at 11:54:04PM -0500, Etienne M. Gagnon wrote: > Yes, automating the inlinability flagging would be an interesting > thing to do, but until them , there's a semi-automatic method: What was I thinking! There's a simpler semi-automatic method: 1- Compile SableVM with all debug options. e.g. ./configure --enable-debugging-features 2- Run SableVM with tracing on; sablevm -v -p sablevm.verbose.methods=true -p sablevm.verbose.instructions=true HelloWorld Be ready to see a lot of text. The thing is that it does give you a pretty good idea of where execution stopped. You'll be amazed how much code needs to run just to execute HelloWorld. :) I hope this helps. Etienne -- Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Etienne M. G. <eti...@uq...> - 2002-11-22 05:01:03
|
On Thu, Nov 21, 2002 at 10:54:20PM +0100, Grzegorz Prokopski wrote: > Thanks to Bdale I have some real results now. > Shortly: it doesn't work! >=20 > We tried two versions of _svmf_iflush (for ia64): > 1) > __asm__ __volatile__ ("fc %0;; sync.i;; srlz.i;;" :: "r"(pword)); >=20 > 2) > extern void __clear_cache (char *beg, char *end); > called this way: > __clear_cache((char*) pword, ((char*)pword)+SVM_WORD_SIZE); You might want to try two things: 1- Implement _svmf_iflush as a "complete flush" of *both* data AND instruction caches. 2- To better isolate the problem, it is easiest to test with a very small inline-threaded interpreter, rather than a full JVM. To this end, here is a few useful URLs: a) The paper introducing the original inline-threading technique: http://www-sor.inria.fr/publi/summaries/1998/ODCSI_pldi98.html b) The related small inline-threaded interpreter source code: http://www-sor.inria.fr/~piumarta/pldi98/ Now, if you can get http://www-sor.inria.fr/~piumarta/pldi98/vm.c to work, we'll be in shape to find out if there's any small hidden bugs in SableVM, and/or flag appropriate instructions as "inlineable" or not on ia64. Yes, automating the inlinability flagging would be an interesting thing to do, but until them , there's a semi-automatic method: 1- Do a very small change in SableVM's prepare_code file, to force sablevm to only build inlined sequences of single instructions. 2- Run Java programs exercising most (or ideally all) bytecodes. 3- Use DDD (or gdb...) to extract explicit segfault point, and identify the currently executed bytecode at time of signal. 4- Flag identified bytecode as non-inlineable on ia64. 5- Repeat until all programs run. >=20 > 1.Can you find anything looking at the logs? ( ;-) The segfault really seems happening in inlined code. > 2. FWIK you haven't tested SableVM on any other arch than > i386 with inline threading enabled? If so - how can you be > sure that even if _svmf_iflush does it's work well - it's > enough to get the engine working right in inlined mode? Try the little vm.c program above. I've tried it on SPARC, and it works, indeed. I haven't yet tried SableVM, though. But the only difference between SableVM direct-threading engine and the inline-threaded one, is the dispatch mechanism (e.g. inlined instruction sequences). So, I would suspect that getting vm.c to work would be a first thing to try. > 4. Threading engine on RISC machines. > Once you were explaining me, that you can only inline > parts which don't contain jumps. But if you compare RISC > and CISC arches (in general) - it's quite common that task > which can be done w/o a jump on CISC - can't be done this > way on RISC where a jump is needed. Ain't this affecting > the whole idea of threading engine? Wouldn't that force > us to reviev the code generated by every compiler and for > every single arch to find the pieces we can inline? Yes, we need to review the "inlinable (or not)" property of each bytecode, for every architecture. In reality, this is much simpler than it looks: Most non-inlinable instructions are already identified as such because they can be determined as such just by looking at the C source code. E.g.: NEW, INVOKE*, ... are not inlinable. For the remaining ones, you do as I suggested above. > BTW: in gcc 3.0.4 sources __clear_cache is still there, > w/o visible changes compared to 2.95. So if that's all we > need - we should just use it and go on with other things IMO. We can definitely try it too. Thanks, Etienne --=20 Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Etienne M. G. <eti...@uq...> - 2002-11-22 05:00:39
|
---------- Forwarded message ---------- Date: Thu, 21 Nov 2002 10:49:52 -0500 From: Diti Anastasopoulos <di...@cs...> Subject: [PROFS] Doctoral Oral Defense McGill University School of Computer Science Doctoral Oral SPEAKER: Etienne Gagnon TITLE: A Portable Research Framework for the Execution of Java Bytecode DATE: Thursday, November 28, 2002 TIME: 2:00 p.m. PLACE: McConnell Engineering Building, Room 103 ABSTRACT: Compilation to bytecode paired with interpretation is often used as a technique to easily build prototypes for new programming languages. Some languages, including Java, push this further and use the bytecode layer to isolate programs from the underlying platform. Current state-of-the-art commercial and research Java virtual machines implement advanced just-in-time and adaptive compilation techniques to deliver high-performance execution of Java bytecode. Yet, experimenting with new features such as adding new bytecodes or redesigning the type system can be a daunting task within these complex systems, when new features invalidate assumptions on which the internal dynamic optimizing compiler depends. On the other hand, simpler existing Java bytecode interpreters, written purely in high-level languages, deliver poor performance. The main motivation behind this thesis was to answer the question: How fast can a portable, easily modifiable Java bytecode interpreter be? In order to address this question, we have designed and developed the SableVM research framework, a portable interpreter-based Java virtual machine written in portable C. In this thesis we introduce innovative techniques for implementing an efficient, yet portable Java bytecode interpreter. These techniques address three areas: instruction dispatch, memory management, and synchronization. Specifically, we show how to implement an inline-threaded engine in the presence of lazy code preparation, without incurring a high synchronization penalty. We then introduce a logical partitioning of runtime system memory that simplifies memory management, and a related sparse interface virtual table design for fast interface-method invocation. We show how to efficiently compute space-efficient garbage collection maps for verifiable bytecode. We also present a bidirectional object layout that simplifies garbage collection. Finally, we introduce an improvement to thin locks, eliminating busy-wait in case of contention. Our experiments within the SableVM framework show that inline threading Java delivers significant performance improvement over switch and direct treading, that sparse interface tables cause no memory loss, and that our map computation algorithm delivers a very small number of distinct garbage collection maps. Our overall performance measurements show that, using our techniques, a portable interpreter can deliver competitive interpretation performance, and even surpass that of a less-portable state-of-the-art interpreter on some benchmarks. COMMITTEE: Prof. L. Hendren (Supervisor) Prof. C. Verbrugge Prof. J. Kienzle Prof. F. Ferrie (External member; ECE) Prof. K. Driesen (Chair) ALL ARE WELCOME ----- End forwarded message ----- |
From: Grzegorz P. <ga...@de...> - 2002-11-21 21:56:14
|
Hi! Thanks to Bdale I have some real results now. Shortly: it doesn't work! We tried two versions of _svmf_iflush (for ia64): 1) __asm__ __volatile__ ("fc %0;; sync.i;; srlz.i;;" :: "r"(pword)); 2) extern void __clear_cache (char *beg, char *end); called this way: __clear_cache((char*) pword, ((char*)pword)+SVM_WORD_SIZE); * all build were done with --with-threading=inlined * first build gave this: /usr/lib/sablevm/bin/java -jar ./HelloWorld.jar sablevm: cannot create vm * Bdale rebuilded with --disable-signals-for-exceptions the result was: Segmentation fault but I got strace and dbg output (both attached). Now a few words to Etienne. 1.Can you find anything looking at the logs? ( ;-) 2. FWIK you haven't tested SableVM on any other arch than i386 with inline threading enabled? If so - how can you be sure that even if _svmf_iflush does it's work well - it's enough to get the engine working right in inlined mode? 3. Looking at the backtrace; I'd suspect, that the first address 0x600000000001d410 is where inline engine has put the code for execution but sth. didn't work right. Sth. like the code cache which hadn't been flushed right. 4. Threading engine on RISC machines. Once you were explaining me, that you can only inline parts which don't contain jumps. But if you compare RISC and CISC arches (in general) - it's quite common that task which can be done w/o a jump on CISC - can't be done this way on RISC where a jump is needed. Ain't this affecting the whole idea of threading engine? Wouldn't that force us to reviev the code generated by every compiler and for every single arch to find the pieces we can inline? BTW: in gcc 3.0.4 sources __clear_cache is still there, w/o visible changes compared to 2.95. So if that's all we need - we should just use it and go on with other things IMO. That's all for now. Grzegorz B. Prokopski |
From: Grzegorz P. <ga...@de...> - 2002-11-20 01:19:33
|
W li=B6cie z pi=B1, 15-11-2002, godz. 01:23, Grzegorz Prokopski pisze:=20 > Hi! >=20 > I just uploaded classpath-tools and free-java-sdk. free-java-sdk (and classpath-tools) entered the archive You can get them by simply issuing: apt-get install free-java-sdk It seems that there are people interested in it, as I already got two bugreport on the topic: add Depends on gjdoc | gjdoc-native instead of just on gjdoc. It also reminds me, that gjdoc still doesn't work w/ sablevm. Other, and probably most important problem ATM, is that SableVM can't run programs compiled with current jikes. Etienne - any chances to have this fixed in some near future? 02AM is good time to go to sleep... g'night all GBP |
From: Etienne M. G. <eti...@uq...> - 2002-11-19 22:44:17
|
Hi Grzegorz, You are doing some very interesting work. A simple comment: we will probably need to be ready to fine tune the flushing strategy for specific architectures. Should we act upon the "data" cache or the "instruction" cache, or both, and what is the ideal granularity of this action (single word (or cache line), or general flush), what do we flush (write back buffer only, all entries in the cache, ...). Yep, a lot of fun ahead... The simplest strategy, on the short term, would be a full cache flush ( of both instruction and data caches). As this only happens "once" for each executed method (at the end of method preparation), the simple approach might have no significant impact on the running time, while allowing the inline-threaded engine to work on modern processors. Of course, once we're done with the inline-threaded engine, we will have to attack the multi-processor cache coherency problem... Thanks a lot for this very important work. Etienne On Tue, Nov 19, 2002 at 11:11:41PM +0100, Grzegorz Prokopski wrote: > W li?cie z wto, 19-11-2002, godz. 18:23, Grzegorz Prokopski pisze: > > Hi! > I was a bit in a hurry, so see the corections below. > > (below paragraph is about already compiled binary version > of sablevm which should survive upgrade of glibc, gcc etc.) > > It's even more complicated if we link to that symbol and it's > > definition changes. On i386 (and most of the arches) we're > > _staticly_ linked to libgcc2 library (which contains the symbol). > > Thus - we don't have to worry about gcc upgrades etc. > > However on some arches, like m68k > this lib (libgcc2) is dynamically linked with every program > > - or so I was told > > > I personally would vote that we use this symbol in one of next > > versions, after my old "every arch" patch is applied. > Not sure yet, but it would be possible to use > #include <linux/types.h> > when available and fallback to autodetection when it fails. > > BTW: I was yet unable to actually test that __clear_cache > function (sorry), because it does nothing for i386 and Bdale > is very busy today so we haven't managed to test that for ia64 > yet :-/ > > (I have assembler version for ia64 ready for another test anyway) > > GBP > > -- Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Grzegorz P. <ga...@de...> - 2002-11-19 22:13:24
|
W li=B6cie z wto, 19-11-2002, godz. 18:23, Grzegorz Prokopski pisze:=20 > Hi! I was a bit in a hurry, so see the corections below. (below paragraph is about already compiled binary version of sablevm which should survive upgrade of glibc, gcc etc.) > It's even more complicated if we link to that symbol and it's > definition changes. On i386 (and most of the arches) we're > _staticly_ linked to libgcc2 library (which contains the symbol). > Thus - we don't have to worry about gcc upgrades etc. > However on some arches, like m68k this lib (libgcc2) is dynamically linked with every program > - or so I was told =20 > I personally would vote that we use this symbol in one of next > versions, after my old "every arch" patch is applied. Not sure yet, but it would be possible to use #include <linux/types.h> when available and fallback to autodetection when it fails. BTW: I was yet unable to actually test that __clear_cache function (sorry), because it does nothing for i386 and Bdale is very busy today so we haven't managed to test that for ia64 yet :-/ (I have assembler version for ia64 ready for another test anyway) GBP |
From: Grzegorz P. <ga...@de...> - 2002-11-19 17:41:44
|
Hi! I have spent most of today's day searching for ways to flush instruction cache in any more portable way, than writing the "right" assembler for every arch. Here's what I found out. There's no exported and usable interface for this in neither glibc nor gcc nor kernel headers, nor linux headers (/usr/include/linux, /usr/include/asm). There were such proposals, but none of them resulted in anything usable by us. From our POV we need simply a function flush_icache_range(void *from, int len), where len is same as word size for current arch. However be warned, that this function not that simple for some architectures and may require kernel function call for ex. Other problem is that it's sometime cheaper to clear all of the cache than flushing specific part (don't ask me, that's what I found in gcc sources). So if we don't want to implement needed assembler/other not-that-nice-and-clean things ourselves for every arch we want to support "inlined" engine on - we have only one solution (it seems). We need to link to __clear_cache symbol that comes from gcc. It's GPL symbol, but with exception for when the usage of it is because of gcc usage - so we fall under this anyway. The upside is that we can simply define: extern void __clear_cache (char *beg, char *end) and just use it. The downside is that - this is internal symbol and as such may be subject to change w/o prior notoice (not saying anything about backward compatibility) - it's only portable across arches where we use gcc (not that big problem ATM anyway) It's even more complicated if we link to that symbol and it's definition changes. On i386 (and most of the arches) we're _staticly_ linked to libgcc2 library (which contains the symbol). Thus - we don't have to worry about gcc upgrades etc. However on some arches, like m68k - or so I was told. Upside once again: - I doubt the symbol will change in some dramatical way. In such case we could either reflect the change in our code or - we can always disable "inlined" engine for selected arches (until a fix/other solution is found) but still support them. I personally would vote that we use this symbol in one of next versions, after my old "every arch" patch is applied. What do you think? Grzegorz B. Prokopski |
From: Grzegorz P. <ga...@de...> - 2002-11-15 06:41:17
|
Hi! I just uploaded classpath-tools and free-java-sdk. [ they should get into archive in about a week if ftpmasters find no showstoppers in them ] The latter uses SableVM as it's main JVM and provides JAVA_HOME type environment in /usr/lib/fjsdk greg@greg:~$ ls -al /usr/lib/fjsdk/bin razem 16 drwxr-xr-x 2 root root 288 2002-11-15 00:36 . drwxr-xr-x 5 root root 120 2002-09-06 11:03 .. -rw-r--r-- 1 root root 288 2002-11-15 00:33 ABOUT.txt lrwxrwxrwx 1 root root 20 2002-11-15 00:36 jar -> ../../../bin/fastjar lrwxrwxrwx 1 root root 22 2002-11-15 00:36 java -> ../../sablevm/bin/java -rwxr-xr-x 1 root root 306 2002-11-15 00:33 java-alt-setup -rwxr-xr-x 1 root root 254 2002-11-15 00:33 javac lrwxrwxrwx 1 root root 26 2002-11-15 00:36 javadoc -> ../../../bin/javadoc-gjdoc lrwxrwxrwx 1 root root 21 2002-11-15 00:36 javah -> ../../../bin/javah-cp lrwxrwxrwx 1 root root 21 2002-11-15 00:36 javap -> ../../../bin/javap-cp lrwxrwxrwx 1 root root 25 2002-11-15 00:36 serialver -> ../../../bin/serialver-cp I belive it's a set of very basic programs that SableVM should run. I rebuilded gjdoc w/ jikes 1.15, but couldn't get it working too: greg@greg:~/deb-pkgs/classpath-tools$ javadoc-gjdoc java.lang.NoClassDefFoundError: [Ljava/lang/String; at java.lang.ClassLoader.createArray(ClassLoader.java:417) at java.lang.ClassLoader.createArray(ClassLoader.java:340) at java.lang.Class.forName(Class.java:309) at java.lang.Class.forName(Class.java:268) at gnu.classpath.tools.gjdoc.Main.class$(Main.java) at gnu.classpath.tools.gjdoc.Main.startDoclet(Main.java:298) at gnu.classpath.tools.gjdoc.Main.start(Main.java:780) at gnu.classpath.tools.gjdoc.Main.main(Main.java:678) at java.lang.VirtualMachine.invokeMain(VirtualMachine.java) at java.lang.VirtualMachine.main(VirtualMachine.java:88) [ thanks to gcj we could probably use native version for now ] I'll drop a note as soon as the packages effectively enter the archive. Cheers, Grzegorz B. Prokopski PS: All mentioned packages are availabe at: http://debian.sente.pl/debian until they enter the archive. You should use dpkg-alternatives or /usr/lib/fjsdk/bin/java-alt-setup to set /usr/bin/java to /usr/lib/sablevm/java to get the resto of the tools working. PSS: Bdale confirmed that SableVM now works on IA64. He also builded and uploaded packages for ia64. |
From: Archie C. <ar...@de...> - 2002-11-15 06:27:21
|
Here's a patch to fix a problem with Runtime.nativeLoad(). The problem is that if the dlopen() operation fails, the error message is lost. This caused me a lot of head scratching the other day trying to figure out why something wasn't working. With this patch the underlying error message (from lt_dlerror()) will appear in the Exception message string. Thanks, -Archie __________________________________________________________________________ Archie Cobbs * Packet Design * http://www.packetdesign.com --- sablevm-class-library-1.0.5/src/java/lang/Runtime.java.orig Thu Nov 14 16:52:41 2002 +++ sablevm-class-library-1.0.5/src/java/lang/Runtime.java Thu Nov 14 16:51:11 2002 @@ -629,8 +629,10 @@ SecurityManager sm = securityManager; // Be thread-safe! if (sm != null) sm.checkLink(filename); - if (nativeLoad(filename) == 0) - throw new UnsatisfiedLinkError("Could not load library " + filename); + String errmsg = nativeLoad(filename); + if (errmsg != null) + throw new UnsatisfiedLinkError("Could not load library " + filename + + ": " + errmsg); } /** @@ -747,9 +749,9 @@ * already been mapped to a true filename. * * @param filename the file to load - * @return 0 on failure, nonzero on success + * @return error message on failure, null on success */ - private native int nativeLoad(String filename); + private native String nativeLoad(String filename); /** * Map a system-independent "short name" to the full file name, and append --- sablevm-1.0.5/src/libsablevm/java_lang_Runtime.h.orig Thu Nov 14 17:08:12 2002 +++ sablevm-1.0.5/src/libsablevm/java_lang_Runtime.h Thu Nov 14 17:07:27 2002 @@ -93,9 +93,9 @@ /* * Class: java_lang_Runtime * Method: nativeLoad - * Signature: (Ljava/lang/String;)I + * Signature: (Ljava/lang/String;)Ljava/lang/String; */ - JNIEXPORT jint JNICALL Java_java_lang_Runtime_nativeLoad + JNIEXPORT jstring JNICALL Java_java_lang_Runtime_nativeLoad (JNIEnv *, jobject, jstring); /* --- sablevm-1.0.5/src/libsablevm/java_lang_Runtime.c.orig Thu Nov 14 16:56:03 2002 +++ sablevm-1.0.5/src/libsablevm/java_lang_Runtime.c Thu Nov 14 17:11:15 2002 @@ -166,16 +166,17 @@ /* * Class: java_lang_Runtime * Method: nativeLoad - * Signature: (Ljava/lang/String;)I + * Signature: (Ljava/lang/String;)Ljava/lang/String; */ -JNIEXPORT jint JNICALL +JNIEXPORT jstring JNICALL Java_java_lang_Runtime_nativeLoad (JNIEnv *_env, jobject this, jstring _filename) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_JavaVM *vm = env->vm; - jint result = 0; + const char *errmsg = "unknown error"; + jstring result = NULL; _svmf_resuming_java (env); @@ -207,6 +208,7 @@ if (handle == NULL) { + errmsg = lt_dlerror(); _svmm_gfree_utf_chars (filename); goto end; } @@ -215,7 +217,7 @@ { if (native_library->handle == handle) { - result = 1; + errmsg = NULL; _svmm_gfree_utf_chars (filename); goto end; } @@ -257,7 +259,7 @@ class_loader_info->native_library_list_tail = &(*(class_loader_info->native_library_list_tail))->next; - result = 1; + errmsg = NULL; end: @@ -272,6 +274,14 @@ { goto end; } + } + + if (errmsg != NULL) + { + /* as we do nothing else after, we can safely ignore the return + value (any exception being also set in the environment) */ + result = _svmf_get_jni_frame_native_local (env); + _svmf_get_string (env, errmsg, result); } } |
From: Etienne M. G. <eti...@uq...> - 2002-11-14 22:21:10
|
Grzegorz Prokopski wrote: > 1.0.5 works well, the auto* build problems seem to be solved > the only problem is - you have to use jikes 1.15 (not 1.17) I am currently working on the Jikes 1.17 related problem. It seems relatively simple to solve, but I have to experiment a little to see if it uncovers any other changes in 1.17 that "tests SableVM's limits" (wasn't this said nicely; I should become a politician;-) > > Hmm... I think I am gonna open a wine and celebrate 8) > Go ahead! :-) Etienne > Grzegorz B. Prokopski > > > > -- Etienne M. Gagnon http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Grzegorz P. <ga...@de...> - 2002-11-14 22:09:14
|
W li=B6cie z czw, 17-10-2002, godz. 02:49, Etienne M. Gagnon pisze:=20 > Hi Grzegorz, >=20 > I have made the 1.0.5 release, paying much attention to make as clean > a build as possible (running all of the auto* stuff on a clean source > tree). Can you check if you still get the Debian build problems with > this version? >=20 > If you still get these problems, then you'll have to tell me exactly > about how you build your package. I guess I'll also have to learn > about the Debian build procedures. I already mailed Etienne the answer along with other mail, but just so that everybody knew... 1.0.5 works well, the auto* build problems seem to be solved the only problem is - you have to use jikes 1.15 (not 1.17) 1.0.5 supports 3 architectures: i386, alpha and ia64 As we're at multiarch support.... I'd like to see my one-for-all-arches patch integrated in some further release (I hope Etienne hasn't change his mind). But it won't make much sense if we're not able to test the beast. I think seriously about some automated test suite that could give us some results about how well sablevm works on every (wannabe) supported arch. (We should hear soon if it really works on ia64) It seems that nobody tested in on alpha so far (else - we'd already have bugreports, because alpha port builded by autobuilders was unusable due to problems with autotools usage in sablevm). I am gonna ITP: sablevm-testsuite now. For now it will consist of three tests: - HelloWorld (should always work) - TestAWT (doesn't work ATM) - TestSwing (doesn't work ATM) I already ITPed mauve test suite, but I don't think we really need such big mechinery yet when there are very visible and well known bugs (or rather missing features). Hmm... I think I am gonna open a wine and celebrate 8) Grzegorz B. Prokopski |
From: Archie C. <ar...@de...> - 2002-11-14 02:30:03
|
Archie Cobbs wrote: > I'm trying to run a Java program that uses AWT stuff, which of course > requires loading the libgnu-java-awt-peer-gtk-1.0.5 native library. > Although other native libraries load fine, this one does not, and the > error seems to happen within libtool itself. > > Any ideas why lt_dlopen() would fail when given a valid filename that > points to a valid shared object file? Nevermind.. this seems to be the problem: dlopen: /usr/local/lib/sablevm/libgnu-java-awt-peer-gtk-1.0.5.so: Undefined symbol "gdk_threads_mutex" Is this GTK stuff supposed to work yet? Thanks, -Archie __________________________________________________________________________ Archie Cobbs * Packet Design * http://www.packetdesign.com |
From: Archie C. <ar...@de...> - 2002-11-14 02:00:06
|
Hi, I'm trying to run a Java program that uses AWT stuff, which of course requires loading the libgnu-java-awt-peer-gtk-1.0.5 native library. Although other native libraries load fine, this one does not, and the error seems to happen within libtool itself. Any ideas why lt_dlopen() would fail when given a valid filename that points to a valid shared object file? Running 'ktrace' shows sablevm successfully opening the shared object and reading the first page of it, but lt_dlopen() still returns NULL. A GDB trace is below. Thanks, -Archie __________________________________________________________________________ Archie Cobbs * Packet Design * http://www.packetdesign.com (gdb) break Java_java_lang_Runtime_nativeLoad Breakpoint 2 at 0x280d0404: file java_lang_Runtime.c, line 176. (gdb) c Continuing. ... [verbose class: loading "java/awt/EventQueue"] [verbose class: loading "java/awt/AWTEvent"] [verbose class: loading "java/util/EventObject"] [verbose class: creating "[Ljava/awt/AWTEvent;"] [verbose class: loading "java/awt/EventDispatchThread"] [verbose class: loading "java/lang/Thread"] [verbose class: loading "java/lang/Runnable"] [verbose class: loading "java/lang/ThreadGroup"] [verbose class: loading "java/lang/InheritableThreadLocal"] [verbose class: loading "java/lang/ThreadLocal"] [verbose class: loading "java/util/ArrayList"] loading gtkpeer Breakpoint 2, Java_java_lang_Runtime_nativeLoad (_env=0x8061200, this=0x919a0f0, _filename=0x919a0d0) at java_lang_Runtime.c:176 176 _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); (gdb) n 177 _svmt_JavaVM *vm = env->vm; (gdb) 178 jint result = 0; (gdb) 180 _svmf_resuming_java (env); (gdb) 184 _svmt_class_loader_info *class_loader_info = (gdb) 186 _svmt_native_library *native_library = (gdb) 189 jboolean monitor_acquired = JNI_FALSE; (gdb) 191 if (_svmf_enter_object_monitor (gdb) 199 monitor_acquired = JNI_TRUE; (gdb) 201 if (_svmm_galloc_utf_chars (env, _filename, filename) != JNI_OK) (gdb) 206 handle = lt_dlopen (filename); (gdb) p filename $1 = 0x8062500 "/usr/local/lib/sablevm/libgnu-java-awt-peer-gtk-1.0.5.so" (gdb) n 0x2806ac54 in _init () from /usr/local/lib/libsablevm.so.1 (gdb) Single stepping until exit from function _init, which has no line number information. Java_java_lang_Runtime_nativeLoad (_env=0x8061200, this=0x919a0f0, _filename=0x919a0d0) at java_lang_Runtime.c:208 208 if (handle == NULL) (gdb) 210 _svmm_gfree_utf_chars (filename); (gdb) p handle $2 = 0x0 (gdb) quit The program is running. Exit anyway? (y or n) y $ file /usr/local/lib/sablevm/libgnu-java-awt-peer-gtk-1.0.5.so /usr/local/lib/sablevm/libgnu-java-awt-peer-gtk-1.0.5.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (FreeBSD), not stripped $ ls -l /usr/local/lib/sablevm/libgnu-java-awt-peer-gtk-1.0.5.so -rwxr-xr-x 1 root wheel 418905 Nov 13 15:45 /usr/local/lib/sablevm/libgnu-java-awt-peer-gtk-1.0.5.so* |
From: Grzegorz P. <gr...@se...> - 2002-10-26 23:26:38
|
W li=B6cie z czw, 24-10-2002, godz. 20:23, Etienne M. Gagnon pisze:=20 > Hi Folks, >=20 > On Wed, Oct 16, 2002 at 01:27:45PM +0200, Grzegorz Prokopski wrote: > > I may be wrong - but it seems that there's something wrong w/ > > createArray? So it is rather gnu classpath related problem not > > SableVM? >=20 > I was running some experiments, and I noticed that SableVM seemed > broken; it wouldn't run the SPECjvm benchamrks anymore! (Complaining > about the missing nativeCreateArray). >=20 > So, after investigation, I finally found the problem: Jikes 1.17 > generates internal class bytecodes which make these invocations, > whereas Jikes 1.15 doesn't. I installed 1.15 jikes for testing and... gjdoc works (at least help shows) only IF libgcj.jar is in the classpath! Else - the previous error appears! > Of course, I'll have to fix SableVM to implement the > nativeCreateArray... On my TODO list (getting pretty long). I think that using jikes 1.15 for gjdoc compilation didn't really solve this problem. GBP PS: Hmm... I just thought that maybe recompilation of sablevm-classlib with jikes 1.15 can help. I won't check it ATM. I will be uploading gjdoc into unstable anyway. (there's always gcj arch-specific version available - thanks to Mark Howard <mh...@ti...> ) |