From asqueaker at gmail.com Wed Oct 1 01:42:13 2014 From: asqueaker at gmail.com (Chris Muller) Date: Wed Oct 1 01:42:15 2014 Subject: [squeak-dev] startup time command line (or dropped files) arguments In-Reply-To: <68822DF1-D934-4532-86DF-4868115D78FF@rowledge.org> References: <68822DF1-D934-4532-86DF-4868115D78FF@rowledge.org> Message-ID: Don't "reel in horror" drama-boy. Squeak's command-line processing is simple and effective. I use it heavily every day. As you know, you can just pass in your arguments into the command-line like this: squeak my.image arg1 arg2 arg3 & Normally, "arg1" is the name of a .st script you would like to execute, while arg2 and arg3 are arguments to that script. This is useful when you want to give the image instructions from a file in the OS. Normally, the .st script would contain something like the following: Smalltalk runAndQuit: [ : arg2 : arg3 | "Do something. arg2 and arg3 are the Strings from the command-line." ] After executing the block, the image will exit without saving. That is useful for batch applications but if you want to launch a server or something interactive where the user invokes the exit, you could simply use Smalltalk #run: instead of #runAndQuit:. There may be another case where you want to "build" an image and want it to save. There's one for that too. I personally like the Smalltalk #run... API because it handles all the Notifications, Warnings, SyntaxErrors and Errors the way I like (by logging them to stdout and stderr) but you don't /have/ to use that if you don't want. You can always check "Smalltalk argumentAt: anInteger" to simply obtain the command-line arguments as Strings. There are advanced cases where you may not want the first argument to be the name of a script. For those you can unset preference "readDocumentAtStartup". On Tue, Sep 30, 2014 at 1:12 PM, tim Rowledge wrote: > How are command line arguments intended for the image supposed to be dealt with these days? It?s an awfully long time since last I looked at this area and the code I?m seeing in the image is? convoluted. > > I need to be able to handle some simple cases for Scratch startup and we seem to have completely changed how that area is handled. I have come across (and reeled in horror) code in ProjectLauncher, AutoStart etc but so far I don?t see anything to make it all make sense in my head. I don?t suppose anybody knows of a correct wiki page? Not found one so far. > > Maybe I need to drop one or more of the current startup related classes and write a ScratchStart class? > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Programmer: One who is too lacking in people skills to be a software engineer. > > > From lewis at mail.msen.com Wed Oct 1 01:49:10 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 1 01:49:13 2014 Subject: [squeak-dev] startup time command line (or dropped files) arguments In-Reply-To: <19E4A7EE-A8B0-4FD8-B968-61C9A443C87D@rowledge.org> References: <68822DF1-D934-4532-86DF-4868115D78FF@rowledge.org> <20140930221654.GA61006@shell.msen.com> <19E4A7EE-A8B0-4FD8-B968-61C9A443C87D@rowledge.org> Message-ID: <20141001014910.GA84450@shell.msen.com> On Tue, Sep 30, 2014 at 03:56:13PM -0700, tim Rowledge wrote: > > On 30-09-2014, at 3:16 PM, David T. Lewis wrote: > > > On Tue, Sep 30, 2014 at 10:29:20PM +0200, Nicolas Cellier wrote: > >> > >> A good soul should take a look at Pharo and pick the good bytes from there > >> > > > > Good idea to take a look at the Pharo handling. > > > Yes, indeed. > > > But I think the Squeak handling > > has been pretty much unchanged for quite a while and it does still work. I'm > > using a unix VM, and there may be some platform differences, but the basic idea > > is that any command line parameters intended for the VM will be handled by the > > VM, and you then specify image name followed by document name followed by > > any other parameters that you may want to pass along to the image. The first > > thing after the image name is treated as a startup document, so that needs to > > be present if you intend to also pass along some other parameters. The remaining > > parameters are available to the image (evaluate "Smalltalk arguments"). Thus you > > can do something like this: > > > > $ /usr/local/bin/squeak -vm-sound-pulse myImage.image myStartupDocument.st param1 param2 param3 > > > > The arguments #('param1' 'param2' 'param3') will be available for use in your > > myStartupDocument.st start script. > > That?s what I thought would be the case. It seems a bit more complex though since some attempted testing dropped me into a problem with AutoStart (which does some fairly involved reading and fiddling with any arguments) passing on to ProjectLauncher>startUp >>>startUpAfterLogin which seems to want to treat any words in the commandline as filepaths and then use a CodeLoader to read them in. For example,` {vm} scratch.image fooble` fails part way through starting up because of an attempt to load `file:///home/pi/Scratch/fooble`. > AutoStart is in the startup list. It has no class comment (WTF?!? Why not?). But it looks like it maintains a registry of launchers that presumably are intended to implement code loaders at image startup time. It further obfuscates the situation by invoking #startUp on the classes in its registry, as if they had been in the startup list, even though they are not in the starup list, and even though nobody could be bothered to document this in a class comment. Happily, class AbstractLauncher does have an excellent comment (yay!) that explains what is going on, and one of its two concrete subclasses also has a comment. The other subclass is the one that we actually use in the registry (ProjectLauncher), so naturally it does not have a class comment. That said, one might reasonably guess that the undocumented class ProjectLauncher that is invoked by the undocumented class AutoStart might very well be the thing thing that is producing the unexpected behavior that is causing problems for Scratch invocation. I have not tried this, but I am guessing that "AutoStart removeLauncher: ProjectLauncher" might disable the unwanted document loading from the command line handling. Or perhaps, and here I am just guessing again, "AutoStart active: false" might just disable the whole thing entirely, which is possibly what you want for the Scratch loading. > Scratch expects (and this is documented old stuff that people appear to rely upon so I can?t easily change it, probably) to be able to do `{vm} scratch.image presentation fullscreen myProject.sb` and to get presentation and fullscreen as sort of keywords and the *.sb as a project filename. > A perfectly sensible expectation. > As an aside I see that the class ProjectLauncher is only referenced in InstallerCruft class>>classProjectLauncher and InstallerCruft is not referenced at all. And I can?t find any actual code that installs it in AutoStart?s very short list of `InstalledLaunchers` so just possibly it isn?t supposed to be there any more? > I don't actually think it's crufty at all, despite my commentary above. The class comment for InstallerCruft looks a bit crufty in its own right. What *does* seem to be missing is a comment for ProjectLauncher and for AutoStart, as well as a class initialization method somewhere that sets up the registery of launchers in AutoStart. If you do decide to implement a startUp loader specifically for Scratch, you would probably want to implement it as a subclass of AbstractLauncher, and register it in the AutoStart registry. Dave From asqueaker at gmail.com Wed Oct 1 01:55:36 2014 From: asqueaker at gmail.com (Chris Muller) Date: Wed Oct 1 01:55:39 2014 Subject: [squeak-dev] re: Running Squeak on Mac OS X fails due to damaged file. In-Reply-To: References: <7356846D-4740-49F0-912E-AD69CABC1C1F@henrikaagaard.com> <67B583A8-8F58-4766-B6B0-FD359A968AA0@henrikaagaard.com> <35E9640E-AA61-4EDB-80C0-C20E1CA59A6F@gmx.de> <9861A0D3-699A-486C-9F7A-75705AF9FA78@henrikaagaard.com> <092A0363-9509-4068-91EA-C26B98958433@henrikaagaard.com> <9008C066-7764-485A-A331-A3820BC0096A@freudenbergs.de> <553EAE8C-8A96-44BB-8A5B-3CE193F10FCF@gmx.de> <85FA282A-CAF6-4DBA-8B05-FB3EE608011F@gmx.de> Message-ID: On Mon, Sep 29, 2014 at 6:26 PM, Craig Latta wrote: > > Hoi Tobias-- > >> Probably Craig can [check the Mac signature on the current release of >> the Squeak 4.5 app]. Craig? > > Hm, yes, that Gatekeeper error is what you get when Gatekeeper is > turned on and allows apps signed by identified developers, but the app > signature doesn't correspond to the contents. The manual Gatekeeper > override (opening the app from the menu get by control-clicking or > right-clicking) doesn't work. The only way to open such an app is to > turn Gatekeeper off. However, after the first time you open it, you can > always open it, regardless of Gatekeeper's state after that. See [1]. > > Just when all that seems intelligible (albeit annoying), there's a > new wrinkle with Mac OS 10.9.5. Oh joy! :) Apparently you can no longer > have arbitrary things (like super-evil malicious code, or super-helpful > documentation) floating around the app folder tree outside the > "Resources" folder. I had to move all that stuff (in this case, the > host-dependent-but-non-Macish code and resources) before I could sign it > again. This is a big problem for the All-In-One. The purpose of the All-In-One is to be *accessible* to the widest possible audience. This new structure makes it not very user-friendly for new Squeak users using Windows or Linux. Before, everything was in the root folder, and Windows users would recognize "squeak.exe" while Linux users would recognize "squeak.sh". Mac users had whatever they needed. Now, are you saying those folks are supposed navigate down into the ./Squeak-4.5-All-in-One.app/Contents/hostDependentNonMac directory to look for the executable and .sh file? Wait, I'm not seeing squeak.sh at all anywhere.. We probably need to discuss this. I'm not sure I understand the point of an All-In-One that is as hard for a new user to figure out as simply downloading the individual pieces or maybe 3 separate downloads one per OS or maybe just go back to the old All-In-One format but call it Windows/Linux make Mac separate..? > > I imagine there will be differing opinions about where that stuff > should go and what it should be called, but in the meantime I made a > choice, fixed the start.sh script for Linux, signed the app, and put it > at [2]. > > > thanks, > > -C > > [1] http://support.apple.com/kb/ht5290 > [2] http://bit.ly/1CBwx1I (Dropbox) > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > From craig at netjam.org Wed Oct 1 11:19:38 2014 From: craig at netjam.org (Craig Latta) Date: Wed Oct 1 11:19:53 2014 Subject: [squeak-dev] re: Running Squeak on Mac OS X fails due to damaged file. In-Reply-To: References: <7356846D-4740-49F0-912E-AD69CABC1C1F@henrikaagaard.com> <67B583A8-8F58-4766-B6B0-FD359A968AA0@henrikaagaard.com> <35E9640E-AA61-4EDB-80C0-C20E1CA59A6F@gmx.de> <9861A0D3-699A-486C-9F7A-75705AF9FA78@henrikaagaard.com> <092A0363-9509-4068-91EA-C26B98958433@henrikaagaard.com> <9008C066-7764-485A-A331-A3820BC0096A@freudenbergs.de> <553EAE8C-8A96-44BB-8A5B-3CE193F10FCF@gmx.de> <85FA282A-CAF6-4DBA-8B05-FB3EE608011F@gmx.de> Message-ID: > Now, are you saying those folks are supposed navigate down into the > ./Squeak-4.5-All-in-One.app/Contents/hostDependentNonMac directory to > look for the executable and .sh file? Well, getting them into .../Contents seems plausible, because it's the only place to go from the root. (Of course I think it's silly that Apple won't even let me put a README there, but it's still tolerable.) >From there, getting them into a directory with a suitably-obvious name seems reasonable (perhaps "LinuxAndWindows" is sufficient, to go with its sibling "MacOS"). We could put a README in .../Contents as well, explaining how to start Squeak in detail (all three sentences of it :). I did these things and updated the signed app[1]. Not sure how squeak.sh got left out before, as I did test on Linux; sorry. Here's hoping that the signing process, the zipping process, and the Dropbox-upload-and-download process aren't messing with shell script files. :) Personally, I still prefer the all-in-one approach. I think it's still accessible for new users (that's the feedback I get from new users, anyway). I think separate downloads actually become more complicated for both new users and the maintainers over time. Each "per-platform" artifact effectively becomes a multi-platform effort anyway, as each host platform becomes multiple platforms unto itself (to support different versions of the host OS, e.g., Windows 7 vs. Windows 8, 32-bit vs. 64-bit, etc.). It ends up resulting in more choices for new users to get wrong, and more structure for the hosting maintainers to get wrong. Users lose the significant convenience of having a single artifact to take between platforms. I actually do meet new users who care about platform portability. We can also make the Squeak app manage multiple user images, so users need not have multiple copies of the Squeak app around just to run multiple images, nor need to understand any conventions about the Resources folder. That makes having a single artifact that can move between platforms even more valuable. The web-based launcher in Spoon is my approach to that; I'm writing the next version of it now. thanks again, -C [1] http://bit.ly/1CBwx1I -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From craig at netjam.org Wed Oct 1 11:27:14 2014 From: craig at netjam.org (Craig Latta) Date: Wed Oct 1 11:27:27 2014 Subject: [squeak-dev] re: startup time command line (or dropped files) arguments In-Reply-To: References: <68822DF1-D934-4532-86DF-4868115D78FF@rowledge.org> Message-ID: Tim> I need to be able to handle some simple cases for Scratch Tim> startup and we seem to have completely changed how that area is Tim> handled. I have come across (and reeled in horror) code in Tim> ProjectLauncher... Chris> Don't "reel in horror" drama-boy. Mmm, coffee... it's always too much (Tim) or not enough (Chris)! :) -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From list at afceurope.com Wed Oct 1 15:20:52 2014 From: list at afceurope.com (Annick Fron) Date: Wed Oct 1 15:20:59 2014 Subject: [Vm-dev] [squeak-dev] Maintainer of FFI-Package In-Reply-To: References: <20140928130459.GA61160@shell.msen.com> <20140928194459.GA24269@shell.msen.com> <73FF9DFA-FE09-4B7C-A4E5-5804704E20F4@afceurope.com> Message-ID: <30DFAB93-2E07-43BB-82EB-40DB685EC43C@afceurope.com> Hi Eliot, The error I get is ? bad argument ? on the primitive call. Another question : why Alien newC: has dataSize 8 bits ? is it for 64 bits architectures ?? Le 30 sept. 2014 ? 20:38, Eliot Miranda a ?crit : > Hi Annick, > > On Mon, Sep 29, 2014 at 5:30 AM, Annick Fron wrote: > Hi, > > > I have recently made some experiments with pharo and FFI, and I have ran into problems with callbacks. > I am using linux 32 bits. > First question : when calling a dynamic library is it necessary that it exports all symbols ? What if symbols are noted ? U ? (undefined) ? > > If you have undefined symbols in an external library, they need to be resoled by the VM or other libraries loaded in the system. If any are not resolved the library will fail to load. > > 2) On one of my callbacks got the message ? callback failed to own the VM ? . Have you any idea of where it comes from ? > > Yes. This means you're trying to callback from a different thread than the VM thread. hat isn't supported yet. > > 3) If the callback is called in a different thread, is it a problem ? > > Yes. > > 4) On Pharo I have an error on the following : is it incorrect ? It is a 64 bits problem ? > Using FFI Linux examples. > > testGetOurWindowLocation > "self new testGetOurWindowLocation" > > | display ourWindow aParent anX anY aWidth aHeight aBorderWidth aDepth | > display := X11Display XOpenDisplay: nil. > ourWindow := display ourWindow. > (Alien lookup: 'XGetGeometry' inLibrary: 'X11') > primFFICallResult: nil > withArguments: > {display. > ourWindow. > (aParent := Alien new: 4). > (anX := Alien new: 4). > (anY := Alien new: 4). > (aWidth := Alien new: 4). > (aHeight := Alien new: 4). > (aBorderWidth := Alien new: 4). > (aDepth := Alien new: 4)}. > (anX unsignedLongAt: 1) inspect > > What's the error you get? > > Annick > Le 28 sept. 2014 ? 21:44, David T. Lewis a ?crit : > > > On Sun, Sep 28, 2014 at 09:04:59AM -0400, David T. Lewis wrote: > >> > >> On Sun, Sep 28, 2014 at 11:19:30AM +0200, Nicolai Hess wrote: > >>> Who is the maintainer of the FFI-Package for > >>> Squeak and/or Pharo ? > >>> I especially interested in the FFI-Unix examples > >>> and the state on working FFI on linux for current squeak release > >>> (AFAIK it does not work with "squeak all in one" 4.5) > >>> > >> > >> The FFI package, including the FFI-Unix examples that you mention, is at > >> http://source.squeak.org/FFI. > >> > >> The primary author was Andreas Raab. Eliot Miranda is the most recent > >> contributor, and he is probably the most knowledgeable in this area. > >> Currently, the Squeak core developers (those with commit rights to Squeak > >> trunk) have commit rights to the FFI project, and can make updates as needed. > >> > >> The FFI examples for Unix work with the old FFI plugin, which is still > >> present in the interpreter VM. The active development of Squeak FFI is > >> taking place in Cog, and I'm not sure if the old FFI examples work with > >> the newer plugins (which would be present in the Squeak all-in-one). > >> The FFI plugin in the interpreter VM (i.e. trunk VMMaker) needs to be > >> updated, and presumably the FFI examples may need some updates as well. > > > > A small but important correction: For the old plugin (currently in the > > interpreter VM), FFI works only for a 32-bit VM. It also works for a 64-bit > > VM, but only if the patches in http://bugs.squeak.org/view.php?id=7237 have > > been applied (in other words, if you compiled it yourself and included > > those patches). > > > > This is mainly of historical interest, although it is possible that some > > of the 64-bit patches will prove helpful for the newer FFI plugin. But > > the emphasis now should be on Eliot's more recent FFI work. > > > > Dave > > > > > > > > > > -- > best, > Eliot > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141001/dcca2158/attachment.htm From stephan at stack.nl Wed Oct 1 15:40:39 2014 From: stephan at stack.nl (Stephan Eggermont) Date: Wed Oct 1 15:40:41 2014 Subject: [squeak-dev] Re: Status of PostgresV3 Message-ID: <72FBA18A-B9D7-4F57-B77F-83A5A75B9F1D@stack.nl> >(YourConnectionPool default executeQuery: ?select 3 + 4?) > first ? a query may returns multiple result sets, now we select the first ? > rows ? we request the rows of the result set ? > first ? then the first row ? > first ? and the first column, this returns the number 7 ? I can get the results back and inspect them. Pg3Row doesn't understand first. If I use a rowsWithColumnNameDictionary, I get an interesting column name: #'?column?' Is that default postgres behavior, or a textconverter issue? Stephan -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141001/722e8b40/attachment.htm From stephan at stack.nl Wed Oct 1 16:07:53 2014 From: stephan at stack.nl (Stephan Eggermont) Date: Wed Oct 1 16:07:56 2014 Subject: [squeak-dev] Re: Status of PostgresV3 Message-ID: <05F2BCFD-5D74-437A-8211-13E6FE69ED4B@stack.nl> >YourSchemaMirror class >> schema > > ^?schema_name? > >Schema mirrors mirror the functions in your database and provide an interface to call them. There is a little tool to inspect the >differences between the methods of the schema mirror and the functions in the database, which can be invoked by: > >YourSchemaMirror browseChanges The default schema that was created is 'public'. When trying to browseChanges on that, I get back a 'function array_accum(text) does not exist' in a Pg3ErrorResponse. (Postgres 9.3.5 on Mac 10.7.5) Stephan -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141001/f0a63596/attachment.htm From casey.obrien.r at gmail.com Wed Oct 1 16:40:42 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Wed Oct 1 16:40:45 2014 Subject: [squeak-dev] Has anyone got a BASIC handy? Message-ID: Found myself waxing romantic over this? http://www.atariarchives.org/basicgames/index.php First thought was "I'll just throw something together" but I wondered if anyone had done a BASIC for Squeak? TIA, Casey P.S. Google didn't help me with this one. It seemed to think I meant "basic squeak" no matter how I typed it in. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141001/048eac28/attachment.htm From craig at netjam.org Wed Oct 1 17:36:20 2014 From: craig at netjam.org (Craig Latta) Date: Wed Oct 1 17:36:26 2014 Subject: [squeak-dev] re: Has anyone got a BASIC handy? In-Reply-To: References: Message-ID: > Found myself waxing romantic over this? > > http://www.atariarchives.org/basicgames/index.php > > First thought was "I'll just throw something together" but I wondered > if anyone had done a BASIC for Squeak? Maybe Carl Gundel has thoughts about it? Pre-Squeak, he wrote Liberty BASIC in Smalltalk. I'm sure you came across it in your Googling, but just in case... https://en.wikipedia.org/wiki/Liberty_BASIC -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From leves at elte.hu Wed Oct 1 17:55:57 2014 From: leves at elte.hu (Levente Uzonyi) Date: Wed Oct 1 17:55:59 2014 Subject: [squeak-dev] Re: Status of PostgresV3 In-Reply-To: <72FBA18A-B9D7-4F57-B77F-83A5A75B9F1D@stack.nl> References: <72FBA18A-B9D7-4F57-B77F-83A5A75B9F1D@stack.nl> Message-ID: Hello Stephan, On Wed, 1 Oct 2014, Stephan Eggermont wrote: > >(YourConnectionPool default executeQuery: ?select 3 + 4?) > > ? ?first ? a query may returns multiple result sets, now we select the first ? > > ? ?rows ? we request the rows of the result set ? > > ? ?first ? then the first row ? > > ? ?first ? and the first column, this returns the number 7 ? > > I can get the results back and inspect them. > > Pg3Row doesn't understand first. That's a bug in the example. You have to use 'at: 1' instead of 'first'. It should be: (YourConnectionPool default executeQuery: 'select 3 + 4') first rows first at: 1 > > If I use a?rowsWithColumnNameDictionary, > I get an interesting column name: > ? #'?column?' #rowsWithColumnNameDictionary will only work if you name your columns and ensure that all of them have different names. Here's an example: (YourConnectionPool default executeQuery: 'select 3 + 4 as "theResult"') first rowsWithColumnNameDictionary first theResult Levente > > Is that default postgres behavior, or a textconverter issue? > > Stephan > > From tim at rowledge.org Wed Oct 1 18:05:06 2014 From: tim at rowledge.org (tim Rowledge) Date: Wed Oct 1 18:05:14 2014 Subject: [squeak-dev] re: startup time command line (or dropped files) arguments In-Reply-To: References: <68822DF1-D934-4532-86DF-4868115D78FF@rowledge.org> Message-ID: On 01-10-2014, at 4:27 AM, Craig Latta wrote: > > Tim> I need to be able to handle some simple cases for Scratch > Tim> startup and we seem to have completely changed how that area is > Tim> handled. I have come across (and reeled in horror) code in > Tim> ProjectLauncher... > > Chris> Don't "reel in horror" drama-boy. > > Mmm, coffee... it's always too much Unpossible! > (Tim) or not enough (Chris)! :) > > > -C tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- He has a tenuous grip on the obvious. From dsblakewatson at gmail.com Wed Oct 1 18:09:44 2014 From: dsblakewatson at gmail.com (blake) Date: Wed Oct 1 18:09:49 2014 Subject: [squeak-dev] Has anyone got a BASIC handy? In-Reply-To: References: Message-ID: Heh. Those books are the "well" I go back to when learning new languages. (I have both in print and learned to program using them.) That said: The code in those books is truly, truly awful, by necessity, due to the limitations of the Basic interpreters of the time. It's easier to reverse-engineer the code based on the limited printouts than to figure out what's going on with the one-character variable names and GOTOs being the primary means of branching. And with THAT said: Something LIKE those books could be incredibly useful. The one thing they had that most environments today don't is that you could start really simple, get a product, and build really easily on it. The Transcript isn't quite up to the task, and it's a big leap from the transcript to a GUI. Rambling aside, when you think about it, it's a pretty small language you could build a DSL for: Variable assignment, basic math, IF-THEN, GOTO and RND....it's all on one page: http://www.atariarchives.org/basicgames/showpage.php?page=i12 Just have the PRINT go to a 80x25 scrolling grid. Heh. Fun! -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141001/bc8bf1ed/attachment.htm From leves at elte.hu Wed Oct 1 18:10:27 2014 From: leves at elte.hu (Levente Uzonyi) Date: Wed Oct 1 18:10:32 2014 Subject: [squeak-dev] Re: Status of PostgresV3 In-Reply-To: <05F2BCFD-5D74-437A-8211-13E6FE69ED4B@stack.nl> References: <05F2BCFD-5D74-437A-8211-13E6FE69ED4B@stack.nl> Message-ID: On Wed, 1 Oct 2014, Stephan Eggermont wrote: > >YourSchemaMirror class >> schema > > > > ? ?^?schema_name? > > > >Schema mirrors mirror the functions in your database and provide an interface to call them. There is a little tool to inspect the >differences between the methods of the schema mirror and the functions in > the database, which can be invoked by: > > > >YourSchemaMirror browseChanges > > The default schema that was created is 'public'. > > When trying to browseChanges on that, I get back > a?'function array_accum(text) does not exist' in a? > Pg3ErrorResponse. (Postgres 9.3.5 on Mac 10.7.5) That's right. The query we use to get the defined functions in a schema uses that aggregate function. We always add it to our databases, because it's really useful. It's from http://www.postgresql.org/docs/9.3/static/xaggr.html and the definition is CREATE AGGREGATE array_accum (anyelement) ( sfunc = array_append, stype = anyarray, initcond = '{}' ); But I've uploaded a new version of PostgresV3-CodeMirror, which doesn't use that function anymore, so it should work with the default Postgres installation. Levente > > Stephan > > From karlramberg at gmail.com Wed Oct 1 18:20:18 2014 From: karlramberg at gmail.com (karl ramberg) Date: Wed Oct 1 18:20:21 2014 Subject: [squeak-dev] Has anyone got a BASIC handy? In-Reply-To: References: Message-ID: http://web.archive.org/web/20090809145959/http://www.zeek-it.com.ar/retrobjects Karl On Wed, Oct 1, 2014 at 6:40 PM, Casey Ransberger wrote: > Found myself waxing romantic over this? > > http://www.atariarchives.org/basicgames/index.php > > First thought was "I'll just throw something together" but I wondered if > anyone had done a BASIC for Squeak? > > TIA, > > Casey > > P.S. > > Google didn't help me with this one. It seemed to think I meant "basic > squeak" no matter how I typed it in. > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141001/04e31352/attachment.htm From tim at rowledge.org Wed Oct 1 18:22:17 2014 From: tim at rowledge.org (tim Rowledge) Date: Wed Oct 1 18:22:23 2014 Subject: [squeak-dev] re: Has anyone got a BASIC handy? In-Reply-To: References: Message-ID: <38B1CE4A-C81B-4057-BA82-AA5A7EF8C417@rowledge.org> On 01-10-2014, at 10:36 AM, Craig Latta wrote: > >> Found myself waxing romantic over this? >> >> http://www.atariarchives.org/basicgames/index.php >> >> First thought was "I'll just throw something together" but I wondered >> if anyone had done a BASIC for Squeak? > > Maybe Carl Gundel has thoughts about it? Pre-Squeak, he wrote > Liberty BASIC in Smalltalk. I'm sure you came across it in your > Googling, but just in case... > > https://en.wikipedia.org/wiki/Liberty_BASIC Actually I though he did ( or re-did) that in Squeak? And let?s not forget that that some older version(s) of Squeak had an alternate syntax capability that let you write and see code in a rather BASIC like form. Personally I thought it a Horror From Beyond The Pit but it sure was clever code. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: YOGA: Exit Finite-State Mode From tim at rowledge.org Wed Oct 1 22:01:08 2014 From: tim at rowledge.org (tim Rowledge) Date: Wed Oct 1 22:01:17 2014 Subject: [squeak-dev] startup time command line (or dropped files) arguments In-Reply-To: References: <68822DF1-D934-4532-86DF-4868115D78FF@rowledge.org> Message-ID: <5087080D-299F-4370-858E-23AB8EBE586B@rowledge.org> On 30-09-2014, at 6:42 PM, Chris Muller wrote: > Don't "reel in horror" drama-boy. Squeak's command-line processing is > simple and effective. I use it heavily every day. You might think it less ?drama-boy? if I remind you that I have to make this work for around 1.5 million regular users that don?t want to see an error notifier when they use a command line according to the older version. I?m inclined to think that some drama would be nice to avoid here? I understand the process you explained and it?s a good way to do things. Nicer still if it were well documented of course - perhaps you could add your explanation to the swiki sometime? And probably as a class comment, come to that. I guess I?ll need to turn off the readDocumentAtStartup pref and manually find any args. That?s really all I needed to know. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Oxymorons: Microsoft Works From tim at rowledge.org Wed Oct 1 23:25:48 2014 From: tim at rowledge.org (tim Rowledge) Date: Wed Oct 1 23:25:58 2014 Subject: [squeak-dev] We need to move Squeak services for the new servers ASAP. Message-ID: For a long time we?ve had free servers available via the SFC that we should be using instead of the Hetzner boxes that cost us (or more accurately, SFC) money. Every now and then we make a little progress in migrating but we really need to make a push on doing this *soon*. Effectively we?re spending other people?s money when we don't? need to. And we don?t even have a ?donate? button on our website right now... Levente is the official box-team leader so it?s up to him exactly how it gets done but I?d be really surprised if he couldn?t do with assistance from one or more people with some sysadmin chops. Please, volunteer if you have serious box-fu. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Dukedom: aristocratic birth control From lewis at mail.msen.com Wed Oct 1 23:39:21 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 1 23:39:24 2014 Subject: [squeak-dev] We need to move Squeak services for the new servers ASAP. In-Reply-To: References: Message-ID: <20141001233921.GC24808@shell.msen.com> On Wed, Oct 01, 2014 at 04:25:48PM -0700, tim Rowledge wrote: > For a long time we?ve had free servers available via the SFC that we > should be using instead of the Hetzner boxes that cost us (or more > accurately, SFC) money. Every now and then we make a little progress > in migrating but we really need to make a push on doing this *soon*. > Effectively we?re spending other people?s money when we don't? need to. > And we don?t even have a ?donate? button on our website right now... > > Levente is the official box-team leader so it?s up to him exactly how > it gets done but I?d be really surprised if he couldn?t do with assistance > from one or more people with some sysadmin chops. Please, volunteer if > you have serious box-fu. > Chris Muller and I were talking about volunteering to handle the migration of source.squeak.org, so I think that you can count on the two of us to take up that part of the project. Chris has a lot of experience with SqueakSource, and I handled the migration of squeaksource.com onto our servers last year, so I think that between the two of us we can get source.squeak.org moved. We will make sure that anything we do has Levente's support and approval. Dave From asqueaker at gmail.com Thu Oct 2 01:41:10 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 2 01:41:17 2014 Subject: [squeak-dev] startup time command line (or dropped files) arguments In-Reply-To: <5087080D-299F-4370-858E-23AB8EBE586B@rowledge.org> References: <68822DF1-D934-4532-86DF-4868115D78FF@rowledge.org> <5087080D-299F-4370-858E-23AB8EBE586B@rowledge.org> Message-ID: >> Don't "reel in horror" drama-boy. Squeak's command-line processing is >> simple and effective. I use it heavily every day. > > You might think it less ?drama-boy? if I remind you that I have to make this work for around 1.5 million regular users that don?t want to see an error notifier when they use a command line according to the older version. I?m inclined to think that some drama would be nice to avoid here? Yes, and in case the full bandwidth didn't come thru, please know that your comment amused me and I was simply playing on it. I hope you weren't offended. > I understand the process you explained and it?s a good way to do things. Nicer still if it were well documented of course - perhaps you could add your explanation to the swiki sometime? And probably as a class comment, come to that. Okay, done. http://wiki.squeak.org/squeak/6199 > I guess I?ll need to turn off the readDocumentAtStartup pref and manually find any args. That?s really all I needed to know. > > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Oxymorons: Microsoft Works > > > From casey.obrien.r at gmail.com Thu Oct 2 05:23:20 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Thu Oct 2 05:23:33 2014 Subject: [squeak-dev] re: Has anyone got a BASIC handy? In-Reply-To: References: Message-ID: Thanks, Craig. No, as I said, my GOOG-fu failed me. I think they recently changed how quoted strings are interpreted, so Google really wanted to think I meant "basic squeak" now matter how I worded it, and gave me Squeak tutorials. I'll check this out:) > On Oct 1, 2014, at 10:36 AM, Craig Latta wrote: > > >> Found myself waxing romantic over this? >> >> http://www.atariarchives.org/basicgames/index.php >> >> First thought was "I'll just throw something together" but I wondered >> if anyone had done a BASIC for Squeak? > > Maybe Carl Gundel has thoughts about it? Pre-Squeak, he wrote > Liberty BASIC in Smalltalk. I'm sure you came across it in your > Googling, but just in case... > > https://en.wikipedia.org/wiki/Liberty_BASIC > > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > From casey.obrien.r at gmail.com Thu Oct 2 05:28:56 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Thu Oct 2 05:29:03 2014 Subject: [squeak-dev] Has anyone got a BASIC handy? In-Reply-To: References: Message-ID: <28632ED0-D2C4-4524-B8C5-8215222A2CA7@gmail.com> Hi Blake. I can concur with some of your "rambling." In fact I do intend to do a rough translation of one of the games in the book. What's great about printed BASIC listings of games is that they tend to be relatively short, so they're fun to reimplement. That said, before doing an implementation of something, it helps to understand the original program very well. Arguably, the best way to understand a small program is to type it in, and deal with whatever bugs crop up right? I'd ideally be doing this in Squeak from the start, but I'm already into using an Apple IIGS emulator to get started. > On Oct 1, 2014, at 11:09 AM, blake wrote: > > Heh. Those books are the "well" I go back to when learning new languages. (I have both in print and learned to program using them.) > > That said: > > The code in those books is truly, truly awful, by necessity, due to the limitations of the Basic interpreters of the time. It's easier to reverse-engineer the code based on the limited printouts than to figure out what's going on with the one-character variable names and GOTOs being the primary means of branching. > > And with THAT said: > > Something LIKE those books could be incredibly useful. The one thing they had that most environments today don't is that you could start really simple, get a product, and build really easily on it. The Transcript isn't quite up to the task, and it's a big leap from the transcript to a GUI. > > Rambling aside, when you think about it, it's a pretty small language you could build a DSL for: Variable assignment, basic math, IF-THEN, GOTO and RND....it's all on one page: http://www.atariarchives.org/basicgames/showpage.php?page=i12 > > Just have the PRINT go to a 80x25 scrolling grid. Heh. Fun! > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141001/04a0708a/attachment.htm From casey.obrien.r at gmail.com Thu Oct 2 05:31:52 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Thu Oct 2 05:32:02 2014 Subject: [squeak-dev] re: Has anyone got a BASIC handy? In-Reply-To: <38B1CE4A-C81B-4057-BA82-AA5A7EF8C417@rowledge.org> References: <38B1CE4A-C81B-4057-BA82-AA5A7EF8C417@rowledge.org> Message-ID: <8F0C59AA-4D85-47BA-A338-1151BDBD6E22@gmail.com> Below > On Oct 1, 2014, at 11:22 AM, tim Rowledge wrote: > > >> On 01-10-2014, at 10:36 AM, Craig Latta wrote: >> >> >>> Found myself waxing romantic over this? >>> >>> http://www.atariarchives.org/basicgames/index.php >>> >>> First thought was "I'll just throw something together" but I wondered >>> if anyone had done a BASIC for Squeak? >> >> Maybe Carl Gundel has thoughts about it? Pre-Squeak, he wrote >> Liberty BASIC in Smalltalk. I'm sure you came across it in your >> Googling, but just in case... >> >> https://en.wikipedia.org/wiki/Liberty_BASIC > > Actually I though he did ( or re-did) that in Squeak? And let?s not forget that that some older version(s) of Squeak had an alternate syntax capability that let you write and see code in a rather BASIC like form. Personally I thought it a Horror From Beyond The Pit but it sure was clever code. > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Strange OpCodes: YOGA: Exit Finite-State Mode Tim: yes, it's rather like taking legs off of a dog. But could be useful if you have an old basic program to remediate and would prefer to replace all of those GOTOs with gradual as opposed to catastrophic evolution. --Casey From dsblakewatson at gmail.com Thu Oct 2 18:07:29 2014 From: dsblakewatson at gmail.com (blake) Date: Thu Oct 2 18:07:32 2014 Subject: [squeak-dev] Has anyone got a BASIC handy? In-Reply-To: <28632ED0-D2C4-4524-B8C5-8215222A2CA7@gmail.com> References: <28632ED0-D2C4-4524-B8C5-8215222A2CA7@gmail.com> Message-ID: Which game are you doing? On Wed, Oct 1, 2014 at 10:28 PM, Casey Ransberger wrote: > Hi Blake. I can concur with some of your "rambling." In fact I do intend > to do a rough translation of one of the games in the book. > > What's great about printed BASIC listings of games is that they tend to be > relatively short, so they're fun to reimplement. That said, before doing an > implementation of something, it helps to understand the original program > very well. Arguably, the best way to understand a small program is to type > it in, and deal with whatever bugs crop up right? > > I'd ideally be doing this in Squeak from the start, but I'm already into > using an Apple IIGS emulator to get started. > > On Oct 1, 2014, at 11:09 AM, blake wrote: > > Heh. Those books are the "well" I go back to when learning new languages. > (I have both in print and learned to program using them.) > > That said: > > The code in those books is truly, truly awful, by necessity, due to the > limitations of the Basic interpreters of the time. It's easier to > reverse-engineer the code based on the limited printouts than to figure out > what's going on with the one-character variable names and GOTOs being the > primary means of branching. > > And with THAT said: > > Something LIKE those books could be incredibly useful. The one thing they > had that most environments today don't is that you could start really > simple, get a product, and build really easily on it. The Transcript isn't > quite up to the task, and it's a big leap from the transcript to a GUI. > > Rambling aside, when you think about it, it's a pretty small language you > could build a DSL for: Variable assignment, basic math, IF-THEN, GOTO and > RND....it's all on one page: > http://www.atariarchives.org/basicgames/showpage.php?page=i12 > > Just have the PRINT go to a 80x25 scrolling grid. Heh. Fun! > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141002/b2538818/attachment.htm From commits at source.squeak.org Thu Oct 2 21:34:12 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 2 21:34:14 2014 Subject: [squeak-dev] The Inbox: Monticello-cmm.601.mcz Message-ID: A new version of Monticello was added to project The Inbox: http://source.squeak.org/inbox/Monticello-cmm.601.mcz ==================== Summary ==================== Name: Monticello-cmm.601 Author: cmm Time: 2 October 2014, 4:34:01.44 pm UUID: 9031e0e5-b991-46fd-a8f0-20ead172757b Ancestors: Monticello-topa.600 Recover quick keyboard access to the classic "install" and "revert" functions on the changed definitions list. Otherwise the new "Ignore (I)" function is selected whether "r" or "i" was pressed on the keyboard. That function has a hot-key anyway, so move it below the the standard Monticello functions. =============== Diff against Monticello-topa.600 =============== Item was changed: ----- Method: MCSaveVersionDialog>>methodListMenu: (in category 'as yet unclassified') ----- methodListMenu: aMenu - aMenu addList:#( - ('ignore (I)' ignoreSelection 'Do not include this change when saving') - -). super methodListMenu: aMenu. + aMenu addList:#(- + ('ignore (I)' ignoreSelection 'Toggle inclusion of this change when saving')). ^aMenu! From list at afceurope.com Fri Oct 3 17:01:06 2014 From: list at afceurope.com (Annick Fron) Date: Fri Oct 3 17:01:09 2014 Subject: [squeak-dev] Alien could not load library Message-ID: <237C01DB-849F-47A3-9A5B-6069E0989A48@afceurope.com> Hi, I have built my own linux dynamic library to use with FFI and Alien. Up to now, everything was OK but I made some changes, and now I am unable to load the library. The compilation was OK. I have checked with ldd the dependencies, and I have loaded the dependent libraries with : Alien ensureLoaded: dependentLib But I have still the problem. Annick From eliot.miranda at gmail.com Sat Oct 4 00:17:08 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sat Oct 4 00:17:12 2014 Subject: [squeak-dev] New Cog VMs available Message-ID: ...at http://www.mirandabanda.org/files/Cog/VM/VM.r3095/. CogVM binaries as per VMMaker.oscog-eem.890/r3095 Fix line-buffered input in sqFilePluginBasicPrims.c when buffer size > 1. fread cannot be relied upon to answer lines. Fix bug in Cogit>>lookup:for:methodAndErrorSelectorInto: which if cogging a method found through an MNU would set the cog method's selector to the original selector that was not understood instead of #doesNotUnderstand:. Fix the description of the blockonwarn flag (not blockonwarning). Spur: Fix one-way become for classes with and without copyHash, primarily by fixing allInstances. One-way become for classes causes duplicates in the class table (either that or an allInstances scan would be needed as part of the become to change instances referring to the deleted class index, which would be slow). So allInstances must be able to cope with duplicates. Hence split it into a fast path common case when the class in question is not duplicated, and a slower path when it is. Make both the marking phase of GC and allInstances check for and eliminate refereces to duplicate entries at wrong/obsolete class indices. Fix markAndShouldScan: to not scan the pun classes of non-objects on the heap such as implicit receiver caches and Sista counters. Eliminate the classTableBitmap premature optimization. All the information we need is in the cassTable and the class's hashes therein. Change pinObject: to answer 0 on failure and the (possibly moved) object on success. Much easier than having to check and follow forwarding pointer. The changes to platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c in r3092 in a Spur MT VM depend on this. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141003/87ec7403/attachment.htm From gerald at g-24.net Sat Oct 4 05:22:52 2014 From: gerald at g-24.net (Gerald Leeb) Date: Sat Oct 4 05:23:12 2014 Subject: [squeak-dev] Fun: Video Smalltalk @ OOPSA 2001 Message-ID: <2D314F44-DBCD-499B-A5FC-33B81D4B19A2@g-24.net> Hi, you may wanna watch a very old movie Squeakers @ OOPSA 2001 just for fun: https://www.youtube.com/watch?v=5RcdB6vmR-8 G. From kosi.balazs at ezomer.hu Sat Oct 4 14:30:35 2014 From: kosi.balazs at ezomer.hu (=?UTF-8?B?QmFsw6F6cyBLw7NzaQ==?=) Date: Sat Oct 4 14:30:40 2014 Subject: [squeak-dev] Debugger hiccups Message-ID: Hi, Today I came across two nuisances in the debugger: The first one is, that if you try to evaluate code in a debugger started from another debugger, you'll get an MNU: MessageAsTempNode>>beMethodArg. The other one is a tad more dangerous, so don't try it in an image dear to you: If you try to debug one of the following expressions: "nil", "-1", "0", "1" and "2" your image hangs. After interrupting it you get infinite debuggers with the message: "subscript is out of bounds: 2". The stack shows just one line: MethodContext(Object)>>error: I did not investigate any further yet. Cheers, Bal?zs -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141004/d27edecf/attachment.htm From lewis at mail.msen.com Sat Oct 4 16:32:57 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sat Oct 4 16:33:00 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: <20141004163257.GA3447@shell.msen.com> On Sat, Oct 04, 2014 at 04:30:35PM +0200, Bal??zs K??si wrote: > Hi, > > Today I came across two nuisances in the debugger: > > The first one is, that if you try to evaluate code in a debugger started > from another debugger, you'll get an MNU: MessageAsTempNode>>beMethodArg. > > The other one is a tad more dangerous, so don't try it in an image dear to > you: If you try to debug one of the following expressions: "nil", "-1", > "0", "1" and "2" your image hangs. After interrupting it you get infinite > debuggers with the message: "subscript is out of bounds: 2". The stack > shows just one line: MethodContext(Object)>>error: > > I did not investigate any further yet. > > Cheers, Bal??zs The second issue appears to be an infinite recursion in the fallback code for ContetPart>object:basicAt: Here is part of the stack trace for an image stuck in this condition: 65024980 ContextPart>object:basicAt: 65024572 ContextPart>object:basicAt: 65024164 ContextPart>object:basicAt: 65023756 ContextPart>object:basicAt: 65023348 ContextPart>object:basicAt: 65006892 ContextPart>object:basicAt: 65006800 ContextPart>object:instVarAt: 65006708 ContextPart>pushReceiverVariable: 65006616 InstructionStream>interpretNextV3ClosuresInstructionFor: 65006524 EncoderForV3PlusClosures class>interpretNextInstructionFor:in: 65006432 InstructionStream>interpretNextInstructionFor: 65006340 ContextPart>step 64823312 ContextPart>stepToSendOrReturn 64823220 Process>stepToSendOrReturn 64823128 BlockClosure>ensure: 64823036 Process>evaluate:onBehalfOf: 64822944 Process>stepToSendOrReturn 64822852 Debugger>send 64665472 TextEditor>debug:receiver:in: 64665380 TextEditor>debugIt 64665288 PluggableTextMorph>debugIt 64665152 TextMorph>handleEdit: 64664936 PluggableTextMorph>handleEdit: 64664844 PluggableTextMorph>debugIt Dave From commits at source.squeak.org Sun Oct 5 09:56:06 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sun Oct 5 09:56:10 2014 Subject: [squeak-dev] The Inbox: Help-Squeak-TerseGuide-dhn.4.mcz Message-ID: Bert Freudenberg uploaded a new version of Help-Squeak-TerseGuide to project The Inbox: http://source.squeak.org/inbox/Help-Squeak-TerseGuide-dhn.4.mcz ==================== Summary ==================== Name: Help-Squeak-TerseGuide-dhn.4 Author: dhn Time: 4 October 2014, 9:25:48.387 pm UUID: 5622b076-0185-a54e-aae1-7a8f158d1e1f Ancestors: Help-Squeak-TerseGuide-dhn.3 Correct comment for detect: (several places). Add findFirst: where applicable. =============== Diff against Help-Squeak-TerseGuide-dtl.2 =============== Item was changed: ----- Method: TerseGuideHelp class>>array (in category 'pages') ----- array ^HelpTopic title: 'Array' contents: '"************************************************************************ * Array: Fixed length collection * * ByteArray: Array limited to byte elements (0-255) * * WordArray: Array limited to word elements (0-2^32) * ************************************************************************" | b x y sum max | x := #(4 3 2 1). "constant array" x := Array with: 5 with: 4 with: 3 with: 2. "create array with up to 4 elements" x := Array new: 4. "allocate an array with specified size" x "set array elements" at: 1 put: 5; at: 2 put: 4; at: 3 put: 3; at: 4 put: 2. b := x isEmpty. "test if array is empty" y := x size. "array size" y := x at: 4. "get array element at index" b := x includes: 3. "test if element is in array" y := x copyFrom: 2 to: 4. "subarray" y := x indexOf: 3 ifAbsent: [0]. "first position of element within array" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the array" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a < 3]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum array elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum array elements" sum := x inject: 0 into: [:a :c | a + c]. "sum array elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in array" ifTrue: [a] ifFalse: [c]]. y := x shuffled. "randomly shuffle collection" y := x asArray. "convert to array" y := x asByteArray. "convert to byte array" y := x asWordArray. "convert to word array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>bag (in category 'pages') ----- bag ^HelpTopic title: 'Bag' contents: '"************************************************************************ * Bag: like OrderedCollection except elements are in no * * particular order * ************************************************************************" | b x y sum max | x := Bag with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := Bag new. "allocate collection" x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" x add: 3 withOccurrences: 2. "add multiple copies to collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" y := x remove: 4 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" b := x includes: 3. "test if element is in collection" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>dictionary (in category 'pages') ----- dictionary ^HelpTopic title: 'Dictionary' contents: '"************************************************************************ * Dictionary: * * IdentityDictionary: uses identity test (== rather than =) * ************************************************************************" | b x y sum max | x := Dictionary new. "allocate collection" x add: #a->4; add: #b->3; add: #c->1; add: #d->2; yourself. "add element to collection" x at: #e put: 3. "set element at index" b := x isEmpty. "test if empty" y := x size. "number of elements" y := x at: #a ifAbsent: []. "retrieve element at index" y := x keyAtValue: 3 ifAbsent: []. "retrieve key for given value with error block" y := x removeKey: #e ifAbsent: []. "remove element from collection" b := x includes: 3. "test if element is in values collection" b := x includesKey: #a. "test if element is in keys collection" y := x occurrencesOf: 3. "number of times object in collection" y := x keys. "set of keys" y := x values. "bag of values" x do: [:a | Transcript show: a printString; cr]. "iterate over the values collection" x keysDo: [:a | Transcript show: a printString; cr]. "iterate over the keys collection" x associationsDo: [:a | Transcript show: a printString; cr]. "iterate over the associations" x keysAndValuesDo: [:aKey :aValue | Transcript "iterate over keys and values" show: aKey printString; space; show: aValue printString; cr]. b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" Smalltalk at: #CMRGlobal put: ''CMR entry''. "put global in Smalltalk Dictionary" x := Smalltalk at: #CMRGlobal. "read global from Smalltalk Dictionary" Transcript show: (CMRGlobal printString). "entries are directly accessible by name" Smalltalk keys do: [ :k | "print out all classes" ((Smalltalk at: k) isKindOf: Class) ifFalse: [Transcript show: k printString; cr]]. Smalltalk at: #CMRDictionary put: (Dictionary new). "set up user defined dictionary" CMRDictionary at: #MyVar1 put: ''hello1''. "put entry in dictionary" CMRDictionary add: #MyVar2->''hello2''. "add entry to dictionary use key->value combo" CMRDictionary size. "dictionary size" CMRDictionary keys do: [ :k | "print out keys in dictionary" Transcript show: k printString; cr]. CMRDictionary values do: [ :k | "print out values in dictionary" Transcript show: k printString; cr]. CMRDictionary keysAndValuesDo: [:aKey :aValue | "print out keys and values" Transcript show: aKey printString; space; show: aValue printString; cr]. CMRDictionary associationsDo: [:aKeyValue | "another iterator for printing key values" Transcript show: aKeyValue printString; cr]. Smalltalk removeKey: #CMRGlobal ifAbsent: []. "remove entry from Smalltalk dictionary" Smalltalk removeKey: #CMRDictionary ifAbsent: []. "remove user dictionary from Smalltalk dictionary" '! Item was changed: ----- Method: TerseGuideHelp class>>interval (in category 'pages') ----- interval ^HelpTopic title: 'Interval' contents: '"************************************************************************ * Interval: * ************************************************************************" | b x y sum max | x := Interval from: 5 to: 10. "create interval object" x := 5 to: 10. x := Interval from: 5 to: 10 by: 2. "create interval object with specified increment" x := 5 to: 10 by: 2. b := x isEmpty. "test if empty" y := x size. "number of elements" x includes: 9. "test if element is in collection" x do: [:k | Transcript show: k printString; cr]. "iterate over interval" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 7]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a > 6]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>orderedCollection (in category 'pages') ----- orderedCollection ^HelpTopic title: 'Ordered Collection' contents: '"************************************************************************ * OrderedCollection: acts like an expandable array * ************************************************************************" | b x y sum max | x := OrderedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := OrderedCollection new. "allocate collection" x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" y := x addFirst: 5. "add element at beginning of collection" y := x removeFirst. "remove first element in collection" y := x addLast: 6. "add element at end of collection" y := x removeLast. "remove last element in collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" x at: 2 put: 3. "set element at index" y := x remove: 5 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" y := x at: 2. "retrieve element at index" y := x first. "retrieve first element in collection" y := x last. "retrieve last element in collection" b := x includes: 5. "test if element is in collection" y := x copyFrom: 2 to: 3. "subcollection" y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a < 2]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x shuffled. "randomly shuffle collection" y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>set (in category 'pages') ----- set ^HelpTopic title: 'Set' contents: '"************************************************************************ * Set: like Bag except duplicates not allowed * * IdentitySet: uses identity test (== rather than =) * ************************************************************************" | b x y sum max | x := Set with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := Set new. "allocate collection" x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" y := x remove: 4 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" x includes: 4. "test if element is in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>sortedCollection (in category 'pages') ----- sortedCollection ^HelpTopic title: 'Sorted Collection' contents: '"************************************************************************ * SortedCollection: like OrderedCollection except order of elements * * determined by sorting criteria * ************************************************************************" | b x y sum max | x := SortedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := SortedCollection new. "allocate collection" x := SortedCollection sortBlock: [:a :c | a > c]. "set sort criteria" x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" "y := x addFirst: 5." "add element at beginning of collection" y := x removeFirst. "remove first element in collection" y := x addLast: 6. "add element at end of collection" y := x removeLast. "remove last element in collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" y := x remove: 5 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" y := x at: 2. "retrieve element at index" y := x first. "retrieve first element in collection" y := x last. "retrieve last element in collection" b := x includes: 4. "test if element is in collection" y := x copyFrom: 2 to: 3. "subcollection" y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a < 3]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! From brasspen at gmail.com Sun Oct 5 13:00:09 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Sun Oct 5 13:00:48 2014 Subject: [squeak-dev] Camp Smalltalk Vanisle presentation - Squeak Services Message-ID: <4748AF9C-2A7B-4BE6-8292-EE6E99B0D26D@gmail.com> Here are my notes on a presentation I made here in Nanaimo on the homepage, SqueakMap, and Swiki. The two main ideas are adding a wiki interface to the current homepage and converting Swiki XML files to object graphs that can be rendered in Seaside and HelpBrowser. Chris Camp Smalltalk Vanisle presentation - homepage; Squeak Map Server; Swiki: an exploration of where these three applications are and where they could go - the code is available at SqueakSource3 at SqueakServices - this stuff is politically contentious; I?m not speaking for the Squeak community; it?s just an interesting problem space - the focus of this talk is to explore an idea. That idea is to write a TinyWiki graph Generator for Xtreams called TWGraphGenerator - Is it possible that creating this subclass of Actor in XTreams could be useful in both the homepage and in a Squeak wiki application? - show the two Shapes app graphics 1. Homepage: Altitude (XTreams) & Twitter Bootstrap - the video for XTreams is Martin Kobetic at Barcelona ESUG 2010 on YouTube - Altitude: tour the running application; move to the the keys; change the URI strategy; then go to the locator; then talk about resources - self first resources at: (self first resources keys first) - show ALExampleApplication>>initializeLocator; show hierarchy of ALExample classes - show squeak.org; talk about 24 char foo versus squeak.org URIs - no rendering tree; has inheritance for its pages - it?s mainly about Twitter Bootstrap and could be skinned to any framework - some miss Aida; but is that what they really miss? A wiki interface. That?s what the code behind the homepage should do - go back to the Shapes app graphics 2. SMServer: Seaside2.8 & SqueakSource & Twitter Bootstrap - HTTPView2 - SMBaseView to HVHttpView and its hierarchy; pages as subclasses; - SMSqueakMapView>>#default - has a Canvas and a Builder like Seaside2.6; compare the Builder to the Canvas with #anchorWithPopupAction:name:extent:toggles:do:; moved from one method per tag to one class per tag - HTTPView2 never evolved to the Canvas it was developing; show selectors for #newaccount in HTTPView2 - There is no HTTPView2 that I can obtain that works in localhost. - sm directory with map files and accounts and cache dirs; there is /sm/accounts and /sm/cache/; One for the server; one for the client; Why does the server have cache directories at all? I don?t know. - the concept of gathering content in the cloud and consuming it on a desktop with a file is a good one that could be extended to the Swiki - SMServer; talk about the object graph of the model; Account?>Package?>Release - uses a list component from SqueakSource; uses WALabelledFormDialog for forms - you can see it running at oopfile.com - 3. Swiki: Seaside2.8 & SqueakSource & Twitter Bootstrap & TinyWiki - show the XML files - ComSwiki - show the wiki format in the edit button of a running ComSwiki - transform the XML files into an intermediate text format with a NuSwikiPageConverter - the NuSwikiPageConverter is an image with Swiki.cs and SS2 - Then feed those strings in the Swiki format to an XTreams parser using #grammarWiki and TWGraphGenerator to make an object graph like TinyWiki?s - we turn every XML page into an instance of TinyWiki; TinyWiki is the wiki in every SqueakSource project that nobody uses - then we render them in Seaside with an application, which could be Ohana - Ohana is Hawaiian for ?family?, as in ?a family of wiki objects?; TinyWiki instances - change the text files into TWFolder instances and then render them in both Seaside and the HelpBrowser - perhaps use a program like Ohana, which is a hacked SqueakSource the brings the TinyWiki instances to the fore - or use Pier, but I suspect an older version in a Seaside 2.8 would be easier to manage than an current version of Pier - all XML pages would be stored as TWFolder objects in a single SSRepository, which could be downloaded and rendered in HelpBrowser by writing a subclass for TWVisitor - covert the TWFolder object graph to the HelpTopic object graph with the Visitor pattern in TinyWiki - the class that makes this all possible is SSProject; it?s stored in SSRepository; it has three ivars that are useful and powerful, which are id; wiki; and viewer - if you want a page with not just one TinyWiki, but several or with components, you subclass SSProjectView - use XTreams to replace SmallCC, TWScanner, and TWParser by creating a TWGraphGenerator class - use the idea of collecting content form a web app and consuming it locally from a file in the manner of SqueakMap and its map file - show the second Shapes app image again -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141005/0ce654e0/attachment.htm From commits at source.squeak.org Sun Oct 5 13:56:09 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sun Oct 5 13:56:12 2014 Subject: [squeak-dev] The Trunk: Help-Squeak-TerseGuide-dhn.4.mcz Message-ID: David T. Lewis uploaded a new version of Help-Squeak-TerseGuide to project The Trunk: http://source.squeak.org/trunk/Help-Squeak-TerseGuide-dhn.4.mcz ==================== Summary ==================== Name: Help-Squeak-TerseGuide-dhn.4 Author: dhn Time: 4 October 2014, 9:25:48.387 pm UUID: 5622b076-0185-a54e-aae1-7a8f158d1e1f Ancestors: Help-Squeak-TerseGuide-dhn.3 Correct comment for detect: (several places). Add findFirst: where applicable. =============== Diff against Help-Squeak-TerseGuide-dtl.2 =============== Item was changed: ----- Method: TerseGuideHelp class>>array (in category 'pages') ----- array ^HelpTopic title: 'Array' contents: '"************************************************************************ * Array: Fixed length collection * * ByteArray: Array limited to byte elements (0-255) * * WordArray: Array limited to word elements (0-2^32) * ************************************************************************" | b x y sum max | x := #(4 3 2 1). "constant array" x := Array with: 5 with: 4 with: 3 with: 2. "create array with up to 4 elements" x := Array new: 4. "allocate an array with specified size" x "set array elements" at: 1 put: 5; at: 2 put: 4; at: 3 put: 3; at: 4 put: 2. b := x isEmpty. "test if array is empty" y := x size. "array size" y := x at: 4. "get array element at index" b := x includes: 3. "test if element is in array" y := x copyFrom: 2 to: 4. "subarray" y := x indexOf: 3 ifAbsent: [0]. "first position of element within array" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the array" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a < 3]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum array elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum array elements" sum := x inject: 0 into: [:a :c | a + c]. "sum array elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in array" ifTrue: [a] ifFalse: [c]]. y := x shuffled. "randomly shuffle collection" y := x asArray. "convert to array" y := x asByteArray. "convert to byte array" y := x asWordArray. "convert to word array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>bag (in category 'pages') ----- bag ^HelpTopic title: 'Bag' contents: '"************************************************************************ * Bag: like OrderedCollection except elements are in no * * particular order * ************************************************************************" | b x y sum max | x := Bag with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := Bag new. "allocate collection" x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" x add: 3 withOccurrences: 2. "add multiple copies to collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" y := x remove: 4 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" b := x includes: 3. "test if element is in collection" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>dictionary (in category 'pages') ----- dictionary ^HelpTopic title: 'Dictionary' contents: '"************************************************************************ * Dictionary: * * IdentityDictionary: uses identity test (== rather than =) * ************************************************************************" | b x y sum max | x := Dictionary new. "allocate collection" x add: #a->4; add: #b->3; add: #c->1; add: #d->2; yourself. "add element to collection" x at: #e put: 3. "set element at index" b := x isEmpty. "test if empty" y := x size. "number of elements" y := x at: #a ifAbsent: []. "retrieve element at index" y := x keyAtValue: 3 ifAbsent: []. "retrieve key for given value with error block" y := x removeKey: #e ifAbsent: []. "remove element from collection" b := x includes: 3. "test if element is in values collection" b := x includesKey: #a. "test if element is in keys collection" y := x occurrencesOf: 3. "number of times object in collection" y := x keys. "set of keys" y := x values. "bag of values" x do: [:a | Transcript show: a printString; cr]. "iterate over the values collection" x keysDo: [:a | Transcript show: a printString; cr]. "iterate over the keys collection" x associationsDo: [:a | Transcript show: a printString; cr]. "iterate over the associations" x keysAndValuesDo: [:aKey :aValue | Transcript "iterate over keys and values" show: aKey printString; space; show: aValue printString; cr]. b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" Smalltalk at: #CMRGlobal put: ''CMR entry''. "put global in Smalltalk Dictionary" x := Smalltalk at: #CMRGlobal. "read global from Smalltalk Dictionary" Transcript show: (CMRGlobal printString). "entries are directly accessible by name" Smalltalk keys do: [ :k | "print out all classes" ((Smalltalk at: k) isKindOf: Class) ifFalse: [Transcript show: k printString; cr]]. Smalltalk at: #CMRDictionary put: (Dictionary new). "set up user defined dictionary" CMRDictionary at: #MyVar1 put: ''hello1''. "put entry in dictionary" CMRDictionary add: #MyVar2->''hello2''. "add entry to dictionary use key->value combo" CMRDictionary size. "dictionary size" CMRDictionary keys do: [ :k | "print out keys in dictionary" Transcript show: k printString; cr]. CMRDictionary values do: [ :k | "print out values in dictionary" Transcript show: k printString; cr]. CMRDictionary keysAndValuesDo: [:aKey :aValue | "print out keys and values" Transcript show: aKey printString; space; show: aValue printString; cr]. CMRDictionary associationsDo: [:aKeyValue | "another iterator for printing key values" Transcript show: aKeyValue printString; cr]. Smalltalk removeKey: #CMRGlobal ifAbsent: []. "remove entry from Smalltalk dictionary" Smalltalk removeKey: #CMRDictionary ifAbsent: []. "remove user dictionary from Smalltalk dictionary" '! Item was changed: ----- Method: TerseGuideHelp class>>interval (in category 'pages') ----- interval ^HelpTopic title: 'Interval' contents: '"************************************************************************ * Interval: * ************************************************************************" | b x y sum max | x := Interval from: 5 to: 10. "create interval object" x := 5 to: 10. x := Interval from: 5 to: 10 by: 2. "create interval object with specified increment" x := 5 to: 10 by: 2. b := x isEmpty. "test if empty" y := x size. "number of elements" x includes: 9. "test if element is in collection" x do: [:k | Transcript show: k printString; cr]. "iterate over interval" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 7]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a > 6]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>orderedCollection (in category 'pages') ----- orderedCollection ^HelpTopic title: 'Ordered Collection' contents: '"************************************************************************ * OrderedCollection: acts like an expandable array * ************************************************************************" | b x y sum max | x := OrderedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := OrderedCollection new. "allocate collection" x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" y := x addFirst: 5. "add element at beginning of collection" y := x removeFirst. "remove first element in collection" y := x addLast: 6. "add element at end of collection" y := x removeLast. "remove last element in collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" x at: 2 put: 3. "set element at index" y := x remove: 5 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" y := x at: 2. "retrieve element at index" y := x first. "retrieve first element in collection" y := x last. "retrieve last element in collection" b := x includes: 5. "test if element is in collection" y := x copyFrom: 2 to: 3. "subcollection" y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a < 2]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x shuffled. "randomly shuffle collection" y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>set (in category 'pages') ----- set ^HelpTopic title: 'Set' contents: '"************************************************************************ * Set: like Bag except duplicates not allowed * * IdentitySet: uses identity test (== rather than =) * ************************************************************************" | b x y sum max | x := Set with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := Set new. "allocate collection" x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" y := x remove: 4 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" x includes: 4. "test if element is in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! Item was changed: ----- Method: TerseGuideHelp class>>sortedCollection (in category 'pages') ----- sortedCollection ^HelpTopic title: 'Sorted Collection' contents: '"************************************************************************ * SortedCollection: like OrderedCollection except order of elements * * determined by sorting criteria * ************************************************************************" | b x y sum max | x := SortedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := SortedCollection new. "allocate collection" x := SortedCollection sortBlock: [:a :c | a > c]. "set sort criteria" x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" "y := x addFirst: 5." "add element at beginning of collection" y := x removeFirst. "remove first element in collection" y := x addLast: 6. "add element at end of collection" y := x removeLast. "remove last element in collection" y := x addAll: #(7 8 9). "add multiple elements to collection" y := x removeAll: #(7 8 9). "remove multiple elements from collection" y := x remove: 5 ifAbsent: []. "remove element from collection" b := x isEmpty. "test if empty" y := x size. "number of elements" y := x at: 2. "retrieve element at index" y := x first. "retrieve first element in collection" y := x last. "retrieve last element in collection" b := x includes: 4. "test if element is in collection" y := x copyFrom: 2 to: 3. "subcollection" y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" y := x occurrencesOf: 3. "number of times object in collection" x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" b := x allSatisfy: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" y := x select: [:a | a > 2]. "return collection of elements that pass test" y := x reject: [:a | a < 2]. "return collection of elements that fail test" y := x collect: [:a | a + a]. "transform each element for new collection" + y := x detect: [:a | a > 3] ifNone: []. "return first element that passes test" + y := x findFirst: [:a | a < 3]. "find position of first element that passes test" - y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" sum := x inject: 0 into: [:a :c | a + c]. "sum elements" max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. y := x asArray. "convert to array" y := x asOrderedCollection. "convert to ordered collection" y := x asSortedCollection. "convert to sorted collection" y := x asBag. "convert to bag collection" y := x asSet. "convert to set collection" '! From frank.shearar at gmail.com Sun Oct 5 19:42:21 2014 From: frank.shearar at gmail.com (Frank Shearar) Date: Sun Oct 5 19:42:24 2014 Subject: [squeak-dev] Re: New Cog VMs available In-Reply-To: References: Message-ID: On 4 October 2014 01:17, Eliot Miranda wrote: > ...at http://www.mirandabanda.org/files/Cog/VM/VM.r3095/. Updated in CI! frank From commits at source.squeak.org Sun Oct 5 23:55:01 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sun Oct 5 23:55:02 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141005235501.1315.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007305.html Name: Help-Squeak-TerseGuide-dhn.4 Ancestors: Help-Squeak-TerseGuide-dhn.3 Correct comment for detect: (several places). Add findFirst: where applicable. ============================================= From goran at krampe.se Mon Oct 6 09:49:03 2014 From: goran at krampe.se (=?windows-1252?Q?G=F6ran_Krampe?=) Date: Mon Oct 6 09:49:27 2014 Subject: [squeak-dev] Camp Smalltalk Vanisle presentation - Squeak Services In-Reply-To: <4748AF9C-2A7B-4BE6-8292-EE6E99B0D26D@gmail.com> References: <4748AF9C-2A7B-4BE6-8292-EE6E99B0D26D@gmail.com> Message-ID: <5432658F.8020506@krampe.se> Hey! On 10/05/2014 03:00 PM, Chris Cunnington wrote: > *2. SMServer: Seaside2.8 & SqueakSource & Twitter Bootstrap * > > - HTTPView2 > - SMBaseView to HVHttpView and its hierarchy; pages as subclasses; > - SMSqueakMapView>>#default > - has a Canvas and a Builder like Seaside2.6; compare the Builder to the > Canvas with #anchorWithPopupAction:name:extent:toggles:do:; moved from > one method per tag to one class per tag > - HTTPView2 never evolved to the Canvas it was developing; show > selectors for #newaccount in HTTPView2 In fact, I started on a new HV2 that reused the canvas from Seaside basically (and I think Giovanni also worked on something similar), it basically worked but I then moved on to Seaside personally. > - There is no HTTPView2 that I can obtain that works in localhost. ? > - sm directory with map files and accounts and cache dirs; there is > /sm/accounts and /sm/cache/; One for the server; one for the client; Why > does the server have cache directories at all? I don?t know. Because the idea was that if the original URL ended up broken, the SM server can still serve the file from its own cache. IIRC this mechanism still works? When you add a release and enter a URL for the file, the server should download it to its own cache. regards, G?ran From brasspen at gmail.com Mon Oct 6 17:09:04 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Mon Oct 6 17:09:26 2014 Subject: [squeak-dev] Camp Smalltalk Vanisle presentation - Squeak Services In-Reply-To: <5432658F.8020506@krampe.se> References: <4748AF9C-2A7B-4BE6-8292-EE6E99B0D26D@gmail.com> <5432658F.8020506@krampe.se> Message-ID: <20B5C362-8766-49E1-A324-BCDC9568B539@gmail.com> On Oct 6, 2014, at 2:49 AM, G?ran Krampe wrote: > Hey! > > On 10/05/2014 03:00 PM, Chris Cunnington wrote: >> *2. SMServer: Seaside2.8 & SqueakSource & Twitter Bootstrap * >> >> - HTTPView2 >> - SMBaseView to HVHttpView and its hierarchy; pages as subclasses; >> - SMSqueakMapView>>#default >> - has a Canvas and a Builder like Seaside2.6; compare the Builder to the >> Canvas with #anchorWithPopupAction:name:extent:toggles:do:; moved from >> one method per tag to one class per tag >> - HTTPView2 never evolved to the Canvas it was developing; show >> selectors for #newaccount in HTTPView2 > > In fact, I started on a new HV2 that reused the canvas from Seaside basically (and I think Giovanni also worked on something similar), it basically worked but I then moved on to Seaside personally. > >> - There is no HTTPView2 that I can obtain that works in localhost. > > ? > >> - sm directory with map files and accounts and cache dirs; there is >> /sm/accounts and /sm/cache/; One for the server; one for the client; Why >> does the server have cache directories at all? I don?t know. > > Because the idea was that if the original URL ended up broken, the SM server can still serve the file from its own cache. IIRC this mechanism still works? Wow. I didn?t know that at all. > When you add a release and enter a URL for the file, the server should download it to its own cache. This is wholly new to me. And it fills a whole in my understanding of SqueakMap. I?m going to explore this with better understanding. Thanks for explaining that. Chris > > regards, G?ran > > From asqueaker at gmail.com Mon Oct 6 17:48:58 2014 From: asqueaker at gmail.com (Chris Muller) Date: Mon Oct 6 17:48:59 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: On Sat, Oct 4, 2014 at 9:30 AM, Bal?zs K?si wrote: > Hi, > > Today I came across two nuisances in the debugger: > > The first one is, that if you try to evaluate code in a debugger started > from another debugger, you'll get an MNU: MessageAsTempNode>>beMethodArg. That's strange, I do that a lot and it works fine for me. > The other one is a tad more dangerous, so don't try it in an image dear to > you: If you try to debug one of the following expressions: "nil", "-1", "0", > "1" and "2" your image hangs. After interrupting it you get infinite > debuggers with the message: "subscript is out of bounds: 2". The stack shows > just one line: MethodContext(Object)>>error: > > I did not investigate any further yet. > > Cheers, Bal?zs > > > From kosi.balazs at ezomer.hu Mon Oct 6 18:21:06 2014 From: kosi.balazs at ezomer.hu (=?UTF-8?B?QmFsw6F6cyBLw7NzaQ==?=) Date: Mon Oct 6 18:21:09 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: On Mon, Oct 6, 2014 at 7:48 PM, Chris Muller wrote: > On Sat, Oct 4, 2014 at 9:30 AM, Bal?zs K?si wrote: > > Hi, > > > Today I came across two nuisances in the debugger: > > > > The first one is, that if you try to evaluate code in a debugger started > > from another debugger, you'll get an MNU: MessageAsTempNode>>beMethodArg. > > That's strange, I do that a lot and it works fine for me. > > It's rather easy to reproduce: 1) debug an expression. eg. 3 + 4 2) from the debugger start another debugger from the code pane or from the pane on the bottom right (with the local variables in scope), but not from the bottom left pane (with the instance in scope as self) 3) try to evaluate any code in the code pane or in the bottom right pane, and you get a debugger. Cheers, Balazs -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/1240a2a3/attachment.htm From asqueaker at gmail.com Mon Oct 6 18:37:18 2014 From: asqueaker at gmail.com (Chris Muller) Date: Mon Oct 6 18:37:22 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: I just tried those exact instructions in trunk image and it worked. I tried the expression, 'hello' asUppercase in both the code pane and the lower-right pane, selected "debug" from teh context menu. It worked for me. On Mon, Oct 6, 2014 at 1:21 PM, Bal?zs K?si wrote: > > > On Mon, Oct 6, 2014 at 7:48 PM, Chris Muller wrote: >> >> On Sat, Oct 4, 2014 at 9:30 AM, Bal?zs K?si wrote: >> > Hi, >> >> > >> > Today I came across two nuisances in the debugger: >> > >> > The first one is, that if you try to evaluate code in a debugger started >> > from another debugger, you'll get an MNU: >> > MessageAsTempNode>>beMethodArg. >> >> That's strange, I do that a lot and it works fine for me. >> > It's rather easy to reproduce: > 1) debug an expression. eg. 3 + 4 > 2) from the debugger start another debugger from the code pane or from the > pane on the bottom right (with the local variables in scope), but not from > the bottom left pane (with the instance in scope as self) > 3) try to evaluate any code in the code pane or in the bottom right pane, > and you get a debugger. > > Cheers, Balazs > > > From eliot.miranda at gmail.com Mon Oct 6 18:38:53 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 6 18:38:57 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: Hi Cris, On Mon, Oct 6, 2014 at 11:37 AM, Chris Muller wrote: > I just tried those exact instructions in trunk image and it worked. I > tried the expression, 'hello' asUppercase in both the code pane and > the lower-right pane, selected "debug" from teh context menu. It > worked for me. > you need to go one step further. 1. debug 3.4. 2. in code pane of debugger #1 debug 4+5 3. in code pane of debugger #2 debug 5+6, boom. > > On Mon, Oct 6, 2014 at 1:21 PM, Bal?zs K?si wrote: > > > > > > On Mon, Oct 6, 2014 at 7:48 PM, Chris Muller > wrote: > >> > >> On Sat, Oct 4, 2014 at 9:30 AM, Bal?zs K?si > wrote: > >> > Hi, > >> > >> > > >> > Today I came across two nuisances in the debugger: > >> > > >> > The first one is, that if you try to evaluate code in a debugger > started > >> > from another debugger, you'll get an MNU: > >> > MessageAsTempNode>>beMethodArg. > >> > >> That's strange, I do that a lot and it works fine for me. > >> > > It's rather easy to reproduce: > > 1) debug an expression. eg. 3 + 4 > > 2) from the debugger start another debugger from the code pane or from > the > > pane on the bottom right (with the local variables in scope), but not > from > > the bottom left pane (with the instance in scope as self) > > 3) try to evaluate any code in the code pane or in the bottom right > pane, > > and you get a debugger. > > > > Cheers, Balazs > > > > > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/e5fffdcc/attachment.htm From eliot.miranda at gmail.com Mon Oct 6 18:39:42 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 6 18:39:45 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: Hi Chris, oops... On Mon, Oct 6, 2014 at 11:37 AM, Chris Muller wrote: > I just tried those exact instructions in trunk image and it worked. I > tried the expression, 'hello' asUppercase in both the code pane and > the lower-right pane, selected "debug" from teh context menu. It > worked for me. > you need to go one step further. 1. debug 3+4 2. in code pane of debugger #1 debug 4+5 3. in code pane of debugger #2 debug 5+6, boom. > > On Mon, Oct 6, 2014 at 1:21 PM, Bal?zs K?si wrote: > > > > > > On Mon, Oct 6, 2014 at 7:48 PM, Chris Muller > wrote: > >> > >> On Sat, Oct 4, 2014 at 9:30 AM, Bal?zs K?si > wrote: > >> > Hi, > >> > >> > > >> > Today I came across two nuisances in the debugger: > >> > > >> > The first one is, that if you try to evaluate code in a debugger > started > >> > from another debugger, you'll get an MNU: > >> > MessageAsTempNode>>beMethodArg. > >> > >> That's strange, I do that a lot and it works fine for me. > >> > > It's rather easy to reproduce: > > 1) debug an expression. eg. 3 + 4 > > 2) from the debugger start another debugger from the code pane or from > the > > pane on the bottom right (with the local variables in scope), but not > from > > the bottom left pane (with the instance in scope as self) > > 3) try to evaluate any code in the code pane or in the bottom right > pane, > > and you get a debugger. > > > > Cheers, Balazs > > > > > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/05d9b37b/attachment.htm From ma.chris.m at gmail.com Mon Oct 6 18:41:37 2014 From: ma.chris.m at gmail.com (Chris Muller) Date: Mon Oct 6 18:41:39 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: Ah, okay, yes. Boom. On Mon, Oct 6, 2014 at 1:38 PM, Eliot Miranda wrote: > Hi Cris, > > On Mon, Oct 6, 2014 at 11:37 AM, Chris Muller wrote: >> >> I just tried those exact instructions in trunk image and it worked. I >> tried the expression, 'hello' asUppercase in both the code pane and >> the lower-right pane, selected "debug" from teh context menu. It >> worked for me. > > > you need to go one step further. > > 1. debug 3.4. > 2. in code pane of debugger #1 debug 4+5 > 3. in code pane of debugger #2 debug 5+6, boom. > >> >> >> On Mon, Oct 6, 2014 at 1:21 PM, Bal?zs K?si wrote: >> > >> > >> > On Mon, Oct 6, 2014 at 7:48 PM, Chris Muller >> > wrote: >> >> >> >> On Sat, Oct 4, 2014 at 9:30 AM, Bal?zs K?si >> >> wrote: >> >> > Hi, >> >> >> >> > >> >> > Today I came across two nuisances in the debugger: >> >> > >> >> > The first one is, that if you try to evaluate code in a debugger >> >> > started >> >> > from another debugger, you'll get an MNU: >> >> > MessageAsTempNode>>beMethodArg. >> >> >> >> That's strange, I do that a lot and it works fine for me. >> >> >> > It's rather easy to reproduce: >> > 1) debug an expression. eg. 3 + 4 >> > 2) from the debugger start another debugger from the code pane or from >> > the >> > pane on the bottom right (with the local variables in scope), but not >> > from >> > the bottom left pane (with the instance in scope as self) >> > 3) try to evaluate any code in the code pane or in the bottom right >> > pane, >> > and you get a debugger. >> > >> > Cheers, Balazs >> > >> > >> > >> > > > > -- > best, > Eliot From commits at source.squeak.org Mon Oct 6 19:47:56 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 19:47:57 2014 Subject: [squeak-dev] The Trunk: ToolBuilder-Kernel-eem.63.mcz Message-ID: Eliot Miranda uploaded a new version of ToolBuilder-Kernel to project The Trunk: http://source.squeak.org/trunk/ToolBuilder-Kernel-eem.63.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-eem.63 Author: eem Time: 6 October 2014, 12:46:57.26 pm UUID: 2a80d908-62c0-4502-92a2-cd3a15f90f3c Ancestors: ToolBuilder-Kernel-mt.62 The method that opens a debugger does need to answer the window created, as its comment says. =============== Diff against ToolBuilder-Kernel-mt.62 =============== Item was changed: ----- Method: ToolBuilder>>openDebugger:label: (in category 'opening') ----- openDebugger: aSpec label: aString "Build and open a debugger from the given spec, labeling it appropriately. Answer the widget opened. Subclasses can override this method if opening a debugger has specific requirements different from opening other widgets." + ^self open: aSpec label: aString - self open: aSpec label: aString ! From commits at source.squeak.org Mon Oct 6 19:58:21 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 19:58:23 2014 Subject: [squeak-dev] The Trunk: Tools-eem.529.mcz Message-ID: Eliot Miranda uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-eem.529.mcz ==================== Summary ==================== Name: Tools-eem.529 Author: eem Time: 6 October 2014, 12:57:06.915 pm UUID: 3c226418-51a9-4b8a-9edc-9015b15b27cb Ancestors: Tools-cmm.528 Have Debugger>>openFullNoSuspendLabel: et al answer the windows they create. Hence also change Debugger class>>openInterrupt:onProcess: to answer the debugger, not the window. =============== Diff against Tools-cmm.528 =============== Item was changed: ----- Method: Debugger class>>openInterrupt:onProcess: (in category 'opening') ----- openInterrupt: aString onProcess: interruptedProcess "Open a notifier in response to an interrupt. An interrupt occurs when the user types the interrupt key (cmd-. on Macs, ctrl-c or alt-. on other systems) or when the low-space watcher detects that memory is low." | debugger | "Simulation guard" debugger := self new. debugger process: interruptedProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers activeControllerProcess == interruptedProcess]) ifTrue: [ScheduledControllers activeController]) context: interruptedProcess suspendedContext. debugger externalInterrupt: true. Preferences logDebuggerStackToFile ifTrue: [(aString includesSubString: 'Space') & (aString includesSubString: 'low') ifTrue: [Smalltalk logError: aString inContext: debugger interruptedContext to: 'LowSpaceDebug.log'] "logging disabled for 4.3 release, see http://lists.squeak.org/pipermail/squeak-dev/2011-December/162503.html" "ifFalse: [Smalltalk logSqueakError: aString inContext: debugger interruptedContext]"]. Preferences eToyFriendly ifTrue: [World stopRunningAll]. + ^debugger + openNotifierContents: nil label: aString; + yourself - ^ debugger - openNotifierContents: nil - label: aString ! Item was changed: ----- Method: Debugger>>openFullNoSuspendFrom: (in category 'initialize') ----- openFullNoSuspendFrom: topView + "Create, schedule and answer a full debugger with the given label. Do not terminate the current active process." - "Create and schedule a full debugger with the given label. Do not terminate the current active process." | oldContextStackIndex | oldContextStackIndex := contextStackIndex. self expandStack. "Sets contextStackIndex to zero." + ^[ToolBuilder default openDebugger: self label: topView label closing: topView] ensure: + [self toggleContextStackIndex: oldContextStackIndex]! - ToolBuilder default openDebugger: self label: topView label closing: topView. - self toggleContextStackIndex: oldContextStackIndex.! Item was changed: ----- Method: Debugger>>openFullNoSuspendLabel: (in category 'initialize') ----- openFullNoSuspendLabel: aString + "Create, schedule and answer a full debugger with the given label. Do not terminate the current active process." - "Create and schedule a full debugger with the given label. Do not terminate the current active process." | oldContextStackIndex | oldContextStackIndex := contextStackIndex. self expandStack. "Sets contextStackIndex to zero." + ^[ToolBuilder default openDebugger: self label: aString] ensure: + [self toggleContextStackIndex: oldContextStackIndex]! - ToolBuilder default openDebugger: self label: aString. - self toggleContextStackIndex: oldContextStackIndex.! Item was changed: ----- Method: Debugger>>openNotifierContents:label: (in category 'initialize') ----- openNotifierContents: msgString label: label + "Create, schedule and answer a notifier view with the given label and message. A notifier view shows just the message or the first several lines of the stack, with a menu that allows the user to open a full debugger if so desired." - "Create and schedule a notifier view with the given label and message. A notifier view shows just the message or the first several lines of the stack, with a menu that allows the user to open a full debugger if so desired." "NOTE: When this method returns, a new process has been scheduled to run the windows, and thus this notifier, but the previous active process has not been suspended. The sender will do this." | msg builder spec | Sensor flushKeyboard. savedCursor := Cursor currentCursor. Cursor currentCursor: Cursor normal. (label beginsWith: 'Space is low') ifTrue: [msg := self lowSpaceChoices, (msgString ifNil: [''])] ifFalse: [msg := msgString]. builder := ToolBuilder default. spec := self buildNotifierWith: builder label: label message: msg. self expandStack. + ^[builder openDebugger: spec] ensure: + [errorWasInUIProcess := Project current spawnNewProcessIfThisIsUI: interruptedProcess] - builder openDebugger: spec. - errorWasInUIProcess := Project current spawnNewProcessIfThisIsUI: interruptedProcess. ! From commits at source.squeak.org Mon Oct 6 20:05:12 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 20:05:13 2014 Subject: [squeak-dev] The Trunk: Compiler-eem.289.mcz Message-ID: Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.289.mcz ==================== Summary ==================== Name: Compiler-eem.289 Author: eem Time: 6 October 2014, 11:58:50.62 am UUID: 7d67c48c-4a2f-4445-83e8-1f8f931801e3 Ancestors: Compiler-eem.288 Fix doits in the codePane of a debugger opened from another debugger. e.g. before this fix 1. debug 3+4. 2. in code pane of debugger #1 debug 4+5 3. in code pane of debugger #2 debug 5+6, boom. The bug was that when the encoder creates temp names for temp vars in the debugged context, which it does by creating messages to DoItIn:'s argument 'ThisContext', if this is a level 3 debug, then the original expression would have a temp var called 'ThisContext' already and that would overwrite the 'ThisContext' argument for this level with a message send, and boom. The fix is merely to filter-out these temps and hence never overwrite DoItIn:'s 'ThisContext' argument in the scope table. =============== Diff against Compiler-eem.288 =============== Item was changed: ----- Method: Encoder>>init:notifying: (in category 'initialize-release') ----- init: aCue notifying: anObject "The use of the variable requestor is a bit confusing here. This is *not* the original requestor, which is available through the cue. It's the Parser instance that is using the encoder." self setCue: aCue. requestor := anObject. nTemps := 0. supered := false. self initScopeAndLiteralTables. cue getClass variablesAndOffsetsDo: [:variable "" :offset "" | offset isNil ifTrue: [scopeTable at: variable name put: (FieldNode new fieldDefinition: variable)] ifFalse: [scopeTable at: variable put: (offset >= 0 ifTrue: [InstanceVariableNode new name: variable index: offset] ifFalse: [MaybeContextInstanceVariableNode new name: variable index: offset negated])]]. cue context ~~ nil ifTrue: [| homeNode | homeNode := self bindTemp: self doItInContextName. "0th temp = aContext passed as arg" cue context tempNames withIndexDo: [:variable :index| + variable ~= self doItInContextName ifTrue: + [scopeTable + at: variable + put: (MessageAsTempNode new + receiver: homeNode + selector: #namedTempAt: + arguments: (Array with: (self encodeLiteral: index)) + precedence: 3 + from: self)]]]. - scopeTable - at: variable - put: (MessageAsTempNode new - receiver: homeNode - selector: #namedTempAt: - arguments: (Array with: (self encodeLiteral: index)) - precedence: 3 - from: self)]]. sourceRanges := Dictionary new: 32. globalSourceRanges := OrderedCollection new: 32 ! From commits at source.squeak.org Mon Oct 6 20:11:07 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 20:11:08 2014 Subject: [squeak-dev] The Trunk: Morphic-eem.746.mcz Message-ID: Eliot Miranda uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-eem.746.mcz ==================== Summary ==================== Name: Morphic-eem.746 Author: eem Time: 6 October 2014, 1:09:34.182 pm UUID: c9ae704e-6a58-40b8-a998-72392d0cff6e Ancestors: Morphic-ul.745 Fix debugging of optimized expressions. =============== Diff against Morphic-ul.745 =============== Item was changed: ----- Method: TextEditor>>debug:receiver:in: (in category 'do-its') ----- debug: aCompiledMethod receiver: anObject in: evalContext + | guineaPig debugger debuggerWindow context | - | guineaPig debugger context | guineaPig := [ aCompiledMethod valueWithReceiver: anObject arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]) ] newProcess. context := guineaPig suspendedContext. debugger := Debugger new process: guineaPig controller: nil context: context. + debuggerWindow := debugger openFullNoSuspendLabel: 'Debug it'. + "Now step into the expression. But if it is quick (is implemented as a primtiive, e.g. `0') + it will return immediately back to the block that is sent newProcess above. Guard + against that with the check for home being thisContext." + [debugger interruptedContext method == aCompiledMethod] + whileFalse: + [debugger interruptedContext home == thisContext ifTrue: + [debuggerWindow delete. + UIManager default inform: 'Nothing to debug; expression is optimized'. + ^self]. + debugger send]! - debugger openFullNoSuspendLabel: 'Debug it'. - [ debugger interruptedContext method == aCompiledMethod ] - whileFalse: [ debugger send ]! From commits at source.squeak.org Mon Oct 6 20:12:22 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 20:12:24 2014 Subject: [squeak-dev] The Trunk: ST80Tools-eem.2.mcz Message-ID: Eliot Miranda uploaded a new version of ST80Tools to project The Trunk: http://source.squeak.org/trunk/ST80Tools-eem.2.mcz ==================== Summary ==================== Name: ST80Tools-eem.2 Author: eem Time: 6 October 2014, 1:11:46.54 pm UUID: 513b7a04-1c98-41a7-99a6-0852b3bb9a94 Ancestors: ST80Tools-fbs.1 Fix debugging of optimized expressions. =============== Diff against ST80Tools-fbs.1 =============== Item was changed: ----- Method: ParagraphEditor>>debug:receiver:in: (in category '*ST80Tools') ----- debug: aCompiledMethod receiver: anObject in: evalContext + | guineaPig debugger debuggerWindow context | - | guineaPig debugger context | guineaPig := [ aCompiledMethod valueWithReceiver: anObject arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]) ] newProcess. context := guineaPig suspendedContext. debugger := Debugger new process: guineaPig + controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: + [ScheduledControllers activeController]) - controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) - ifTrue: [ScheduledControllers activeController] - ifFalse: [nil]) context: context. + debuggerWindow := debugger openFullNoSuspendLabel: 'Debug it'. + "Now step into the expression. But if it is quick (is implemented as a primtiive, e.g. `0') + it will return immediately back to the block that is sent newProcess above. Guard + against that with the check for home being thisContext." - debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] + whileFalse: + [debugger interruptedContext home == thisContext ifTrue: + [debuggerWindow controller closeAndUnschedule. + UIManager default inform: 'Nothing to debug; expression is optimized'. + ^self]. + debugger send]! - whileFalse: [debugger send]! From eliot.miranda at gmail.com Mon Oct 6 20:21:46 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 6 20:21:48 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: On Sat, Oct 4, 2014 at 7:30 AM, Bal?zs K?si wrote: > Hi, > > Today I came across two nuisances in the debugger: > > The first one is, that if you try to evaluate code in a debugger started > from another debugger, you'll get an MNU: MessageAsTempNode>>beMethodArg. > > The other one is a tad more dangerous, so don't try it in an image dear to > you: If you try to debug one of the following expressions: "nil", "-1", > "0", "1" and "2" your image hangs. After interrupting it you get infinite > debuggers with the message: "subscript is out of bounds: 2". The stack > shows just one line: MethodContext(Object)>>error: > > I did not investigate any further yet. > > Cheers, Bal?zs > both issues fixed. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/dafca936/attachment.htm From kosi.balazs at ezomer.hu Mon Oct 6 21:43:07 2014 From: kosi.balazs at ezomer.hu (=?UTF-8?B?QmFsw6F6cyBLw7NzaQ==?=) Date: Mon Oct 6 21:43:13 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: Thanks Eliot for fixing this! I've updated my image and now anything I try to debug results in the popup: 'Nothing to debug; expression is optimized', so I removed the code creating the popup, and can confirm that the first issue is gone. Balazs -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/55decedf/attachment.htm From commits at source.squeak.org Mon Oct 6 22:41:23 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 22:41:25 2014 Subject: [squeak-dev] The Trunk: Morphic-eem.747.mcz Message-ID: Eliot Miranda uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-eem.747.mcz ==================== Summary ==================== Name: Morphic-eem.747 Author: eem Time: 6 October 2014, 3:39:08.651 pm UUID: 6d5fda0b-2826-43c4-af1e-9f5c0cf7258e Ancestors: Morphic-eem.746 Fix the broken fix in Morphic-eem.746 for debugging optimized methods. =============== Diff against Morphic-eem.746 =============== Item was changed: ----- Method: TextEditor>>debug:receiver:in: (in category 'do-its') ----- debug: aCompiledMethod receiver: anObject in: evalContext | guineaPig debugger debuggerWindow context | + guineaPig := + [aCompiledMethod - guineaPig := [ - aCompiledMethod valueWithReceiver: anObject + arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]). + guineaPig := nil "spot the return from aCompiledMethod"] newProcess. - arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]) ] newProcess. context := guineaPig suspendedContext. debugger := Debugger new process: guineaPig controller: nil context: context. debuggerWindow := debugger openFullNoSuspendLabel: 'Debug it'. "Now step into the expression. But if it is quick (is implemented as a primtiive, e.g. `0') it will return immediately back to the block that is sent newProcess above. Guard against that with the check for home being thisContext." [debugger interruptedContext method == aCompiledMethod] whileFalse: + [(guineaPig isNil + and: [debugger interruptedContext home == thisContext]) ifTrue: - [debugger interruptedContext home == thisContext ifTrue: [debuggerWindow delete. UIManager default inform: 'Nothing to debug; expression is optimized'. ^self]. debugger send]! From eliot.miranda at gmail.com Mon Oct 6 22:43:43 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 6 22:43:45 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: On Mon, Oct 6, 2014 at 2:43 PM, Bal?zs K?si wrote: > Thanks Eliot for fixing this! > > I've updated my image and now anything I try to debug results in the > popup: 'Nothing to debug; expression is optimized', so I removed the code > creating the popup, and can confirm that the first issue is gone. > Doh! I forgot to test that debug it still works, and of course broke it. OK, there's a new fix in place now. I do apologize. > > Balazs > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/2f17f08e/attachment.htm From eliot.miranda at gmail.com Mon Oct 6 22:44:52 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 6 22:44:54 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: On Mon, Oct 6, 2014 at 3:43 PM, Eliot Miranda wrote: > > > On Mon, Oct 6, 2014 at 2:43 PM, Bal?zs K?si wrote: > >> Thanks Eliot for fixing this! >> >> I've updated my image and now anything I try to debug results in the >> popup: 'Nothing to debug; expression is optimized', so I removed the code >> creating the popup, and can confirm that the first issue is gone. >> > > Doh! I forgot to test that debug it still works, and of course broke it. > OK, there's a new fix in place now. I do apologize. > Ugh, I'm having a bad day. I just committed something that exhibited the old symptom. Sorry. Give me a few to get this right. > > >> >> Balazs >> >> >> >> > > > -- > best, > Eliot > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/1c58e842/attachment.htm From lewis at mail.msen.com Mon Oct 6 22:58:14 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Mon Oct 6 22:58:16 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: Message-ID: <20141006225814.GA49968@shell.msen.com> On Mon, Oct 06, 2014 at 03:44:52PM -0700, Eliot Miranda wrote: > On Mon, Oct 6, 2014 at 3:43 PM, Eliot Miranda wrote: > > > > On Mon, Oct 6, 2014 at 2:43 PM, Bal??zs K??si wrote: > > > >> Thanks Eliot for fixing this! > >> > >> I've updated my image and now anything I try to debug results in the > >> popup: 'Nothing to debug; expression is optimized', so I removed the code > >> creating the popup, and can confirm that the first issue is gone. > > > > Doh! I forgot to test that debug it still works, and of course broke it. > > OK, there's a new fix in place now. I do apologize. > > Ugh, I'm having a bad day. I just committed something that exhibited the > old symptom. Sorry. Give me a few to get this right. Eliot, You on a bad day would be way better than me on a good day, and I'm probably not the only one who would say that. Thanks very much for addressing these issues, and thanks for keeping the MVC side updated too :-) Dave From commits at source.squeak.org Mon Oct 6 23:19:54 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 23:19:56 2014 Subject: [squeak-dev] The Trunk: Kernel-eem.877.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-eem.877.mcz ==================== Summary ==================== Name: Kernel-eem.877 Author: eem Time: 6 October 2014, 4:19:05.019 pm UUID: 0261bf17-d453-4738-924c-ed2bab916f63 Ancestors: Kernel-eem.876 Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) =============== Diff against Kernel-eem.876 =============== Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and arguments are given as arguments to this message. If successful, push result and return resuming context, else ^ PrimitiveFailToken. Any primitive which provokes execution needs to be intercepted and simulated to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. "ContextPart>>blockCopy:; simulated to get startpc right" (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) ifTrue: [^self push: ((BlockContext newForMethod: receiver method) home: receiver home startpc: pc + 2 nargs: (arguments at: 1))]. (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" ifTrue: [^receiver pushArgs: arguments from: self]. (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" ifTrue: [^receiver pushArgs: arguments first from: self]. primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" ifTrue: [^self send: arguments first to: receiver with: arguments allButFirst super: false]. primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" ifTrue: [^self send: arguments first to: receiver with: (arguments at: 2) startClass: nil]. primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" ifTrue: [^self send: arguments first to: receiver with: (arguments at: 2) startClass: (arguments at: 3)]. "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. ^((self objectClass: value) == Array and: [value size = 2 and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" + and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: arguments last + arguments: (primitiveIndex = 189 + ifTrue: [arguments at: 1] + ifFalse: [arguments allButLast])]. - method: (arguments at: 2) - arguments: (arguments at: 1)]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" [^receiver simulateValueWithArguments: arguments caller: self]. primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. ^((self objectClass: value) == Array and: [value size = 2 and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! From commits at source.squeak.org Mon Oct 6 23:24:15 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 23:24:16 2014 Subject: [squeak-dev] The Trunk: Kernel-eem.878.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-eem.878.mcz ==================== Summary ==================== Name: Kernel-eem.878 Author: eem Time: 6 October 2014, 4:23:20.811 pm UUID: e4b864d7-c2bc-4a8c-b0fa-e867a1508410 Ancestors: Kernel-eem.876 Less haste, more speed. Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) =============== Diff against Kernel-eem.876 =============== Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and arguments are given as arguments to this message. If successful, push result and return resuming context, else ^ PrimitiveFailToken. Any primitive which provokes execution needs to be intercepted and simulated to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. "ContextPart>>blockCopy:; simulated to get startpc right" (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) ifTrue: [^self push: ((BlockContext newForMethod: receiver method) home: receiver home startpc: pc + 2 nargs: (arguments at: 1))]. (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" ifTrue: [^receiver pushArgs: arguments from: self]. (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" ifTrue: [^receiver pushArgs: arguments first from: self]. primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" ifTrue: [^self send: arguments first to: receiver with: arguments allButFirst super: false]. primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" ifTrue: [^self send: arguments first to: receiver with: (arguments at: 2) startClass: nil]. primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" ifTrue: [^self send: arguments first to: receiver with: (arguments at: 2) startClass: (arguments at: 3)]. "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. ^((self objectClass: value) == Array and: [value size = 2 and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" + and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: arguments last + arguments: (primitiveIndex = 188 + ifTrue: [arguments at: 1] + ifFalse: [arguments allButLast])]. - method: (arguments at: 2) - arguments: (arguments at: 1)]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" [^receiver simulateValueWithArguments: arguments caller: self]. primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. ^((self objectClass: value) == Array and: [value size = 2 and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! From lewis at mail.msen.com Mon Oct 6 23:36:44 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Mon Oct 6 23:36:47 2014 Subject: [squeak-dev] A small convenience update to OSProcess/CommandShell Message-ID: <20141006233644.GA57411@shell.msen.com> I have updated OSProcess/CommandShell with some changes that allow PipeableOSProcess to be used more conveniently for executing commands on a Unix/Linux/OSX system. You can now run a simple command without worrying about closing (pipe) file handles or other special handling. For example: ( PipeableOSProcess command: 'ls -l' ) output Explanation: PipeableOSProcess was originally designed to support command pipeline execution within a CommandShell. In that scenario, the command shell handles all setup and cleanup of pipe handles. In practice, PipeableOSProcess turns out to be useful for simple command execution with input and output pipes connected to the image. The updates to PipeableOSProcess class>>command: add the necessary setup and cleanup that would otherwise have been done by the command shell. OSProcess and CommandShell are on SqueakMap (select the "head" version to get the latest), or from the squeaksource repository at: http://www.squeaksource.com/OSProcess http://www.squeaksource.com/CommandShell Dave From commits at source.squeak.org Mon Oct 6 23:39:29 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 23:39:32 2014 Subject: [squeak-dev] The Trunk: Morphic-eem.748.mcz Message-ID: Eliot Miranda uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-eem.748.mcz ==================== Summary ==================== Name: Morphic-eem.748 Author: eem Time: 6 October 2014, 4:37:20.596 pm UUID: d98f5dd3-77d5-4f51-94ed-92378abe641c Ancestors: Morphic-ul.745 Fix debugging of optimized expressions. Depends also on Kernel-eem.878. =============== Diff against Morphic-ul.745 =============== Item was changed: ----- Method: TextEditor>>debug:receiver:in: (in category 'do-its') ----- debug: aCompiledMethod receiver: anObject in: evalContext + | guineaPig debugger debuggerWindow context | + guineaPig := + [aCompiledMethod - | guineaPig debugger context | - guineaPig := [ - aCompiledMethod valueWithReceiver: anObject + arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]). + guineaPig := nil "spot the return from aCompiledMethod"] newProcess. - arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]) ] newProcess. context := guineaPig suspendedContext. debugger := Debugger new process: guineaPig controller: nil context: context. + debuggerWindow := debugger openFullNoSuspendLabel: 'Debug it'. + "Now step into the expression. But if it is quick (is implemented as a primtiive, e.g. `0') + it will return immediately back to the block that is sent newProcess above. Guard + against that with the check for home being thisContext." + [debugger interruptedContext method == aCompiledMethod] + whileFalse: + [(guineaPig isNil + and: [debugger interruptedContext home == thisContext]) ifTrue: + [debuggerWindow delete. + UIManager default inform: 'Nothing to debug; expression is optimized'. + ^self]. + debugger send]! - debugger openFullNoSuspendLabel: 'Debug it'. - [ debugger interruptedContext method == aCompiledMethod ] - whileFalse: [ debugger send ]! From commits at source.squeak.org Mon Oct 6 23:45:33 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 23:45:35 2014 Subject: [squeak-dev] The Trunk: ST80Tools-eem.3.mcz Message-ID: Eliot Miranda uploaded a new version of ST80Tools to project The Trunk: http://source.squeak.org/trunk/ST80Tools-eem.3.mcz ==================== Summary ==================== Name: ST80Tools-eem.3 Author: eem Time: 6 October 2014, 4:45:25.26 pm UUID: 025a1ce4-d05a-4afb-b5c8-fc0df26ef4e0 Ancestors: ST80Tools-fbs.1 Fix debugging of optimized expressions. Depends also on Kernel-eem.878. =============== Diff against ST80Tools-fbs.1 =============== Item was changed: ----- Method: ParagraphEditor>>debug:receiver:in: (in category '*ST80Tools') ----- debug: aCompiledMethod receiver: anObject in: evalContext + | guineaPig debugger debuggerWindow context | + guineaPig := + [aCompiledMethod - | guineaPig debugger context | - guineaPig := [ - aCompiledMethod valueWithReceiver: anObject + arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]). + guineaPig := nil "spot the return from aCompiledMethod"] newProcess. - arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ]) ] newProcess. context := guineaPig suspendedContext. debugger := Debugger new process: guineaPig + controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: + [ScheduledControllers activeController]) - controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) - ifTrue: [ScheduledControllers activeController] - ifFalse: [nil]) context: context. + debuggerWindow := debugger openFullNoSuspendLabel: 'Debug it'. + "Now step into the expression. But if it is quick (is implemented as a primtiive, e.g. `0') + it will return immediately back to the block that is sent newProcess above. Guard + against that with the check for home being thisContext." - debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] + whileFalse: + [(guineaPig isNil + and: [debugger interruptedContext home == thisContext]) ifTrue: + [debuggerWindow controller closeAndUnschedule. + UIManager default inform: 'Nothing to debug; expression is optimized'. + ^self]. + debugger send]! - whileFalse: [debugger send]! From eliot.miranda at gmail.com Mon Oct 6 23:47:14 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 6 23:47:15 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: <20141006225814.GA49968@shell.msen.com> References: <20141006225814.GA49968@shell.msen.com> Message-ID: On Mon, Oct 6, 2014 at 3:58 PM, David T. Lewis wrote: > On Mon, Oct 06, 2014 at 03:44:52PM -0700, Eliot Miranda wrote: > > On Mon, Oct 6, 2014 at 3:43 PM, Eliot Miranda > wrote: > > > > > > On Mon, Oct 6, 2014 at 2:43 PM, Bal??zs K??si > wrote: > > > > > >> Thanks Eliot for fixing this! > > >> > > >> I've updated my image and now anything I try to debug results in the > > >> popup: 'Nothing to debug; expression is optimized', so I removed the > code > > >> creating the popup, and can confirm that the first issue is gone. > > > > > > Doh! I forgot to test that debug it still works, and of course broke > it. > > > OK, there's a new fix in place now. I do apologize. > > > > Ugh, I'm having a bad day. I just committed something that exhibited the > > old symptom. Sorry. Give me a few to get this right. > > Eliot, > > You on a bad day would be way better than me on a good day, and I'm > probably > not the only one who would say that. Thanks very much for addressing these > issues, and thanks for keeping the MVC side updated too :-) > thanks for the kind words. I wish I was that good ;-). But fingers crossed there's a proper fix there now. If it's easy please test the MVC changes; TIA. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/c0f96b06/attachment.htm From commits at source.squeak.org Mon Oct 6 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 6 23:55:04 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141006235502.24641.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007306.html Name: ToolBuilder-Kernel-eem.63 Ancestors: ToolBuilder-Kernel-mt.62 The method that opens a debugger does need to answer the window created, as its comment says. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007307.html Name: Tools-eem.529 Ancestors: Tools-cmm.528 Have Debugger>>openFullNoSuspendLabel: et al answer the windows they create. Hence also change Debugger class>>openInterrupt:onProcess: to answer the debugger, not the window. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007308.html Name: Compiler-eem.289 Ancestors: Compiler-eem.288 Fix doits in the codePane of a debugger opened from another debugger. e.g. before this fix 1. debug 3+4. 2. in code pane of debugger #1 debug 4+5 3. in code pane of debugger #2 debug 5+6, boom. The bug was that when the encoder creates temp names for temp vars in the debugged context, which it does by creating messages to DoItIn:'s argument 'ThisContext', if this is a level 3 debug, then the original expression would have a temp var called 'ThisContext' already and that would overwrite the 'ThisContext' argument for this level with a message send, and boom. The fix is merely to filter-out these temps and hence never overwrite DoItIn:'s 'ThisContext' argument in the scope table. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007309.html Name: Morphic-eem.746 Ancestors: Morphic-ul.745 Fix debugging of optimized expressions. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007310.html Name: ST80Tools-eem.2 Ancestors: ST80Tools-fbs.1 Fix debugging of optimized expressions. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007311.html Name: Morphic-eem.747 Ancestors: Morphic-eem.746 Fix the broken fix in Morphic-eem.746 for debugging optimized methods. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007312.html Name: Kernel-eem.877 Ancestors: Kernel-eem.876 Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007313.html Name: Kernel-eem.878 Ancestors: Kernel-eem.876 Less haste, more speed. Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007314.html Name: Morphic-eem.748 Ancestors: Morphic-ul.745 Fix debugging of optimized expressions. Depends also on Kernel-eem.878. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007315.html Name: ST80Tools-eem.3 Ancestors: ST80Tools-fbs.1 Fix debugging of optimized expressions. Depends also on Kernel-eem.878. ============================================= From lewis at mail.msen.com Tue Oct 7 00:07:52 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 7 00:07:55 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: <20141006225814.GA49968@shell.msen.com> Message-ID: <20141007000752.GA61018@shell.msen.com> On Mon, Oct 06, 2014 at 04:47:14PM -0700, Eliot Miranda wrote: > On Mon, Oct 6, 2014 at 3:58 PM, David T. Lewis wrote: > > > On Mon, Oct 06, 2014 at 03:44:52PM -0700, Eliot Miranda wrote: > > > On Mon, Oct 6, 2014 at 3:43 PM, Eliot Miranda > > wrote: > > > > > > > > On Mon, Oct 6, 2014 at 2:43 PM, Bal??zs K??si > > wrote: > > > > > > > >> Thanks Eliot for fixing this! > > > >> > > > >> I've updated my image and now anything I try to debug results in the > > > >> popup: 'Nothing to debug; expression is optimized', so I removed the > > code > > > >> creating the popup, and can confirm that the first issue is gone. > > > > > > > > Doh! I forgot to test that debug it still works, and of course broke > > it. > > > > OK, there's a new fix in place now. I do apologize. > > > > > > Ugh, I'm having a bad day. I just committed something that exhibited the > > > old symptom. Sorry. Give me a few to get this right. > > > > Eliot, > > > > You on a bad day would be way better than me on a good day, and I'm > > probably > > not the only one who would say that. Thanks very much for addressing these > > issues, and thanks for keeping the MVC side updated too :-) > > > > thanks for the kind words. I wish I was that good ;-). But fingers > crossed there's a proper fix there now. If it's easy please test the MVC > changes; TIA. There is some kind of glitch with "debug it" in MVC, although I don't know if it is related to the recent updates. I'll try to figure out the issue and give some feedback, though possibly not tonight. Dave From florin.mateoc at gmail.com Tue Oct 7 03:51:46 2014 From: florin.mateoc at gmail.com (Florin Mateoc) Date: Tue Oct 7 03:51:24 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: References: <20141006225814.GA49968@shell.msen.com> Message-ID: <54336352.4080109@gmail.com> Hi Eliot, Seeing that the commit is called "fix debugging of optimized expressions", I remembered that I had recently stumbled upon a debugger annoyance related to an optimized expression. I checked and unfortunately it is still there, so if you fell inspired :) One easy way to see it is to debug CompiledMethod>>#= , comparing a compiled method to itself. In the to:do: loop, at every iteration, the debugger highlights the early exit "^false", even though it does not actually execute it. Cheers, Florin On 10/6/2014 7:47 PM, Eliot Miranda wrote: > > > On Mon, Oct 6, 2014 at 3:58 PM, David T. Lewis > wrote: > > On Mon, Oct 06, 2014 at 03:44:52PM -0700, Eliot Miranda wrote: > > On Mon, Oct 6, 2014 at 3:43 PM, Eliot Miranda > wrote: > > > > > > On Mon, Oct 6, 2014 at 2:43 PM, Bal??zs K??si > wrote: > > > > > >> Thanks Eliot for fixing this! > > >> > > >> I've updated my image and now anything I try to debug results in the > > >> popup: 'Nothing to debug; expression is optimized', so I removed the code > > >> creating the popup, and can confirm that the first issue is gone. > > > > > > Doh! I forgot to test that debug it still works, and of course broke it. > > > OK, there's a new fix in place now. I do apologize. > > > > Ugh, I'm having a bad day. I just committed something that exhibited the > > old symptom. Sorry. Give me a few to get this right. > > Eliot, > > You on a bad day would be way better than me on a good day, and I'm probably > not the only one who would say that. Thanks very much for addressing these > issues, and thanks for keeping the MVC side updated too :-) > > > thanks for the kind words. I wish I was that good ;-). But fingers crossed there's a proper fix there now. If it's > easy please test the MVC changes; TIA. > -- > best, > Eliot > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141006/1dbc486f/attachment.htm From lecteur at zogotounga.net Tue Oct 7 08:37:21 2014 From: lecteur at zogotounga.net (=?UTF-8?B?U3TDqXBoYW5lIFJvbGxhbmRpbg==?=) Date: Tue Oct 7 08:37:21 2014 Subject: [squeak-dev] Saucers for Mac broken ? Message-ID: <5433A641.9000605@zogotounga.net> Hello, I set up a web page for my Space Invader: http://www.zogotounga.net/comp/saucers.htm Now, some of my friends on Mac (but not all) complain that the all-in-one available via the "for Mac" link is broken and does not install. On the other hand I saw it install perfectly on a Mac laptop; it does work for some. I don't know s*** about Macs. Could someone solve that case for me ? What I did is take the official 4.5 all-in-one, and simply replace the 4.5 image with mine (renamed, obviously). Stef From kosi.balazs at ezomer.hu Tue Oct 7 08:41:44 2014 From: kosi.balazs at ezomer.hu (=?UTF-8?B?QmFsw6F6cyBLw7NzaQ==?=) Date: Tue Oct 7 08:41:48 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: <54336352.4080109@gmail.com> References: <20141006225814.GA49968@shell.msen.com> <54336352.4080109@gmail.com> Message-ID: Thanks Eliot for fixing this, and for all your effort making Squeak the wonderful place it is! Balazs -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141007/89e8305d/attachment.htm From lecteur at zogotounga.net Tue Oct 7 08:42:41 2014 From: lecteur at zogotounga.net (=?windows-1252?Q?St=E9phane_Rollandin?=) Date: Tue Oct 7 08:42:38 2014 Subject: [squeak-dev] Debugger hiccups In-Reply-To: <20141006225814.GA49968@shell.msen.com> References: <20141006225814.GA49968@shell.msen.com> Message-ID: <5433A781.4070609@zogotounga.net> > Eliot, > > You on a bad day would be way better than me on a good day, and I'm probably > not the only one who would say that. Indeed. Stef From edw at generalmagic.at Tue Oct 7 08:47:40 2014 From: edw at generalmagic.at (Wolfgang Eder) Date: Tue Oct 7 08:47:49 2014 Subject: [squeak-dev] Saucers for Mac broken ? In-Reply-To: <5433A641.9000605@zogotounga.net> References: <5433A641.9000605@zogotounga.net> Message-ID: it depends on your mac security settings. if you have them at ?mac app store? or ?mac app store and verified developers?, then the mac complains that the app is broken and wants to move it to the trash. if you have them at ?no limitations? the mac complains that it has been downloaded from the internet, but you can start and run it (and it works). kind regards wolfgang Am 07.10.2014 um 10:37 schrieb St?phane Rollandin : > Hello, > > I set up a web page for my Space Invader: > http://www.zogotounga.net/comp/saucers.htm > > Now, some of my friends on Mac (but not all) complain that the all-in-one available via the "for Mac" link is broken and does not install. > > On the other hand I saw it install perfectly on a Mac laptop; it does work for some. > > I don't know s*** about Macs. Could someone solve that case for me ? > > What I did is take the official 4.5 all-in-one, and simply replace the 4.5 image with mine (renamed, obviously). > > > Stef > From edgardec2005 at gmail.com Tue Oct 7 09:00:33 2014 From: edgardec2005 at gmail.com (Edgar J de Cleene) Date: Tue Oct 7 09:00:42 2014 Subject: [squeak-dev] Saucers for Mac broken ? In-Reply-To: <5433A641.9000605@zogotounga.net> References: <5433A641.9000605@zogotounga.net> Message-ID: <72487F02E6B04636841EED596C8AA234@gmail.com> I try it on my macs, (have severals) and works I wish the source code for including in FunSqueak4.6 :=) -- Edgar J de Cleene @morplenauta en twitter Sent with Sparrow (http://www.sparrowmailapp.com/?sig) On Tuesday, October 7, 2014 at 05:37, St?phane Rollandin wrote: > Hello, > > I set up a web page for my Space Invader: > http://www.zogotounga.net/comp/saucers.htm > > Now, some of my friends on Mac (but not all) complain that the > all-in-one available via the "for Mac" link is broken and does not install. > > On the other hand I saw it install perfectly on a Mac laptop; it does > work for some. > > I don't know s*** about Macs. Could someone solve that case for me ? > > What I did is take the official 4.5 all-in-one, and simply replace the > 4.5 image with mine (renamed, obviously). > > > Stef -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141007/82e7d2b4/attachment.htm From Das.Linux at gmx.de Tue Oct 7 09:00:34 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Tue Oct 7 09:00:42 2014 Subject: [squeak-dev] Saucers for Mac broken ? In-Reply-To: <5433A641.9000605@zogotounga.net> References: <5433A641.9000605@zogotounga.net> Message-ID: On 07.10.2014, at 10:37, St?phane Rollandin wrote: > Hello, > > I set up a web page for my Space Invader: > http://www.zogotounga.net/comp/saucers.htm > > Now, some of my friends on Mac (but not all) complain that the all-in-one available via the "for Mac" link is broken and does not install. > > On the other hand I saw it install perfectly on a Mac laptop; it does work for some. > > I don't know s*** about Macs. Could someone solve that case for me ? > > What I did is take the official 4.5 all-in-one, and simply replace the 4.5 image with mine (renamed, obviously). The 4.5 all-in-one is code-signed, so replacing the image will invalidate the signature, that's what OS X complains about. Best -Tobias From lecteur at zogotounga.net Tue Oct 7 09:22:36 2014 From: lecteur at zogotounga.net (=?windows-1252?Q?St=E9phane_Rollandin?=) Date: Tue Oct 7 09:22:31 2014 Subject: [squeak-dev] Saucers for Mac broken ? In-Reply-To: References: <5433A641.9000605@zogotounga.net> Message-ID: <5433B0DC.9000909@zogotounga.net> Le 07/10/2014 10:47, Wolfgang Eder a ?crit : > it depends on your mac security settings. > if you have them at ?mac app store? or ?mac app store and verified developers?, > then the mac complains that the app is broken and wants to move it to the trash. > if you have them at ?no limitations? the mac complains that it has been downloaded > from the internet, but you can start and run it (and it works). > kind regards > wolfgang Ah, thanks. Stef From lecteur at zogotounga.net Tue Oct 7 09:27:18 2014 From: lecteur at zogotounga.net (=?windows-1252?Q?St=E9phane_Rollandin?=) Date: Tue Oct 7 09:27:13 2014 Subject: [squeak-dev] Saucers for Mac broken ? In-Reply-To: References: <5433A641.9000605@zogotounga.net> Message-ID: <5433B1F6.6050307@zogotounga.net> > The 4.5 all-in-one is code-signed, so replacing the image will invalidate the signature, > that's what OS X complains about. So what is the correct way to create a all-in-one from a Windows system ? Stef From lecteur at zogotounga.net Tue Oct 7 09:32:10 2014 From: lecteur at zogotounga.net (=?windows-1252?Q?St=E9phane_Rollandin?=) Date: Tue Oct 7 09:32:07 2014 Subject: [squeak-dev] Saucers for Mac broken ? In-Reply-To: <72487F02E6B04636841EED596C8AA234@gmail.com> References: <5433A641.9000605@zogotounga.net> <72487F02E6B04636841EED596C8AA234@gmail.com> Message-ID: <5433B31A.70301@zogotounga.net> > I try it on my macs, (have severals) and works > I wish the source code for including in FunSqueak4.6 :=) The image is hacked at a few critical points, so I cannot make it into a loadable package that would be a good citizen wrt other packages. It disable hibernation of Forms, for example. Stef From asqueaker at gmail.com Tue Oct 7 16:03:09 2014 From: asqueaker at gmail.com (Chris Muller) Date: Tue Oct 7 16:03:11 2014 Subject: [squeak-dev] A small convenience update to OSProcess/CommandShell In-Reply-To: <20141006233644.GA57411@shell.msen.com> References: <20141006233644.GA57411@shell.msen.com> Message-ID: A good improvement! On Mon, Oct 6, 2014 at 6:36 PM, David T. Lewis wrote: > I have updated OSProcess/CommandShell with some changes that allow > PipeableOSProcess to be used more conveniently for executing commands on > a Unix/Linux/OSX system. You can now run a simple command without worrying > about closing (pipe) file handles or other special handling. For example: > > ( PipeableOSProcess command: 'ls -l' ) output > > Explanation: PipeableOSProcess was originally designed to support command > pipeline execution within a CommandShell. In that scenario, the command shell > handles all setup and cleanup of pipe handles. In practice, PipeableOSProcess > turns out to be useful for simple command execution with input and output > pipes connected to the image. The updates to PipeableOSProcess class>>command: > add the necessary setup and cleanup that would otherwise have been done by > the command shell. > > OSProcess and CommandShell are on SqueakMap (select the "head" version to > get the latest), or from the squeaksource repository at: > > http://www.squeaksource.com/OSProcess > http://www.squeaksource.com/CommandShell > > Dave > > From asqueaker at gmail.com Tue Oct 7 19:41:02 2014 From: asqueaker at gmail.com (Chris Muller) Date: Tue Oct 7 19:41:04 2014 Subject: [squeak-dev] What is the contract of SocketStream>>#next:? Message-ID: Assuming its 'shouldSignal' is true, if I say: mySocketStream next: 4 shouldn't I be guaranteed either 4 bytes of data, or an exception (Timeout or ConnectionClosed)? But, never less than 4 bytes of data, right? Over the last few weeks I have been running very heavy networking and noticed several times "SocketStream>>#next: 4" returning me either an empty Array or nil. I've seen it more than once but can't reproduce it. Wouldn't that have to be a bug? From nicolas.cellier.aka.nice at gmail.com Tue Oct 7 20:42:52 2014 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue Oct 7 20:42:55 2014 Subject: [squeak-dev] What is the contract of SocketStream>>#next:? In-Reply-To: References: Message-ID: Since (String new readStream next: 4) answers an empty string, so at least this seem consistent with the rest... Some dialects have something like nextAvailable: 4 for this behavior and let next: 4 raise an exception, but not Squeak. 2014-10-07 21:41 GMT+02:00 Chris Muller : > Assuming its 'shouldSignal' is true, if I say: > > mySocketStream next: 4 > > shouldn't I be guaranteed either 4 bytes of data, or an exception > (Timeout or ConnectionClosed)? But, never less than 4 bytes of data, > right? > > Over the last few weeks I have been running very heavy networking and > noticed several times "SocketStream>>#next: 4" returning me either an > empty Array or nil. I've seen it more than once but can't reproduce > it. > > Wouldn't that have to be a bug? > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141007/3a355496/attachment.htm From asqueaker at gmail.com Tue Oct 7 21:40:01 2014 From: asqueaker at gmail.com (Chris Muller) Date: Tue Oct 7 21:40:03 2014 Subject: [squeak-dev] What is the contract of SocketStream>>#next:? In-Reply-To: References: Message-ID: On Tue, Oct 7, 2014 at 3:42 PM, Nicolas Cellier wrote: > Since (String new readStream next: 4) answers an empty string, so at least > this seem consistent with the rest... > Some dialects have something like nextAvailable: 4 for this behavior and let > next: 4 raise an exception, but not Squeak. I get your point about consistency but isn't that impossible / unusable for SocketStream? Because there would be no way to discern the difference between a Timeout and EOD (end of data). I feel I should be able to write: header := mySocketStream next: 4 and not have to check the length of header before I access it. Otherwise, please tell me what I should have to do if I get only 3 bytes of data back when I need and expect 4? Treat it the same as a Timeout? Or loop try again? Aren't those what SocketStream should be doing for me? From commits at source.squeak.org Wed Oct 8 10:29:00 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 8 10:29:02 2014 Subject: [squeak-dev] The Trunk: Collections-ul.584.mcz Message-ID: Levente Uzonyi uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-ul.584.mcz ==================== Summary ==================== Name: Collections-ul.584 Author: ul Time: 8 October 2014, 12:27:20.538 pm UUID: 804f22d8-8350-4e41-b218-3ab57aa6a6cb Ancestors: Collections-nice.583 Character changes: - use the value instance variable instead of #asciiValue where possible - implemented #<= and #>= =============== Diff against Collections-nice.583 =============== Item was changed: ----- Method: Character>>< (in category 'comparing') ----- < aCharacter "Answer true if the receiver's value < aCharacter's value." + ^value < aCharacter asciiValue! - ^self asciiValue < aCharacter asciiValue! Item was added: + ----- Method: Character>><= (in category 'comparing') ----- + <= aCharacter + "Answer true if the receiver's value <= aCharacter's value." + + ^value <= aCharacter asciiValue! Item was changed: ----- Method: Character>>= (in category 'comparing') ----- = aCharacter ^self == aCharacter or: [ + aCharacter isCharacter and: [ aCharacter asciiValue = value ] ]! - aCharacter isCharacter and: [ self asciiValue = aCharacter asciiValue ] ]! Item was changed: ----- Method: Character>>> (in category 'comparing') ----- > aCharacter "Answer true if the receiver's value > aCharacter's value." + ^value > aCharacter asciiValue! - ^self asciiValue > aCharacter asciiValue! Item was added: + ----- Method: Character>>>= (in category 'comparing') ----- + >= aCharacter + "Answer true if the receiver's value >= aCharacter's value." + + ^value >= aCharacter asciiValue! Item was changed: ----- Method: Character>>codePoint (in category 'accessing') ----- codePoint "Return the encoding value of the receiver." #Fundmntl. + + ^value! - ^ self asciiValue! Item was changed: ----- Method: Character>>macToSqueak (in category 'converting') ----- macToSqueak "Convert the receiver from MacRoman to Squeak encoding" | asciiValue | value < 128 ifTrue: [^ self]. value > 255 ifTrue: [^ self]. asciiValue := #[ 196 197 199 201 209 214 220 225 224 226 228 227 229 231 233 232 "80-8F" 234 235 237 236 238 239 241 243 242 244 246 245 250 249 251 252 "90-9F" 134 176 162 163 167 149 182 223 174 169 153 180 168 128 198 216 "A0-AF" 129 177 138 141 165 181 142 143 144 154 157 170 186 158 230 248 "B0-BF" 191 161 172 166 131 173 178 171 187 133 160 192 195 213 140 156 "C0-CF" 150 151 147 148 145 146 247 179 255 159 185 164 139 155 188 189 "D0-DF" 135 183 130 132 137 194 202 193 203 200 205 206 207 204 211 212 "E0-EF" 190 210 218 219 217 208 136 152 175 215 221 222 184 240 253 254 ] "F0-FF" + at: value - 127. - at: self asciiValue - 127. ^ Character value: asciiValue.! Item was changed: ----- Method: Character>>to: (in category 'converting') ----- to: other "Answer with a collection in ascii order -- $a to: $z" + ^ (value to: other asciiValue) - ^ (self asciiValue to: other asciiValue) collect: [:ascii | Character value: ascii] as: String! From commits at source.squeak.org Wed Oct 8 10:39:11 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 8 10:39:13 2014 Subject: [squeak-dev] The Trunk: KernelTests-ul.278.mcz Message-ID: Levente Uzonyi uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-ul.278.mcz ==================== Summary ==================== Name: KernelTests-ul.278 Author: ul Time: 8 October 2014, 12:38:15.725 pm UUID: 6ee3d1ac-77c4-4550-bff8-7db203c28f50 Ancestors: KernelTests-dtl.277 RandomTest changes: - updated #testWellKnownSequence to match the new seed hashing values - added two new test cases for edge case seed values =============== Diff against KernelTests-dtl.277 =============== Item was changed: ----- Method: RandomTest>>testNext (in category 'tests') ----- testNext 10000 timesRepeat: [ | next | next := gen next. + self assert: next >= 0.0. + self assert: next < 1.0 ].! - self assert: (next >= 0). - self assert: (next < 1). - ].! Item was added: + ----- Method: RandomTest>>testNextForEdgeCases (in category 'tests') ----- + testNextForEdgeCases + " Test #next for edge case input-output pairs " + + self assert: 0.0 equals: (Random seed: 1407677000) next. + self assert: (1 << 31 - 1) asFloat / (1 << 31) asFloat equals: (Random seed: 0) next! Item was added: + ----- Method: RandomTest>>testNextValueForEdgeCases (in category 'tests') ----- + testNextValueForEdgeCases + " Test #nextValue for edge case input-output pairs " + + self assert: 1.0 equals: (Random seed: 1407677000) nextValue. + self assert: (1 << 31 - 1) asFloat equals: (Random seed: 0) nextValue! Item was changed: ----- Method: RandomTest>>testWellKnownSequence (in category 'tests') ----- testWellKnownSequence "This test assert the immutability of Random generation algorithm. It uses Float equality tests, which is a very strict notion of immutability. Anyone changing Random algorithm will have to adapt this test." | theSeedOfWellKnownSequence wellKnownSequence rng effectiveSequence | theSeedOfWellKnownSequence := 2345678901. + wellKnownSequence := #(0.32506402597067136 0.3510923149767762 0.8085456405806102 0.22658906421930952 0.28241015983857687 0.46756423286514553 0.3520695904046621 0.23361375705972953 0.3464227287780599 0.32681039875690376). - wellKnownSequence := #(0.14924326965084453 0.3316330217437972 0.7561964480002394 0.3937015400238808 0.9417831813645471 0.5499291939427746 0.6599625962134277 0.991354559078512 0.6960744325518955 0.922987899707159 ). rng := Random new. rng seed: theSeedOfWellKnownSequence. effectiveSequence := (1 to: 10) collect: [:i | rng next ]. self assert: effectiveSequence equals: wellKnownSequence! From commits at source.squeak.org Wed Oct 8 20:54:16 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 8 20:54:18 2014 Subject: [squeak-dev] The Trunk: Compiler-eem.290.mcz Message-ID: Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.290.mcz ==================== Summary ==================== Name: Compiler-eem.290 Author: eem Time: 8 October 2014, 1:53:43.085 pm UUID: a2799479-1a99-45c4-b17c-4160d19b04e3 Ancestors: Compiler-eem.289 Define the other extension acessor, the one that locates extensions before an extended bytecode. Tighten up the comment on the one that accesses the extension bytecodes themselves. =============== Diff against Compiler-eem.289 =============== Item was changed: ----- Method: BytecodeEncoder class>>extensionsAt:in:into: (in category 'instruction stream support') ----- extensionsAt: pc in: aCompiledMethod into: trinaryBlock "If the bytecode at pc is an extension then evaluate aTrinaryBlock with the values of extA and extB and number of extension *bytes*. + If the bytecode at pc is not an extension then evaluate with 0, 0, 0." - If the bytecode at pc is not extended then evaluate with 0, 0, 0." self subclassResponsibility! Item was added: + ----- Method: BytecodeEncoder class>>extensionsFor:in:into: (in category 'instruction stream support') ----- + extensionsFor: pc in: aCompiledMethod into: trinaryBlock + "If the bytecode at pc is an extension, or if the bytecode at pc is preceeded by extensions, + then evaluate aTrinaryBlock with the values of extA and extB and number of extension *bytes*. + If the bytecode at pc is neither an extension or extended then evaluate with 0, 0, 0." + + self subclassResponsibility! Item was changed: ----- Method: EncoderForV3 class>>extensionsAt:in:into: (in category 'instruction stream support') ----- extensionsAt: pc in: aCompiledMethod into: trinaryBlock "If the bytecode at pc is an extension then evaluate aTrinaryBlock with the values of extA and extB and number of extension *bytes*. + If the bytecode at pc is not an extension then evaluate with 0, 0, 0. - If the bytecode at pc is not extended then evaluate with 0, 0, 0. There are no extensions in the SqueakV3/Smalltalk-80 bytecode set, so..." ^trinaryBlock value: 0 value: 0 value: 0! Item was added: + ----- Method: EncoderForV3 class>>extensionsFor:in:into: (in category 'instruction stream support') ----- + extensionsFor: pc in: aCompiledMethod into: trinaryBlock + "If the bytecode at pc is an extension, or if the bytecode at pc is preceeded by extensions, + then evaluate aTrinaryBlock with the values of extA and extB and number of extension *bytes*. + If the bytecode at pc is neither an extension or extended then evaluate with 0, 0, 0. + There are no extensions in the SqueakV3/Smalltalk-80 bytecode set, so..." + ^trinaryBlock value: 0 value: 0 value: 0! From eliot.miranda at gmail.com Wed Oct 8 23:12:05 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 8 23:12:09 2014 Subject: [squeak-dev] .mcd to .mcz (urgent) Message-ID: Hi All, so *how* do I ensure I have a .mcz when there appears to only be a .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from trunk when Kernel-ul.875(eem.872).mcd appears to be on offer. If I try MCCacheRepository default storeVersion: (trunk versionNamed: 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my cache repository. I'm f*&^%d until I can get this working. help, please! -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141008/ae3e7526/attachment.htm From commits at source.squeak.org Wed Oct 8 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 8 23:55:04 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141008235502.12082.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007316.html Name: Collections-ul.584 Ancestors: Collections-nice.583 Character changes: - use the value instance variable instead of #asciiValue where possible - implemented #<= and #>= ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007317.html Name: KernelTests-ul.278 Ancestors: KernelTests-dtl.277 RandomTest changes: - updated #testWellKnownSequence to match the new seed hashing values - added two new test cases for edge case seed values ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007318.html Name: Compiler-eem.290 Ancestors: Compiler-eem.289 Define the other extension acessor, the one that locates extensions before an extended bytecode. Tighten up the comment on the one that accesses the extension bytecodes themselves. ============================================= From eliot.miranda at gmail.com Thu Oct 9 00:37:39 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 9 00:37:42 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: OK here's what I came up with, and it's not pretty. But it is useful. Should this be included in MCCacheRepository or MCFileBasedRepository as a general facility? IMO, yes, to have some poor soul going down this same route. But I want to canvas opinion first. Nte that one wpould think all one had to do was cacheRepo storeVersion: (repo versionNamed: versionName). but MCCacheRepository defeats that simple route with MCCacheRepository >>basicStoreVersion: aVersion (aVersion isCacheable not or: [self allFileNames includes: aVersion fileName]) ifFalse: [super basicStoreVersion: aVersion] So that leaves the brute-force: cachedNonDiffyVersionNamed: versionName from: repo "Make sure that the cache contains a non-diffy version of versionName and answer it." | cacheRepo | self assert: (versionName endsWith: '.mcz'). cacheRepo := MCCacheRepository default. "Make sure that at least the diffy (.mcd) version is present" (cacheRepo directory includesKey: versionName) ifFalse: [cacheRepo storeVersion: (repo versionNamed: versionName)]. "if after storeVersion there's still no .mcz we need to create one; sigh..." (cacheRepo directory includesKey: versionName) ifFalse: [| baseName diffyVersionName diffyVersion file delete | baseName := versionName allButLast: 4. "strip .mcz" diffyVersionName := cacheRepo directory fileNames detect: [:fn| (fn endsWith: '.mcd') and: [(fn copyUpTo: $() = baseName]]. diffyVersion := cacheRepo versionNamed: diffyVersionName. file := cacheRepo directory newFileNamed: versionName. delete := false. [file binary. [MCMczWriter fileOut: diffyVersion on: file] on: Error do: [:ex| delete := true. "don't leave half-formed .mcz files around to screw things up later on..." ex pass]] ensure: [file close. delete ifTrue: [cacheRepo directory deleteFileNamed: versionName]]. "now delete the damn diffy version that caused all the pain in the first place" delete ifFalse: [cacheRepo directory deleteFileNamed: diffyVersionName]. cacheRepo cacheAllFilenames]. ^cacheRepo versionNamed: versionName On Wed, Oct 8, 2014 at 4:12 PM, Eliot Miranda wrote: > Hi All, > > so *how* do I ensure I have a .mcz when there appears to only be a > .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from trunk > when Kernel-ul.875(eem.872).mcd appears to be on offer. If I try > > MCCacheRepository default storeVersion: (trunk versionNamed: > 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my cache > repository. I'm f*&^%d until I can get this working. help, please! > > -- > best, > Eliot > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141008/9abf3d16/attachment.htm From asqueaker at gmail.com Thu Oct 9 00:59:19 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 9 00:59:22 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: Hi, I'm sure it would help to understand the broader context of why the .mcd doesn't meet your needs. I assume you must have some external (non-Smalltalk) tool unzipping the mcz to get at the contents? Because if you were only accessing via the MCRepository API's then mcd shouldn't matter. I think you're on the right track with the cacheRepo storeVersion: (repo versionNamed: versionName). approach, because that lets the Repository "do its job" the way it wants or needs to, able to assume its users would only care about the objects returned, not its private, internal storage format. There is a 'alwaysStoreDiffs' option for every Repository, so it might help to make sure that's turned off on your CacheRepository. But I know that's not what you want if the incoming is _already_ a mcd, because you want a 'alwaysStoreFull', but I'm not sure why.. On Wed, Oct 8, 2014 at 7:37 PM, Eliot Miranda wrote: > OK here's what I came up with, and it's not pretty. But it is useful. > Should this be included in MCCacheRepository or MCFileBasedRepository as a > general facility? IMO, yes, to have some poor soul going down this same > route. But I want to canvas opinion first. Nte that one wpould think all > one had to do was > > cacheRepo storeVersion: (repo versionNamed: versionName). > > but MCCacheRepository defeats that simple route with > > MCCacheRepository >>basicStoreVersion: aVersion > (aVersion isCacheable not or: [self allFileNames includes: aVersion > fileName]) > ifFalse: [super basicStoreVersion: aVersion] > > So that leaves the brute-force: > > cachedNonDiffyVersionNamed: versionName from: repo > "Make sure that the cache contains a non-diffy version of versionName and > answer it." > | cacheRepo | > self assert: (versionName endsWith: '.mcz'). > cacheRepo := MCCacheRepository default. > "Make sure that at least the diffy (.mcd) version is present" > (cacheRepo directory includesKey: versionName) ifFalse: > [cacheRepo storeVersion: (repo versionNamed: versionName)]. > "if after storeVersion there's still no .mcz we need to create one; sigh..." > (cacheRepo directory includesKey: versionName) ifFalse: > [| baseName diffyVersionName diffyVersion file delete | > baseName := versionName allButLast: 4. "strip .mcz" > diffyVersionName := cacheRepo directory fileNames detect: [:fn| (fn > endsWith: '.mcd') and: [(fn copyUpTo: $() = baseName]]. > diffyVersion := cacheRepo versionNamed: diffyVersionName. > file := cacheRepo directory newFileNamed: versionName. > delete := false. > [file binary. > [MCMczWriter fileOut: diffyVersion on: file] > on: Error > do: [:ex| > delete := true. "don't leave half-formed .mcz files around to screw things > up later on..." > ex pass]] > ensure: > [file close. > delete ifTrue: > [cacheRepo directory deleteFileNamed: versionName]]. > "now delete the damn diffy version that caused all the pain in the first > place" > delete ifFalse: > [cacheRepo directory deleteFileNamed: diffyVersionName]. > cacheRepo cacheAllFilenames]. > ^cacheRepo versionNamed: versionName > > On Wed, Oct 8, 2014 at 4:12 PM, Eliot Miranda > wrote: >> >> Hi All, >> >> so *how* do I ensure I have a .mcz when there appears to only be a >> .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from trunk when >> Kernel-ul.875(eem.872).mcd appears to be on offer. If I try >> >> MCCacheRepository default storeVersion: (trunk versionNamed: >> 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my cache >> repository. I'm f*&^%d until I can get this working. help, please! >> >> -- >> best, >> Eliot > > > > > -- > best, > Eliot > > > From eliot.miranda at gmail.com Thu Oct 9 01:05:40 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 9 01:05:43 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: On Wed, Oct 8, 2014 at 5:59 PM, Chris Muller wrote: > Hi, I'm sure it would help to understand the broader context of why > the .mcd doesn't meet your needs. I assume you must have some > external (non-Smalltalk) tool unzipping the mcz to get at the > contents? Because if you were only accessing via the MCRepository > API's then mcd shouldn't matter. > The Spur bootstrap depends on being able to generate patched files. I could, had I known the syetem better, have produced those patches as mcd's, but have produced them as .mczs. IMO mcd is a premature optimization, saving a littel bit I think you're on the right track with the > > cacheRepo storeVersion: (repo versionNamed: versionName). > > approach, because that lets the Repository "do its job" the way it > wants or needs to, able to assume its users would only care about the > objects returned, not its private, internal storage format. > There really should be an "If I say store a version I mean it" API that means that diffy versions can be stored. It's a PITA not having this. > > There is a 'alwaysStoreDiffs' option for every Repository, so it might > help to make sure that's turned off on your CacheRepository. But I > know that's not what you want if the incoming is _already_ a mcd, > because you want a 'alwaysStoreFull', but I'm not sure why.. > Um, the cache repository's value is indeed false (actually nil, which defaults to false). But the storeVersion code doesn't pay attention to that flag. > > On Wed, Oct 8, 2014 at 7:37 PM, Eliot Miranda > wrote: > > OK here's what I came up with, and it's not pretty. But it is useful. > > Should this be included in MCCacheRepository or MCFileBasedRepository as > a > > general facility? IMO, yes, to have some poor soul going down this same > > route. But I want to canvas opinion first. Nte that one wpould think > all > > one had to do was > > > > cacheRepo storeVersion: (repo versionNamed: versionName). > > > > but MCCacheRepository defeats that simple route with > > > > MCCacheRepository >>basicStoreVersion: aVersion > > (aVersion isCacheable not or: [self allFileNames includes: aVersion > > fileName]) > > ifFalse: [super basicStoreVersion: aVersion] > > > > So that leaves the brute-force: > > > > cachedNonDiffyVersionNamed: versionName from: repo > > "Make sure that the cache contains a non-diffy version of versionName and > > answer it." > > | cacheRepo | > > self assert: (versionName endsWith: '.mcz'). > > cacheRepo := MCCacheRepository default. > > "Make sure that at least the diffy (.mcd) version is present" > > (cacheRepo directory includesKey: versionName) ifFalse: > > [cacheRepo storeVersion: (repo versionNamed: versionName)]. > > "if after storeVersion there's still no .mcz we need to create one; > sigh..." > > (cacheRepo directory includesKey: versionName) ifFalse: > > [| baseName diffyVersionName diffyVersion file delete | > > baseName := versionName allButLast: 4. "strip .mcz" > > diffyVersionName := cacheRepo directory fileNames detect: [:fn| (fn > > endsWith: '.mcd') and: [(fn copyUpTo: $() = baseName]]. > > diffyVersion := cacheRepo versionNamed: diffyVersionName. > > file := cacheRepo directory newFileNamed: versionName. > > delete := false. > > [file binary. > > [MCMczWriter fileOut: diffyVersion on: file] > > on: Error > > do: [:ex| > > delete := true. "don't leave half-formed .mcz files around to screw > things > > up later on..." > > ex pass]] > > ensure: > > [file close. > > delete ifTrue: > > [cacheRepo directory deleteFileNamed: versionName]]. > > "now delete the damn diffy version that caused all the pain in the first > > place" > > delete ifFalse: > > [cacheRepo directory deleteFileNamed: diffyVersionName]. > > cacheRepo cacheAllFilenames]. > > ^cacheRepo versionNamed: versionName > > > > On Wed, Oct 8, 2014 at 4:12 PM, Eliot Miranda > > wrote: > >> > >> Hi All, > >> > >> so *how* do I ensure I have a .mcz when there appears to only be a > >> .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from trunk > when > >> Kernel-ul.875(eem.872).mcd appears to be on offer. If I try > >> > >> MCCacheRepository default storeVersion: (trunk versionNamed: > >> 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my cache > >> repository. I'm f*&^%d until I can get this working. help, please! > >> > >> -- > >> best, > >> Eliot > > > > > > > > > > -- > > best, > > Eliot > > > > > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141008/33e5851c/attachment.htm From eliot.miranda at gmail.com Thu Oct 9 01:06:17 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 9 01:06:21 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: On Wed, Oct 8, 2014 at 6:05 PM, Eliot Miranda wrote: > > > On Wed, Oct 8, 2014 at 5:59 PM, Chris Muller wrote: > >> Hi, I'm sure it would help to understand the broader context of why >> the .mcd doesn't meet your needs. I assume you must have some >> external (non-Smalltalk) tool unzipping the mcz to get at the >> contents? Because if you were only accessing via the MCRepository >> API's then mcd shouldn't matter. >> > > The Spur bootstrap depends on being able to generate patched files. I > could, had I known the syetem better, have produced those patches as mcd's, > but have produced them as .mczs. IMO mcd is a premature optimization, > saving a littel bit > oops. ignore the partial sentence. I had meant to delete it ;-) > > I think you're on the right track with the >> >> cacheRepo storeVersion: (repo versionNamed: versionName). >> >> approach, because that lets the Repository "do its job" the way it >> wants or needs to, able to assume its users would only care about the >> objects returned, not its private, internal storage format. >> > > There really should be an "If I say store a version I mean it" API that > means that diffy versions can be stored. It's a PITA not having this. > > >> >> There is a 'alwaysStoreDiffs' option for every Repository, so it might >> help to make sure that's turned off on your CacheRepository. But I >> know that's not what you want if the incoming is _already_ a mcd, >> because you want a 'alwaysStoreFull', but I'm not sure why.. >> > > Um, the cache repository's value is indeed false (actually nil, which > defaults to false). But the storeVersion code doesn't pay attention to > that flag. > > >> >> On Wed, Oct 8, 2014 at 7:37 PM, Eliot Miranda >> wrote: >> > OK here's what I came up with, and it's not pretty. But it is useful. >> > Should this be included in MCCacheRepository or MCFileBasedRepository >> as a >> > general facility? IMO, yes, to have some poor soul going down this same >> > route. But I want to canvas opinion first. Nte that one wpould think >> all >> > one had to do was >> > >> > cacheRepo storeVersion: (repo versionNamed: versionName). >> > >> > but MCCacheRepository defeats that simple route with >> > >> > MCCacheRepository >>basicStoreVersion: aVersion >> > (aVersion isCacheable not or: [self allFileNames includes: aVersion >> > fileName]) >> > ifFalse: [super basicStoreVersion: aVersion] >> > >> > So that leaves the brute-force: >> > >> > cachedNonDiffyVersionNamed: versionName from: repo >> > "Make sure that the cache contains a non-diffy version of versionName >> and >> > answer it." >> > | cacheRepo | >> > self assert: (versionName endsWith: '.mcz'). >> > cacheRepo := MCCacheRepository default. >> > "Make sure that at least the diffy (.mcd) version is present" >> > (cacheRepo directory includesKey: versionName) ifFalse: >> > [cacheRepo storeVersion: (repo versionNamed: versionName)]. >> > "if after storeVersion there's still no .mcz we need to create one; >> sigh..." >> > (cacheRepo directory includesKey: versionName) ifFalse: >> > [| baseName diffyVersionName diffyVersion file delete | >> > baseName := versionName allButLast: 4. "strip .mcz" >> > diffyVersionName := cacheRepo directory fileNames detect: [:fn| (fn >> > endsWith: '.mcd') and: [(fn copyUpTo: $() = baseName]]. >> > diffyVersion := cacheRepo versionNamed: diffyVersionName. >> > file := cacheRepo directory newFileNamed: versionName. >> > delete := false. >> > [file binary. >> > [MCMczWriter fileOut: diffyVersion on: file] >> > on: Error >> > do: [:ex| >> > delete := true. "don't leave half-formed .mcz files around to screw >> things >> > up later on..." >> > ex pass]] >> > ensure: >> > [file close. >> > delete ifTrue: >> > [cacheRepo directory deleteFileNamed: versionName]]. >> > "now delete the damn diffy version that caused all the pain in the first >> > place" >> > delete ifFalse: >> > [cacheRepo directory deleteFileNamed: diffyVersionName]. >> > cacheRepo cacheAllFilenames]. >> > ^cacheRepo versionNamed: versionName >> > >> > On Wed, Oct 8, 2014 at 4:12 PM, Eliot Miranda >> > wrote: >> >> >> >> Hi All, >> >> >> >> so *how* do I ensure I have a .mcz when there appears to only be a >> >> .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from trunk >> when >> >> Kernel-ul.875(eem.872).mcd appears to be on offer. If I try >> >> >> >> MCCacheRepository default storeVersion: (trunk versionNamed: >> >> 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my cache >> >> repository. I'm f*&^%d until I can get this working. help, please! >> >> >> >> -- >> >> best, >> >> Eliot >> > >> > >> > >> > >> > -- >> > best, >> > Eliot >> > >> > >> > >> >> > > > -- > best, > Eliot > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141008/da0184cf/attachment.htm From ma.chris.m at gmail.com Thu Oct 9 01:20:36 2014 From: ma.chris.m at gmail.com (Chris Muller) Date: Thu Oct 9 01:20:39 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: On Wed, Oct 8, 2014 at 8:05 PM, Eliot Miranda wrote: > > > On Wed, Oct 8, 2014 at 5:59 PM, Chris Muller wrote: >> >> Hi, I'm sure it would help to understand the broader context of why >> the .mcd doesn't meet your needs. I assume you must have some >> external (non-Smalltalk) tool unzipping the mcz to get at the >> contents? Because if you were only accessing via the MCRepository >> API's then mcd shouldn't matter. > > > The Spur bootstrap depends on being able to generate patched files. I > could, had I known the syetem better, have produced those patches as mcd's, > but have produced them as .mczs. Okay, but when you generate those patched mcd's, they are still based off the prior version, so I'm still having trouble understanding why Spur bootstrap would have any trouble reading a mcd.. >IMO mcd is a premature optimization, > saving a littel bit > >> I think you're on the right track with the >> >> cacheRepo storeVersion: (repo versionNamed: versionName). >> >> approach, because that lets the Repository "do its job" the way it >> wants or needs to, able to assume its users would only care about the >> objects returned, not its private, internal storage format. > > There really should be an "If I say store a version I mean it" API that > means that diffy versions can be stored. It's a PITA not having this. It's an internal format that's supposed to be invisible to users of Repository's. I think exposing it could create PITA's.. >> There is a 'alwaysStoreDiffs' option for every Repository, so it might >> help to make sure that's turned off on your CacheRepository. But I >> know that's not what you want if the incoming is _already_ a mcd, >> because you want a 'alwaysStoreFull', but I'm not sure why.. > > > Um, the cache repository's value is indeed false (actually nil, which > defaults to false). But the storeVersion code doesn't pay attention to that > flag. Yes it does, it calls #prepareVersionForStorage: which checks it. As I said, it won't convert a mcd to a mcz, it will only convert a mcz to a mcd, which Spur should be able to read just fine assuming the ancestor of the patched package is available in a repository...? >> On Wed, Oct 8, 2014 at 7:37 PM, Eliot Miranda >> wrote: >> > OK here's what I came up with, and it's not pretty. But it is useful. >> > Should this be included in MCCacheRepository or MCFileBasedRepository as >> > a >> > general facility? IMO, yes, to have some poor soul going down this same >> > route. But I want to canvas opinion first. Nte that one wpould think >> > all >> > one had to do was >> > >> > cacheRepo storeVersion: (repo versionNamed: versionName). >> > >> > but MCCacheRepository defeats that simple route with >> > >> > MCCacheRepository >>basicStoreVersion: aVersion >> > (aVersion isCacheable not or: [self allFileNames includes: aVersion >> > fileName]) >> > ifFalse: [super basicStoreVersion: aVersion] >> > >> > So that leaves the brute-force: >> > >> > cachedNonDiffyVersionNamed: versionName from: repo >> > "Make sure that the cache contains a non-diffy version of versionName >> > and >> > answer it." >> > | cacheRepo | >> > self assert: (versionName endsWith: '.mcz'). >> > cacheRepo := MCCacheRepository default. >> > "Make sure that at least the diffy (.mcd) version is present" >> > (cacheRepo directory includesKey: versionName) ifFalse: >> > [cacheRepo storeVersion: (repo versionNamed: versionName)]. >> > "if after storeVersion there's still no .mcz we need to create one; >> > sigh..." >> > (cacheRepo directory includesKey: versionName) ifFalse: >> > [| baseName diffyVersionName diffyVersion file delete | >> > baseName := versionName allButLast: 4. "strip .mcz" >> > diffyVersionName := cacheRepo directory fileNames detect: [:fn| (fn >> > endsWith: '.mcd') and: [(fn copyUpTo: $() = baseName]]. >> > diffyVersion := cacheRepo versionNamed: diffyVersionName. >> > file := cacheRepo directory newFileNamed: versionName. >> > delete := false. >> > [file binary. >> > [MCMczWriter fileOut: diffyVersion on: file] >> > on: Error >> > do: [:ex| >> > delete := true. "don't leave half-formed .mcz files around to screw >> > things >> > up later on..." >> > ex pass]] >> > ensure: >> > [file close. >> > delete ifTrue: >> > [cacheRepo directory deleteFileNamed: versionName]]. >> > "now delete the damn diffy version that caused all the pain in the first >> > place" >> > delete ifFalse: >> > [cacheRepo directory deleteFileNamed: diffyVersionName]. >> > cacheRepo cacheAllFilenames]. >> > ^cacheRepo versionNamed: versionName >> > >> > On Wed, Oct 8, 2014 at 4:12 PM, Eliot Miranda >> > wrote: >> >> >> >> Hi All, >> >> >> >> so *how* do I ensure I have a .mcz when there appears to only be a >> >> .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from trunk >> >> when >> >> Kernel-ul.875(eem.872).mcd appears to be on offer. If I try >> >> >> >> MCCacheRepository default storeVersion: (trunk versionNamed: >> >> 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my cache >> >> repository. I'm f*&^%d until I can get this working. help, please! >> >> >> >> -- >> >> best, >> >> Eliot >> > >> > >> > >> > >> > -- >> > best, >> > Eliot >> > >> > >> > >> > > > > -- > best, > Eliot From eliot.miranda at gmail.com Thu Oct 9 02:54:42 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 9 02:54:46 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: On Wed, Oct 8, 2014 at 6:20 PM, Chris Muller wrote: > On Wed, Oct 8, 2014 at 8:05 PM, Eliot Miranda > wrote: > > > > > > On Wed, Oct 8, 2014 at 5:59 PM, Chris Muller > wrote: > >> > >> Hi, I'm sure it would help to understand the broader context of why > >> the .mcd doesn't meet your needs. I assume you must have some > >> external (non-Smalltalk) tool unzipping the mcz to get at the > >> contents? Because if you were only accessing via the MCRepository > >> API's then mcd shouldn't matter. > > > > > > The Spur bootstrap depends on being able to generate patched files. I > > could, had I known the syetem better, have produced those patches as > mcd's, > > but have produced them as .mczs. > > Okay, but when you generate those patched mcd's, they are still based > off the prior version, so I'm still having trouble understanding why > Spur bootstrap would have any trouble reading a mcd.. > I don't generate patches mcds. I generate patched mczs. The issue is that some versions are only available as mcds and need to be cnverted into mczs before they can be patched. An annoying associated issue is that the query available version interface blurs the distinction between mczs and mcds so if you ask for an mcz and the repository has an mcd it'll tell you it has the version but it doesn't. It only has the mcd. Further there's no convenient way to get the mcz form the mcd. Thats why I had to write the below, that constructs the full mcz form the mcd. > > >IMO mcd is a premature optimization, > > saving a littel bit > > > >> I think you're on the right track with the > >> > >> cacheRepo storeVersion: (repo versionNamed: versionName). > >> > >> approach, because that lets the Repository "do its job" the way it > >> wants or needs to, able to assume its users would only care about the > >> objects returned, not its private, internal storage format. > > > > There really should be an "If I say store a version I mean it" API that > > means that diffy versions can be stored. It's a PITA not having this. > > It's an internal format that's supposed to be invisible to users of > Repository's. I think exposing it could create PITA's.. > mcd is *not* an internal format. If one interacts with repositories and asks for mczs one gets given mcds if these are what's available. It would be *great* if they were an internal format but I assure you they're not. > > >> There is a 'alwaysStoreDiffs' option for every Repository, so it might > >> help to make sure that's turned off on your CacheRepository. But I > >> know that's not what you want if the incoming is _already_ a mcd, > >> because you want a 'alwaysStoreFull', but I'm not sure why.. > > > > > > Um, the cache repository's value is indeed false (actually nil, which > > defaults to false). But the storeVersion code doesn't pay attention to > that > > flag. > > Yes it does, it calls #prepareVersionForStorage: which checks it. As > I said, it won't convert a mcd to a mcz, it will only convert a mcz to > a mcd, which Spur should be able to read just fine assuming the > ancestor of the patched package is available in a repository...? > Did you see my comment below re basicStoreVersion: ? Prepare version for storage will arrange to store a diffy version from a full version, but it *won't* arrange to store a full version from a diffy version. But later on MCCacheRepository >>basicStoreVersion: refuses to store anything anyway. I wouldn't have written the below if mcd's weren't a problem. I'm not a masochist ;-) >> On Wed, Oct 8, 2014 at 7:37 PM, Eliot Miranda > >> wrote: > >> > OK here's what I came up with, and it's not pretty. But it is useful. > >> > Should this be included in MCCacheRepository or MCFileBasedRepository > as > >> > a > >> > general facility? IMO, yes, to have some poor soul going down this > same > >> > route. But I want to canvas opinion first. Nte that one wpould think > >> > all > >> > one had to do was > >> > > >> > cacheRepo storeVersion: (repo versionNamed: versionName). > >> > > >> > but MCCacheRepository defeats that simple route with > >> > > >> > MCCacheRepository >>basicStoreVersion: aVersion > >> > (aVersion isCacheable not or: [self allFileNames includes: aVersion > >> > fileName]) > >> > ifFalse: [super basicStoreVersion: aVersion] > >> > > >> > So that leaves the brute-force: > >> > > >> > cachedNonDiffyVersionNamed: versionName from: repo > >> > "Make sure that the cache contains a non-diffy version of versionName > >> > and > >> > answer it." > >> > | cacheRepo | > >> > self assert: (versionName endsWith: '.mcz'). > >> > cacheRepo := MCCacheRepository default. > >> > "Make sure that at least the diffy (.mcd) version is present" > >> > (cacheRepo directory includesKey: versionName) ifFalse: > >> > [cacheRepo storeVersion: (repo versionNamed: versionName)]. > >> > "if after storeVersion there's still no .mcz we need to create one; > >> > sigh..." > >> > (cacheRepo directory includesKey: versionName) ifFalse: > >> > [| baseName diffyVersionName diffyVersion file delete | > >> > baseName := versionName allButLast: 4. "strip .mcz" > >> > diffyVersionName := cacheRepo directory fileNames detect: [:fn| (fn > >> > endsWith: '.mcd') and: [(fn copyUpTo: $() = baseName]]. > >> > diffyVersion := cacheRepo versionNamed: diffyVersionName. > >> > file := cacheRepo directory newFileNamed: versionName. > >> > delete := false. > >> > [file binary. > >> > [MCMczWriter fileOut: diffyVersion on: file] > >> > on: Error > >> > do: [:ex| > >> > delete := true. "don't leave half-formed .mcz files around to screw > >> > things > >> > up later on..." > >> > ex pass]] > >> > ensure: > >> > [file close. > >> > delete ifTrue: > >> > [cacheRepo directory deleteFileNamed: versionName]]. > >> > "now delete the damn diffy version that caused all the pain in the > first > >> > place" > >> > delete ifFalse: > >> > [cacheRepo directory deleteFileNamed: diffyVersionName]. > >> > cacheRepo cacheAllFilenames]. > >> > ^cacheRepo versionNamed: versionName > >> > > >> > On Wed, Oct 8, 2014 at 4:12 PM, Eliot Miranda < > eliot.miranda@gmail.com> > >> > wrote: > >> >> > >> >> Hi All, > >> >> > >> >> so *how* do I ensure I have a .mcz when there appears to only be > a > >> >> .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from trunk > >> >> when > >> >> Kernel-ul.875(eem.872).mcd appears to be on offer. If I try > >> >> > >> >> MCCacheRepository default storeVersion: (trunk versionNamed: > >> >> 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my cache > >> >> repository. I'm f*&^%d until I can get this working. help, please! > >> >> > >> >> -- > >> >> best, > >> >> Eliot > >> > > >> > > >> > > >> > > >> > -- > >> > best, > >> > Eliot > >> > > >> > > >> > > >> > > > > > > > > -- > > best, > > Eliot > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141008/144ebd64/attachment.htm From ma.chris.m at gmail.com Thu Oct 9 03:27:02 2014 From: ma.chris.m at gmail.com (Chris Muller) Date: Thu Oct 9 03:27:06 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: On Wed, Oct 8, 2014 at 9:54 PM, Eliot Miranda wrote: > > > On Wed, Oct 8, 2014 at 6:20 PM, Chris Muller wrote: >> >> On Wed, Oct 8, 2014 at 8:05 PM, Eliot Miranda >> wrote: >> > >> > >> > On Wed, Oct 8, 2014 at 5:59 PM, Chris Muller >> > wrote: >> >> >> >> Hi, I'm sure it would help to understand the broader context of why >> >> the .mcd doesn't meet your needs. I assume you must have some >> >> external (non-Smalltalk) tool unzipping the mcz to get at the >> >> contents? Because if you were only accessing via the MCRepository >> >> API's then mcd shouldn't matter. >> > >> > >> > The Spur bootstrap depends on being able to generate patched files. I >> > could, had I known the syetem better, have produced those patches as >> > mcd's, >> > but have produced them as .mczs. >> >> Okay, but when you generate those patched mcd's, they are still based >> off the prior version, so I'm still having trouble understanding why >> Spur bootstrap would have any trouble reading a mcd.. > > > I don't generate patches mcds. I generate patched mczs. The issue is that > some versions are only available as mcds and need to be cnverted into mczs > before they can be patched. If there's a case where a distinction needs to be made between diffy's and full's when interacting with a Repository (other than performance tuning) then I'm terribly interested in understanding what it is, but you keep not telling me. > An annoying associated issue is that the query > available version interface blurs the distinction between mczs and mcds so > if you ask for an mcz and the repository has an mcd it'll tell you it has > the version but it doesn't. It only has the mcd. Further there's no > convenient way to get the mcz form the mcd. Thats why I had to write the > below, that constructs the full mcz form the mcd. > > >> >> >> >IMO mcd is a premature optimization, >> > saving a littel bit >> > >> >> I think you're on the right track with the >> >> >> >> cacheRepo storeVersion: (repo versionNamed: versionName). >> >> >> >> approach, because that lets the Repository "do its job" the way it >> >> wants or needs to, able to assume its users would only care about the >> >> objects returned, not its private, internal storage format. >> > >> > There really should be an "If I say store a version I mean it" API that >> > means that diffy versions can be stored. It's a PITA not having this. >> >> It's an internal format that's supposed to be invisible to users of >> Repository's. I think exposing it could create PITA's.. > > > mcd is *not* an internal format. If one interacts with repositories and > asks for mczs one gets given mcds if these are what's available. It would > be *great* if they were an internal format but I assure you they're not. Please forgive my curiousity not being quenched by mere "assurance". :) For your patching, I assume you need access to the MCDefinitions inside the Snapshot. Whether an mcd or mcz, when accessing through the MCRepository API, you've got them all (hence my wondering if it was for external tool access) as long as the ancestor be available. >> >> There is a 'alwaysStoreDiffs' option for every Repository, so it might >> >> help to make sure that's turned off on your CacheRepository. But I >> >> know that's not what you want if the incoming is _already_ a mcd, >> >> because you want a 'alwaysStoreFull', but I'm not sure why.. >> > >> > >> > Um, the cache repository's value is indeed false (actually nil, which >> > defaults to false). But the storeVersion code doesn't pay attention to >> > that >> > flag. >> >> Yes it does, it calls #prepareVersionForStorage: which checks it. As >> I said, it won't convert a mcd to a mcz, it will only convert a mcz to >> a mcd, which Spur should be able to read just fine assuming the >> ancestor of the patched package is available in a repository...? > > > Did you see my comment below re basicStoreVersion: ? Prepare version for > storage will arrange to store a diffy version from a full version, but it > *won't* arrange to store a full version from a diffy version. But later on > MCCacheRepository >>basicStoreVersion: refuses to store anything anyway. I > wouldn't have written the below if mcd's weren't a problem. I'm not a > masochist ;-) I don't see it. 'cache' in #basicStoreVersion does not refer to the cache repository... Anyway, if that works for you I couldn't do better without understanding why I was doing it. > > >> >> On Wed, Oct 8, 2014 at 7:37 PM, Eliot Miranda >> >> wrote: >> >> > OK here's what I came up with, and it's not pretty. But it is >> >> > useful. >> >> > Should this be included in MCCacheRepository or MCFileBasedRepository >> >> > as >> >> > a >> >> > general facility? IMO, yes, to have some poor soul going down this >> >> > same >> >> > route. But I want to canvas opinion first. Nte that one wpould >> >> > think >> >> > all >> >> > one had to do was >> >> > >> >> > cacheRepo storeVersion: (repo versionNamed: versionName). >> >> > >> >> > but MCCacheRepository defeats that simple route with >> >> > >> >> > MCCacheRepository >>basicStoreVersion: aVersion >> >> > (aVersion isCacheable not or: [self allFileNames includes: aVersion >> >> > fileName]) >> >> > ifFalse: [super basicStoreVersion: aVersion] >> >> > >> >> > So that leaves the brute-force: >> >> > >> >> > cachedNonDiffyVersionNamed: versionName from: repo >> >> > "Make sure that the cache contains a non-diffy version of versionName >> >> > and >> >> > answer it." >> >> > | cacheRepo | >> >> > self assert: (versionName endsWith: '.mcz'). >> >> > cacheRepo := MCCacheRepository default. >> >> > "Make sure that at least the diffy (.mcd) version is present" >> >> > (cacheRepo directory includesKey: versionName) ifFalse: >> >> > [cacheRepo storeVersion: (repo versionNamed: versionName)]. >> >> > "if after storeVersion there's still no .mcz we need to create one; >> >> > sigh..." >> >> > (cacheRepo directory includesKey: versionName) ifFalse: >> >> > [| baseName diffyVersionName diffyVersion file delete | >> >> > baseName := versionName allButLast: 4. "strip .mcz" >> >> > diffyVersionName := cacheRepo directory fileNames detect: [:fn| (fn >> >> > endsWith: '.mcd') and: [(fn copyUpTo: $() = baseName]]. >> >> > diffyVersion := cacheRepo versionNamed: diffyVersionName. >> >> > file := cacheRepo directory newFileNamed: versionName. >> >> > delete := false. >> >> > [file binary. >> >> > [MCMczWriter fileOut: diffyVersion on: file] >> >> > on: Error >> >> > do: [:ex| >> >> > delete := true. "don't leave half-formed .mcz files around to screw >> >> > things >> >> > up later on..." >> >> > ex pass]] >> >> > ensure: >> >> > [file close. >> >> > delete ifTrue: >> >> > [cacheRepo directory deleteFileNamed: versionName]]. >> >> > "now delete the damn diffy version that caused all the pain in the >> >> > first >> >> > place" >> >> > delete ifFalse: >> >> > [cacheRepo directory deleteFileNamed: diffyVersionName]. >> >> > cacheRepo cacheAllFilenames]. >> >> > ^cacheRepo versionNamed: versionName >> >> > >> >> > On Wed, Oct 8, 2014 at 4:12 PM, Eliot Miranda >> >> > >> >> > wrote: >> >> >> >> >> >> Hi All, >> >> >> >> >> >> so *how* do I ensure I have a .mcz when there appears to only be >> >> >> a >> >> >> .mcd? I'm talking about trying to get 'Kernel-ul.875.mcz' from >> >> >> trunk >> >> >> when >> >> >> Kernel-ul.875(eem.872).mcd appears to be on offer. If I try >> >> >> >> >> >> MCCacheRepository default storeVersion: (trunk versionNamed: >> >> >> 'Kernel-ul.875.mcz') I *do not* get a 'Kernel-ul.875.mcz' in my >> >> >> cache >> >> >> repository. I'm f*&^%d until I can get this working. help, please! >> >> >> >> >> >> -- >> >> >> best, >> >> >> Eliot >> >> > >> >> > >> >> > >> >> > >> >> > -- >> >> > best, >> >> > Eliot >> >> > >> >> > >> >> > >> >> >> > >> > >> > >> > -- >> > best, >> > Eliot > > > > > -- > best, > Eliot From bert at freudenbergs.de Thu Oct 9 06:35:52 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Thu Oct 9 06:36:00 2014 Subject: [squeak-dev] Re: .mcd to .mcz (urgent) In-Reply-To: References: Message-ID: <0BD81F7E-E7DD-4743-BE4C-392BA02CE7D0@freudenbergs.de> On 09.10.2014, at 02:37, Eliot Miranda wrote: > OK here's what I came up with, and it's not pretty. But it is useful. Should this be included in MCCacheRepository or MCFileBasedRepository as a general facility? IMO, yes, to have some poor soul going down this same route. But I want to canvas opinion first. Nte that one wpould think all one had to do was > > cacheRepo storeVersion: (repo versionNamed: versionName). The whole point of MCDiffyVersion is to be efficient, and avoiding having to create and store a full snapshot. The easiest way to achieve what you want would be something like cacheRepo storeVersion: (repo versionNamed: versionName) asNonDiffyVersion. MCVersion>>asNonDiffyVersion ^self MCDiffyVersion>>asNonDiffyVersion ^MCVersion package: package info: info snapshot: self snapshot dependencies: dependencies This is untested but sounds trivial enough that it might have the chance of being right ;) - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141009/a745b71e/smime-0001.bin From commits at source.squeak.org Thu Oct 9 07:21:43 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 07:21:46 2014 Subject: [squeak-dev] The Trunk: Monticello-bf.601.mcz Message-ID: Bert Freudenberg uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-bf.601.mcz ==================== Summary ==================== Name: Monticello-bf.601 Author: bf Time: 9 October 2014, 9:20:50.628 am UUID: 3f294c63-d2cd-4517-b480-f9fbbb882ea6 Ancestors: Monticello-topa.600 Do not warn about possibly newer versions on different branch (e.g. VMMaker.oscog) =============== Diff against Monticello-topa.600 =============== Item was changed: ----- Method: MCRepository>>possiblyNewerVersionsOfAnyOf: (in category 'versions') ----- possiblyNewerVersionsOfAnyOf: versionNames "Answer a collection of MCVersionNames which might be newer versions of the versions identified by versionNames." ^self cacheAllFileNamesDuring: [ versionNames inject: OrderedCollection new into: [ : coll : eachVersionName | | eachPackageName | + eachPackageName := eachVersionName packageAndBranchName. - eachPackageName := eachVersionName packageName. (self versionNamesForPackageNamed: eachPackageName) do: + [ : eachInSelf | (eachPackageName = eachInSelf packageAndBranchName and: [ + eachInSelf versionNumber > eachVersionName versionNumber or: + [ eachInSelf versionNumber = eachVersionName versionNumber and: [ eachInSelf author ~= eachVersionName author ] ] ]) ifTrue: [ coll add: eachInSelf ] ]. - [ : eachInSelf | (eachInSelf versionNumber > eachVersionName versionNumber or: - [ eachInSelf versionNumber = eachVersionName versionNumber and: [ eachInSelf author ~= eachVersionName author ] ]) ifTrue: [ coll add: eachInSelf ] ]. coll ] ]! From craig at netjam.org Thu Oct 9 08:07:47 2014 From: craig at netjam.org (Craig Latta) Date: Thu Oct 9 08:07:52 2014 Subject: [squeak-dev] re: A small convenience update to OSProcess/CommandShell In-Reply-To: <20141006233644.GA57411@shell.msen.com> References: <20141006233644.GA57411@shell.msen.com> Message-ID: > You can now run a simple command without worrying about closing > (pipe) file handles or other special handling. For example: > > ( PipeableOSProcess command: 'ls -l' ) output Thanks! -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From craig at netjam.org Thu Oct 9 08:17:13 2014 From: craig at netjam.org (Craig Latta) Date: Thu Oct 9 08:17:21 2014 Subject: [squeak-dev] re: Saucers for Mac broken ? In-Reply-To: <5433B1F6.6050307@zogotounga.net> References: <5433A641.9000605@zogotounga.net> <5433B1F6.6050307@zogotounga.net> Message-ID: Hoi Stef-- > ...what is the correct way to create a all-in-one from a Windows > system? There is good progress on porting the open-source Mac app signing code to non-Mac platforms, but it still needs some work. And apparently you can sign with non-Apple (e.g., free) certificates and still satisfy Gatekeeper on an end-user Mac, but I don't think it'd pass review for the Apple app store (although it probably would for the Microsoft store). See [1]. -C [1] http://bit.ly/1vOxWyI (stackoverflow.com) -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From craig at netjam.org Thu Oct 9 08:19:41 2014 From: craig at netjam.org (Craig Latta) Date: Thu Oct 9 08:20:06 2014 Subject: [squeak-dev] re: What is the contract of SocketStream>>#next:? In-Reply-To: References: Message-ID: > I feel I should be able to write: > > header := mySocketStream next: 4 > > and not have to check the length of header before I access it. Yeah, Squeak socket support is broken here (and a lot of other places), I'd say. -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From stephan at stack.nl Thu Oct 9 10:30:30 2014 From: stephan at stack.nl (Stephan Eggermont) Date: Thu Oct 9 10:30:38 2014 Subject: [squeak-dev] Printing nanos in Time print24 Message-ID: Since 2009-6-25 (dtl) Time>>#print24:showSeconds:on: prints nanos. This contradicts the class and method comments. The tests carefully avoid the issue. Why was this behavior introduced, and can it safely be improved? It occurs in both Squeak and Pharo (issue 14198) Stephan From lewis at mail.msen.com Thu Oct 9 14:06:30 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Thu Oct 9 14:06:33 2014 Subject: [squeak-dev] The Trunk: Monticello-bf.601.mcz In-Reply-To: <201410090721.s997LqmJ030465@shell.msen.com> References: <201410090721.s997LqmJ030465@shell.msen.com> Message-ID: <55569.136.2.1.105.1412863590.squirrel@webmail.msen.com> > Bert Freudenberg uploaded a new version of Monticello to project The > Trunk: > http://source.squeak.org/trunk/Monticello-bf.601.mcz > > Do not warn about possibly newer versions on different branch (e.g. > VMMaker.oscog) > Thank you for this! From bert at freudenbergs.de Thu Oct 9 14:10:47 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Thu Oct 9 14:10:53 2014 Subject: [squeak-dev] The Trunk: Monticello-bf.601.mcz In-Reply-To: <55569.136.2.1.105.1412863590.squirrel@webmail.msen.com> References: <201410090721.s997LqmJ030465@shell.msen.com> <55569.136.2.1.105.1412863590.squirrel@webmail.msen.com> Message-ID: On 09.10.2014, at 16:06, David T. Lewis wrote: >> Bert Freudenberg uploaded a new version of Monticello to project The >> Trunk: >> http://source.squeak.org/trunk/Monticello-bf.601.mcz >> >> Do not warn about possibly newer versions on different branch (e.g. >> VMMaker.oscog) >> > > Thank you for this! Hehe - you should've complained earlier ;) - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141009/337abd0e/smime.bin From asqueaker at gmail.com Thu Oct 9 15:49:09 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 9 15:49:12 2014 Subject: [squeak-dev] re: What is the contract of SocketStream>>#next:? In-Reply-To: References: Message-ID: On Thu, Oct 9, 2014 at 3:19 AM, Craig Latta wrote: > >> I feel I should be able to write: >> >> header := mySocketStream next: 4 >> >> and not have to check the length of header before I access it. > > Yeah, Squeak socket support is broken here (and a lot of other > places), I'd say. That might be overstating it. I've only ever seen the issue under very heavy load, so there might be a timing bug in the SocketStream wrapper. I was just trying to confirm the contract of this method with y'all so I could proceed with scrutinizing it on that basis. > > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > From commits at source.squeak.org Thu Oct 9 17:45:10 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:45:12 2014 Subject: [squeak-dev] The Trunk: Collections.spur-nice.574.mcz Message-ID: Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections.spur-nice.574.mcz ==================== Summary ==================== Name: Collections.spur-nice.574 Author: eem Time: 9 October 2014, 10:42:51.888 am UUID: 89389e41-ddf8-4738-97fa-8854d513a681 Ancestors: Collections-nice.574, Collections.spur-ul.573 Collections-nice.574 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Less ascii/binary dance. The sender of nextString doesn't try to force ascii, anymore so the implementor doesn't have to force binary. =============== Diff against Collections-nice.574 =============== Item was changed: ==== ERROR === Error: Unrecognized class type 9 October 2014 5:45:09.37 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(Character) Arguments and temporary variables: Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(Character) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Thu Oct 9 17:45:55 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:45:57 2014 Subject: [squeak-dev] The Trunk: Compiler.spur-eem.289.mcz Message-ID: Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler.spur-eem.289.mcz ==================== Summary ==================== Name: Compiler.spur-eem.289 Author: eem Time: 9 October 2014, 10:39:46.718 am UUID: df8da696-d94a-496a-86d7-e00fa44d715f Ancestors: Compiler-eem.289, Compiler.spur-eem.288 Compiler-eem.289 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Fix doits in the codePane of a debugger opened from another debugger. e.g. before this fix 1. debug 3+4. 2. in code pane of debugger #1 debug 4+5 3. in code pane of debugger #2 debug 5+6, boom. The bug was that when the encoder creates temp names for temp vars in the debugged context, which it does by creating messages to DoItIn:'s argument 'ThisContext', if this is a level 3 debug, then the original expression would have a temp var called 'ThisContext' already and that would overwrite the 'ThisContext' argument for this level with a message send, and boom. The fix is merely to filter-out these temps and hence never overwrite DoItIn:'s 'ThisContext' argument in the scope table. =============== Diff against Compiler-eem.289 =============== Item was changed: ----- Method: BytecodeEncoder>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') ----- computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex + numArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. + numTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + numLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. + ^(CompiledMethod headerFlagForEncoder: self) + + (numArgs bitShift: 24) + + (numTemps bitShift: 18) + "+ (largeBit bitShift: 17)" "largeBit gets filled in later" + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + numLits! - "Compute the compiled method header that encodes the arguments - in the receiver's header format (see CompiledMehtod's class comment)." - self subclassResponsibility! Item was removed: - ----- Method: EncoderForV3>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') ----- - computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex - | primBits | - numTemps > 63 ifTrue: - [^self error: 'Cannot compile -- too many temporary variables']. - numLits > 255 ifTrue: - [^self error: 'Cannot compile -- too many literals']. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: "For now the high bit of primitive no. is in the 29th bit of header" - [primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. - ^(numArgs bitShift: 24) - + (numTemps bitShift: 18) - "+ (largeBit bitShift: 17)" "largeBit gets filled in later" - + (numLits bitShift: 9) - + primBits! Item was changed: ----- Method: EncoderForV3PlusClosures class>>bytecodeSize: (in category 'instruction stream support') ----- bytecodeSize: bytecode "Answer the number of bytes in the bytecode." bytecode <= 125 ifTrue: [^1]. bytecode >= 176 ifTrue: [^1]. bytecode >= 160 ifTrue: "long jumps" [^2]. bytecode >= 144 ifTrue: "short jumps" [^1]. "extensions" bytecode >= 128 ifTrue: + [^#(2 2 2 2 3 2 2 1 1 1 2 3 3 3 3 4) at: bytecode - 127]. - [^#(2 2 2 2 3 2 2 1 1 1 2 nil 3 3 3 4) at: bytecode - 127]. ^nil! Item was added: + ----- Method: EncoderForV3PlusClosures class>>callPrimitiveCode (in category 'bytecode decoding') ----- + callPrimitiveCode + "139 11101111 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256)" + ^139! Item was added: + ----- Method: EncoderForV3PlusClosures>>genCallPrimitive: (in category 'bytecode generation') ----- + genCallPrimitive: primitiveIndex + "139 11101111 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256)" + (primitiveIndex < 1 or: [primitiveIndex > 65535]) ifTrue: + [self outOfRangeError: 'primitive index' index: primitiveIndex range: 1 to: 65535]. + stream + nextPut: 139; + nextPut: (primitiveIndex bitAnd: 255); + nextPut: (primitiveIndex bitShift: -8)! Item was changed: ----- Method: MethodNode>>generate:using: (in category 'code generation') ----- generate: trailer using: aCompiledMethodClass "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass. The argument, trailer, is arbitrary but is typically either the reference to the source code that is stored with every CompiledMethod, or an encoding of the method's temporary names." + | primErrNode blkSize nLits locals literals stack header method | - | primErrNode blkSize nLits literals stack method | self generate: trailer using: aCompiledMethodClass ifQuick: [:m | encoder noteBlockExtent: (0 to: 2) hasLocals: arguments. m literalAt: 2 put: encoder associationForClass; properties: properties. ^m]. primErrNode := self primitiveErrorVariableName ifNotNil: [encoder fixTemp: self primitiveErrorVariableName]. + self ensureClosureAnalysisDone. + encoder rootNode: self. "this is for BlockNode>>sizeCodeForClosureValue:" - encoder supportsClosureOpcodes ifTrue: - [self ensureClosureAnalysisDone. - encoder rootNode: self. "this is for BlockNode>>sizeCodeForClosureValue:"]. blkSize := (block sizeCodeForEvaluatedValue: encoder) + + (primitive > 0 + ifTrue: [encoder sizeCallPrimitive: primitive] + ifFalse: [0]) + (primErrNode ifNil: [0] ifNotNil: [primErrNode index: arguments size + temporaries size; sizeCodeForStore: encoder "The VM relies on storeIntoTemp: (129)"]). + locals := arguments, temporaries, (primErrNode ifNil: [#()] ifNotNil: [{primErrNode}]). + encoder noteBlockExtent: block blockExtent hasLocals: locals. + header := encoder computeMethodHeaderForNumArgs: arguments size + numTemps: locals size + numLits: (nLits := (literals := encoder allLiterals) size) + primitive: primitive. + method := trailer + createMethod: blkSize + class: aCompiledMethodClass + header: header. - method := aCompiledMethodClass - newBytes: blkSize - trailerBytes: trailer - nArgs: arguments size - nTemps: (encoder supportsClosureOpcodes - ifTrue: [| locals | - locals := arguments, - temporaries, - (primErrNode - ifNil: [#()] - ifNotNil: [{primErrNode}]). - encoder - noteBlockExtent: block blockExtent - hasLocals: locals. - locals size] - ifFalse: [encoder maxTemp]) - nStack: 0 - nLits: (nLits := (literals := encoder allLiterals) size) - primitive: primitive. - nLits > 255 ifTrue: - [^self error: 'Too many literals referenced']. 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)]. encoder streamToMethod: method. stack := ParseStack new init. + primitive > 0 ifTrue: + [encoder genCallPrimitive: primitive. + primErrNode ifNotNil: + [primErrNode emitCodeForStore: stack encoder: encoder]]. - primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: encoder]. stack position: method numTemps. [block emitCodeForEvaluatedValue: stack encoder: encoder] on: Error "If an attempt is made to write too much code the method will be asked" do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:" ex signalerContext sender method = (CompiledMethod class>>#new:) ifTrue: [^self error: 'Compiler code size discrepancy'] ifFalse: [ex pass]]. stack position ~= (method numTemps + 1) ifTrue: [^self error: 'Compiler stack discrepancy']. encoder methodStreamPosition ~= (method size - trailer size) ifTrue: [^self error: 'Compiler code size discrepancy']. method needsFrameSize: stack size - method numTemps. method properties: properties. ^method! From commits at source.squeak.org Thu Oct 9 17:46:14 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:46:17 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.584.mcz Message-ID: Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections.spur-ul.584.mcz ==================== Summary ==================== Name: Collections.spur-ul.584 Author: eem Time: 9 October 2014, 10:43:11.427 am UUID: 73af4851-d240-41c0-89bd-6360f25f91d3 Ancestors: Collections-ul.584, Collections.spur-nice.583 Collections-ul.584 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Character changes: - use the value instance variable instead of #asciiValue where possible - implemented #<= and #>= =============== Diff against Collections-ul.584 =============== Item was changed: ==== ERROR === Error: Unrecognized class type 9 October 2014 5:46:13.493 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(Character) Arguments and temporary variables: Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(Character) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Thu Oct 9 17:46:29 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:46:31 2014 Subject: [squeak-dev] The Trunk: Compiler.spur-eem.290.mcz Message-ID: Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler.spur-eem.290.mcz ==================== Summary ==================== Name: Compiler.spur-eem.290 Author: eem Time: 9 October 2014, 10:39:47.456 am UUID: e9930511-da13-4bdb-8422-9236f0cb138c Ancestors: Compiler-eem.290, Compiler.spur-eem.289 Compiler-eem.290 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Define the other extension acessor, the one that locates extensions before an extended bytecode. Tighten up the comment on the one that accesses the extension bytecodes themselves. =============== Diff against Compiler-eem.290 =============== Item was changed: ----- Method: BytecodeEncoder>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') ----- computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex + numArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. + numTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + numLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. + ^(CompiledMethod headerFlagForEncoder: self) + + (numArgs bitShift: 24) + + (numTemps bitShift: 18) + "+ (largeBit bitShift: 17)" "largeBit gets filled in later" + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + numLits! - "Compute the compiled method header that encodes the arguments - in the receiver's header format (see CompiledMehtod's class comment)." - self subclassResponsibility! Item was removed: - ----- Method: EncoderForV3>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') ----- - computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex - | primBits | - numTemps > 63 ifTrue: - [^self error: 'Cannot compile -- too many temporary variables']. - numLits > 255 ifTrue: - [^self error: 'Cannot compile -- too many literals']. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: "For now the high bit of primitive no. is in the 29th bit of header" - [primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. - ^(numArgs bitShift: 24) - + (numTemps bitShift: 18) - "+ (largeBit bitShift: 17)" "largeBit gets filled in later" - + (numLits bitShift: 9) - + primBits! Item was changed: ----- Method: EncoderForV3PlusClosures class>>bytecodeSize: (in category 'instruction stream support') ----- bytecodeSize: bytecode "Answer the number of bytes in the bytecode." bytecode <= 125 ifTrue: [^1]. bytecode >= 176 ifTrue: [^1]. bytecode >= 160 ifTrue: "long jumps" [^2]. bytecode >= 144 ifTrue: "short jumps" [^1]. "extensions" bytecode >= 128 ifTrue: + [^#(2 2 2 2 3 2 2 1 1 1 2 3 3 3 3 4) at: bytecode - 127]. - [^#(2 2 2 2 3 2 2 1 1 1 2 nil 3 3 3 4) at: bytecode - 127]. ^nil! Item was added: + ----- Method: EncoderForV3PlusClosures class>>callPrimitiveCode (in category 'bytecode decoding') ----- + callPrimitiveCode + "139 11101111 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256)" + ^139! Item was added: + ----- Method: EncoderForV3PlusClosures>>genCallPrimitive: (in category 'bytecode generation') ----- + genCallPrimitive: primitiveIndex + "139 11101111 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256)" + (primitiveIndex < 1 or: [primitiveIndex > 65535]) ifTrue: + [self outOfRangeError: 'primitive index' index: primitiveIndex range: 1 to: 65535]. + stream + nextPut: 139; + nextPut: (primitiveIndex bitAnd: 255); + nextPut: (primitiveIndex bitShift: -8)! Item was changed: ----- Method: MethodNode>>generate:using: (in category 'code generation') ----- generate: trailer using: aCompiledMethodClass "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass. The argument, trailer, is arbitrary but is typically either the reference to the source code that is stored with every CompiledMethod, or an encoding of the method's temporary names." + | primErrNode blkSize nLits locals literals stack header method | - | primErrNode blkSize nLits literals stack method | self generate: trailer using: aCompiledMethodClass ifQuick: [:m | encoder noteBlockExtent: (0 to: 2) hasLocals: arguments. m literalAt: 2 put: encoder associationForClass; properties: properties. ^m]. primErrNode := self primitiveErrorVariableName ifNotNil: [encoder fixTemp: self primitiveErrorVariableName]. + self ensureClosureAnalysisDone. + encoder rootNode: self. "this is for BlockNode>>sizeCodeForClosureValue:" - encoder supportsClosureOpcodes ifTrue: - [self ensureClosureAnalysisDone. - encoder rootNode: self. "this is for BlockNode>>sizeCodeForClosureValue:"]. blkSize := (block sizeCodeForEvaluatedValue: encoder) + + (primitive > 0 + ifTrue: [encoder sizeCallPrimitive: primitive] + ifFalse: [0]) + (primErrNode ifNil: [0] ifNotNil: [primErrNode index: arguments size + temporaries size; sizeCodeForStore: encoder "The VM relies on storeIntoTemp: (129)"]). + locals := arguments, temporaries, (primErrNode ifNil: [#()] ifNotNil: [{primErrNode}]). + encoder noteBlockExtent: block blockExtent hasLocals: locals. + header := encoder computeMethodHeaderForNumArgs: arguments size + numTemps: locals size + numLits: (nLits := (literals := encoder allLiterals) size) + primitive: primitive. + method := trailer + createMethod: blkSize + class: aCompiledMethodClass + header: header. - method := aCompiledMethodClass - newBytes: blkSize - trailerBytes: trailer - nArgs: arguments size - nTemps: (encoder supportsClosureOpcodes - ifTrue: [| locals | - locals := arguments, - temporaries, - (primErrNode - ifNil: [#()] - ifNotNil: [{primErrNode}]). - encoder - noteBlockExtent: block blockExtent - hasLocals: locals. - locals size] - ifFalse: [encoder maxTemp]) - nStack: 0 - nLits: (nLits := (literals := encoder allLiterals) size) - primitive: primitive. - nLits > 255 ifTrue: - [^self error: 'Too many literals referenced']. 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)]. encoder streamToMethod: method. stack := ParseStack new init. + primitive > 0 ifTrue: + [encoder genCallPrimitive: primitive. + primErrNode ifNotNil: + [primErrNode emitCodeForStore: stack encoder: encoder]]. - primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: encoder]. stack position: method numTemps. [block emitCodeForEvaluatedValue: stack encoder: encoder] on: Error "If an attempt is made to write too much code the method will be asked" do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:" ex signalerContext sender method = (CompiledMethod class>>#new:) ifTrue: [^self error: 'Compiler code size discrepancy'] ifFalse: [ex pass]]. stack position ~= (method numTemps + 1) ifTrue: [^self error: 'Compiler stack discrepancy']. encoder methodStreamPosition ~= (method size - trailer size) ifTrue: [^self error: 'Compiler code size discrepancy']. method needsFrameSize: stack size - method numTemps. method properties: properties. ^method! From commits at source.squeak.org Thu Oct 9 17:49:03 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:49:07 2014 Subject: [squeak-dev] The Trunk: Kernel.spur-eem.876.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel.spur-eem.876.mcz ==================== Summary ==================== Name: Kernel.spur-eem.876 Author: eem Time: 9 October 2014, 10:41:29.864 am UUID: 0a9168c5-2111-4097-9d7e-bd2d0a8f480e Ancestors: Kernel-eem.876, Kernel.spur-ul.875 Kernel-eem.876 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Fix handleSignal: for a rare edge case that can occur on Stack & Cog VMs. =============== Diff against Kernel-eem.876 =============== Item was changed: ----- Method: Behavior>>allInstances (in category 'accessing instances and variables') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + (inst == insts or: [inst == insts originalContents]) ifFalse: [insts nextPut: inst]. + inst := next]. + ^insts contents! - allInstances - "Answer a collection of all current instances of the receiver." - - | all | - all := OrderedCollection new. - self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. - ^ all asArray - ! Item was changed: ----- Method: Behavior>>allInstancesDo: (in category 'enumerating') ----- + allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst." - allInstancesDo: aBlock - "Evaluate the argument, aBlock, for each of the current instances of the - receiver. - - Because aBlock might change the class of inst (for example, using become:), - it is essential to compute next before aBlock value: inst." - | inst next | inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == nil] - whileFalse: - [ - next := inst nextInstance. - aBlock value: inst. - inst := next]! Item was added: + ----- Method: Behavior>>allInstancesOrNil (in category 'enumerating') ----- + allInstancesOrNil + "Answer all instances of the receiver, or nil if the primitive + fails, which it may be due to being out of memory." + + ^nil! Item was changed: ----- Method: Behavior>>basicNew (in category 'instance creation') ----- basicNew "Primitive. Answer an instance of the receiver (which is a class) with no + indexable variables. Fail if the class is indexable. Essential. See Object + documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run + before the method is activated. Check that space was low and retry + via handleFailingBasicNew if so." - indexable variables. Fail if the class is indexable. Essential. See Object - documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew]. + self isVariable ifTrue: [^self basicNew: 0]. + self primitiveFailed! - - self isVariable ifTrue: [ ^ self basicNew: 0 ]. - "space must be low" - OutOfMemory signal. - ^ self basicNew "retry if user proceeds" - ! Item was changed: ----- Method: Behavior>>basicNew: (in category 'instance creation') ----- + basicNew: sizeRequested + "Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run before the + method is activated. Check args and retry via handleFailingBasicNew: if they're OK." - basicNew: sizeRequested - "Primitive. Answer an instance of this class with the number - of indexable variables specified by the argument, sizeRequested. - Fail if this class is not indexable or if the argument is not a - positive Integer, or if there is not enough memory available. - Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew: sizeRequested]. - self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. - (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: - ["arg okay; space must be low." - OutOfMemory signal. - ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstance (in category 'accessing instances and variables') ----- + byteSizeOfInstance + "Answer the total memory size of an instance of the receiver." + + + self isVariable ifTrue: + [^self byteSizeOfInstanceOfSize: 0]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstanceOfSize: (in category 'accessing instances and variables') ----- + byteSizeOfInstanceOfSize: basicSize + "Answer the total memory size of an instance of the receiver + with the given number of indexable instance variables." + + + self isVariable + ifTrue: "If the primitive overflowed answer a close approximation" + [(basicSize isInteger + and: [basicSize >= 16r1000000]) ifTrue: + [^2 * (self byteSizeOfInstanceOfSize: basicSize + 1 // 2) + - (self byteSizeOfInstanceOfSize: 0)]] + ifFalse: + [basicSize = 0 ifTrue: + [^self byteSizeOfInstance]]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>elementSize (in category 'accessing instances and variables') ----- + elementSize + "Answer the size in bytes of an element in the receiver. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + instSpec < 9 ifTrue: [^Smalltalk wordSize]. + instSpec >= 16 ifTrue: [^1]. + instSpec >= 12 ifTrue: [^2]. + instSpec >= 10 ifTrue: [^4]. + ^8! Item was added: + ----- Method: Behavior>>handleFailingBasicNew (in category 'private') ----- + handleFailingBasicNew + "handleFailingBasicNew gets sent after basicNew has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew. If + handleFailingBasicNew fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + Smalltalk garbageCollect < 1048576 ifTrue: + [Smalltalk growMemoryByAtLeast: 1048576]. + ^self handleFailingFailingBasicNew "retry after global garbage collect"! Item was added: + ----- Method: Behavior>>handleFailingBasicNew: (in category 'private') ----- + handleFailingBasicNew: sizeRequested + "handleFailingBasicNew: gets sent after basicNew: has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew:. If + handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := self byteSizeOfInstanceOfSize: sizeRequested. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingBasicNew: sizeRequested! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew (in category 'private') ----- + handleFailingFailingBasicNew + "This basicNew gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low" + OutOfMemory signal. + ^self basicNew "retry if user proceeds"! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew: (in category 'private') ----- + handleFailingFailingBasicNew: sizeRequested + "This basicNew: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + ^self basicNew: sizeRequested "retry if user proceeds"! Item was added: + ----- Method: Behavior>>identityHash (in category 'comparing') ----- + identityHash + "Answer a SmallInteger whose value is related to the receiver's identity. + Behavior implements identityHash to allow the VM to use an object representation which + does not include a direct reference to an object's class in an object. If the VM is using + this implementation then classes are held in a class table and instances contain the index + of their class in the table. A class's class table index is its identityHash so that an instance + can be created without searching the table for a class's index. The VM uses this primitive + to enter the class into the class table, assigning its identityHash with an as yet unused + class table index. If this primitive fails it means that the class table is full. In Spur as of + 2014 there are 22 bits of classTable index and 22 bits of identityHash per object. + + Primitive. Essential. Do not override. See Object documentation whatIsAPrimitive." + + + self primitiveFailed! Item was changed: ----- Method: Behavior>>indexIfCompact (in category 'private') ----- indexIfCompact + "Backward compatibility with the Squeak V3 object format. + Spur does not have a distinction between compact and non-compact classes." + ^0! - "If these 5 bits are non-zero, then instances of this class - will be compact. It is crucial that there be an entry in - Smalltalk compactClassesArray for any class so optimized. - See the msgs becomeCompact and becomeUncompact." - ^ (format bitShift: -11) bitAnd: 16r1F - " - Smalltalk compactClassesArray doWithIndex: - [:c :i | c == nil ifFalse: - [c indexIfCompact = i ifFalse: [self halt]]] - "! Item was changed: ----- Method: Behavior>>instSize (in category 'testing') ----- instSize "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^format bitAnd: 16rFFFF! - (as opposed to indexed variables) of the receiver." - - self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - When we revise the image format, it should become... - ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 - Note also that every other method in this category will require - 2 bits more of right shift after the change. - " - ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! Item was changed: ----- Method: Behavior>>instSpec (in category 'testing') ----- instSpec + "Answer the instance specification part of the format that defines what kind of object + an instance of the receiver is. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^(format bitShift: -16) bitAnd: 16r1F! - ^ (format bitShift: -7) bitAnd: 16rF! Item was changed: ----- Method: Behavior>>isBits (in category 'testing') ----- isBits + "Answer whether the receiver contains just bits (not pointers). + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 7! - "Answer whether the receiver contains just bits (not pointers)." - - ^ self instSpec >= 6! Item was changed: ----- Method: Behavior>>isBytes (in category 'testing') ----- isBytes + "Answer whether the receiver has 8-bit instance variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 16! - "Answer whether the receiver has 8-bit instance variables." - - ^ self instSpec >= 8! Item was added: + ----- Method: Behavior>>isEphemeronClass (in category 'testing') ----- + isEphemeronClass + "Answer whether the receiver has ephemeral instance variables. The garbage collector will + fire (queue for finalization) any ephemeron whose first instance variable is not referenced + other than from the transitive closure of references from ephemerons. Hence referring to + an object from the first inst var of an ephemeron will cause the ephemeron to fire when + the rest of the system does not refer to the object and that object is ready to be collected. + Since references from the remaining inst vars of an ephemeron will not prevent the ephemeron + from firing, ephemerons may act as the associations in weak dictionaries such that the value + (e.g. properties attached to the key) will not prevent firing when the key is no longer referenced + other than from ephemerons. Ephemerons can therefore be used to implement instance-based + pre-mortem finalization." + ^self instSpec = 5! Item was added: + ----- Method: Behavior>>isImmediateClass (in category 'testing') ----- + isImmediateClass + "Answer whether the receiver has immediate instances. Immediate instances + store their value in their object pointer, not in an object body. Hence immediates + take no space and are immutable. The immediates are distinguished by tag bits + in the pointer. They include SmallIntegers and Characters. Hence in the 32-bit + system SmallIntegers are 31-bit signed integers and Characters are 30-bit + unsigned character codes." + ^self instSpec = 7! Item was changed: ----- Method: Behavior>>isVariable (in category 'testing') ----- isVariable + "Answer whether the receiver has indexable variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + ^instSpec >= 2 and: [instSpec <= 4 or: [instSpec >= 9]]! - "Answer whether the receiver has indexable variables." - - ^ self instSpec >= 2! Item was changed: ----- Method: Behavior>>kindOfSubclass (in category 'testing class hierarchy') ----- kindOfSubclass + "Answer a String that is the keyword that describes the receiver's kind of subclass, + either a regular subclass, a variableSubclass, a variableByteSubclass, + a variableWordSubclass, a weakSubclass, an ephemeronSubclass or an immediateSubclass. + c.f. typeOfClass" + ^self isVariable + ifTrue: + [self isBits + ifTrue: + [self isBytes + ifTrue: [' variableByteSubclass: '] + ifFalse: [' variableWordSubclass: ']] + ifFalse: + [self isWeak + ifTrue: [' weakSubclass: '] + ifFalse: [' variableSubclass: ']]] + ifFalse: + [self isImmediateClass + ifTrue: [' immediateSubclass: '] + ifFalse: + [self isEphemeronClass + ifTrue: [' ephemeronSubclass: '] + ifFalse: [' subclass: ']]]! - "Answer a String that is the keyword that describes the receiver's kind - of subclass, either a regular subclass, a variableSubclass, a - variableByteSubclass, a variableWordSubclass, or a weakSubclass." - self isWeak - ifTrue: [^ ' weakSubclass: ']. - ^ self isVariable - ifTrue: [self isBits - ifTrue: [self isBytes - ifTrue: [ ' variableByteSubclass: '] - ifFalse: [ ' variableWordSubclass: ']] - ifFalse: [ ' variableSubclass: ']] - ifFalse: [ ' subclass: ']! Item was changed: ----- Method: Behavior>>shouldNotBeRedefined (in category 'testing') ----- shouldNotBeRedefined + "Answer if the receiver should not be redefined. + The assumption is that classes in Smalltalk specialObjects and + instance-specific Behaviors should not be redefined" - "Return true if the receiver should not be redefined. - The assumption is that compact classes, - classes in Smalltalk specialObjects and - Behaviors should not be redefined" + ^(Smalltalk specialObjectsArray + identityIndexOf: self + ifAbsent: [(self isKindOf: self) ifTrue: [1] ifFalse: [0]]) ~= 0! - ^(Smalltalk compactClassesArray includes: self) - or:[(Smalltalk specialObjectsArray includes: self) - or:[self isKindOf: self]]! Item was changed: ----- Method: Behavior>>typeOfClass (in category 'accessing') ----- typeOfClass + "Answer a symbol uniquely describing the type of the receiver. c.f. kindOfSubclass" + self isBytes ifTrue: + [^self instSpec = CompiledMethod instSpec + ifTrue: [#compiledMethod] "Very special!!" + ifFalse: [#bytes]]. + (self isWords and: [self isPointers not]) ifTrue: + [^self instSpec = SmallInteger instSpec + ifTrue: [#immediate] "Very special!!" + ifFalse: [#words]]. + self isWeak ifTrue: [^#weak]. + self isVariable ifTrue: [^#variable]. + self isEphemeronClass ifTrue: [^#ephemeron]. + ^#normal! - "Answer a symbol uniquely describing the type of the receiver" - self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" - self isBytes ifTrue:[^#bytes]. - (self isWords and:[self isPointers not]) ifTrue:[^#words]. - self isWeak ifTrue:[^#weak]. - self isVariable ifTrue:[^#variable]. - ^#normal.! Item was changed: ----- Method: BlockClosure>>simulateValueWithArguments:caller: (in category 'system simulation') ----- simulateValueWithArguments: anArray caller: aContext + "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity." | newContext sz | - (anArray class ~~ Array - or: [numArgs ~= anArray size]) ifTrue: - [^ContextPart primitiveFailTokenFor: nil]. newContext := (MethodContext newForMethod: outerContext method) setSender: aContext receiver: outerContext receiver method: outerContext method closure: self startpc: startpc. + ((newContext objectClass: anArray) ~~ Array + or: [numArgs ~= anArray size]) ifTrue: + [^ContextPart primitiveFailTokenFor: nil]. sz := self basicSize. newContext stackp: sz + numArgs. 1 to: numArgs do: [:i| newContext at: i put: (anArray at: i)]. 1 to: sz do: [:i| newContext at: i + numArgs put: (self at: i)]. ^newContext! Item was added: + ----- Method: Class>>immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'subclass creation') ----- + immediateSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a new + immediate class as a subclass of an existing class (the receiver)." + ^ClassBuilder new + superclass: self + immediateSubclass: t + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>computeFormat:instSize:forSuper:ccIndex: (in category 'class format') ----- computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. + Answer the format or nil if there is any problem." - Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | type == #compiledMethod ifTrue: + [newInstSize > 0 ifTrue: + [self error: 'A compiled method class cannot have named instance variables'. + ^nil]. + ^CompiledMethod format]. - [^(CompiledMethod format - bitClear: (16r1F bitShift: 11)) - bitOr: (ccIndex bitShift: 11)]. instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). + instSize > 65535 ifTrue: - instSize > 254 ifTrue: [self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true]. type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false]. type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false]. type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false]. type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true]. + type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true]. + type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true]. + (isPointers not and: [instSize > 0]) ifTrue: + [self error: 'A non-pointer class cannot have named instance variables'. - (isPointers not and:[instSize > 0]) ifTrue: - [self error:'A non-pointer class cannot have instance variables'. ^nil]. + ^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak! - ^(self format: instSize - variable: isVar - words: isWords - pointers: isPointers - weak: isWeak) + (ccIndex bitShift: 11).! Item was changed: ----- Method: ClassBuilder>>format:variable:words:pointers:weak: (in category 'class format') ----- + format: nInstVars variable: isVar words: is32BitWords pointers: isPointers weak: isWeak + "Compute the format for the given instance specfication. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = reserved for 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | - format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak - "Compute the format for the given instance specfication." - | cClass instSpec sizeHiBits fmt | - self flag: #instSizeChange. - " - Smalltalk browseAllCallsOn: #instSizeChange. - Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. - Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. - " - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - For now the format word is... - <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> - But when we revise the image format, it should become... - <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> - " - sizeHiBits := (nInstVars+1) // 64. - cClass := 0. "for now" instSpec := isWeak + ifTrue: + [isVar + ifTrue: [4] + ifFalse: [5]] + ifFalse: + [isPointers + ifTrue: + [isVar + ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]] + ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]] + ifFalse: + [isVar + ifTrue: [is32BitWords ifTrue: [10] ifFalse: [16]] + ifFalse: [7]]]. + ^(instSpec bitShift: 16) + nInstVars! - ifTrue:[4] - ifFalse:[isPointers - ifTrue: [isVar - ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] - ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] - ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. - fmt := sizeHiBits. - fmt := (fmt bitShift: 5) + cClass. - fmt := (fmt bitShift: 4) + instSpec. - fmt := (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" - fmt := (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" - ^fmt! Item was added: + ----- Method: ClassBuilder>>superclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'public') ----- + superclass: aClass + immediateSubclass: t instanceVariableNames: f + classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a + new immediate class as a subclass of an existing class." + | env | + aClass instSize > 0 + ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields']. + aClass isVariable + ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables']. + aClass isPointers + ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields']. + "Cope with pre-environment and environment versions. Simplify asap." + env := (Smalltalk classNamed: #EnvironmentRequest) + ifNil: [aClass environment] + ifNotNil: [:erc| erc signal ifNil: [aClass environment]]. + ^self + name: t + inEnvironment: env + subclassOf: aClass + type: #immediate + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" - "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. - We can rely on two assumptions (which are critical): - #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) - #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. - Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. - " | meta | meta := oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." - [ - "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). - Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "make sure that the VM cache is clean" oldClass methodDict do: [:cm | cm flushCache]. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue: [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. oldClass updateMethodBindingsTo: oldClass binding. oldClass class updateMethodBindingsTo: oldClass class binding]. + "eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was + to ensure no old instances existed after the becomeForward:. Without the GC it was possible + to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward: + updated references from the old objects to new objects but didn't destroy the old objects. + But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."] + valueUnpreemptively! - Smalltalk garbageCollect. - - "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). - - The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: - - On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. - - Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). - - Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. - - Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." - - ] valueUnpreemptively. - ! Item was changed: ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame' poolDictionaries: '' category: 'Kernel-Methods'! + !CompiledMethod commentStamp: 'eem 8/12/2014 14:45' prior: 0! + CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. - !CompiledMethod commentStamp: 'eem 5/12/2014 18:02' prior: 0! - My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. I'm a subclass of ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. Class variables: SmallFrame - the number of stack slots in a small frame Context LargeFrame - the number of stack slots in a large frame Context PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set The current format of a CompiledMethod is as follows: header (4 or 8 bytes, SmallInteger) + literals (4 or 8 bytes each, Object, see "The last literal..." below) - literals (4 or 8 bytes each, Object) bytecodes (variable, bytes) trailer (variable, bytes) + The header is a 31-bit signed integer (a SmallInteger) in the following format: - The header is a 31-bit signed integer (a SmallInteger) with one of the two following formats, selected by the sign bit: - sign bit 0, header >= 0: - (index 0) 9 bits: main part of primitive number (#primitive) - (index 9) 8 bits: number of literals (#numLiterals) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) - (index 18) 6 bits: number of temporary variables (#numTemps) - (index 24) 4 bits: number of arguments to the method (#numArgs) - (index 28) 1 bit: high-bit of primitive number (#primitive) - (index 29) 1 bit: flag bit, ignored by the VM (#flag) - (index 30/63) sign bit: 0 selects the Primary instruction set (#signFlag) - sign bit 1, header < 0: (index 0) 16 bits: number of literals (#numLiterals) (index 16) 1 bit: has primitive + (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) + (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag). + (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4, 0 selects the primary instruction set, e.g. SqueakV3PlusClosures) (#signFlag) - (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public) - (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4) (#signFlag) - i.e. the Secondary Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode. + If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. + + The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer. + + The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be left nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.! - The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.! Item was added: + ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') ----- + handleFailingFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails then the + system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + "retry if user proceeds" + ^self newMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') ----- + handleFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after newMethod:header: has failed + and allowed a scavenging garbage collection to occur. The scavenging + collection will have happened as the VM is activating the (failing) basicNew:. + If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') ----- + installPrimaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was added: + ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') ----- + installSecondaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: ["For now the high bit of primitive no. is in the 29th bit of header" - primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits flagBit | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - "For now the high bit of the primitive no. is in a high bit of the header" - primBits := (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19). - - flagBit := flag ifTrue: [ 1 ] ifFalse: [ 0 ]. - - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits + - (flagBit bitShift: 29)! Item was changed: ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') ----- + newMethod: numberOfBytes header: headerWord - newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other + information) is specified by the headerWord (see my class comment). + The first argument specifies the number of fields for bytecodes in the + method. Fail if either argument is not a SmallInteger, or if numberOfBytes + is negative, or if memory is low. Once the header of a method is set by + this primitive, it cannot be changed to change the number of literals. + Essential. See Object documentation whatIsAPrimitive." - information) is specified the headerWord. The first argument specifies - the number of fields for bytecodes in the method. Fail if either - argument is not a SmallInteger, or if numberOfBytes is negative. Once - the header of a method is set by this primitive, it cannot be changed in - any way. Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingNewMethod: numberOfBytes header: headerWord]. - - (numberOfBytes isInteger and: - [headerWord isInteger and: - [numberOfBytes >= 0]]) ifTrue: [ - "args okay; space must be low" - OutOfMemory signal. - "retry if user proceeds" - ^ self newMethod: numberOfBytes header: headerWord - ]. ^self primitiveFailed! Item was changed: ----- Method: CompiledMethod class>>toReturnConstant:trailerBytes: (in category 'instance creation') ----- toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index - ! Item was changed: ----- Method: CompiledMethod class>>toReturnField:trailerBytes: (in category 'instance creation') ----- toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field - ! Item was changed: ----- Method: CompiledMethod class>>toReturnSelfTrailerBytes: (in category 'instance creation') ----- toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 - ! Item was added: + ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') ----- + bytecodeSetName + ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''! Item was changed: ----- Method: CompiledMethod>>headerDescription (in category 'literals') ----- headerDescription + "Answer a description containing the information about the form of the + receiver and the form of the context needed to run the receiver." - "Answer a description containing the information about the form of the - receiver and the form of the context needed to run the receiver." + ^(ByteString new: 128) writeStream + print: self header; cr; + nextPutAll: '"primitive: '; print: self primitive; cr; + nextPutAll: ' numArgs: '; print: self numArgs; cr; + nextPutAll: ' numTemps: '; print: self numTemps; cr; + nextPutAll: ' numLiterals: '; print: self numLiterals; cr; + nextPutAll: ' frameSize: '; print: self frameSize; cr; + nextPutAll: ' bytecodeSet: '; nextPutAll: self bytecodeSetName; + nextPut: $"; cr; + contents! - | s | - s := '' writeStream. - self header printOn: s. - s cr; nextPutAll: '"primitive: '. - self primitive printOn: s. - s cr; nextPutAll: ' numArgs: '. - self numArgs printOn: s. - s cr; nextPutAll: ' numTemps: '. - self numTemps printOn: s. - s cr; nextPutAll: ' numLiterals: '. - self numLiterals printOn: s. - s cr; nextPutAll: ' frameSize: '. - self frameSize printOn: s. - s cr; nextPutAll: ' isClosureCompiled: '. - self isBlueBookCompiled not printOn: s. - s nextPut: $"; cr. - ^ s contents! Item was changed: ----- Method: CompiledMethod>>numLiterals (in category 'accessing') ----- numLiterals "Answer the number of literals used by the receiver." + ^self header bitAnd: 65535! - | header | - ^(header := self header) < 0 - ifTrue: [header bitAnd: 65535] - ifFalse: [(header bitShift: -9) bitAnd: 16rFF]! Item was changed: ----- Method: CompiledMethod>>primitive (in category 'accessing') ----- primitive "Answer the primitive index associated with the receiver. + Zero indicates that this is not a primitive method." + | initialPC | + ^(self header anyMask: 65536) "Is the hasPrimitive? flag set?" + ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] + ifFalse: [0]! - Zero indicates that this is not a primitive method. - In the original header format we currently allow 10 bits of primitive index, but they are - in two places for backward compatibility. In the new format the primitive index is in the - last two bytes of a three byte callPrimitive: bytecode. The time to unpack is negligible, - since the derived primitive function pointer full index is stored in the method cache." - | header initialPC | - ^(header := self header) < 0 - ifTrue: - [(header anyMask: 65536) "Is the hasPrimitive? flag set?" - ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] - ifFalse: [0]] - ifFalse: - [(header bitAnd: 16r1FF) + ((header bitShift: -19) bitAnd: 16r200)]! Item was changed: ----- Method: ContextPart>>activateReturn:value: (in category 'private') ----- activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" + ^MethodContext + sender: self - ^ self - activateMethod: ContextPart theReturnMethod - withArgs: {value} receiver: aContext + method: MethodContext theReturnMethod + arguments: {value}! - class: aContext class! Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments + "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and + arguments are given as arguments to this message. If successful, push result and return + resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes + execution needs to be intercepted and simulated to avoid execution running away." - "Simulate a primitive method whose index is primitiveIndex. The - simulated receiver and arguments are given as arguments to this message. - If successful, push result and return resuming context, else ^ PrimitiveFailToken. - Any primitive which provokes execution needs to be intercepted and simulated - to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug + interesting code, such as the debugger itself. hence use primitive 19 with care :-)" - interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. + ((primitiveIndex between: 201 and: 222) + and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: + [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" + or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" + [^receiver simulateValueWithArguments: arguments caller: self]. + primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" + [^receiver simulateValueWithArguments: arguments first caller: self]]. - "ContextPart>>blockCopy:; simulated to get startpc right" - (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) - ifTrue: [^self push: ((BlockContext newForMethod: receiver method) - home: receiver home - startpc: pc + 2 - nargs: (arguments at: 1))]. - (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" - ifTrue: [^receiver pushArgs: arguments from: self]. - (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" - ifTrue: [^receiver pushArgs: arguments first from: self]. - primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" - ifTrue: [^self send: arguments first - to: receiver - with: arguments allButFirst - super: false]. - primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: nil]. - primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: (arguments at: 3)]. + primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [^self send: arguments first to: receiver with: arguments allButFirst super: false]. + primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. + primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. + "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. + ^(self isPrimFailToken: value) - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver method: (arguments at: 2) arguments: (arguments at: 1)]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. - ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" - or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" - [^receiver simulateValueWithArguments: arguments caller: self]. - primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" - [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] + ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. + + ^(self isPrimFailToken: value) - ifFalse: - [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! Item was added: + ----- Method: ContextPart>>isPrimFailToken: (in category 'private') ----- + isPrimFailToken: anObject + ^(self objectClass: anObject) == Array + and: [anObject size = 2 + and: [anObject first == PrimitiveFailToken]]! Item was added: + ----- Method: ContextPart>>send:to:with:lookupIn: (in category 'controlling') ----- + send: selector to: rcvr with: arguments lookupIn: lookupClass + "Simulate the action of sending a message with selector and arguments + to rcvr. The argument, lookupClass, is the class in which to lookup the + message. This is the receiver's class for normal messages, but for super + messages it will be some specific class related to the source method." + + | meth primIndex val ctxt | + (meth := lookupClass lookupSelector: selector) ifNil: + [^self send: #doesNotUnderstand: + to: rcvr + with: {Message selector: selector arguments: arguments} + lookupIn: lookupClass]. + (primIndex := meth primitive) > 0 ifTrue: + [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments. + (self isPrimFailToken: val) ifFalse: + [^val]]. + (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue: + [^self error: 'Simulated message ', arguments first selector, ' not understood']. + ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments. + primIndex > 0 ifTrue: + [ctxt failPrimitiveWith: val]. + ^ctxt! Item was changed: ----- Method: ContextPart>>send:to:with:super: (in category 'controlling') ----- + send: selector to: rcvr with: arguments super: superFlag + "Simulate the action of sending a message with selector arguments + to rcvr. The argument, superFlag, tells whether the receiver of the + message was specified with 'super' in the source method." - send: selector to: rcvr with: args super: superFlag - "Simulate the action of sending a message with selector, selector, and - arguments, args, to receiver. The argument, superFlag, tells whether the - receiver of the message was specified with 'super' in the source method." + ^self send: selector + to: rcvr + with: arguments + lookupIn: (superFlag + ifTrue: [self method methodClassAssociation value superclass] + ifFalse: [self objectClass: rcvr])! - | class meth val ctxt | - class := superFlag - ifTrue: [self method methodClassAssociation value superclass] - ifFalse: [self objectClass: rcvr]. - meth := class lookupSelector: selector. - meth == nil ifTrue: - [^self - send: #doesNotUnderstand: - to: rcvr - with: (Array with: (Message selector: selector arguments: args)) - super: superFlag]. - val := self tryPrimitiveFor: meth receiver: rcvr args: args. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken]]) ifFalse: - [^val]. - (selector == #doesNotUnderstand: - and: [class == ProtoObject]) ifTrue: - [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood']. - ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken - and: [val last notNil - and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue: - [ctxt at: ctxt stackPtr put: val last]. - ^ctxt! Item was changed: ----- Method: ContextPart>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') ----- tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments + "Invoke the named primitive for aCompiledMethod, answering its result, or, + if the primiitve fails, answering the error code." - | selector theMethod spec receiverClass | ec ifNotNil: ["If ec is an integer other than -1 there was a problem with primitive 218, not with the external primitive itself. -1 indicates a generic failure (where ec should be nil) but ec = nil means primitive 218 is not implemented. So interpret -1 to mean the external primitive failed with a nil error code." ec isInteger ifTrue: [ec = -1 ifTrue: [ec := nil] + ifFalse: [self primitiveFailed]]]. + ^self class primitiveFailTokenFor: ec! - ifFalse: [self primitiveFailed]]. - ^{PrimitiveFailToken. ec}]. - "Assume a nil error code implies the primitive is not implemented and fall back on the old code." - "Hack. Attempt to execute the named primitive from the given compiled method" - arguments size > 8 ifTrue: - [^{PrimitiveFailToken. nil}]. - selector := #( - tryNamedPrimitive - tryNamedPrimitive: - tryNamedPrimitive:with: - tryNamedPrimitive:with:with: - tryNamedPrimitive:with:with:with: - tryNamedPrimitive:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. - receiverClass := self objectClass: aReceiver. - theMethod := receiverClass lookupSelector: selector. - theMethod == nil ifTrue: - [^{PrimitiveFailToken. nil}]. - spec := theMethod literalAt: 1. - spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. - Smalltalk unbindExternalPrimitives. - ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass! Item was added: + ----- Method: InstructionClient>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: pimIndex + "V3PlusClosures: 139 10001011 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + NewsqueakV4: 249 11111001 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + ( jjjjjjj * 256) + m=1 means inlined primitive, no hard return after execution."! Item was added: + ----- Method: InstructionPrinter>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: index + "Print the callPrimitive." + + self print: 'callPrimtive: ' , index printString! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self error: 'unusedBytecode']. byte3 := method at: pc. pc := pc + 1. + offset = 11 ifTrue: [^client callPrimitive: byte2 + (byte3 bitShift: 8)]. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: Integer class>>initialize (in category 'class initialization') ----- + initialize + "Integer initialize" + self initializeLowBitPerByteTable! - initialize "Integer initialize" - "Ensure we have the right compact class index" - - "LPI has been a compact class forever - just ensure basic correctness" - (LargePositiveInteger indexIfCompact = 5) ifFalse:[ - (Smalltalk compactClassesArray at: 5) - ifNil:[LargePositiveInteger becomeCompactSimplyAt: 5] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - "Cog requires LNI to be compact at 4 (replacing PseudoContext)" - (LargeNegativeInteger indexIfCompact = 4) ifFalse:[ - "PseudoContext will likely get removed at some point so write this test - without introducing a hard dependency" - (Smalltalk compactClassesArray at: 4) name == #PseudoContext - ifTrue:[Smalltalk compactClassesArray at: 4 put: nil]. - (Smalltalk compactClassesArray at: 4) - ifNil:[LargeNegativeInteger becomeCompactSimplyAt: 4] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - self initializeLowBitPerByteTable - ! Item was added: + ----- Method: MethodContext class>>allInstances (in category 'enumerating') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst. + Only count until thisContext since this context has been created only to + compute the existing instances." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + insts nextPut: inst. + inst := next]. + ^insts contents! Item was changed: ----- Method: MethodContext class>>allInstancesDo: (in category 'private') ----- allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst. + Only count until thisContext since evaluation of aBlock will create new contexts." - "Only count until thisContext since evaluation of aBlock will create new contexts." - | inst next | inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == thisContext] whileFalse:[ - next := inst nextInstance. - aBlock value: inst. - inst := next] - ! Item was added: + ----- Method: MethodContext>>failPrimitiveWith: (in category 'system simulation') ----- + failPrimitiveWith: maybePrimFailToken + "The receiver is a freshly-created context on a primitive method. Skip the callPrimitive: + bytecode and store the primitive fail code if there is one and the method consumes it." + self skipCallPrimitive. + ((self isPrimFailToken: maybePrimFailToken) + and: [method encoderClass isStoreAt: pc in: method]) ifTrue: + [self at: stackp put: maybePrimFailToken last]! Item was changed: ----- Method: ProtoObject>>scaledIdentityHash (in category 'comparing') ----- scaledIdentityHash "For identityHash values returned by primitive 75, answer + such values times 2^8. Otherwise, match the existing + identityHash implementation" - such values times 2^18. Otherwise, match the existing - identityHash implementation" + ^self identityHash * 256 "bitShift: 8"! - ^self identityHash * 262144 "bitShift: 18"! Item was changed: ==== ERROR === Error: Unrecognized class type 9 October 2014 5:49:02.234 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(SmallInteger) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Thu Oct 9 17:49:55 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:49:58 2014 Subject: [squeak-dev] The Trunk: Kernel.spur-eem.877.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel.spur-eem.877.mcz ==================== Summary ==================== Name: Kernel.spur-eem.877 Author: eem Time: 9 October 2014, 10:41:31.341 am UUID: cd5ef356-e4f8-4627-99c6-e4ee7e3500be Ancestors: Kernel-eem.877, Kernel.spur-eem.876 Kernel-eem.877 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) =============== Diff against Kernel-eem.877 =============== Item was changed: ----- Method: Behavior>>allInstances (in category 'accessing instances and variables') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + (inst == insts or: [inst == insts originalContents]) ifFalse: [insts nextPut: inst]. + inst := next]. + ^insts contents! - allInstances - "Answer a collection of all current instances of the receiver." - - | all | - all := OrderedCollection new. - self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. - ^ all asArray - ! Item was changed: ----- Method: Behavior>>allInstancesDo: (in category 'enumerating') ----- + allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst." - allInstancesDo: aBlock - "Evaluate the argument, aBlock, for each of the current instances of the - receiver. - - Because aBlock might change the class of inst (for example, using become:), - it is essential to compute next before aBlock value: inst." - | inst next | inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == nil] - whileFalse: - [ - next := inst nextInstance. - aBlock value: inst. - inst := next]! Item was added: + ----- Method: Behavior>>allInstancesOrNil (in category 'enumerating') ----- + allInstancesOrNil + "Answer all instances of the receiver, or nil if the primitive + fails, which it may be due to being out of memory." + + ^nil! Item was changed: ----- Method: Behavior>>basicNew (in category 'instance creation') ----- basicNew "Primitive. Answer an instance of the receiver (which is a class) with no + indexable variables. Fail if the class is indexable. Essential. See Object + documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run + before the method is activated. Check that space was low and retry + via handleFailingBasicNew if so." - indexable variables. Fail if the class is indexable. Essential. See Object - documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew]. + self isVariable ifTrue: [^self basicNew: 0]. + self primitiveFailed! - - self isVariable ifTrue: [ ^ self basicNew: 0 ]. - "space must be low" - OutOfMemory signal. - ^ self basicNew "retry if user proceeds" - ! Item was changed: ----- Method: Behavior>>basicNew: (in category 'instance creation') ----- + basicNew: sizeRequested + "Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run before the + method is activated. Check args and retry via handleFailingBasicNew: if they're OK." - basicNew: sizeRequested - "Primitive. Answer an instance of this class with the number - of indexable variables specified by the argument, sizeRequested. - Fail if this class is not indexable or if the argument is not a - positive Integer, or if there is not enough memory available. - Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew: sizeRequested]. - self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. - (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: - ["arg okay; space must be low." - OutOfMemory signal. - ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstance (in category 'accessing instances and variables') ----- + byteSizeOfInstance + "Answer the total memory size of an instance of the receiver." + + + self isVariable ifTrue: + [^self byteSizeOfInstanceOfSize: 0]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstanceOfSize: (in category 'accessing instances and variables') ----- + byteSizeOfInstanceOfSize: basicSize + "Answer the total memory size of an instance of the receiver + with the given number of indexable instance variables." + + + self isVariable + ifTrue: "If the primitive overflowed answer a close approximation" + [(basicSize isInteger + and: [basicSize >= 16r1000000]) ifTrue: + [^2 * (self byteSizeOfInstanceOfSize: basicSize + 1 // 2) + - (self byteSizeOfInstanceOfSize: 0)]] + ifFalse: + [basicSize = 0 ifTrue: + [^self byteSizeOfInstance]]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>elementSize (in category 'accessing instances and variables') ----- + elementSize + "Answer the size in bytes of an element in the receiver. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + instSpec < 9 ifTrue: [^Smalltalk wordSize]. + instSpec >= 16 ifTrue: [^1]. + instSpec >= 12 ifTrue: [^2]. + instSpec >= 10 ifTrue: [^4]. + ^8! Item was added: + ----- Method: Behavior>>handleFailingBasicNew (in category 'private') ----- + handleFailingBasicNew + "handleFailingBasicNew gets sent after basicNew has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew. If + handleFailingBasicNew fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + Smalltalk garbageCollect < 1048576 ifTrue: + [Smalltalk growMemoryByAtLeast: 1048576]. + ^self handleFailingFailingBasicNew "retry after global garbage collect"! Item was added: + ----- Method: Behavior>>handleFailingBasicNew: (in category 'private') ----- + handleFailingBasicNew: sizeRequested + "handleFailingBasicNew: gets sent after basicNew: has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew:. If + handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := self byteSizeOfInstanceOfSize: sizeRequested. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingBasicNew: sizeRequested! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew (in category 'private') ----- + handleFailingFailingBasicNew + "This basicNew gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low" + OutOfMemory signal. + ^self basicNew "retry if user proceeds"! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew: (in category 'private') ----- + handleFailingFailingBasicNew: sizeRequested + "This basicNew: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + ^self basicNew: sizeRequested "retry if user proceeds"! Item was added: + ----- Method: Behavior>>identityHash (in category 'comparing') ----- + identityHash + "Answer a SmallInteger whose value is related to the receiver's identity. + Behavior implements identityHash to allow the VM to use an object representation which + does not include a direct reference to an object's class in an object. If the VM is using + this implementation then classes are held in a class table and instances contain the index + of their class in the table. A class's class table index is its identityHash so that an instance + can be created without searching the table for a class's index. The VM uses this primitive + to enter the class into the class table, assigning its identityHash with an as yet unused + class table index. If this primitive fails it means that the class table is full. In Spur as of + 2014 there are 22 bits of classTable index and 22 bits of identityHash per object. + + Primitive. Essential. Do not override. See Object documentation whatIsAPrimitive." + + + self primitiveFailed! Item was changed: ----- Method: Behavior>>indexIfCompact (in category 'private') ----- indexIfCompact + "Backward compatibility with the Squeak V3 object format. + Spur does not have a distinction between compact and non-compact classes." + ^0! - "If these 5 bits are non-zero, then instances of this class - will be compact. It is crucial that there be an entry in - Smalltalk compactClassesArray for any class so optimized. - See the msgs becomeCompact and becomeUncompact." - ^ (format bitShift: -11) bitAnd: 16r1F - " - Smalltalk compactClassesArray doWithIndex: - [:c :i | c == nil ifFalse: - [c indexIfCompact = i ifFalse: [self halt]]] - "! Item was changed: ----- Method: Behavior>>instSize (in category 'testing') ----- instSize "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^format bitAnd: 16rFFFF! - (as opposed to indexed variables) of the receiver." - - self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - When we revise the image format, it should become... - ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 - Note also that every other method in this category will require - 2 bits more of right shift after the change. - " - ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! Item was changed: ----- Method: Behavior>>instSpec (in category 'testing') ----- instSpec + "Answer the instance specification part of the format that defines what kind of object + an instance of the receiver is. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^(format bitShift: -16) bitAnd: 16r1F! - ^ (format bitShift: -7) bitAnd: 16rF! Item was changed: ----- Method: Behavior>>isBits (in category 'testing') ----- isBits + "Answer whether the receiver contains just bits (not pointers). + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 7! - "Answer whether the receiver contains just bits (not pointers)." - - ^ self instSpec >= 6! Item was changed: ----- Method: Behavior>>isBytes (in category 'testing') ----- isBytes + "Answer whether the receiver has 8-bit instance variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 16! - "Answer whether the receiver has 8-bit instance variables." - - ^ self instSpec >= 8! Item was added: + ----- Method: Behavior>>isEphemeronClass (in category 'testing') ----- + isEphemeronClass + "Answer whether the receiver has ephemeral instance variables. The garbage collector will + fire (queue for finalization) any ephemeron whose first instance variable is not referenced + other than from the transitive closure of references from ephemerons. Hence referring to + an object from the first inst var of an ephemeron will cause the ephemeron to fire when + the rest of the system does not refer to the object and that object is ready to be collected. + Since references from the remaining inst vars of an ephemeron will not prevent the ephemeron + from firing, ephemerons may act as the associations in weak dictionaries such that the value + (e.g. properties attached to the key) will not prevent firing when the key is no longer referenced + other than from ephemerons. Ephemerons can therefore be used to implement instance-based + pre-mortem finalization." + ^self instSpec = 5! Item was added: + ----- Method: Behavior>>isImmediateClass (in category 'testing') ----- + isImmediateClass + "Answer whether the receiver has immediate instances. Immediate instances + store their value in their object pointer, not in an object body. Hence immediates + take no space and are immutable. The immediates are distinguished by tag bits + in the pointer. They include SmallIntegers and Characters. Hence in the 32-bit + system SmallIntegers are 31-bit signed integers and Characters are 30-bit + unsigned character codes." + ^self instSpec = 7! Item was changed: ----- Method: Behavior>>isVariable (in category 'testing') ----- isVariable + "Answer whether the receiver has indexable variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + ^instSpec >= 2 and: [instSpec <= 4 or: [instSpec >= 9]]! - "Answer whether the receiver has indexable variables." - - ^ self instSpec >= 2! Item was changed: ----- Method: Behavior>>kindOfSubclass (in category 'testing class hierarchy') ----- kindOfSubclass + "Answer a String that is the keyword that describes the receiver's kind of subclass, + either a regular subclass, a variableSubclass, a variableByteSubclass, + a variableWordSubclass, a weakSubclass, an ephemeronSubclass or an immediateSubclass. + c.f. typeOfClass" + ^self isVariable + ifTrue: + [self isBits + ifTrue: + [self isBytes + ifTrue: [' variableByteSubclass: '] + ifFalse: [' variableWordSubclass: ']] + ifFalse: + [self isWeak + ifTrue: [' weakSubclass: '] + ifFalse: [' variableSubclass: ']]] + ifFalse: + [self isImmediateClass + ifTrue: [' immediateSubclass: '] + ifFalse: + [self isEphemeronClass + ifTrue: [' ephemeronSubclass: '] + ifFalse: [' subclass: ']]]! - "Answer a String that is the keyword that describes the receiver's kind - of subclass, either a regular subclass, a variableSubclass, a - variableByteSubclass, a variableWordSubclass, or a weakSubclass." - self isWeak - ifTrue: [^ ' weakSubclass: ']. - ^ self isVariable - ifTrue: [self isBits - ifTrue: [self isBytes - ifTrue: [ ' variableByteSubclass: '] - ifFalse: [ ' variableWordSubclass: ']] - ifFalse: [ ' variableSubclass: ']] - ifFalse: [ ' subclass: ']! Item was changed: ----- Method: Behavior>>shouldNotBeRedefined (in category 'testing') ----- shouldNotBeRedefined + "Answer if the receiver should not be redefined. + The assumption is that classes in Smalltalk specialObjects and + instance-specific Behaviors should not be redefined" - "Return true if the receiver should not be redefined. - The assumption is that compact classes, - classes in Smalltalk specialObjects and - Behaviors should not be redefined" + ^(Smalltalk specialObjectsArray + identityIndexOf: self + ifAbsent: [(self isKindOf: self) ifTrue: [1] ifFalse: [0]]) ~= 0! - ^(Smalltalk compactClassesArray includes: self) - or:[(Smalltalk specialObjectsArray includes: self) - or:[self isKindOf: self]]! Item was changed: ----- Method: Behavior>>typeOfClass (in category 'accessing') ----- typeOfClass + "Answer a symbol uniquely describing the type of the receiver. c.f. kindOfSubclass" + self isBytes ifTrue: + [^self instSpec = CompiledMethod instSpec + ifTrue: [#compiledMethod] "Very special!!" + ifFalse: [#bytes]]. + (self isWords and: [self isPointers not]) ifTrue: + [^self instSpec = SmallInteger instSpec + ifTrue: [#immediate] "Very special!!" + ifFalse: [#words]]. + self isWeak ifTrue: [^#weak]. + self isVariable ifTrue: [^#variable]. + self isEphemeronClass ifTrue: [^#ephemeron]. + ^#normal! - "Answer a symbol uniquely describing the type of the receiver" - self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" - self isBytes ifTrue:[^#bytes]. - (self isWords and:[self isPointers not]) ifTrue:[^#words]. - self isWeak ifTrue:[^#weak]. - self isVariable ifTrue:[^#variable]. - ^#normal.! Item was changed: ----- Method: BlockClosure>>simulateValueWithArguments:caller: (in category 'system simulation') ----- simulateValueWithArguments: anArray caller: aContext + "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity." | newContext sz | - (anArray class ~~ Array - or: [numArgs ~= anArray size]) ifTrue: - [^ContextPart primitiveFailTokenFor: nil]. newContext := (MethodContext newForMethod: outerContext method) setSender: aContext receiver: outerContext receiver method: outerContext method closure: self startpc: startpc. + ((newContext objectClass: anArray) ~~ Array + or: [numArgs ~= anArray size]) ifTrue: + [^ContextPart primitiveFailTokenFor: nil]. sz := self basicSize. newContext stackp: sz + numArgs. 1 to: numArgs do: [:i| newContext at: i put: (anArray at: i)]. 1 to: sz do: [:i| newContext at: i + numArgs put: (self at: i)]. ^newContext! Item was added: + ----- Method: Class>>immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'subclass creation') ----- + immediateSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a new + immediate class as a subclass of an existing class (the receiver)." + ^ClassBuilder new + superclass: self + immediateSubclass: t + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>computeFormat:instSize:forSuper:ccIndex: (in category 'class format') ----- computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. + Answer the format or nil if there is any problem." - Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | type == #compiledMethod ifTrue: + [newInstSize > 0 ifTrue: + [self error: 'A compiled method class cannot have named instance variables'. + ^nil]. + ^CompiledMethod format]. - [^(CompiledMethod format - bitClear: (16r1F bitShift: 11)) - bitOr: (ccIndex bitShift: 11)]. instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). + instSize > 65535 ifTrue: - instSize > 254 ifTrue: [self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true]. type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false]. type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false]. type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false]. type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true]. + type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true]. + type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true]. + (isPointers not and: [instSize > 0]) ifTrue: + [self error: 'A non-pointer class cannot have named instance variables'. - (isPointers not and:[instSize > 0]) ifTrue: - [self error:'A non-pointer class cannot have instance variables'. ^nil]. + ^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak! - ^(self format: instSize - variable: isVar - words: isWords - pointers: isPointers - weak: isWeak) + (ccIndex bitShift: 11).! Item was changed: ----- Method: ClassBuilder>>format:variable:words:pointers:weak: (in category 'class format') ----- + format: nInstVars variable: isVar words: is32BitWords pointers: isPointers weak: isWeak + "Compute the format for the given instance specfication. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = reserved for 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | - format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak - "Compute the format for the given instance specfication." - | cClass instSpec sizeHiBits fmt | - self flag: #instSizeChange. - " - Smalltalk browseAllCallsOn: #instSizeChange. - Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. - Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. - " - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - For now the format word is... - <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> - But when we revise the image format, it should become... - <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> - " - sizeHiBits := (nInstVars+1) // 64. - cClass := 0. "for now" instSpec := isWeak + ifTrue: + [isVar + ifTrue: [4] + ifFalse: [5]] + ifFalse: + [isPointers + ifTrue: + [isVar + ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]] + ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]] + ifFalse: + [isVar + ifTrue: [is32BitWords ifTrue: [10] ifFalse: [16]] + ifFalse: [7]]]. + ^(instSpec bitShift: 16) + nInstVars! - ifTrue:[4] - ifFalse:[isPointers - ifTrue: [isVar - ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] - ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] - ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. - fmt := sizeHiBits. - fmt := (fmt bitShift: 5) + cClass. - fmt := (fmt bitShift: 4) + instSpec. - fmt := (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" - fmt := (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" - ^fmt! Item was added: + ----- Method: ClassBuilder>>superclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'public') ----- + superclass: aClass + immediateSubclass: t instanceVariableNames: f + classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a + new immediate class as a subclass of an existing class." + | env | + aClass instSize > 0 + ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields']. + aClass isVariable + ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables']. + aClass isPointers + ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields']. + "Cope with pre-environment and environment versions. Simplify asap." + env := (Smalltalk classNamed: #EnvironmentRequest) + ifNil: [aClass environment] + ifNotNil: [:erc| erc signal ifNil: [aClass environment]]. + ^self + name: t + inEnvironment: env + subclassOf: aClass + type: #immediate + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" - "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. - We can rely on two assumptions (which are critical): - #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) - #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. - Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. - " | meta | meta := oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." - [ - "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). - Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "make sure that the VM cache is clean" oldClass methodDict do: [:cm | cm flushCache]. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue: [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. oldClass updateMethodBindingsTo: oldClass binding. oldClass class updateMethodBindingsTo: oldClass class binding]. + "eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was + to ensure no old instances existed after the becomeForward:. Without the GC it was possible + to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward: + updated references from the old objects to new objects but didn't destroy the old objects. + But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."] + valueUnpreemptively! - Smalltalk garbageCollect. - - "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). - - The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: - - On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. - - Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). - - Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. - - Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." - - ] valueUnpreemptively. - ! Item was changed: ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame' poolDictionaries: '' category: 'Kernel-Methods'! + !CompiledMethod commentStamp: 'eem 8/12/2014 14:45' prior: 0! + CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. - !CompiledMethod commentStamp: 'eem 5/12/2014 18:02' prior: 0! - My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. I'm a subclass of ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. Class variables: SmallFrame - the number of stack slots in a small frame Context LargeFrame - the number of stack slots in a large frame Context PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set The current format of a CompiledMethod is as follows: header (4 or 8 bytes, SmallInteger) + literals (4 or 8 bytes each, Object, see "The last literal..." below) - literals (4 or 8 bytes each, Object) bytecodes (variable, bytes) trailer (variable, bytes) + The header is a 31-bit signed integer (a SmallInteger) in the following format: - The header is a 31-bit signed integer (a SmallInteger) with one of the two following formats, selected by the sign bit: - sign bit 0, header >= 0: - (index 0) 9 bits: main part of primitive number (#primitive) - (index 9) 8 bits: number of literals (#numLiterals) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) - (index 18) 6 bits: number of temporary variables (#numTemps) - (index 24) 4 bits: number of arguments to the method (#numArgs) - (index 28) 1 bit: high-bit of primitive number (#primitive) - (index 29) 1 bit: flag bit, ignored by the VM (#flag) - (index 30/63) sign bit: 0 selects the Primary instruction set (#signFlag) - sign bit 1, header < 0: (index 0) 16 bits: number of literals (#numLiterals) (index 16) 1 bit: has primitive + (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) + (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag). + (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4, 0 selects the primary instruction set, e.g. SqueakV3PlusClosures) (#signFlag) - (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public) - (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4) (#signFlag) - i.e. the Secondary Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode. + If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. + + The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer. + + The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be left nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.! - The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.! Item was added: + ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') ----- + handleFailingFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails then the + system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + "retry if user proceeds" + ^self newMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') ----- + handleFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after newMethod:header: has failed + and allowed a scavenging garbage collection to occur. The scavenging + collection will have happened as the VM is activating the (failing) basicNew:. + If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') ----- + installPrimaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was added: + ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') ----- + installSecondaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: ["For now the high bit of primitive no. is in the 29th bit of header" - primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits flagBit | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - "For now the high bit of the primitive no. is in a high bit of the header" - primBits := (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19). - - flagBit := flag ifTrue: [ 1 ] ifFalse: [ 0 ]. - - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits + - (flagBit bitShift: 29)! Item was changed: ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') ----- + newMethod: numberOfBytes header: headerWord - newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other + information) is specified by the headerWord (see my class comment). + The first argument specifies the number of fields for bytecodes in the + method. Fail if either argument is not a SmallInteger, or if numberOfBytes + is negative, or if memory is low. Once the header of a method is set by + this primitive, it cannot be changed to change the number of literals. + Essential. See Object documentation whatIsAPrimitive." - information) is specified the headerWord. The first argument specifies - the number of fields for bytecodes in the method. Fail if either - argument is not a SmallInteger, or if numberOfBytes is negative. Once - the header of a method is set by this primitive, it cannot be changed in - any way. Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingNewMethod: numberOfBytes header: headerWord]. - - (numberOfBytes isInteger and: - [headerWord isInteger and: - [numberOfBytes >= 0]]) ifTrue: [ - "args okay; space must be low" - OutOfMemory signal. - "retry if user proceeds" - ^ self newMethod: numberOfBytes header: headerWord - ]. ^self primitiveFailed! Item was changed: ----- Method: CompiledMethod class>>toReturnConstant:trailerBytes: (in category 'instance creation') ----- toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index - ! Item was changed: ----- Method: CompiledMethod class>>toReturnField:trailerBytes: (in category 'instance creation') ----- toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field - ! Item was changed: ----- Method: CompiledMethod class>>toReturnSelfTrailerBytes: (in category 'instance creation') ----- toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 - ! Item was added: + ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') ----- + bytecodeSetName + ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''! Item was changed: ----- Method: CompiledMethod>>headerDescription (in category 'literals') ----- headerDescription + "Answer a description containing the information about the form of the + receiver and the form of the context needed to run the receiver." - "Answer a description containing the information about the form of the - receiver and the form of the context needed to run the receiver." + ^(ByteString new: 128) writeStream + print: self header; cr; + nextPutAll: '"primitive: '; print: self primitive; cr; + nextPutAll: ' numArgs: '; print: self numArgs; cr; + nextPutAll: ' numTemps: '; print: self numTemps; cr; + nextPutAll: ' numLiterals: '; print: self numLiterals; cr; + nextPutAll: ' frameSize: '; print: self frameSize; cr; + nextPutAll: ' bytecodeSet: '; nextPutAll: self bytecodeSetName; + nextPut: $"; cr; + contents! - | s | - s := '' writeStream. - self header printOn: s. - s cr; nextPutAll: '"primitive: '. - self primitive printOn: s. - s cr; nextPutAll: ' numArgs: '. - self numArgs printOn: s. - s cr; nextPutAll: ' numTemps: '. - self numTemps printOn: s. - s cr; nextPutAll: ' numLiterals: '. - self numLiterals printOn: s. - s cr; nextPutAll: ' frameSize: '. - self frameSize printOn: s. - s cr; nextPutAll: ' isClosureCompiled: '. - self isBlueBookCompiled not printOn: s. - s nextPut: $"; cr. - ^ s contents! Item was changed: ----- Method: CompiledMethod>>numLiterals (in category 'accessing') ----- numLiterals "Answer the number of literals used by the receiver." + ^self header bitAnd: 65535! - | header | - ^(header := self header) < 0 - ifTrue: [header bitAnd: 65535] - ifFalse: [(header bitShift: -9) bitAnd: 16rFF]! Item was changed: ----- Method: CompiledMethod>>primitive (in category 'accessing') ----- primitive "Answer the primitive index associated with the receiver. + Zero indicates that this is not a primitive method." + | initialPC | + ^(self header anyMask: 65536) "Is the hasPrimitive? flag set?" + ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] + ifFalse: [0]! - Zero indicates that this is not a primitive method. - In the original header format we currently allow 10 bits of primitive index, but they are - in two places for backward compatibility. In the new format the primitive index is in the - last two bytes of a three byte callPrimitive: bytecode. The time to unpack is negligible, - since the derived primitive function pointer full index is stored in the method cache." - | header initialPC | - ^(header := self header) < 0 - ifTrue: - [(header anyMask: 65536) "Is the hasPrimitive? flag set?" - ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] - ifFalse: [0]] - ifFalse: - [(header bitAnd: 16r1FF) + ((header bitShift: -19) bitAnd: 16r200)]! Item was changed: ----- Method: ContextPart>>activateReturn:value: (in category 'private') ----- activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" + ^MethodContext + sender: self - ^ self - activateMethod: ContextPart theReturnMethod - withArgs: {value} receiver: aContext + method: MethodContext theReturnMethod + arguments: {value}! - class: aContext class! Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments + "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and + arguments are given as arguments to this message. If successful, push result and return + resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes + execution needs to be intercepted and simulated to avoid execution running away." - "Simulate a primitive method whose index is primitiveIndex. The - simulated receiver and arguments are given as arguments to this message. - If successful, push result and return resuming context, else ^ PrimitiveFailToken. - Any primitive which provokes execution needs to be intercepted and simulated - to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug + interesting code, such as the debugger itself. hence use primitive 19 with care :-)" - interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. + ((primitiveIndex between: 201 and: 222) + and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: + [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" + or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" + [^receiver simulateValueWithArguments: arguments caller: self]. + primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" + [^receiver simulateValueWithArguments: arguments first caller: self]]. - "ContextPart>>blockCopy:; simulated to get startpc right" - (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) - ifTrue: [^self push: ((BlockContext newForMethod: receiver method) - home: receiver home - startpc: pc + 2 - nargs: (arguments at: 1))]. - (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" - ifTrue: [^receiver pushArgs: arguments from: self]. - (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" - ifTrue: [^receiver pushArgs: arguments first from: self]. - primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" - ifTrue: [^self send: arguments first - to: receiver - with: arguments allButFirst - super: false]. - primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: nil]. - primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: (arguments at: 3)]. + primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [^self send: arguments first to: receiver with: arguments allButFirst super: false]. + primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. + primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. + "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. + ^(self isPrimFailToken: value) - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" - and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: (arguments at: 2) + arguments: (arguments at: 1)]. - method: arguments last - arguments: (primitiveIndex = 189 - ifTrue: [arguments at: 1] - ifFalse: [arguments allButLast])]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. - ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" - or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" - [^receiver simulateValueWithArguments: arguments caller: self]. - primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" - [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] + ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. + + ^(self isPrimFailToken: value) - ifFalse: - [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! Item was added: + ----- Method: ContextPart>>isPrimFailToken: (in category 'private') ----- + isPrimFailToken: anObject + ^(self objectClass: anObject) == Array + and: [anObject size = 2 + and: [anObject first == PrimitiveFailToken]]! Item was added: + ----- Method: ContextPart>>send:to:with:lookupIn: (in category 'controlling') ----- + send: selector to: rcvr with: arguments lookupIn: lookupClass + "Simulate the action of sending a message with selector and arguments + to rcvr. The argument, lookupClass, is the class in which to lookup the + message. This is the receiver's class for normal messages, but for super + messages it will be some specific class related to the source method." + + | meth primIndex val ctxt | + (meth := lookupClass lookupSelector: selector) ifNil: + [^self send: #doesNotUnderstand: + to: rcvr + with: {Message selector: selector arguments: arguments} + lookupIn: lookupClass]. + (primIndex := meth primitive) > 0 ifTrue: + [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments. + (self isPrimFailToken: val) ifFalse: + [^val]]. + (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue: + [^self error: 'Simulated message ', arguments first selector, ' not understood']. + ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments. + primIndex > 0 ifTrue: + [ctxt failPrimitiveWith: val]. + ^ctxt! Item was changed: ----- Method: ContextPart>>send:to:with:super: (in category 'controlling') ----- + send: selector to: rcvr with: arguments super: superFlag + "Simulate the action of sending a message with selector arguments + to rcvr. The argument, superFlag, tells whether the receiver of the + message was specified with 'super' in the source method." - send: selector to: rcvr with: args super: superFlag - "Simulate the action of sending a message with selector, selector, and - arguments, args, to receiver. The argument, superFlag, tells whether the - receiver of the message was specified with 'super' in the source method." + ^self send: selector + to: rcvr + with: arguments + lookupIn: (superFlag + ifTrue: [self method methodClassAssociation value superclass] + ifFalse: [self objectClass: rcvr])! - | class meth val ctxt | - class := superFlag - ifTrue: [self method methodClassAssociation value superclass] - ifFalse: [self objectClass: rcvr]. - meth := class lookupSelector: selector. - meth == nil ifTrue: - [^self - send: #doesNotUnderstand: - to: rcvr - with: (Array with: (Message selector: selector arguments: args)) - super: superFlag]. - val := self tryPrimitiveFor: meth receiver: rcvr args: args. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken]]) ifFalse: - [^val]. - (selector == #doesNotUnderstand: - and: [class == ProtoObject]) ifTrue: - [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood']. - ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken - and: [val last notNil - and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue: - [ctxt at: ctxt stackPtr put: val last]. - ^ctxt! Item was changed: ----- Method: ContextPart>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') ----- tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments + "Invoke the named primitive for aCompiledMethod, answering its result, or, + if the primiitve fails, answering the error code." - | selector theMethod spec receiverClass | ec ifNotNil: ["If ec is an integer other than -1 there was a problem with primitive 218, not with the external primitive itself. -1 indicates a generic failure (where ec should be nil) but ec = nil means primitive 218 is not implemented. So interpret -1 to mean the external primitive failed with a nil error code." ec isInteger ifTrue: [ec = -1 ifTrue: [ec := nil] + ifFalse: [self primitiveFailed]]]. + ^self class primitiveFailTokenFor: ec! - ifFalse: [self primitiveFailed]]. - ^{PrimitiveFailToken. ec}]. - "Assume a nil error code implies the primitive is not implemented and fall back on the old code." - "Hack. Attempt to execute the named primitive from the given compiled method" - arguments size > 8 ifTrue: - [^{PrimitiveFailToken. nil}]. - selector := #( - tryNamedPrimitive - tryNamedPrimitive: - tryNamedPrimitive:with: - tryNamedPrimitive:with:with: - tryNamedPrimitive:with:with:with: - tryNamedPrimitive:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. - receiverClass := self objectClass: aReceiver. - theMethod := receiverClass lookupSelector: selector. - theMethod == nil ifTrue: - [^{PrimitiveFailToken. nil}]. - spec := theMethod literalAt: 1. - spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. - Smalltalk unbindExternalPrimitives. - ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass! Item was added: + ----- Method: InstructionClient>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: pimIndex + "V3PlusClosures: 139 10001011 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + NewsqueakV4: 249 11111001 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + ( jjjjjjj * 256) + m=1 means inlined primitive, no hard return after execution."! Item was added: + ----- Method: InstructionPrinter>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: index + "Print the callPrimitive." + + self print: 'callPrimtive: ' , index printString! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self error: 'unusedBytecode']. byte3 := method at: pc. pc := pc + 1. + offset = 11 ifTrue: [^client callPrimitive: byte2 + (byte3 bitShift: 8)]. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: Integer class>>initialize (in category 'class initialization') ----- + initialize + "Integer initialize" + self initializeLowBitPerByteTable! - initialize "Integer initialize" - "Ensure we have the right compact class index" - - "LPI has been a compact class forever - just ensure basic correctness" - (LargePositiveInteger indexIfCompact = 5) ifFalse:[ - (Smalltalk compactClassesArray at: 5) - ifNil:[LargePositiveInteger becomeCompactSimplyAt: 5] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - "Cog requires LNI to be compact at 4 (replacing PseudoContext)" - (LargeNegativeInteger indexIfCompact = 4) ifFalse:[ - "PseudoContext will likely get removed at some point so write this test - without introducing a hard dependency" - (Smalltalk compactClassesArray at: 4) name == #PseudoContext - ifTrue:[Smalltalk compactClassesArray at: 4 put: nil]. - (Smalltalk compactClassesArray at: 4) - ifNil:[LargeNegativeInteger becomeCompactSimplyAt: 4] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - self initializeLowBitPerByteTable - ! Item was added: + ----- Method: MethodContext class>>allInstances (in category 'enumerating') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst. + Only count until thisContext since this context has been created only to + compute the existing instances." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + insts nextPut: inst. + inst := next]. + ^insts contents! Item was changed: ----- Method: MethodContext class>>allInstancesDo: (in category 'private') ----- allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst. + Only count until thisContext since evaluation of aBlock will create new contexts." - "Only count until thisContext since evaluation of aBlock will create new contexts." - | inst next | inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == thisContext] whileFalse:[ - next := inst nextInstance. - aBlock value: inst. - inst := next] - ! Item was added: + ----- Method: MethodContext>>failPrimitiveWith: (in category 'system simulation') ----- + failPrimitiveWith: maybePrimFailToken + "The receiver is a freshly-created context on a primitive method. Skip the callPrimitive: + bytecode and store the primitive fail code if there is one and the method consumes it." + self skipCallPrimitive. + ((self isPrimFailToken: maybePrimFailToken) + and: [method encoderClass isStoreAt: pc in: method]) ifTrue: + [self at: stackp put: maybePrimFailToken last]! Item was changed: ----- Method: ProtoObject>>scaledIdentityHash (in category 'comparing') ----- scaledIdentityHash "For identityHash values returned by primitive 75, answer + such values times 2^8. Otherwise, match the existing + identityHash implementation" - such values times 2^18. Otherwise, match the existing - identityHash implementation" + ^self identityHash * 256 "bitShift: 8"! - ^self identityHash * 262144 "bitShift: 18"! Item was changed: ==== ERROR === Error: Unrecognized class type 9 October 2014 5:49:49.796 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(SmallInteger) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Thu Oct 9 17:51:16 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:51:20 2014 Subject: [squeak-dev] The Trunk: System.spur-nice.673.mcz Message-ID: Eliot Miranda uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System.spur-nice.673.mcz ==================== Summary ==================== Name: System.spur-nice.673 Author: eem Time: 9 October 2014, 10:44:05.407 am UUID: ec1f5581-a968-4a9f-b269-5cfe6c7e40c5 Ancestors: System-nice.673, System.spur-dtl.672 System-nice.673 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Continue to disentangle the nest of vipers, one knot at a time. Replace usage of compressedMIMEEncodedStream, because - we do not need a ReadWriteStream (such requirement should be so rare) - we do not even need a ReadStream - we just need a String So let's use a String =============== Diff against System-nice.673 =============== Item was changed: ----- Method: SmalltalkImage>>compactClassesArray (in category 'special objects') ----- compactClassesArray "Smalltalk compactClassesArray" + "Backward-compatibility support. Spur does not have compact classes." + ^{}! - "Return the array of 31 classes whose instances may be - represented compactly" - ^ self specialObjectsArray at: 29! Item was added: + ----- Method: SmalltalkImage>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Essential. Fail if no memory is available." + + (numBytes isInteger and: [numBytes > 0]) ifTrue: + [OutOfMemory signal]. + ^self primitiveFailed! Item was added: + ----- Method: SmalltalkImage>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was changed: ----- Method: SmalltalkImage>>recreateSpecialObjectsArray (in category 'special objects') ----- recreateSpecialObjectsArray "Smalltalk recreateSpecialObjectsArray" "To external package developers: **** DO NOT OVERRIDE THIS METHOD. ***** If you are writing a plugin and need additional special object(s) for your own use, use addGCRoot() function and use own, separate special objects registry " "The Special Objects Array is an array of objects used by the Squeak virtual machine. Its contents are critical and accesses to it by the VM are unchecked, so don't even think of playing here unless you know what you are doing." | newArray | + newArray := Array new: 60. - newArray := Array new: 58. "Nil false and true get used throughout the interpreter" newArray at: 1 put: nil. newArray at: 2 put: false. newArray at: 3 put: true. "This association holds the active process (a ProcessScheduler)" newArray at: 4 put: (self specialObjectsArray at: 4) "(self bindingOf: #Processor) but it answers an Alias". "Numerous classes below used for type checking and instantiation" newArray at: 5 put: Bitmap. newArray at: 6 put: SmallInteger. newArray at: 7 put: ByteString. newArray at: 8 put: Array. newArray at: 9 put: Smalltalk. newArray at: 10 put: Float. + newArray at: 11 put: (self globals at: #MethodContext ifAbsent: [self globals at: #Context]). + newArray at: 12 put: nil. "was BlockContext." - newArray at: 11 put: MethodContext. - newArray at: 12 put: BlockContext. newArray at: 13 put: Point. newArray at: 14 put: LargePositiveInteger. newArray at: 15 put: Display. newArray at: 16 put: Message. newArray at: 17 put: CompiledMethod. + newArray at: 18 put: ((self specialObjectsArray at: 18) ifNil: [Semaphore new]). "low space Semaphore" - newArray at: 18 put: (self specialObjectsArray at: 18). - "(low space Semaphore)" newArray at: 19 put: Semaphore. newArray at: 20 put: Character. newArray at: 21 put: #doesNotUnderstand:. newArray at: 22 put: #cannotReturn:. newArray at: 23 put: nil. "This is the process signalling low space." "An array of the 32 selectors that are compiled as special bytecodes, paired alternately with the number of arguments each takes." newArray at: 24 put: #( #+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0 ). "An array of the 255 Characters in ascii order. + Cog inlines table into machine code at: prim so do not regenerate it. + This is nil in Spur, which has immediate Characters." - Cog inlines table into machine code at: prim so do not regenerate it." newArray at: 25 put: (self specialObjectsArray at: 25). newArray at: 26 put: #mustBeBoolean. newArray at: 27 put: ByteArray. newArray at: 28 put: Process. + "An array of up to 31 classes whose instances will have compact headers; an empty array in Spur" - "An array of up to 31 classes whose instances will have compact headers" newArray at: 29 put: self compactClassesArray. + newArray at: 30 put: ((self specialObjectsArray at: 30) ifNil: [Semaphore new]). "delay Semaphore" + newArray at: 31 put: ((self specialObjectsArray at: 31) ifNil: [Semaphore new]). "user interrupt Semaphore" - newArray at: 30 put: (self specialObjectsArray at: 30). "(delay Semaphore)" - newArray at: 31 put: (self specialObjectsArray at: 31). "(user interrupt Semaphore)" "Entries 32 - 34 unreferenced. Previously these contained prototype instances to be copied for fast initialization" + newArray at: 32 put: nil. "was the prototype Float" + newArray at: 33 put: nil. "was the prototype 4-byte LargePositiveInteger" + newArray at: 34 put: nil. "was the prototype Point" - newArray at: 32 put: nil. "was (Float new: 2)" - newArray at: 33 put: nil. "was (LargePositiveInteger new: 4)" - newArray at: 34 put: nil. "was Point new" newArray at: 35 put: #cannotInterpret:. + newArray at: 36 put: nil. "was the prototype MethodContext" - "Note: This must be fixed once we start using context prototypes (yeah, right)" - "(MethodContext new: CompiledMethod fullFrameSize)." - newArray at: 36 put: (self specialObjectsArray at: 36). "Is the prototype MethodContext (unused by the VM)" newArray at: 37 put: BlockClosure. + newArray at: 38 put: nil. "was the prototype BlockContext" - "(BlockContext new: CompiledMethod fullFrameSize)." - newArray at: 38 put: (self specialObjectsArray at: 38). "Is the prototype BlockContext (unused by the VM)" "array of objects referred to by external code" + newArray at: 39 put: (self specialObjectsArray at: 39). "external semaphores" - newArray at: 39 put: (self specialObjectsArray at: 39). "preserve external semaphores" newArray at: 40 put: nil. "Reserved for Mutex in Cog VMs" + newArray at: 41 put: ((self specialObjectsArray at: 41) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT" + newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). "finalization Semaphore" - newArray at: 41 put: nil. "Reserved for a LinkedList instance for overlapped calls in CogMT" - "finalization Semaphore" - newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). newArray at: 43 put: LargeNegativeInteger. "External objects for callout. Note: Written so that one can actually completely remove the FFI." newArray at: 44 put: (self at: #ExternalAddress ifAbsent: []). newArray at: 45 put: (self at: #ExternalStructure ifAbsent: []). newArray at: 46 put: (self at: #ExternalData ifAbsent: []). newArray at: 47 put: (self at: #ExternalFunction ifAbsent: []). newArray at: 48 put: (self at: #ExternalLibrary ifAbsent: []). newArray at: 49 put: #aboutToReturn:through:. newArray at: 50 put: #run:with:in:. "51 reserved for immutability message" + newArray at: 51 put: #attemptToAssign:withIndex:. - "newArray at: 51 put: #attemptToAssign:withIndex:." - newArray at: 51 put: (self specialObjectsArray at: 51 ifAbsent: []). newArray at: 52 put: #(nil "nil => generic error" #'bad receiver' #'bad argument' #'bad index' #'bad number of arguments' #'inappropriate operation' #'unsupported operation' #'no modification' #'insufficient object memory' #'insufficient C memory' #'not found' #'bad method' #'internal error in named primitive machinery' #'object may move' #'resource limit exceeded' + #'object is pinned' #'primitive write beyond end of object'). - #'object is pinned'). "53 to 55 are for Alien" newArray at: 53 put: (self at: #Alien ifAbsent: []). + newArray at: 54 put: #invokeCallbackContext:. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." - newArray at: 54 put: #invokeCallbackContext::. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." newArray at: 55 put: (self at: #UnsafeAlien ifAbsent: []). + "Used to be WeakFinalizationList for WeakFinalizationList hasNewFinalization, obsoleted by ephemeron support." + newArray at: 56 put: nil. - "Weak reference finalization" - newArray at: 56 put: (self at: #WeakFinalizationList ifAbsent: []). "reserved for foreign callback process" newArray at: 57 put: (self specialObjectsArray at: 57 ifAbsent: []). newArray at: 58 put: #unusedBytecode. + "59 reserved for Sista counter tripped message" + newArray at: 59 put: #conditionalBranchCounterTrippedOn:. + "60 reserved for Sista class trap message" + newArray at: 60 put: #classTrapFor:. "Now replace the interpreter's reference in one atomic operation" + self specialObjectsArray becomeForward: newArray! - self specialObjectsArray becomeForward: newArray - ! Item was changed: ----- Method: SmalltalkImage>>setGCParameters (in category 'snapshot and quit') ----- setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" - "Adjust the VM's default GC parameters to avoid premature tenuring." + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! - self vmParameterAt: 5 put: 4000. "do an incremental GC after this many allocations" - self vmParameterAt: 6 put: 2000. "tenure when more than this many objects survive the GC" - ! Item was changed: ----- Method: SpaceTally>>spaceForInstancesOf: (in category 'instance size') ----- spaceForInstancesOf: aClass + "Answer a pair of the number of bytes consumed by all instances of the + given class, including their object headers, and the number of instances." - "Answer the number of bytes consumed by all instances of the given class, including their object headers and the number of instances." + | instances total | + instances := aClass allInstances. + instances isEmpty ifTrue: [^#(0 0)]. - | smallHeaderSize instVarBytes isVariable bytesPerElement total lastInstance instance instanceCount | - instance := aClass someInstance ifNil: [ ^#(0 0) ]. - smallHeaderSize := aClass isCompact ifTrue: [ 4 ] ifFalse: [ 8 ]. - instVarBytes := aClass instSize * 4. - isVariable := aClass isVariable. - bytesPerElement := isVariable - ifFalse: [ 0 ] - ifTrue: [ aClass isBytes ifTrue: [ 1 ] ifFalse: [ 4 ] ]. total := 0. + aClass isVariable + ifTrue: + [instances do: + [:i| total := total + (aClass byteSizeOfInstanceOfSize: i basicSize)]] + ifFalse: + [total := instances size * aClass byteSizeOfInstance]. + ^{ total. instances size }! - instanceCount := 0. - "A modified version of #allInstancesDo: is inlined here. It avoids an infinite loop when another process is creating new instances of aClass." - self flag: #allInstancesDo:. - lastInstance := - aClass == CompiledMethod "CompiledMethod has special format, see its class comment" - ifTrue: [aClass new] - ifFalse: [aClass basicNew]. - [ instance == lastInstance ] whileFalse: [ - | contentBytes headerBytes | - contentBytes := instVarBytes + (isVariable - ifFalse: [ 0 ] - ifTrue: [ instance basicSize * bytesPerElement ]). - headerBytes := contentBytes > 255 - ifTrue: [ 12 ] - ifFalse: [ smallHeaderSize ]. - total := total + headerBytes + (contentBytes roundUpTo: 4). - instanceCount := instanceCount + 1. - instance := instance nextInstance ]. - ^{ total. instanceCount }! Item was added: + ----- Method: SystemDictionary>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Fail if no memory is available. Essential." + + ^(numBytes isInteger and: [numBytes > 0]) + ifTrue: [OutOfMemory signal] + ifFalse: [self primitiveFailed]! Item was added: + ----- Method: SystemDictionary>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was added: + ----- Method: SystemDictionary>>setGCParameters (in category 'snapshot and quit') ----- + setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" + + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! Item was added: + ----- Method: SystemNavigation>>allObjects (in category 'query') ----- + allObjects + "Answer an Array of all objects in the system. Fail if + there isn't enough memory to instantiate the result." + + ^self primitiveFailed! Item was changed: ----- Method: SystemNavigation>>allObjectsDo: (in category 'query') ----- allObjectsDo: aBlock + "Evaluate the argument, aBlock, for each object in the system, excluding immediates + such as SmallInteger and Character." + self allObjectsOrNil + ifNotNil: [:allObjects| allObjects do: aBlock] + ifNil: + ["Fall back on the old single object primitive code. With closures, this needs + to use an end marker (lastObject) since activation of the block will create + new contexts and cause an infinite loop. The lastObject must be created + before calling someObject, so that the VM can settle the enumeration (e.g. + by flushing new space) as a side effect of someObject" + | object lastObject | + lastObject := Object new. + object := self someObject. + [lastObject == object or: [0 == object]] whileFalse: + [aBlock value: object. + object := object nextObject]]! - "Evaluate the argument, aBlock, for each object in the system - excluding SmallIntegers. With closures, this needs to use an end - marker (lastObject) since activation of the block will create new - contexts and cause an infinite loop." - | object lastObject | - object := self someObject. - lastObject := Object new. - [lastObject == object or: [0 == object]] - whileFalse: [aBlock value: object. - object := object nextObject]! Item was added: + ----- Method: SystemNavigation>>allObjectsOrNil (in category 'query') ----- + allObjectsOrNil + "Answer an Array of all objects in the system. Fail if there isn't + enough memory to instantiate the result and answer nil." + + ^nil! From commits at source.squeak.org Thu Oct 9 17:51:16 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:51:27 2014 Subject: [squeak-dev] The Trunk: Kernel.spur-eem.878.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel.spur-eem.878.mcz ==================== Summary ==================== Name: Kernel.spur-eem.878 Author: eem Time: 9 October 2014, 10:41:32.967 am UUID: 7891bff2-b17e-44a6-a843-7f29201ce3b0 Ancestors: Kernel-eem.878, Kernel.spur-eem.876 Kernel-eem.878 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Less haste, more speed. Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) =============== Diff against Kernel-eem.878 =============== Item was changed: ----- Method: Behavior>>allInstances (in category 'accessing instances and variables') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + (inst == insts or: [inst == insts originalContents]) ifFalse: [insts nextPut: inst]. + inst := next]. + ^insts contents! - allInstances - "Answer a collection of all current instances of the receiver." - - | all | - all := OrderedCollection new. - self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. - ^ all asArray - ! Item was changed: ----- Method: Behavior>>allInstancesDo: (in category 'enumerating') ----- + allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst." - allInstancesDo: aBlock - "Evaluate the argument, aBlock, for each of the current instances of the - receiver. - - Because aBlock might change the class of inst (for example, using become:), - it is essential to compute next before aBlock value: inst." - | inst next | inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == nil] - whileFalse: - [ - next := inst nextInstance. - aBlock value: inst. - inst := next]! Item was added: + ----- Method: Behavior>>allInstancesOrNil (in category 'enumerating') ----- + allInstancesOrNil + "Answer all instances of the receiver, or nil if the primitive + fails, which it may be due to being out of memory." + + ^nil! Item was changed: ----- Method: Behavior>>basicNew (in category 'instance creation') ----- basicNew "Primitive. Answer an instance of the receiver (which is a class) with no + indexable variables. Fail if the class is indexable. Essential. See Object + documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run + before the method is activated. Check that space was low and retry + via handleFailingBasicNew if so." - indexable variables. Fail if the class is indexable. Essential. See Object - documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew]. + self isVariable ifTrue: [^self basicNew: 0]. + self primitiveFailed! - - self isVariable ifTrue: [ ^ self basicNew: 0 ]. - "space must be low" - OutOfMemory signal. - ^ self basicNew "retry if user proceeds" - ! Item was changed: ----- Method: Behavior>>basicNew: (in category 'instance creation') ----- + basicNew: sizeRequested + "Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run before the + method is activated. Check args and retry via handleFailingBasicNew: if they're OK." - basicNew: sizeRequested - "Primitive. Answer an instance of this class with the number - of indexable variables specified by the argument, sizeRequested. - Fail if this class is not indexable or if the argument is not a - positive Integer, or if there is not enough memory available. - Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew: sizeRequested]. - self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. - (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: - ["arg okay; space must be low." - OutOfMemory signal. - ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstance (in category 'accessing instances and variables') ----- + byteSizeOfInstance + "Answer the total memory size of an instance of the receiver." + + + self isVariable ifTrue: + [^self byteSizeOfInstanceOfSize: 0]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstanceOfSize: (in category 'accessing instances and variables') ----- + byteSizeOfInstanceOfSize: basicSize + "Answer the total memory size of an instance of the receiver + with the given number of indexable instance variables." + + + self isVariable + ifTrue: "If the primitive overflowed answer a close approximation" + [(basicSize isInteger + and: [basicSize >= 16r1000000]) ifTrue: + [^2 * (self byteSizeOfInstanceOfSize: basicSize + 1 // 2) + - (self byteSizeOfInstanceOfSize: 0)]] + ifFalse: + [basicSize = 0 ifTrue: + [^self byteSizeOfInstance]]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>elementSize (in category 'accessing instances and variables') ----- + elementSize + "Answer the size in bytes of an element in the receiver. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + instSpec < 9 ifTrue: [^Smalltalk wordSize]. + instSpec >= 16 ifTrue: [^1]. + instSpec >= 12 ifTrue: [^2]. + instSpec >= 10 ifTrue: [^4]. + ^8! Item was added: + ----- Method: Behavior>>handleFailingBasicNew (in category 'private') ----- + handleFailingBasicNew + "handleFailingBasicNew gets sent after basicNew has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew. If + handleFailingBasicNew fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + Smalltalk garbageCollect < 1048576 ifTrue: + [Smalltalk growMemoryByAtLeast: 1048576]. + ^self handleFailingFailingBasicNew "retry after global garbage collect"! Item was added: + ----- Method: Behavior>>handleFailingBasicNew: (in category 'private') ----- + handleFailingBasicNew: sizeRequested + "handleFailingBasicNew: gets sent after basicNew: has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew:. If + handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := self byteSizeOfInstanceOfSize: sizeRequested. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingBasicNew: sizeRequested! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew (in category 'private') ----- + handleFailingFailingBasicNew + "This basicNew gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low" + OutOfMemory signal. + ^self basicNew "retry if user proceeds"! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew: (in category 'private') ----- + handleFailingFailingBasicNew: sizeRequested + "This basicNew: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + ^self basicNew: sizeRequested "retry if user proceeds"! Item was added: + ----- Method: Behavior>>identityHash (in category 'comparing') ----- + identityHash + "Answer a SmallInteger whose value is related to the receiver's identity. + Behavior implements identityHash to allow the VM to use an object representation which + does not include a direct reference to an object's class in an object. If the VM is using + this implementation then classes are held in a class table and instances contain the index + of their class in the table. A class's class table index is its identityHash so that an instance + can be created without searching the table for a class's index. The VM uses this primitive + to enter the class into the class table, assigning its identityHash with an as yet unused + class table index. If this primitive fails it means that the class table is full. In Spur as of + 2014 there are 22 bits of classTable index and 22 bits of identityHash per object. + + Primitive. Essential. Do not override. See Object documentation whatIsAPrimitive." + + + self primitiveFailed! Item was changed: ----- Method: Behavior>>indexIfCompact (in category 'private') ----- indexIfCompact + "Backward compatibility with the Squeak V3 object format. + Spur does not have a distinction between compact and non-compact classes." + ^0! - "If these 5 bits are non-zero, then instances of this class - will be compact. It is crucial that there be an entry in - Smalltalk compactClassesArray for any class so optimized. - See the msgs becomeCompact and becomeUncompact." - ^ (format bitShift: -11) bitAnd: 16r1F - " - Smalltalk compactClassesArray doWithIndex: - [:c :i | c == nil ifFalse: - [c indexIfCompact = i ifFalse: [self halt]]] - "! Item was changed: ----- Method: Behavior>>instSize (in category 'testing') ----- instSize "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^format bitAnd: 16rFFFF! - (as opposed to indexed variables) of the receiver." - - self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - When we revise the image format, it should become... - ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 - Note also that every other method in this category will require - 2 bits more of right shift after the change. - " - ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! Item was changed: ----- Method: Behavior>>instSpec (in category 'testing') ----- instSpec + "Answer the instance specification part of the format that defines what kind of object + an instance of the receiver is. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^(format bitShift: -16) bitAnd: 16r1F! - ^ (format bitShift: -7) bitAnd: 16rF! Item was changed: ----- Method: Behavior>>isBits (in category 'testing') ----- isBits + "Answer whether the receiver contains just bits (not pointers). + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 7! - "Answer whether the receiver contains just bits (not pointers)." - - ^ self instSpec >= 6! Item was changed: ----- Method: Behavior>>isBytes (in category 'testing') ----- isBytes + "Answer whether the receiver has 8-bit instance variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 16! - "Answer whether the receiver has 8-bit instance variables." - - ^ self instSpec >= 8! Item was added: + ----- Method: Behavior>>isEphemeronClass (in category 'testing') ----- + isEphemeronClass + "Answer whether the receiver has ephemeral instance variables. The garbage collector will + fire (queue for finalization) any ephemeron whose first instance variable is not referenced + other than from the transitive closure of references from ephemerons. Hence referring to + an object from the first inst var of an ephemeron will cause the ephemeron to fire when + the rest of the system does not refer to the object and that object is ready to be collected. + Since references from the remaining inst vars of an ephemeron will not prevent the ephemeron + from firing, ephemerons may act as the associations in weak dictionaries such that the value + (e.g. properties attached to the key) will not prevent firing when the key is no longer referenced + other than from ephemerons. Ephemerons can therefore be used to implement instance-based + pre-mortem finalization." + ^self instSpec = 5! Item was added: + ----- Method: Behavior>>isImmediateClass (in category 'testing') ----- + isImmediateClass + "Answer whether the receiver has immediate instances. Immediate instances + store their value in their object pointer, not in an object body. Hence immediates + take no space and are immutable. The immediates are distinguished by tag bits + in the pointer. They include SmallIntegers and Characters. Hence in the 32-bit + system SmallIntegers are 31-bit signed integers and Characters are 30-bit + unsigned character codes." + ^self instSpec = 7! Item was changed: ----- Method: Behavior>>isVariable (in category 'testing') ----- isVariable + "Answer whether the receiver has indexable variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + ^instSpec >= 2 and: [instSpec <= 4 or: [instSpec >= 9]]! - "Answer whether the receiver has indexable variables." - - ^ self instSpec >= 2! Item was changed: ----- Method: Behavior>>kindOfSubclass (in category 'testing class hierarchy') ----- kindOfSubclass + "Answer a String that is the keyword that describes the receiver's kind of subclass, + either a regular subclass, a variableSubclass, a variableByteSubclass, + a variableWordSubclass, a weakSubclass, an ephemeronSubclass or an immediateSubclass. + c.f. typeOfClass" + ^self isVariable + ifTrue: + [self isBits + ifTrue: + [self isBytes + ifTrue: [' variableByteSubclass: '] + ifFalse: [' variableWordSubclass: ']] + ifFalse: + [self isWeak + ifTrue: [' weakSubclass: '] + ifFalse: [' variableSubclass: ']]] + ifFalse: + [self isImmediateClass + ifTrue: [' immediateSubclass: '] + ifFalse: + [self isEphemeronClass + ifTrue: [' ephemeronSubclass: '] + ifFalse: [' subclass: ']]]! - "Answer a String that is the keyword that describes the receiver's kind - of subclass, either a regular subclass, a variableSubclass, a - variableByteSubclass, a variableWordSubclass, or a weakSubclass." - self isWeak - ifTrue: [^ ' weakSubclass: ']. - ^ self isVariable - ifTrue: [self isBits - ifTrue: [self isBytes - ifTrue: [ ' variableByteSubclass: '] - ifFalse: [ ' variableWordSubclass: ']] - ifFalse: [ ' variableSubclass: ']] - ifFalse: [ ' subclass: ']! Item was changed: ----- Method: Behavior>>shouldNotBeRedefined (in category 'testing') ----- shouldNotBeRedefined + "Answer if the receiver should not be redefined. + The assumption is that classes in Smalltalk specialObjects and + instance-specific Behaviors should not be redefined" - "Return true if the receiver should not be redefined. - The assumption is that compact classes, - classes in Smalltalk specialObjects and - Behaviors should not be redefined" + ^(Smalltalk specialObjectsArray + identityIndexOf: self + ifAbsent: [(self isKindOf: self) ifTrue: [1] ifFalse: [0]]) ~= 0! - ^(Smalltalk compactClassesArray includes: self) - or:[(Smalltalk specialObjectsArray includes: self) - or:[self isKindOf: self]]! Item was changed: ----- Method: Behavior>>typeOfClass (in category 'accessing') ----- typeOfClass + "Answer a symbol uniquely describing the type of the receiver. c.f. kindOfSubclass" + self isBytes ifTrue: + [^self instSpec = CompiledMethod instSpec + ifTrue: [#compiledMethod] "Very special!!" + ifFalse: [#bytes]]. + (self isWords and: [self isPointers not]) ifTrue: + [^self instSpec = SmallInteger instSpec + ifTrue: [#immediate] "Very special!!" + ifFalse: [#words]]. + self isWeak ifTrue: [^#weak]. + self isVariable ifTrue: [^#variable]. + self isEphemeronClass ifTrue: [^#ephemeron]. + ^#normal! - "Answer a symbol uniquely describing the type of the receiver" - self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" - self isBytes ifTrue:[^#bytes]. - (self isWords and:[self isPointers not]) ifTrue:[^#words]. - self isWeak ifTrue:[^#weak]. - self isVariable ifTrue:[^#variable]. - ^#normal.! Item was changed: ----- Method: BlockClosure>>simulateValueWithArguments:caller: (in category 'system simulation') ----- simulateValueWithArguments: anArray caller: aContext + "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity." | newContext sz | - (anArray class ~~ Array - or: [numArgs ~= anArray size]) ifTrue: - [^ContextPart primitiveFailTokenFor: nil]. newContext := (MethodContext newForMethod: outerContext method) setSender: aContext receiver: outerContext receiver method: outerContext method closure: self startpc: startpc. + ((newContext objectClass: anArray) ~~ Array + or: [numArgs ~= anArray size]) ifTrue: + [^ContextPart primitiveFailTokenFor: nil]. sz := self basicSize. newContext stackp: sz + numArgs. 1 to: numArgs do: [:i| newContext at: i put: (anArray at: i)]. 1 to: sz do: [:i| newContext at: i + numArgs put: (self at: i)]. ^newContext! Item was added: + ----- Method: Class>>immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'subclass creation') ----- + immediateSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a new + immediate class as a subclass of an existing class (the receiver)." + ^ClassBuilder new + superclass: self + immediateSubclass: t + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>computeFormat:instSize:forSuper:ccIndex: (in category 'class format') ----- computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. + Answer the format or nil if there is any problem." - Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | type == #compiledMethod ifTrue: + [newInstSize > 0 ifTrue: + [self error: 'A compiled method class cannot have named instance variables'. + ^nil]. + ^CompiledMethod format]. - [^(CompiledMethod format - bitClear: (16r1F bitShift: 11)) - bitOr: (ccIndex bitShift: 11)]. instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). + instSize > 65535 ifTrue: - instSize > 254 ifTrue: [self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true]. type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false]. type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false]. type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false]. type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true]. + type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true]. + type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true]. + (isPointers not and: [instSize > 0]) ifTrue: + [self error: 'A non-pointer class cannot have named instance variables'. - (isPointers not and:[instSize > 0]) ifTrue: - [self error:'A non-pointer class cannot have instance variables'. ^nil]. + ^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak! - ^(self format: instSize - variable: isVar - words: isWords - pointers: isPointers - weak: isWeak) + (ccIndex bitShift: 11).! Item was changed: ----- Method: ClassBuilder>>format:variable:words:pointers:weak: (in category 'class format') ----- + format: nInstVars variable: isVar words: is32BitWords pointers: isPointers weak: isWeak + "Compute the format for the given instance specfication. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = reserved for 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | - format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak - "Compute the format for the given instance specfication." - | cClass instSpec sizeHiBits fmt | - self flag: #instSizeChange. - " - Smalltalk browseAllCallsOn: #instSizeChange. - Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. - Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. - " - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - For now the format word is... - <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> - But when we revise the image format, it should become... - <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> - " - sizeHiBits := (nInstVars+1) // 64. - cClass := 0. "for now" instSpec := isWeak + ifTrue: + [isVar + ifTrue: [4] + ifFalse: [5]] + ifFalse: + [isPointers + ifTrue: + [isVar + ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]] + ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]] + ifFalse: + [isVar + ifTrue: [is32BitWords ifTrue: [10] ifFalse: [16]] + ifFalse: [7]]]. + ^(instSpec bitShift: 16) + nInstVars! - ifTrue:[4] - ifFalse:[isPointers - ifTrue: [isVar - ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] - ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] - ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. - fmt := sizeHiBits. - fmt := (fmt bitShift: 5) + cClass. - fmt := (fmt bitShift: 4) + instSpec. - fmt := (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" - fmt := (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" - ^fmt! Item was added: + ----- Method: ClassBuilder>>superclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'public') ----- + superclass: aClass + immediateSubclass: t instanceVariableNames: f + classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a + new immediate class as a subclass of an existing class." + | env | + aClass instSize > 0 + ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields']. + aClass isVariable + ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables']. + aClass isPointers + ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields']. + "Cope with pre-environment and environment versions. Simplify asap." + env := (Smalltalk classNamed: #EnvironmentRequest) + ifNil: [aClass environment] + ifNotNil: [:erc| erc signal ifNil: [aClass environment]]. + ^self + name: t + inEnvironment: env + subclassOf: aClass + type: #immediate + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" - "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. - We can rely on two assumptions (which are critical): - #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) - #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. - Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. - " | meta | meta := oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." - [ - "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). - Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "make sure that the VM cache is clean" oldClass methodDict do: [:cm | cm flushCache]. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue: [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. oldClass updateMethodBindingsTo: oldClass binding. oldClass class updateMethodBindingsTo: oldClass class binding]. + "eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was + to ensure no old instances existed after the becomeForward:. Without the GC it was possible + to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward: + updated references from the old objects to new objects but didn't destroy the old objects. + But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."] + valueUnpreemptively! - Smalltalk garbageCollect. - - "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). - - The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: - - On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. - - Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). - - Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. - - Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." - - ] valueUnpreemptively. - ! Item was changed: ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame' poolDictionaries: '' category: 'Kernel-Methods'! + !CompiledMethod commentStamp: 'eem 8/12/2014 14:45' prior: 0! + CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. - !CompiledMethod commentStamp: 'eem 5/12/2014 18:02' prior: 0! - My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. I'm a subclass of ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. Class variables: SmallFrame - the number of stack slots in a small frame Context LargeFrame - the number of stack slots in a large frame Context PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set The current format of a CompiledMethod is as follows: header (4 or 8 bytes, SmallInteger) + literals (4 or 8 bytes each, Object, see "The last literal..." below) - literals (4 or 8 bytes each, Object) bytecodes (variable, bytes) trailer (variable, bytes) + The header is a 31-bit signed integer (a SmallInteger) in the following format: - The header is a 31-bit signed integer (a SmallInteger) with one of the two following formats, selected by the sign bit: - sign bit 0, header >= 0: - (index 0) 9 bits: main part of primitive number (#primitive) - (index 9) 8 bits: number of literals (#numLiterals) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) - (index 18) 6 bits: number of temporary variables (#numTemps) - (index 24) 4 bits: number of arguments to the method (#numArgs) - (index 28) 1 bit: high-bit of primitive number (#primitive) - (index 29) 1 bit: flag bit, ignored by the VM (#flag) - (index 30/63) sign bit: 0 selects the Primary instruction set (#signFlag) - sign bit 1, header < 0: (index 0) 16 bits: number of literals (#numLiterals) (index 16) 1 bit: has primitive + (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) + (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag). + (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4, 0 selects the primary instruction set, e.g. SqueakV3PlusClosures) (#signFlag) - (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public) - (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4) (#signFlag) - i.e. the Secondary Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode. + If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. + + The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer. + + The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be left nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.! - The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.! Item was added: + ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') ----- + handleFailingFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails then the + system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + "retry if user proceeds" + ^self newMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') ----- + handleFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after newMethod:header: has failed + and allowed a scavenging garbage collection to occur. The scavenging + collection will have happened as the VM is activating the (failing) basicNew:. + If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') ----- + installPrimaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was added: + ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') ----- + installSecondaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: ["For now the high bit of primitive no. is in the 29th bit of header" - primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits flagBit | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - "For now the high bit of the primitive no. is in a high bit of the header" - primBits := (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19). - - flagBit := flag ifTrue: [ 1 ] ifFalse: [ 0 ]. - - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits + - (flagBit bitShift: 29)! Item was changed: ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') ----- + newMethod: numberOfBytes header: headerWord - newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other + information) is specified by the headerWord (see my class comment). + The first argument specifies the number of fields for bytecodes in the + method. Fail if either argument is not a SmallInteger, or if numberOfBytes + is negative, or if memory is low. Once the header of a method is set by + this primitive, it cannot be changed to change the number of literals. + Essential. See Object documentation whatIsAPrimitive." - information) is specified the headerWord. The first argument specifies - the number of fields for bytecodes in the method. Fail if either - argument is not a SmallInteger, or if numberOfBytes is negative. Once - the header of a method is set by this primitive, it cannot be changed in - any way. Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingNewMethod: numberOfBytes header: headerWord]. - - (numberOfBytes isInteger and: - [headerWord isInteger and: - [numberOfBytes >= 0]]) ifTrue: [ - "args okay; space must be low" - OutOfMemory signal. - "retry if user proceeds" - ^ self newMethod: numberOfBytes header: headerWord - ]. ^self primitiveFailed! Item was changed: ----- Method: CompiledMethod class>>toReturnConstant:trailerBytes: (in category 'instance creation') ----- toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index - ! Item was changed: ----- Method: CompiledMethod class>>toReturnField:trailerBytes: (in category 'instance creation') ----- toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field - ! Item was changed: ----- Method: CompiledMethod class>>toReturnSelfTrailerBytes: (in category 'instance creation') ----- toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 - ! Item was added: + ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') ----- + bytecodeSetName + ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''! Item was changed: ----- Method: CompiledMethod>>headerDescription (in category 'literals') ----- headerDescription + "Answer a description containing the information about the form of the + receiver and the form of the context needed to run the receiver." - "Answer a description containing the information about the form of the - receiver and the form of the context needed to run the receiver." + ^(ByteString new: 128) writeStream + print: self header; cr; + nextPutAll: '"primitive: '; print: self primitive; cr; + nextPutAll: ' numArgs: '; print: self numArgs; cr; + nextPutAll: ' numTemps: '; print: self numTemps; cr; + nextPutAll: ' numLiterals: '; print: self numLiterals; cr; + nextPutAll: ' frameSize: '; print: self frameSize; cr; + nextPutAll: ' bytecodeSet: '; nextPutAll: self bytecodeSetName; + nextPut: $"; cr; + contents! - | s | - s := '' writeStream. - self header printOn: s. - s cr; nextPutAll: '"primitive: '. - self primitive printOn: s. - s cr; nextPutAll: ' numArgs: '. - self numArgs printOn: s. - s cr; nextPutAll: ' numTemps: '. - self numTemps printOn: s. - s cr; nextPutAll: ' numLiterals: '. - self numLiterals printOn: s. - s cr; nextPutAll: ' frameSize: '. - self frameSize printOn: s. - s cr; nextPutAll: ' isClosureCompiled: '. - self isBlueBookCompiled not printOn: s. - s nextPut: $"; cr. - ^ s contents! Item was changed: ----- Method: CompiledMethod>>numLiterals (in category 'accessing') ----- numLiterals "Answer the number of literals used by the receiver." + ^self header bitAnd: 65535! - | header | - ^(header := self header) < 0 - ifTrue: [header bitAnd: 65535] - ifFalse: [(header bitShift: -9) bitAnd: 16rFF]! Item was changed: ----- Method: CompiledMethod>>primitive (in category 'accessing') ----- primitive "Answer the primitive index associated with the receiver. + Zero indicates that this is not a primitive method." + | initialPC | + ^(self header anyMask: 65536) "Is the hasPrimitive? flag set?" + ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] + ifFalse: [0]! - Zero indicates that this is not a primitive method. - In the original header format we currently allow 10 bits of primitive index, but they are - in two places for backward compatibility. In the new format the primitive index is in the - last two bytes of a three byte callPrimitive: bytecode. The time to unpack is negligible, - since the derived primitive function pointer full index is stored in the method cache." - | header initialPC | - ^(header := self header) < 0 - ifTrue: - [(header anyMask: 65536) "Is the hasPrimitive? flag set?" - ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] - ifFalse: [0]] - ifFalse: - [(header bitAnd: 16r1FF) + ((header bitShift: -19) bitAnd: 16r200)]! Item was changed: ----- Method: ContextPart>>activateReturn:value: (in category 'private') ----- activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" + ^MethodContext + sender: self - ^ self - activateMethod: ContextPart theReturnMethod - withArgs: {value} receiver: aContext + method: MethodContext theReturnMethod + arguments: {value}! - class: aContext class! Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments + "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and + arguments are given as arguments to this message. If successful, push result and return + resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes + execution needs to be intercepted and simulated to avoid execution running away." - "Simulate a primitive method whose index is primitiveIndex. The - simulated receiver and arguments are given as arguments to this message. - If successful, push result and return resuming context, else ^ PrimitiveFailToken. - Any primitive which provokes execution needs to be intercepted and simulated - to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug + interesting code, such as the debugger itself. hence use primitive 19 with care :-)" - interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. + ((primitiveIndex between: 201 and: 222) + and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: + [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" + or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" + [^receiver simulateValueWithArguments: arguments caller: self]. + primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" + [^receiver simulateValueWithArguments: arguments first caller: self]]. - "ContextPart>>blockCopy:; simulated to get startpc right" - (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) - ifTrue: [^self push: ((BlockContext newForMethod: receiver method) - home: receiver home - startpc: pc + 2 - nargs: (arguments at: 1))]. - (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" - ifTrue: [^receiver pushArgs: arguments from: self]. - (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" - ifTrue: [^receiver pushArgs: arguments first from: self]. - primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" - ifTrue: [^self send: arguments first - to: receiver - with: arguments allButFirst - super: false]. - primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: nil]. - primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: (arguments at: 3)]. + primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [^self send: arguments first to: receiver with: arguments allButFirst super: false]. + primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. + primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. + "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. + ^(self isPrimFailToken: value) - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" - and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: (arguments at: 2) + arguments: (arguments at: 1)]. - method: arguments last - arguments: (primitiveIndex = 188 - ifTrue: [arguments at: 1] - ifFalse: [arguments allButLast])]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. - ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" - or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" - [^receiver simulateValueWithArguments: arguments caller: self]. - primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" - [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] + ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. + + ^(self isPrimFailToken: value) - ifFalse: - [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! Item was added: + ----- Method: ContextPart>>isPrimFailToken: (in category 'private') ----- + isPrimFailToken: anObject + ^(self objectClass: anObject) == Array + and: [anObject size = 2 + and: [anObject first == PrimitiveFailToken]]! Item was added: + ----- Method: ContextPart>>send:to:with:lookupIn: (in category 'controlling') ----- + send: selector to: rcvr with: arguments lookupIn: lookupClass + "Simulate the action of sending a message with selector and arguments + to rcvr. The argument, lookupClass, is the class in which to lookup the + message. This is the receiver's class for normal messages, but for super + messages it will be some specific class related to the source method." + + | meth primIndex val ctxt | + (meth := lookupClass lookupSelector: selector) ifNil: + [^self send: #doesNotUnderstand: + to: rcvr + with: {Message selector: selector arguments: arguments} + lookupIn: lookupClass]. + (primIndex := meth primitive) > 0 ifTrue: + [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments. + (self isPrimFailToken: val) ifFalse: + [^val]]. + (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue: + [^self error: 'Simulated message ', arguments first selector, ' not understood']. + ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments. + primIndex > 0 ifTrue: + [ctxt failPrimitiveWith: val]. + ^ctxt! Item was changed: ----- Method: ContextPart>>send:to:with:super: (in category 'controlling') ----- + send: selector to: rcvr with: arguments super: superFlag + "Simulate the action of sending a message with selector arguments + to rcvr. The argument, superFlag, tells whether the receiver of the + message was specified with 'super' in the source method." - send: selector to: rcvr with: args super: superFlag - "Simulate the action of sending a message with selector, selector, and - arguments, args, to receiver. The argument, superFlag, tells whether the - receiver of the message was specified with 'super' in the source method." + ^self send: selector + to: rcvr + with: arguments + lookupIn: (superFlag + ifTrue: [self method methodClassAssociation value superclass] + ifFalse: [self objectClass: rcvr])! - | class meth val ctxt | - class := superFlag - ifTrue: [self method methodClassAssociation value superclass] - ifFalse: [self objectClass: rcvr]. - meth := class lookupSelector: selector. - meth == nil ifTrue: - [^self - send: #doesNotUnderstand: - to: rcvr - with: (Array with: (Message selector: selector arguments: args)) - super: superFlag]. - val := self tryPrimitiveFor: meth receiver: rcvr args: args. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken]]) ifFalse: - [^val]. - (selector == #doesNotUnderstand: - and: [class == ProtoObject]) ifTrue: - [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood']. - ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken - and: [val last notNil - and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue: - [ctxt at: ctxt stackPtr put: val last]. - ^ctxt! Item was changed: ----- Method: ContextPart>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') ----- tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments + "Invoke the named primitive for aCompiledMethod, answering its result, or, + if the primiitve fails, answering the error code." - | selector theMethod spec receiverClass | ec ifNotNil: ["If ec is an integer other than -1 there was a problem with primitive 218, not with the external primitive itself. -1 indicates a generic failure (where ec should be nil) but ec = nil means primitive 218 is not implemented. So interpret -1 to mean the external primitive failed with a nil error code." ec isInteger ifTrue: [ec = -1 ifTrue: [ec := nil] + ifFalse: [self primitiveFailed]]]. + ^self class primitiveFailTokenFor: ec! - ifFalse: [self primitiveFailed]]. - ^{PrimitiveFailToken. ec}]. - "Assume a nil error code implies the primitive is not implemented and fall back on the old code." - "Hack. Attempt to execute the named primitive from the given compiled method" - arguments size > 8 ifTrue: - [^{PrimitiveFailToken. nil}]. - selector := #( - tryNamedPrimitive - tryNamedPrimitive: - tryNamedPrimitive:with: - tryNamedPrimitive:with:with: - tryNamedPrimitive:with:with:with: - tryNamedPrimitive:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. - receiverClass := self objectClass: aReceiver. - theMethod := receiverClass lookupSelector: selector. - theMethod == nil ifTrue: - [^{PrimitiveFailToken. nil}]. - spec := theMethod literalAt: 1. - spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. - Smalltalk unbindExternalPrimitives. - ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass! Item was added: + ----- Method: InstructionClient>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: pimIndex + "V3PlusClosures: 139 10001011 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + NewsqueakV4: 249 11111001 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + ( jjjjjjj * 256) + m=1 means inlined primitive, no hard return after execution."! Item was added: + ----- Method: InstructionPrinter>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: index + "Print the callPrimitive." + + self print: 'callPrimtive: ' , index printString! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self error: 'unusedBytecode']. byte3 := method at: pc. pc := pc + 1. + offset = 11 ifTrue: [^client callPrimitive: byte2 + (byte3 bitShift: 8)]. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: Integer class>>initialize (in category 'class initialization') ----- + initialize + "Integer initialize" + self initializeLowBitPerByteTable! - initialize "Integer initialize" - "Ensure we have the right compact class index" - - "LPI has been a compact class forever - just ensure basic correctness" - (LargePositiveInteger indexIfCompact = 5) ifFalse:[ - (Smalltalk compactClassesArray at: 5) - ifNil:[LargePositiveInteger becomeCompactSimplyAt: 5] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - "Cog requires LNI to be compact at 4 (replacing PseudoContext)" - (LargeNegativeInteger indexIfCompact = 4) ifFalse:[ - "PseudoContext will likely get removed at some point so write this test - without introducing a hard dependency" - (Smalltalk compactClassesArray at: 4) name == #PseudoContext - ifTrue:[Smalltalk compactClassesArray at: 4 put: nil]. - (Smalltalk compactClassesArray at: 4) - ifNil:[LargeNegativeInteger becomeCompactSimplyAt: 4] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - self initializeLowBitPerByteTable - ! Item was added: + ----- Method: MethodContext class>>allInstances (in category 'enumerating') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst. + Only count until thisContext since this context has been created only to + compute the existing instances." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + insts nextPut: inst. + inst := next]. + ^insts contents! Item was changed: ----- Method: MethodContext class>>allInstancesDo: (in category 'private') ----- allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst. + Only count until thisContext since evaluation of aBlock will create new contexts." - "Only count until thisContext since evaluation of aBlock will create new contexts." - | inst next | inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == thisContext] whileFalse:[ - next := inst nextInstance. - aBlock value: inst. - inst := next] - ! Item was added: + ----- Method: MethodContext>>failPrimitiveWith: (in category 'system simulation') ----- + failPrimitiveWith: maybePrimFailToken + "The receiver is a freshly-created context on a primitive method. Skip the callPrimitive: + bytecode and store the primitive fail code if there is one and the method consumes it." + self skipCallPrimitive. + ((self isPrimFailToken: maybePrimFailToken) + and: [method encoderClass isStoreAt: pc in: method]) ifTrue: + [self at: stackp put: maybePrimFailToken last]! Item was changed: ----- Method: ProtoObject>>scaledIdentityHash (in category 'comparing') ----- scaledIdentityHash "For identityHash values returned by primitive 75, answer + such values times 2^8. Otherwise, match the existing + identityHash implementation" - such values times 2^18. Otherwise, match the existing - identityHash implementation" + ^self identityHash * 256 "bitShift: 8"! - ^self identityHash * 262144 "bitShift: 18"! Item was changed: ==== ERROR === Error: Unrecognized class type 9 October 2014 5:51:15.56 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(SmallInteger) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Thu Oct 9 17:53:09 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:53:12 2014 Subject: [squeak-dev] The Trunk: System.spur-nice.674.mcz Message-ID: Eliot Miranda uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System.spur-nice.674.mcz ==================== Summary ==================== Name: System.spur-nice.674 Author: eem Time: 9 October 2014, 10:44:07.052 am UUID: 7c8b8ca7-efad-4808-a542-a57babc79b82 Ancestors: System-nice.674, System.spur-nice.673 System-nice.674 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Remove SmartRefStream class>>streamedRepresentationOf: which is essentially the same as super. The sole difference is that it tries to close the RWBinaryOrTextStream, but this is a no-op... =============== Diff against System-nice.674 =============== Item was changed: ----- Method: SmalltalkImage>>compactClassesArray (in category 'special objects') ----- compactClassesArray "Smalltalk compactClassesArray" + "Backward-compatibility support. Spur does not have compact classes." + ^{}! - "Return the array of 31 classes whose instances may be - represented compactly" - ^ self specialObjectsArray at: 29! Item was added: + ----- Method: SmalltalkImage>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Essential. Fail if no memory is available." + + (numBytes isInteger and: [numBytes > 0]) ifTrue: + [OutOfMemory signal]. + ^self primitiveFailed! Item was added: + ----- Method: SmalltalkImage>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was changed: ----- Method: SmalltalkImage>>recreateSpecialObjectsArray (in category 'special objects') ----- recreateSpecialObjectsArray "Smalltalk recreateSpecialObjectsArray" "To external package developers: **** DO NOT OVERRIDE THIS METHOD. ***** If you are writing a plugin and need additional special object(s) for your own use, use addGCRoot() function and use own, separate special objects registry " "The Special Objects Array is an array of objects used by the Squeak virtual machine. Its contents are critical and accesses to it by the VM are unchecked, so don't even think of playing here unless you know what you are doing." | newArray | + newArray := Array new: 60. - newArray := Array new: 58. "Nil false and true get used throughout the interpreter" newArray at: 1 put: nil. newArray at: 2 put: false. newArray at: 3 put: true. "This association holds the active process (a ProcessScheduler)" newArray at: 4 put: (self specialObjectsArray at: 4) "(self bindingOf: #Processor) but it answers an Alias". "Numerous classes below used for type checking and instantiation" newArray at: 5 put: Bitmap. newArray at: 6 put: SmallInteger. newArray at: 7 put: ByteString. newArray at: 8 put: Array. newArray at: 9 put: Smalltalk. newArray at: 10 put: Float. + newArray at: 11 put: (self globals at: #MethodContext ifAbsent: [self globals at: #Context]). + newArray at: 12 put: nil. "was BlockContext." - newArray at: 11 put: MethodContext. - newArray at: 12 put: BlockContext. newArray at: 13 put: Point. newArray at: 14 put: LargePositiveInteger. newArray at: 15 put: Display. newArray at: 16 put: Message. newArray at: 17 put: CompiledMethod. + newArray at: 18 put: ((self specialObjectsArray at: 18) ifNil: [Semaphore new]). "low space Semaphore" - newArray at: 18 put: (self specialObjectsArray at: 18). - "(low space Semaphore)" newArray at: 19 put: Semaphore. newArray at: 20 put: Character. newArray at: 21 put: #doesNotUnderstand:. newArray at: 22 put: #cannotReturn:. newArray at: 23 put: nil. "This is the process signalling low space." "An array of the 32 selectors that are compiled as special bytecodes, paired alternately with the number of arguments each takes." newArray at: 24 put: #( #+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0 ). "An array of the 255 Characters in ascii order. + Cog inlines table into machine code at: prim so do not regenerate it. + This is nil in Spur, which has immediate Characters." - Cog inlines table into machine code at: prim so do not regenerate it." newArray at: 25 put: (self specialObjectsArray at: 25). newArray at: 26 put: #mustBeBoolean. newArray at: 27 put: ByteArray. newArray at: 28 put: Process. + "An array of up to 31 classes whose instances will have compact headers; an empty array in Spur" - "An array of up to 31 classes whose instances will have compact headers" newArray at: 29 put: self compactClassesArray. + newArray at: 30 put: ((self specialObjectsArray at: 30) ifNil: [Semaphore new]). "delay Semaphore" + newArray at: 31 put: ((self specialObjectsArray at: 31) ifNil: [Semaphore new]). "user interrupt Semaphore" - newArray at: 30 put: (self specialObjectsArray at: 30). "(delay Semaphore)" - newArray at: 31 put: (self specialObjectsArray at: 31). "(user interrupt Semaphore)" "Entries 32 - 34 unreferenced. Previously these contained prototype instances to be copied for fast initialization" + newArray at: 32 put: nil. "was the prototype Float" + newArray at: 33 put: nil. "was the prototype 4-byte LargePositiveInteger" + newArray at: 34 put: nil. "was the prototype Point" - newArray at: 32 put: nil. "was (Float new: 2)" - newArray at: 33 put: nil. "was (LargePositiveInteger new: 4)" - newArray at: 34 put: nil. "was Point new" newArray at: 35 put: #cannotInterpret:. + newArray at: 36 put: nil. "was the prototype MethodContext" - "Note: This must be fixed once we start using context prototypes (yeah, right)" - "(MethodContext new: CompiledMethod fullFrameSize)." - newArray at: 36 put: (self specialObjectsArray at: 36). "Is the prototype MethodContext (unused by the VM)" newArray at: 37 put: BlockClosure. + newArray at: 38 put: nil. "was the prototype BlockContext" - "(BlockContext new: CompiledMethod fullFrameSize)." - newArray at: 38 put: (self specialObjectsArray at: 38). "Is the prototype BlockContext (unused by the VM)" "array of objects referred to by external code" + newArray at: 39 put: (self specialObjectsArray at: 39). "external semaphores" - newArray at: 39 put: (self specialObjectsArray at: 39). "preserve external semaphores" newArray at: 40 put: nil. "Reserved for Mutex in Cog VMs" + newArray at: 41 put: ((self specialObjectsArray at: 41) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT" + newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). "finalization Semaphore" - newArray at: 41 put: nil. "Reserved for a LinkedList instance for overlapped calls in CogMT" - "finalization Semaphore" - newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). newArray at: 43 put: LargeNegativeInteger. "External objects for callout. Note: Written so that one can actually completely remove the FFI." newArray at: 44 put: (self at: #ExternalAddress ifAbsent: []). newArray at: 45 put: (self at: #ExternalStructure ifAbsent: []). newArray at: 46 put: (self at: #ExternalData ifAbsent: []). newArray at: 47 put: (self at: #ExternalFunction ifAbsent: []). newArray at: 48 put: (self at: #ExternalLibrary ifAbsent: []). newArray at: 49 put: #aboutToReturn:through:. newArray at: 50 put: #run:with:in:. "51 reserved for immutability message" + newArray at: 51 put: #attemptToAssign:withIndex:. - "newArray at: 51 put: #attemptToAssign:withIndex:." - newArray at: 51 put: (self specialObjectsArray at: 51 ifAbsent: []). newArray at: 52 put: #(nil "nil => generic error" #'bad receiver' #'bad argument' #'bad index' #'bad number of arguments' #'inappropriate operation' #'unsupported operation' #'no modification' #'insufficient object memory' #'insufficient C memory' #'not found' #'bad method' #'internal error in named primitive machinery' #'object may move' #'resource limit exceeded' + #'object is pinned' #'primitive write beyond end of object'). - #'object is pinned'). "53 to 55 are for Alien" newArray at: 53 put: (self at: #Alien ifAbsent: []). + newArray at: 54 put: #invokeCallbackContext:. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." - newArray at: 54 put: #invokeCallbackContext::. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." newArray at: 55 put: (self at: #UnsafeAlien ifAbsent: []). + "Used to be WeakFinalizationList for WeakFinalizationList hasNewFinalization, obsoleted by ephemeron support." + newArray at: 56 put: nil. - "Weak reference finalization" - newArray at: 56 put: (self at: #WeakFinalizationList ifAbsent: []). "reserved for foreign callback process" newArray at: 57 put: (self specialObjectsArray at: 57 ifAbsent: []). newArray at: 58 put: #unusedBytecode. + "59 reserved for Sista counter tripped message" + newArray at: 59 put: #conditionalBranchCounterTrippedOn:. + "60 reserved for Sista class trap message" + newArray at: 60 put: #classTrapFor:. "Now replace the interpreter's reference in one atomic operation" + self specialObjectsArray becomeForward: newArray! - self specialObjectsArray becomeForward: newArray - ! Item was changed: ----- Method: SmalltalkImage>>setGCParameters (in category 'snapshot and quit') ----- setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" - "Adjust the VM's default GC parameters to avoid premature tenuring." + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! - self vmParameterAt: 5 put: 4000. "do an incremental GC after this many allocations" - self vmParameterAt: 6 put: 2000. "tenure when more than this many objects survive the GC" - ! Item was changed: ----- Method: SpaceTally>>spaceForInstancesOf: (in category 'instance size') ----- spaceForInstancesOf: aClass + "Answer a pair of the number of bytes consumed by all instances of the + given class, including their object headers, and the number of instances." - "Answer the number of bytes consumed by all instances of the given class, including their object headers and the number of instances." + | instances total | + instances := aClass allInstances. + instances isEmpty ifTrue: [^#(0 0)]. - | smallHeaderSize instVarBytes isVariable bytesPerElement total lastInstance instance instanceCount | - instance := aClass someInstance ifNil: [ ^#(0 0) ]. - smallHeaderSize := aClass isCompact ifTrue: [ 4 ] ifFalse: [ 8 ]. - instVarBytes := aClass instSize * 4. - isVariable := aClass isVariable. - bytesPerElement := isVariable - ifFalse: [ 0 ] - ifTrue: [ aClass isBytes ifTrue: [ 1 ] ifFalse: [ 4 ] ]. total := 0. + aClass isVariable + ifTrue: + [instances do: + [:i| total := total + (aClass byteSizeOfInstanceOfSize: i basicSize)]] + ifFalse: + [total := instances size * aClass byteSizeOfInstance]. + ^{ total. instances size }! - instanceCount := 0. - "A modified version of #allInstancesDo: is inlined here. It avoids an infinite loop when another process is creating new instances of aClass." - self flag: #allInstancesDo:. - lastInstance := - aClass == CompiledMethod "CompiledMethod has special format, see its class comment" - ifTrue: [aClass new] - ifFalse: [aClass basicNew]. - [ instance == lastInstance ] whileFalse: [ - | contentBytes headerBytes | - contentBytes := instVarBytes + (isVariable - ifFalse: [ 0 ] - ifTrue: [ instance basicSize * bytesPerElement ]). - headerBytes := contentBytes > 255 - ifTrue: [ 12 ] - ifFalse: [ smallHeaderSize ]. - total := total + headerBytes + (contentBytes roundUpTo: 4). - instanceCount := instanceCount + 1. - instance := instance nextInstance ]. - ^{ total. instanceCount }! Item was added: + ----- Method: SystemDictionary>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Fail if no memory is available. Essential." + + ^(numBytes isInteger and: [numBytes > 0]) + ifTrue: [OutOfMemory signal] + ifFalse: [self primitiveFailed]! Item was added: + ----- Method: SystemDictionary>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was added: + ----- Method: SystemDictionary>>setGCParameters (in category 'snapshot and quit') ----- + setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" + + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! Item was added: + ----- Method: SystemNavigation>>allObjects (in category 'query') ----- + allObjects + "Answer an Array of all objects in the system. Fail if + there isn't enough memory to instantiate the result." + + ^self primitiveFailed! Item was changed: ----- Method: SystemNavigation>>allObjectsDo: (in category 'query') ----- allObjectsDo: aBlock + "Evaluate the argument, aBlock, for each object in the system, excluding immediates + such as SmallInteger and Character." + self allObjectsOrNil + ifNotNil: [:allObjects| allObjects do: aBlock] + ifNil: + ["Fall back on the old single object primitive code. With closures, this needs + to use an end marker (lastObject) since activation of the block will create + new contexts and cause an infinite loop. The lastObject must be created + before calling someObject, so that the VM can settle the enumeration (e.g. + by flushing new space) as a side effect of someObject" + | object lastObject | + lastObject := Object new. + object := self someObject. + [lastObject == object or: [0 == object]] whileFalse: + [aBlock value: object. + object := object nextObject]]! - "Evaluate the argument, aBlock, for each object in the system - excluding SmallIntegers. With closures, this needs to use an end - marker (lastObject) since activation of the block will create new - contexts and cause an infinite loop." - | object lastObject | - object := self someObject. - lastObject := Object new. - [lastObject == object or: [0 == object]] - whileFalse: [aBlock value: object. - object := object nextObject]! Item was added: + ----- Method: SystemNavigation>>allObjectsOrNil (in category 'query') ----- + allObjectsOrNil + "Answer an Array of all objects in the system. Fail if there isn't + enough memory to instantiate the result and answer nil." + + ^nil! From commits at source.squeak.org Thu Oct 9 17:53:20 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 17:53:22 2014 Subject: [squeak-dev] The Trunk: System.spur-nice.675.mcz Message-ID: Eliot Miranda uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System.spur-nice.675.mcz ==================== Summary ==================== Name: System.spur-nice.675 Author: eem Time: 9 October 2014, 10:44:08.836 am UUID: bbe651c0-9d1f-458b-ba72-69bfbdc22bcf Ancestors: System-nice.675, System.spur-nice.674 System-nice.675 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Remove a bit of ascii/binary dance. This is possible - in CodeLoader because ByteArray now understands unzipped - in DataStream>>readString, because nextString will turn stream to binary right after we asked for ascii... - in SmartRefStream>>appendClassDefns because we can forward the job to an asciiStream. Beware, this last part was not WideString friendly, and still isn't really. We should better use something like UTF8 but it's not a local change - we'll see later... =============== Diff against System-nice.675 =============== Item was changed: ----- Method: SmalltalkImage>>compactClassesArray (in category 'special objects') ----- compactClassesArray "Smalltalk compactClassesArray" + "Backward-compatibility support. Spur does not have compact classes." + ^{}! - "Return the array of 31 classes whose instances may be - represented compactly" - ^ self specialObjectsArray at: 29! Item was added: + ----- Method: SmalltalkImage>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Essential. Fail if no memory is available." + + (numBytes isInteger and: [numBytes > 0]) ifTrue: + [OutOfMemory signal]. + ^self primitiveFailed! Item was added: + ----- Method: SmalltalkImage>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was changed: ----- Method: SmalltalkImage>>recreateSpecialObjectsArray (in category 'special objects') ----- recreateSpecialObjectsArray "Smalltalk recreateSpecialObjectsArray" "To external package developers: **** DO NOT OVERRIDE THIS METHOD. ***** If you are writing a plugin and need additional special object(s) for your own use, use addGCRoot() function and use own, separate special objects registry " "The Special Objects Array is an array of objects used by the Squeak virtual machine. Its contents are critical and accesses to it by the VM are unchecked, so don't even think of playing here unless you know what you are doing." | newArray | + newArray := Array new: 60. - newArray := Array new: 58. "Nil false and true get used throughout the interpreter" newArray at: 1 put: nil. newArray at: 2 put: false. newArray at: 3 put: true. "This association holds the active process (a ProcessScheduler)" newArray at: 4 put: (self specialObjectsArray at: 4) "(self bindingOf: #Processor) but it answers an Alias". "Numerous classes below used for type checking and instantiation" newArray at: 5 put: Bitmap. newArray at: 6 put: SmallInteger. newArray at: 7 put: ByteString. newArray at: 8 put: Array. newArray at: 9 put: Smalltalk. newArray at: 10 put: Float. + newArray at: 11 put: (self globals at: #MethodContext ifAbsent: [self globals at: #Context]). + newArray at: 12 put: nil. "was BlockContext." - newArray at: 11 put: MethodContext. - newArray at: 12 put: BlockContext. newArray at: 13 put: Point. newArray at: 14 put: LargePositiveInteger. newArray at: 15 put: Display. newArray at: 16 put: Message. newArray at: 17 put: CompiledMethod. + newArray at: 18 put: ((self specialObjectsArray at: 18) ifNil: [Semaphore new]). "low space Semaphore" - newArray at: 18 put: (self specialObjectsArray at: 18). - "(low space Semaphore)" newArray at: 19 put: Semaphore. newArray at: 20 put: Character. newArray at: 21 put: #doesNotUnderstand:. newArray at: 22 put: #cannotReturn:. newArray at: 23 put: nil. "This is the process signalling low space." "An array of the 32 selectors that are compiled as special bytecodes, paired alternately with the number of arguments each takes." newArray at: 24 put: #( #+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0 ). "An array of the 255 Characters in ascii order. + Cog inlines table into machine code at: prim so do not regenerate it. + This is nil in Spur, which has immediate Characters." - Cog inlines table into machine code at: prim so do not regenerate it." newArray at: 25 put: (self specialObjectsArray at: 25). newArray at: 26 put: #mustBeBoolean. newArray at: 27 put: ByteArray. newArray at: 28 put: Process. + "An array of up to 31 classes whose instances will have compact headers; an empty array in Spur" - "An array of up to 31 classes whose instances will have compact headers" newArray at: 29 put: self compactClassesArray. + newArray at: 30 put: ((self specialObjectsArray at: 30) ifNil: [Semaphore new]). "delay Semaphore" + newArray at: 31 put: ((self specialObjectsArray at: 31) ifNil: [Semaphore new]). "user interrupt Semaphore" - newArray at: 30 put: (self specialObjectsArray at: 30). "(delay Semaphore)" - newArray at: 31 put: (self specialObjectsArray at: 31). "(user interrupt Semaphore)" "Entries 32 - 34 unreferenced. Previously these contained prototype instances to be copied for fast initialization" + newArray at: 32 put: nil. "was the prototype Float" + newArray at: 33 put: nil. "was the prototype 4-byte LargePositiveInteger" + newArray at: 34 put: nil. "was the prototype Point" - newArray at: 32 put: nil. "was (Float new: 2)" - newArray at: 33 put: nil. "was (LargePositiveInteger new: 4)" - newArray at: 34 put: nil. "was Point new" newArray at: 35 put: #cannotInterpret:. + newArray at: 36 put: nil. "was the prototype MethodContext" - "Note: This must be fixed once we start using context prototypes (yeah, right)" - "(MethodContext new: CompiledMethod fullFrameSize)." - newArray at: 36 put: (self specialObjectsArray at: 36). "Is the prototype MethodContext (unused by the VM)" newArray at: 37 put: BlockClosure. + newArray at: 38 put: nil. "was the prototype BlockContext" - "(BlockContext new: CompiledMethod fullFrameSize)." - newArray at: 38 put: (self specialObjectsArray at: 38). "Is the prototype BlockContext (unused by the VM)" "array of objects referred to by external code" + newArray at: 39 put: (self specialObjectsArray at: 39). "external semaphores" - newArray at: 39 put: (self specialObjectsArray at: 39). "preserve external semaphores" newArray at: 40 put: nil. "Reserved for Mutex in Cog VMs" + newArray at: 41 put: ((self specialObjectsArray at: 41) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT" + newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). "finalization Semaphore" - newArray at: 41 put: nil. "Reserved for a LinkedList instance for overlapped calls in CogMT" - "finalization Semaphore" - newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). newArray at: 43 put: LargeNegativeInteger. "External objects for callout. Note: Written so that one can actually completely remove the FFI." newArray at: 44 put: (self at: #ExternalAddress ifAbsent: []). newArray at: 45 put: (self at: #ExternalStructure ifAbsent: []). newArray at: 46 put: (self at: #ExternalData ifAbsent: []). newArray at: 47 put: (self at: #ExternalFunction ifAbsent: []). newArray at: 48 put: (self at: #ExternalLibrary ifAbsent: []). newArray at: 49 put: #aboutToReturn:through:. newArray at: 50 put: #run:with:in:. "51 reserved for immutability message" + newArray at: 51 put: #attemptToAssign:withIndex:. - "newArray at: 51 put: #attemptToAssign:withIndex:." - newArray at: 51 put: (self specialObjectsArray at: 51 ifAbsent: []). newArray at: 52 put: #(nil "nil => generic error" #'bad receiver' #'bad argument' #'bad index' #'bad number of arguments' #'inappropriate operation' #'unsupported operation' #'no modification' #'insufficient object memory' #'insufficient C memory' #'not found' #'bad method' #'internal error in named primitive machinery' #'object may move' #'resource limit exceeded' + #'object is pinned' #'primitive write beyond end of object'). - #'object is pinned'). "53 to 55 are for Alien" newArray at: 53 put: (self at: #Alien ifAbsent: []). + newArray at: 54 put: #invokeCallbackContext:. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." - newArray at: 54 put: #invokeCallbackContext::. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." newArray at: 55 put: (self at: #UnsafeAlien ifAbsent: []). + "Used to be WeakFinalizationList for WeakFinalizationList hasNewFinalization, obsoleted by ephemeron support." + newArray at: 56 put: nil. - "Weak reference finalization" - newArray at: 56 put: (self at: #WeakFinalizationList ifAbsent: []). "reserved for foreign callback process" newArray at: 57 put: (self specialObjectsArray at: 57 ifAbsent: []). newArray at: 58 put: #unusedBytecode. + "59 reserved for Sista counter tripped message" + newArray at: 59 put: #conditionalBranchCounterTrippedOn:. + "60 reserved for Sista class trap message" + newArray at: 60 put: #classTrapFor:. "Now replace the interpreter's reference in one atomic operation" + self specialObjectsArray becomeForward: newArray! - self specialObjectsArray becomeForward: newArray - ! Item was changed: ----- Method: SmalltalkImage>>setGCParameters (in category 'snapshot and quit') ----- setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" - "Adjust the VM's default GC parameters to avoid premature tenuring." + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! - self vmParameterAt: 5 put: 4000. "do an incremental GC after this many allocations" - self vmParameterAt: 6 put: 2000. "tenure when more than this many objects survive the GC" - ! Item was changed: ----- Method: SpaceTally>>spaceForInstancesOf: (in category 'instance size') ----- spaceForInstancesOf: aClass + "Answer a pair of the number of bytes consumed by all instances of the + given class, including their object headers, and the number of instances." - "Answer the number of bytes consumed by all instances of the given class, including their object headers and the number of instances." + | instances total | + instances := aClass allInstances. + instances isEmpty ifTrue: [^#(0 0)]. - | smallHeaderSize instVarBytes isVariable bytesPerElement total lastInstance instance instanceCount | - instance := aClass someInstance ifNil: [ ^#(0 0) ]. - smallHeaderSize := aClass isCompact ifTrue: [ 4 ] ifFalse: [ 8 ]. - instVarBytes := aClass instSize * 4. - isVariable := aClass isVariable. - bytesPerElement := isVariable - ifFalse: [ 0 ] - ifTrue: [ aClass isBytes ifTrue: [ 1 ] ifFalse: [ 4 ] ]. total := 0. + aClass isVariable + ifTrue: + [instances do: + [:i| total := total + (aClass byteSizeOfInstanceOfSize: i basicSize)]] + ifFalse: + [total := instances size * aClass byteSizeOfInstance]. + ^{ total. instances size }! - instanceCount := 0. - "A modified version of #allInstancesDo: is inlined here. It avoids an infinite loop when another process is creating new instances of aClass." - self flag: #allInstancesDo:. - lastInstance := - aClass == CompiledMethod "CompiledMethod has special format, see its class comment" - ifTrue: [aClass new] - ifFalse: [aClass basicNew]. - [ instance == lastInstance ] whileFalse: [ - | contentBytes headerBytes | - contentBytes := instVarBytes + (isVariable - ifFalse: [ 0 ] - ifTrue: [ instance basicSize * bytesPerElement ]). - headerBytes := contentBytes > 255 - ifTrue: [ 12 ] - ifFalse: [ smallHeaderSize ]. - total := total + headerBytes + (contentBytes roundUpTo: 4). - instanceCount := instanceCount + 1. - instance := instance nextInstance ]. - ^{ total. instanceCount }! Item was added: + ----- Method: SystemDictionary>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Fail if no memory is available. Essential." + + ^(numBytes isInteger and: [numBytes > 0]) + ifTrue: [OutOfMemory signal] + ifFalse: [self primitiveFailed]! Item was added: + ----- Method: SystemDictionary>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was added: + ----- Method: SystemDictionary>>setGCParameters (in category 'snapshot and quit') ----- + setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" + + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! Item was added: + ----- Method: SystemNavigation>>allObjects (in category 'query') ----- + allObjects + "Answer an Array of all objects in the system. Fail if + there isn't enough memory to instantiate the result." + + ^self primitiveFailed! Item was changed: ----- Method: SystemNavigation>>allObjectsDo: (in category 'query') ----- allObjectsDo: aBlock + "Evaluate the argument, aBlock, for each object in the system, excluding immediates + such as SmallInteger and Character." + self allObjectsOrNil + ifNotNil: [:allObjects| allObjects do: aBlock] + ifNil: + ["Fall back on the old single object primitive code. With closures, this needs + to use an end marker (lastObject) since activation of the block will create + new contexts and cause an infinite loop. The lastObject must be created + before calling someObject, so that the VM can settle the enumeration (e.g. + by flushing new space) as a side effect of someObject" + | object lastObject | + lastObject := Object new. + object := self someObject. + [lastObject == object or: [0 == object]] whileFalse: + [aBlock value: object. + object := object nextObject]]! - "Evaluate the argument, aBlock, for each object in the system - excluding SmallIntegers. With closures, this needs to use an end - marker (lastObject) since activation of the block will create new - contexts and cause an infinite loop." - | object lastObject | - object := self someObject. - lastObject := Object new. - [lastObject == object or: [0 == object]] - whileFalse: [aBlock value: object. - object := object nextObject]! Item was added: + ----- Method: SystemNavigation>>allObjectsOrNil (in category 'query') ----- + allObjectsOrNil + "Answer an Array of all objects in the system. Fail if there isn't + enough memory to instantiate the result and answer nil." + + ^nil! From craig at netjam.org Thu Oct 9 19:20:40 2014 From: craig at netjam.org (Craig Latta) Date: Thu Oct 9 19:20:45 2014 Subject: [squeak-dev] re: What is the contract of SocketStream>>#next:? In-Reply-To: References: Message-ID: Chris> I feel I should be able to write: Chris> Chris> header := mySocketStream next: 4 Chris> Chris> and not have to check the length of header before I access it. Craig> Yeah, Squeak socket support is broken here (and a lot of other Craig> places), I'd say. Chris> That might be overstating it. I've only ever seen the issue Chris> under very heavy load... Well, we disagree. -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From asqueaker at gmail.com Thu Oct 9 20:03:44 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 9 20:03:47 2014 Subject: [squeak-dev] re: What is the contract of SocketStream>>#next:? In-Reply-To: References: Message-ID: On Thu, Oct 9, 2014 at 2:20 PM, Craig Latta wrote: > > Chris> I feel I should be able to write: > Chris> > Chris> header := mySocketStream next: 4 > Chris> > Chris> and not have to check the length of header before I access it. > > Craig> Yeah, Squeak socket support is broken here (and a lot of other > Craig> places), I'd say. > > Chris> That might be overstating it. I've only ever seen the issue > Chris> under very heavy load... > > Well, we disagree. Maybe not, it might help if you elaborated some of the broken places, I'm probably simply unaware of them. My apps make very heavy use of Squeak's Socket with no problems, but last month I upgraded Magma to use the SocketStream wrapper and only then did I notice this issue perhaps 2 or 3 times in the last month, and each time when a server was processing thousands of requests per minute over TCP sockets. From asqueaker at gmail.com Thu Oct 9 20:05:56 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 9 20:06:01 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.584.mcz In-Reply-To: <5436c9f4.e102980a.2151.235eSMTPIN_ADDED_MISSING@mx.google.com> References: <5436c9f4.e102980a.2151.235eSMTPIN_ADDED_MISSING@mx.google.com> Message-ID: "==== ERROR === Error: Unrecognized class type" is a little disconcerting.. On Thu, Oct 9, 2014 at 12:44 PM, wrote: > Eliot Miranda uploaded a new version of Collections to project The Trunk: > http://source.squeak.org/trunk/Collections.spur-ul.584.mcz > > ==================== Summary ==================== > > Name: Collections.spur-ul.584 > Author: eem > Time: 9 October 2014, 10:43:11.427 am > UUID: 73af4851-d240-41c0-89bd-6360f25f91d3 > Ancestors: Collections-ul.584, Collections.spur-nice.583 > > Collections-ul.584 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 > > Character changes: > - use the value instance variable instead of #asciiValue where possible > - implemented #<= and #>= > > =============== Diff against Collections-ul.584 =============== > > Item was changed: > ==== ERROR === > > Error: Unrecognized class type > > 9 October 2014 5:46:13.493 pm > > VM: unix - a SmalltalkImage > Image: Squeak3.11alpha [latest update: #8824] > > SecurityManager state: > Restricted: false > FileAccess: true > SocketAccess: true > Working Dir /home/squeaksource > Trusted Dir /home/squeaksource/secure > Untrusted Dir /home/squeaksource/My Squeak > > MCClassDefinition(Object)>>error: > Receiver: a MCClassDefinition(Character) > Arguments and temporary variables: > aString: 'Unrecognized class type' > Receiver's instance variables: > name: #Character > superclassName: #Magnitude > variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... > category: #'Collections-Strings' > type: #immediate > comment: 'I represent a character by storing its associated Unicode as an unsig...etc... > commentStamp: 'eem 8/12/2014 14:53' > traitComposition: nil > classTraitComposition: nil > > MCClassDefinition>>kindOfSubclass > Receiver: a MCClassDefinition(Character) > Arguments and temporary variables: > > Receiver's instance variables: > name: #Character > superclassName: #Magnitude > variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... > category: #'Collections-Strings' > type: #immediate > comment: 'I represent a character by storing its associated Unicode as an unsig...etc... > commentStamp: 'eem 8/12/2014 14:53' > traitComposition: nil > classTraitComposition: nil > > MCClassDefinition>>printDefinitionOn: > Receiver: a MCClassDefinition(Character) > Arguments and temporary variables: > stream: a WriteStream > Receiver's instance variables: > name: #Character > superclassName: #Magnitude > variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... > category: #'Collections-Strings' > type: #immediate > comment: 'I represent a character by storing its associated Unicode as an unsig...etc... > commentStamp: 'eem 8/12/2014 14:53' > traitComposition: nil > classTraitComposition: nil > > [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: > Receiver: a MCDiffyTextWriter > Arguments and temporary variables: > definition: a WriteStream > s: a MCClassDefinition(Character) > Receiver's instance variables: > stream: a WriteStream > initStream: nil > > > --- The full stack --- > MCClassDefinition(Object)>>error: > MCClassDefinition>>kindOfSubclass > MCClassDefinition>>printDefinitionOn: > [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > String class(SequenceableCollection class)>>new:streamContents: > String class(SequenceableCollection class)>>streamContents: > MCDiffyTextWriter(MCTextWriter)>>chunkContents: > MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: > MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: > MCClassDefinition>>accept: > [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: > String class(SequenceableCollection class)>>new:streamContents: > String class(SequenceableCollection class)>>streamContents: > MCDiffyTextWriter(MCTextWriter)>>visitInFork: > MCDiffyTextWriter>>writePatchFrom:to: > MCDiffyTextWriter>>writeModification: > [] in MCDiffyTextWriter>>writePatch: > SortedCollection(OrderedCollection)>>do: > MCDiffyTextWriter>>writePatch: > SSDiffyTextWriter>>writePatch: > [] in SSDiffyTextWriter>>writeVersion:for: > BlockClosure>>on:do: > SSDiffyTextWriter>>writeVersion:for: > [] in SSEMailSubscription>>versionAdded:to: > BlockClosure>>on:do: > SSEMailSubscription>>versionAdded:to: > [] in [] in SSProject>>versionAdded: > [] in BlockClosure>>newProcess > From eliot.miranda at gmail.com Thu Oct 9 20:18:08 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 9 20:18:11 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.584.mcz In-Reply-To: References: <5436c9f4.e102980a.2151.235eSMTPIN_ADDED_MISSING@mx.google.com> Message-ID: On Thu, Oct 9, 2014 at 1:05 PM, Chris Muller wrote: > "==== ERROR === > > Error: Unrecognized class type" > > is a little disconcerting.. > Try it in a Spur image. Try it in an updated trunk image. You'll find no crash, and you'll find the class type is appropriate. Here's the diff from an updated trunk v3 (non-spur) image: Magnitude *immediateSubclass:**subclass:* #Character instanceVariableNames: '*value*' classVariableNames: 'CharacterTable ClassificationTable DigitValues LetterBits LowercaseBit UppercaseBit' poolDictionaries: '' category: 'Collections-Strings' > > On Thu, Oct 9, 2014 at 12:44 PM, wrote: > > Eliot Miranda uploaded a new version of Collections to project The Trunk: > > http://source.squeak.org/trunk/Collections.spur-ul.584.mcz > > > > ==================== Summary ==================== > > > > Name: Collections.spur-ul.584 > > Author: eem > > Time: 9 October 2014, 10:43:11.427 am > > UUID: 73af4851-d240-41c0-89bd-6360f25f91d3 > > Ancestors: Collections-ul.584, Collections.spur-nice.583 > > > > Collections-ul.584 patched for Spur by > SpurBootstrapMonticelloPackagePatcher Cog-eem.209 > > > > Character changes: > > - use the value instance variable instead of #asciiValue where possible > > - implemented #<= and #>= > > > > =============== Diff against Collections-ul.584 =============== > > > > Item was changed: > > ==== ERROR === > > > > Error: Unrecognized class type > > > > 9 October 2014 5:46:13.493 pm > > > > VM: unix - a SmalltalkImage > > Image: Squeak3.11alpha [latest update: #8824] > > > > SecurityManager state: > > Restricted: false > > FileAccess: true > > SocketAccess: true > > Working Dir /home/squeaksource > > Trusted Dir /home/squeaksource/secure > > Untrusted Dir /home/squeaksource/My Squeak > > > > MCClassDefinition(Object)>>error: > > Receiver: a MCClassDefinition(Character) > > Arguments and temporary variables: > > aString: 'Unrecognized class type' > > Receiver's instance variables: > > name: #Character > > superclassName: #Magnitude > > variables: an OrderedCollection(a > MCClassVariableDefinition(CharacterTable) a M...etc... > > category: #'Collections-Strings' > > type: #immediate > > comment: 'I represent a character by storing its > associated Unicode as an unsig...etc... > > commentStamp: 'eem 8/12/2014 14:53' > > traitComposition: nil > > classTraitComposition: nil > > > > MCClassDefinition>>kindOfSubclass > > Receiver: a MCClassDefinition(Character) > > Arguments and temporary variables: > > > > Receiver's instance variables: > > name: #Character > > superclassName: #Magnitude > > variables: an OrderedCollection(a > MCClassVariableDefinition(CharacterTable) a M...etc... > > category: #'Collections-Strings' > > type: #immediate > > comment: 'I represent a character by storing its > associated Unicode as an unsig...etc... > > commentStamp: 'eem 8/12/2014 14:53' > > traitComposition: nil > > classTraitComposition: nil > > > > MCClassDefinition>>printDefinitionOn: > > Receiver: a MCClassDefinition(Character) > > Arguments and temporary variables: > > stream: a WriteStream > > Receiver's instance variables: > > name: #Character > > superclassName: #Magnitude > > variables: an OrderedCollection(a > MCClassVariableDefinition(CharacterTable) a M...etc... > > category: #'Collections-Strings' > > type: #immediate > > comment: 'I represent a character by storing its > associated Unicode as an unsig...etc... > > commentStamp: 'eem 8/12/2014 14:53' > > traitComposition: nil > > classTraitComposition: nil > > > > [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: > > Receiver: a MCDiffyTextWriter > > Arguments and temporary variables: > > definition: a WriteStream > > s: a MCClassDefinition(Character) > > Receiver's instance variables: > > stream: a WriteStream > > initStream: nil > > > > > > --- The full stack --- > > MCClassDefinition(Object)>>error: > > MCClassDefinition>>kindOfSubclass > > MCClassDefinition>>printDefinitionOn: > > [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: > > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > > String class(SequenceableCollection class)>>new:streamContents: > > String class(SequenceableCollection class)>>streamContents: > > MCDiffyTextWriter(MCTextWriter)>>chunkContents: > > MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: > > MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: > > MCClassDefinition>>accept: > > [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: > > String class(SequenceableCollection class)>>new:streamContents: > > String class(SequenceableCollection class)>>streamContents: > > MCDiffyTextWriter(MCTextWriter)>>visitInFork: > > MCDiffyTextWriter>>writePatchFrom:to: > > MCDiffyTextWriter>>writeModification: > > [] in MCDiffyTextWriter>>writePatch: > > SortedCollection(OrderedCollection)>>do: > > MCDiffyTextWriter>>writePatch: > > SSDiffyTextWriter>>writePatch: > > [] in SSDiffyTextWriter>>writeVersion:for: > > BlockClosure>>on:do: > > SSDiffyTextWriter>>writeVersion:for: > > [] in SSEMailSubscription>>versionAdded:to: > > BlockClosure>>on:do: > > SSEMailSubscription>>versionAdded:to: > > [] in [] in SSProject>>versionAdded: > > [] in BlockClosure>>newProcess > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141009/79ad0122/attachment.htm From commits at source.squeak.org Thu Oct 9 20:36:45 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 20:36:47 2014 Subject: [squeak-dev] The Trunk: Kernel-eem.879.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-eem.879.mcz ==================== Summary ==================== Name: Kernel-eem.879 Author: eem Time: 9 October 2014, 1:35:55.93 pm UUID: fbc8b106-b977-4d3b-8df9-4f4836beff40 Ancestors: Kernel-eem.878 Add a usable unusedBytecode hook that allows InstructionClients to define unusedBytecode and act appropriately. Remove the obsolete interpretExtension:in:for: =============== Diff against Kernel-eem.878 =============== Item was removed: - ----- Method: InstructionStream>>interpretExtension:in:for: (in category 'private') ----- - interpretExtension: offset in: method for: client - | type offset2 byte2 byte3 byte4 | - offset <= 6 ifTrue: - ["Extended op codes 128-134" - byte2 := method at: pc. pc := pc + 1. - offset <= 2 ifTrue: - ["128-130: extended pushes and pops" - type := byte2 // 64. - offset2 := byte2 \\ 64. - offset = 0 ifTrue: - [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. - type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. - type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. - type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. - offset = 1 ifTrue: - [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. - type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. - type = 2 ifTrue: [self error: 'illegalStore']. - type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. - offset = 2 ifTrue: - [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. - type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. - type = 2 ifTrue: [self error: 'illegalStore']. - type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. - "131-134: extended sends" - offset = 3 ifTrue: "Single extended send" - [^client send: (method literalAt: byte2 \\ 32 + 1) - super: false numArgs: byte2 // 32]. - offset = 4 ifTrue: "Double extended do-anything" - [byte3 := method at: pc. pc := pc + 1. - type := byte2 // 32. - type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) - super: false numArgs: byte2 \\ 32]. - type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) - super: true numArgs: byte2 \\ 32]. - type = 2 ifTrue: [^client pushReceiverVariable: byte3]. - type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. - type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. - type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. - type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. - type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. - offset = 5 ifTrue: "Single extended send to super" - [^client send: (method literalAt: byte2 \\ 32 + 1) - super: true numArgs: byte2 // 32]. - offset = 6 ifTrue: "Second extended send" - [^client send: (method literalAt: byte2 \\ 64 + 1) - super: false numArgs: byte2 // 64]]. - offset = 7 ifTrue: [^client doPop]. - offset = 8 ifTrue: [^client doDup]. - offset = 9 ifTrue: [^client pushActiveContext]. - byte2 := method at: pc. pc := pc + 1. - offset = 10 ifTrue: - [^byte2 < 128 - ifTrue: [client pushNewArrayOfSize: byte2] - ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self error: 'unusedBytecode']. - byte3 := method at: pc. pc := pc + 1. - offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. - offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. - offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. - "offset = 15" - byte4 := method at: pc. pc := pc + 1. - ^client - pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) - numArgs: (byte2 bitAnd: 16rF) - blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: InstructionStream>>interpretNextV3ClosuresInstructionFor: (in category 'decoding - private - v3 plus closures') ----- interpretNextV3ClosuresInstructionFor: client "Send to the argument, client, a message that specifies the type of the next instruction." | byte type offset method | method := self method. byte := method at: pc. type := byte // 16. offset := byte \\ 16. pc := pc+1. "We do an inline binary search on each of the possible 16 values of type." type < 8 ifTrue: [type < 4 ifTrue: [type < 2 ifTrue: [type = 0 ifTrue: [^ client pushReceiverVariable: offset]. ^ client pushTemporaryVariable: offset]. "type = 1" type = 2 ifTrue: [^ client pushConstant: (method literalAt: offset + 1)]. ^ client pushConstant: (method literalAt: offset + 17)]. "type = 3" type < 6 ifTrue: [type = 4 ifTrue: [^ client pushLiteralVariable: (method literalAt: offset + 1)]. ^ client pushLiteralVariable: (method literalAt: offset + 17)]."type = 5" type = 6 ifTrue: [offset < 8 ifTrue: [^ client popIntoReceiverVariable: offset]. ^ client popIntoTemporaryVariable: offset - 8]. "type = 7" offset = 0 ifTrue: [^ client pushReceiver]. offset < 8 ifTrue: [^ client pushConstant: (SpecialConstants at: offset)]. offset = 8 ifTrue: [^ client methodReturnReceiver]. offset < 12 ifTrue: [^ client methodReturnConstant: (SpecialConstants at: offset - 8)]. offset = 12 ifTrue: [^ client methodReturnTop]. offset = 13 ifTrue: [^ client blockReturnTop]. + ^ self unusedBytecode: client at: pc - 1]. "offset = 14 & offset = 15, 126 & 127" - offset > 13 ifTrue: [^ self error: 'unusedBytecode']]. type < 12 ifTrue: [type < 10 ifTrue: [type = 8 ifTrue: [^ self interpretV3ClosuresExtension: offset in: method for: client]. "type = 9 (short jumps)" offset < 8 ifTrue: [^ client jump: offset + 1]. ^ client jump: offset - 8 + 1 if: false]. type = 10 ifTrue: "(long jumps)" [byte := method at: pc. pc := pc + 1. offset < 8 ifTrue: [^ client jump: offset - 4 * 256 + byte]. ^ client jump: (offset bitAnd: 3) * 256 + byte if: offset < 12]. "type = 11; arithmetic special selector sends" ^ client send: (Smalltalk specialSelectorAt: offset + 1) super: false numArgs: (Smalltalk specialNargsAt: offset + 1)]. type = 12 ifTrue: "non-arithmetic special selector sends" [^ client send: (Smalltalk specialSelectorAt: offset + 17) super: false numArgs: (Smalltalk specialNargsAt: offset + 17)]. "type = 13, 14 or 15" ^ client send: (method literalAt: offset + 1) super: false numArgs: type - 13 "0, 1 & 2"! Item was changed: ----- Method: InstructionStream>>interpretNextV3InstructionFor: (in category 'decoding - private - v3 plus closures') ----- interpretNextV3InstructionFor: client "Send to the argument, client, a message that specifies the type of the next instruction." | byte type offset method | method := self method. byte := method at: pc. type := byte // 16. offset := byte \\ 16. pc := pc+1. "We do an inline binary search on each of the possible 16 values of type." type < 8 ifTrue: [type < 4 ifTrue: [type < 2 ifTrue: [type = 0 ifTrue: [^ client pushReceiverVariable: offset]. ^ client pushTemporaryVariable: offset]. "type = 1" type = 2 ifTrue: [^ client pushConstant: (method literalAt: offset + 1)]. ^ client pushConstant: (method literalAt: offset + 17)]. "type = 3" type < 6 ifTrue: [type = 4 ifTrue: [^ client pushLiteralVariable: (method literalAt: offset + 1)]. ^ client pushLiteralVariable: (method literalAt: offset + 17)]."type = 5" type = 6 ifTrue: [offset < 8 ifTrue: [^ client popIntoReceiverVariable: offset]. ^ client popIntoTemporaryVariable: offset - 8]. "type = 7" offset = 0 ifTrue: [^ client pushReceiver]. offset < 8 ifTrue: [^ client pushConstant: (SpecialConstants at: offset)]. offset = 8 ifTrue: [^ client methodReturnReceiver]. offset < 12 ifTrue: [^ client methodReturnConstant: (SpecialConstants at: offset - 8)]. offset = 12 ifTrue: [^ client methodReturnTop]. offset = 13 ifTrue: [^ client blockReturnTop]. + ^ self unusedBytecode: client at: pc - 1]. "offset = 14 & offset = 15, 126 & 127" - ^ self error: 'unusedBytecode']. "offset = 14 & offset = 15, 126 & 127" type < 12 ifTrue: [type < 10 ifTrue: [type = 8 ifTrue: [^ self interpretV3Extension: offset in: method for: client]. "type = 9 (short jumps)" offset < 8 ifTrue: [^ client jump: offset + 1]. ^ client jump: offset - 8 + 1 if: false]. type = 10 ifTrue: "(long jumps)" [byte := method at: pc. pc := pc + 1. offset < 8 ifTrue: [^ client jump: offset - 4 * 256 + byte]. ^ client jump: (offset bitAnd: 3) * 256 + byte if: offset < 12]. "type = 11; arithmetic special selector sends" ^ client send: (Smalltalk specialSelectorAt: offset + 1) super: false numArgs: (Smalltalk specialNargsAt: offset + 1)]. type = 12 ifTrue: "non-arithmetic special selector sends" [^ client send: (Smalltalk specialSelectorAt: offset + 17) super: false numArgs: (Smalltalk specialNargsAt: offset + 17)]. "type = 13, 14 or 15" ^ client send: (method literalAt: offset + 1) super: false numArgs: type - 13 "0, 1 & 2"! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. + offset = 11 ifTrue: [^self unusedBytecode: client at: pc - 1]. - offset = 11 ifTrue: [^self error: 'unusedBytecode']. byte3 := method at: pc. pc := pc + 1. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: InstructionStream>>interpretV3Extension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3Extension: offset in: method for: client | type offset2 byte2 byte3 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. + ^self unusedBytecode: client at: pc! - ^self error: 'unusedBytecode'! Item was added: + ----- Method: InstructionStream>>unusedBytecode:at: (in category 'private') ----- + unusedBytecode: client at: targetPC + [client unusedBytecode] + on: MessageNotUnderstood + do: [:ex| + (ex receiver == client + and: [ex message selector == #unusedBytecode]) + ifTrue: [self error: 'unusedBytecode'] + ifFalse: [ex pass]]! From commits at source.squeak.org Thu Oct 9 22:18:31 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 22:18:34 2014 Subject: [squeak-dev] The Trunk: Kernel.spur-eem.879.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel.spur-eem.879.mcz ==================== Summary ==================== Name: Kernel.spur-eem.879 Author: eem Time: 9 October 2014, 3:16:54.331 pm UUID: 5d49d6fa-2a6e-4b3a-8eda-b4cb90335bff Ancestors: Kernel-eem.879, Kernel.spur-eem.878 Kernel-eem.879 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Add a usable unusedBytecode hook that allows InstructionClients to define unusedBytecode and act appropriately. Remove the obsolete interpretExtension:in:for: =============== Diff against Kernel-eem.879 =============== Item was changed: ----- Method: Behavior>>allInstances (in category 'accessing instances and variables') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + (inst == insts or: [inst == insts originalContents]) ifFalse: [insts nextPut: inst]. + inst := next]. + ^insts contents! - allInstances - "Answer a collection of all current instances of the receiver." - - | all | - all := OrderedCollection new. - self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. - ^ all asArray - ! Item was changed: ----- Method: Behavior>>allInstancesDo: (in category 'enumerating') ----- + allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst." - allInstancesDo: aBlock - "Evaluate the argument, aBlock, for each of the current instances of the - receiver. - - Because aBlock might change the class of inst (for example, using become:), - it is essential to compute next before aBlock value: inst." - | inst next | inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == nil] - whileFalse: - [ - next := inst nextInstance. - aBlock value: inst. - inst := next]! Item was added: + ----- Method: Behavior>>allInstancesOrNil (in category 'enumerating') ----- + allInstancesOrNil + "Answer all instances of the receiver, or nil if the primitive + fails, which it may be due to being out of memory." + + ^nil! Item was changed: ----- Method: Behavior>>basicNew (in category 'instance creation') ----- basicNew "Primitive. Answer an instance of the receiver (which is a class) with no + indexable variables. Fail if the class is indexable. Essential. See Object + documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run + before the method is activated. Check that space was low and retry + via handleFailingBasicNew if so." - indexable variables. Fail if the class is indexable. Essential. See Object - documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew]. + self isVariable ifTrue: [^self basicNew: 0]. + self primitiveFailed! - - self isVariable ifTrue: [ ^ self basicNew: 0 ]. - "space must be low" - OutOfMemory signal. - ^ self basicNew "retry if user proceeds" - ! Item was changed: ----- Method: Behavior>>basicNew: (in category 'instance creation') ----- + basicNew: sizeRequested + "Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run before the + method is activated. Check args and retry via handleFailingBasicNew: if they're OK." - basicNew: sizeRequested - "Primitive. Answer an instance of this class with the number - of indexable variables specified by the argument, sizeRequested. - Fail if this class is not indexable or if the argument is not a - positive Integer, or if there is not enough memory available. - Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew: sizeRequested]. - self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. - (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: - ["arg okay; space must be low." - OutOfMemory signal. - ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstance (in category 'accessing instances and variables') ----- + byteSizeOfInstance + "Answer the total memory size of an instance of the receiver." + + + self isVariable ifTrue: + [^self byteSizeOfInstanceOfSize: 0]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstanceOfSize: (in category 'accessing instances and variables') ----- + byteSizeOfInstanceOfSize: basicSize + "Answer the total memory size of an instance of the receiver + with the given number of indexable instance variables." + + + self isVariable + ifTrue: "If the primitive overflowed answer a close approximation" + [(basicSize isInteger + and: [basicSize >= 16r1000000]) ifTrue: + [^2 * (self byteSizeOfInstanceOfSize: basicSize + 1 // 2) + - (self byteSizeOfInstanceOfSize: 0)]] + ifFalse: + [basicSize = 0 ifTrue: + [^self byteSizeOfInstance]]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>elementSize (in category 'accessing instances and variables') ----- + elementSize + "Answer the size in bytes of an element in the receiver. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + instSpec < 9 ifTrue: [^Smalltalk wordSize]. + instSpec >= 16 ifTrue: [^1]. + instSpec >= 12 ifTrue: [^2]. + instSpec >= 10 ifTrue: [^4]. + ^8! Item was added: + ----- Method: Behavior>>handleFailingBasicNew (in category 'private') ----- + handleFailingBasicNew + "handleFailingBasicNew gets sent after basicNew has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew. If + handleFailingBasicNew fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + Smalltalk garbageCollect < 1048576 ifTrue: + [Smalltalk growMemoryByAtLeast: 1048576]. + ^self handleFailingFailingBasicNew "retry after global garbage collect"! Item was added: + ----- Method: Behavior>>handleFailingBasicNew: (in category 'private') ----- + handleFailingBasicNew: sizeRequested + "handleFailingBasicNew: gets sent after basicNew: has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew:. If + handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := self byteSizeOfInstanceOfSize: sizeRequested. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingBasicNew: sizeRequested! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew (in category 'private') ----- + handleFailingFailingBasicNew + "This basicNew gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low" + OutOfMemory signal. + ^self basicNew "retry if user proceeds"! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew: (in category 'private') ----- + handleFailingFailingBasicNew: sizeRequested + "This basicNew: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + ^self basicNew: sizeRequested "retry if user proceeds"! Item was added: + ----- Method: Behavior>>identityHash (in category 'comparing') ----- + identityHash + "Answer a SmallInteger whose value is related to the receiver's identity. + Behavior implements identityHash to allow the VM to use an object representation which + does not include a direct reference to an object's class in an object. If the VM is using + this implementation then classes are held in a class table and instances contain the index + of their class in the table. A class's class table index is its identityHash so that an instance + can be created without searching the table for a class's index. The VM uses this primitive + to enter the class into the class table, assigning its identityHash with an as yet unused + class table index. If this primitive fails it means that the class table is full. In Spur as of + 2014 there are 22 bits of classTable index and 22 bits of identityHash per object. + + Primitive. Essential. Do not override. See Object documentation whatIsAPrimitive." + + + self primitiveFailed! Item was changed: ----- Method: Behavior>>indexIfCompact (in category 'private') ----- indexIfCompact + "Backward compatibility with the Squeak V3 object format. + Spur does not have a distinction between compact and non-compact classes." + ^0! - "If these 5 bits are non-zero, then instances of this class - will be compact. It is crucial that there be an entry in - Smalltalk compactClassesArray for any class so optimized. - See the msgs becomeCompact and becomeUncompact." - ^ (format bitShift: -11) bitAnd: 16r1F - " - Smalltalk compactClassesArray doWithIndex: - [:c :i | c == nil ifFalse: - [c indexIfCompact = i ifFalse: [self halt]]] - "! Item was changed: ----- Method: Behavior>>instSize (in category 'testing') ----- instSize "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^format bitAnd: 16rFFFF! - (as opposed to indexed variables) of the receiver." - - self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - When we revise the image format, it should become... - ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 - Note also that every other method in this category will require - 2 bits more of right shift after the change. - " - ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! Item was changed: ----- Method: Behavior>>instSpec (in category 'testing') ----- instSpec + "Answer the instance specification part of the format that defines what kind of object + an instance of the receiver is. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^(format bitShift: -16) bitAnd: 16r1F! - ^ (format bitShift: -7) bitAnd: 16rF! Item was changed: ----- Method: Behavior>>isBits (in category 'testing') ----- isBits + "Answer whether the receiver contains just bits (not pointers). + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 7! - "Answer whether the receiver contains just bits (not pointers)." - - ^ self instSpec >= 6! Item was changed: ----- Method: Behavior>>isBytes (in category 'testing') ----- isBytes + "Answer whether the receiver has 8-bit instance variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 16! - "Answer whether the receiver has 8-bit instance variables." - - ^ self instSpec >= 8! Item was added: + ----- Method: Behavior>>isEphemeronClass (in category 'testing') ----- + isEphemeronClass + "Answer whether the receiver has ephemeral instance variables. The garbage collector will + fire (queue for finalization) any ephemeron whose first instance variable is not referenced + other than from the transitive closure of references from ephemerons. Hence referring to + an object from the first inst var of an ephemeron will cause the ephemeron to fire when + the rest of the system does not refer to the object and that object is ready to be collected. + Since references from the remaining inst vars of an ephemeron will not prevent the ephemeron + from firing, ephemerons may act as the associations in weak dictionaries such that the value + (e.g. properties attached to the key) will not prevent firing when the key is no longer referenced + other than from ephemerons. Ephemerons can therefore be used to implement instance-based + pre-mortem finalization." + ^self instSpec = 5! Item was added: + ----- Method: Behavior>>isImmediateClass (in category 'testing') ----- + isImmediateClass + "Answer whether the receiver has immediate instances. Immediate instances + store their value in their object pointer, not in an object body. Hence immediates + take no space and are immutable. The immediates are distinguished by tag bits + in the pointer. They include SmallIntegers and Characters. Hence in the 32-bit + system SmallIntegers are 31-bit signed integers and Characters are 30-bit + unsigned character codes." + ^self instSpec = 7! Item was changed: ----- Method: Behavior>>isVariable (in category 'testing') ----- isVariable + "Answer whether the receiver has indexable variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + ^instSpec >= 2 and: [instSpec <= 4 or: [instSpec >= 9]]! - "Answer whether the receiver has indexable variables." - - ^ self instSpec >= 2! Item was changed: ----- Method: Behavior>>kindOfSubclass (in category 'testing class hierarchy') ----- kindOfSubclass + "Answer a String that is the keyword that describes the receiver's kind of subclass, + either a regular subclass, a variableSubclass, a variableByteSubclass, + a variableWordSubclass, a weakSubclass, an ephemeronSubclass or an immediateSubclass. + c.f. typeOfClass" + ^self isVariable + ifTrue: + [self isBits + ifTrue: + [self isBytes + ifTrue: [' variableByteSubclass: '] + ifFalse: [' variableWordSubclass: ']] + ifFalse: + [self isWeak + ifTrue: [' weakSubclass: '] + ifFalse: [' variableSubclass: ']]] + ifFalse: + [self isImmediateClass + ifTrue: [' immediateSubclass: '] + ifFalse: + [self isEphemeronClass + ifTrue: [' ephemeronSubclass: '] + ifFalse: [' subclass: ']]]! - "Answer a String that is the keyword that describes the receiver's kind - of subclass, either a regular subclass, a variableSubclass, a - variableByteSubclass, a variableWordSubclass, or a weakSubclass." - self isWeak - ifTrue: [^ ' weakSubclass: ']. - ^ self isVariable - ifTrue: [self isBits - ifTrue: [self isBytes - ifTrue: [ ' variableByteSubclass: '] - ifFalse: [ ' variableWordSubclass: ']] - ifFalse: [ ' variableSubclass: ']] - ifFalse: [ ' subclass: ']! Item was changed: ----- Method: Behavior>>shouldNotBeRedefined (in category 'testing') ----- shouldNotBeRedefined + "Answer if the receiver should not be redefined. + The assumption is that classes in Smalltalk specialObjects and + instance-specific Behaviors should not be redefined" - "Return true if the receiver should not be redefined. - The assumption is that compact classes, - classes in Smalltalk specialObjects and - Behaviors should not be redefined" + ^(Smalltalk specialObjectsArray + identityIndexOf: self + ifAbsent: [(self isKindOf: self) ifTrue: [1] ifFalse: [0]]) ~= 0! - ^(Smalltalk compactClassesArray includes: self) - or:[(Smalltalk specialObjectsArray includes: self) - or:[self isKindOf: self]]! Item was changed: ----- Method: Behavior>>typeOfClass (in category 'accessing') ----- typeOfClass + "Answer a symbol uniquely describing the type of the receiver. c.f. kindOfSubclass" + self isBytes ifTrue: + [^self instSpec = CompiledMethod instSpec + ifTrue: [#compiledMethod] "Very special!!" + ifFalse: [#bytes]]. + (self isWords and: [self isPointers not]) ifTrue: + [^self instSpec = SmallInteger instSpec + ifTrue: [#immediate] "Very special!!" + ifFalse: [#words]]. + self isWeak ifTrue: [^#weak]. + self isVariable ifTrue: [^#variable]. + self isEphemeronClass ifTrue: [^#ephemeron]. + ^#normal! - "Answer a symbol uniquely describing the type of the receiver" - self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" - self isBytes ifTrue:[^#bytes]. - (self isWords and:[self isPointers not]) ifTrue:[^#words]. - self isWeak ifTrue:[^#weak]. - self isVariable ifTrue:[^#variable]. - ^#normal.! Item was changed: ----- Method: BlockClosure>>simulateValueWithArguments:caller: (in category 'system simulation') ----- simulateValueWithArguments: anArray caller: aContext + "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity." | newContext sz | - (anArray class ~~ Array - or: [numArgs ~= anArray size]) ifTrue: - [^ContextPart primitiveFailTokenFor: nil]. newContext := (MethodContext newForMethod: outerContext method) setSender: aContext receiver: outerContext receiver method: outerContext method closure: self startpc: startpc. + ((newContext objectClass: anArray) ~~ Array + or: [numArgs ~= anArray size]) ifTrue: + [^ContextPart primitiveFailTokenFor: nil]. sz := self basicSize. newContext stackp: sz + numArgs. 1 to: numArgs do: [:i| newContext at: i put: (anArray at: i)]. 1 to: sz do: [:i| newContext at: i + numArgs put: (self at: i)]. ^newContext! Item was added: + ----- Method: Class>>immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'subclass creation') ----- + immediateSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a new + immediate class as a subclass of an existing class (the receiver)." + ^ClassBuilder new + superclass: self + immediateSubclass: t + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>computeFormat:instSize:forSuper:ccIndex: (in category 'class format') ----- computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. + Answer the format or nil if there is any problem." - Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | type == #compiledMethod ifTrue: + [newInstSize > 0 ifTrue: + [self error: 'A compiled method class cannot have named instance variables'. + ^nil]. + ^CompiledMethod format]. - [^(CompiledMethod format - bitClear: (16r1F bitShift: 11)) - bitOr: (ccIndex bitShift: 11)]. instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). + instSize > 65535 ifTrue: - instSize > 254 ifTrue: [self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true]. type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false]. type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false]. type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false]. type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true]. + type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true]. + type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true]. + (isPointers not and: [instSize > 0]) ifTrue: + [self error: 'A non-pointer class cannot have named instance variables'. - (isPointers not and:[instSize > 0]) ifTrue: - [self error:'A non-pointer class cannot have instance variables'. ^nil]. + ^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak! - ^(self format: instSize - variable: isVar - words: isWords - pointers: isPointers - weak: isWeak) + (ccIndex bitShift: 11).! Item was changed: ----- Method: ClassBuilder>>format:variable:words:pointers:weak: (in category 'class format') ----- + format: nInstVars variable: isVar words: is32BitWords pointers: isPointers weak: isWeak + "Compute the format for the given instance specfication. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = reserved for 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | - format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak - "Compute the format for the given instance specfication." - | cClass instSpec sizeHiBits fmt | - self flag: #instSizeChange. - " - Smalltalk browseAllCallsOn: #instSizeChange. - Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. - Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. - " - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - For now the format word is... - <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> - But when we revise the image format, it should become... - <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> - " - sizeHiBits := (nInstVars+1) // 64. - cClass := 0. "for now" instSpec := isWeak + ifTrue: + [isVar + ifTrue: [4] + ifFalse: [5]] + ifFalse: + [isPointers + ifTrue: + [isVar + ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]] + ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]] + ifFalse: + [isVar + ifTrue: [is32BitWords ifTrue: [10] ifFalse: [16]] + ifFalse: [7]]]. + ^(instSpec bitShift: 16) + nInstVars! - ifTrue:[4] - ifFalse:[isPointers - ifTrue: [isVar - ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] - ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] - ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. - fmt := sizeHiBits. - fmt := (fmt bitShift: 5) + cClass. - fmt := (fmt bitShift: 4) + instSpec. - fmt := (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" - fmt := (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" - ^fmt! Item was added: + ----- Method: ClassBuilder>>superclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'public') ----- + superclass: aClass + immediateSubclass: t instanceVariableNames: f + classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a + new immediate class as a subclass of an existing class." + | env | + aClass instSize > 0 + ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields']. + aClass isVariable + ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables']. + aClass isPointers + ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields']. + "Cope with pre-environment and environment versions. Simplify asap." + env := (Smalltalk classNamed: #EnvironmentRequest) + ifNil: [aClass environment] + ifNotNil: [:erc| erc signal ifNil: [aClass environment]]. + ^self + name: t + inEnvironment: env + subclassOf: aClass + type: #immediate + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" - "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. - We can rely on two assumptions (which are critical): - #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) - #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. - Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. - " | meta | meta := oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." - [ - "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). - Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "make sure that the VM cache is clean" oldClass methodDict do: [:cm | cm flushCache]. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue: [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. oldClass updateMethodBindingsTo: oldClass binding. oldClass class updateMethodBindingsTo: oldClass class binding]. + "eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was + to ensure no old instances existed after the becomeForward:. Without the GC it was possible + to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward: + updated references from the old objects to new objects but didn't destroy the old objects. + But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."] + valueUnpreemptively! - Smalltalk garbageCollect. - - "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). - - The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: - - On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. - - Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). - - Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. - - Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." - - ] valueUnpreemptively. - ! Item was changed: ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame' poolDictionaries: '' category: 'Kernel-Methods'! + !CompiledMethod commentStamp: 'eem 8/12/2014 14:45' prior: 0! + CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. - !CompiledMethod commentStamp: 'eem 5/12/2014 18:02' prior: 0! - My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. I'm a subclass of ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. Class variables: SmallFrame - the number of stack slots in a small frame Context LargeFrame - the number of stack slots in a large frame Context PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set The current format of a CompiledMethod is as follows: header (4 or 8 bytes, SmallInteger) + literals (4 or 8 bytes each, Object, see "The last literal..." below) - literals (4 or 8 bytes each, Object) bytecodes (variable, bytes) trailer (variable, bytes) + The header is a 31-bit signed integer (a SmallInteger) in the following format: - The header is a 31-bit signed integer (a SmallInteger) with one of the two following formats, selected by the sign bit: - sign bit 0, header >= 0: - (index 0) 9 bits: main part of primitive number (#primitive) - (index 9) 8 bits: number of literals (#numLiterals) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) - (index 18) 6 bits: number of temporary variables (#numTemps) - (index 24) 4 bits: number of arguments to the method (#numArgs) - (index 28) 1 bit: high-bit of primitive number (#primitive) - (index 29) 1 bit: flag bit, ignored by the VM (#flag) - (index 30/63) sign bit: 0 selects the Primary instruction set (#signFlag) - sign bit 1, header < 0: (index 0) 16 bits: number of literals (#numLiterals) (index 16) 1 bit: has primitive + (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) + (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag). + (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4, 0 selects the primary instruction set, e.g. SqueakV3PlusClosures) (#signFlag) - (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public) - (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4) (#signFlag) - i.e. the Secondary Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode. + If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. + + The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer. + + The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be left nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.! - The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.! Item was added: + ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') ----- + handleFailingFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails then the + system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + "retry if user proceeds" + ^self newMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') ----- + handleFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after newMethod:header: has failed + and allowed a scavenging garbage collection to occur. The scavenging + collection will have happened as the VM is activating the (failing) basicNew:. + If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') ----- + installPrimaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was added: + ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') ----- + installSecondaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: ["For now the high bit of primitive no. is in the 29th bit of header" - primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits flagBit | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - "For now the high bit of the primitive no. is in a high bit of the header" - primBits := (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19). - - flagBit := flag ifTrue: [ 1 ] ifFalse: [ 0 ]. - - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits + - (flagBit bitShift: 29)! Item was changed: ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') ----- + newMethod: numberOfBytes header: headerWord - newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other + information) is specified by the headerWord (see my class comment). + The first argument specifies the number of fields for bytecodes in the + method. Fail if either argument is not a SmallInteger, or if numberOfBytes + is negative, or if memory is low. Once the header of a method is set by + this primitive, it cannot be changed to change the number of literals. + Essential. See Object documentation whatIsAPrimitive." - information) is specified the headerWord. The first argument specifies - the number of fields for bytecodes in the method. Fail if either - argument is not a SmallInteger, or if numberOfBytes is negative. Once - the header of a method is set by this primitive, it cannot be changed in - any way. Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingNewMethod: numberOfBytes header: headerWord]. - - (numberOfBytes isInteger and: - [headerWord isInteger and: - [numberOfBytes >= 0]]) ifTrue: [ - "args okay; space must be low" - OutOfMemory signal. - "retry if user proceeds" - ^ self newMethod: numberOfBytes header: headerWord - ]. ^self primitiveFailed! Item was changed: ----- Method: CompiledMethod class>>toReturnConstant:trailerBytes: (in category 'instance creation') ----- toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index - ! Item was changed: ----- Method: CompiledMethod class>>toReturnField:trailerBytes: (in category 'instance creation') ----- toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field - ! Item was changed: ----- Method: CompiledMethod class>>toReturnSelfTrailerBytes: (in category 'instance creation') ----- toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 - ! Item was added: + ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') ----- + bytecodeSetName + ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''! Item was changed: ----- Method: CompiledMethod>>headerDescription (in category 'literals') ----- headerDescription + "Answer a description containing the information about the form of the + receiver and the form of the context needed to run the receiver." - "Answer a description containing the information about the form of the - receiver and the form of the context needed to run the receiver." + ^(ByteString new: 128) writeStream + print: self header; cr; + nextPutAll: '"primitive: '; print: self primitive; cr; + nextPutAll: ' numArgs: '; print: self numArgs; cr; + nextPutAll: ' numTemps: '; print: self numTemps; cr; + nextPutAll: ' numLiterals: '; print: self numLiterals; cr; + nextPutAll: ' frameSize: '; print: self frameSize; cr; + nextPutAll: ' bytecodeSet: '; nextPutAll: self bytecodeSetName; + nextPut: $"; cr; + contents! - | s | - s := '' writeStream. - self header printOn: s. - s cr; nextPutAll: '"primitive: '. - self primitive printOn: s. - s cr; nextPutAll: ' numArgs: '. - self numArgs printOn: s. - s cr; nextPutAll: ' numTemps: '. - self numTemps printOn: s. - s cr; nextPutAll: ' numLiterals: '. - self numLiterals printOn: s. - s cr; nextPutAll: ' frameSize: '. - self frameSize printOn: s. - s cr; nextPutAll: ' isClosureCompiled: '. - self isBlueBookCompiled not printOn: s. - s nextPut: $"; cr. - ^ s contents! Item was changed: ----- Method: CompiledMethod>>numLiterals (in category 'accessing') ----- numLiterals "Answer the number of literals used by the receiver." + ^self header bitAnd: 65535! - | header | - ^(header := self header) < 0 - ifTrue: [header bitAnd: 65535] - ifFalse: [(header bitShift: -9) bitAnd: 16rFF]! Item was changed: ----- Method: CompiledMethod>>primitive (in category 'accessing') ----- primitive "Answer the primitive index associated with the receiver. + Zero indicates that this is not a primitive method." + | initialPC | + ^(self header anyMask: 65536) "Is the hasPrimitive? flag set?" + ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] + ifFalse: [0]! - Zero indicates that this is not a primitive method. - In the original header format we currently allow 10 bits of primitive index, but they are - in two places for backward compatibility. In the new format the primitive index is in the - last two bytes of a three byte callPrimitive: bytecode. The time to unpack is negligible, - since the derived primitive function pointer full index is stored in the method cache." - | header initialPC | - ^(header := self header) < 0 - ifTrue: - [(header anyMask: 65536) "Is the hasPrimitive? flag set?" - ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] - ifFalse: [0]] - ifFalse: - [(header bitAnd: 16r1FF) + ((header bitShift: -19) bitAnd: 16r200)]! Item was changed: ----- Method: ContextPart>>activateReturn:value: (in category 'private') ----- activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" + ^MethodContext + sender: self - ^ self - activateMethod: ContextPart theReturnMethod - withArgs: {value} receiver: aContext + method: MethodContext theReturnMethod + arguments: {value}! - class: aContext class! Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments + "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and + arguments are given as arguments to this message. If successful, push result and return + resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes + execution needs to be intercepted and simulated to avoid execution running away." - "Simulate a primitive method whose index is primitiveIndex. The - simulated receiver and arguments are given as arguments to this message. - If successful, push result and return resuming context, else ^ PrimitiveFailToken. - Any primitive which provokes execution needs to be intercepted and simulated - to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug + interesting code, such as the debugger itself. hence use primitive 19 with care :-)" - interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. + ((primitiveIndex between: 201 and: 222) + and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: + [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" + or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" + [^receiver simulateValueWithArguments: arguments caller: self]. + primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" + [^receiver simulateValueWithArguments: arguments first caller: self]]. - "ContextPart>>blockCopy:; simulated to get startpc right" - (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) - ifTrue: [^self push: ((BlockContext newForMethod: receiver method) - home: receiver home - startpc: pc + 2 - nargs: (arguments at: 1))]. - (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" - ifTrue: [^receiver pushArgs: arguments from: self]. - (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" - ifTrue: [^receiver pushArgs: arguments first from: self]. - primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" - ifTrue: [^self send: arguments first - to: receiver - with: arguments allButFirst - super: false]. - primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: nil]. - primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: (arguments at: 3)]. + primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [^self send: arguments first to: receiver with: arguments allButFirst super: false]. + primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. + primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. + "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. + ^(self isPrimFailToken: value) - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" - and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: (arguments at: 2) + arguments: (arguments at: 1)]. - method: arguments last - arguments: (primitiveIndex = 188 - ifTrue: [arguments at: 1] - ifFalse: [arguments allButLast])]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. - ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" - or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" - [^receiver simulateValueWithArguments: arguments caller: self]. - primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" - [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] + ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. + + ^(self isPrimFailToken: value) - ifFalse: - [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! Item was added: + ----- Method: ContextPart>>isPrimFailToken: (in category 'private') ----- + isPrimFailToken: anObject + ^(self objectClass: anObject) == Array + and: [anObject size = 2 + and: [anObject first == PrimitiveFailToken]]! Item was added: + ----- Method: ContextPart>>send:to:with:lookupIn: (in category 'controlling') ----- + send: selector to: rcvr with: arguments lookupIn: lookupClass + "Simulate the action of sending a message with selector and arguments + to rcvr. The argument, lookupClass, is the class in which to lookup the + message. This is the receiver's class for normal messages, but for super + messages it will be some specific class related to the source method." + + | meth primIndex val ctxt | + (meth := lookupClass lookupSelector: selector) ifNil: + [^self send: #doesNotUnderstand: + to: rcvr + with: {Message selector: selector arguments: arguments} + lookupIn: lookupClass]. + (primIndex := meth primitive) > 0 ifTrue: + [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments. + (self isPrimFailToken: val) ifFalse: + [^val]]. + (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue: + [^self error: 'Simulated message ', arguments first selector, ' not understood']. + ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments. + primIndex > 0 ifTrue: + [ctxt failPrimitiveWith: val]. + ^ctxt! Item was changed: ----- Method: ContextPart>>send:to:with:super: (in category 'controlling') ----- + send: selector to: rcvr with: arguments super: superFlag + "Simulate the action of sending a message with selector arguments + to rcvr. The argument, superFlag, tells whether the receiver of the + message was specified with 'super' in the source method." - send: selector to: rcvr with: args super: superFlag - "Simulate the action of sending a message with selector, selector, and - arguments, args, to receiver. The argument, superFlag, tells whether the - receiver of the message was specified with 'super' in the source method." + ^self send: selector + to: rcvr + with: arguments + lookupIn: (superFlag + ifTrue: [self method methodClassAssociation value superclass] + ifFalse: [self objectClass: rcvr])! - | class meth val ctxt | - class := superFlag - ifTrue: [self method methodClassAssociation value superclass] - ifFalse: [self objectClass: rcvr]. - meth := class lookupSelector: selector. - meth == nil ifTrue: - [^self - send: #doesNotUnderstand: - to: rcvr - with: (Array with: (Message selector: selector arguments: args)) - super: superFlag]. - val := self tryPrimitiveFor: meth receiver: rcvr args: args. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken]]) ifFalse: - [^val]. - (selector == #doesNotUnderstand: - and: [class == ProtoObject]) ifTrue: - [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood']. - ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken - and: [val last notNil - and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue: - [ctxt at: ctxt stackPtr put: val last]. - ^ctxt! Item was changed: ----- Method: ContextPart>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') ----- tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments + "Invoke the named primitive for aCompiledMethod, answering its result, or, + if the primiitve fails, answering the error code." - | selector theMethod spec receiverClass | ec ifNotNil: ["If ec is an integer other than -1 there was a problem with primitive 218, not with the external primitive itself. -1 indicates a generic failure (where ec should be nil) but ec = nil means primitive 218 is not implemented. So interpret -1 to mean the external primitive failed with a nil error code." ec isInteger ifTrue: [ec = -1 ifTrue: [ec := nil] + ifFalse: [self primitiveFailed]]]. + ^self class primitiveFailTokenFor: ec! - ifFalse: [self primitiveFailed]]. - ^{PrimitiveFailToken. ec}]. - "Assume a nil error code implies the primitive is not implemented and fall back on the old code." - "Hack. Attempt to execute the named primitive from the given compiled method" - arguments size > 8 ifTrue: - [^{PrimitiveFailToken. nil}]. - selector := #( - tryNamedPrimitive - tryNamedPrimitive: - tryNamedPrimitive:with: - tryNamedPrimitive:with:with: - tryNamedPrimitive:with:with:with: - tryNamedPrimitive:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. - receiverClass := self objectClass: aReceiver. - theMethod := receiverClass lookupSelector: selector. - theMethod == nil ifTrue: - [^{PrimitiveFailToken. nil}]. - spec := theMethod literalAt: 1. - spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. - Smalltalk unbindExternalPrimitives. - ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass! Item was added: + ----- Method: InstructionClient>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: pimIndex + "V3PlusClosures: 139 10001011 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + NewsqueakV4: 249 11111001 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + ( jjjjjjj * 256) + m=1 means inlined primitive, no hard return after execution."! Item was added: + ----- Method: InstructionPrinter>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: index + "Print the callPrimitive." + + self print: 'callPrimtive: ' , index printString! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self unusedBytecode: client at: pc - 1]. byte3 := method at: pc. pc := pc + 1. + offset = 11 ifTrue: [^client callPrimitive: byte2 + (byte3 bitShift: 8)]. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: Integer class>>initialize (in category 'class initialization') ----- + initialize + "Integer initialize" + self initializeLowBitPerByteTable! - initialize "Integer initialize" - "Ensure we have the right compact class index" - - "LPI has been a compact class forever - just ensure basic correctness" - (LargePositiveInteger indexIfCompact = 5) ifFalse:[ - (Smalltalk compactClassesArray at: 5) - ifNil:[LargePositiveInteger becomeCompactSimplyAt: 5] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - "Cog requires LNI to be compact at 4 (replacing PseudoContext)" - (LargeNegativeInteger indexIfCompact = 4) ifFalse:[ - "PseudoContext will likely get removed at some point so write this test - without introducing a hard dependency" - (Smalltalk compactClassesArray at: 4) name == #PseudoContext - ifTrue:[Smalltalk compactClassesArray at: 4 put: nil]. - (Smalltalk compactClassesArray at: 4) - ifNil:[LargeNegativeInteger becomeCompactSimplyAt: 4] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - self initializeLowBitPerByteTable - ! Item was added: + ----- Method: MethodContext class>>allInstances (in category 'enumerating') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst. + Only count until thisContext since this context has been created only to + compute the existing instances." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + insts nextPut: inst. + inst := next]. + ^insts contents! Item was changed: ----- Method: MethodContext class>>allInstancesDo: (in category 'private') ----- allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst. + Only count until thisContext since evaluation of aBlock will create new contexts." - "Only count until thisContext since evaluation of aBlock will create new contexts." - | inst next | inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == thisContext] whileFalse:[ - next := inst nextInstance. - aBlock value: inst. - inst := next] - ! Item was added: + ----- Method: MethodContext>>failPrimitiveWith: (in category 'system simulation') ----- + failPrimitiveWith: maybePrimFailToken + "The receiver is a freshly-created context on a primitive method. Skip the callPrimitive: + bytecode and store the primitive fail code if there is one and the method consumes it." + self skipCallPrimitive. + ((self isPrimFailToken: maybePrimFailToken) + and: [method encoderClass isStoreAt: pc in: method]) ifTrue: + [self at: stackp put: maybePrimFailToken last]! Item was changed: ----- Method: ProtoObject>>scaledIdentityHash (in category 'comparing') ----- scaledIdentityHash "For identityHash values returned by primitive 75, answer + such values times 2^8. Otherwise, match the existing + identityHash implementation" - such values times 2^18. Otherwise, match the existing - identityHash implementation" + ^self identityHash * 256 "bitShift: 8"! - ^self identityHash * 262144 "bitShift: 18"! Item was changed: ==== ERROR === Error: Unrecognized class type 9 October 2014 10:18:30.917 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(SmallInteger) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Thu Oct 9 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 9 23:55:04 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141009235502.8776.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007319.html Name: Monticello-bf.601 Ancestors: Monticello-topa.600 Do not warn about possibly newer versions on different branch (e.g. VMMaker.oscog) ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007320.html Name: Collections.spur-nice.574 Ancestors: Collections-nice.574, Collections.spur-ul.573 Collections-nice.574 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Less ascii/binary dance. The sender of nextString doesn't try to force ascii, anymore so the implementor doesn't have to force binary. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007321.html Name: Compiler.spur-eem.289 Ancestors: Compiler-eem.289, Compiler.spur-eem.288 Compiler-eem.289 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Fix doits in the codePane of a debugger opened from another debugger. e.g. before this fix 1. debug 3+4. 2. in code pane of debugger #1 debug 4+5 3. in code pane of debugger #2 debug 5+6, boom. The bug was that when the encoder creates temp names for temp vars in the debugged context, which it does by creating messages to DoItIn:'s argument 'ThisContext', if this is a level 3 debug, then the original expression would have a temp var called 'ThisContext' already and that would overwrite the 'ThisContext' argument for this level with a message send, and boom. The fix is merely to filter-out these temps and hence never overwrite DoItIn:'s 'ThisContext' argument in the scope table. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007322.html Name: Collections.spur-ul.584 Ancestors: Collections-ul.584, Collections.spur-nice.583 Collections-ul.584 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Character changes: - use the value instance variable instead of #asciiValue where possible - implemented #<= and #>= ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007323.html Name: Compiler.spur-eem.290 Ancestors: Compiler-eem.290, Compiler.spur-eem.289 Compiler-eem.290 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Define the other extension acessor, the one that locates extensions before an extended bytecode. Tighten up the comment on the one that accesses the extension bytecodes themselves. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007324.html Name: Kernel.spur-eem.876 Ancestors: Kernel-eem.876, Kernel.spur-ul.875 Kernel-eem.876 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Fix handleSignal: for a rare edge case that can occur on Stack & Cog VMs. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007325.html Name: Kernel.spur-eem.877 Ancestors: Kernel-eem.877, Kernel.spur-eem.876 Kernel-eem.877 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007326.html Name: System.spur-nice.673 Ancestors: System-nice.673, System.spur-dtl.672 System-nice.673 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Continue to disentangle the nest of vipers, one knot at a time. Replace usage of compressedMIMEEncodedStream, because - we do not need a ReadWriteStream (such requirement should be so rare) - we do not even need a ReadStream - we just need a String So let's use a String ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007327.html Name: Kernel.spur-eem.878 Ancestors: Kernel-eem.878, Kernel.spur-eem.876 Kernel-eem.878 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Less haste, more speed. Fix doPrimitive:method:receiver:args: for primitive 188 and quick methods (Object>>withArgs:executeMethod:) and support primitive 189 (Object>>with:*executeMethod:) ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007328.html Name: System.spur-nice.674 Ancestors: System-nice.674, System.spur-nice.673 System-nice.674 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Remove SmartRefStream class>>streamedRepresentationOf: which is essentially the same as super. The sole difference is that it tries to close the RWBinaryOrTextStream, but this is a no-op... ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007329.html Name: System.spur-nice.675 Ancestors: System-nice.675, System.spur-nice.674 System-nice.675 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Remove a bit of ascii/binary dance. This is possible - in CodeLoader because ByteArray now understands unzipped - in DataStream>>readString, because nextString will turn stream to binary right after we asked for ascii... - in SmartRefStream>>appendClassDefns because we can forward the job to an asciiStream. Beware, this last part was not WideString friendly, and still isn't really. We should better use something like UTF8 but it's not a local change - we'll see later... ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007330.html Name: Kernel-eem.879 Ancestors: Kernel-eem.878 Add a usable unusedBytecode hook that allows InstructionClients to define unusedBytecode and act appropriately. Remove the obsolete interpretExtension:in:for: ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007331.html Name: Kernel.spur-eem.879 Ancestors: Kernel-eem.879, Kernel.spur-eem.878 Kernel-eem.879 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.209 Add a usable unusedBytecode hook that allows InstructionClients to define unusedBytecode and act appropriately. Remove the obsolete interpretExtension:in:for: ============================================= From lecteur at zogotounga.net Fri Oct 10 07:31:24 2014 From: lecteur at zogotounga.net (=?windows-1252?Q?St=E9phane_Rollandin?=) Date: Fri Oct 10 07:31:30 2014 Subject: [squeak-dev] re: Saucers for Mac broken ? In-Reply-To: References: <5433A641.9000605@zogotounga.net> <5433B1F6.6050307@zogotounga.net> Message-ID: <54378B4C.2000404@zogotounga.net> > There is good progress on porting the open-source Mac app signing > code to non-Mac platforms, but it still needs some work. And apparently > you can sign with non-Apple (e.g., free) certificates and still satisfy > Gatekeeper on an end-user Mac, but I don't think it'd pass review for > the Apple app store (although it probably would for the Microsoft > store). See [1]. > > > -C > > [1] http://bit.ly/1vOxWyI (stackoverflow.com) Hmm.. I don't understand most of this stuff; I take it that it is not trivial to deploy a Squeak image on Macs... sad. Well, I'll tell my friends to change their security settings. Thanks, Stef From lecteur at zogotounga.net Fri Oct 10 08:31:02 2014 From: lecteur at zogotounga.net (=?UTF-8?B?U3TDqXBoYW5lIFJvbGxhbmRpbg==?=) Date: Fri Oct 10 08:31:07 2014 Subject: [squeak-dev] [ANN] Home page for Saucers! Message-ID: <54379946.8080403@zogotounga.net> Hello, So I set-up a home page for the Saucers! game: http://www.zogotounga.net/comp/saucers.htm At the bottom I put a link to squeak.org, along with the source code. Conversely, I suggest that folks wanting to promote Morphic link to it as an example of what can be done. Maybe from the squeak.org projects page ? Stef From edgardec2005 at gmail.com Fri Oct 10 11:14:06 2014 From: edgardec2005 at gmail.com (Edgar J de Cleene) Date: Fri Oct 10 11:14:20 2014 Subject: [squeak-dev] [ANN] Home page for Saucers! In-Reply-To: <54379946.8080403@zogotounga.net> References: <54379946.8080403@zogotounga.net> Message-ID: <2B9AA32947A14FF18BF5DDBB58F92CDA@gmail.com> Thanls for this Stephane !!! -- Edgar J de Cleene @morplenauta en twitter Sent with Sparrow (http://www.sparrowmailapp.com/?sig) On Friday, October 10, 2014 at 05:31, St?phane Rollandin wrote: > Hello, > > So I set-up a home page for the Saucers! game: > http://www.zogotounga.net/comp/saucers.htm > > At the bottom I put a link to squeak.org (http://squeak.org), along with the source code. > Conversely, I suggest that folks wanting to promote Morphic link to it > as an example of what can be done. Maybe from the squeak.org (http://squeak.org) projects page ? > > > Stef -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141010/b6b97a71/attachment.htm From craig at netjam.org Fri Oct 10 11:55:41 2014 From: craig at netjam.org (Craig Latta) Date: Fri Oct 10 11:55:56 2014 Subject: [squeak-dev] re: Saucers for Mac broken ? In-Reply-To: <54378B4C.2000404@zogotounga.net> References: <5433A641.9000605@zogotounga.net> <5433B1F6.6050307@zogotounga.net> <54378B4C.2000404@zogotounga.net> Message-ID: > I take it that it is not trivial to deploy a Squeak image on Macs... > sad. I don't think it's ever been trivial to deploy any Smalltalk app on any platform, ever, and yes, that's sad. :) We're making progress though, even with the advent of walled-off "app stores" from Apple, Microsoft, Google, etc. As for your particular signing issue, I'm happy to sign it if you like. -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From lecteur at zogotounga.net Fri Oct 10 12:00:42 2014 From: lecteur at zogotounga.net (=?windows-1252?Q?St=E9phane_Rollandin?=) Date: Fri Oct 10 12:00:47 2014 Subject: [squeak-dev] re: Saucers for Mac broken ? In-Reply-To: References: <5433A641.9000605@zogotounga.net> <5433B1F6.6050307@zogotounga.net> <54378B4C.2000404@zogotounga.net> Message-ID: <5437CA6A.8080000@zogotounga.net> > > As for your particular signing issue, I'm happy to sign it if you like. Thanks, but asking people to lower their security settings did the trick for me. Stef From brasspen at gmail.com Fri Oct 10 15:41:47 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Fri Oct 10 15:41:55 2014 Subject: [squeak-dev] Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? Message-ID: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> I recall there was a problem with the All-In-One.[1] Craig made a new one. [2] It needs to replace the old one.[3]. Is that correct? Chris [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-September/180037.html [2] http://bit.ly/1CBwx1I [3] http://ftp.squeak.org/4.5/ -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141010/84004431/attachment.htm From Das.Linux at gmx.de Fri Oct 10 15:46:47 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri Oct 10 15:46:52 2014 Subject: [squeak-dev] Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> Message-ID: <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> On 10.10.2014, at 17:41, Chris Cunnington wrote: > I recall there was a problem with the All-In-One.[1] Craig made a new one. [2] It needs to replace the old one.[3]. Is that correct? > > Chris > > > [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-September/180037.html > > [2] http://bit.ly/1CBwx1I > [3] http://ftp.squeak.org/4.5/ Yes but we now must talk about how to handle all-in-ones. When apple really no longer allow stuff besides the Contents/ directory, it renders the whole thing moot. Then we better either distribute 3 individual files or an unsigned all-in-one. Best -Tobias From brasspen at gmail.com Fri Oct 10 15:51:08 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Fri Oct 10 15:51:13 2014 Subject: [squeak-dev] Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> Message-ID: <16DC801A-288B-4883-8FEC-DA560AEF172E@gmail.com> > On Oct 10, 2014, at 11:46 AM, Tobias Pape wrote: > > > On 10.10.2014, at 17:41, Chris Cunnington wrote: > >> I recall there was a problem with the All-In-One.[1] Craig made a new one. [2] It needs to replace the old one.[3]. Is that correct? >> >> Chris >> >> >> [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-September/180037.html >> >> [2] http://bit.ly/1CBwx1I >> [3] http://ftp.squeak.org/4.5/ > > Yes but we now must talk about how to handle all-in-ones. I thought as much. I made a humorous post expecting this. I erased it as I figured it would annoy people. Soooo, when you?ve finished deciding what you want, please create a message that say in the Subject line: ?Webteam Leader Request - blah, blah?. The upload and change will take place soon after. I think I can be forgiven for not wanting to read about the details. Cheers, Chris > When apple really no longer allow stuff besides the Contents/ directory, > it renders the whole thing moot. > Then we better > either distribute 3 individual files > or an unsigned all-in-one. > > > Best > -Tobias From Das.Linux at gmx.de Fri Oct 10 16:15:22 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri Oct 10 16:15:29 2014 Subject: [squeak-dev] Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: <16DC801A-288B-4883-8FEC-DA560AEF172E@gmail.com> References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> <16DC801A-288B-4883-8FEC-DA560AEF172E@gmail.com> Message-ID: <9708A328-A910-475C-8436-A4174BA721A0@gmx.de> On 10.10.2014, at 17:51, Chris Cunnington wrote: >> >> On Oct 10, 2014, at 11:46 AM, Tobias Pape wrote: >> >> >> On 10.10.2014, at 17:41, Chris Cunnington wrote: >> >>> I recall there was a problem with the All-In-One.[1] Craig made a new one. [2] It needs to replace the old one.[3]. Is that correct? >>> >>> Chris >>> >>> >>> [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-September/180037.html >>> >>> [2] http://bit.ly/1CBwx1I >>> [3] http://ftp.squeak.org/4.5/ >> >> Yes but we now must talk about how to handle all-in-ones. > > I thought as much. I made a humorous post expecting this. I erased it as I figured it would annoy people. > Soooo, when you?ve finished deciding what you want, please create a message that say in the Subject line: ?Webteam Leader Request - blah, blah?. The upload and change will take place soon after. > I think I can be forgiven for not wanting to read about the details. > ACK > Cheers, > Chris > >> When apple really no longer allow stuff besides the Contents/ directory, >> it renders the whole thing moot. >> Then we better >> either distribute 3 individual files >> or an unsigned all-in-one. >> >> >> Best >> -Tobias From asqueaker at gmail.com Fri Oct 10 16:21:27 2014 From: asqueaker at gmail.com (Chris Muller) Date: Fri Oct 10 16:21:33 2014 Subject: [squeak-dev] Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> Message-ID: We talked about it in last week's board meeting. We decided there is merit to staying with an All-In-One but there was a discussion about whether there should be shortcuts in the main directory for each platform. There was representation for both sides of that question, but the majority settled on including them. Chris C., since I was the 4.5 release manager, if you don't mind, after Craig has time to put that together, I'd like to take a look at it and I'll just go ahead and upload it myself afterward. Just FYI, everything in the ftp site should be uploaded as the "updates" user, not root. Thanks. On Fri, Oct 10, 2014 at 10:46 AM, Tobias Pape wrote: > > On 10.10.2014, at 17:41, Chris Cunnington wrote: > >> I recall there was a problem with the All-In-One.[1] Craig made a new one. [2] It needs to replace the old one.[3]. Is that correct? >> >> Chris >> >> >> [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-September/180037.html >> >> [2] http://bit.ly/1CBwx1I >> [3] http://ftp.squeak.org/4.5/ > > Yes but we now must talk about how to handle all-in-ones. > When apple really no longer allow stuff besides the Contents/ directory, > it renders the whole thing moot. > Then we better > either distribute 3 individual files > or an unsigned all-in-one. > > > Best > -Tobias From brasspen at gmail.com Fri Oct 10 16:23:25 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Fri Oct 10 16:23:30 2014 Subject: [squeak-dev] Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> Message-ID: > On Oct 10, 2014, at 12:21 PM, Chris Muller wrote: > > We talked about it in last week's board meeting. We decided there is > merit to staying with an All-In-One but there was a discussion about > whether there should be shortcuts in the main directory for each > platform. There was representation for both sides of that question, > but the majority settled on including them. > > Chris C., since I was the 4.5 release manager, if you don't mind, > after Craig has time to put that together, I'd like to take a look at > it and I'll just go ahead and upload it myself afterward. No problem. *now bowing out* > Just FYI, > everything in the ftp site should be uploaded as the "updates" user, > not root. Good to know. Chris > > Thanks. > > On Fri, Oct 10, 2014 at 10:46 AM, Tobias Pape wrote: >> >> On 10.10.2014, at 17:41, Chris Cunnington wrote: >> >>> I recall there was a problem with the All-In-One.[1] Craig made a new one. [2] It needs to replace the old one.[3]. Is that correct? >>> >>> Chris >>> >>> >>> [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-September/180037.html >>> >>> [2] http://bit.ly/1CBwx1I >>> [3] http://ftp.squeak.org/4.5/ >> >> Yes but we now must talk about how to handle all-in-ones. >> When apple really no longer allow stuff besides the Contents/ directory, >> it renders the whole thing moot. >> Then we better >> either distribute 3 individual files >> or an unsigned all-in-one. >> >> >> Best >> -Tobias > From Das.Linux at gmx.de Fri Oct 10 16:45:27 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri Oct 10 16:45:40 2014 Subject: [squeak-dev] Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> Message-ID: <08E7039B-4686-4B35-AA6D-0B2842800A4F@gmx.de> On 10.10.2014, at 18:21, Chris Muller wrote: > We talked about it in last week's board meeting. We decided there is > merit to staying with an All-In-One but there was a discussion about > whether there should be shortcuts in the main directory for each > platform. From how I understood Craig, this won't work with a signed AIO. I would go for an unsigned one. Best -Tobias -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1625 bytes Desc: Message signed with OpenPGP using GPGMail Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141010/1d6bc68a/signature.pgp From craig at netjam.org Fri Oct 10 20:40:39 2014 From: craig at netjam.org (Craig Latta) Date: Fri Oct 10 20:40:54 2014 Subject: [squeak-dev] re: Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: <08E7039B-4686-4B35-AA6D-0B2842800A4F@gmx.de> References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> <08E7039B-4686-4B35-AA6D-0B2842800A4F@gmx.de> Message-ID: Hi-- Chris Muller> We talked about it in last week's board meeting. We Chris Muller> decided there is merit to staying with an All-In-One but Chris Muller> there was a discussion about whether there should be Chris Muller> shortcuts in the main directory for each platform. Tobias> From how I understood Craig, this won't work with a signed AIO. Tobias> I would go for an unsigned one. Chris is referring to a suggestion to create sibling files to the .app folder, each of which is a platform-dependent script that launches the app. E.g., on Linux you would put a Squeak4.5.app folder in /usr/local/bin (for example), there is a script /usr/local/bin/squeak4.5 which starts the app, and you include /usr/local/bin in your executable search paths. The "main directory" Chris mentions would be a new directory in the release artifact, containing the .app folder and the launch scripts. The suggestion had nothing to do with signatures, but rather with a longstanding complaint by a board member about having to descend into the .app folder to start the app on non-Mac platforms, no matter how deep (specifically, in .app as before, or, as I made it to work with Apple's new signing rules, .app/Contents/LinuxAndWindows). Personally, I make explicit Linux shell aliases and Windows shortcuts for launching each Squeak release I have. I have so many VMs floating around that I don't trust executable search paths to work correctly. Of course, it'd be better if those platforms would finally decide on a way of representing a self-contained app; it could just live anywhere in a filesystem, be found through search, and launched from the search interface. This is how I launch most apps on the Mac (from Spotlight). Anyway, we may as well continue signing the .app folder. -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From Das.Linux at gmx.de Fri Oct 10 20:58:15 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri Oct 10 20:58:23 2014 Subject: [squeak-dev] re: Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> <08E7039B-4686-4B35-AA6D-0B2842800A4F@gmx.de> Message-ID: Hi, On 10.10.2014, at 22:40, Craig Latta wrote: > > Hi-- > > Chris Muller> We talked about it in last week's board meeting. We > Chris Muller> decided there is merit to staying with an All-In-One but > Chris Muller> there was a discussion about whether there should be > Chris Muller> shortcuts in the main directory for each platform. > > Tobias> From how I understood Craig, this won't work with a signed AIO. > Tobias> I would go for an unsigned one. > > Chris is referring to a suggestion to create sibling files to the > .app folder, each of which is a platform-dependent script that launches > the app. E.g., on Linux you would put a Squeak4.5.app folder in > /usr/local/bin (for example), there is a script /usr/local/bin/squeak4.5 > which starts the app, and you include /usr/local/bin in your executable > search paths. The "main directory" Chris mentions would be a new > directory in the release artifact, containing the .app folder and the > launch scripts. > ugh, I wouldn't like that. but I am mostly a Mac user, so my vote doesn't really count here? Best -Tobias > The suggestion had nothing to do with signatures, but rather with a > longstanding complaint by a board member about having to descend into > the .app folder to start the app on non-Mac platforms, no matter how > deep (specifically, in .app as before, or, as I made it to work with > Apple's new signing rules, .app/Contents/LinuxAndWindows). > > Personally, I make explicit Linux shell aliases and Windows > shortcuts for launching each Squeak release I have. I have so many VMs > floating around that I don't trust executable search paths to work > correctly. Of course, it'd be better if those platforms would finally > decide on a way of representing a self-contained app; it could just live > anywhere in a filesystem, be found through search, and launched from the > search interface. This is how I launch most apps on the Mac (from > Spotlight). > > Anyway, we may as well continue signing the .app folder. > > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > > > From ma.chris.m at gmail.com Fri Oct 10 23:01:45 2014 From: ma.chris.m at gmail.com (Chris Muller (via Google Drive)) Date: Fri Oct 10 23:01:48 2014 Subject: [squeak-dev] Squeak-4.5-All-in-One.zip Message-ID: <001a11c2e4cc77ed7505051988e3@google.com> I've shared an item with you: Squeak-4.5-All-in-One.zip https://drive.google.com/file/d/0B3OQpyHgoVuxZTYtbXRKT1FNLWM/view?usp=sharing&invite=CNe6vnk It's not an attachment -- it's stored online. To open this item, just click the link above. Hi Craig, here's the All-In-One with the __MACOS removed and the Linux and Windows shortcuts added. Tedious! But, it seems to be one-click working on Linux and Windows. All that needs done is signing and verifying on Mac I guess, then I'll upload it and we'll be done. Thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141010/97ead5ab/attachment.htm From Das.Linux at gmx.de Fri Oct 10 23:29:49 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri Oct 10 23:29:56 2014 Subject: [squeak-dev] Squeak-4.5-All-in-One.zip In-Reply-To: <001a11c2e4cc77ed7505051988e3@google.com> References: <001a11c2e4cc77ed7505051988e3@google.com> Message-ID: <0CF3B86E-ADA2-4578-B8A8-A4DBAC1229AF@gmx.de> Hi chris, On 11.10.2014, at 01:01, Chris Muller (via Google Drive) wrote: > Chris Muller has shared the following file: > Squeak-4.5-All-in-One.zip > Hi Craig, here's the All-In-One with the __MACOS removed and the Linux and Windows shortcuts added. Tedious! But, it seems to be one-click working on Linux and Windows. All that needs done is signing and verifying on Mac I guess, then I'll upload it and we'll be done. The following things need fixing: 1. Please don't name the toplevel *.app anymore, it causes trouble to access the actual .app (including renaming is virtually impossible) 2. Strangely, Squeak-4.5-All-in-One.app/Contents/MacOS/Squeak is missing the execute permission and hence the app wont start at all. HTH Best -Tobias From asqueaker at gmail.com Fri Oct 10 23:36:04 2014 From: asqueaker at gmail.com (Chris Muller) Date: Fri Oct 10 23:36:09 2014 Subject: [squeak-dev] re: Running Squeak on Mac OS X fails due to damaged file - upload to the 4.5 directory? In-Reply-To: References: <6EF4732C-E2AB-451C-A800-C54D02912FF2@gmail.com> <3CA6255D-C388-4E31-9D7A-B8F16600EACB@gmx.de> <08E7039B-4686-4B35-AA6D-0B2842800A4F@gmx.de> Message-ID: > Chris Muller> We talked about it in last week's board meeting. We > Chris Muller> decided there is merit to staying with an All-In-One but > Chris Muller> there was a discussion about whether there should be > Chris Muller> shortcuts in the main directory for each platform. > > Tobias> From how I understood Craig, this won't work with a signed AIO. > Tobias> I would go for an unsigned one. > > Chris is referring to a suggestion to create sibling files to the > .app folder, each of which is a platform-dependent script that launches > the app. E.g., on Linux you would put a Squeak4.5.app folder in > /usr/local/bin (for example), there is a script /usr/local/bin/squeak4.5 > which starts the app, and you include /usr/local/bin in your executable > search paths. The "main directory" Chris mentions would be a new > directory in the release artifact, containing the .app folder and the > launch scripts. That's quite different than what I thought we were discussing in the meeting..? Maybe I was disconnected from what you and/or Eliot was talking about..? I thought the suggestion was simply to include two one-liner shortcuts as siblings to Squeak-4.5-All-in-One.app. (I actually would prefer them to be siblings of the Contents folder but I guess that's not an option due to Apple restrictions?) Since the shortcuts simply point to relative locatoins within the All-In-One, so there's no need to adjust paths for anything. The purpose of the All-In-One is to get newbies into Squeak with as little effort as possible. By the time they get to wanting to launch all different kinds of VM's they'll no longer be using the All-In-One. So, if we were speaking differnt languages in the meeting, hopefully you like this a little better. I sent you a link from the other email. Thanks Craig. > The suggestion had nothing to do with signatures, but rather with a > longstanding complaint by a board member about having to descend into > the .app folder to start the app on non-Mac platforms, no matter how > deep (specifically, in .app as before, or, as I made it to work with > Apple's new signing rules, .app/Contents/LinuxAndWindows). > > Personally, I make explicit Linux shell aliases and Windows > shortcuts for launching each Squeak release I have. I have so many VMs > floating around that I don't trust executable search paths to work > correctly. Of course, it'd be better if those platforms would finally > decide on a way of representing a self-contained app; it could just live > anywhere in a filesystem, be found through search, and launched from the > search interface. This is how I launch most apps on the Mac (from > Spotlight). > Anyway, we may as well continue signing the .app folder. > > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > > > From tim at rowledge.org Sat Oct 11 03:37:24 2014 From: tim at rowledge.org (tim Rowledge) Date: Sat Oct 11 03:37:33 2014 Subject: [squeak-dev] Form>asFormOfDepth: appears to break transparency Message-ID: I have Form of 16bpp, which results from rotating a ColorForm with WarpBlt. This 16bpp form displays ?properly? when painted onto another form such as the Display. So far so good. If I run it through my Scratch filters (which do fun things like colour warping, whirling and pixellating) it all goes horribly wrong; the once transparent areas are now solid black instead. This makes me very sad :-( The culprit appears to be #asFormOfDepth: and in particular the recently added (ok, 2008 vintage) fiddle to stuff 16rFF into the top byte of each pixel. I kinda see the logic of this newfangled bit poking but suspect that it needs to be done a touch more cleverly and should avoid pixels where transparency is expected. Or maybe the bitblt code for paint needs some futzing? Anybody feeling familiar with this stuff and able to explain it a bit more? tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Sentio aliquos togatos contra me conspirare = I think some people in togas are plotting against me. From juanlists at jvuletich.org Sat Oct 11 12:00:43 2014 From: juanlists at jvuletich.org (J. Vuletich (mail lists)) Date: Sat Oct 11 12:00:48 2014 Subject: [squeak-dev] Form>asFormOfDepth: appears to break transparency In-Reply-To: References: Message-ID: <20141011120043.Horde.3TEQfVQmNil3IPASUCWqnQ6@gator3294.hostgator.com> Hi Tim, What do you get if you evaluate: f _ Form extent: 8@8 depth: 16. f32 _ f asFormOfDepth: 32. {f colorAt: 1@1. f32 colorAt: 1@1 } If you get transparent twice, then the problem is not in #formOfDepth:, but in your Scratch filters... If that is the case, an alternative to fixing them to support 16bpp would be to do all the stuff in 32bpp. Can you prepare an image for us to try? It would help us give better answers. Cheers, Juan Vuletich Quoting tim Rowledge : > I have Form of 16bpp, which results from rotating a ColorForm with > WarpBlt. This 16bpp form displays ?properly? when painted onto > another form such as the Display. So far so good. > > If I run it through my Scratch filters (which do fun things like > colour warping, whirling and pixellating) it all goes horribly > wrong; the once transparent areas are now solid black instead. This > makes me very sad :-( > > The culprit appears to be #asFormOfDepth: and in particular the > recently added (ok, 2008 vintage) fiddle to stuff 16rFF into the top > byte of each pixel. I kinda see the logic of this newfangled bit > poking but suspect that it needs to be done a touch more cleverly > and should avoid pixels where transparency is expected. Or maybe the > bitblt code for paint needs some futzing? > > Anybody feeling familiar with this stuff and able to explain it a bit more? > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Useful Latin Phrases:- Sentio aliquos togatos contra me conspirare = > I think some people in togas are plotting against me. From asqueaker at gmail.com Sat Oct 11 16:54:53 2014 From: asqueaker at gmail.com (Chris Muller) Date: Sat Oct 11 16:54:56 2014 Subject: [squeak-dev] Squeak-4.5-All-in-One.zip In-Reply-To: <0CF3B86E-ADA2-4578-B8A8-A4DBAC1229AF@gmx.de> References: <001a11c2e4cc77ed7505051988e3@google.com> <0CF3B86E-ADA2-4578-B8A8-A4DBAC1229AF@gmx.de> Message-ID: On Fri, Oct 10, 2014 at 6:29 PM, Tobias Pape wrote: > Hi chris, > On 11.10.2014, at 01:01, Chris Muller (via Google Drive) wrote: > >> Chris Muller has shared the following file: >> Squeak-4.5-All-in-One.zip >> Hi Craig, here's the All-In-One with the __MACOS removed and the Linux and Windows shortcuts added. Tedious! But, it seems to be one-click working on Linux and Windows. All that needs done is signing and verifying on Mac I guess, then I'll upload it and we'll be done. > > The following things need fixing: > > 1. Please don't name the toplevel *.app anymore, it causes trouble > to access the actual .app (including renaming is virtually impossible) What should it be named? In fact, can we get rid of the top level altogether? Because otherwise we end up with is a structure that's 3 levels deep for no organizational reason (but maybe required to work on crApple?). IOW, could we simply have this as the the root of the zip? Squeak-4.5-All-in-One.app squeak.bat squeak.sh ? If not, please suggest a name for the root root folder. > 2. Strangely, Squeak-4.5-All-in-One.app/Contents/MacOS/Squeak is missing the > execute permission and hence the app wont start at all. Not strange, because when I was testing in Windows, there were some issues which, after fixing, had to re-zip it but Windows is oblivious to Linux file-permissions. So after transferring it back to a Linux machine and testing I noticed the file-permissions and individually fixed execute bit on 3 or 4 files for Linux, but ignored Apple. I'll fix that for the next version, but please give me your input on the question above first. Thanks! From Das.Linux at gmx.de Sat Oct 11 17:41:22 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Sat Oct 11 17:41:36 2014 Subject: [squeak-dev] Squeak-4.5-All-in-One.zip In-Reply-To: References: <001a11c2e4cc77ed7505051988e3@google.com> <0CF3B86E-ADA2-4578-B8A8-A4DBAC1229AF@gmx.de> Message-ID: <6E856244-4122-4FB4-967A-BE50CDE07A2F@gmx.de> Hey, On 11.10.2014, at 18:54, Chris Muller wrote: > On Fri, Oct 10, 2014 at 6:29 PM, Tobias Pape wrote: >> Hi chris, >> On 11.10.2014, at 01:01, Chris Muller (via Google Drive) wrote: >> >>> Chris Muller has shared the following file: >>> Squeak-4.5-All-in-One.zip >>> Hi Craig, here's the All-In-One with the __MACOS removed and the Linux and Windows shortcuts added. Tedious! But, it seems to be one-click working on Linux and Windows. All that needs done is signing and verifying on Mac I guess, then I'll upload it and we'll be done. >> >> The following things need fixing: >> >> 1. Please don't name the toplevel *.app anymore, it causes trouble >> to access the actual .app (including renaming is virtually impossible) > > What should it be named? In fact, can we get rid of the top level > altogether? Because otherwise we end up with is a structure that's 3 > levels deep for no organizational reason (but maybe required to work > on crApple?). > > IOW, could we simply have this as the the root of the zip? > > Squeak-4.5-All-in-One.app > squeak.bat > squeak.sh > Yes, this can work. Most zip programs would create a parent folder anyway. > ? If not, please suggest a name for the root root folder. > >> 2. Strangely, Squeak-4.5-All-in-One.app/Contents/MacOS/Squeak is missing the >> execute permission and hence the app wont start at all. > > Not strange, because when I was testing in Windows, there were some > issues which, after fixing, had to re-zip it but Windows is oblivious > to Linux file-permissions. So after transferring it back to a Linux > machine and testing I noticed the file-permissions and individually > fixed execute bit on 3 or 4 files for Linux, but ignored Apple. I'll > fix that for the next version, but please give me your input on the > question above first. Ok. I don't know, but probably packing on linux is better, because there are other files that have to be executable (all the plugins for Linux and OS X) and others that should better be not (but this is not crucial). Best -Tobias From tim at rowledge.org Sat Oct 11 17:54:09 2014 From: tim at rowledge.org (tim Rowledge) Date: Sat Oct 11 17:54:16 2014 Subject: [squeak-dev] Form>asFormOfDepth: appears to break transparency In-Reply-To: <20141011120043.Horde.3TEQfVQmNil3IPASUCWqnQ6@gator3294.hostgator.com> References: <20141011120043.Horde.3TEQfVQmNil3IPASUCWqnQ6@gator3294.hostgator.com> Message-ID: On 11-10-2014, at 5:00 AM, J. Vuletich (mail lists) wrote: > > What do you get if you evaluate: > > f _ Form extent: 8@8 depth: 16. > f32 _ f asFormOfDepth: 32. > {f colorAt: 1@1. f32 colorAt: 1@1 } > > If you get transparent twice, then the problem is not in #formOfDepth:, but in your Scratch filters... If that is the case, an alternative to fixing them to support 16bpp would be to do all the stuff in 32bpp. I get transparent in both cases, but a) this is done *before* the scratch filtering in order to make 32bpp forms because the plugin code to do swirlies etc only handles 32bpp. (I?d love to alter this; a move to using 16bpp everywhere in Scratch would benefit the Pi greatly since it is frequently memory bus bound) b) inspect the two bitmaps; you?ll see that the 8bpp one has 0s but the 32bpp has 16rFF000000s. c) display each of them with ?paint? and you?ll notice that the 32bpp one is black and the 8bpp one is invisible |f f32| f := Form extent: 8@8 depth: 16. f32 := f asFormOfDepth: 32. f displayOn: Display at: 500@10 rule: Form paint. f32 displayOn: Display at: 510@10 rule: Form paint. {f . f32 } Inspect that to see what I mean. If I use a hacked asFormOfDepth: that does not do the alpha channel ?fixing? then both Forms are transparent. This doesn?t surprise me much since that is what asFormOfDepth: did in Squeak in the ancient days when Scratch was first written by scraping tiny symbols on polished stone slabs. > > Can you prepare an image for us to try? It would help us give better answers. No need, since this is not stuff I?ve changed (At least.. not knowingly. Always a chance I?ve screwed something up somewhere, of course) However, the image is available from https://github.com/raspberrypi/scratch/blob/master/NuScratchBeta10.tgz in a package which includes the Pi vm etc. Just shift-click on the top half of the ?R? in the Scratch logo and ?turn fill screen off? to get to the desktop. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Romani quidem artem amatoriam invenerunt. = You know, the Romans invented the art of love. From juanlists at jvuletich.org Sat Oct 11 19:23:52 2014 From: juanlists at jvuletich.org (J. Vuletich (mail lists)) Date: Sat Oct 11 19:23:55 2014 Subject: [squeak-dev] Form>asFormOfDepth: appears to break transparency In-Reply-To: References: <20141011120043.Horde.3TEQfVQmNil3IPASUCWqnQ6@gator3294.hostgator.com> Message-ID: <20141011192352.Horde.ukHOYaus3TAAOisbGu8BOQ1@gator3294.hostgator.com> Hi Tim, Yes. In Squeak there is a bug in #asFormOfDepth: . The last lines are: "Special case: For a 16 -> 32 bit conversion fill the alpha channel because it gets lost in translation." (self depth = 16 and:[d= 32]) ifTrue:[newForm fillAlpha: 255]. But they should be as in Cuis: "If we build a 32bpp from one of smaller depth, it will have zero in the alpha channel (until BitBlt is fixed!)" d = 32 ifTrue: [ newForm fixAlpha ]. I think this should fix your problem. Besides, the sample code I sent gets transparent, although the stuff in the Form, 16rFF000000, is opaque black. This is because of another bug, this one at #colorFromPixelValue:depth: . I suggest taking the code verbatim from Cuis. Cheers, Juan Vuletich Quoting tim Rowledge : > On 11-10-2014, at 5:00 AM, J. Vuletich (mail lists) > wrote: >> >> What do you get if you evaluate: >> >> f _ Form extent: 8@8 depth: 16. >> f32 _ f asFormOfDepth: 32. >> {f colorAt: 1@1. f32 colorAt: 1@1 } >> >> If you get transparent twice, then the problem is not in >> #formOfDepth:, but in your Scratch filters... If that is the case, >> an alternative to fixing them to support 16bpp would be to do all >> the stuff in 32bpp. > > I get transparent in both cases, but > a) this is done *before* the scratch filtering in order to make > 32bpp forms because the plugin code to do swirlies etc only handles > 32bpp. (I?d love to alter this; a move to using 16bpp everywhere in > Scratch would benefit the Pi greatly since it is frequently memory > bus bound) > b) inspect the two bitmaps; you?ll see that the 8bpp one has 0s but > the 32bpp has 16rFF000000s. > c) display each of them with ?paint? and you?ll notice that the > 32bpp one is black and the 8bpp one is invisible > > |f f32| > f := Form extent: 8@8 depth: 16. > f32 := f asFormOfDepth: 32. > f displayOn: Display at: 500@10 rule: Form paint. > f32 displayOn: Display at: 510@10 rule: Form paint. > {f . f32 } > > Inspect that to see what I mean. > > If I use a hacked asFormOfDepth: that does not do the alpha channel > ?fixing? then both Forms are transparent. This doesn?t surprise me > much since that is what asFormOfDepth: did in Squeak in the ancient > days when Scratch was first written by scraping tiny symbols on > polished stone slabs. > >> >> Can you prepare an image for us to try? It would help us give >> better answers. > > No need, since this is not stuff I?ve changed (At least.. not > knowingly. Always a chance I?ve screwed something up somewhere, of > course) > However, the image is available from > https://github.com/raspberrypi/scratch/blob/master/NuScratchBeta10.tgz in a > package which includes the Pi vm etc. Just shift-click on the top > half of the ?R? in the Scratch logo and ?turn fill screen off? to > get to the desktop. > > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Useful Latin Phrases:- Romani quidem artem amatoriam invenerunt. = > You know, the Romans invented the art of love. From ma.chris.m at gmail.com Sat Oct 11 22:03:05 2014 From: ma.chris.m at gmail.com (Chris Muller (via Google Drive)) Date: Sat Oct 11 22:03:09 2014 Subject: [squeak-dev] Squeak-4.5-All-In-One.zip Message-ID: <20cf303b3ba57d3d1805052cd468@google.com> I've shared an item with you: Squeak-4.5-All-In-One.zip https://drive.google.com/file/d/0B3OQpyHgoVuxT2d5TV9xMVF0bDA/view?usp=sharing&invite=CKa24aIJ It's not an attachment -- it's stored online. To open this item, just click the link above. Okay, I went back to the one in Craig's dropbox to preserve all the file permissions, then simply re-fixed the squeak.ini and added in the two shortcuts. Tested on Linux and Windows, just need Mac signing and testing. Thanks again. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141011/328b3378/attachment.htm From craig at netjam.org Sat Oct 11 23:44:33 2014 From: craig at netjam.org (Craig Latta) Date: Sat Oct 11 23:44:44 2014 Subject: [squeak-dev] re: Squeak-4.5-All-In-One.zip In-Reply-To: <20cf303b3ba57d3d1805052cd468@google.com> References: <20cf303b3ba57d3d1805052cd468@google.com> Message-ID: <5439C0E1.2040600@netjam.org> > ...just need Mac signing and testing. Okay, tested on Linux, Windows, and Mac, and Apple-signed. http://bit.ly/1s5VkpV (Dropbox). -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From tim at rowledge.org Sun Oct 12 05:49:30 2014 From: tim at rowledge.org (tim Rowledge) Date: Sun Oct 12 05:49:39 2014 Subject: [squeak-dev] Form>asFormOfDepth: appears to break transparency In-Reply-To: <20141011192352.Horde.ukHOYaus3TAAOisbGu8BOQ1@gator3294.hostgator.com> References: <20141011120043.Horde.3TEQfVQmNil3IPASUCWqnQ6@gator3294.hostgator.com> <20141011192352.Horde.ukHOYaus3TAAOisbGu8BOQ1@gator3294.hostgator.com> Message-ID: <6B03485D-E88B-41ED-A13E-2D4465AE5B3B@rowledge.org> On 11-10-2014, at 12:23 PM, J. Vuletich (mail lists) wrote: > Yes. In Squeak there is a bug in #asFormOfDepth: . The last lines are: > > "Special case: For a 16 -> 32 bit conversion fill the alpha channel because it gets lost in translation." > (self depth = 16 and:[d= 32]) ifTrue:[newForm fillAlpha: 255]. > > But they should be as in Cuis: > > "If we build a 32bpp from one of smaller depth, > it will have zero in the alpha channel (until BitBlt is fixed!)" > d = 32 ifTrue: [ > newForm fixAlpha ]. > > I think this should fix your problem. Yup. Given that there is a bitblt rule specifically to fix this problem, and a method specifically provided to use said bitblt to specifically fix this problem, I?m more than a bit puzzled as to why the most important bit of code (to be specific) in the image that needs this specific bit of code, doesn?t, specifically, have it. Even weirder is that Andreas wrote it and five years later carefully rewrote asFormOfDepth: to deal with this problem *and didn?t use his own careful fix*. > > Besides, the sample code I sent gets transparent, although the stuff in the Form, 16rFF000000, is opaque black. This is because of another bug, this one at #colorFromPixelValue:depth: . I suggest taking the code verbatim from Cuis. Probably a good idea. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Can't find log base two of 65536 without a calculator. From leves at elte.hu Sun Oct 12 06:04:33 2014 From: leves at elte.hu (Levente Uzonyi) Date: Sun Oct 12 06:04:38 2014 Subject: [squeak-dev] Questions about external objects Message-ID: Hi, I found that the handling of external objects is suboptimal in the image, and I came up with some ideas to make it better. I have a working solution in my image, but it can be even better. It seems to me that only Semaphores are stored in the external objects array (slot 39 in the special objects array), but in practice any object can be stored there. Does it make sense to support objects of any other kind? If not, then the code could be simplified. I also thought that I'll create a special semaphore (ExternalSemaphore - which is a subclass of Semaphore) that knows its own index in the external objects array. This could be really handy for finding the object in the array, but the VM is not willing to signal these semaphores in the external objects array. I thought that this is because the VM doesn't know anything about this class. So I tried to change Semaphore itself, but after the change the VM refused to signal any semaphores in the external objects array. Changing the class back to the original didn't help either. Without looking at the VM code, I assumed that the VM will signal anything which has the class in the 19th slot of the special objects array, but that doesn't seem to be the case. Is there any way to make this (add an instatnce variable to Semaphore and still get signals from the VM, or use instances of a subclass of Semaphore there) work? Levente From bert at freudenbergs.de Sun Oct 12 11:50:33 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Sun Oct 12 11:50:38 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: Message-ID: On 12.10.2014, at 08:04, Levente Uzonyi wrote: > Hi, > > I found that the handling of external objects is suboptimal in the image, and I came up with some ideas to make it better. I have a working solution in my image, but it can be even better. > > It seems to me that only Semaphores are stored in the external objects array (slot 39 in the special objects array), but in practice any object can be stored there. Does it make sense to support objects of any other kind? If not, then the code could be simplified. Currently the VM uses the ExternalObjectsArray only for semaphores. Other objects use different mechanisms (e.g. SurfacePlugin for external forms). I'm not sure if there is a good use case for storing non-semaphores in ExternalObjectsArray, maybe ask on the vm-dev list? > I also thought that I'll create a special semaphore (ExternalSemaphore - > which is a subclass of Semaphore) that knows its own index in the external objects array. This could be really handy for finding the object in the array, but the VM is not willing to signal these semaphores in the external objects array. I thought that this is because the VM doesn't know anything about this class. > So I tried to change Semaphore itself, but after the change the VM refused to signal any semaphores in the external objects array. Changing the class back to the original didn't help either. Without looking at the VM code, I assumed that the VM will signal anything which has the class in the 19th slot of the special objects array, but that doesn't seem to be the case. > Is there any way to make this (add an instatnce variable to Semaphore and still get signals from the VM, or use instances of a subclass of Semaphore there) work? The VM only checks for the exact class in slot 19, not for subclasses. Adding an inst var to Semaphore itself should be fine, but you cannot use a subclass without changing the VM. Are you sure you put the modified Semaphore class into SpecialObjectsArray after adding the inst var? - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141012/a1bca4a6/smime.bin From juanlists at jvuletich.org Sun Oct 12 13:01:48 2014 From: juanlists at jvuletich.org (J. Vuletich (mail lists)) Date: Sun Oct 12 13:01:52 2014 Subject: [squeak-dev] Form>asFormOfDepth: appears to break transparency In-Reply-To: <6B03485D-E88B-41ED-A13E-2D4465AE5B3B@rowledge.org> References: <20141011120043.Horde.3TEQfVQmNil3IPASUCWqnQ6@gator3294.hostgator.com> <20141011192352.Horde.ukHOYaus3TAAOisbGu8BOQ1@gator3294.hostgator.com> <6B03485D-E88B-41ED-A13E-2D4465AE5B3B@rowledge.org> Message-ID: <20141012130148.Horde.58iyVuvzYjwpoSbPm34_2A4@gator3294.hostgator.com> Quoting tim Rowledge : > On 11-10-2014, at 12:23 PM, J. Vuletich (mail lists) > wrote: >> Yes. In Squeak there is a bug in #asFormOfDepth: . The last lines are: >> >> "Special case: For a 16 -> 32 bit conversion fill the alpha >> channel because it gets lost in translation." >> (self depth = 16 and:[d= 32]) ifTrue:[newForm fillAlpha: 255]. >> >> But they should be as in Cuis: >> >> "If we build a 32bpp from one of smaller depth, >> it will have zero in the alpha channel (until BitBlt is fixed!)" >> d = 32 ifTrue: [ >> newForm fixAlpha ]. >> >> I think this should fix your problem. > > Yup. Given that there is a bitblt rule specifically to fix this > problem, and a method specifically provided to use said bitblt to > specifically fix this problem, I?m more than a bit puzzled as to why > the most important bit of code (to be specific) in the image that > needs this specific bit of code, doesn?t, specifically, have it. > Even weirder is that Andreas wrote it and five years later carefully > rewrote asFormOfDepth: to deal with this problem *and didn?t use his > own careful fix*. Yes. I'm puzzled too. Anybody can shed some light on this? In any case, the Cuis way works. >> >> Besides, the sample code I sent gets transparent, although the >> stuff in the Form, 16rFF000000, is opaque black. This is because of >> another bug, this one at #colorFromPixelValue:depth: . I suggest >> taking the code verbatim from Cuis. > > Probably a good idea. > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Useful random insult:- Can't find log base two of 65536 without a calculator. Cheers, Juan Vuletich From karlramberg at gmail.com Sun Oct 12 14:32:38 2014 From: karlramberg at gmail.com (karl ramberg) Date: Sun Oct 12 14:32:42 2014 Subject: [squeak-dev] Re: [Vm-dev] New Cog VMs available In-Reply-To: References: Message-ID: Skipped content of type multipart/alternative-------------- next part -------------- A non-text attachment was scrubbed... Name: crash.dmp Type: application/octet-stream Size: 18376 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141012/6da0e2c6/crash.obj From Das.Linux at gmx.de Sun Oct 12 17:34:16 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Sun Oct 12 17:34:24 2014 Subject: [squeak-dev] re: Squeak-4.5-All-In-One.zip In-Reply-To: <5439C0E1.2040600@netjam.org> References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> Message-ID: <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Hi Craig On 12.10.2014, at 01:44, Craig Latta wrote: >> ...just need Mac signing and testing. > > Okay, tested on Linux, Windows, and Mac, and Apple-signed. > > http://bit.ly/1s5VkpV (Dropbox). The app does not run for me: $ spctl -a -t exec -vv Squeak-4.5-All-in-One.app Squeak-4.5-All-in-One.app: rejected source=no usable signature could that have to do with changes in 10.9.5[1]? Best -Tobias [1]: https://developer.apple.com/library/mac/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG205 From tim at rowledge.org Sun Oct 12 18:09:44 2014 From: tim at rowledge.org (tim Rowledge) Date: Sun Oct 12 18:09:51 2014 Subject: [squeak-dev] VanIsle CampSmalltalk 3rd - 5th October 2014 In-Reply-To: <541AC259.2040206@shingarov.com> References: <541AC259.2040206@shingarov.com> Message-ID: Camp Smalltalk 2014 is over and I think the general conclusion was that it was Jolly Good. I?ll leave it to other 20 plus attendees to pass opinions and just describe a little of what went on. The event was held at the Makerspace Nanaimo facility and we had plenty of room, comfy chairs, plenty of food and drinks, a nice projector, and 24/7 access. I think everybody considered it a really good place to hold the camp. We got fabulous support from the Makerspace and they?re (I should say ?we? since I?m a member too!) looking forward to doing it again. People arrived as early as the Thursday and several stayed until late Monday. Most of the action was on Friday/Saturday/Sunday - including the excitement on Saturday of the Makerspace open house mixed with our stuff. That might seem like a recipe for disaster but it had the big benefit for Makerspace of showing off how a very young organisation could host an international conference in a small town that is very keen to make a name. The mayor and several councillors were visibly surprised and impressed. Having the open house also had the side benefit of a pretty damn good bbq being fired up and free burgers and dogs provided. We kept the formal schedule light, with a few opportunities for talks but mostly just groups self-organising to discuss projects, problems and other news. During the Makerspace event a bunch of people decamped to a lecture hall at the local university to take advantage of higher bandwidth so that a Terf conference could be used. We kept a laptop logged into that displaying on the projector at Makerspace and it was a source of quite a bit of interest. People were quite amazed that we could have attendees from all over the west coast and Canada plus bring in people from Europe and the Moon via the network. Oh, wait, we don?t have that Moon base yet? Damn. In the evenings we sampled the delights of Nanaimo?s nightlife, which turned out to be fairly nice. Gina?s Mexican restaurant did us very well on very short notice, people enjoyed Fibber Magee?s pub fare (some enjoyed an awful lot of the liquid sustenance too) and on Sunday we got very well fed for brunch at the Coast Bastion and later at Beefeater?s. Right now we?re seriously considering trying to do this again in 6 months or so. It was *that much* fun. tim PS - I know not every attendee reads this list, so feel free to forward this to any other list of relevance -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim For every action, there is an equal and opposite criticism. From craig at netjam.org Sun Oct 12 20:08:01 2014 From: craig at netjam.org (Craig Latta) Date: Sun Oct 12 20:08:15 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: > The app does not run for me: > > $ spctl -a -t exec -vv Squeak-4.5-All-in-One.app > Squeak-4.5-All-in-One.app: rejected > source=no usable signature > > could that have to do with changes in 10.9.5? Hm, I don't have an older MacOS to check when this started, but the situation with regard to creating and expanding ZIP archives without messing with the signature/contents correlation has become annoying (as I thought it might). For the signature to be valid, the .app directory has to be compressed and uncompressed by itself (no siblings), and it has to be done with the Mac Finder GUI (not from zip/unzip on the command line, in either MacOS or another OS that has access to the filesystem). So... the release is now a ZIP archive that contains the two non-Mac launch scripts, along with another ZIP archive which contains the .app directory. This also means that non-Mac users will get the "__MAC" and ".DS_Store" debris after uncompressing, as well. I still think all this is tolerable. However, I'll say again here that I strongly prefer having the .app directory be the root of our release artifact, a totally self-contained thing, and leaving it to users to set up launch shortcuts appropriate to their local system (given a directory structure that is obvious enough for them to realize how to do it). When the release has other stuff at a sibling or higher level than the .app directory, I think people are more likely to think, mistakenly, that they can duplicate, copy, rename, and move things around without breaking them. I realize I disagree with the 4.5 release manager (Chris) on this, but I still want to be on record. New bits at [1]. thanks, -C [1] http://bit.ly/1CBwx1I (Dropbox) -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From eliot.miranda at gmail.com Mon Oct 13 01:12:00 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 13 01:12:04 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: Hi Craig, On Sun, Oct 12, 2014 at 1:08 PM, Craig Latta wrote: > > > The app does not run for me: > > > > $ spctl -a -t exec -vv Squeak-4.5-All-in-One.app > > Squeak-4.5-All-in-One.app: rejected > > source=no usable signature > > > > could that have to do with changes in 10.9.5? > > Hm, I don't have an older MacOS to check when this started, but the > situation with regard to creating and expanding ZIP archives without > messing with the signature/contents correlation has become annoying (as > I thought it might). > I have a 10.6.8 machine. I'm checking this now. For the signature to be valid, the .app directory has to be > compressed and uncompressed by itself (no siblings), and it has to be > done with the Mac Finder GUI (not from zip/unzip on the command line, in > either MacOS or another OS that has access to the filesystem). > Why uncompressed by itself? If one uncompresses an archive containing a foo.app with a bar sibling, that will surely produce exactly the same bits in foo.app as uncompressing an archive that contains only foo.app. The decompression program would be broken if it creates different bits, right? So... If the archive is created in two steps, the first as you state including only Squeak-4.5-All-in-One.app, using the finder, and then, via the command line using zip -u to add the siblings how can that not work? It can't produce a different Squeak-4.5-All-in-One.app without zip being hopelessly broken, which it isn't, right? > > So... the release is now a ZIP archive that contains the two > non-Mac launch scripts, along with another ZIP archive which contains > the .app directory. This also means that non-Mac users will get the > "__MAC" and ".DS_Store" debris after uncompressing, as well. > It doesn't have to be this way. Use zip -u to add the siblings at a later date. > I still think all this is tolerable. However, I'll say again here > that I strongly prefer having the .app directory be the root of our > release artifact, a totally self-contained thing, and leaving it to > users to set up launch shortcuts appropriate to their local system > (given a directory structure that is obvious enough for them to realize > how to do it). Craig, you are a decent human being, but your attitude on this is so discourteous to users. Why *should* they have to unpack and decode the structure of a .app, especially when they might be WIndows or Linux users only. Why don't you see it as an obligation to provide a pleasant and simple install step to that community rather than asking them to perform a manual step? I don't understand. I want to go on record therefore that I think providing the scripts is important, especially for newbies, a group we surely want to appeal to. When the release has other stuff at a sibling or higher > level than the .app directory, I think people are more likely to think, > mistakenly, that they can duplicate, copy, rename, and move things > around without breaking them. I realize I disagree with the 4.5 release > manager (Chris) on this, but I still want to be on record. > > New bits at [1]. > > > thanks, > > -C > > [1] http://bit.ly/1CBwx1I (Dropbox) > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141012/2015f861/attachment.htm From eliot.miranda at gmail.com Mon Oct 13 01:14:17 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 13 01:14:20 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: On Sun, Oct 12, 2014 at 6:12 PM, Eliot Miranda wrote: > Hi Craig, > > On Sun, Oct 12, 2014 at 1:08 PM, Craig Latta wrote: > >> >> > The app does not run for me: >> > >> > $ spctl -a -t exec -vv Squeak-4.5-All-in-One.app >> > Squeak-4.5-All-in-One.app: rejected >> > source=no usable signature >> > >> > could that have to do with changes in 10.9.5? >> >> Hm, I don't have an older MacOS to check when this started, but the >> situation with regard to creating and expanding ZIP archives without >> messing with the signature/contents correlation has become annoying (as >> I thought it might). >> > > I have a 10.6.8 machine. I'm checking this now. > and the app runs just fine on 10.6.8. > > For the signature to be valid, the .app directory has to be >> compressed and uncompressed by itself (no siblings), and it has to be >> done with the Mac Finder GUI (not from zip/unzip on the command line, in >> either MacOS or another OS that has access to the filesystem). >> > > Why uncompressed by itself? If one uncompresses an archive containing a > foo.app with a bar sibling, that will surely produce exactly the same bits > in foo.app as uncompressing an archive that contains only foo.app. The > decompression program would be broken if it creates different bits, right? > So... > > If the archive is created in two steps, the first as you state including > only Squeak-4.5-All-in-One.app, using the finder, and then, via the command > line using zip -u to add the siblings how can that not work? It can't > produce a different Squeak-4.5-All-in-One.app without zip being hopelessly > broken, which it isn't, right? > > >> >> So... the release is now a ZIP archive that contains the two >> non-Mac launch scripts, along with another ZIP archive which contains >> the .app directory. This also means that non-Mac users will get the >> "__MAC" and ".DS_Store" debris after uncompressing, as well. >> > > It doesn't have to be this way. Use zip -u to add the siblings at a later > date. > > >> I still think all this is tolerable. However, I'll say again here >> that I strongly prefer having the .app directory be the root of our >> release artifact, a totally self-contained thing, and leaving it to >> users to set up launch shortcuts appropriate to their local system >> (given a directory structure that is obvious enough for them to realize >> how to do it). > > > Craig, you are a decent human being, but your attitude on this is so > discourteous to users. Why *should* they have to unpack and decode the > structure of a .app, especially when they might be WIndows or Linux users > only. Why don't you see it as an obligation to provide a pleasant and > simple install step to that community rather than asking them to perform a > manual step? I don't understand. I want to go on record therefore that I > think providing the scripts is important, especially for newbies, a group > we surely want to appeal to. > > When the release has other stuff at a sibling or higher >> level than the .app directory, I think people are more likely to think, >> mistakenly, that they can duplicate, copy, rename, and move things >> around without breaking them. I realize I disagree with the 4.5 release >> manager (Chris) on this, but I still want to be on record. >> >> New bits at [1]. >> >> >> thanks, >> >> -C >> >> [1] http://bit.ly/1CBwx1I (Dropbox) >> >> -- >> Craig Latta >> netjam.org >> +31 6 2757 7177 (SMS ok) >> + 1 415 287 3547 (no SMS) >> >> >> > > > -- > best, > Eliot > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141012/ca468758/attachment.htm From Das.Linux at gmx.de Mon Oct 13 08:21:50 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon Oct 13 08:21:56 2014 Subject: [squeak-dev] Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: On 13.10.2014, at 03:14, Eliot Miranda wrote: > On Sun, Oct 12, 2014 at 6:12 PM, Eliot Miranda wrote: > Hi Craig, > > On Sun, Oct 12, 2014 at 1:08 PM, Craig Latta wrote: > > > The app does not run for me: > > > > $ spctl -a -t exec -vv Squeak-4.5-All-in-One.app > > Squeak-4.5-All-in-One.app: rejected > > source=no usable signature > > > > could that have to do with changes in 10.9.5? > > Hm, I don't have an older MacOS to check when this started, but the > situation with regard to creating and expanding ZIP archives without > messing with the signature/contents correlation has become annoying (as > I thought it might). > > I have a 10.6.8 machine. I'm checking this now. > > and the app runs just fine on 10.6.8. Then it might be a ?version 1 vs Version 2 signature? as in the Apple note... > > > For the signature to be valid, the .app directory has to be > compressed and uncompressed by itself (no siblings), and it has to be > done with the Mac Finder GUI (not from zip/unzip on the command line, in > either MacOS or another OS that has access to the filesystem). > > Why uncompressed by itself? If one uncompresses an archive containing a foo.app with a bar sibling, that will surely produce exactly the same bits in foo.app as uncompressing an archive that contains only foo.app. The decompression program would be broken if it creates different bits, right? So... > > If the archive is created in two steps, the first as you state including only Squeak-4.5-All-in-One.app, using the finder, and then, via the command line using zip -u to add the siblings how can that not work? It can't produce a different Squeak-4.5-All-in-One.app without zip being hopelessly broken, which it isn't, right? > > > So... the release is now a ZIP archive that contains the two > non-Mac launch scripts, along with another ZIP archive which contains > the .app directory. This also means that non-Mac users will get the > "__MAC" and ".DS_Store" debris after uncompressing, as well. > > It doesn't have to be this way. Use zip -u to add the siblings at a later date. > > > I still think all this is tolerable. However, I'll say again here > that I strongly prefer having the .app directory be the root of our > release artifact, a totally self-contained thing, and leaving it to > users to set up launch shortcuts appropriate to their local system > (given a directory structure that is obvious enough for them to realize > how to do it). > > Craig, you are a decent human being, but your attitude on this is so discourteous to users. Why *should* they have to unpack and decode the structure of a .app, especially when they might be WIndows or Linux users only. Why don't you see it as an obligation to provide a pleasant and simple install step to that community rather than asking them to perform a manual step? I don't understand. I want to go on record therefore that I think providing the scripts is important, especially for newbies, a group we surely want to appeal to. > > When the release has other stuff at a sibling or higher > level than the .app directory, I think people are more likely to think, > mistakenly, that they can duplicate, copy, rename, and move things > around without breaking them. I realize I disagree with the 4.5 release > manager (Chris) on this, but I still want to be on record. > > New bits at [1]. > > > thanks, > > -C > > [1] http://bit.ly/1CBwx1I (Dropbox) From stephan at stack.nl Mon Oct 13 09:15:28 2014 From: stephan at stack.nl (Stephan Eggermont) Date: Mon Oct 13 09:15:47 2014 Subject: [squeak-dev] Smalltalk Devroom at FOSDEM 2015: Call for Participation Message-ID: Call for Participation in the Smalltalk Devroom at FOSDEM 2015. http://www.fosdem.org, please forward " A devroom for the Pharo, Squeak, Amber, GST, Etoil?, Seaside, Moose Smalltalk projects & Objective Smalltalk and Newspeak as derived languages. Smalltalk environments offer a very high development productivity, unmatched by their successors. Come do some pair programming with us and experience yourself the advantages of a real OO environment" The meetup will take place Sunday, February 1, 2015, room S.H.2214. This room has 100 seats, a VGA video projector and wireless internet. Presentations will be video recorded (CC BY). Proposals on content and format are welcome. HOW TO SUBMIT: All submissions are made in the Pentabarf event planning tool at https://penta.fosdem.org/submission/FOSDEM15 When submitting your talk in Pentabarf, make sure to select the 'Smalltalk devroom' as the 'Track'. If you already have an account there, please reuse it. QUESTIONS & VOLUNTEERS Any questions, and video volunteers, please mail to stephan[@]stack[dot]nl with [FOSDEM] in the subject. I will send out updates on a regular basis to the lists and anyone stating his interest. PLANNED SCHEDULE: Sessions of 30/60 minutes (-5 min setup), last session a two hour hands-on introduction to smalltalk. First session or lunch session can be show-us-your-project, lightning talks. The desired time slot is meant to help you prevent conflicts with other dev rooms in which you might have a talk or your travel arrangements. There are alternative, non smalltalk-specific tracks available: lightning talk and the main track Please submit before December 1, 23:00 GMT+1. Devroom related URLs: http://www.pharo.org http://www.squeak.org/ http://etoileos.com/ http://www.seaside.st/ http://smalltalk.gnu.org/ http://www.moosetechnology.org http://amber-lang.net http://newspeaklanguage.org/ http://http://objective.st http://www.esug.org FOSDEM is the Free and Open source Software Developers' European Meeting, a free and non-commercial two-day weekend event that offers open source contributors a place to meet, share ideas and collaborate. From casey.obrien.r at gmail.com Mon Oct 13 10:04:17 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Mon Oct 13 10:04:26 2014 Subject: [squeak-dev] Form>asFormOfDepth: appears to break transparency In-Reply-To: <20141012130148.Horde.58iyVuvzYjwpoSbPm34_2A4@gator3294.hostgator.com> References: <20141011120043.Horde.3TEQfVQmNil3IPASUCWqnQ6@gator3294.hostgator.com> <20141011192352.Horde.ukHOYaus3TAAOisbGu8BOQ1@gator3294.hostgator.com> <6B03485D-E88B-41ED-A13E-2D4465AE5B3B@rowledge.org> <20141012130148.Horde.58iyVuvzYjwpoSbPm34_2A4@gator3294.hostgator.com> Message-ID: He was probably overworked. On Sun, Oct 12, 2014 at 6:01 AM, J. Vuletich (mail lists) < juanlists@jvuletich.org> wrote: > > Quoting tim Rowledge : > > On 11-10-2014, at 12:23 PM, J. Vuletich (mail lists) < >> juanlists@jvuletich.org> wrote: >> >>> Yes. In Squeak there is a bug in #asFormOfDepth: . The last lines are: >>> >>> "Special case: For a 16 -> 32 bit conversion fill the alpha >>> channel because it gets lost in translation." >>> (self depth = 16 and:[d= 32]) ifTrue:[newForm fillAlpha: 255]. >>> >>> But they should be as in Cuis: >>> >>> "If we build a 32bpp from one of smaller depth, >>> it will have zero in the alpha channel (until BitBlt is fixed!)" >>> d = 32 ifTrue: [ >>> newForm fixAlpha ]. >>> >>> I think this should fix your problem. >>> >> >> Yup. Given that there is a bitblt rule specifically to fix this problem, >> and a method specifically provided to use said bitblt to specifically fix >> this problem, I?m more than a bit puzzled as to why the most important bit >> of code (to be specific) in the image that needs this specific bit of code, >> doesn?t, specifically, have it. Even weirder is that Andreas wrote it and >> five years later carefully rewrote asFormOfDepth: to deal with this problem >> *and didn?t use his own careful fix*. >> > > Yes. I'm puzzled too. Anybody can shed some light on this? > > In any case, the Cuis way works. > > >>> Besides, the sample code I sent gets transparent, although the stuff in >>> the Form, 16rFF000000, is opaque black. This is because of another bug, >>> this one at #colorFromPixelValue:depth: . I suggest taking the code >>> verbatim from Cuis. >>> >> >> Probably a good idea. >> >> tim >> -- >> tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim >> Useful random insult:- Can't find log base two of 65536 without a >> calculator. >> > > Cheers, > Juan Vuletich > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141013/9ef3439d/attachment.htm From craig at netjam.org Mon Oct 13 14:19:39 2014 From: craig at netjam.org (Craig Latta) Date: Mon Oct 13 14:19:54 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: Hi Eliot-- > Why uncompressed by itself? If one uncompresses an archive > containing a foo.app with a bar sibling, that will surely produce > exactly the same bits in foo.app as uncompressing an archive that > contains only foo.app. The decompression program would be broken if > it creates different bits, right? So... > > If the archive is created in two steps, the first as you state > including only Squeak-4.5-All-in-One.app, using the finder, and then, > via the command line using zip -u to add the siblings how can that > not work? It can't produce a different Squeak-4.5-All-in-One.app > without zip being hopelessly broken, which it isn't, right? Hey, I don't claim knowledge of why MacOS 10.9.5 behaves as it does, or that it should behave as it does (in fact, it seems rather stupid). I'm only relaying that, as far as I can tell: - If you sign the .app, then make a ZIP archive with the .app folder and the scripts as siblings, then unarchive it, then MacOS 10.9.5 Gatekeeper rejects the signature (unless you have Gatekeeper turned off). - If you use anything other than the Mac Finder GUI to make the archive, or open it, then MacOS 10.9.5 Gatekeeper rejects the signature (unless you have Gatekeeper turned off). > > ...the release is now a ZIP archive that contains the two non-Mac > > launch scripts, along with another ZIP archive which contains the > > .app directory. This also means that non-Mac users will get the > > "__MAC" and ".DS_Store" debris after uncompressing, as well. > > It doesn't have to be this way. Use zip -u to add the siblings at a > later date. No; it's the Mac-Finder-GUI way of making the ZIP that adds the debris, apparently. At that later date, you've already lost, either by using the Mac Finder GUI to make the ZIP (and getting a good signature on open, and debris) or making the ZIP some other way (and getting a bad signature on open). > > I still think all this is tolerable. However, I'll say again here > > that I strongly prefer having the .app directory be the root of our > > release artifact, a totally self-contained thing, and leaving it to > > users to set up launch shortcuts appropriate to their local system > > (given a directory structure that is obvious enough for them to > > realize how to do it). > > Craig, you are a decent human being but... Yikes, Eliot. I don't think any of this has anything to do with what kind of human beings we are, and making that part of the discussion is hyperbolic to the point of histrionic. Please calm down? > ...your attitude on this is so discourteous to users. Clearly we disagree about that. Specifically, the new users with whom I have worked see the expression of a clear boundary as to what can be moved around and renamed as a courtesy. > Why *should* they have to unpack and decode the structure of a .app... Indeed, I would prefer that they not have to do that (I don't even like having to use ".app" in a directory name). I see a tradeoff between that and running into confusion later over where each piece of the release artifact is supposed to live, and what it can be named. I think the lesser evil here, and the greater courtesy, is for the release artifact to be a self-contained directory. I realize we disagree. > ...especially when they might be Windows or Linux users only? ...and Mac users who prefer to use the command line. In the Appsterdam community here, I'd say there's an even split between Mac devs who prefer the command line and those who don't. They are all newcomers to Squeak. I use all the host platforms on which Squeak runs, regularly. I'm exploring how to make an all-in-one release artifact in the least contorted way. I don't think anything I've suggested is a slight against the users of any of the platforms/usage configurations. (What I *really* want, in addition to what we've done so far, is the option to install the system, launch it, stop it, etc., from a web browser. It would be something like the system launchers in Parallels and VMWare. But security constraints on all the platforms pretty much force us to have the user handle a downloaded ZIP file directly.) > Why don't you see it as an obligation to provide a pleasant and > simple install step to that community rather than asking them to > perform a manual step? On the contrary, I do see an obligation to make the installation process as pleasant as it can be. Those users are already performing manual steps: downloading the ZIP file manually, unpacking it manually, and putting the contents somewhere in their filesystem manually (especially in the use case you seem to care about most, putting the contents in a directory which is already in their executables search path). Given that they are already performing these manual steps, I don't see what I propose as onerous. I'm curious as to why you didn't say anything sooner, after the all-in-one approach started years ago. > I want to go on record therefore that I think providing the scripts > is important, especially for newbies, a group we surely want to > appeal to. Yes, we surely want to appeal to newbies. I think equating disagreeing with you on this with neglecting newbies is disingenuous. Anyway, yeesh. The decision was up to Chris and he made it (and he agrees with you); this issue is over, for 4.5 anyway. I don't see a lack of unanimity about it as a dire thing. Let's debate namespaces and modules instead. :) thanks, -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From Das.Linux at gmx.de Mon Oct 13 14:28:39 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon Oct 13 14:28:43 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: Hi, On 13.10.2014, at 16:19, Craig Latta wrote: > > Hi Eliot-- > >> Why uncompressed by itself? If one uncompresses an archive >> containing a foo.app with a bar sibling, that will surely produce >> exactly the same bits in foo.app as uncompressing an archive that >> contains only foo.app. The decompression program would be broken if >> it creates different bits, right? So... >> >> If the archive is created in two steps, the first as you state >> including only Squeak-4.5-All-in-One.app, using the finder, and then, >> via the command line using zip -u to add the siblings how can that >> not work? It can't produce a different Squeak-4.5-All-in-One.app >> without zip being hopelessly broken, which it isn't, right? > > Hey, I don't claim knowledge of why MacOS 10.9.5 behaves as it > does, or that it should behave as it does (in fact, it seems rather > stupid). I'm only relaying that, as far as I can tell: > > - If you sign the .app, then make a ZIP archive with the .app folder > and the scripts as siblings, then unarchive it, then MacOS 10.9.5 > Gatekeeper rejects the signature (unless you have Gatekeeper > turned off). > > - If you use anything other than the Mac Finder GUI to make the > archive, or open it, then MacOS 10.9.5 Gatekeeper rejects the > signature (unless you have Gatekeeper turned off). > >>> ...the release is now a ZIP archive that contains the two non-Mac >>> launch scripts, along with another ZIP archive which contains the >>> .app directory. This also means that non-Mac users will get the >>> "__MAC" and ".DS_Store" debris after uncompressing, as well. >> >> It doesn't have to be this way. Use zip -u to add the siblings at a >> later date. > > No; it's the Mac-Finder-GUI way of making the ZIP that adds the > debris, apparently. At that later date, you've already lost, either by > using the Mac Finder GUI to make the ZIP (and getting a good signature > on open, and debris) or making the ZIP some other way (and getting a bad > signature on open). > This is because the codesgining will store some stuff in resource files, which are only preserved if ._stuff files or __MACOSX folders are present. >>> I still think all this is tolerable. However, I'll say again here >>> that I strongly prefer having the .app directory be the root of our >>> release artifact, a totally self-contained thing, and leaving it to >>> users to set up launch shortcuts appropriate to their local system >>> (given a directory structure that is obvious enough for them to >>> realize how to do it). >> >> Craig, you are a decent human being but... > > Yikes, Eliot. I don't think any of this has anything to do with > what kind of human beings we are, and making that part of the discussion > is hyperbolic to the point of histrionic. Please calm down? > >> ...your attitude on this is so discourteous to users. > > Clearly we disagree about that. Specifically, the new users with > whom I have worked see the expression of a clear boundary as to what can > be moved around and renamed as a courtesy. > >> Why *should* they have to unpack and decode the structure of a .app... > > Indeed, I would prefer that they not have to do that (I don't even > like having to use ".app" in a directory name). I see a tradeoff between > that and running into confusion later over where each piece of the > release artifact is supposed to live, and what it can be named. I think > the lesser evil here, and the greater courtesy, is for the release > artifact to be a self-contained directory. I realize we disagree. > >> ...especially when they might be Windows or Linux users only? > > ...and Mac users who prefer to use the command line. In the > Appsterdam community here, I'd say there's an even split between Mac > devs who prefer the command line and those who don't. They are all > newcomers to Squeak. > > I use all the host platforms on which Squeak runs, regularly. I'm > exploring how to make an all-in-one release artifact in the least > contorted way. I don't think anything I've suggested is a slight against > the users of any of the platforms/usage configurations. > > (What I *really* want, in addition to what we've done so far, is > the option to install the system, launch it, stop it, etc., from a web > browser. It would be something like the system launchers in Parallels > and VMWare. But security constraints on all the platforms pretty much > force us to have the user handle a downloaded ZIP file directly.) > >> Why don't you see it as an obligation to provide a pleasant and >> simple install step to that community rather than asking them to >> perform a manual step? > > On the contrary, I do see an obligation to make the installation > process as pleasant as it can be. Those users are already performing > manual steps: downloading the ZIP file manually, unpacking it manually, > and putting the contents somewhere in their filesystem manually > (especially in the use case you seem to care about most, putting the > contents in a directory which is already in their executables search > path). Given that they are already performing these manual steps, I > don't see what I propose as onerous. > > I'm curious as to why you didn't say anything sooner, after the > all-in-one approach started years ago. > >> I want to go on record therefore that I think providing the scripts >> is important, especially for newbies, a group we surely want to >> appeal to. > > Yes, we surely want to appeal to newbies. I think equating > disagreeing with you on this with neglecting newbies is disingenuous. > > Anyway, yeesh. The decision was up to Chris and he made it (and he > agrees with you); this issue is over, for 4.5 anyway. I don't see a lack > of unanimity about it as a dire thing. Let's debate namespaces and > modules instead. :) > > > thanks, > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > From asqueaker at gmail.com Mon Oct 13 16:25:35 2014 From: asqueaker at gmail.com (Chris Muller) Date: Mon Oct 13 16:25:38 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: Okay, so I actually had posted the prior one you gave me to the FTP site, the one without the embedded Zip, before I saw this new one, WITH the embedded zip. Between Tobias' and Eliot's responses, Tobias> The app does not run for me: Eliot> and the app runs just fine on 10.6.8. Tobias> Then it might be a ?version 1 vs Version 2 signature? as in the Apple note... I can't tell what our status is. Can the one Craig signed and I posted (w/o the embedded zip) be run by Mac users or not? >> Why uncompressed by itself? If one uncompresses an archive >> ...snip... >> > - If you sign the .app, then make a ZIP archive with the .app folder > and the scripts as siblings, then unarchive it, then MacOS 10.9.5 > Gatekeeper rejects the signature (unless you have Gatekeeper > turned off). Can't you sign the .app + the two scripts together? > - If you use anything other than the Mac Finder GUI to make the > archive, or open it, then MacOS 10.9.5 Gatekeeper rejects the > signature (unless you have Gatekeeper turned off). > >> > ...the release is now a ZIP archive that contains the two non-Mac >> > launch scripts, along with another ZIP archive which contains the >> > .app directory. This also means that non-Mac users will get the >> > "__MAC" and ".DS_Store" debris after uncompressing, as well. >> >> It doesn't have to be this way. Use zip -u to add the siblings at a >> later date. > > No; it's the Mac-Finder-GUI way of making the ZIP that adds the > debris, apparently. At that later date, you've already lost, either by > using the Mac Finder GUI to make the ZIP (and getting a good signature > on open, and debris) or making the ZIP some other way (and getting a bad > signature on open). > >> > I still think all this is tolerable. However, I'll say again here >> > that I strongly prefer having the .app directory be the root of our >> > release artifact, a totally self-contained thing, and leaving it to >> > users to set up launch shortcuts appropriate to their local system >> > (given a directory structure that is obvious enough for them to >> > realize how to do it). You keep mentioning this feature about setting up custom launch shortcuts but ignoring my rebuttal that the audience the All-In-One is designed for is for newbies. Newbies are the ones who have only just heard about Squeak and are saying, "Just Show Me Squeak Right Fucking Now". The group you're referring to, who wants to unzip the All-In-One, and then set it up in custom locations with shortcuts for repeated access over the long-term, those folks are not who the All-In-One is targeting. Besides that, the shortcut scripts are not an impediment to doing what you said anyway. If anything, they "document" where and how to launch it and so if they want to move them to a different place, they'll know how. The type of person who is adventurous enough to customize it will not "fold" and whine "hey it didn't work when I moved / renamed / whatever." In fact, they would probably find the documentation on squeak.org about the invididual components (.image, .changes, vm, .sources) and set it up truly custom, and now this person is a totally disparate audience from the All-In-One audience. > ...snip... > >> Why don't you see it as an obligation to provide a pleasant and >> simple install step to that community rather than asking them to >> perform a manual step? > > On the contrary, I do see an obligation to make the installation > process as pleasant as it can be. Those users are already performing > manual steps: downloading the ZIP file manually, unpacking it manually, Done at this point. Once unpacked, it's ready to run. > and putting the contents somewhere in their filesystem manually > (especially in the use case you seem to care about most, putting the > contents in a directory which is already in their executables search > path). No, the $PATH variable has nothing to do with launching Squeak from the All-In-One. This makes no sense to me.. > Given that they are already performing these manual steps, I > don't see what I propose as onerous. If I downloaded a ZIP and I found another Zip inside it, I would think that the .sh and .bat were things that would unpack that zip FOR ME. Assuming I figured out that was wrong,I would then wonder am I supposed to put this inner-zip? In the same directory or can it stand alone elsewhere? If it has to be in teh same dir, then why the fuck didn't the authors just put it that way? It's totally confusing, irritating, and repelling. Exactly the opposites we want newbies to feel. The goal is to get them into the image as quickly and easily as possible. >> I want to go on record therefore that I think providing the scripts >> is important, especially for newbies, a group we surely want to >> appeal to. > > Yes, we surely want to appeal to newbies. I think equating > disagreeing with you on this with neglecting newbies is disingenuous. C'mon. When Eliot said you are a decent human being, he was simply expressing his disagreement in a way that was trying to avoid you becoming upset. It appears he failed, but at least he tried. > Anyway, yeesh. The decision was up to Chris and he made it (and he > agrees with you); this issue is over, for 4.5 anyway. I don't see a lack > of unanimity about it as a dire thing. Let's debate namespaces and > modules instead. :) I appreciate that, but I don't know if we've made any progress whatsoever from the original post though, which expressed that the All-In-One was having trouble for Mac users.. I have no Mac. What's our status of the one that's there now? > > > thanks, > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > From kbrown at mac.com Mon Oct 13 21:17:35 2014 From: kbrown at mac.com (Ken G. Brown) Date: Mon Oct 13 21:18:19 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: <3D29FC3E-7EF4-467F-AAF2-9F4AB5F9799B@mac.com> Having watched the recent discussions about troubles with the all-in-one release, I'd just like to make the observation that it might be time to forget the all-in-one. I personally don't like to have to download a bunch of extra large files if I just am interested in the release for a certain platform. And cluttering up the Mac .app folder with other stuff for other platforms just seems somehow really wrong. In my opinion it is pretty easy for a newbie to decide up front whether to download for Windows, Linux or Mac and have a nicely tailored install for that platform. My vote is to streamline the release process by dropping the all-in-one and just have separate downloads for each platform. Ken G. Brown, from my iPhone > On Oct 13, 2014, at 08:19, Craig Latta wrote: > > > Hi Eliot-- > >> Why uncompressed by itself? If one uncompresses an archive >> containing a foo.app with a bar sibling, that will surely produce >> exactly the same bits in foo.app as uncompressing an archive that >> contains only foo.app. The decompression program would be broken if >> it creates different bits, right? So... >> >> If the archive is created in two steps, the first as you state >> including only Squeak-4.5-All-in-One.app, using the finder, and then, >> via the command line using zip -u to add the siblings how can that >> not work? It can't produce a different Squeak-4.5-All-in-One.app >> without zip being hopelessly broken, which it isn't, right? > > Hey, I don't claim knowledge of why MacOS 10.9.5 behaves as it > does, or that it should behave as it does (in fact, it seems rather > stupid). I'm only relaying that, as far as I can tell: > > - If you sign the .app, then make a ZIP archive with the .app folder > and the scripts as siblings, then unarchive it, then MacOS 10.9.5 > Gatekeeper rejects the signature (unless you have Gatekeeper > turned off). > > - If you use anything other than the Mac Finder GUI to make the > archive, or open it, then MacOS 10.9.5 Gatekeeper rejects the > signature (unless you have Gatekeeper turned off). > >>> ...the release is now a ZIP archive that contains the two non-Mac >>> launch scripts, along with another ZIP archive which contains the >>> .app directory. This also means that non-Mac users will get the >>> "__MAC" and ".DS_Store" debris after uncompressing, as well. >> >> It doesn't have to be this way. Use zip -u to add the siblings at a >> later date. > > No; it's the Mac-Finder-GUI way of making the ZIP that adds the > debris, apparently. At that later date, you've already lost, either by > using the Mac Finder GUI to make the ZIP (and getting a good signature > on open, and debris) or making the ZIP some other way (and getting a bad > signature on open). > >>> I still think all this is tolerable. However, I'll say again here >>> that I strongly prefer having the .app directory be the root of our >>> release artifact, a totally self-contained thing, and leaving it to >>> users to set up launch shortcuts appropriate to their local system >>> (given a directory structure that is obvious enough for them to >>> realize how to do it). >> >> Craig, you are a decent human being but... > > Yikes, Eliot. I don't think any of this has anything to do with > what kind of human beings we are, and making that part of the discussion > is hyperbolic to the point of histrionic. Please calm down? > >> ...your attitude on this is so discourteous to users. > > Clearly we disagree about that. Specifically, the new users with > whom I have worked see the expression of a clear boundary as to what can > be moved around and renamed as a courtesy. > >> Why *should* they have to unpack and decode the structure of a .app... > > Indeed, I would prefer that they not have to do that (I don't even > like having to use ".app" in a directory name). I see a tradeoff between > that and running into confusion later over where each piece of the > release artifact is supposed to live, and what it can be named. I think > the lesser evil here, and the greater courtesy, is for the release > artifact to be a self-contained directory. I realize we disagree. > >> ...especially when they might be Windows or Linux users only? > > ...and Mac users who prefer to use the command line. In the > Appsterdam community here, I'd say there's an even split between Mac > devs who prefer the command line and those who don't. They are all > newcomers to Squeak. > > I use all the host platforms on which Squeak runs, regularly. I'm > exploring how to make an all-in-one release artifact in the least > contorted way. I don't think anything I've suggested is a slight against > the users of any of the platforms/usage configurations. > > (What I *really* want, in addition to what we've done so far, is > the option to install the system, launch it, stop it, etc., from a web > browser. It would be something like the system launchers in Parallels > and VMWare. But security constraints on all the platforms pretty much > force us to have the user handle a downloaded ZIP file directly.) > >> Why don't you see it as an obligation to provide a pleasant and >> simple install step to that community rather than asking them to >> perform a manual step? > > On the contrary, I do see an obligation to make the installation > process as pleasant as it can be. Those users are already performing > manual steps: downloading the ZIP file manually, unpacking it manually, > and putting the contents somewhere in their filesystem manually > (especially in the use case you seem to care about most, putting the > contents in a directory which is already in their executables search > path). Given that they are already performing these manual steps, I > don't see what I propose as onerous. > > I'm curious as to why you didn't say anything sooner, after the > all-in-one approach started years ago. > >> I want to go on record therefore that I think providing the scripts >> is important, especially for newbies, a group we surely want to >> appeal to. > > Yes, we surely want to appeal to newbies. I think equating > disagreeing with you on this with neglecting newbies is disingenuous. > > Anyway, yeesh. The decision was up to Chris and he made it (and he > agrees with you); this issue is over, for 4.5 anyway. I don't see a lack > of unanimity about it as a dire thing. Let's debate namespaces and > modules instead. :) > > > thanks, > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > From stephan at stack.nl Mon Oct 13 21:22:54 2014 From: stephan at stack.nl (Stephan Eggermont) Date: Mon Oct 13 21:22:55 2014 Subject: [squeak-dev] Re: Printing nanos in Time print24 Message-ID: <6526F6BC-6280-4440-949B-D29C97968E46@stack.nl> Anyone? From eliot.miranda at gmail.com Tue Oct 14 00:51:47 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 14 00:51:49 2014 Subject: [squeak-dev] New Cog VMs available Message-ID: ...at http://www.mirandabanda.org/files/Cog/VM/VM.r3104 CogVM source as per VMMaker.oscog-eem.900/r3104 Change a couple of between:and:'s that should be oop:isGreaterThanOrEqualTo: andLessThan:'s Fix signed/unsigned comparisons with freeStart in V3. Fix old V3 NewObjectMemory bug in fullGC. sweepPhaseForFullGC failed to update freeStart at the end of its sweep which could leave a partial object between the last object and freeStart, causing subsequent crashes in enumeration. This fixes an occasional crash in muO's release process: MuODeployer makeImageRelease -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141013/8cab7bf6/attachment.htm From lewis at mail.msen.com Tue Oct 14 03:07:18 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 14 03:07:22 2014 Subject: [squeak-dev] Printing nanos in Time print24 In-Reply-To: References: Message-ID: <20141014030718.GA48304@shell.msen.com> On Thu, Oct 09, 2014 at 12:30:30PM +0200, Stephan Eggermont wrote: > Since 2009-6-25 (dtl) > Time>>#print24:showSeconds:on: > prints nanos. This contradicts the class and > method comments. The tests carefully > avoid the issue. > > Why was this behavior introduced, > and can it safely be improved? > It occurs in both Squeak and Pharo (issue 14198) Stephan, I do not know the reason, but I see that the method has my initials on it, so I owe you a better answer. Dave From lewis at mail.msen.com Tue Oct 14 03:42:26 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 14 03:42:32 2014 Subject: [squeak-dev] Printing nanos in Time print24 In-Reply-To: <20141014030718.GA48304@shell.msen.com> References: <20141014030718.GA48304@shell.msen.com> Message-ID: <20141014034226.GA70245@shell.msen.com> On Mon, Oct 13, 2014 at 11:07:18PM -0400, David T. Lewis wrote: > On Thu, Oct 09, 2014 at 12:30:30PM +0200, Stephan Eggermont wrote: > > Since 2009-6-25 (dtl) > > Time>>#print24:showSeconds:on: > > prints nanos. This contradicts the class and > > method comments. The tests carefully > > avoid the issue. > > > > Why was this behavior introduced, > > and can it safely be improved? > > It occurs in both Squeak and Pharo (issue 14198) > > Stephan, > > I do not know the reason, but I see that the method has my initials on > it, so I owe you a better answer. > The change was introduced here: Name: Kernel-dtl.177 Author: dtl Time: 13 July 2009, 12:08:49.002 pm UUID: 152a8933-6259-46cc-a118-55029e8dbb5a Ancestors: Kernel-dtl.176 Reference Mantis 0007356: DateAndTime fromSeconds: 0.5 => walkback, broken since Mantis 4669 Allow #fromSeconds: to accept non-integer arguments, and update Time>>printString to display fractional seconds for better compatibility with the original Squeak implementation. The expressions 'DateAndTime fromSeconds: 0.5' and 'Time fromSeconds: 0.5' now behave as expected. This change set fixes a limitation of #fromSeconds: that was introduced in Mantis 4669: [ENH] TimeForSpeed. It changes the corresponding #fromSeconds: and #printString for class Time to match DateAndTime and to be more compatible with the original Squeak implementation. Based on this, I think that my intention at the time was to make Time>>printString behave similarly to its original intended behavior. I am not sure if the problem with Time>>print24:showSeconds:on: is a bug in the method comment or in its current implementation. Dave From lecteur at zogotounga.net Tue Oct 14 07:25:12 2014 From: lecteur at zogotounga.net (=?UTF-8?B?U3TDqXBoYW5lIFJvbGxhbmRpbg==?=) Date: Tue Oct 14 07:25:18 2014 Subject: [squeak-dev] Cog VM on older architecture ? Message-ID: <543CCFD8.6050900@zogotounga.net> Hello, I got hold of an old laptop on Pentium II. I installed Windows XP in it and tried to run Squeak to see how it goes, but my attempts with various Cog VM all failed (with a message from the system, not a VM crash). The interpreter VM worked fine (but it's slooow). Is it expected ? Stef From stephan at stack.nl Tue Oct 14 08:42:28 2014 From: stephan at stack.nl (Stephan Eggermont) Date: Tue Oct 14 08:42:37 2014 Subject: [squeak-dev] Re: Printing nanos in Time print24 Message-ID: <77A256DF-09AA-4636-B5DE-6E2FE1CFF8C0@stack.nl> Ok, that is clear. I also have a need for time printing to seconds precision. Would it be better to keep the current behavior, fix the comments and add a method hhmmss or so, or to route printString to a printWithNanos and remove the nanos printing in #print24:showSeconds:on:? Stephan From eliot.miranda at gmail.com Tue Oct 14 11:17:29 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 14 11:17:36 2014 Subject: [squeak-dev] Cog VM on older architecture ? In-Reply-To: <543CCFD8.6050900@zogotounga.net> References: <543CCFD8.6050900@zogotounga.net> Message-ID: <4885C878-EC6E-4071-891C-E97310A095AD@gmail.com> Hi St?phane, On Oct 14, 2014, at 12:25 AM, St?phane Rollandin wrote: > Hello, > > I got hold of an old laptop on Pentium II. I installed Windows XP in it and tried to run Squeak to see how it goes, but my attempts with various Cog VM all failed (with a message from the system, not a VM crash). The interpreter VM worked fine (but it's slooow). I'd love to see the message, but I'm guessing it is that the Pentium II doesn't have SSE2 instructions. The solution would be fir you to build your own Cog VM not using the -sse2 flag. The JIT tests for the availability of SSE2 instructions and if available generates machine code floating point primitives. But the C compiler can't choose dynamically. So your hand rolled VM will have poorer floating point performance but otherwise should be good. > Is it expected ? Yes. Pentium II has MMX, not SSE2. > Stef From lewis at mail.msen.com Tue Oct 14 12:10:39 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 14 12:10:43 2014 Subject: [squeak-dev] Re: Printing nanos in Time print24 In-Reply-To: <77A256DF-09AA-4636-B5DE-6E2FE1CFF8C0@stack.nl> References: <77A256DF-09AA-4636-B5DE-6E2FE1CFF8C0@stack.nl> Message-ID: <20141014121039.GA61520@shell.msen.com> On Tue, Oct 14, 2014 at 10:42:28AM +0200, Stephan Eggermont wrote: > Ok, that is clear. I also have a need for time printing to seconds precision. > Would it be better to keep the current behavior, fix the comments and > add a method hhmmss or so, or to route printString to a printWithNanos > and remove the nanos printing in #print24:showSeconds:on:? Stephan, That certainly sounds like a reasonable solution to me. I am away and cannot look at it right now, but I would encourage you to add an update to the inbox if you come up with a patch that handles this properly. I think I recall a similar issue related to printing DateAndTime so you may want to look and see if there is a solution there. Dave From craig at netjam.org Tue Oct 14 14:43:44 2014 From: craig at netjam.org (Craig Latta) Date: Tue Oct 14 14:43:56 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: Hoi-- Tobias writes: > This is because the codesigning will store some stuff in resource > files, which are only preserved if ._stuff files or __MACOSX folders > are present. I can believe that. I haven't looked into the details of what the signing actually does. *** Chris writes: > Okay, so I actually had posted the prior one you gave me to the FTP > site, the one without the embedded Zip, before I saw this new one, > WITH the embedded zip. > > Between Tobias' and Eliot's responses, > > Tobias> The app does not run for me: > Eliot> and the app runs just fine on 10.6.8. > Tobias> Then it might be a ?version 1 vs Version 2 signature? as in > Tobias> the Apple note... > > I can't tell what our status is. Can the one Craig signed and I > posted (w/o the embedded zip) be run by Mac users or not? Apparently it's fine on 10.6.8, where Gatekeeper doesn't exist (Apple introduced it in MacOS 10.7.5, see [1]). On MacOS 10.9.5, Gatekeeper rejects the signature. > Can't you sign the .app + the two scripts together? No; well, not with the scripts where you want them. The thing being signed has to conform to a particular Apple "bundle" format, which wants everything to be rooted in the .app directory. There are a bunch of other constraints, too, most prominently for us the one about arbitrary stuff disallowed in .app/Contents. That's what got this whole conversation started. > You keep mentioning this feature about setting up custom launch > shortcuts but ignoring my rebuttal that the audience the All-In-One is > designed for is for newbies. I'm not ignoring anything you'd said, we simply disagree. In particular, we disagree about how much to treat a Squeak newbie like a newbie with regard to their host platform. > Newbies are the ones who have only just heard about Squeak and are > saying, "Just Show Me Squeak Right Fucking Now". Was that profanity really necessary? Anyway, the way things were a month ago, command-line and Windows Squeak newbies were already having to go into the .app folder to start Squeak. They had to have exactly as much host platform knowledge before the Gatekeeper-caused change as after. > The group you're referring to, who wants to unzip the All-In-One, and > then set it up in custom locations with shortcuts for repeated access > over the long-term, those folks are not who the All-In-One is > targeting. That's not the use case I get from Eliot. His *primary* concern in the 2014-10-02 board meeting was that someone could put the contents of the ZIP in a place already included in their search paths (like /usr/local/bin), and then "just type the name of the script" to run Squeak. > Eliot> Why don't you see it as an obligation to provide a pleasant and > Eliot> simple install step to that community rather than asking them > Eliot> to perform a manual step? > > Craig> On the contrary, I do see an obligation to make the > Craig> installation process as pleasant as it can be. Those users are > Craig> already performing manual steps: downloading the ZIP file > Craig> manually, unpacking it manually... > > Done at this point. Once unpacked, it's ready to run. Not to Eliot's satisfaction as I understood it in the 2014-10-02 board meeting, no. He wanted the results of the installation to include a script in one of his search paths, so that he could type the name of the script from a shell with an arbitrary working directory, and have it run. For that to happen, the installation must include putting the contents of the ZIP in a particular place (like /usr/local/bin). > No, the $PATH variable has nothing to do with launching Squeak from > the All-In-One. This makes no sense to me.. Hey, this is just what I heard Eliot saying. Apparently you heard something else. There's another board meeting on Thursday... > If I downloaded a ZIP and I found another Zip inside it, I would think > that the .sh and .bat were things that would unpack that zip FOR ME. Great, we can make them do that. > If it has to be in teh same dir, then why the fuck didn't the authors > just put it that way? Chris, please calm down. This issue is already settled, and by you no less. I only wanted to speak my view for the record. Why don't you just let my dissenting comments stand and move on? I don't understand why you're getting so upset about this. > I don't know if we've made any progress whatsoever from the original > post though, which expressed that the All-In-One was having trouble > for Mac users. We've made substantial progress: we've figured out how to make a ZIP file which jumps through all the hoops set for it. The latest one I made is such a ZIP, at [2]. The one currently on squeak.org, as I discussed in detail above, is not (bad signature). Apparently we should make one more version with Linux and Windows scripts that unzip the .app folder if it hasn't been unzipped already, or forget the all-in-one approach altogether (or forget about Apple signatures :). *** Ken G. Brown writes: > Having watched the recent discussions about troubles with the > all-in-one release, I'd just like to make the observation that it > might be time to forget the all-in-one. I personally don't like to > have to download a bunch of extra large files if I just am interested > in the release for a certain platform. And cluttering up the Mac .app > folder with other stuff for other platforms just seems somehow really > wrong. As I said in [3], an all-in-one release gives users the significant convenience of having a single artifact to take between platforms. I actually do meet new users who care about platform portability. We can also make the Squeak app manage multiple user images, so users need not have multiple copies of the Squeak app around just to run multiple images, nor need to understand any conventions about the Resources folder. That makes having a single artifact that can move between platforms even more valuable. > In my opinion it is pretty easy for a newbie to decide up front > whether to download for Windows, Linux or Mac and have a nicely > tailored install for that platform. Sure; if it were up to me I'd do all four: Windows, Linux, Mac, and all-in-one. thanks, -C [1] https://en.wikipedia.org/wiki/Gatekeeper_(OS_X) [2] http://bit.ly/1CBwx1I (Dropbox) [3] http://bit.ly/ZXYW4u (lists.squeakfoundation.org) -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From eliot.miranda at gmail.com Tue Oct 14 16:23:47 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 14 16:23:50 2014 Subject: [squeak-dev] Anyone have contact info for Ragnar Hojland Espinosa? Message-ID: re http://lists.squeakfoundation.org/pipermail/squeak-dev/2003-May/057750.html does anyone have contact info for Ragnar Hojland Espinosa? I have Ragnar Hojland Espinosa but it bounces. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/c3c11dd3/attachment.htm From brasspen at gmail.com Tue Oct 14 17:39:25 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Tue Oct 14 17:39:30 2014 Subject: [squeak-dev] Anyone have contact info for Ragnar Hojland Espinosa? In-Reply-To: References: Message-ID: <7DD31091-15F3-4223-A862-4642F9C03237@gmail.com> I see on LinkedIn that one RHE works as a sysadmin in Dublin at http://www.dedsert.com since July and might be contacted by LinkedIn InMail. Of course, that may not be the droid you?re looking for. FWIW, Chris > On Oct 14, 2014, at 12:23 PM, Eliot Miranda wrote: > > re http://lists.squeakfoundation.org/pipermail/squeak-dev/2003-May/057750.html does anyone have contact info for Ragnar Hojland Espinosa? I have Ragnar Hojland Espinosa > but it bounces. > > -- > best, > Eliot > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/759734d8/attachment.htm From nicolaihess at web.de Tue Oct 14 18:26:47 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Tue Oct 14 18:26:54 2014 Subject: [squeak-dev] Re: [Pharo-users] Trouble opening large files In-Reply-To: References: Message-ID: There is a bug report on mantis for squeaks unix vm. I think this applies to pharo too, although I don't know if this bug is still valid on recent squeak vm. http://bugs.squeak.org/view.php?id=7522 2014-10-14 17:43 GMT+02:00 Evan Donahue : > The OS is Arch Linux. > > I can read the file with less. > > The problem, insofar as I can trace it, seems to stem from this line in > UnixStore: > > Primitives lookupDirectory: encodedPath filename: encodedBasename > > When I have my 57G file there this line returns nil. If I move the 57G > file and create a small file with the same name, the same command > successfully finds the file. I am not sure how large a file must be to > cause this issue, but A 1.5G file works fine. > > On Tue, Oct 14, 2014 at 8:17 AM, Nicolai Hess wrote: > >> 2014-10-14 6:38 GMT+02:00 Evan Donahue : >> >>> Hi, thanks for the reply. >>> >>> The response is the same: "MessageNotUnderstood: >>> False>>humanReadableSIByteSize." >>> >>> This happens both to print-it as well as to do-it-and-go. Running the >>> command on the neighboring "wiki.torrent" torrent file yields the correct >>> 54kb. >>> >>> Thanks, >>> Evan >>> >>> On Tue, Oct 14, 2014 at 12:24 AM, Tudor Girba >>> wrote: >>> >>>> Hi, >>>> >>>> If I understand correctly, the failure occurs while navigating in the >>>> "Items" presentation. >>>> >>>> I cannot reproduce this problem because I do not have enough disk space >>>> for such a large file :). But, could you do the following and let me know >>>> what the outcome is: >>>> >>>> 'path/to/your/large/file.xml' asFileReference humanReadableSize >>>> >>>> ? >>>> >>>> Cheers, >>>> Doru >>>> >>>> >>>> >>>> On Tue, Oct 14, 2014 at 2:27 AM, Evan Donahue >>>> wrote: >>>> >>>>> Hello, I've run into some odd behavior and wanted to check whether I >>>>> might be missing something: >>>>> >>>>> I have downloaded a copy of the english wikipedia as an xml file and >>>>> am hoping to (sax) parse it. However, I can't even seem to get pharo to >>>>> recognize that the file exists. >>>>> >>>>> If I open FileSystem disk root in the playground and naigate, >>>>> attempting to enter the folder containing the (57G) xml file fails with >>>>> "MessageNotUnderstood: False>>humanReadableSIByteSize." Likewise if I get a >>>>> FileReference with FileSystem disk root / 'path' / 'to' / 'file' then self >>>>> exists returns false and the parser fails. >>>>> >>>>> Am I doing something wrong? Should I be able to do this? >>>>> >>>>> The version number is #40283 >>>>> >>>>> Thanks, >>>>> Evan >>>>> >>>> >>>> >>>> >>>> -- >>>> www.tudorgirba.com >>>> >>>> "Every thing has its own flow" >>>> >>> >>> >> >> Which OS ? >> Can you check with other programs if this file is readable at all? >> >> >> >> >> Nicolai >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/edd0402e/attachment.htm From eliot.miranda at gmail.com Tue Oct 14 18:49:50 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 14 18:49:52 2014 Subject: [squeak-dev] Re: [Pharo-users] Trouble opening large files In-Reply-To: References: Message-ID: Hi Nicolai, On Tue, Oct 14, 2014 at 11:26 AM, Nicolai Hess wrote: > There is a bug report on mantis for squeaks unix vm. > I think this applies to pharo too, although I don't know if this > bug is still valid on recent squeak vm. > > http://bugs.squeak.org/view.php?id=7522 > yes, one must compile with -D_FILE_OFFSET_BITS=64. The Cog VMs are also built with -D_GNU_SOURCE. Here's a line from a Squeak file list on the current Cog VM: (2014.10.11 07:00:46 7,115,143,880) Formula1.2014.Round16.Russia.Qualifying.BBCOneHD.1080i.H264.English-wserhkzt.ts No 32-bit limit here. > > 2014-10-14 17:43 GMT+02:00 Evan Donahue : > >> The OS is Arch Linux. >> >> I can read the file with less. >> >> The problem, insofar as I can trace it, seems to stem from this line in >> UnixStore: >> >> Primitives lookupDirectory: encodedPath filename: encodedBasename >> >> When I have my 57G file there this line returns nil. If I move the 57G >> file and create a small file with the same name, the same command >> successfully finds the file. I am not sure how large a file must be to >> cause this issue, but A 1.5G file works fine. >> >> On Tue, Oct 14, 2014 at 8:17 AM, Nicolai Hess wrote: >> >>> 2014-10-14 6:38 GMT+02:00 Evan Donahue : >>> >>>> Hi, thanks for the reply. >>>> >>>> The response is the same: "MessageNotUnderstood: >>>> False>>humanReadableSIByteSize." >>>> >>>> This happens both to print-it as well as to do-it-and-go. Running the >>>> command on the neighboring "wiki.torrent" torrent file yields the correct >>>> 54kb. >>>> >>>> Thanks, >>>> Evan >>>> >>>> On Tue, Oct 14, 2014 at 12:24 AM, Tudor Girba >>>> wrote: >>>> >>>>> Hi, >>>>> >>>>> If I understand correctly, the failure occurs while navigating in the >>>>> "Items" presentation. >>>>> >>>>> I cannot reproduce this problem because I do not have enough disk >>>>> space for such a large file :). But, could you do the following and let me >>>>> know what the outcome is: >>>>> >>>>> 'path/to/your/large/file.xml' asFileReference humanReadableSize >>>>> >>>>> ? >>>>> >>>>> Cheers, >>>>> Doru >>>>> >>>>> >>>>> >>>>> On Tue, Oct 14, 2014 at 2:27 AM, Evan Donahue >>>>> wrote: >>>>> >>>>>> Hello, I've run into some odd behavior and wanted to check whether I >>>>>> might be missing something: >>>>>> >>>>>> I have downloaded a copy of the english wikipedia as an xml file and >>>>>> am hoping to (sax) parse it. However, I can't even seem to get pharo to >>>>>> recognize that the file exists. >>>>>> >>>>>> If I open FileSystem disk root in the playground and naigate, >>>>>> attempting to enter the folder containing the (57G) xml file fails with >>>>>> "MessageNotUnderstood: False>>humanReadableSIByteSize." Likewise if I get a >>>>>> FileReference with FileSystem disk root / 'path' / 'to' / 'file' then self >>>>>> exists returns false and the parser fails. >>>>>> >>>>>> Am I doing something wrong? Should I be able to do this? >>>>>> >>>>>> The version number is #40283 >>>>>> >>>>>> Thanks, >>>>>> Evan >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> www.tudorgirba.com >>>>> >>>>> "Every thing has its own flow" >>>>> >>>> >>>> >>> >>> Which OS ? >>> Can you check with other programs if this file is readable at all? >>> >>> >>> >>> >>> Nicolai >>> >>> >>> >> > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/02c152fd/attachment.htm From nicolaihess at web.de Tue Oct 14 19:02:48 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Tue Oct 14 19:02:50 2014 Subject: [squeak-dev] Re: [Pharo-users] Trouble opening large files In-Reply-To: References: Message-ID: Rebuild pharo vm with D_FILE_OFFSET_BITS=64 option: Reading list directories with (very) large files working now. 2014-10-14 20:26 GMT+02:00 Nicolai Hess : > There is a bug report on mantis for squeaks unix vm. > I think this applies to pharo too, although I don't know if this > bug is still valid on recent squeak vm. > > http://bugs.squeak.org/view.php?id=7522 > > 2014-10-14 17:43 GMT+02:00 Evan Donahue : > >> The OS is Arch Linux. >> >> I can read the file with less. >> >> The problem, insofar as I can trace it, seems to stem from this line in >> UnixStore: >> >> Primitives lookupDirectory: encodedPath filename: encodedBasename >> >> When I have my 57G file there this line returns nil. If I move the 57G >> file and create a small file with the same name, the same command >> successfully finds the file. I am not sure how large a file must be to >> cause this issue, but A 1.5G file works fine. >> >> On Tue, Oct 14, 2014 at 8:17 AM, Nicolai Hess wrote: >> >>> 2014-10-14 6:38 GMT+02:00 Evan Donahue : >>> >>>> Hi, thanks for the reply. >>>> >>>> The response is the same: "MessageNotUnderstood: >>>> False>>humanReadableSIByteSize." >>>> >>>> This happens both to print-it as well as to do-it-and-go. Running the >>>> command on the neighboring "wiki.torrent" torrent file yields the correct >>>> 54kb. >>>> >>>> Thanks, >>>> Evan >>>> >>>> On Tue, Oct 14, 2014 at 12:24 AM, Tudor Girba >>>> wrote: >>>> >>>>> Hi, >>>>> >>>>> If I understand correctly, the failure occurs while navigating in the >>>>> "Items" presentation. >>>>> >>>>> I cannot reproduce this problem because I do not have enough disk >>>>> space for such a large file :). But, could you do the following and let me >>>>> know what the outcome is: >>>>> >>>>> 'path/to/your/large/file.xml' asFileReference humanReadableSize >>>>> >>>>> ? >>>>> >>>>> Cheers, >>>>> Doru >>>>> >>>>> >>>>> >>>>> On Tue, Oct 14, 2014 at 2:27 AM, Evan Donahue >>>>> wrote: >>>>> >>>>>> Hello, I've run into some odd behavior and wanted to check whether I >>>>>> might be missing something: >>>>>> >>>>>> I have downloaded a copy of the english wikipedia as an xml file and >>>>>> am hoping to (sax) parse it. However, I can't even seem to get pharo to >>>>>> recognize that the file exists. >>>>>> >>>>>> If I open FileSystem disk root in the playground and naigate, >>>>>> attempting to enter the folder containing the (57G) xml file fails with >>>>>> "MessageNotUnderstood: False>>humanReadableSIByteSize." Likewise if I get a >>>>>> FileReference with FileSystem disk root / 'path' / 'to' / 'file' then self >>>>>> exists returns false and the parser fails. >>>>>> >>>>>> Am I doing something wrong? Should I be able to do this? >>>>>> >>>>>> The version number is #40283 >>>>>> >>>>>> Thanks, >>>>>> Evan >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> www.tudorgirba.com >>>>> >>>>> "Every thing has its own flow" >>>>> >>>> >>>> >>> >>> Which OS ? >>> Can you check with other programs if this file is readable at all? >>> >>> >>> >>> >>> Nicolai >>> >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/b6d3f07b/attachment.htm From asqueaker at gmail.com Tue Oct 14 19:17:16 2014 From: asqueaker at gmail.com (Chris Muller) Date: Tue Oct 14 19:17:18 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: >> Can't you sign the .app + the two scripts together? > > No; well, not with the scripts where you want them. The thing being > signed has to conform to a particular Apple "bundle" format, which wants > everything to be rooted in the .app directory. Could the scripts be placed in the .app directory then, as siblings of the Contents dir? >> ... >> Newbies are the ones who have only just heard about Squeak and are >> saying, "Just Show Me Squeak Right Fucking Now". > > Was that profanity really necessary? It (and the double-quotes and capitalization) was me portraying the use-case from the actor's POV, a grumpy-newbie, to emphasize the importance of the newbies "first kiss" impression of Squeak. >> The group you're referring to, who wants to unzip the All-In-One, and >> then set it up in custom locations with shortcuts for repeated access >> over the long-term, those folks are not who the All-In-One is >> targeting. > > That's not the use case I get from Eliot. His *primary* concern in > the 2014-10-02 board meeting was that someone could put the contents of > the ZIP in a place already included in their search paths (like > /usr/local/bin), and then "just type the name of the script" to run Squeak. Okay. We'll have to ask Eliot about that. To me, that use-case is secondary to the more important one (above) to get the grumpy-newbie kissing instead of cussing. >> If I downloaded a ZIP and I found another Zip inside it, I would think >> that the .sh and .bat were things that would unpack that zip FOR ME. > > Great, we can make them do that. > >> If it has to be in teh same dir, then why the fuck didn't the authors >> just put it that way? > > Chris, please calm down. (I was simply role playing the primary actor of this use-case again, the grumpy-newbie). >> I don't know if we've made any progress whatsoever from the original >> post though, which expressed that the All-In-One was having trouble >> for Mac users. > > We've made substantial progress: we've figured out how to make a > ZIP file which jumps through all the hoops set for it. The latest one I > made is such a ZIP, at [2]. Earlier in this thread, you wrote: ---------- Craig> For the signature to be valid, the .app directory has to be compressed and uncompressed by itself (no siblings), and it has to be done with the Mac Finder GUI (not from zip/unzip on the command line, in either MacOS or another OS that has access to the filesystem). Craig> So... the release is now a ZIP archive that contains the two non-Mac launch scripts, along with another ZIP archive which contains the .app directory. This also means that non-Mac users will get the "__MAC" and ".DS_Store" debris after uncompressing, as well. ----------- I've read it 3 times, sorry if I'm being dense: I'm not understanding the causaility in the first paragraph that leads to the requirement of the inner-Zip mentioned in the second paragraph. If "the .app directory has to be compressed and uncompressed by itself (no siblings)", fine, but why the inner zip instead of just staying iwth the "Squeak-4.5-All-in-One.app"? Since we can't have siblings to the .app, here is a second-best Zip structure I hope we can do: Squeak-4.5-All-in-One.app Contents squeak.bat squeak.sh Can that be done? > The one currently on squeak.org, as I > discussed in detail above, is not (bad signature). Apparently we should > make one more version with Linux and Windows scripts that unzip the .app > folder if it hasn't been unzipped already, or forget the all-in-one > approach altogether (or forget about Apple signatures :). From eliot.miranda at gmail.com Tue Oct 14 19:28:20 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 14 19:28:26 2014 Subject: [squeak-dev] Anyone have contact info for Ragnar Hojland Espinosa? In-Reply-To: <7DD31091-15F3-4223-A862-4642F9C03237@gmail.com> References: <7DD31091-15F3-4223-A862-4642F9C03237@gmail.com> Message-ID: I just got a reply from Ragnar, so no worries. Thanks! On Tue, Oct 14, 2014 at 10:39 AM, Chris Cunnington wrote: > I see on LinkedIn that one RHE works as a sysadmin in Dublin at > http://www.dedsert.com since July and might be contacted by > LinkedIn InMail. Of course, that may not be the droid you?re looking for. > > FWIW, > Chris > > On Oct 14, 2014, at 12:23 PM, Eliot Miranda > wrote: > > re > http://lists.squeakfoundation.org/pipermail/squeak-dev/2003-May/057750.html does > anyone have contact info for Ragnar Hojland Espinosa? I have Ragnar > Hojland Espinosa but it bounces. > > -- > best, > Eliot > > > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/3cbc0a4b/attachment.htm From nicolaihess at web.de Tue Oct 14 19:29:51 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Tue Oct 14 19:29:55 2014 Subject: [squeak-dev] Re: [Pharo-users] Trouble opening large files In-Reply-To: References: Message-ID: Ah, good to know. At least for squeak, bug 7522 can be closed :) Nicolai 2014-10-14 20:49 GMT+02:00 Eliot Miranda : > Hi Nicolai, > > On Tue, Oct 14, 2014 at 11:26 AM, Nicolai Hess wrote: > >> There is a bug report on mantis for squeaks unix vm. >> I think this applies to pharo too, although I don't know if this >> bug is still valid on recent squeak vm. >> >> http://bugs.squeak.org/view.php?id=7522 >> > > yes, one must compile with -D_FILE_OFFSET_BITS=64. The Cog VMs are also > built with -D_GNU_SOURCE. > > Here's a line from a Squeak file list on the current Cog VM: > > (2014.10.11 07:00:46 7,115,143,880) > Formula1.2014.Round16.Russia.Qualifying.BBCOneHD.1080i.H264.English-wserhkzt.ts > > No 32-bit limit here. > > >> >> 2014-10-14 17:43 GMT+02:00 Evan Donahue : >> >>> The OS is Arch Linux. >>> >>> I can read the file with less. >>> >>> The problem, insofar as I can trace it, seems to stem from this line in >>> UnixStore: >>> >>> Primitives lookupDirectory: encodedPath filename: encodedBasename >>> >>> When I have my 57G file there this line returns nil. If I move the 57G >>> file and create a small file with the same name, the same command >>> successfully finds the file. I am not sure how large a file must be to >>> cause this issue, but A 1.5G file works fine. >>> >>> On Tue, Oct 14, 2014 at 8:17 AM, Nicolai Hess >>> wrote: >>> >>>> 2014-10-14 6:38 GMT+02:00 Evan Donahue : >>>> >>>>> Hi, thanks for the reply. >>>>> >>>>> The response is the same: "MessageNotUnderstood: >>>>> False>>humanReadableSIByteSize." >>>>> >>>>> This happens both to print-it as well as to do-it-and-go. Running the >>>>> command on the neighboring "wiki.torrent" torrent file yields the correct >>>>> 54kb. >>>>> >>>>> Thanks, >>>>> Evan >>>>> >>>>> On Tue, Oct 14, 2014 at 12:24 AM, Tudor Girba >>>>> wrote: >>>>> >>>>>> Hi, >>>>>> >>>>>> If I understand correctly, the failure occurs while navigating in the >>>>>> "Items" presentation. >>>>>> >>>>>> I cannot reproduce this problem because I do not have enough disk >>>>>> space for such a large file :). But, could you do the following and let me >>>>>> know what the outcome is: >>>>>> >>>>>> 'path/to/your/large/file.xml' asFileReference humanReadableSize >>>>>> >>>>>> ? >>>>>> >>>>>> Cheers, >>>>>> Doru >>>>>> >>>>>> >>>>>> >>>>>> On Tue, Oct 14, 2014 at 2:27 AM, Evan Donahue >>>>>> wrote: >>>>>> >>>>>>> Hello, I've run into some odd behavior and wanted to check whether I >>>>>>> might be missing something: >>>>>>> >>>>>>> I have downloaded a copy of the english wikipedia as an xml file and >>>>>>> am hoping to (sax) parse it. However, I can't even seem to get pharo to >>>>>>> recognize that the file exists. >>>>>>> >>>>>>> If I open FileSystem disk root in the playground and naigate, >>>>>>> attempting to enter the folder containing the (57G) xml file fails with >>>>>>> "MessageNotUnderstood: False>>humanReadableSIByteSize." Likewise if I get a >>>>>>> FileReference with FileSystem disk root / 'path' / 'to' / 'file' then self >>>>>>> exists returns false and the parser fails. >>>>>>> >>>>>>> Am I doing something wrong? Should I be able to do this? >>>>>>> >>>>>>> The version number is #40283 >>>>>>> >>>>>>> Thanks, >>>>>>> Evan >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> www.tudorgirba.com >>>>>> >>>>>> "Every thing has its own flow" >>>>>> >>>>> >>>>> >>>> >>>> Which OS ? >>>> Can you check with other programs if this file is readable at all? >>>> >>>> >>>> >>>> >>>> Nicolai >>>> >>>> >>>> >>> >> >> >> >> > > > -- > best, > Eliot > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/295b6794/attachment.htm From lewis at mail.msen.com Tue Oct 14 23:22:28 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 14 23:22:38 2014 Subject: [squeak-dev] Re: [Pharo-users] Trouble opening large files In-Reply-To: References: Message-ID: <20141014232228.GA84513@shell.msen.com> On Tue, Oct 14, 2014 at 09:29:51PM +0200, Nicolai Hess wrote: > Ah, good to know. At least for squeak, > bug 7522 can be closed :) > Closed. I'll note also that LFS is needed for saving large 64-bit image files :-) Dave From dale.henrichs at gemtalksystems.com Wed Oct 15 00:14:13 2014 From: dale.henrichs at gemtalksystems.com (Dale Henrichs) Date: Wed Oct 15 00:14:18 2014 Subject: [squeak-dev] http://build.squeak.org/ down? Message-ID: Getting a 503 at the moment ... Dale -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/d16bdc6e/attachment.htm From brasspen at gmail.com Wed Oct 15 00:37:56 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Wed Oct 15 00:38:01 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: References: Message-ID: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> Yes. I noticed this morning that Chris Muller has started a new SS process on box4. And the usual address [1] is routing to the default when there is no service on box2. I conclude that he is moving SS to box4 and is in-between boxes. I would imagine that the process on box4 needs to be announced by routing the dns on box2 to its new location [2]. [1] http://trunk.squeak.org [2] http://box4.squeak.org:8888 Chris > On Oct 14, 2014, at 8:14 PM, Dale Henrichs wrote: > > Getting a 503 at the moment ... > > Dale > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/734bc856/attachment.htm From lewis at mail.msen.com Wed Oct 15 00:52:03 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 15 00:52:06 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> References: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> Message-ID: <20141015005203.GA845@shell.msen.com> > On Tue, Oct 14, 2014 at 08:37:56PM -0400, Chris Cunnington wrote: > > On Oct 14, 2014, at 8:14 PM, Dale Henrichs wrote: > > > > Getting a 503 at the moment ... > > Yes. I noticed this morning that Chris Muller has started a new SS process > on box4. And the usual address [1] is routing to the default when there is > no service on box2. I conclude that he is moving SS to box4 and is in-between > boxes. I would imagine that the process on box4 needs to be announced by > routing the dns on box2 to its new location [2]. > No this is nothing to do with anything on box4. The build.squeak.org service is on box3 along with squeaksource.com. Squeaksource is fine, but Jenkins is not. There are currently about 30 Squeak VMs of various flavors running under the Jenkins uid. Ick. I'll try to restart the Jenkins service and see if I can clear out the mess. Dave From dale.henrichs at gemtalksystems.com Wed Oct 15 00:52:56 2014 From: dale.henrichs at gemtalksystems.com (Dale Henrichs) Date: Wed Oct 15 00:52:59 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: <20141015005203.GA845@shell.msen.com> References: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> <20141015005203.GA845@shell.msen.com> Message-ID: Thanks guys! On Tue, Oct 14, 2014 at 5:52 PM, David T. Lewis wrote: > > On Tue, Oct 14, 2014 at 08:37:56PM -0400, Chris Cunnington wrote: > > > On Oct 14, 2014, at 8:14 PM, Dale Henrichs < > dale.henrichs@gemtalksystems.com> wrote: > > > > > > Getting a 503 at the moment ... > > > > Yes. I noticed this morning that Chris Muller has started a new SS > process > > on box4. And the usual address [1] is routing to the default when there > is > > no service on box2. I conclude that he is moving SS to box4 and is > in-between > > boxes. I would imagine that the process on box4 needs to be announced by > > routing the dns on box2 to its new location [2]. > > > > No this is nothing to do with anything on box4. The build.squeak.org > service > is on box3 along with squeaksource.com. Squeaksource is fine, but Jenkins > is > not. There are currently about 30 Squeak VMs of various flavors running > under > the Jenkins uid. Ick. I'll try to restart the Jenkins service and see if I > can > clear out the mess. > > Dave > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/52e757cd/attachment-0001.htm From lewis at mail.msen.com Wed Oct 15 01:11:21 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 15 01:11:23 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: <20141015005203.GA845@shell.msen.com> References: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> <20141015005203.GA845@shell.msen.com> Message-ID: <20141015011121.GB845@shell.msen.com> On Tue, Oct 14, 2014 at 08:52:03PM -0400, David T. Lewis wrote: > > On Tue, Oct 14, 2014 at 08:37:56PM -0400, Chris Cunnington wrote: > > > On Oct 14, 2014, at 8:14 PM, Dale Henrichs wrote: > > > > > > Getting a 503 at the moment ... > > > > Yes. I noticed this morning that Chris Muller has started a new SS process > > on box4. And the usual address [1] is routing to the default when there is > > no service on box2. I conclude that he is moving SS to box4 and is in-between > > boxes. I would imagine that the process on box4 needs to be announced by > > routing the dns on box2 to its new location [2]. > > > > No this is nothing to do with anything on box4. The build.squeak.org service > is on box3 along with squeaksource.com. Squeaksource is fine, but Jenkins is > not. There are currently about 30 Squeak VMs of various flavors running under > the Jenkins uid. Ick. I'll try to restart the Jenkins service and see if I can > clear out the mess. > > Dave > I killed 41 rogue VMs running under Jenkins, and restarted the service. It is now apparently working. Frank ... we need to clean this up. Seriously. Dave From brasspen at gmail.com Wed Oct 15 01:45:38 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Wed Oct 15 01:45:44 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: <20141015005203.GA845@shell.msen.com> References: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> <20141015005203.GA845@shell.msen.com> Message-ID: <539222CD-1DA2-402E-A203-75FA19A0093F@gmail.com> Actually, I misread the question and saw what I wanted to see. The question was about build.squeak.org and I thought I saw trunk.squeak.org . Seems to me that what I?m saying about trunk.squeak.org is still true: it has been shut down on its usual subdomain; and, a new process has appeared on box4. Looks to me like trunk development is halted for the moment. Chris > On Oct 14, 2014, at 8:52 PM, David T. Lewis wrote: > >> On Tue, Oct 14, 2014 at 08:37:56PM -0400, Chris Cunnington wrote: >>> On Oct 14, 2014, at 8:14 PM, Dale Henrichs wrote: >>> >>> Getting a 503 at the moment ... >> >> Yes. I noticed this morning that Chris Muller has started a new SS process >> on box4. And the usual address [1] is routing to the default when there is >> no service on box2. I conclude that he is moving SS to box4 and is in-between >> boxes. I would imagine that the process on box4 needs to be announced by >> routing the dns on box2 to its new location [2]. >> > > No this is nothing to do with anything on box4. The build.squeak.org service > is on box3 along with squeaksource.com. Squeaksource is fine, but Jenkins is > not. There are currently about 30 Squeak VMs of various flavors running under > the Jenkins uid. Ick. I'll try to restart the Jenkins service and see if I can > clear out the mess. > > Dave > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141014/a5a61f19/attachment.htm From lewis at mail.msen.com Wed Oct 15 03:19:01 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 15 03:19:04 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: <539222CD-1DA2-402E-A203-75FA19A0093F@gmail.com> References: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> <20141015005203.GA845@shell.msen.com> <539222CD-1DA2-402E-A203-75FA19A0093F@gmail.com> Message-ID: <20141015031901.GA22312@shell.msen.com> Chris, I do not understand what you mean. If Chris Muller had wanted to make a change that affected our servers or the trunk development process, I am sure he would have cleared it with Levente and mentioned it on box-admins, as any of us would do if we were making such a change. Trunk development happens on source.squeak.org. The mirror of source.squeak.org that runs on http://box4.squeak.org:8888 with a Magma back end has been in service for a long time, and has been discussed on squeak-dev. As far as I am aware, nothing has changed on any of the outward facing boxes. So no, trunk development is not halted. The only thing that happened is that the Jenkins service melted down, and I restarted it. Dave On Tue, Oct 14, 2014 at 09:45:38PM -0400, Chris Cunnington wrote: > Actually, I misread the question and saw what I wanted to see. The question was about build.squeak.org and I thought I saw trunk.squeak.org . > Seems to me that what I???m saying about trunk.squeak.org is still true: it has been shut down on its usual subdomain; and, a new process has appeared on box4. > Looks to me like trunk development is halted for the moment. > > Chris > > > On Oct 14, 2014, at 8:52 PM, David T. Lewis wrote: > > > >> On Tue, Oct 14, 2014 at 08:37:56PM -0400, Chris Cunnington wrote: > >>> On Oct 14, 2014, at 8:14 PM, Dale Henrichs wrote: > >>> > >>> Getting a 503 at the moment ... > >> > >> Yes. I noticed this morning that Chris Muller has started a new SS process > >> on box4. And the usual address [1] is routing to the default when there is > >> no service on box2. I conclude that he is moving SS to box4 and is in-between > >> boxes. I would imagine that the process on box4 needs to be announced by > >> routing the dns on box2 to its new location [2]. > >> > > > > No this is nothing to do with anything on box4. The build.squeak.org service > > is on box3 along with squeaksource.com. Squeaksource is fine, but Jenkins is > > not. There are currently about 30 Squeak VMs of various flavors running under > > the Jenkins uid. Ick. I'll try to restart the Jenkins service and see if I can > > clear out the mess. > > > > Dave > > > > > > From brasspen at gmail.com Wed Oct 15 03:52:06 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Wed Oct 15 03:52:21 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: <20141015031901.GA22312@shell.msen.com> References: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> <20141015005203.GA845@shell.msen.com> <539222CD-1DA2-402E-A203-75FA19A0093F@gmail.com> <20141015031901.GA22312@shell.msen.com> Message-ID: <94AC507B-54F7-40C6-9075-EFCF3AA556C6@gmail.com> You?re absolutely right, David. Chris > On Oct 14, 2014, at 11:19 PM, David T. Lewis wrote: > > Chris, > > I do not understand what you mean. If Chris Muller had wanted to make a change > that affected our servers or the trunk development process, I am sure he would > have cleared it with Levente and mentioned it on box-admins, as any of us would > do if we were making such a change. > > Trunk development happens on source.squeak.org. The mirror of source.squeak.org > that runs on http://box4.squeak.org:8888 with a Magma back end has been in service > for a long time, and has been discussed on squeak-dev. As far as I am aware, > nothing has changed on any of the outward facing boxes. > > So no, trunk development is not halted. The only thing that happened is that > the Jenkins service melted down, and I restarted it. > > Dave > > > On Tue, Oct 14, 2014 at 09:45:38PM -0400, Chris Cunnington wrote: >> Actually, I misread the question and saw what I wanted to see. The question was about build.squeak.org and I thought I saw trunk.squeak.org . >> Seems to me that what I???m saying about trunk.squeak.org is still true: it has been shut down on its usual subdomain; and, a new process has appeared on box4. >> Looks to me like trunk development is halted for the moment. >> >> Chris >> >>> On Oct 14, 2014, at 8:52 PM, David T. Lewis wrote: >>> >>>> On Tue, Oct 14, 2014 at 08:37:56PM -0400, Chris Cunnington wrote: >>>>> On Oct 14, 2014, at 8:14 PM, Dale Henrichs wrote: >>>>> >>>>> Getting a 503 at the moment ... >>>> >>>> Yes. I noticed this morning that Chris Muller has started a new SS process >>>> on box4. And the usual address [1] is routing to the default when there is >>>> no service on box2. I conclude that he is moving SS to box4 and is in-between >>>> boxes. I would imagine that the process on box4 needs to be announced by >>>> routing the dns on box2 to its new location [2]. >>>> >>> >>> No this is nothing to do with anything on box4. The build.squeak.org service >>> is on box3 along with squeaksource.com. Squeaksource is fine, but Jenkins is >>> not. There are currently about 30 Squeak VMs of various flavors running under >>> the Jenkins uid. Ick. I'll try to restart the Jenkins service and see if I can >>> clear out the mess. >>> >>> Dave >>> >>> >> > >> > > From craig at netjam.org Wed Oct 15 12:57:54 2014 From: craig at netjam.org (Craig Latta) Date: Wed Oct 15 12:58:13 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: Hi Chris-- > > > Can't you sign the .app + the two scripts together? > > > > No; well, not with the scripts where you want them. The thing being > > signed has to conform to a particular Apple "bundle" format, which > > wants everything to be rooted in the .app directory. > > Could the scripts be placed in the .app directory then, as siblings of > the Contents dir? No, that's what got this conversation started in the first place (when Apple changed their signing code for MacOS 10.9.5). The bundle format that the signing code now requires does not allow for siblings of the Contents directory. That's why I suggested putting those scripts in .app/Contents/LinuxAndWindows/. Since there's only one choice of where to look next at the ".app" and "Contents" levels, and "LinuxAndWindows" is obvious, even an impatient newbie will find the scripts, and we avoid any ZIP-within-a-ZIP silliness. > I'm not understanding the... requirement of the inner-Zip... The format of the contents of the ZIP has to be a certain way for the signing-zip-unzip process to yield a valid signature. This includes the .app directory itself having no siblings, and there being no siblings of .app/Contents/. Please, if yer gonna get angry, get angry at Apple (and tell them!). I certainly will. I think it's incredibly stupid that I'm not allowed to have a .app/README file. It's Unix heresy! :) Let's please save any further discussion of this for the next board meeting, when we can all speak interactively. Thanks! -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From list at afceurope.com Wed Oct 15 14:57:15 2014 From: list at afceurope.com (Annick Fron) Date: Wed Oct 15 14:57:17 2014 Subject: [squeak-dev] FFI syntax Message-ID: What is the syntax to describe an external structure with an array of int of size 6 ? I know only the syntax fields ^#( (param1 ?long?) (param2 ?long?) (param3 ?long?) (param4 ?long?) (param5 ?long?) (param6 ?long?) ) Annick From eliot.miranda at gmail.com Wed Oct 15 17:18:04 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 15 17:18:07 2014 Subject: [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: Hi Annick, On Wed, Oct 15, 2014 at 7:57 AM, Annick Fron wrote: > What is the syntax to describe an external structure with an array of int > of size 6 ? > > I know only the syntax > > fields > ^#( > (param1 ?long?) > (param2 ?long?) > (param3 ?long?) > (param4 ?long?) > (param5 ?long?) > (param6 ?long?) > ) > Hmm. Good question. It seems you can write fields "IAXCallStateEvent defineFields" ^#( (type 'long') (callNo 'long') (state 'long') (format 'long') (vformat 'long') (remote 'char[256]') (remoteName 'char[256]') (local 'char[256]') (localContext 'char[256]') ) But as a community we really need to document the FFI more thoroughly :-/ > > Annick > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141015/93b20f22/attachment.htm From eliot.miranda at gmail.com Wed Oct 15 19:45:11 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 15 19:45:14 2014 Subject: [squeak-dev] windows in all projects? Message-ID: Hi, occasionally I find it useful to have a window that is always present in the current project, so that wen I change projects the window either moves to the new project, or is in all worlds. Is there a way of doing this in the standard system? (I can't see this from reading the labyrinthine project enter code, but I could be missing something ;-) ). Anyone have a changeset to do the same? -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141015/eec5ec9e/attachment.htm From karlramberg at gmail.com Wed Oct 15 19:53:35 2014 From: karlramberg at gmail.com (karl ramberg) Date: Wed Oct 15 19:53:38 2014 Subject: [squeak-dev] windows in all projects? In-Reply-To: References: Message-ID: You can maybe put the window in a shared flap? Karl On Wed, Oct 15, 2014 at 9:45 PM, Eliot Miranda wrote: > Hi, > > occasionally I find it useful to have a window that is always present > in the current project, so that wen I change projects the window either > moves to the new project, or is in all worlds. Is there a way of doing > this in the standard system? (I can't see this from reading the > labyrinthine project enter code, but I could be missing something ;-) ). > Anyone have a changeset to do the same? > > -- > best, > Eliot > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141015/dbd28e71/attachment.htm From commits at source.squeak.org Wed Oct 15 20:23:12 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 15 20:23:14 2014 Subject: [squeak-dev] The Trunk: MonticelloConfigurations-bf.128.mcz Message-ID: Bert Freudenberg uploaded a new version of MonticelloConfigurations to project The Trunk: http://source.squeak.org/trunk/MonticelloConfigurations-bf.128.mcz ==================== Summary ==================== Name: MonticelloConfigurations-bf.128 Author: bf Time: 15 October 2014, 1:18:18.317 pm UUID: dc6bd95c-a076-46e7-9b68-f89121087387 Ancestors: MonticelloConfigurations-eem.127 Make the name of the update config map configurable. =============== Diff against MonticelloConfigurations-eem.127 =============== Item was removed: - ----- Method: MCConfigurationBrowser>>add (in category 'actions') ----- - add - (self pickWorkingCopiesSatisfying: [:each | (self includesPackage: each package) not]) - do: [:wc | - wc ancestors isEmpty - ifTrue: [self inform: 'You must save ', wc packageName, ' first!! - Skipping this package'] - ifFalse: [ - self dependencies add: (MCVersionDependency - package: wc package - info: wc ancestors first)]]. - self changed: #dependencyList; changed: #description! Item was changed: ----- Method: MCConfigurationBrowser>>buttonSpecs (in category 'morphic ui') ----- buttonSpecs + ^ #(('Add' addDependency 'Add a dependency') - ^ #(('Add' add 'Add a dependency') ('Update' updateMenu 'Update dependencies') ('Install' installMenu 'Load/Merge/Upgrade into image') ('Up' up 'Move item up in list' canMoveUp) ('Down' down 'Move item down in list' canMoveDown) ('Remove' remove 'Remove item' canRemove) ('Store' store 'store configuration') ('Post' post 'Post this configuration to an update stream') )! Item was changed: Object subclass: #MCMcmUpdater instanceVariableNames: '' + classVariableNames: 'DefaultUpdateURL LastUpdateMap SkipPackages UpdateFromServerAtStartup UpdateMapName UpdateMissingPackages' - classVariableNames: 'DefaultUpdateURL LastUpdateMap SkipPackages UpdateFromServerAtStartup UpdateMissingPackages' poolDictionaries: '' category: 'MonticelloConfigurations'! !MCMcmUpdater commentStamp: 'cbc 8/26/2010 16:42' prior: 0! MCMcmUpdater provides utility methods for updating Monticello packages from Monticello configurations. When Monticello configurations are stored in a repository (or repositories), MCMcmUpdater acts as an update stream. It first ensures that each configuration map has been loaded in sequence, then updates the last configuration map to the most recent version for each specified package, and finally loads these versions to produce a fully updated configuration. Currently if a set of packages are unloaded from the image, using this class to reload them may cause problems, depending on what dependencies those classes have. Success is not assured. Removing packages via SmalltalkImage>>unloadAllKnownPackages will be successful, it flags the packages removed so that they are not loaded by this utility. If you wish to not have MCMcmUpdater update packages, there are two ways to handle this: 1) To have MCMcmUpdater not update any packages not currently in the image set the UpdateMissingPackages preference to false: MCMcmUpdater updateMissingPackages: false Note that any new packages added to the repositories will not be picked up when this is turned off. 2) To have MCMcmUpdater not update a specific package, evaluate MCMcmUpdater disableUpdatesOfPackage: Class Variables definitions: DefaultUpdateURL - String: the URL that will be checked by default for updates. This would be set for a common standard location to check. LastUpdateMap - Dictionary of Integer: version number of the last loaded update map per repository. Keeps track of the last configuration map, so that the utility will not have to run through the full history in the repositories each time you ask to update. SkipPackages - Set of Strings: names of packages to not update in MCMcmUpdater (empty by default). UpdateMissingPackages - Boolean: if true (default), new packages in the update config map will be loaded unless they are in SkipPackages. If false, packages not currently loaded in the image will not be loaded by MCMcmUpdater. (This can be dangerous if packages are split - use at your own risk). ! Item was changed: ----- Method: MCMcmUpdater class>>updateListFor: (in category 'private') ----- updateListFor: repo | updateList allNames minVersion | updateList := OrderedCollection new. minVersion := LastUpdateMap at: repo description ifAbsent: [0]. + "Find all the update-*.mcm files" - "Find all the updates-author.version.mcm files" allNames := 'Checking ', repo description displayProgressFrom: 0 to: 1 during: [:bar| bar value: 0. repo allFileNamesOrCache ]. + allNames do: [:fileName | | version | + ((fileName endsWith: '.mcm') + and: [fileName packageAndBranchName = self updateMapName + and: [(version := fileName versionNumber) >= minVersion]]) + ifTrue: [updateList add: version -> fileName]]. - allNames do: [:versionedName | | version base parts author type | - parts := versionedName findTokens: '.-'. - parts size = 4 ifTrue: [ - base := parts at: 1. - author := parts at: 2. - version := [(parts at: 3) asNumber] on: Error do: [:ex | ex return: 0]. - type := parts at: 4. - ]. - (base = 'update' and: [version >= minVersion and: [type = 'mcm']]) - ifTrue: [updateList add: version -> versionedName]]. ^updateList sort! Item was added: + ----- Method: MCMcmUpdater class>>updateMapName (in category 'preferences') ----- + updateMapName + "Name for update map, without version info" + + + + ^UpdateMapName ifNil: ['update']! Item was added: + ----- Method: MCMcmUpdater class>>updateMapName: (in category 'preferences') ----- + updateMapName: aString + "Name for update map, without version info" + UpdateMapName := aString! From tim at rowledge.org Wed Oct 15 20:23:25 2014 From: tim at rowledge.org (tim Rowledge) Date: Wed Oct 15 20:23:31 2014 Subject: [squeak-dev] windows in all projects? In-Reply-To: References: Message-ID: <726BEE5A-4153-442A-9F69-BF99E7DCE8EA@rowledge.org> > On Wed, Oct 15, 2014 at 9:45 PM, Eliot Miranda wrote: > Hi, > > occasionally I find it useful to have a window that is always present in the current project, so that wen I change projects the window either moves to the new project, or is in all worlds. Is there a way of doing this in the standard system? (I can't see this from reading the labyrinthine project enter code, but I could be missing something ;-) ). Anyone have a changeset to do the same? Wow, I remember using this all the time back in the Old Days. I think you wrote the code for MVC to do it. Or maybe it was me after talking with you about it? Dunno. IIRC it wasn?t at all hard in MVC-land but after looking at how this sort of thing is done in Ankh-Morph-pork I?m not sure it?s intelligible to mere humans. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Fac me cocleario vomere! = Gag me with a spoon! From nicolaihess at web.de Wed Oct 15 20:59:33 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Wed Oct 15 20:59:36 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: 2014-10-15 19:18 GMT+02:00 Eliot Miranda : > Hi Annick, > > On Wed, Oct 15, 2014 at 7:57 AM, Annick Fron wrote: > >> What is the syntax to describe an external structure with an array of int >> of size 6 ? >> >> I know only the syntax >> >> fields >> ^#( >> (param1 ?long?) >> (param2 ?long?) >> (param3 ?long?) >> (param4 ?long?) >> (param5 ?long?) >> (param6 ?long?) >> ) >> > > Hmm. Good question. It seems you can write > > fields > "IAXCallStateEvent defineFields" > ^#( > (type 'long') > (callNo 'long') > (state 'long') > (format 'long') > (vformat 'long') > (remote 'char[256]') > (remoteName 'char[256]') > (local 'char[256]') > (localContext 'char[256]') > ) > > > But as a community we really need to document the FFI more thoroughly :-/ > > +1 I can not even find up to date information on how to *install* current working FFI. Aren't there any "alive" projects build on FFI (old or Alien-FFI). It would help to see more real-life examples. > >> Annick >> > > > > -- > best, > Eliot > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141015/e8bd7f98/attachment.htm From cunningham.cb at gmail.com Wed Oct 15 21:09:52 2014 From: cunningham.cb at gmail.com (Chris Cunningham) Date: Wed Oct 15 21:09:54 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: So, I use the ODBC package from SqueakMap, which relies on FFI. It works. Although I have a fun time trying to remember how to do it each time, so I wrote notes the last time. In essence: - this last one because it regularly fails for Win32 things, which I use. Among other things, this part requires you to turn on _ as part of variable names, so that things like WS_EX_ACCEPTFILES := 16r10. is valid. Note this is all old FFI - not Alien. -cbc On Wed, Oct 15, 2014 at 1:59 PM, Nicolai Hess wrote: > 2014-10-15 19:18 GMT+02:00 Eliot Miranda : > >> Hi Annick, >> >> On Wed, Oct 15, 2014 at 7:57 AM, Annick Fron wrote: >> >>> What is the syntax to describe an external structure with an array of >>> int of size 6 ? >>> >>> I know only the syntax >>> >>> fields >>> ^#( >>> (param1 ?long?) >>> (param2 ?long?) >>> (param3 ?long?) >>> (param4 ?long?) >>> (param5 ?long?) >>> (param6 ?long?) >>> ) >>> >> >> Hmm. Good question. It seems you can write >> >> fields >> "IAXCallStateEvent defineFields" >> ^#( >> (type 'long') >> (callNo 'long') >> (state 'long') >> (format 'long') >> (vformat 'long') >> (remote 'char[256]') >> (remoteName 'char[256]') >> (local 'char[256]') >> (localContext 'char[256]') >> ) >> > > > > >> >> But as a community we really need to document the FFI more thoroughly :-/ >> >> > > +1 > I can not even find up to date information on how to *install* current > working FFI. > Aren't there any "alive" projects build on FFI (old or Alien-FFI). > It would help to see more real-life examples. > > > > >> >>> Annick >>> >> >> >> >> -- >> best, >> Eliot >> > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141015/64d1b582/attachment.htm From lewis at mail.msen.com Wed Oct 15 21:22:39 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 15 21:22:41 2014 Subject: [squeak-dev] windows in all projects? In-Reply-To: <726BEE5A-4153-442A-9F69-BF99E7DCE8EA@rowledge.org> References: <726BEE5A-4153-442A-9F69-BF99E7DCE8EA@rowledge.org> Message-ID: <20141015212239.GA15727@shell.msen.com> On Wed, Oct 15, 2014 at 01:23:25PM -0700, tim Rowledge wrote: > > > On Wed, Oct 15, 2014 at 9:45 PM, Eliot Miranda wrote: > > Hi, > > > > occasionally I find it useful to have a window that is always present in the current project, so that wen I change projects the window either moves to the new project, or is in all worlds. Is there a way of doing this in the standard system? (I can't see this from reading the labyrinthine project enter code, but I could be missing something ;-) ). Anyone have a changeset to do the same? > > Wow, I remember using this all the time back in the Old Days. I think you wrote the code for MVC to do it. Or maybe it was me after talking with you about it? Dunno. IIRC it wasn?t at all hard in MVC-land but after looking at how this sort of thing is done in Ankh-Morph-pork I?m not sure it?s intelligible to mere humans. > Interesting question. Karl's suggestion of using a shared flap is probably the quickest expedient. But more generally: MorphicProject and MVCProject would need to handle this differently as would (the regrettably yet to be implemented) SeasideProject, AidaProject, and CuisMorphic3Project. So the concept would make sense within a given species of Project. For MVC it would presumably be a matter of adding a new View for the given Model in all of the projects of type MVCProject. For Morphic, it is probably a matter of inserting the actual Morph into the morph hierarchy for all projects of type MorphicProject. In either case, these would need to be top level windows, so the insertion logic is probably not too hard to figure out. I guess you would want some window menu option to make the window sticky in all projects, or to remove it from all other projects except the currently active one. Also a visual indicator that the window has been pinned to all relevant projects. It is probably also possible to make the window be migratory (Eliot's suggestion of having it be reopened in the currently active project, whatever that might happen to be). However, as a practical matter that probably would need to be limited to moving from one project to another of the same type, unless of course we do a more complete implementation of ToolBuilder for all windows of interest. This would make a great project for somebody to try. Part concept, part requirements, part design, part implementation, and none of it too huge in scope. Any takers? Dave From cunningham.cb at gmail.com Wed Oct 15 21:41:26 2014 From: cunningham.cb at gmail.com (Chris Cunningham) Date: Wed Oct 15 21:41:32 2014 Subject: [squeak-dev] windows in all projects? In-Reply-To: <20141015212239.GA15727@shell.msen.com> References: <726BEE5A-4153-442A-9F69-BF99E7DCE8EA@rowledge.org> <20141015212239.GA15727@shell.msen.com> Message-ID: On Wed, Oct 15, 2014 at 2:22 PM, David T. Lewis wrote: > On Wed, Oct 15, 2014 at 01:23:25PM -0700, tim Rowledge wrote: > > > > > On Wed, Oct 15, 2014 at 9:45 PM, Eliot Miranda < > eliot.miranda@gmail.com> wrote: > > > Hi, > > > > > > occasionally I find it useful to have a window that is always > present in the current project, so that wen I change projects the window > either moves to the new project, or is in all worlds. Is there a way of > doing this in the standard system? (I can't see this from reading the > labyrinthine project enter code, but I could be missing something ;-) ). > Anyone have a changeset to do the same? > > > > Wow, I remember using this all the time back in the Old Days. I think > you wrote the code for MVC to do it. Or maybe it was me after talking with > you about it? Dunno. IIRC it wasn?t at all hard in MVC-land but after > looking at how this sort of thing is done in Ankh-Morph-pork I?m not sure > it?s intelligible to mere humans. > > > > Interesting question. Karl's suggestion of using a shared flap is probably > the quickest expedient. But more generally: > > MorphicProject and MVCProject would need to handle this differently as > would > (the regrettably yet to be implemented) SeasideProject, AidaProject, and > CuisMorphic3Project. So the concept would make sense within a given species > of Project. Maybe an alternative would be to actually make use of the native windows support (finally?) to handle this. I think I remember that one of the prototypes was to have one of the native windows be its own project - so you could with the primary window around like mad between project (event including a Tweak project, say), while this other window just stays open. As I understand it, this isn't done yet, and I probably wouldn't be able to do it, but sounds like an actually useful use for the native window concept - a window that sticks around when you switch projects. -cbc -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141015/76d93793/attachment.htm From lewis at mail.msen.com Wed Oct 15 21:50:24 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 15 21:50:26 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> Message-ID: <20141015215024.GB15727@shell.msen.com> On Wed, Oct 15, 2014 at 02:57:54PM +0200, Craig Latta wrote: > > Let's please save any further discussion of this for the next board > meeting, when we can all speak interactively. Thanks! Happily our next board meeting is tomorrow, so I'm sure we can sort out any confusion. However, I do want to note for the record that figuring out implementation issues such as this is the business of the Squeak community at large, not the board. So if we come up with any great ideas tomorrow, let's make sure that we contribute them to the community right here on squeak-dev for discussion. FWIW, I'm not a big proponent of the all-in-one as a primary release artifact. But having said that I think that Craig's point of view has merit, based on the fact that he has actually tried it out on a range of actual new users. I also agree with Craig's position that it is up the the release manager to take care of the release artifacts. It is perfectly OK to agree to disagree, and we dissenters should simply note our point of view and move on. Dave From craig at netjam.org Wed Oct 15 21:59:32 2014 From: craig at netjam.org (Craig Latta) Date: Wed Oct 15 21:59:52 2014 Subject: [squeak-dev] re: Squeak-4.5-All-in-One.zip In-Reply-To: <20141015215024.GB15727@shell.msen.com> References: <20cf303b3ba57d3d1805052cd468@google.com> <5439C0E1.2040600@netjam.org> <815301C2-77DF-44AD-93EA-D4BA75A770FA@gmx.de> <20141015215024.GB15727@shell.msen.com> Message-ID: > ...figuring out implementation issues such as this is the business of > the Squeak community at large, not the board. Oh, indeed, good point. I was only noting an opportunity to move a conversation between two people who happen to be on the board from email to an interactive board meeting. :) Thanks for clarifying. -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From eliot.miranda at gmail.com Wed Oct 15 22:25:30 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 15 22:25:34 2014 Subject: [squeak-dev] windows in all projects? In-Reply-To: <20141015212239.GA15727@shell.msen.com> References: <726BEE5A-4153-442A-9F69-BF99E7DCE8EA@rowledge.org> <20141015212239.GA15727@shell.msen.com> Message-ID: On Wed, Oct 15, 2014 at 2:22 PM, David T. Lewis wrote: > On Wed, Oct 15, 2014 at 01:23:25PM -0700, tim Rowledge wrote: > > > > > On Wed, Oct 15, 2014 at 9:45 PM, Eliot Miranda < > eliot.miranda@gmail.com> wrote: > > > Hi, > > > > > > occasionally I find it useful to have a window that is always > present in the current project, so that wen I change projects the window > either moves to the new project, or is in all worlds. Is there a way of > doing this in the standard system? (I can't see this from reading the > labyrinthine project enter code, but I could be missing something ;-) ). > Anyone have a changeset to do the same? > > > > Wow, I remember using this all the time back in the Old Days. I think > you wrote the code for MVC to do it. Or maybe it was me after talking with > you about it? Dunno. IIRC it wasn?t at all hard in MVC-land but after > looking at how this sort of thing is done in Ankh-Morph-pork I?m not sure > it?s intelligible to mere humans. > > > > Interesting question. Karl's suggestion of using a shared flap is probably > the quickest expedient. But more generally: > > MorphicProject and MVCProject would need to handle this differently as > would > (the regrettably yet to be implemented) SeasideProject, AidaProject, and > CuisMorphic3Project. So the concept would make sense within a given species > of Project. > When I did this years ago I just added a per-window property and had the Project enter code check for the property and move it if set. So one could move windows between projects by setting, entering and unsetting. That's simple. But I hoped someone had already done this. The Project code is complex enough as it is... > For MVC it would presumably be a matter of adding a new View for the given > Model in all of the projects of type MVCProject. For Morphic, it is > probably > a matter of inserting the actual Morph into the morph hierarchy for all > projects of type MorphicProject. In either case, these would need to be > top level windows, so the insertion logic is probably not too hard to > figure > out. > > I guess you would want some window menu option to make the window sticky > in all projects, or to remove it from all other projects except the > currently > active one. Also a visual indicator that the window has been pinned to all > relevant projects. > > It is probably also possible to make the window be migratory (Eliot's > suggestion of having it be reopened in the currently active project, > whatever that might happen to be). However, as a practical matter that > probably would need to be limited to moving from one project to another > of the same type, unless of course we do a more complete implementation > of ToolBuilder for all windows of interest. > > This would make a great project for somebody to try. Part concept, part > requirements, part design, part implementation, and none of it too huge > in scope. Any takers? > > Dave > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141015/fd06cac3/attachment.htm From lewis at mail.msen.com Wed Oct 15 22:51:19 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 15 22:51:21 2014 Subject: [squeak-dev] windows in all projects? In-Reply-To: References: <726BEE5A-4153-442A-9F69-BF99E7DCE8EA@rowledge.org> <20141015212239.GA15727@shell.msen.com> Message-ID: <20141015225119.GA32208@shell.msen.com> On Wed, Oct 15, 2014 at 03:25:30PM -0700, Eliot Miranda wrote: > > When I did this years ago I just added a per-window property and had the > Project enter code check for the property and move it if set. So one could > move windows between projects by setting, entering and unsetting. That's > simple. But I hoped someone had already done this. The Project code is > complex enough as it is... Sorry, I am confused. Do you mean that you have done this previously in another dialect and that you are hoping that someone has done something similar in Squeak? I think I am misunderstanding your question, sorry. Dave From commits at source.squeak.org Wed Oct 15 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 15 23:55:05 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141015235502.4644.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007332.html Name: MonticelloConfigurations-bf.128 Ancestors: MonticelloConfigurations-eem.127 Make the name of the update config map configurable. ============================================= From brasspen at gmail.com Thu Oct 16 02:07:59 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Thu Oct 16 02:08:06 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage Message-ID: <7EFDF49E-397A-46E5-A4EB-087534734CCC@gmail.com> The FunSqueak link is in the Beginners? section of the Downloads page. The Donate button is on the homepage. Chris From tim at rowledge.org Thu Oct 16 02:13:40 2014 From: tim at rowledge.org (tim Rowledge) Date: Thu Oct 16 02:13:51 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: <7EFDF49E-397A-46E5-A4EB-087534734CCC@gmail.com> References: <7EFDF49E-397A-46E5-A4EB-087534734CCC@gmail.com> Message-ID: <2D7A313F-707D-4E89-B42D-F79B37E907C2@rowledge.org> On 15-10-2014, at 7:07 PM, Chris Cunnington wrote: > The FunSqueak link is in the Beginners? section of the Downloads page. The Donate button is on the homepage Yay! Thanks Chris. Now, everybody else:- please consider donating a few dollars/pounds/yen/euros/bolivars/escudos/whatevers. It goes towards supporting the servers that we rely upon to bring you Squeak. No money, no servers. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim A "politically savvy challenge to evolution" is as self-evidently ridiculous as an agriculturally savvy challenge to euclidean geometry would be. From frank.shearar at gmail.com Thu Oct 16 06:43:57 2014 From: frank.shearar at gmail.com (Frank Shearar) Date: Thu Oct 16 06:44:27 2014 Subject: [squeak-dev] http://build.squeak.org/ down? In-Reply-To: <20141015005203.GA845@shell.msen.com> References: <92E49FFD-06B6-4BC4-9CD5-9405CA8D7561@gmail.com> <20141015005203.GA845@shell.msen.com> Message-ID: <543f6944.459dc20a.572e.ffff8048@mx.google.com> The VM processes are apt to leak for reasons unknown: Maybe Jenkins can't track the shell games I have to try play with Squeak. Suggestions for improvement actively sought. -----Original Message----- From: "David T. Lewis" Sent: ?15/?10/?2014 01:52 To: "The general-purpose Squeak developers list" Subject: Re: [squeak-dev] http://build.squeak.org/ down? > On Tue, Oct 14, 2014 at 08:37:56PM -0400, Chris Cunnington wrote: > > On Oct 14, 2014, at 8:14 PM, Dale Henrichs wrote: > > > > Getting a 503 at the moment ... > > Yes. I noticed this morning that Chris Muller has started a new SS process > on box4. And the usual address [1] is routing to the default when there is > no service on box2. I conclude that he is moving SS to box4 and is in-between > boxes. I would imagine that the process on box4 needs to be announced by > routing the dns on box2 to its new location [2]. > No this is nothing to do with anything on box4. The build.squeak.org service is on box3 along with squeaksource.com. Squeaksource is fine, but Jenkins is not. There are currently about 30 Squeak VMs of various flavors running under the Jenkins uid. Ick. I'll try to restart the Jenkins service and see if I can clear out the mess. Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141016/3516ce69/attachment.htm From list at afceurope.com Thu Oct 16 09:53:18 2014 From: list at afceurope.com (Annick Fron) Date: Thu Oct 16 09:53:27 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: <45BD1B8B-0EBB-4276-A377-8A85DF1C58FC@afceurope.com> Hi Eliot, Thank you. Meanwhile I have tried to use only pointers to structs by writing some C code. I confirm that in Pharo you can load FFI and OldAlien in the ConfigurationBrowser. Yet it seems both FFI and Alien versions in the ConfigurationBrowser are behind the squeak repositories. I did not try if the new versions worked. I have posted some time ago an example for X11 windows on Linux, and I never got an answer why it was failing. It was the following testGetOurWindowLocation "self new testGetOurWindowLocation" | display ourWindow aParent anX anY aWidth aHeight aBorderWidth aDepth | display := X11Display XOpenDisplay: nil. ourWindow := display ourWindow. (Alien lookup: 'XGetGeometry' inLibrary: 'X11') primFFICallResult: nil withArguments: {display. ourWindow xid. (aParent := Alien new: 4). (anX := Alien new: 4). (anY := Alien new: 4). (aWidth := Alien new: 4). (aHeight := Alien new: 4). (aBorderWidth := Alien new: 4). (aDepth := Alien new: 4)}. (anX unsignedLongAt: 1) inspect. Has anybody looked at Wayland (replacement of X11) on Linux ? Annick Le 15 oct. 2014 ? 19:18, Eliot Miranda a ?crit : > Hi Annick, > > On Wed, Oct 15, 2014 at 7:57 AM, Annick Fron wrote: > What is the syntax to describe an external structure with an array of int of size 6 ? > > I know only the syntax > > fields > ^#( > (param1 ?long?) > (param2 ?long?) > (param3 ?long?) > (param4 ?long?) > (param5 ?long?) > (param6 ?long?) > ) > > Hmm. Good question. It seems you can write > > fields > "IAXCallStateEvent defineFields" > ^#( > (type 'long') > (callNo 'long') > (state 'long') > (format 'long') > (vformat 'long') > (remote 'char[256]') > (remoteName 'char[256]') > (local 'char[256]') > (localContext 'char[256]') > ) > > But as a community we really need to document the FFI more thoroughly :-/ > > > Annick > > > > -- > best, > Eliot Le 15 oct. 2014 ? 19:18, Eliot Miranda a ?crit : > Hi Annick, > > On Wed, Oct 15, 2014 at 7:57 AM, Annick Fron wrote: > What is the syntax to describe an external structure with an array of int of size 6 ? > > I know only the syntax > > fields > ^#( > (param1 ?long?) > (param2 ?long?) > (param3 ?long?) > (param4 ?long?) > (param5 ?long?) > (param6 ?long?) > ) > > Hmm. Good question. It seems you can write > > fields > "IAXCallStateEvent defineFields" > ^#( > (type 'long') > (callNo 'long') > (state 'long') > (format 'long') > (vformat 'long') > (remote 'char[256]') > (remoteName 'char[256]') > (local 'char[256]') > (localContext 'char[256]') > ) > > But as a community we really need to document the FFI more thoroughly :-/ > > > Annick > > > > -- > best, > Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141016/a500fbe3/attachment-0001.htm From leves at elte.hu Thu Oct 16 11:46:45 2014 From: leves at elte.hu (Levente Uzonyi) Date: Thu Oct 16 11:46:51 2014 Subject: [squeak-dev] SqueakSSL + TLS SNI Message-ID: Hi, I've implemented support for TLS SNI[1] for SqueakSSL on unix. I've uploaded the modified source files[2][3], a diff[4], and a prebuilt module[5] (built on Ubuntu 14.04 from the Cog branch). The image side code is also available[6], along with an updated version of the WebClient[7] package, and intermediate packages with various improvements[8]. The image side code works even if the plugin doesn't support TLS SNI, but this version of WebClient won't work with older versions of the SqueakSSL-Core package. Please review the changes, and consider adding them to the corresponding repositories! Levente [1] https://en.wikipedia.org/wiki/Server_Name_Indication [2] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL.h [3] http://leves.web.elte.hu/squeak/SqueakSSL/sqUnixOpenSSL.c [4] http://leves.web.elte.hu/squeak/SqueakSSL/diff.txt [5] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL [6] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL-Core-ul.29.mcz [7] http://leves.web.elte.hu/squeak/SqueakSSL/WebClient-Core-ul.98.mcz [8] http://leves.web.elte.hu/squeak/SqueakSSL/ From nicolaihess at web.de Thu Oct 16 12:00:28 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Thu Oct 16 12:00:53 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: <45BD1B8B-0EBB-4276-A377-8A85DF1C58FC@afceurope.com> References: <45BD1B8B-0EBB-4276-A377-8A85DF1C58FC@afceurope.com> Message-ID: 2014-10-16 11:53 GMT+02:00 Annick Fron : > Hi Eliot, > > Thank you. Meanwhile I have tried to use only pointers to structs by > writing some C code. > > I confirm that in Pharo you can load FFI and OldAlien in the > ConfigurationBrowser. > Yet it seems both FFI and Alien versions in the ConfigurationBrowser are > behind the squeak repositories. > I did not try if the new versions worked. > > I have posted some time ago an example for X11 windows on Linux, and I > never got an answer why it was failing. > actually I did answer ;) http://forum.world.st/FFI-on-Linux-again-td4780236.html and you changed the argument "ourWindow" to "ourWindow xid" like I proposed. But yes, actually this didn't help, I guess. You still get the error "bad argument" ? My next bet would be: Maybe we cannot mix Alien calls with (old) FFI structures (display is a externalstructure defined for FFI). > > It was the following > testGetOurWindowLocation > "self new testGetOurWindowLocation" > > | display ourWindow aParent anX anY aWidth aHeight aBorderWidth aDepth | > display := X11Display XOpenDisplay: nil. > ourWindow := display ourWindow. > (Alien lookup: 'XGetGeometry' inLibrary: 'X11') > primFFICallResult: nil > withArguments: > {display. > ourWindow xid. > (aParent := Alien new: 4). > (anX := Alien new: 4). > (anY := Alien new: 4). > (aWidth := Alien new: 4). > (aHeight := Alien new: 4). > (aBorderWidth := Alien new: 4). > (aDepth := Alien new: 4)}. > (anX unsignedLongAt: 1) inspect. > > Has anybody looked at Wayland (replacement of X11) on Linux ? > > Annick > > Le 15 oct. 2014 ? 19:18, Eliot Miranda a ?crit : > > Hi Annick, > > On Wed, Oct 15, 2014 at 7:57 AM, Annick Fron wrote: > >> What is the syntax to describe an external structure with an array of int >> of size 6 ? >> >> I know only the syntax >> >> fields >> ^#( >> (param1 ?long?) >> (param2 ?long?) >> (param3 ?long?) >> (param4 ?long?) >> (param5 ?long?) >> (param6 ?long?) >> ) >> > > Hmm. Good question. It seems you can write > > fields > "IAXCallStateEvent defineFields" > ^#( > (type 'long') > (callNo 'long') > (state 'long') > (format 'long') > (vformat 'long') > (remote 'char[256]') > (remoteName 'char[256]') > (local 'char[256]') > (localContext 'char[256]') > ) > > But as a community we really need to document the FFI more thoroughly :-/ > > >> >> Annick >> > > > > -- > best, > Eliot > > Le 15 oct. 2014 ? 19:18, Eliot Miranda a ?crit : > > Hi Annick, > > On Wed, Oct 15, 2014 at 7:57 AM, Annick Fron wrote: > >> What is the syntax to describe an external structure with an array of int >> of size 6 ? >> >> I know only the syntax >> >> fields >> ^#( >> (param1 ?long?) >> (param2 ?long?) >> (param3 ?long?) >> (param4 ?long?) >> (param5 ?long?) >> (param6 ?long?) >> ) >> > > Hmm. Good question. It seems you can write > > fields > "IAXCallStateEvent defineFields" > ^#( > (type 'long') > (callNo 'long') > (state 'long') > (format 'long') > (vformat 'long') > (remote 'char[256]') > (remoteName 'char[256]') > (local 'char[256]') > (localContext 'char[256]') > ) > > But as a community we really need to document the FFI more thoroughly :-/ > > >> >> Annick >> > > > > -- > best, > Eliot > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141016/99320cf4/attachment.htm From gus.duarte at gmail.com Thu Oct 16 13:23:51 2014 From: gus.duarte at gmail.com (Gustavo Duarte) Date: Thu Oct 16 13:23:55 2014 Subject: [squeak-dev] Fwd: usb 3.0 support on Linux In-Reply-To: References: Message-ID: FYI ---------- Forwarded message ---------- From: Gustavo Duarte Date: Thu, Oct 16, 2014 at 10:58 AM Subject: usb 3.0 support on Linux To: Squeak Virtual Machine Development Discussion < vm-dev@lists.squeakfoundation.org> Hey guys, I'm having troubles with enchanting application ( http://enchanting.robotclub.ab.ca/Enchanting+On+Linux), as you know based on squeak. In particular the problem is, running Enchanting on Ubuntu 12.04 and squeak-vm 4.10, the frontend isn't detect the presence of the Lego Brick when is connected through USB port. I guess that the problem is the type of USB port, because when use Enchanting on a PC with USB 2.0 with the same software environment, Ubuntu 12.04 + squeak-vm +Enchanting version, all work fine. However when i try on a PC with USB 3.0 the frontend isn't detecte the brick. Other additional information, Ubuntu 12.04 use for USB 2.0 ehci-pci driver module and for 3.0 use xhci_hcd. So my guess is, could be some incompatibility with xhci_hcd driver module. My question is, where I can start to find this issue, on squeak-vm or on enchanting image ? Where is handle the usb connection on squeak-vm or at image level ? Thanks in advance. Gustavo. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141016/522f50d6/attachment.htm From lewis at mail.msen.com Fri Oct 17 00:51:41 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Fri Oct 17 00:51:44 2014 Subject: [squeak-dev] Re: [Vm-dev] SqueakSSL + TLS SNI In-Reply-To: References: Message-ID: <20141017005141.GA89436@shell.msen.com> On Thu, Oct 16, 2014 at 01:46:45PM +0200, Levente Uzonyi wrote: > > Hi, > > I've implemented support for TLS SNI[1] for SqueakSSL on unix. I've > uploaded the modified source files[2][3], a diff[4], and a prebuilt > module[5] (built on Ubuntu 14.04 from the Cog branch). > The image side code is also available[6], along with an updated version of > the WebClient[7] package, and intermediate packages with various > improvements[8]. > The image side code works even if the plugin doesn't support TLS SNI, but > this version of WebClient won't work with older versions of the > SqueakSSL-Core package. > Please review the changes, and consider adding them to the corresponding > repositories! > > Levente > > [1] https://en.wikipedia.org/wiki/Server_Name_Indication > [2] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL.h > [3] http://leves.web.elte.hu/squeak/SqueakSSL/sqUnixOpenSSL.c > [4] http://leves.web.elte.hu/squeak/SqueakSSL/diff.txt > [5] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL > [6] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL-Core-ul.29.mcz > [7] http://leves.web.elte.hu/squeak/SqueakSSL/WebClient-Core-ul.98.mcz > [8] http://leves.web.elte.hu/squeak/SqueakSSL/ Thanks Levente, For the VM plugin, I entered this as Mantis 7824: Add TLS SNI Server Name Indication support to SqueakSSL plugin http://bugs.squeak.org/view.php?id=7824 Dave From bert at freudenbergs.de Fri Oct 17 01:57:12 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Fri Oct 17 01:57:18 2014 Subject: [squeak-dev] [Trivia] Name the connection of this song to Smalltalk Message-ID: <4C900D43-D9B5-470A-AED8-13433952532F@freudenbergs.de> http://www.gratefulweb.com/articles/arlo-guthrie-celebrates-50th-anniversary-alices-restaurant-w-tour - Bert - From tim at rowledge.org Fri Oct 17 02:02:32 2014 From: tim at rowledge.org (tim Rowledge) Date: Fri Oct 17 02:02:38 2014 Subject: [squeak-dev] [Trivia] Name the connection of this song to Smalltalk In-Reply-To: <4C900D43-D9B5-470A-AED8-13433952532F@freudenbergs.de> References: <4C900D43-D9B5-470A-AED8-13433952532F@freudenbergs.de> Message-ID: On 16-10-2014, at 6:57 PM, Bert Freudenberg wrote: > http://www.gratefulweb.com/articles/arlo-guthrie-celebrates-50th-anniversary-alices-restaurant-w-tour Best I can come up with is that there is an Alice?s Restaurant at the top end of PageMills rd, a few miles further along than PARC tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Spero nos familiares mansuros. = I hope we'll still be friends. From djm1329 at san.rr.com Fri Oct 17 02:10:38 2014 From: djm1329 at san.rr.com (Douglas McPherson) Date: Fri Oct 17 02:10:38 2014 Subject: [squeak-dev] [Trivia] Name the connection of this song to Smalltalk In-Reply-To: References: <4C900D43-D9B5-470A-AED8-13433952532F@freudenbergs.de> Message-ID: <469348D5-C491-4023-A0E9-2901C5C4DDA9@san.rr.com> It was the inspiration for some of the selector names for Collection ... Doug On Oct 16, 2014, at 19:02 , tim Rowledge wrote: > > On 16-10-2014, at 6:57 PM, Bert Freudenberg wrote: > >> http://www.gratefulweb.com/articles/arlo-guthrie-celebrates-50th-anniversary-alices-restaurant-w-tour > > Best I can come up with is that there is an Alice?s Restaurant at the top end of PageMills rd, a few miles further along than PARC > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Useful Latin Phrases:- Spero nos familiares mansuros. = I hope we'll still be friends. > > > From brasspen at gmail.com Fri Oct 17 02:11:28 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Fri Oct 17 02:11:35 2014 Subject: [squeak-dev] [Trivia] Name the connection of this song to Smalltalk In-Reply-To: References: <4C900D43-D9B5-470A-AED8-13433952532F@freudenbergs.de> Message-ID: Song lyrics from Alice?s Restaurant: "They got a building down New York City, it's called Whitehall Street, Where you walk in, you get injected, inspected, detected, infected, Neglected and selected.? #inject:into: #detect: #collect: #select: #reject: Chris > On Oct 16, 2014, at 10:02 PM, tim Rowledge wrote: > > > On 16-10-2014, at 6:57 PM, Bert Freudenberg wrote: > >> http://www.gratefulweb.com/articles/arlo-guthrie-celebrates-50th-anniversary-alices-restaurant-w-tour > > Best I can come up with is that there is an Alice?s Restaurant at the top end of PageMills rd, a few miles further along than PARC > > tim > -- > tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim > Useful Latin Phrases:- Spero nos familiares mansuros. = I hope we'll still be friends. > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141016/27c8de51/attachment.htm From lewis at mail.msen.com Fri Oct 17 02:29:45 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Fri Oct 17 02:29:49 2014 Subject: [squeak-dev] [Trivia] Name the connection of this song to Smalltalk In-Reply-To: References: <4C900D43-D9B5-470A-AED8-13433952532F@freudenbergs.de> Message-ID: <20141017022945.GB94803@shell.msen.com> On Thu, Oct 16, 2014 at 07:02:32PM -0700, tim Rowledge wrote: > > On 16-10-2014, at 6:57 PM, Bert Freudenberg wrote: > > > http://www.gratefulweb.com/articles/arlo-guthrie-celebrates-50th-anniversary-alices-restaurant-w-tour > > Best I can come up with is that there is an Alice?s Restaurant at the top end of PageMills rd, a few miles further along than PARC > I used to be able to play the guitar part for hours, but I'm afraid my fingers may have forgotten some of the details. The Squeak connection is reportedly associated with the collections protocol, which evidently has not been fully implemented. The correct selectors would be { #injected . #inspected . #detected . #infected . #neglected . #selected }. Dave From eliot.miranda at gmail.com Fri Oct 17 06:51:20 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri Oct 17 06:51:26 2014 Subject: [squeak-dev] New Spur trunk image available Message-ID: Hi All, finally the Spur Squeak trunk image is updateable. The image in http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created today and thanks to Bert Freudenberg's latest Monticello work can be updated independently of the non-Spur trunk. Spur VMs are available in http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they appear). Without wanting to appear too overconfident the Spur system looks to be ready for use apart from image segments (which I hope to have working some time next month). I'm really interested in having this stress tested by as many people as possible. Spur really does offer a significant performance and functionality improvement over the current system, but it needs testing to ensure its reliability. Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I hope Pharo 4 Spur will be available soon. As far as trunk goes, using Spur alongside non-Spur trunk is going to be difficult to manage for the near future. Right now, Spur modifies the Collections, Compiler, Kernel and System packages, and this is done by auto-editing the non-Spur versions of those packages, something I do periodically as new versions arrive. I also auto-edit trunk configurations (the part of the image update scheme that ensures packages are loaded in the right order when there are dependencies between packages) from non-Spur "update" to Spur "update.spur" forms. This at east means that Spur can keep up with trunk. But it does /not/ provide a way of committing to Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting out of sync with non-Spur trunk. Note that apart from these packages, one /can/ safely commit any other package from a Spur image to trunk. Right now the plan is to release both V3 (the pre-Spur format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak 5.0). This isn't my preference. I'd like to see just Spur released, once reliability is verified. But I understand the safety and backward-compatibility concerns (Spur won't be able to load V3 image segments, and vice verse). The issue is of course that we have this tricky package situation to manage where, to keep the two systems in sync, modifications to Collections, Compiler, Kernel and System need to be committed from V3 and auto-edited to Spur. I think that's too clumsy to be practicable. Perhaps allowing the two systems to fork and doing a manual merge will be acceptable, but it'll be work to keep them in sync. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141016/cd420f08/attachment.htm From casey.obrien.r at gmail.com Fri Oct 17 07:37:33 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Fri Oct 17 07:37:41 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: References: Message-ID: <190A33CE-D3D3-41C7-BB80-EF929E6EF1BA@gmail.com> Hi Eliot. I will make time to install Spur (assuming it's presently working on the Mac.) I'll use it as my primary VM unless I run into problems, in which case I will report them. I think I understood you, but I want to be clear; you're saying that (like Cog) changes needed to be made to the image to support the new VM. Query: can the Interpreter (either that or Stack) VM be modified to support images which run above Spur? Or is this necessarily a forking event? (CC Cuis folks.) Query: should incorporating the changes to the image that you have outlined below into Cuis allow Cuis to make use of the new VM? (I perhaps am digging very vaguely into what those changes are. Sorry I'm not presently equipped to ask smarter questions: I'm probably just beside myself with enthusiasm for your work and perchance "jumping the gun" a bit.) TIA, Casey P.S. Please forgive the pun, if you noticed it! :D > On Oct 16, 2014, at 11:51 PM, Eliot Miranda wrote: > > Hi All, > > finally the Spur Squeak trunk image is updateable. The image in http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created today and thanks to Bert Freudenberg's latest Monticello work can be updated independently of the non-Spur trunk. Spur VMs are available in http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they appear). Without wanting to appear too overconfident the Spur system looks to be ready for use apart from image segments (which I hope to have working some time next month). I'm really interested in having this stress tested by as many people as possible. Spur really does offer a significant performance and functionality improvement over the current system, but it needs testing to ensure its reliability. > > Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I hope Pharo 4 Spur will be available soon. > > As far as trunk goes, using Spur alongside non-Spur trunk is going to be difficult to manage for the near future. Right now, Spur modifies the Collections, Compiler, Kernel and System packages, and this is done by auto-editing the non-Spur versions of those packages, something I do periodically as new versions arrive. I also auto-edit trunk configurations (the part of the image update scheme that ensures packages are loaded in the right order when there are dependencies between packages) from non-Spur "update" to Spur "update.spur" forms. This at east means that Spur can keep up with trunk. But it does /not/ provide a way of committing to Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting out of sync with non-Spur trunk. Note that apart from these packages, one /can/ safely commit any other package from a Spur image to trunk. > > Right now the plan is to release both V3 (the pre-Spur format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak 5.0). This isn't my preference. I'd like to see just Spur released, once reliability is verified. But I understand the safety and backward-compatibility concerns (Spur won't be able to load V3 image segments, and vice verse). The issue is of course that we have this tricky package situation to manage where, to keep the two systems in sync, modifications to Collections, Compiler, Kernel and System need to be committed from V3 and auto-edited to Spur. I think that's too clumsy to be practicable. Perhaps allowing the two systems to fork and doing a manual merge will be acceptable, but it'll be work to keep them in sync. > -- > best, > Eliot > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141017/dc2959e3/attachment.htm From leves at elte.hu Fri Oct 17 12:40:20 2014 From: leves at elte.hu (Levente Uzonyi) Date: Fri Oct 17 12:40:32 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: References: Message-ID: On Thu, 16 Oct 2014, Eliot Miranda wrote: > Hi All, > ? ? finally the Spur Squeak trunk image is updateable.? The image in?http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created today and thanks to Bert Freudenberg's latest Monticello work can > be updated independently of the non-Spur trunk.? Spur VMs are available in?http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they appear).? Without wanting to appear too overconfident the Spur > system looks to be ready for use apart from image segments (which I hope to have working some time next month).? I'm really interested in having this stress tested by as many people as possible.? Spur really > does offer a significant performance and functionality improvement over the current system, but it needs testing to ensure its reliability. Great news. > > Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I hope Pharo 4 Spur will be available soon. > > As far as trunk goes, using Spur alongside non-Spur trunk is going to be difficult to manage for the near future.? Right now, Spur modifies the Collections, Compiler, Kernel and System packages, and this is > done by auto-editing the non-Spur versions of those packages, something I do periodically as new versions arrive.? I also auto-edit trunk configurations (the part of the image update scheme that ensures > packages are loaded in the right order when there are dependencies between packages) from non-Spur "update" to Spur "update.spur" forms.? This at east means that Spur can keep up with trunk.? But it does > /not/ provide a way of committing to?Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting out of sync with non-Spur trunk.? Note that apart from these packages, one /can/ safely commit > any other package from a Spur image to trunk. > > Right now the plan is to release both V3 (the pre-Spur format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak 5.0).? This isn't my preference.? I'd like to see just Spur released, once > reliability is verified.? But I understand the safety and backward-compatibility concerns (Spur won't be able to load V3 image segments, and vice verse).? The issue is of course that we have this tricky > package situation to manage where, to keep the two systems in sync, modifications to Collections, Compiler, Kernel and System need to be committed from V3 and auto-edited to Spur. I think that's too clumsy to > be practicable.? Perhaps allowing the two systems to fork and doing a manual merge will be acceptable, but it'll be work to keep them in sync. How about releasing the V3 version as Squeak 4.6, and the Spur version as Squeak 5.0 at the same time? This way we could keep Trunk as is; pushing all changes to Trunk until 4.6 is released, then - leaving V3 behind - use the Trunk for Spur-only. Then any changes could be backported manually to the future squeak46 repository if needed. Levente > -- > best,Eliot > > From leves at elte.hu Fri Oct 17 12:43:39 2014 From: leves at elte.hu (Levente Uzonyi) Date: Fri Oct 17 12:46:32 2014 Subject: [squeak-dev] Re: [Vm-dev] SqueakSSL + TLS SNI In-Reply-To: <20141017005141.GA89436@shell.msen.com> References: <20141017005141.GA89436@shell.msen.com> Message-ID: Thanks Dave, IIRC Cog and Trunk use the same plugin directory, so all changes are shared, including http://bugs.squeak.org/view.php?id=7793 . Levente On Thu, 16 Oct 2014, David T. Lewis wrote: > On Thu, Oct 16, 2014 at 01:46:45PM +0200, Levente Uzonyi wrote: >> >> Hi, >> >> I've implemented support for TLS SNI[1] for SqueakSSL on unix. I've >> uploaded the modified source files[2][3], a diff[4], and a prebuilt >> module[5] (built on Ubuntu 14.04 from the Cog branch). >> The image side code is also available[6], along with an updated version of >> the WebClient[7] package, and intermediate packages with various >> improvements[8]. >> The image side code works even if the plugin doesn't support TLS SNI, but >> this version of WebClient won't work with older versions of the >> SqueakSSL-Core package. >> Please review the changes, and consider adding them to the corresponding >> repositories! >> >> Levente >> >> [1] https://en.wikipedia.org/wiki/Server_Name_Indication >> [2] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL.h >> [3] http://leves.web.elte.hu/squeak/SqueakSSL/sqUnixOpenSSL.c >> [4] http://leves.web.elte.hu/squeak/SqueakSSL/diff.txt >> [5] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL >> [6] http://leves.web.elte.hu/squeak/SqueakSSL/SqueakSSL-Core-ul.29.mcz >> [7] http://leves.web.elte.hu/squeak/SqueakSSL/WebClient-Core-ul.98.mcz >> [8] http://leves.web.elte.hu/squeak/SqueakSSL/ > > Thanks Levente, > > For the VM plugin, I entered this as Mantis 7824: Add TLS SNI Server Name Indication support to SqueakSSL plugin > > http://bugs.squeak.org/view.php?id=7824 > > Dave > > > From johnson at cs.uiuc.edu Fri Oct 17 13:12:08 2014 From: johnson at cs.uiuc.edu (Ralph Johnson) Date: Fri Oct 17 13:12:12 2014 Subject: [squeak-dev] [Trivia] Name the connection of this song to Smalltalk In-Reply-To: <20141017022945.GB94803@shell.msen.com> References: <4C900D43-D9B5-470A-AED8-13433952532F@freudenbergs.de> <20141017022945.GB94803@shell.msen.com> Message-ID: Someone should definitely define #infect: and #neglect: -Ralph On Thu, Oct 16, 2014 at 9:29 PM, David T. Lewis wrote: > On Thu, Oct 16, 2014 at 07:02:32PM -0700, tim Rowledge wrote: > > > > On 16-10-2014, at 6:57 PM, Bert Freudenberg > wrote: > > > > > > http://www.gratefulweb.com/articles/arlo-guthrie-celebrates-50th-anniversary-alices-restaurant-w-tour > > > > Best I can come up with is that there is an Alice?s Restaurant at the > top end of PageMills rd, a few miles further along than PARC > > > > I used to be able to play the guitar part for hours, but I'm afraid my > fingers > may have forgotten some of the details. > > The Squeak connection is reportedly associated with the collections > protocol, > which evidently has not been fully implemented. The correct selectors would > be { #injected . #inspected . #detected . #infected . #neglected . > #selected }. > > Dave > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141017/491441cf/attachment.htm From eliot.miranda at gmail.com Fri Oct 17 13:13:36 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri Oct 17 13:13:44 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: <190A33CE-D3D3-41C7-BB80-EF929E6EF1BA@gmail.com> References: <190A33CE-D3D3-41C7-BB80-EF929E6EF1BA@gmail.com> Message-ID: <79896CE5-203D-4057-95AC-5FB371031F67@gmail.com> Hi Casey, On Oct 17, 2014, at 12:37 AM, Casey Ransberger wrote: > Hi Eliot. I will make time to install Spur (assuming it's presently working on the Mac.) I'll use it as my primary VM unless I run into problems, in which case I will report them. Yes, I build Spur VMs alongside Cog VMs, so they're available for Mac, x86 Windows and x86 linux. (and soon stack VMs for ARM linux). And thank you, both for using it and for these great questions. > I think I understood you, but I want to be clear; you're saying that (like Cog) changes needed to be made to the image to support the new VM. In this case more like to exploit the new VM. So 32-bit Spur has immediate characters alongside immediate SmallIntegers, and 64-bit Spur will add immediate floats. Spur has a 64k literal limit in methods vs 256 in V3 (pre-Spur). There are slightly different versions of Behavior>>new, new:, basicNew & basicNew: to marry with the new GC and segmented heap, and there are primitives for allInstances and allObjects. These are all benefits that could have been done without, but are clearly good and indeed the 64k literal limit exists in V3 Newspeak. In fact, the 64k limit is also associated with support for two bytecode sets. And that leads to support for Sista, the adaptive optimizer we hope will be available later next year. The necessary change is to add Behavior>>identityHash to ensure a class's identityHash is its index in the VM's class table. This is what keeps Spur objects relatively compact, and keeps their header uniform. i.e. every object's header contains its class's index in a 22-bit field instead of a direct reference to its class object. > Query: can the Interpreter (either that or Stack) VM be modified to support images which run above Spur? Or is this necessarily a forking event? (CC Cuis folks.) Yes. Stack Spur VMs are easily generable from a VMMaker image. In fact Stack Spur was the first working version. But porting the context Interpreter means finishing the merge with trunk VMMaker for which the community (in the person of David Lewis and myself) have so few cycles (volunteers welcome, but they must be prepared to merge the Interpreter into the Cog branch, not the other way). > Query: should incorporating the changes to the image that you have outlined below into Cuis allow Cuis to make use of the new VM? (I perhaps am digging very vaguely into what those changes are. Sorry I'm not presently equipped to ask smarter questions: I'm probably just beside myself with enthusiasm for your work and perchance "jumping the gun" a bit.) Yes. The bootstrap is written as an image editor. Adding support for Cuis should be straightforward, provided Cuis's compiler is brought close to trunk's (to support and exploit the 64k literal limit and multiple bytecode sets). Anyone motivated to port Cuis should contact me to discuss and for me to show you around the code. > TIA, Thanks. These questions have allowed me to clarify. But do you (or anyone else) have any opinions or concerns about the parallel development model for trunk I outlined? > Casey > > P.S. > > Please forgive the pun, if you noticed it! :D I missed it :-/ Eliot (phone) > > On Oct 16, 2014, at 11:51 PM, Eliot Miranda wrote: > >> Hi All, >> >> finally the Spur Squeak trunk image is updateable. The image in http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created today and thanks to Bert Freudenberg's latest Monticello work can be updated independently of the non-Spur trunk. Spur VMs are available in http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they appear). Without wanting to appear too overconfident the Spur system looks to be ready for use apart from image segments (which I hope to have working some time next month). I'm really interested in having this stress tested by as many people as possible. Spur really does offer a significant performance and functionality improvement over the current system, but it needs testing to ensure its reliability. >> >> Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I hope Pharo 4 Spur will be available soon. >> >> As far as trunk goes, using Spur alongside non-Spur trunk is going to be difficult to manage for the near future. Right now, Spur modifies the Collections, Compiler, Kernel and System packages, and this is done by auto-editing the non-Spur versions of those packages, something I do periodically as new versions arrive. I also auto-edit trunk configurations (the part of the image update scheme that ensures packages are loaded in the right order when there are dependencies between packages) from non-Spur "update" to Spur "update.spur" forms. This at east means that Spur can keep up with trunk. But it does /not/ provide a way of committing to Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting out of sync with non-Spur trunk. Note that apart from these packages, one /can/ safely commit any other package from a Spur image to trunk. >> >> Right now the plan is to release both V3 (the pre-Spur format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak 5.0). This isn't my preference. I'd like to see just Spur released, once reliability is verified. But I understand the safety and backward-compatibility concerns (Spur won't be able to load V3 image segments, and vice verse). The issue is of course that we have this tricky package situation to manage where, to keep the two systems in sync, modifications to Collections, Compiler, Kernel and System need to be committed from V3 and auto-edited to Spur. I think that's too clumsy to be practicable. Perhaps allowing the two systems to fork and doing a manual merge will be acceptable, but it'll be work to keep them in sync. >> -- >> best, >> Eliot >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141017/947287d5/attachment.htm From craig at netjam.org Fri Oct 17 14:11:14 2014 From: craig at netjam.org (Craig Latta) Date: Fri Oct 17 14:11:42 2014 Subject: [squeak-dev] request for Squeak 4.5 with Alien FFI loaded Message-ID: Hoi-- Would someone please create for me a Squeak 4.5 object memory with Alien FFI loaded, along with a README saying how it was done? When I do [ConfigurationOfAlien loadLatestVersion], I get a badly messed-up Compiler which barfs on initialization. thanks! -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From leves at elte.hu Fri Oct 17 15:42:32 2014 From: leves at elte.hu (Levente Uzonyi) Date: Fri Oct 17 15:42:39 2014 Subject: [Pharo-dev] [squeak-dev] New Spur trunk image available In-Reply-To: References: Message-ID: I guess this was intended to go to the squeak-dev list. On Fri, 17 Oct 2014, Eliot Miranda wrote: > Hi Levente, > > On Oct 17, 2014, at 5:40 AM, Levente Uzonyi wrote: > >> On Thu, 16 Oct 2014, Eliot Miranda wrote: >> >>> Hi All, >>> finally the Spur Squeak trunk image is updateable. The image in http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created today and thanks to Bert Freudenberg's latest Monticello work can >>> be updated independently of the non-Spur trunk. Spur VMs are available in http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they appear). Without wanting to appear too overconfident the Spur >>> system looks to be ready for use apart from image segments (which I hope to have working some time next month). I'm really interested in having this stress tested by as many people as possible. Spur really >>> does offer a significant performance and functionality improvement over the current system, but it needs testing to ensure its reliability. >> >> Great news. >> >>> Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I hope Pharo 4 Spur will be available soon. >>> As far as trunk goes, using Spur alongside non-Spur trunk is going to be difficult to manage for the near future. Right now, Spur modifies the Collections, Compiler, Kernel and System packages, and this is >>> done by auto-editing the non-Spur versions of those packages, something I do periodically as new versions arrive. I also auto-edit trunk configurations (the part of the image update scheme that ensures >>> packages are loaded in the right order when there are dependencies between packages) from non-Spur "update" to Spur "update.spur" forms. This at east means that Spur can keep up with trunk. But it does >>> /not/ provide a way of committing to Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting out of sync with non-Spur trunk. Note that apart from these packages, one /can/ safely commit >>> any other package from a Spur image to trunk. >>> Right now the plan is to release both V3 (the pre-Spur format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak 5.0). This isn't my preference. I'd like to see just Spur released, once >>> reliability is verified. But I understand the safety and backward-compatibility concerns (Spur won't be able to load V3 image segments, and vice verse). The issue is of course that we have this tricky >>> package situation to manage where, to keep the two systems in sync, modifications to Collections, Compiler, Kernel and System need to be committed from V3 and auto-edited to Spur. I think that's too clumsy to >>> be practicable. Perhaps allowing the two systems to fork and doing a manual merge will be acceptable, but it'll be work to keep them in sync. >> >> How about releasing the V3 version as Squeak 4.6, and the Spur version as Squeak 5.0 at the same time? >> This way we could keep Trunk as is; pushing all changes to Trunk until 4.6 is released, then - leaving V3 behind - use the Trunk for Spur-only. >> Then any changes could be backported manually to the future squeak46 repository if needed. > > Works for me. Good idea! Objections? > > >> Levente >> >>> -- >>> best,Eliot > > Eliot (phone) > From commits at source.squeak.org Fri Oct 17 17:48:31 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 17 17:48:33 2014 Subject: [squeak-dev] The Trunk: Morphic-topa.749.mcz Message-ID: Tobias Pape uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-topa.749.mcz ==================== Summary ==================== Name: Morphic-topa.749 Author: topa Time: 17 October 2014, 7:47:18.876 pm UUID: 5ffca218-b49c-4921-a67e-362aeb1ac71c Ancestors: Morphic-eem.748 Make MenueItemMorph respect the #menueWithIcons preference. =============== Diff against Morphic-eem.748 =============== Item was changed: ----- Method: MenuItemMorph>>hasIcon (in category 'accessing') ----- hasIcon + "Answer whether the receiver has an icon. If menues without icons are + requested, pretend to not bear one unless we have not content." + ^ self icon notNil and: [ + Preferences menuWithIcons or: [self contents isEmptyOrNil]].! - "Answer whether the receiver has an icon." - ^ icon notNil! From commits at source.squeak.org Fri Oct 17 17:52:36 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 17 17:52:38 2014 Subject: [squeak-dev] The Trunk: Graphics-topa.302.mcz Message-ID: Tobias Pape uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-topa.302.mcz ==================== Summary ==================== Name: Graphics-topa.302 Author: topa Time: 17 October 2014, 7:52:01.909 pm UUID: 6f29f93b-d314-4b50-bf38-3939460a11c6 Ancestors: Graphics-topa.301 Fix Color>>#duller for already grey colors. Resolves the violet tinting of SystemWindows in "uniform color" mode. =============== Diff against Graphics-topa.301 =============== Item was changed: ----- Method: Color>>duller (in category 'transformations') ----- duller + "Answer a darker, desaturated color. If the original color isn't very saturated, desaturate it by less (otherwise will just end up with grey). If the original color is a grey, don't try to be smart." - "Answer a darker, desaturated color. If the original color isn't very saturated, desaturate it by less (otherwise will just end up with grey)." | sat adjust | (sat := self saturation) > 0.3 ifTrue: [adjust := -0.1] ifFalse: [adjust := 0.1 - sat max: 0.0]. + ^ sat isZero + ifTrue: [self adjustBrightness: -0.1] + ifFalse: [self adjustSaturation: adjust brightness: -0.1]! - ^ self adjustSaturation: adjust brightness: -0.1! From commits at source.squeak.org Fri Oct 17 17:57:42 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 17 17:57:43 2014 Subject: [squeak-dev] The Trunk: Morphic-topa.750.mcz Message-ID: Tobias Pape uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-topa.750.mcz ==================== Summary ==================== Name: Morphic-topa.750 Author: topa Time: 17 October 2014, 7:56:41.314 pm UUID: 4b0f4bf4-aa80-4f90-8cf7-255aa5107744 Ancestors: Morphic-topa.749 Enhancement: Allow each menu of the main docking bar to be hidden via a preference. =============== Diff against Morphic-topa.749 =============== Item was added: + ----- Method: TheWorldMainDockingBar class>>disableMenuPreference: (in category 'preferences') ----- + disableMenuPreference: aPreferenceSymbol + + self setMenuPreference: aPreferenceSymbol to: false.! Item was added: + ----- Method: TheWorldMainDockingBar class>>enableMenuPreference: (in category 'preferences') ----- + enableMenuPreference: aPreferenceSymbol + + self setMenuPreference: aPreferenceSymbol to: true.! Item was added: + ----- Method: TheWorldMainDockingBar class>>getMenuPreference: (in category 'preferences') ----- + getMenuPreference: aPreferenceSymbol + + ^ self getMenuPreference: aPreferenceSymbol ifAbsent: [true]! Item was added: + ----- Method: TheWorldMainDockingBar class>>getMenuPreference:ifAbsent: (in category 'preferences') ----- + getMenuPreference: aPreferenceSymbol ifAbsent: aBlock + + | project | + ^ (project := Project current) isMorphic + ifTrue: [project projectPreferenceFlagDictionary at: aPreferenceSymbol ifAbsent: aBlock] + ifFalse: aBlock + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>setMenuPreference:to: (in category 'preferences') ----- + setMenuPreference: aPreferenceSymbol to: aBoolean + | project | + (project := Project current) isMorphic ifTrue: [ + project projectPreferenceFlagDictionary at: aPreferenceSymbol put: aBoolean. + (aBoolean ~= (Preferences perform: aPreferenceSymbol)) + ifTrue: [Preferences setPreference: aPreferenceSymbol toValue: aBoolean]]. + self updateInstances.! Item was added: + ----- Method: TheWorldMainDockingBar class>>showAppsMenuInWorldMainDockingBar (in category 'preferences') ----- + showAppsMenuInWorldMainDockingBar + + + ^ self getMenuPreference: #showAppsMenuInWorldMainDockingBar ifAbsent: [true] + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showAppsMenuInWorldMainDockingBar: (in category 'preferences') ----- + showAppsMenuInWorldMainDockingBar: aBoolean + + self + setMenuPreference: #showAppsMenuInWorldMainDockingBar + to: aBoolean. + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showExtrasMenuInWorldMainDockingBar (in category 'preferences') ----- + showExtrasMenuInWorldMainDockingBar + + + ^ self getMenuPreference: #showExtrasMenuInWorldMainDockingBar ifAbsent: [true] + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showExtrasMenuInWorldMainDockingBar: (in category 'preferences') ----- + showExtrasMenuInWorldMainDockingBar: aBoolean + + self + setMenuPreference: #showExtrasMenuInWorldMainDockingBar + to: aBoolean. + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showHelpMenuInWorldMainDockingBar (in category 'preferences') ----- + showHelpMenuInWorldMainDockingBar + + + ^ self getMenuPreference: #showHelpMenuInWorldMainDockingBar ifAbsent: [true] + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showHelpMenuInWorldMainDockingBar: (in category 'preferences') ----- + showHelpMenuInWorldMainDockingBar: aBoolean + + self + setMenuPreference: #showHelpMenuInWorldMainDockingBar + to: aBoolean. + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showMainMenuInWorldMainDockingBar (in category 'preferences') ----- + showMainMenuInWorldMainDockingBar + + + ^ self getMenuPreference: #showMainMenuInWorldMainDockingBar ifAbsent: [true] + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showMainMenuInWorldMainDockingBar: (in category 'preferences') ----- + showMainMenuInWorldMainDockingBar: aBoolean + + self + setMenuPreference: #showMainMenuInWorldMainDockingBar + to: aBoolean. + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showProjectsMenuInWorldMainDockingBar (in category 'preferences') ----- + showProjectsMenuInWorldMainDockingBar + + + ^ self getMenuPreference: #showProjectsMenuInWorldMainDockingBar ifAbsent: [true] + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showProjectsMenuInWorldMainDockingBar: (in category 'preferences') ----- + showProjectsMenuInWorldMainDockingBar: aBoolean + + self + setMenuPreference: #showProjectsMenuInWorldMainDockingBar + to: aBoolean. + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showToolsMenuInWorldMainDockingBar (in category 'preferences') ----- + showToolsMenuInWorldMainDockingBar + + + ^ self getMenuPreference: #showToolsMenuInWorldMainDockingBar ifAbsent: [true] + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showToolsMenuInWorldMainDockingBar: (in category 'preferences') ----- + showToolsMenuInWorldMainDockingBar: aBoolean + + self + setMenuPreference: #showToolsMenuInWorldMainDockingBar + to: aBoolean. + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showWindowsMenuInWorldMainDockingBar (in category 'preferences') ----- + showWindowsMenuInWorldMainDockingBar + + + ^ self getMenuPreference: #showWindowsMenuInWorldMainDockingBar ifAbsent: [true] + ! Item was added: + ----- Method: TheWorldMainDockingBar class>>showWindowsMenuInWorldMainDockingBar: (in category 'preferences') ----- + showWindowsMenuInWorldMainDockingBar: aBoolean + + self + setMenuPreference: #showWindowsMenuInWorldMainDockingBar + to: aBoolean. + ! Item was changed: ----- Method: TheWorldMainDockingBar>>menusOn: (in category 'construction') ----- menusOn: aDockingBar + self class showMainMenuInWorldMainDockingBar ifTrue: [ + self squeakMenuOn: aDockingBar]. + + self class showProjectsMenuInWorldMainDockingBar ifTrue: [ + self projectsMenuOn: aDockingBar]. + + self class showToolsMenuInWorldMainDockingBar ifTrue: [ + self toolsMenuOn: aDockingBar]. + + self class showAppsMenuInWorldMainDockingBar ifTrue: [ + self appsMenuOn: aDockingBar]. + + self class showExtrasMenuInWorldMainDockingBar ifTrue: [ + self extrasMenuOn: aDockingBar]. + + self class showWindowsMenuInWorldMainDockingBar ifTrue: [ + self windowsMenuOn: aDockingBar]. + + self class showHelpMenuInWorldMainDockingBar ifTrue: [ + self helpMenuOn: aDockingBar].! - self - squeakMenuOn: aDockingBar; - projectsMenuOn: aDockingBar; - toolsMenuOn: aDockingBar; - appsMenuOn: aDockingBar; - extrasMenuOn: aDockingBar; - windowsMenuOn: aDockingBar; - helpMenuOn: aDockingBar! From asqueaker at gmail.com Fri Oct 17 19:20:53 2014 From: asqueaker at gmail.com (Chris Muller) Date: Fri Oct 17 19:20:56 2014 Subject: [squeak-dev] windows in all projects? In-Reply-To: References: Message-ID: Maui has a similar requirement. I implemented it by handling the #aboutToLeaveWorld triggered by World's (PasteUpMorphs). There is also #aboutToEnterWorld available if that suits you better. Example from Maui: MauiWorld class>>#listenForLeavingWorlds Project allProjects do: [ : each | each world when: #aboutToLeaveWorld send: #setUpTransferMorphListeners to: self ] "Release" releaseLeavingWorldListeners Project allProjects do: [ : each | each world removeActionsForEvent: #aboutToLeaveWorld ] On Wed, Oct 15, 2014 at 2:45 PM, Eliot Miranda wrote: > Hi, > > occasionally I find it useful to have a window that is always present in > the current project, so that wen I change projects the window either moves > to the new project, or is in all worlds. Is there a way of doing this in > the standard system? (I can't see this from reading the labyrinthine > project enter code, but I could be missing something ;-) ). Anyone have a > changeset to do the same? > > -- > best, > Eliot > > > From asqueaker at gmail.com Fri Oct 17 19:25:57 2014 From: asqueaker at gmail.com (Chris Muller) Date: Fri Oct 17 19:25:59 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: <2D7A313F-707D-4E89-B42D-F79B37E907C2@rowledge.org> References: <7EFDF49E-397A-46E5-A4EB-087534734CCC@gmail.com> <2D7A313F-707D-4E89-B42D-F79B37E907C2@rowledge.org> Message-ID: On Wed, Oct 15, 2014 at 9:13 PM, tim Rowledge wrote: > > On 15-10-2014, at 7:07 PM, Chris Cunnington wrote: > >> The FunSqueak link is in the Beginners? section of the Downloads page. The Donate button is on the homepage > > Yay! Thanks Chris. > > Now, everybody else:- please consider donating a few dollars/pounds/yen/euros/bolivars/escudos/whatevers. It goes towards supporting the servers that we rely upon to bring you Squeak. No money, no servers. Contributions are always welcome, but we are not on the verge of losing any servers. We have an annoying expense we can get rid of by moving remaining services off of box2 (onto box3 and box4). From asqueaker at gmail.com Fri Oct 17 20:54:37 2014 From: asqueaker at gmail.com (Chris Muller) Date: Fri Oct 17 20:54:41 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: > I can not even find up to date information on how to *install* current > working FFI. Look no further than the "head" version of "FFI" on SqueakMap. You can install it straight from the menu or select "Edit Release" to see the script it uses to load it. We've been so lulled into things being undocumented that, even when they are, people don't find it because they don't think to look. From asqueaker at gmail.com Fri Oct 17 20:56:26 2014 From: asqueaker at gmail.com (Chris Muller) Date: Fri Oct 17 20:56:29 2014 Subject: [squeak-dev] The Trunk: Morphic-topa.750.mcz In-Reply-To: <5441589e.24a3700a.1005.060bSMTPIN_ADDED_MISSING@mx.google.com> References: <5441589e.24a3700a.1005.060bSMTPIN_ADDED_MISSING@mx.google.com> Message-ID: Ohh, thank you! I never use those menus and they just get in the way of the search bar when I want to make the window narrow.. On Fri, Oct 17, 2014 at 12:56 PM, wrote: > Tobias Pape uploaded a new version of Morphic to project The Trunk: > http://source.squeak.org/trunk/Morphic-topa.750.mcz > > ==================== Summary ==================== > > Name: Morphic-topa.750 > Author: topa > Time: 17 October 2014, 7:56:41.314 pm > UUID: 4b0f4bf4-aa80-4f90-8cf7-255aa5107744 > Ancestors: Morphic-topa.749 > > Enhancement: > Allow each menu of the main docking bar to be hidden via a preference. > > =============== Diff against Morphic-topa.749 =============== > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>disableMenuPreference: (in category 'preferences') ----- > + disableMenuPreference: aPreferenceSymbol > + > + self setMenuPreference: aPreferenceSymbol to: false.! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>enableMenuPreference: (in category 'preferences') ----- > + enableMenuPreference: aPreferenceSymbol > + > + self setMenuPreference: aPreferenceSymbol to: true.! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>getMenuPreference: (in category 'preferences') ----- > + getMenuPreference: aPreferenceSymbol > + > + ^ self getMenuPreference: aPreferenceSymbol ifAbsent: [true]! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>getMenuPreference:ifAbsent: (in category 'preferences') ----- > + getMenuPreference: aPreferenceSymbol ifAbsent: aBlock > + > + | project | > + ^ (project := Project current) isMorphic > + ifTrue: [project projectPreferenceFlagDictionary at: aPreferenceSymbol ifAbsent: aBlock] > + ifFalse: aBlock > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>setMenuPreference:to: (in category 'preferences') ----- > + setMenuPreference: aPreferenceSymbol to: aBoolean > + | project | > + (project := Project current) isMorphic ifTrue: [ > + project projectPreferenceFlagDictionary at: aPreferenceSymbol put: aBoolean. > + (aBoolean ~= (Preferences perform: aPreferenceSymbol)) > + ifTrue: [Preferences setPreference: aPreferenceSymbol toValue: aBoolean]]. > + self updateInstances.! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showAppsMenuInWorldMainDockingBar (in category 'preferences') ----- > + showAppsMenuInWorldMainDockingBar > + > + + category: 'docking bars' > + description: 'Whether world''s main docking bar should show the ''Apps'' menu.' > + type: #Boolean> > + ^ self getMenuPreference: #showAppsMenuInWorldMainDockingBar ifAbsent: [true] > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showAppsMenuInWorldMainDockingBar: (in category 'preferences') ----- > + showAppsMenuInWorldMainDockingBar: aBoolean > + > + self > + setMenuPreference: #showAppsMenuInWorldMainDockingBar > + to: aBoolean. > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showExtrasMenuInWorldMainDockingBar (in category 'preferences') ----- > + showExtrasMenuInWorldMainDockingBar > + > + + category: 'docking bars' > + description: 'Whether world''s main docking bar should show the ''Extras'' menu.' > + type: #Boolean> > + ^ self getMenuPreference: #showExtrasMenuInWorldMainDockingBar ifAbsent: [true] > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showExtrasMenuInWorldMainDockingBar: (in category 'preferences') ----- > + showExtrasMenuInWorldMainDockingBar: aBoolean > + > + self > + setMenuPreference: #showExtrasMenuInWorldMainDockingBar > + to: aBoolean. > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showHelpMenuInWorldMainDockingBar (in category 'preferences') ----- > + showHelpMenuInWorldMainDockingBar > + > + + category: 'docking bars' > + description: 'Whether world''s main docking bar should show the ''Help'' menu.' > + type: #Boolean> > + ^ self getMenuPreference: #showHelpMenuInWorldMainDockingBar ifAbsent: [true] > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showHelpMenuInWorldMainDockingBar: (in category 'preferences') ----- > + showHelpMenuInWorldMainDockingBar: aBoolean > + > + self > + setMenuPreference: #showHelpMenuInWorldMainDockingBar > + to: aBoolean. > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showMainMenuInWorldMainDockingBar (in category 'preferences') ----- > + showMainMenuInWorldMainDockingBar > + > + + category: 'docking bars' > + description: 'Whether world''s main docking bar should show the ''Main'' menu.' > + type: #Boolean> > + ^ self getMenuPreference: #showMainMenuInWorldMainDockingBar ifAbsent: [true] > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showMainMenuInWorldMainDockingBar: (in category 'preferences') ----- > + showMainMenuInWorldMainDockingBar: aBoolean > + > + self > + setMenuPreference: #showMainMenuInWorldMainDockingBar > + to: aBoolean. > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showProjectsMenuInWorldMainDockingBar (in category 'preferences') ----- > + showProjectsMenuInWorldMainDockingBar > + > + + category: 'docking bars' > + description: 'Whether world''s main docking bar should show the ''Projects'' menu.' > + type: #Boolean> > + ^ self getMenuPreference: #showProjectsMenuInWorldMainDockingBar ifAbsent: [true] > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showProjectsMenuInWorldMainDockingBar: (in category 'preferences') ----- > + showProjectsMenuInWorldMainDockingBar: aBoolean > + > + self > + setMenuPreference: #showProjectsMenuInWorldMainDockingBar > + to: aBoolean. > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showToolsMenuInWorldMainDockingBar (in category 'preferences') ----- > + showToolsMenuInWorldMainDockingBar > + > + + category: 'docking bars' > + description: 'Whether world''s main docking bar should show the ''Tools'' menu.' > + type: #Boolean> > + ^ self getMenuPreference: #showToolsMenuInWorldMainDockingBar ifAbsent: [true] > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showToolsMenuInWorldMainDockingBar: (in category 'preferences') ----- > + showToolsMenuInWorldMainDockingBar: aBoolean > + > + self > + setMenuPreference: #showToolsMenuInWorldMainDockingBar > + to: aBoolean. > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showWindowsMenuInWorldMainDockingBar (in category 'preferences') ----- > + showWindowsMenuInWorldMainDockingBar > + > + + category: 'docking bars' > + description: 'Whether world''s main docking bar should show the ''Windows'' menu.' > + type: #Boolean> > + ^ self getMenuPreference: #showWindowsMenuInWorldMainDockingBar ifAbsent: [true] > + ! > > Item was added: > + ----- Method: TheWorldMainDockingBar class>>showWindowsMenuInWorldMainDockingBar: (in category 'preferences') ----- > + showWindowsMenuInWorldMainDockingBar: aBoolean > + > + self > + setMenuPreference: #showWindowsMenuInWorldMainDockingBar > + to: aBoolean. > + ! > > Item was changed: > ----- Method: TheWorldMainDockingBar>>menusOn: (in category 'construction') ----- > menusOn: aDockingBar > > + self class showMainMenuInWorldMainDockingBar ifTrue: [ > + self squeakMenuOn: aDockingBar]. > + > + self class showProjectsMenuInWorldMainDockingBar ifTrue: [ > + self projectsMenuOn: aDockingBar]. > + > + self class showToolsMenuInWorldMainDockingBar ifTrue: [ > + self toolsMenuOn: aDockingBar]. > + > + self class showAppsMenuInWorldMainDockingBar ifTrue: [ > + self appsMenuOn: aDockingBar]. > + > + self class showExtrasMenuInWorldMainDockingBar ifTrue: [ > + self extrasMenuOn: aDockingBar]. > + > + self class showWindowsMenuInWorldMainDockingBar ifTrue: [ > + self windowsMenuOn: aDockingBar]. > + > + self class showHelpMenuInWorldMainDockingBar ifTrue: [ > + self helpMenuOn: aDockingBar].! > - self > - squeakMenuOn: aDockingBar; > - projectsMenuOn: aDockingBar; > - toolsMenuOn: aDockingBar; > - appsMenuOn: aDockingBar; > - extrasMenuOn: aDockingBar; > - windowsMenuOn: aDockingBar; > - helpMenuOn: aDockingBar! > > From frank.shearar at gmail.com Fri Oct 17 21:37:52 2014 From: frank.shearar at gmail.com (Frank Shearar) Date: Fri Oct 17 21:37:56 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: On 17 October 2014 21:54, Chris Muller wrote: >> I can not even find up to date information on how to *install* current >> working FFI. > > Look no further than the "head" version of "FFI" on SqueakMap. You > can install it straight from the menu or select "Edit Release" to see > the script it uses to load it. > > We've been so lulled into things being undocumented that, even when > they are, people don't find it because they don't think to look. For instance: https://github.com/squeak-smalltalk/squeak-ci/blob/master/package-load-scripts/FFI.st which says Installer squeakmap update; install: 'FFI (head)'. frank From asqueaker at gmail.com Fri Oct 17 22:00:52 2014 From: asqueaker at gmail.com (Chris Muller) Date: Fri Oct 17 22:00:55 2014 Subject: [Pharo-dev] [squeak-dev] New Spur trunk image available In-Reply-To: References: Message-ID: > How about releasing the V3 version as Squeak 4.6, and the Spur version as > Squeak 5.0 at the same time? Yes, that's the way to go! They (4.6 and 5.0) should be "equivalent" with each other -- Everything other than the VM and new restrictions (i.e., 64K restriction) would be the same. That way external apps can "port" to being Spur-compatible without worrying about any other functionality gaps between the two images causing problems. > This way we could keep Trunk as is; pushing all changes to Trunk until 4.6 > is released, then - leaving V3 behind - use the Trunk for Spur-only. > Then any changes could be backported manually to the future squeak46 > repository if needed. Yip. > > Levente > >> -- >> best,Eliot >> > From nicolaihess at web.de Fri Oct 17 22:24:23 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Fri Oct 17 22:24:30 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: 2014-10-17 22:54 GMT+02:00 Chris Muller : > > I can not even find up to date information on how to *install* current > > working FFI. > > Look no further than the "head" version of "FFI" on SqueakMap. You > can install it straight from the menu or select "Edit Release" to see > the script it uses to load it. > > We've been so lulled into things being undocumented that, even when > they are, people don't find it because they don't think to look. > "people don't find it because they don't think to look." ? This: "I can not even find up to date information on how to *install* current working FFI." was about a working version on linux. Working with tests and examples, something a beginner can look into and see how it is used. Sure maybe it is just as simple as select one entry from the squeak map list. But how should a beginner know to look there ? We have three package managers (in the current 4.5 release). squeak map catalog monticello universe browser (<- is still here but not working) searching squeak mailing shows links to source.squeak.org ffi on wiki.squeak does not link to squeak map And no,ffi examples are not in squeak map. some ffi tests are failing. loading ffi examples from squeak source: FFI-Unix-Examples ->failing (can not coerce arguments) FFI-Examples -> crash the image. -> maybe I am just uncapable, but I thnk it is not obvious how to get FFI working, it just does not work with the current squeak 4.5 release. You have to find a working cog version from eliots site. nicolai -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141018/6f2ff706/attachment.htm From nicolaihess at web.de Fri Oct 17 22:45:24 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Fri Oct 17 22:45:28 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: 2014-10-18 0:24 GMT+02:00 Nicolai Hess : > 2014-10-17 22:54 GMT+02:00 Chris Muller : > >> > I can not even find up to date information on how to *install* current >> > working FFI. >> >> Look no further than the "head" version of "FFI" on SqueakMap. You >> can install it straight from the menu or select "Edit Release" to see >> the script it uses to load it. >> >> We've been so lulled into things being undocumented that, even when >> they are, people don't find it because they don't think to look. >> > > "people don't find it because they don't think to look." > ? > > This: > "I can not even find up to date information on how to *install* current > working FFI." > was about a working version on linux. Working with tests and examples, > something > a beginner can look into and see how it is used. > > Sure maybe it is just as simple as select one entry from the squeak map > list. > But how should a beginner know to look there ? > We have three package managers (in the current 4.5 release). > squeak map catalog > monticello > universe browser (<- is still here but not working) > > searching squeak mailing shows links to source.squeak.org > ffi on wiki.squeak does not link to squeak map > > And no,ffi examples are not in squeak map. > some ffi tests are failing. > loading ffi examples from squeak source: > FFI-Unix-Examples ->failing (can not coerce arguments) > FFI-Examples -> crash the image. > > same results on windows: some ffi tests are failing. FFI-Examples -> crash the image. FFI-Win32 can not be loaded > -> maybe I am just uncapable, but I thnk it is not obvious how to get FFI > working, it just does not work with the > current squeak 4.5 release. You have to find a working cog version from > eliots site. > > nicolai > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141018/f56ac803/attachment-0001.htm From ma.chris.m at gmail.com Fri Oct 17 23:11:13 2014 From: ma.chris.m at gmail.com (Chris Muller) Date: Fri Oct 17 23:11:15 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: > This: > "I can not even find up to date information on how to *install* current > working FFI." > was about a working version on linux. Working with tests and examples, > something > a beginner can look into and see how it is used. > > Sure maybe it is just as simple as select one entry from the squeak map > list. > But how should a beginner know to look there ? I always hoped the word "Catalog" on the menu entry would stand out enough to encourage beginners to click and "see what's there". If not, there is lots of beginner documentation: wiki, videos, etc. which refer to SqueakMap. I agree there's room for improvement though.. > We have three package managers (in the current 4.5 release). > squeak map catalog > monticello > universe browser (<- is still here but not working) Universes brings up an empty list, SqueakMap does not. Simply following the path of least resistance gets you a working FFI in Squeak 4.5. > searching squeak mailing shows links to source.squeak.org > ffi on wiki.squeak does not link to squeak map The whole point of SqueakMap is to _avoid_ having to search mailing lists. It is the only single place that can document where any Squeak software is, regardless what other SCM repository is being used to host it. That's why SqueakMap shoud always be checked first and, if not there, only then have to dig thru mailing lists, etc. > And no,ffi examples are not in squeak map. Then why not make an entry for them there so the next person can find them? It is really very easy to do that (see [1]). I made entries for a lot of projects that aren't mine, but the only way to get out of this rut as a community is to embrace our catalog as a community. > some ffi tests are failing. Not the ones from loaded from SqueakMap. I just tried it in a stock 4.5 and trunk and got 32 out of 32 green tests, on Ubuntu Linux 12.04 LTS. > loading ffi examples from squeak source: > FFI-Unix-Examples ->failing (can not coerce arguments) > FFI-Examples -> crash the image. > > -> maybe I am just uncapable, but I thnk it is not obvious how to get FFI > working, it just does not work with the > current squeak 4.5 release. You have to find a working cog version from > eliots site. SqueakMap documentation for FFI Core and Tests appears to be up-to-date. If you have found a working "FFI Examples" somewhere (mirandabanda.org?) and you got it working in 4.5 or trunk, I hope you'll add an entry to SqueakMap.. I'll help! - Chris [1] -- "SqueakMap Publishing Guidelines" http://wiki.squeak.org/squeak/6182 From nicolaihess at web.de Fri Oct 17 23:41:49 2014 From: nicolaihess at web.de (Nicolai Hess) Date: Fri Oct 17 23:41:55 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: 2014-10-18 1:11 GMT+02:00 Chris Muller : > And no,ffi examples are not in squeak map. > > Then why not make an entry for them there so the next person can find > them? It is really very easy to do that (see [1]). > > I made entries for a lot of projects that aren't mine, but the only > way to get out of this rut as a community is to embrace our catalog as > a community. > > I'll try it. SqueakMap documentation for FFI Core and Tests appears to be > up-to-date. If you have found a working "FFI Examples" somewhere > (mirandabanda.org?) and you got it working in 4.5 or trunk, I tried to find the maintainer ( http://forum.world.st/Maintainer-of-FFI-Package-td4781017.html) or whoever made the latest changes,because, the latest comment for FFI-Unix: "made the XLib examples actually work (Window is an unsigned int handle, not a struct)" sounds like they should work now, but as far as I understand the code, this can not work, I would like to clearify this. Did you use the 4.5 image *and* the vm from Squeak 4.5 all-in-one? Because I can not get it to work not on linux (ok, ubuntu 10.04 32 Bit I'll try it on a more recent version) and not on windows (Windows 7 32 Bit) I hope > you'll add an entry to SqueakMap.. I'll help! > Thank you for your help. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141018/83fe79eb/attachment.htm From commits at source.squeak.org Fri Oct 17 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 17 23:55:04 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141017235502.15585.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007333.html Name: Morphic-topa.749 Ancestors: Morphic-eem.748 Make MenueItemMorph respect the #menueWithIcons preference. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007334.html Name: Graphics-topa.302 Ancestors: Graphics-topa.301 Fix Color>>#duller for already grey colors. Resolves the violet tinting of SystemWindows in "uniform color" mode. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007335.html Name: Morphic-topa.750 Ancestors: Morphic-topa.749 Enhancement: Allow each menu of the main docking bar to be hidden via a preference. ============================================= From eliot.miranda at gmail.com Fri Oct 17 23:59:17 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri Oct 17 23:59:19 2014 Subject: [squeak-dev] request for Squeak 4.5 with Alien FFI loaded In-Reply-To: References: Message-ID: Hi Craig, the scripts such as http://www.squeakvm.org/svn/squeak/branches/Cog/image/buildspurtrunkvmmakerimage.sh load Alien into an image that becomes a VMMaker image. It is as simple as loading the most recent Alien package in http://www.squeaksource.com/Alien On Fri, Oct 17, 2014 at 7:11 AM, Craig Latta wrote: > > Hoi-- > > Would someone please create for me a Squeak 4.5 object memory with > Alien FFI loaded, along with a README saying how it was done? When I do > [ConfigurationOfAlien loadLatestVersion], I get a badly messed-up > Compiler which barfs on initialization. > > > thanks! > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141017/dca96546/attachment.htm From ma.chris.m at gmail.com Sat Oct 18 03:12:35 2014 From: ma.chris.m at gmail.com (Chris Muller) Date: Sat Oct 18 03:12:37 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: > Did you use the 4.5 image *and* the vm from Squeak 4.5 all-in-one? > Because I can not get it to work not on linux (ok, ubuntu 10.04 32 Bit I'll > try it on > a more recent version) and not on windows (Windows 7 32 Bit) I tried it with the Cog-Linux-HT-3095 VM. From hilaire at drgeo.eu Sat Oct 18 14:06:17 2014 From: hilaire at drgeo.eu (Hilaire) Date: Sat Oct 18 14:10:06 2014 Subject: [squeak-dev] Re: New Spur trunk image available In-Reply-To: References: Message-ID: Thanks to all of you Le 17/10/2014 08:51, Eliot Miranda a ?crit : > finally the Spur Squeak trunk image is updateable. The image > in http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was > created today and thanks to Bert Freudenberg's latest Monticello work > can be updated independently of the non-Spur trunk. Spur VMs are > available in http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and -- Dr. Geo - http://drgeo.eu iStoa - http://istoa.drgeo.eu From craig at netjam.org Sat Oct 18 14:41:28 2014 From: craig at netjam.org (Craig Latta) Date: Sat Oct 18 14:41:47 2014 Subject: [squeak-dev] re: request for Squeak 4.5 with Alien FFI loaded In-Reply-To: References: Message-ID: > the scripts such as [1] load Alien into an image that becomes a > VMMaker image. It is as simple as loading the most recent Alien > package in http://www.squeaksource.com/Alien Thanks! What I had done was Squeak 4.5 official release, load Metacello from SqueakSource, load Alien, [ConfigurationOfAlient loadLatestVersion]. -C [1] http://bit.ly/1pnQIs5 (squeakvm.org) -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From list at afceurope.com Sat Oct 18 16:52:53 2014 From: list at afceurope.com (Annick Fron) Date: Sat Oct 18 16:52:56 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: I have tried a version of the examples mentioned in the list, and it works. But I have still doubts with passing variables by reference (&var in C): this is common in C to allocate a variable, pass its pointer as argument to get the value back, instead of using function returns. Annick Le 18 oct. 2014 ? 05:12, Chris Muller a ?crit : >> Did you use the 4.5 image *and* the vm from Squeak 4.5 all-in-one? >> Because I can not get it to work not on linux (ok, ubuntu 10.04 32 Bit I'll >> try it on >> a more recent version) and not on windows (Windows 7 32 Bit) > > I tried it with the Cog-Linux-HT-3095 VM. > From bert at freudenbergs.de Sat Oct 18 17:40:26 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Sat Oct 18 17:40:32 2014 Subject: [Pharo-users] [squeak-dev] FFI syntax In-Reply-To: References: Message-ID: <717A7DF1-5F6E-4B3A-90BD-1FAD84650755@freudenbergs.de> On 18.10.2014, at 09:52, Annick Fron wrote: > But I have still doubts with passing variables by reference (&var in C): this is common in C to allocate a variable, pass its pointer as argument to get the value back, instead of using function returns. Internally, C handles references as pointers. - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141018/e30b9c3b/smime.bin From sean at clipperadams.com Sat Oct 18 23:11:05 2014 From: sean at clipperadams.com (Sean P. DeNigris) Date: Sat Oct 18 23:13:24 2014 Subject: [squeak-dev] squeak.org Trunk Download Link Message-ID: <1413673865755-4785337.post@n4.nabble.com> The "Bleeding Edge Trunk Image & Changes (at Jenkins Build Server)" link on http://www.squeak.org/Downloads points to http://build.squeak.org/job/SqueakTrunk/TrunkImage.zip, which gives a 404. Maybe it should be http://build.squeak.org/job/SqueakTrunk/lastSuccessfulBuild/artifact/target/TrunkImage.zip ? ----- Cheers, Sean -- View this message in context: http://forum.world.st/squeak-org-Trunk-Download-Link-tp4785337.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From sean at clipperadams.com Sat Oct 18 23:34:57 2014 From: sean at clipperadams.com (Sean P. DeNigris) Date: Sat Oct 18 23:37:14 2014 Subject: [squeak-dev] Contribution Instructions Message-ID: <1413675297489-4785338.post@n4.nabble.com> Does something exist like https://pharo.org/contribute-propose-fix for Pharo? An apparent new user is asking a lot of very basic questions about how to contribute a fix. On http://stackoverflow.com/questions/26442071/how-to-check-out-code-for-squeaksource, Tobias suggested "A New Community Development Model". I went to look myself and it didn't really seem to be geared toward newbies. Is there anywhere such a user can go that explains the process from start to finish? ----- Cheers, Sean -- View this message in context: http://forum.world.st/Contribution-Instructions-tp4785338.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From sean at clipperadams.com Sat Oct 18 23:44:15 2014 From: sean at clipperadams.com (Sean P. DeNigris) Date: Sat Oct 18 23:46:31 2014 Subject: [squeak-dev] Error when Opening Repo from MC Browser Message-ID: <1413675855785-4785340.post@n4.nabble.com> Squeak4.5 latest update: #13965 1. In MC Browser, select http://source.squeak.org/trunk 2. Click open I get "Error: subscript is out of bounds: -2" when SocketStream>>upToAll:limit: computes a negative index via "lastRead - sz + 2", which is (0 - 4 + 2). ----- Cheers, Sean -- View this message in context: http://forum.world.st/Error-when-Opening-Repo-from-MC-Browser-tp4785340.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From commits at source.squeak.org Sat Oct 18 23:47:59 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 18 23:48:01 2014 Subject: [squeak-dev] The Inbox: SMBase-nice.132.mcz Message-ID: A new version of SMBase was added to project The Inbox: http://source.squeak.org/inbox/SMBase-nice.132.mcz ==================== Summary ==================== Name: SMBase-nice.132 Author: nice Time: 16 December 2013, 4:08:19.355 pm UUID: a70c8bd2-3eee-4e21-b9c6-113f6b194527 Ancestors: SMBase-dtl.131 Use non logging Compiler protocol rather than providing a logged: false argument. =============== Diff against SMBase-dtl.131 =============== Item was changed: ----- Method: SMSqueakMap class>>recreateInstalledPackagesFromChangeLog (in category 'migration') ----- recreateInstalledPackagesFromChangeLog "Clear and recreate the Dictionary with information on installed packages. NOTE: This takes some time to run and will only find packages installed using SM and since the last changelog condense. For packages installed prior to SqueakMap 1.07 there is no timestamp nor counter logged. These packages will be given the time of the replay and a separate count (from -10000 upwards) maintaining correct order of installation." "SMSqueakMap recreateInstalledPackagesFromChangeLog" | changesFile chunk | SMSqueakMap default clearInstalledPackages. changesFile := (SourceFiles at: 2) readOnlyCopy. [changesFile atEnd] whileFalse: [ chunk := changesFile nextChunk. ((chunk beginsWith: '"Installed') and: [ (chunk indexOfSubCollection: 'SMSqueakMap noteInstalledPackage:' startingAt: 10) > 0]) + ifTrue: [Compiler evaluate: chunk]]. - ifTrue: [Compiler evaluate: chunk logged: false]]. changesFile close! From commits at source.squeak.org Sat Oct 18 23:48:26 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 18 23:48:28 2014 Subject: [squeak-dev] The Inbox: Metacello-Base-dkh.109.mcz Message-ID: A new version of Metacello-Base was added to project The Inbox: http://source.squeak.org/inbox/Metacello-Base-dkh.109.mcz ==================== Summary ==================== Name: Metacello-Base-dkh.109 Author: dkh Time: 29 June 2013, 12:29:46 pm UUID: 00d8693d-7ca3-4fba-a201-54905f9b6891 Ancestors: Metacello-Base-dkh.108 Issue #172: replace source references to ss3.gemstone.com ==================== Snapshot ==================== SystemOrganization addCategory: 'Metacello-Base'! Object subclass: #ConfigurationOf instanceVariableNames: 'project' classVariableNames: '' poolDictionaries: '' category: 'Metacello-Base'! !ConfigurationOf commentStamp: 'dkh 5/30/2012 16:31' prior: 0! You must use a *configuration* when your project is stored in a repository using `.mcz` files. If you are using a source code manager (SCM) like [git][1] and have created a *baseline* (see the [**BaselineOf** class comment][3] for more info) you may use a *configuration* to associate a specific git commit (SHA, branch name, tag name) with a [Metacello version][2]. To create a new Metacello configuration: 1. Create a subclass of the **ConfigurationOf** class. The configuration class for your project should be names by appending the name of your project to the string `ConfigurationOf`. The name of the category and package should be the same as the name of the class: ```Smalltalk ConfigurationOf subclass: #ConfigurationOfExample instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ConfigurationOfExample' ``` 2. Create a **baselineXXXX:** method where you specify the structure of your project: ```Smalltalk baseline0100: spec spec for: #common do: [ spec repository: 'http://ss3.gemstone.com/ss/Example'. spec package: 'Example-Core'; package: 'Example-Tests' with: [ spec requires: 'Example-Core' ]]. ``` 3. Create a **versionXXXX:** method where you specify the specific versions of the packages to be loaded for this version: ```Smalltalk version01000: spec spec for: #common do: [ spec blessing: #release. spec package: 'Example-Core' with: 'Example-Core'; package: 'Example-Tests' with: 'Example-Tests' ]. ``` 4. Create a Monticello package for your **ConfigurationOf** class and save it in the repository where your packages are stored. [1]: http://git-scm.com/ [2]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#metacello-version-numbers [3]: https://github.com/dalehenrich/metacello-work/blob/master/repository/Metacello-Base.package/BaselineOf.class/README.md ! ConfigurationOf subclass: #BaselineOf instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Metacello-Base'! !BaselineOf commentStamp: 'dkh 5/30/2012 16:30' prior: 0! You should use a *baseline* when you are using a disk-based source code manager (SCM) like [git][1]. When using a disk-based SCM it is not necessary to use the Metacello *version* method, because it is intended for use with `.mcz` files. With a disk-based SCM you only need a single `baseline:` method. When you change the structure of your project you can change the baseline and save everything in a single commit. So multiple `baseline:` methods are no longer needed. You may still need a *configuration* when using a *baseline*. The [Sample project][3] on GitHub has a good example of a configuration used in conjunction with a *baseline*. See the [**ConfigurationOf** class comment][2] for information on creating a *configuration*. To create a new Metacello baseline: 1. Create a subclass of the **BaselineOf** class. The baseline class for your project should be named by appending the name of your project to the string `BaselineOf`. The name of the category and package should be the same as the name of the class: ```Smalltalk BaselineOf subclass: #BaselineOfExample instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'BaselineOfExample' ``` 2. Create a **baseline:** method where you specify the structure of your project: ```Smalltalk baseline: spec spec for: #common do: [ spec package: 'Example-Core'; package: 'Example-Tests' with: [ spec requires: 'Example-Core' ]]. ``` 3. Create a Monticello package for your **BaselineOf** class and save it in the repository where your packages are stored. [1]: http://git-scm.com/ [2]: https://github.com/dalehenrich/metacello-work/blob/master/repository/Metacello-Base.package/ConfigurationOf.class/README.md [3]: https://github.com/dalehenrich/sample/tree/configuration/ConfigurationOfSample.package/ConfigurationOfSample.class ! ----- Method: BaselineOf>>projectClass (in category 'accessing') ----- projectClass ^ MetacelloMCBaselineProject! ----- Method: BaselineOf>>versionNumberClass (in category 'accessing') ----- versionNumberClass ^ MetacelloVersionNumber! ----- Method: ConfigurationOf class>>bootstrapMetacelloFrom: (in category 'private') ----- bootstrapMetacelloFrom: repositoryUrl "Corresponds to version 1.0.0-beta.32.6" "KEEP MetacelloConfigTemplate class>>ensureMetacelloBaseConfiguration in synch!!" | platformPkg | self ensureGoferVersion: 'Gofer-Core-lr.115' repositoryUrl: repositoryUrl. #('Metacello-Core-dkh.678' 'Metacello-MC-dkh.674') do: [ :pkg | self bootstrapPackage: pkg from: repositoryUrl ]. platformPkg := Smalltalk at: #'SystemVersion' ifPresent: [ :cl | | versionString | versionString := cl current version. (versionString beginsWith: 'Squeak') ifTrue: [ (versionString beginsWith: 'Squeak3') ifTrue: [ 'Metacello-Platform.squeak-dkh.5' ] ifFalse: [ 'Metacello-Platform.squeak-dkh.22' ] ] ifFalse: [ (versionString beginsWith: 'Pharo') ifTrue: [ self bootstrapPackage: 'Metacello-PharoCommonPlatform-dkh.2' from: repositoryUrl. (versionString beginsWith: 'Pharo2') ifTrue: [ 'Metacello-Platform.pharo20-dkh.33' ] ifFalse: [ 'Metacello-Platform.pharo-dkh.34' ] ] ] ]. self bootstrapPackage: platformPkg from: repositoryUrl! ----- Method: ConfigurationOf class>>bootstrapPackage:from: (in category 'private') ----- bootstrapPackage: aString from: aPath | repository version | repository := (MCCacheRepository default includesVersionNamed: aString) ifTrue: [ MCCacheRepository default ] ifFalse: [ MCHttpRepository location: aPath user: '' password: '' ]. self retry: [ repository versionReaderForFileNamed: aString , '.mcz' do: [ :reader | version := reader version. version load. version workingCopy repositoryGroup addRepository: repository ] ]! ----- Method: ConfigurationOf class>>ensureGoferVersion:repositoryUrl: (in category 'private') ----- ensureGoferVersion: goferVersion repositoryUrl: repositoryUrl "load the p=file goferVersion if Gofer isn't loaded or an earlier version of Gofer is currently loaded" | goferVersionNumber wc pName | (Smalltalk at: #'Gofer' ifAbsent: [ ]) == nil ifTrue: [ ^ self bootstrapPackage: goferVersion from: repositoryUrl ]. goferVersionNumber := (goferVersion copyAfterLast: $.) asNumber. wc := [ ((Smalltalk at: #'GoferPackageReference') name: 'Gofer') workingCopy ] on: Error do: [ :ex | ex return: ((Smalltalk at: #'GoferPackageReference') name: 'Gofer-Core') workingCopy ]. pName := wc ancestry ancestors first name. (pName copyAfterLast: $.) asNumber <= goferVersionNumber ifTrue: [ self bootstrapPackage: goferVersion from: repositoryUrl ]! ----- Method: ConfigurationOf class>>ensureMetacello (in category 'private') ----- ensureMetacello "Bootstrap Metacello and load the 'botstrap' group" self ensureMetacello: #('batch')! ----- Method: ConfigurationOf class>>ensureMetacello: (in category 'private') ----- ensureMetacello: loadList "Bootstrap Metacello, retry using alternate repository, if primary repository is not accessible" Smalltalk at: #'MetacelloProject' ifAbsent: [ | version error gofer | (Array with: 'http://smalltalkhub.com/mc/dkh/metacello/main' with: 'http://seaside.gemtalksystems.com/ss/metacello') do: [ :repositoryUrl | "bootstrap Metacello" [ self bootstrapMetacelloFrom: repositoryUrl. Smalltalk at: #'ConfigurationOfMetacello' ifAbsent: [ self retry: [ gofer := (Smalltalk at: #'Gofer') new. gofer perform: #'url:' with: repositoryUrl; perform: #'package:' with: 'ConfigurationOfMetacello'; perform: #'load' ] ]. version := (Smalltalk at: #'ConfigurationOfMetacello') project version: #'previewBootstrap'. version load: loadList. self retry: [ gofer := (Smalltalk at: #'Gofer') new. Smalltalk at: #'ConfigurationOfMetacelloPreview' ifAbsent: [ gofer perform: #'url:' with: repositoryUrl; perform: #'package:' with: 'ConfigurationOfMetacelloPreview'; perform: #'load' ] ]. version := (Smalltalk at: #'ConfigurationOfMetacelloPreview') project version: #'stable'. "load latest from GitHub" version load: loadList. ^ self ] on: Error do: [ :ex | error := ex. Transcript cr; show: 'failed ensureMetacello using '; show: repositoryUrl printString; show: ' : '; show: ex description printString; show: '...retrying'. "try again" ex return: nil ] ]. "shouldn't get here unless the load failed ... throw an error" self error: 'retry with alternate repository failed: ' , error description printString ]! ----- Method: ConfigurationOf class>>project (in category 'accessing') ----- project ^self new project! ----- Method: ConfigurationOf class>>retry: (in category 'private') ----- retry: aBlock self retry: aBlock retryCount: 3! ----- Method: ConfigurationOf class>>retry:retryCount: (in category 'private') ----- retry: aBlock retryCount: retryCount | count | count := 1. [ true ] whileTrue: [ [ aBlock value. ^ self ] on: Error do: [ :ex | count < retryCount ifTrue: [ Transcript cr; show: 'RETRYING AFTER:'; cr; show: ex description printString. (Delay forSeconds: 5) wait ] ifFalse: [ Transcript cr; show: 'FAILED RETRYING:'; cr; show: ex description printString. ex pass ] ]. count := count + 1 ]! ----- Method: ConfigurationOf class>>unloadMetacello (in category 'unloading Metacello') ----- unloadMetacello "Unload the classes that implement Metacello. Metacello is not needed once a project has been loaded, so it can safely be unloaded." "self unloadMetacello" | gofer | gofer := (Smalltalk at: #Gofer) new. MCWorkingCopy allManagers do: [:wc | ((wc packageName beginsWith: 'Metacello') or: [ wc packageName beginsWith: 'OB-Metacello' ]) ifTrue: [ gofer package: wc packageName ]]. gofer unload.! ----- Method: ConfigurationOf class>>validate (in category 'accessing') ----- validate "Check the configuration for Errors, Critical Warnings, and Warnings (see class comment for MetacelloMCVersionValidator for more information). Errors identify specification issues that will result in unexpected behaviour when you load the configuration. Critical Warnings identify specification issues that may result in unexpected behavior when you load the configuration. Warnings identify specification issues that are technically correct, but are worth take a look at." "self validate" self ensureMetacello. ^ ((Smalltalk at: #MetacelloToolBox) validateConfiguration: self debug: #() recurse: false) explore! ----- Method: ConfigurationOf>>bleedingEdge (in category 'defaults') ----- bleedingEdge "override if different behavior desired. Use: self versionDoesNotExistError: #bleedingEdge if #bleedingEdge version is disallowed." ^self defaultBleedingEdgeVersion! ----- Method: ConfigurationOf>>customProjectAttributes (in category 'accessing') ----- customProjectAttributes "Edit to return a collection of any custom attributes e.g. for conditional loading: Array with: #'Condition1' with: #'Condition2. For more information see: http://code.google.com/p/metacello/wiki/CustomProjectAttrributes " ^ #()! ----- Method: ConfigurationOf>>defaultBleedingEdgeVersion (in category 'defaults') ----- defaultBleedingEdgeVersion | bleedingEdgeVersion | bleedingEdgeVersion := (self project map values select: [ :version | version blessing == #baseline ]) detectMax: [ :version | version ]. bleedingEdgeVersion ifNil: [ ^#'notDefined' ]. ^ bleedingEdgeVersion versionString! ----- Method: ConfigurationOf>>project (in category 'accessing') ----- project ^ project ifNil: [ "Bootstrap Metacello if it is not already loaded" self class ensureMetacello. project := self projectClass new projectAttributes: self customProjectAttributes. "Create the Metacello project" project versionNumberClass: self versionNumberClass. project class versionConstructorClass on: self project: project. "Construct the project" project loadType: #'linear'. "change to #atomic if desired" project ]! ----- Method: ConfigurationOf>>project: (in category 'accessing') ----- project: aProject project ifNil: [ self class ensureMetacello ]. project := aProject! ----- Method: ConfigurationOf>>projectClass (in category 'accessing') ----- projectClass ^ MetacelloMCProject! ----- Method: ConfigurationOf>>versionDoesNotExistError: (in category 'private') ----- versionDoesNotExistError: versionStringOrSymbol ((Smalltalk at: #MetacelloSymbolicVersionDoesNotExistError) project: self project versionString: versionStringOrSymbol) signal! ----- Method: ConfigurationOf>>versionNumberClass (in category 'accessing') ----- versionNumberClass ^ MetacelloSemanticVersionNumber! Object subclass: #Metacello instanceVariableNames: 'executorSpec statements' classVariableNames: '' poolDictionaries: '' category: 'Metacello-Base'! !Metacello commentStamp: 'dkh 7/28/2012 20:04' prior: 0! # Metacello User Guide In this guide we'll take a walk through a couple of common development scenarios and highlight some of the features of the *Metacello Scripting API*. *For installatation and more detailed documentation on the Metacello Scripting API, see the [Metcello Scripting API Documentation][1].* ## Introduction The number one job of the *Metacello Scripting API* is to simplify the job of loading projects into your image. As you are probably all too aware, today it's a two step process where you first load the configuration into your image using [Gofer][2] and then load your project using Metacello: ```Smalltalk Gofer new package: 'ConfigurationOfSeaside30'; squeaksource: 'MetacelloRepository'; load. ((Smalltalk at: #ConfigurationOfSeaside30) version: #stable) load. ``` In the early days of Metacello (and Gofer) this was a great improvement over the alternatives, but today, 3 years after the introduction of Metacello, there should be a better way...and there is. Using the *Metacello Scripting API* the above expression reduces to the following: ```Smalltalk Metacello new configuration: 'Seaside30'; load. ``` ## Loading In this example of the [`load` command][5] we are leveraging a couple of default values, namely the `version` of the project and the `repository` where the **ConfigurationOfSeaside** package can be found: ```Smalltalk Metacello new configuration: 'Seaside30'; load. ``` Here is a variant of the same expression with the (current) default values explicitly specified: ```Smalltalk Metacello new configuration: 'Seaside30'; version: #stable; squeaksource: 'MetacelloRepository'; load. ``` The `version` attribute can be any legal [version number][10]. `squeaksource` is a [repository shortcut][4]. You can also specify the full [repository description][3] as follows: ```Smalltalk Metacello new configuration: 'Seaside30'; version: #stable; repository: 'http://www.squeaksource.com/MetacelloRepository'; load. ``` ##Listing Once you've loaded one or more projects into your image, you may want to list them. The following is an example of the [`list` command][6]: ```Smalltalk Metacello image configuration: [:spec | true ]; list. ``` The `image` message tells Metacello that you'd like to look at only loaded configurations. The *block* argument to the `configuration:` message is used to *select* against the list of loaded [MetacelloProjectSpec][7] instances in the [registry][8]. The `list` command itself returns a list of [MetacelloProjectSpec][7] instances that can be printed, inspected or otherwise manipulated. In addition to a *select block*, you can specify a *select collection* specifying the names of the projects you'd like to select: ```Smalltalk Metacello registry configuration: #('Seaside30' 'MetacelloPreview'); list. ``` The `registry` message tells Metacello that you'd like to look at all projects in the [registry][8] whether or not they are loaded. The *collection* argument to the `configuration:` message is used to *select* against the list of project names in the [registry][8]. The `list` command can also be used to look at configurations in Monticello repositories. For example: ```Smalltalk Metacello new configuration: [:spec | spec name beginsWith: 'Seaside']; squeaksource: 'MetacelloRepository'; list. ``` lists the configurations whose names (sans the `ConfigurationOf`) begin with `Seaside` in the `MetacelloRepositry` in the [Squeaksource](http://www.squeaksource.com) repostory. ## Getting Once you've loaded a project into your image the next logical step is upgrading your project to a new version. Let's say that a new `#stable` version of Seaside30 has been released and that you want to upgrade. This is a two step process: * [get a new version of the configuration][11] * [load the new version][12] ### Get a new version of the configuration The following expression gets the latest version of the configuration: ```Smalltalk Metacello image configuration: 'Seaside30'; get. ``` By using the `image` message, you can leverage the fact that the [registry][8] remembers from which repository you loaded the original version of the configuration. The `get` command simply downloads the latest version of the configuration package from the repository. You may download the configuration from a different repository: ```Smalltalk Metacello image configuration: 'Seaside30'; squeaksource: 'Seaside30; get. ``` The `get` command will update the [registry][8] with the new repository location information. You may also use the `get` command to load a configuration for a project into your image without actually loading the project itself: ```Smalltalk Metacello image configuration: 'SeasideRest'; squeaksource: 'Seaside30'; get. ``` The 'SeasideRest' project information will be registered in the [registry][8] and marked as *unloaded*. ### Load the new version Once you've got a new copy of the Seaside30 configuration loaded into your image, you may upgrade your image with the following expression: ```Smalltalk Metacello image configuration: 'Seaside30'; version: #stable; load. ``` By using the `image` message, you are asking Metacello to look the project up in the [registry][8] before performing the operation, so it isn't necessary to supply all of the project details for every command operation. Of course, the `load` command updates the [registry][8]. If you want to load a project for which you've already done a `get` (like the SeasideRest project earlier), you can do the following: ```Smalltalk Metacello registry configuration: 'SeasideRest'; version: #stable; load. ``` In this case you use the `registry` message to indicate that you are interested in both *loaded* and *unloaded* projects. ##Locking Let's say that you are using an older version of Seaside30 (say 3.0.5) instead of the #stable version (3.0.7) and that your application doesn't work with newer versions of Seaside30 (you've tried and it's more work to get you application to work with the newer version of Seaside30 than it's worth). Let's also say that you want to try out something in the SeasideRest project, but when you try loading SeasideRest, you end up having Seaside 3.0.7 loaded as well. This is an unfortunate side effect of Metacello trying to *do the right thing*, only in your case it is the wrong thing. Fortunately, the [`lock` command][9] can give you control. First you need to `lock` the Seaside30 project: ```Smalltalk Metacello image configuration: 'Seaside30'; lock. ``` The `image` message tells Metacello to do a lookup in the list of loaded projects and then to put a lock on the loaded version of the project. If you want you can specify which version of the project you want locked: ```Smalltalk Metacello image configuration: 'Seaside30'; version: '3.0.5'; lock. ``` After a project is locked an error (**MetacelloLockedProjectError**) is thrown when you attempt to load a project that has a dependency upon a different version of Seaside30. The error is thrown before any packages are actually loaded. ### Bypassing locks Let's say that you want to load the SeasideRest project even though it may require a version of Seaside30 that is later than the version that you have locked. To do that you need to suppress the upgrade of the Seaside30 project during the load of the SeasideRest project and you can do that with the use of the `onUpgrade:` message: ```Smalltalk Metacello new configuration: 'SeasideRest'; version: #stable; onUpgrade: [:ex :existing :new | existing baseName = 'Seaside30' ifTrue: [ ex disallow ]. ex pass ]; load. ``` The `onUpgrade:` block tells Metacello to disallow the upgrade of any project whose `baseName` is `Seaside30` and to continue with the load. Of course if there are any explicit dependencies between SeasideRest and the later version of Seaside30 (missing classes, etc.) then you may very well get load errors or errors while using the SeasideRest, but that's the price you pay for not upgrading. ### Upgrading a locked project If you want to explicitly upgrade a locked project, you can use the `load` command. The following command will upgrade Seaside30 to version 3.0.6 even if it is locked: ```Smalltalk Metacello image configuration: 'Seaside30'; version: '3.0.6'; lock. ``` The newly loaded of the project will continue to be locked. [1]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md [2]: http://www.lukas-renggli.ch/blog/gofer [3]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#repository-descriptions [4]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#repository-shortcuts [5]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#loading [6]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#listing [7]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#metacelloprojectspec [8]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#metacello-project-registry [9]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#locking [10]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloScriptingAPI.md#metacello-version-numbers [11]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloUserGuide.md#get-a-new-version-of-the-configuration [12]: https://github.com/dalehenrich/metacello-work/blob/master/docs/MetacelloUserGuide.md#load-the-new-version! ----- Method: Metacello class>>classic (in category 'instance creation') ----- classic "set the options such that the load performed will be identical to the classic ConfigurationOf load: (ConfigurationOfExample project version: '1.0') load #classic forces Metacello to look at image state to determine which version of a project is loaded instead of using the registry to tell us explicitly which version of a project is loaded .. image state is not PRECISE" "useCurrentVersion is a 'private' option for enforcing classic rules, so it's not part of scripting api" ^ self new onUpgrade: [ :ex | ex allow ]; onConflict: [ :ex | ex allow ]; addStatement: #'useCurrentVersion:' args: {true}; yourself! ----- Method: Metacello class>>image (in category 'instance creation') ----- image ^ self new executorSpec: #'MetacelloScriptImageExecutor' -> 'batch'; yourself! ----- Method: Metacello class>>registry (in category 'instance creation') ----- registry ^ self new executorSpec: #'MetacelloScriptRegistryExecutor' -> 'batch'; yourself! ----- Method: Metacello class>>scriptExecutorClass (in category 'private') ----- scriptExecutorClass ^ self scriptExecutorClass: {(#'MetacelloScriptApiExecutor' -> 'batch')}! ----- Method: Metacello class>>scriptExecutorClass: (in category 'private') ----- scriptExecutorClass: anExecutorSpec Smalltalk at: anExecutorSpec key ifAbsent: [ ConfigurationOf ensureMetacello: anExecutorSpec value ]. ^ Smalltalk at: anExecutorSpec key! ----- Method: Metacello>>addStatement:args: (in category 'private') ----- addStatement: selector args: args self statements add: selector -> args! ----- Method: Metacello>>baseline: (in category 'api projectSpec') ----- baseline: projectName self addStatement: #'baselineArg:' args: {projectName}! ----- Method: Metacello>>blueplane: (in category 'api repository shortcuts') ----- blueplane: projectName self repository: 'http://squeaksource.blueplane.jp/' , projectName! ----- Method: Metacello>>cacheRepository: (in category 'api options') ----- cacheRepository: aRepositoryDescription self addStatement: #'cacheRepository:' args: {aRepositoryDescription}! ----- Method: Metacello>>className: (in category 'api projectSpec') ----- className: className self addStatement: #'classNameArg:' args: {className}! ----- Method: Metacello>>configuration: (in category 'api projectSpec') ----- configuration: projectName self addStatement: #'configurationArg:' args: {projectName}! ----- Method: Metacello>>croquet: (in category 'api repository shortcuts') ----- croquet: projectName self repository: 'http://hedgehog.software.umn.edu:8888/' , projectName! ----- Method: Metacello>>execute (in category 'private') ----- execute | script | script := self statements. self statements: nil. ^ self scriptExecutor execute: script! ----- Method: Metacello>>executorSpec (in category 'accessing') ----- executorSpec executorSpec ifNil: [ executorSpec := #'MetacelloScriptApiExecutor' -> 'batch' ]. ^ executorSpec! ----- Method: Metacello>>executorSpec: (in category 'accessing') ----- executorSpec: anAssoc executorSpec := anAssoc! ----- Method: Metacello>>fetch (in category 'api actions') ----- fetch self addStatement: #'fetch:' args: #(#()). ^ self execute! ----- Method: Metacello>>fetch: (in category 'api actions') ----- fetch: required self addStatement: #'fetch:' args: {required}. ^ self execute! ----- Method: Metacello>>gemsource: (in category 'api repository shortcuts') ----- gemsource: projectName self repository: 'http://seaside.gemtalksystems.com/ss/' , projectName! ----- Method: Metacello>>get (in category 'api actions') ----- get "resolve project name in given repository and return an instance of MetacelloProject resolved from a ConfigurationOf or BaselineOf" self addStatement: #'get' args: #(). ^ self execute! ----- Method: Metacello>>ignoreImage (in category 'api options') ----- ignoreImage "ignore image state" self addStatement: #'ignoreImage:' args: {true}! ----- Method: Metacello>>impara: (in category 'api repository shortcuts') ----- impara: projectName self repository: 'http://source.impara.de/' , projectName! ----- Method: Metacello>>list (in category 'api actions') ----- list "list projects in registry" self addStatement: #'list' args: #(). ^ self execute! ----- Method: Metacello>>load (in category 'api actions') ----- load self addStatement: #'load:' args: #(#()). ^ self execute! ----- Method: Metacello>>load: (in category 'api actions') ----- load: required self addStatement: #'load:' args: {required}. ^ self execute! ----- Method: Metacello>>lock (in category 'api actions') ----- lock "lock projects in registry" self addStatement: #'lock' args: #(). ^ self execute! ----- Method: Metacello>>onConflict: (in category 'api options') ----- onConflict: aBlock self addStatement: #'onConflict:' args: {aBlock}! ----- Method: Metacello>>onDowngrade: (in category 'api options') ----- onDowngrade: aBlock self addStatement: #'onDowngrade:' args: {aBlock}! ----- Method: Metacello>>onUpgrade: (in category 'api options') ----- onUpgrade: aBlock self addStatement: #'onUpgrade:' args: {aBlock}! ----- Method: Metacello>>project: (in category 'api projectSpec') ----- project: projectName self addStatement: #'projectArg:' args: {projectName}! ----- Method: Metacello>>record (in category 'api actions') ----- record self addStatement: #'record:' args: #(#()). ^ self execute! ----- Method: Metacello>>record: (in category 'api actions') ----- record: required self addStatement: #'record:' args: {required}. ^ self execute! ----- Method: Metacello>>renggli: (in category 'api repository shortcuts') ----- renggli: projectName self repository: 'http://source.lukas-renggli.ch/' , projectName! ----- Method: Metacello>>repository: (in category 'api projectSpec') ----- repository: repositoryDescription self addStatement: #'repositoryArg:' args: {repositoryDescription}! ----- Method: Metacello>>repositoryOverrides: (in category 'api options') ----- repositoryOverrides: aRepositoryDescriptionCollection self addStatement: #'repositoryOverrides:' args: {aRepositoryDescriptionCollection}! ----- Method: Metacello>>saltypickle: (in category 'api repository shortcuts') ----- saltypickle: projectName self repository: 'http://squeak.saltypickle.com/' , projectName! ----- Method: Metacello>>scriptExecutor (in category 'accessing') ----- scriptExecutor ^ (self class scriptExecutorClass: self executorSpec) new! ----- Method: Metacello>>silently (in category 'api options') ----- silently "no progress bars" self addStatement: #'silently:' args: {true}! ----- Method: Metacello>>squeakfoundation: (in category 'api repository shortcuts') ----- squeakfoundation: projectName self repository: 'http://source.squeakfoundation.org/' , projectName! ----- Method: Metacello>>squeaksource3: (in category 'api repository shortcuts') ----- squeaksource3: projectName self repository: 'http://ss3.gemstone.com/ss/' , projectName! ----- Method: Metacello>>squeaksource: (in category 'api repository shortcuts') ----- squeaksource: projectName self repository: 'http://www.squeaksource.com/' , projectName! ----- Method: Metacello>>ss3: (in category 'api repository shortcuts') ----- ss3: projectName self squeaksource3: projectName! ----- Method: Metacello>>statements (in category 'accessing') ----- statements statements ifNil: [ statements := OrderedCollection new ]. ^ statements! ----- Method: Metacello>>statements: (in category 'accessing') ----- statements: anObject statements := anObject! ----- Method: Metacello>>unlock (in category 'api actions') ----- unlock "unlock projects in registry" self addStatement: #'unlock' args: #(). ^ self execute! ----- Method: Metacello>>version: (in category 'api projectSpec') ----- version: versionString self addStatement: #'versionArg:' args: {versionString}! ----- Method: Metacello>>wiresong: (in category 'api repository shortcuts') ----- wiresong: projectName self repository: 'http://source.wiresong.ca/' , projectName! From commits at source.squeak.org Sat Oct 18 23:48:28 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 18 23:48:34 2014 Subject: [squeak-dev] The Inbox: GraphicsTests-fbs.38.mcz Message-ID: A new version of GraphicsTests was added to project The Inbox: http://source.squeak.org/inbox/GraphicsTests-fbs.38.mcz ==================== Summary ==================== Name: GraphicsTests-fbs.38 Author: fbs Time: 20 December 2013, 1:30:35.779 pm UUID: 081189cc-a44f-fa4e-965e-25438280ea93 Ancestors: GraphicsTests-fbs.37 Bare #assert:s are useless in an offline environment. =============== Diff against GraphicsTests-fbs.37 =============== Item was changed: ----- Method: PNGReadWriterTest>>decodeColors:depth: (in category 'tests - decoding') ----- decodeColors: colorsAndFiles depth: requiredDepth colorsAndFiles do:[:assoc| | form color bytes | color := assoc key. bytes := Base64MimeConverter mimeDecodeToBytes: assoc value readStream. form := PNGReadWriter formFromStream: bytes. + self assert: requiredDepth equals: form depth description: 'Form depth'. + self assert: (color pixelValueForDepth: requiredDepth) equals: (form pixelValueAt: 1@1) description: 'Corner pixel'. - self assert: form depth = requiredDepth. - self assert: (form pixelValueAt: 1@1) = (color pixelValueForDepth: requiredDepth). ].! From commits at source.squeak.org Sat Oct 18 23:48:37 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 18 23:48:40 2014 Subject: [squeak-dev] The Inbox: ToolBuilder-Morphic-mt.93.mcz Message-ID: A new version of ToolBuilder-Morphic was added to project The Inbox: http://source.squeak.org/inbox/ToolBuilder-Morphic-mt.93.mcz ==================== Summary ==================== Name: ToolBuilder-Morphic-mt.93 Author: mt Time: 13 August 2014, 10:55:11.88 am UUID: b0f4fa7e-d60a-e944-98b3-341e5df2fb91 Ancestors: ToolBuilder-Morphic-mt.92 Added support for pluggable scroll panes as introduced in ToolBuilder-Kernel-mt.62 (merged from inbox) =============== Diff against ToolBuilder-Morphic-mt.92 =============== From commits at source.squeak.org Sat Oct 18 23:48:38 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 18 23:48:42 2014 Subject: [squeak-dev] The Inbox: KernelTests-ul.278.mcz Message-ID: A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-ul.278.mcz ==================== Summary ==================== Name: KernelTests-ul.278 Author: ul Time: 8 October 2014, 12:38:15.725 pm UUID: 6ee3d1ac-77c4-4550-bff8-7db203c28f50 Ancestors: KernelTests-dtl.277 RandomTest changes: - updated #testWellKnownSequence to match the new seed hashing values - added two new test cases for edge case seed values =============== Diff against KernelTests-dtl.277 =============== Item was changed: ----- Method: RandomTest>>testNext (in category 'tests') ----- testNext 10000 timesRepeat: [ | next | next := gen next. + self assert: next >= 0.0. + self assert: next < 1.0 ].! - self assert: (next >= 0). - self assert: (next < 1). - ].! Item was added: + ----- Method: RandomTest>>testNextForEdgeCases (in category 'tests') ----- + testNextForEdgeCases + " Test #next for edge case input-output pairs " + + self assert: 0.0 equals: (Random seed: 1407677000) next. + self assert: (1 << 31 - 1) asFloat / (1 << 31) asFloat equals: (Random seed: 0) next! Item was added: + ----- Method: RandomTest>>testNextValueForEdgeCases (in category 'tests') ----- + testNextValueForEdgeCases + " Test #nextValue for edge case input-output pairs " + + self assert: 1.0 equals: (Random seed: 1407677000) nextValue. + self assert: (1 << 31 - 1) asFloat equals: (Random seed: 0) nextValue! Item was changed: ----- Method: RandomTest>>testWellKnownSequence (in category 'tests') ----- testWellKnownSequence "This test assert the immutability of Random generation algorithm. It uses Float equality tests, which is a very strict notion of immutability. Anyone changing Random algorithm will have to adapt this test." | theSeedOfWellKnownSequence wellKnownSequence rng effectiveSequence | theSeedOfWellKnownSequence := 2345678901. + wellKnownSequence := #(0.32506402597067136 0.3510923149767762 0.8085456405806102 0.22658906421930952 0.28241015983857687 0.46756423286514553 0.3520695904046621 0.23361375705972953 0.3464227287780599 0.32681039875690376). - wellKnownSequence := #(0.14924326965084453 0.3316330217437972 0.7561964480002394 0.3937015400238808 0.9417831813645471 0.5499291939427746 0.6599625962134277 0.991354559078512 0.6960744325518955 0.922987899707159 ). rng := Random new. rng seed: theSeedOfWellKnownSequence. effectiveSequence := (1 to: 10) collect: [:i | rng next ]. self assert: effectiveSequence equals: wellKnownSequence! From commits at source.squeak.org Sat Oct 18 23:48:42 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 18 23:48:45 2014 Subject: [squeak-dev] The Inbox: ShoutCore-ul.42.mcz Message-ID: A new version of ShoutCore was added to project The Inbox: http://source.squeak.org/inbox/ShoutCore-ul.42.mcz ==================== Summary ==================== Name: ShoutCore-ul.42 Author: ul Time: 8 July 2014, 2:38:44.976 pm UUID: 071b2588-3dfb-433a-be3c-6db67e8f07dd Ancestors: ShoutCore-nice.41, ShoutCore-ul.41 - merged - use #encodedCharSet where possible =============== Diff against ShoutCore-nice.41 =============== Item was changed: Object subclass: #SHParserST80 + instanceVariableNames: 'classOrMetaClass source workspace arguments sourcePosition currentToken currentTokenFirst temporaries instanceVariables errorBlock currentTokenSourcePosition blockDepth bracketDepth ranges environment encodedCharSet' - instanceVariableNames: 'classOrMetaClass source workspace arguments sourcePosition currentToken currentTokenFirst temporaries instanceVariables errorBlock currentTokenSourcePosition blockDepth bracketDepth ranges environment' classVariableNames: '' poolDictionaries: '' category: 'ShoutCore-Parsing'! !SHParserST80 commentStamp: 'tween 8/16/2004 15:44' prior: 0! I am a Smalltalk method / expression parser. Rather than creating an Abstract Syntax Tree, I create a sequence of SHRanges (in my 'ranges' instance variable), which represent the tokens within the String I am parsing. I am used by a SHTextStylerST80 to parse method source strings. I am able to parse incomplete / incorrect methods, and so can be used to parse methods that are being edited. My 'source' instance variable should be set to the string to be parsed. My 'classOrMetaClass' instance var must be set to the class or metaClass for the method source so that I can correctly resolve identifiers within the source. If this is nil , I parse the source as an expression (i.e. a doIt expression). My 'workspace' instance variable can be set to a Workspace, so that I can resolve workspace variables. My 'environment' instance variable is the global namespace (this is initialized to Smalltalk, but can be set to a different environment). Example 1. ranges := SHParserST80 new classOrMetaClass: Object; source: 'testMethod ^self'; parse; ranges ! Item was changed: ----- Method: SHParserST80>>currentChar (in category 'scan') ----- currentChar + ^source at: sourcePosition ifAbsent: nil! - ^source at: sourcePosition ifAbsent: [nil]! Item was changed: ----- Method: SHParserST80>>isKeyword (in category 'token testing') ----- isKeyword "This method assumes that currentTokenFirst is a non-letter character when currentToken is nil." + ^((encodedCharSet isLetter: currentTokenFirst) or: [ - ^(currentTokenFirst isLetter or: [ currentTokenFirst == $_ and: [ currentToken notNil and: [ currentToken size > 1 and: [ self allowUnderscoreSelectors ] ] ] ]) and: [ currentToken last == $: ]! Item was changed: ----- Method: SHParserST80>>isName (in category 'token testing') ----- isName "This method assumes that currentTokenFirst is a non-letter character when currentToken is nil." + ^((encodedCharSet isLetter: currentTokenFirst) + or: [ currentTokenFirst == $_ + and: [ currentToken notNil + and: [ currentToken size > 1 + and: [ self allowUnderscoreSelectors ] ] ] ]) + and: [ (encodedCharSet isAlphaNumeric: currentToken last) + or: [ currentToken last == $_ + and: [ self allowUnderscoreSelectors ] ] ] ! - ^(currentTokenFirst isLetter or: [ - currentTokenFirst == $_ and: [ - currentToken notNil and: [ - currentToken size > 1 and: [ - self allowUnderscoreSelectors ] ] ] ]) and: [ - currentToken last isAlphaNumeric or: [ - currentToken last == $_ and: [ - self allowUnderscoreSelectors ] ] ] ! Item was changed: ----- Method: SHParserST80>>isSelectorCharacter: (in category 'character testing') ----- isSelectorCharacter: aCharacter + (encodedCharSet isAlphaNumeric: aCharacter) ifTrue: [^false]. - aCharacter isAlphaNumeric ifTrue: [^false]. aCharacter isSeparator ifTrue:[^false]. ('"#$'':().;[]{}^_' includes: aCharacter) ifTrue:[^false]. aCharacter asciiValue = 30 ifTrue: [^false "the doIt char"]. aCharacter asciiValue = 0 ifTrue: [^false]. "Any other char is ok as a binary selector char." ^true ! Item was changed: ----- Method: SHParserST80>>parseByteArray (in category 'parse') ----- parseByteArray [currentTokenFirst == $]] whileFalse: [ + (encodedCharSet isDigit: currentTokenFirst) - currentTokenFirst isDigit ifTrue: [ "do not parse the number, can be time consuming" self scanPast: #number] ifFalse: [ self failWhen: currentTokenFirst == $. . self error]]. self scanPast: #byteArrayEnd! Item was changed: ----- Method: SHParserST80>>parseExternalCall (in category 'parse') ----- parseExternalCall [self scanNext. ((Smalltalk at: #ExternalFunction) callingConventionModifierFor: currentToken) notNil] whileTrue. self failUnless: currentToken notNil. self scanPast: #externalCallType. currentToken = '*' ifTrue: [self scanPast: #externalCallTypePointerIndicator]. + (encodedCharSet isDigit: currentTokenFirst) - currentTokenFirst isDigit ifTrue: [self scanPast: #integer] ifFalse: [ self failUnless: currentTokenFirst == $'. self parseString]. self failUnless: currentTokenFirst == $(. self scanPast: #leftParenthesis. [currentTokenFirst ~= $)] whileTrue: [ self failUnless: currentToken notNil. self scanPast: #externalCallType. currentToken = '*' ifTrue: [self scanPast: #externalCallTypePointerIndicator]]. self scanPast: #rightParenthesis. currentToken = 'module:' ifTrue: [ self scanPast: #module. self parseStringOrSymbol ]. currentToken = 'error:' ifTrue: [ self scanPast: #primitive. "there's no rangeType for error" self isName ifTrue: [ self scanPast: #patternTempVar ] ifFalse: [ self parseStringOrSymbol ] ]. self failUnless: currentToken = '>'. self scanPast: #primitiveOrExternalCallEnd! Item was changed: ----- Method: SHParserST80>>parseLiteral: (in category 'parse') ----- parseLiteral: inArray currentTokenFirst == $$ ifTrue: [ | pos | self failWhen: self currentChar isNil. self rangeType: #'$'. pos := currentTokenSourcePosition + 1. self nextChar. ^self scanPast: #character start: pos end: pos]. + (encodedCharSet isDigit: currentTokenFirst) - currentTokenFirst isDigit ifTrue: [ "do not parse the number, can be time consuming" ^self scanPast: #number]. currentToken = '-' ifTrue: [ | c | c := self currentChar. + (inArray and: [c isNil or: [(encodedCharSet isDigit: c) not]]) - (inArray and: [c isNil or: [c isDigit not]]) ifTrue: [ "single - can be a symbol in an Array" ^self scanPast: #symbol]. self scanPast: #-. self failWhen: currentToken isNil. "token isNil ifTrue: [self error: 'Unexpected End Of Input']." "do not parse the number, can be time consuming" ^self scanPast: #number]. currentTokenFirst == $' ifTrue: [^self parseString]. currentTokenFirst == $# ifTrue: [^self parseSymbol]. (inArray and: [currentToken notNil]) ifTrue: [^self scanPast: #symbol]. self failWhen: currentTokenFirst == $. . self error ": 'argument missing'"! Item was changed: ----- Method: SHParserST80>>parseLiteralArrayElement (in category 'parse') ----- parseLiteralArrayElement + (encodedCharSet isLetter: currentTokenFirst) - currentTokenFirst isLetter ifTrue: [ + #true = currentToken ifTrue: [ ^self scanPast: #true ]. + #false = currentToken ifTrue: [ ^self scanPast: #false ]. + #nil = currentToken ifTrue: [ ^self scanPast: #nil ]. + ^self scanPast: #symbol ]. - | type | - type := (#('true' 'false' 'nil') includes: currentToken) - ifTrue: [currentToken asSymbol] - ifFalse: [#symbol]. - ^self scanPast: type]. currentTokenFirst == $( ifTrue: [ self scanPast: #arrayStart. ^self parseArray]. ^self parseLiteral: true! Item was changed: ----- Method: SHParserST80>>parsePrimitive (in category 'parse') ----- parsePrimitive self scanNext. + (encodedCharSet isDigit: currentTokenFirst) - currentTokenFirst isDigit ifTrue: [ self scanPast: #integer ] ifFalse: [ self parseStringOrSymbol. currentToken = 'module:' ifTrue: [ self scanPast: #module. self parseStringOrSymbol ] ]. currentToken = 'error:' ifTrue: [ self scanPast: #primitive. "there's no rangeType for error" self isName ifTrue: [ self scanPast: #patternTempVar ] ifFalse: [ self parseStringOrSymbol ] ]. self failUnless: currentToken = '>'. self scanPast: #primitiveOrExternalCallEnd! Item was changed: ----- Method: SHParserST80>>parseString (in category 'parse') ----- parseString + | first c last | - | first c answer last | first := sourcePosition. - answer := ''. [(c := self currentChar) ifNil: [ self rangeType: #unfinishedString start: first - 1 end: source size. self error ": 'unfinished string'"]. + c ~~ $' or: [ - (c == $' - ifFalse: [answer := answer copyWith: c. true] - ifTrue: [false] - ) or: [ self peekChar == $' ifTrue: [ sourcePosition := sourcePosition + 1. - answer := answer copyWith: $'. true] ifFalse: [false]] ] whileTrue: [sourcePosition := sourcePosition + 1]. last := sourcePosition. self nextChar. + self scanPast: #string start: first - 1 end: last! - self scanPast: #string start: first - 1 end: last. - ^answer! Item was changed: ----- Method: SHParserST80>>parseSymbol (in category 'parse') ----- parseSymbol | c | currentToken = '#' ifTrue: [ "if token is just the #, then scan whitespace and comments and then process the next character. Squeak allows space between the # and the start of the symbol e.g. # (), # a, # 'sym' " self rangeType: #symbol. self scanWhitespace]. c := self currentChar. self failWhen: (c isNil or: [c isSeparator]). c == $( ifTrue: [ self nextChar. self scanPast: #arrayStart start: currentTokenSourcePosition end: currentTokenSourcePosition + 1. ^self parseArray]. c == $' ifTrue: [^self parseSymbolString]. c == $[ ifTrue: [ self nextChar. self scanPast: #byteArrayStart start: currentTokenSourcePosition end: currentTokenSourcePosition + 1. ^self parseByteArray]. ((self isSelectorCharacter: c) or: [c == $-]) ifTrue: [^self parseSymbolSelector]. + ((encodedCharSet isLetter: c) or: [ - (c isLetter or: [ c == $: or: [ c == $_ and: [self allowUnderscoreSelectors] ] ]) ifTrue: [^self parseSymbolIdentifier]. ^self parseCharSymbol! Item was changed: ----- Method: SHParserST80>>parseSymbolIdentifier (in category 'parse') ----- parseSymbolIdentifier | c start end | c := self currentChar. + self failUnless: ((encodedCharSet isLetter: c) or: [c == $: or: [c == $_ and: [self allowUnderscoreSelectors]]]). - self failUnless: (c isLetter or: [c == $: or: [c == $_ and: [self allowUnderscoreSelectors]]]). start := sourcePosition. [c := self nextChar. + (encodedCharSet isAlphaNumeric: c) or: [c == $: or: [c == $_ and: [self allowUnderscoreSelectors]]]] whileTrue. - c isAlphaNumeric or: [c == $: or: [c == $_ and: [self allowUnderscoreSelectors]]]] whileTrue. end := sourcePosition - 1. c := source copyFrom: start - 1 to: end. self scanPast: #symbol start: start - 1 end: end. ^c! Item was changed: ----- Method: SHParserST80>>peekChar (in category 'scan') ----- peekChar + ^source at: sourcePosition + 1 ifAbsent: $ ! - ^source at: sourcePosition + 1 ifAbsent: [$ ]! Item was changed: ----- Method: SHParserST80>>resolve: (in category 'identifier testing') ----- + resolve: aString + + aString = #self ifTrue: [ ^#self ]. + aString = #true ifTrue: [ ^#true ]. + aString = #false ifTrue: [ ^#false ]. + aString = #nil ifTrue: [ ^#nil ]. + aString = #super ifTrue: [ ^#super ]. + aString = #thisContext ifTrue: [ ^#thisContext ]. - resolve: aString - (#('self' 'super' 'true' 'false' 'nil' 'thisContext') includes: aString) - ifTrue: [^aString asSymbol]. (self isBlockTempName: aString) ifTrue: [^#blockTempVar]. (self isBlockArgName: aString) ifTrue: [^#blockArg]. (self isMethodTempName: aString) ifTrue: [^#tempVar]. (self isMethodArgName: aString) ifTrue: [^#methodArg]. (instanceVariables includes: aString) ifTrue: [^#instVar]. workspace ifNotNil: [(workspace hasBindingOf: aString) ifTrue: [^#workspaceVar]]. Symbol hasInterned: aString ifTrue: [:sym | classOrMetaClass isBehavior ifTrue: [ classOrMetaClass theNonMetaClass withAllSuperclasses do: [:c | (c classPool bindingOf: sym) ifNotNil: [^#classVar]. c sharedPools do: [:p | (p bindingOf: sym) ifNotNil: [^#poolConstant]]. (c environment bindingOf: sym) ifNotNil: [^#globalVar]]] ifFalse: [(environment bindingOf: sym) ifNotNil: [^#globalVar]]]. ^self resolvePartial: aString! Item was changed: ----- Method: SHParserST80>>scanIdentifier (in category 'scan') ----- scanIdentifier | c start | start := sourcePosition. + [(encodedCharSet isAlphaNumeric: (c := self nextChar)) or: [c == $_ and: [self allowUnderscoreSelectors]]] whileTrue. - [(c := self nextChar) isAlphaNumeric or: [c == $_ and: [self allowUnderscoreSelectors]]] whileTrue. (c == $: and: [(self isSelectorCharacter: self peekChar) not]) ifTrue: [self nextChar]. currentToken := source copyFrom: start to: sourcePosition - 1. currentTokenSourcePosition := start! Item was changed: ----- Method: SHParserST80>>scanNext (in category 'scan') ----- scanNext self scanWhitespace. currentTokenFirst := self currentChar. currentTokenFirst ifNil: [" end of input " currentTokenFirst := $ . currentTokenSourcePosition := nil. currentToken := nil. ^nil]. + (encodedCharSet isDigit: currentTokenFirst) ifTrue: [^self scanNumber]. + ((encodedCharSet isLetter: currentTokenFirst) or: [ - currentTokenFirst isDigit ifTrue: [^self scanNumber]. - (currentTokenFirst isLetter or: [ currentTokenFirst == $_ and: [ self allowUnderscoreSelectors ] ]) ifTrue: [^self scanIdentifier]. ^self scanBinary! Item was changed: ----- Method: SHParserST80>>scanNumber (in category 'scan') ----- scanNumber | start c nc base | start := sourcePosition. self skipDigits. c := self currentChar. c == $r ifTrue: [ base := Integer readFrom: (ReadStream on: (source copyFrom: start to: sourcePosition - 1)). self peekChar == $- ifTrue:[self nextChar]. self skipBigDigits: base. c := self currentChar. c == $. ifTrue: [ (self isBigDigit: self nextChar base: base) ifFalse: [sourcePosition := sourcePosition - 1] ifTrue: [self skipBigDigits: base]]. c := self currentChar. ('deq'includes: c) ifTrue: [ + ((encodedCharSet isDigit: (nc := self nextChar)) or: [nc == $- and:[(encodedCharSet isDigit: self peekChar)]]) - ((nc := self nextChar) isDigit or: [nc == $- and:[self peekChar isDigit]]) ifFalse: [sourcePosition := sourcePosition - 1] ifTrue: [self skipDigits]]. c == $s ifTrue: [ + (encodedCharSet isDigit: self nextChar) - self nextChar isDigit ifFalse: [sourcePosition := sourcePosition - 1] ifTrue: [self skipDigits]]. currentToken := source copyFrom: start to: sourcePosition - 1. ^currentTokenSourcePosition := start]. c == $s ifTrue: [ + (encodedCharSet isDigit: self nextChar) - self nextChar isDigit ifFalse: [sourcePosition := sourcePosition - 1] ifTrue: [self skipDigits.]. currentToken := source copyFrom: start to: sourcePosition - 1. ^currentTokenSourcePosition := start]. c == $. ifTrue: [ + (encodedCharSet isDigit: self nextChar) - self nextChar isDigit ifFalse: [ sourcePosition := sourcePosition - 1. currentToken := source copyFrom: start to: sourcePosition - 1. ^currentTokenSourcePosition := start] ifTrue: [self skipDigits]]. c := self currentChar. ('deq' includes: c) ifTrue: [ + ((encodedCharSet isDigit: (nc := self nextChar)) or: [nc == $- and:[(encodedCharSet isDigit: self peekChar)]]) - ((nc := self nextChar) isDigit or: [nc == $- and:[self peekChar isDigit]]) ifFalse: [sourcePosition := sourcePosition - 1] ifTrue: [self skipDigits]]. c == $s ifTrue: [ + (encodedCharSet isDigit: self nextChar) - self nextChar isDigit ifFalse: [sourcePosition := sourcePosition - 1] ifTrue: [self skipDigits]]. currentToken := source copyFrom: start to: sourcePosition - 1. ^currentTokenSourcePosition := start! Item was changed: ----- Method: SHParserST80>>scanPast: (in category 'scan') ----- scanPast: rangeType "record rangeType for current token . record argument and temp declarations. scan and answer the next token" + rangeType == #blockPatternArg ifTrue: [self pushArgument: currentToken]. + rangeType == #blockPatternTempVar ifTrue: [self pushTemporary: currentToken]. + rangeType == #patternArg ifTrue: [self pushArgument: currentToken]. + rangeType == #patternTempVar ifTrue: [self pushTemporary: currentToken]. - rangeType = #blockPatternArg ifTrue: [self pushArgument: currentToken]. - rangeType = #blockPatternTempVar ifTrue: [self pushTemporary: currentToken]. - rangeType = #patternArg ifTrue: [self pushArgument: currentToken]. - rangeType = #patternTempVar ifTrue: [self pushTemporary: currentToken]. ^self rangeType: rangeType; scanNext! Item was changed: ----- Method: SHParserST80>>skipDigits (in category 'scan') ----- skipDigits + + [ (encodedCharSet isDigit: self nextChar) ] whileTrue! - [self nextChar isDigit] - whileTrue: []! Item was changed: ----- Method: SHParserST80>>source: (in category 'accessing') ----- source: aString + + source := aString. + encodedCharSet := (source at: 1 ifAbsent: [ $0 ]) encodedCharSet + ! - source := aString! From karlramberg at gmail.com Sun Oct 19 10:41:56 2014 From: karlramberg at gmail.com (karl ramberg) Date: Sun Oct 19 10:42:00 2014 Subject: [squeak-dev] Contribution Instructions In-Reply-To: <1413675297489-4785338.post@n4.nabble.com> References: <1413675297489-4785338.post@n4.nabble.com> Message-ID: Bert made this video for Etoys: https://www.youtube.com/watch?v=2QKmfI4taGo Karl On Sun, Oct 19, 2014 at 1:34 AM, Sean P. DeNigris wrote: > Does something exist like https://pharo.org/contribute-propose-fix for > Pharo? > An apparent new user is asking a lot of very basic questions about how to > contribute a fix. On > > http://stackoverflow.com/questions/26442071/how-to-check-out-code-for-squeaksource > , > Tobias suggested "A New Community Development Model". I went to look myself > and it didn't really seem to be geared toward newbies. Is there anywhere > such a user can go that explains the process from start to finish? > > > > ----- > Cheers, > Sean > -- > View this message in context: > http://forum.world.st/Contribution-Instructions-tp4785338.html > Sent from the Squeak - Dev mailing list archive at Nabble.com. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141019/03867d3c/attachment.htm From juanlists at jvuletich.org Sun Oct 19 11:16:32 2014 From: juanlists at jvuletich.org (J. Vuletich (mail lists)) Date: Sun Oct 19 11:16:40 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: <79896CE5-203D-4057-95AC-5FB371031F67@gmail.com> References: <190A33CE-D3D3-41C7-BB80-EF929E6EF1BA@gmail.com> <79896CE5-203D-4057-95AC-5FB371031F67@gmail.com> Message-ID: <20141019111632.Horde.9T2EfAQTkbY-WmZzNgm3Aw8@gator3294.hostgator.com> Hi Eliot, Casey, Quoting Eliot Miranda : > Hi Casey, > > On Oct 17, 2014, at 12:37 AM, Casey Ransberger > wrote: > ? > >> Hi Eliot. I will make time to install Spur (assuming it's presently >> working on the Mac.) I'll use it as my primary VM unless I run into >> problems, in which case I will report them. > > ? > > Yes, I build Spur VMs alongside Cog VMs, so they're available for Mac, > x86 Windows and x86 linux. ?(and soon stack VMs for ARM linux). > ? > And thank you, both for using it and for these great questions. > ? > > >> I think I understood you, but I want to be clear; you're saying that >> (like Cog) changes needed to be made to the image to support the new >> VM.? > > ? > In this case more like to exploit the new VM. ?So 32-bit Spur has > immediate characters alongside immediate SmallIntegers, and 64-bit Spur > will add immediate floats. ?Spur has a 64k literal limit in methods vs > 256 in V3 (pre-Spur). ?There are slightly different versions of > Behavior>>new, new:, basicNew & basicNew: to marry with the new GC and > segmented heap, and there are primitives for allInstances and > allObjects. ?These are all benefits that could have been done without, > but are clearly good and indeed the 64k literal limit exists in V3 > Newspeak. > ? > In fact, the 64k limit is also associated with support for two > bytecode sets. ?And that leads to support for Sista, the adaptive > optimizer we hope will be available later next year. > ? > The necessary change is to add Behavior>>identityHash to ensure a > class's identityHash is its index in the VM's class table. ?This is what > keeps Spur objects relatively compact, and keeps their header uniform. > ?i.e. every object's header contains its class's index in a 22-bit field > instead of a direct reference to its class object. Thanks for all this detail. It will be really useful. >> Query: can the Interpreter (either that or Stack) VM be modified to >> support images which run above Spur? Or is this necessarily a forking >> event? (CC Cuis folks.) > > ? > Yes. ?Stack Spur VMs are easily generable from a VMMaker image. ?In fact > Stack Spur was the first working version. ?But porting the context > Interpreter means finishing the merge with trunk VMMaker for which the > community (in the person of David Lewis and myself) have so few cycles > (volunteers welcome, but they must be prepared to merge the Interpreter > into the Cog branch, not the other way). WRT Stack Spur VM, this is indeed great news! It means that Cuis can adopt the Spur image format and continue to be fully multi-platform, without needing to maintain two active branchs. Yay! WRT the context Interpreter, it would be nice to merge it, essentially to ease the landscape to contributors. >> Query: should incorporating the changes to the image that you have >> outlined below into Cuis allow Cuis to make use of the new VM? (I >> perhaps am digging very vaguely into what those changes are. Sorry I'm >> not presently equipped to ask smarter questions: I'm probably just >> beside myself with enthusiasm for your work and perchance "jumping the >> gun" a bit.) > > ? > Yes. ?The bootstrap is written as an image editor. ?Adding support for > Cuis should be straightforward, provided Cuis's compiler is brought > close to trunk's (to support and exploit the 64k literal limit and > multiple bytecode sets). > ? The Cuis compiler has always been close to Squeak's, especially after Cuis adopted Cog. (For the record, AFAIK, I was the only person, besides Eliot, to migrate a context Interpreter image to Cog. That was Cuis, of course.) Eliot, after taking a look at the Spur bootstrap some months ago (haven't found time yet to make it work on Cuis), and reading this message of yours, I wonder, wouldn't it make sense to do just the essential (i.e. mandatory) changes (like?Behavior>>identityHash, rehashing, image header, etc) in the bootstrap? Then do all the rest afterwards, after starting the image with a Spur VM. ?This should ease significantly adapting this second part to various Squeak images, and would encourage wider adoption by other projects. It would also ease keeing the Spur bootstrap updated, as the target images keep changing. > Anyone motivated to port Cuis should contact me to discuss and for me to > show you around the code. Thanks for the offer, Eliot. If nobody else in the Cuis community beats me to it (folks, you are welcome to do it!), I will. Right now all my spare cycles are devoted to advancing Morphic 3 (the pre-alpha code was released MIT recently). But I will have time to do this in maybe a month, and I will really appreciate your help. >> TIA, > > ? > Thanks. ?These questions have allowed me to clarify. ?But do you (or > anyone else) have any opinions or concerns about the parallel > development model for trunk I outlined? > ? > > >> Casey >> ? >> P.S. >> ? >> Please forgive the pun, if you noticed it! :D > > ? > I missed it :-/ > > Eliot (phone) > >> ? Thanks Eliot for the thoughtful answer, and thanks Casey for asking the questions. Cheers, Juan Vuletich >> On Oct 16, 2014, at 11:51 PM, Eliot Miranda >> wrote: >> ? >> >>> Hi All, ? >>> ? ? finally the Spur Squeak trunk image is updateable.? The >>> image in?http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ >>> was created today and thanks to Bert Freudenberg's latest Monticello >>> work can be updated independently of the non-Spur trunk.? Spur VMs are >>> available in?http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and >>> later as they appear).? Without wanting to appear too overconfident >>> the Spur system looks to be ready for use apart from image segments >>> (which I hope to have working some time next month).? I'm really >>> interested in having this stress tested by as many people as >>> possible.? Spur really does offer a significant performance and >>> functionality improvement over the current system, but it needs >>> testing to ensure its reliability. >>> ? >>> Esteban Lorenzano is hard at work on the Pharo bootstrap for >>> Spur so I hope Pharo 4 Spur will be available soon. >>> ? >>> As far as trunk goes, using Spur alongside non-Spur trunk is >>> going to be difficult to manage for the near future.? Right now, Spur >>> modifies the Collections, Compiler, Kernel and System packages, and >>> this is done by auto-editing the non-Spur versions of those packages, >>> something I do periodically as new versions arrive.? I also auto-edit >>> trunk configurations (the part of the image update scheme that ensures >>> packages are loaded in the right order when there are dependencies >>> between packages) from non-Spur "update" to Spur "update.spur" forms.? >>> This at east means that Spur can keep up with trunk.? But it does >>> /not/ provide a way of committing to?Collections.spur, Compiler.spur, >>> Kernel.spur or System.spur without getting out of sync with non-Spur >>> trunk.? Note that apart from these packages, one /can/ safely commit >>> any other package from a Spur image to trunk. >>> ? >>> Right now the plan is to release both V3 (the pre-Spur >>> format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak >>> 5.0).? This isn't my preference.? I'd like to see just Spur released, >>> once reliability is verified.? But I understand the safety and >>> backward-compatibility concerns (Spur won't be able to load V3 image >>> segments, and vice verse).? The issue is of course that we have this >>> tricky package situation to manage where, to keep the two systems in >>> sync, modifications to Collections, Compiler, Kernel and System need >>> to be committed from V3 and auto-edited to Spur. I think that's too >>> clumsy to be practicable.? Perhaps allowing the two systems to fork >>> and doing a manual merge will be acceptable, but it'll be work to keep >>> them in sync. >>> -- >>> best, Eliot >> >>> ? > >> ? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141019/02cb5cd6/attachment-0001.htm From leves at elte.hu Sun Oct 19 15:31:11 2014 From: leves at elte.hu (Levente Uzonyi) Date: Sun Oct 19 15:31:18 2014 Subject: [squeak-dev] The Inbox: SMBase-nice.132.mcz In-Reply-To: References: Message-ID: I don't know who and why pushed these packages to The Inbox, but I moved them to The Treated Inbox. Levente From kbrown at mac.com Sun Oct 19 22:54:02 2014 From: kbrown at mac.com (Ken G. Brown) Date: Sun Oct 19 22:54:04 2014 Subject: [squeak-dev] Shrinking In-Reply-To: References: Message-ID: <63D5220D-9180-4979-8158-65D2C328762B@mac.com> An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141019/b0ceb74e/attachment.htm From lewis at mail.msen.com Sun Oct 19 23:26:33 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sun Oct 19 23:26:35 2014 Subject: [squeak-dev] Error when Opening Repo from MC Browser In-Reply-To: <1413675855785-4785340.post@n4.nabble.com> References: <1413675855785-4785340.post@n4.nabble.com> Message-ID: <20141019232633.GA89099@shell.msen.com> On Sat, Oct 18, 2014 at 04:44:15PM -0700, Sean P. DeNigris wrote: > Squeak4.5 > latest update: #13965 > > 1. In MC Browser, select http://source.squeak.org/trunk > 2. Click open > > I get "Error: subscript is out of bounds: -2" when > SocketStream>>upToAll:limit: computes a negative index via "lastRead - sz + > 2", which is (0 - 4 + 2). > I am not seeing this in my image. Anyone else? Possible a transient network problem? Dave From eliot.miranda at gmail.com Mon Oct 20 01:01:29 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 20 01:01:32 2014 Subject: [squeak-dev] Image Segment semantics and weakness Message-ID: Hi All, I want to check my understanding of reference semantics for image segments as I'm close to completing the Spur implementation. Specifically the question is whether objects reachable only through weak pointers should be included in an image segment or not. Remember that an image segment is created from the transitive closure of an Array of root objects, the *segment roots*. i.e. we can think of an image segment as a set of objects created by tracing the object graph from the segment roots. The segment always includes the segment roots. Except for the roots, objects are excluded from the segment that are also reachable form the roots of the system (the *system roots*, effectively the root environment, Smalltalk, and the stack of the current process). Consider a weak array in the transitive closure that is not reachable from the system roots, and hence should be included in the segment. Objects referenced from that weak array may be in one of three categories - reachable from the system roots (and hence not to be included in the segment) - *not* reachable form the system roots, but reachable from the segment roots via strong pointers (and hence to be included in the segment) - *not* reachable form the system roots, *not* reachable from the segment roots via strong pointers Should this last category be included or excluded from the segment? I think that it makes no difference, and excluding them is only an optimization. The argument is as follows. Imagine that immediately after loading the image segment there is a garbage collection. That garbage collection will collect all the objects in the last category as they are only reachable from the weak arrays in the segment. Hence we are free to follow weak references as if they are strong when we create the image segment, leaving it to subsequent events to reclaim those objects. An analogous argument accounts for objects reachable from ephemerons. Is my reasoning sound? -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141019/39617144/attachment.htm From juanlists at jvuletich.org Mon Oct 20 14:21:04 2014 From: juanlists at jvuletich.org (J. Vuletich (mail lists)) Date: Mon Oct 20 14:21:11 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: Message-ID: <20141020142104.Horde.8GeCQ1mgSb_PPouvQ0DjEA1@gator3294.hostgator.com> Hi Eliot, Quoting Eliot Miranda : > Hi All, ? > ? ? I want to check my understanding of reference semantics for image > segments as I'm close to completing the Spur implementation.? > Specifically the question is whether objects reachable only through weak > pointers should be included in an image segment or not. > ? > Remember that an image segment is created from the transitive closure > of an Array of root objects, the /segment roots/. i.e. we can think of > an image segment as a set of objects created by tracing the object graph > from the segment roots. > ? > The segment always includes the segment roots.? Except for the roots, > objects are excluded from the segment that are also reachable form the > roots of the system (the /system roots/,?effectively the root > environment, Smalltalk, and the stack of the current process). > ? > Consider a weak array in the transitive closure that is not reachable > from the system roots, and hence should be included in the segment.? > Objects referenced from that weak array may be in one of three categories > ? > - reachable from the system roots (and hence not to be included in > the segment) > - /not/?reachable form the system roots, but?reachable from the > segment roots via strong pointers (and hence to be included in the > segment) > -?/not/?reachable form the system roots, /not/?reachable from the > segment roots via strong pointers > ? > Should this last category be included or excluded from the segment?? > I think that it makes no difference, and excluding them is only an > optimization.? The argument is as follows.? Imagine that immediately > after loading the image segment there is a garbage collection.? That > garbage collection will collect all the objects in the last category as > they are only reachable from the weak arrays in the segment.? Hence we > are free to follow weak references as if they are strong when we create > the image segment, leaving it to subsequent events to reclaim those > objects. ? > ? > An analogous argument accounts for objects reachable from > ephemerons.? Is my reasoning sound? > -- > best, Eliot I think you are right. But there is a risk of somehow, someone, gaining a strong reference to the object after the image segment was created, breaking our invariants when the segment is loaded again. An object might be (not reachable / strongly reachable / weakely reachable) from system roots and / or segment roots. This gives us 9 possibilities. Six of them are easy (and I'll not go into them). The other three are tricky: a- Not reachable from system roots. Weakely reachable from segment roots. Do not include them. It is best to run a GC before building the image segment, to get rid of them (run termination, etc). This is to avoid the risk of the object gaining somehow a strong reference after the segment is built, making the segment miss the weak ref to it. Doing this way would also mean that any objects affected by termination would be consistent, both in the image and in the segment. b- Weakely reachable from system roots. Weakely reachable from segment roots. Do not include them. If the object manages to survive by gaining a strong ref from the system roots, the weak ref will be repaired on segment load (Am I right on this?) If the original object was included in the segment, then on segment load it would point to a duplicate object that is about to be collected (and maybe terminated?) In any case, doing this way would also mean that any objects affected by termination would be consistent, both in the image and in the segment. c- Weakely reachable from system roots. Strongly reachable from segment roots. Do include them. It seems reasonable to run a GC and get rid of them after unloading the segment, to avoid the risk of the object gaining somehow a strong ref in the image, and being duplicated on segment load. But doing as I say means that we would be loading into the image an object that was already terminated, although in the state it had before running termination. Not really sure if this is ok. There could be some risk of objects in the segment being in some pre-termination state, with some objects in the image being in some after-termination state. In any case, this would suggest bad design... So perhaps it makes sense to throw an exception in these cases? I hope this rant is of use. Cheers, Juan Vuletich -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141020/99920655/attachment.htm From sean at clipperadams.com Mon Oct 20 18:12:50 2014 From: sean at clipperadams.com (Sean P. DeNigris) Date: Mon Oct 20 18:15:20 2014 Subject: [squeak-dev] Re: Error when Opening Repo from MC Browser In-Reply-To: <20141019232633.GA89099@shell.msen.com> References: <1413675855785-4785340.post@n4.nabble.com> <20141019232633.GA89099@shell.msen.com> Message-ID: <1413828770954-4785593.post@n4.nabble.com> David T. Lewis wrote > "lastRead - sz + 2", which is (0 - 4 + 2). > > I am not seeing this in my image. Anyone else? Possible a transient > network problem? I can not reproduce this again either. Sorry for the noise :) p.s. At the time it when I reported it, it was failing consistently and I worked around it by changing the "+ 2" to "+ 5" ----- Cheers, Sean -- View this message in context: http://forum.world.st/Error-when-Opening-Repo-from-MC-Browser-tp4785340p4785593.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From eliot.miranda at gmail.com Mon Oct 20 19:41:51 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 20 19:41:55 2014 Subject: [squeak-dev] Re: [Pharo-dev] Image Segment semantics and weakness In-Reply-To: <54452992.4050506@free.fr> References: <54452992.4050506@free.fr> Message-ID: On Mon, Oct 20, 2014 at 8:26 AM, stepharo wrote: > While I as a big fan of imageSegment and proposed to mariano to work on > imageSegment2 (it was the original idea for his phd) > he convinced us that imagesegment were not worth their complexity. > I absolutely agree. > So why do you want to have imageSegment? > Because of backwards-compatibility. If Spur does not provide image segments then the barrier to entry for Terf, eToys and Squeak may be too high. Spur is supposed to be a plug-in replacement for Cog, not something that requires lots of effort to port to. > Stef > > > > On 20/10/14 03:01, Eliot Miranda wrote: > > Hi All, > > I want to check my understanding of reference semantics for image > segments as I'm close to completing the Spur implementation. Specifically > the question is whether objects reachable only through weak pointers should > be included in an image segment or not. > > Remember that an image segment is created from the transitive closure of > an Array of root objects, the *segment roots*. i.e. we can think of an > image segment as a set of objects created by tracing the object graph from > the segment roots. > > The segment always includes the segment roots. Except for the roots, > objects are excluded from the segment that are also reachable form the > roots of the system (the *system roots*, effectively the root > environment, Smalltalk, and the stack of the current process). > > Consider a weak array in the transitive closure that is not reachable > from the system roots, and hence should be included in the segment. > Objects referenced from that weak array may be in one of three categories > > - reachable from the system roots (and hence not to be included in the > segment) > - *not* reachable form the system roots, but reachable from the segment > roots via strong pointers (and hence to be included in the segment) > - *not* reachable form the system roots, *not* reachable from the segment > roots via strong pointers > > Should this last category be included or excluded from the segment? I > think that it makes no difference, and excluding them is only an > optimization. The argument is as follows. Imagine that immediately after > loading the image segment there is a garbage collection. That garbage > collection will collect all the objects in the last category as they are > only reachable from the weak arrays in the segment. Hence we are free to > follow weak references as if they are strong when we create the image > segment, leaving it to subsequent events to reclaim those objects. > > An analogous argument accounts for objects reachable from ephemerons. > Is my reasoning sound? > -- > best, > Eliot > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141020/50843267/attachment.htm From estebanlm at gmail.com Mon Oct 20 20:00:06 2014 From: estebanlm at gmail.com (Esteban Lorenzano) Date: Mon Oct 20 20:00:12 2014 Subject: [squeak-dev] Re: [Vm-dev] Re: [Pharo-dev] Image Segment semantics and weakness In-Reply-To: References: <54452992.4050506@free.fr> Message-ID: > On 20 Oct 2014, at 21:41, Eliot Miranda wrote: > > > > On Mon, Oct 20, 2014 at 8:26 AM, stepharo > wrote: > While I as a big fan of imageSegment and proposed to mariano to work on imageSegment2 (it was the original idea for his phd) > he convinced us that imagesegment were not worth their complexity. > > I absolutely agree. > > So why do you want to have imageSegment? > > Because of backwards-compatibility. If Spur does not provide image segments then the barrier to entry for Terf, eToys and Squeak may be too high. Spur is supposed to be a plug-in replacement for Cog, not something that requires lots of effort to port to. but? (and tell me if I?m saying something stupid), it would be probably better to ask the guys using ImageSegments to spend some time doing an adaptor to use fuel (who is already there, works fine and faster than ImageSegments itself). In the not-so-long term, is better investment that make you replicate a technology that we all agree is not the best option (also, I would bet is better to use your valuable time in other stuff). Is not that there is no alternative to IS? and also, the IS binary format for Spur will not be compatible with the older one, so? why not? anyway, that?s my 2c Esteban > > Stef > > > > On 20/10/14 03:01, Eliot Miranda wrote: >> Hi All, >> >> I want to check my understanding of reference semantics for image segments as I'm close to completing the Spur implementation. Specifically the question is whether objects reachable only through weak pointers should be included in an image segment or not. >> >> Remember that an image segment is created from the transitive closure of an Array of root objects, the segment roots. i.e. we can think of an image segment as a set of objects created by tracing the object graph from the segment roots. >> >> The segment always includes the segment roots. Except for the roots, objects are excluded from the segment that are also reachable form the roots of the system (the system roots, effectively the root environment, Smalltalk, and the stack of the current process). >> >> Consider a weak array in the transitive closure that is not reachable from the system roots, and hence should be included in the segment. Objects referenced from that weak array may be in one of three categories >> >> - reachable from the system roots (and hence not to be included in the segment) >> - not reachable form the system roots, but reachable from the segment roots via strong pointers (and hence to be included in the segment) >> - not reachable form the system roots, not reachable from the segment roots via strong pointers >> >> Should this last category be included or excluded from the segment? I think that it makes no difference, and excluding them is only an optimization. The argument is as follows. Imagine that immediately after loading the image segment there is a garbage collection. That garbage collection will collect all the objects in the last category as they are only reachable from the weak arrays in the segment. Hence we are free to follow weak references as if they are strong when we create the image segment, leaving it to subsequent events to reclaim those objects. >> >> An analogous argument accounts for objects reachable from ephemerons. Is my reasoning sound? >> -- >> best, >> Eliot > > > > > -- > best, > Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141020/d52639e6/attachment.htm From asqueaker at gmail.com Mon Oct 20 20:46:00 2014 From: asqueaker at gmail.com (Chris Muller) Date: Mon Oct 20 20:46:02 2014 Subject: [squeak-dev] Error when Opening Repo from MC Browser In-Reply-To: <20141019232633.GA89099@shell.msen.com> References: <1413675855785-4785340.post@n4.nabble.com> <20141019232633.GA89099@shell.msen.com> Message-ID: Transient network problems should result in network-Exceptions being signaled, not buffer pointers errors. I sent a message a week or two ago, "What is the contract of SocketStream>>#next:?" which talked about a similar-sounding problem with a different method. Since then I saw the problem happen again (#next: 4 giving me back an empty Array with no error signaled at all). I traced through the code for over an hour trying to figure what could posisbly have happened, but the code looks correct.. On Sun, Oct 19, 2014 at 6:26 PM, David T. Lewis wrote: > On Sat, Oct 18, 2014 at 04:44:15PM -0700, Sean P. DeNigris wrote: >> Squeak4.5 >> latest update: #13965 >> >> 1. In MC Browser, select http://source.squeak.org/trunk >> 2. Click open >> >> I get "Error: subscript is out of bounds: -2" when >> SocketStream>>upToAll:limit: computes a negative index via "lastRead - sz + >> 2", which is (0 - 4 + 2). >> > > I am not seeing this in my image. Anyone else? Possible a transient network problem? > > Dave > From commits at source.squeak.org Tue Oct 21 00:49:17 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 21 00:49:19 2014 Subject: [squeak-dev] The Trunk: Collections-cmm.585.mcz Message-ID: Chris Muller uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-cmm.585.mcz ==================== Summary ==================== Name: Collections-cmm.585 Author: cmm Time: 20 October 2014, 7:48:42.698 pm UUID: 954b50eb-27a5-41e8-9b9f-a49f39336c75 Ancestors: Collections-ul.584 Speed up visiting with #addNewElement:. It provides the common pattern of checking for inclusion, followed by add:, in just one scan, instead of two. =============== Diff against Collections-ul.584 =============== Item was added: + ----- Method: Set>>addNewElement: (in category 'adding') ----- + addNewElement: anObject + "Ensure anObject is part of the receiver. Answer whether its membership was newly acquired." + | index | + index := self scanFor: anObject. + ^ (array at: index) + ifNil: + [ self + atNewIndex: index + put: anObject asSetElement. + true ] + ifNotNil: [ false ]! From jvuletich at dc.uba.ar Tue Oct 21 00:56:53 2014 From: jvuletich at dc.uba.ar (jvuletich@dc.uba.ar) Date: Tue Oct 21 00:57:00 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: Message-ID: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Hi Eliot, > Hi All, > > I want to check my understanding of reference semantics for image > segments as I'm close to completing the Spur implementation. Specifically > the question is whether objects reachable only through weak pointers > should > be included in an image segment or not. > > Remember that an image segment is created from the transitive closure of > an > Array of root objects, the *segment roots*. i.e. we can think of an image > segment as a set of objects created by tracing the object graph from the > segment roots. > > The segment always includes the segment roots. Except for the roots, > objects are excluded from the segment that are also reachable form the > roots of the system (the *system roots*, effectively the root environment, > Smalltalk, and the stack of the current process). > > Consider a weak array in the transitive closure that is not reachable from > the system roots, and hence should be included in the segment. Objects > referenced from that weak array may be in one of three categories > > - reachable from the system roots (and hence not to be included in the > segment) > - *not* reachable form the system roots, but reachable from the segment > roots via strong pointers (and hence to be included in the segment) > - *not* reachable form the system roots, *not* reachable from the segment > roots via strong pointers > > Should this last category be included or excluded from the segment? I > think that it makes no difference, and excluding them is only an > optimization. The argument is as follows. Imagine that immediately after > loading the image segment there is a garbage collection. That garbage > collection will collect all the objects in the last category as they are > only reachable from the weak arrays in the segment. Hence we are free to > follow weak references as if they are strong when we create the image > segment, leaving it to subsequent events to reclaim those objects. > > An analogous argument accounts for objects reachable from ephemerons. Is > my reasoning sound? > -- > best, > Eliot > > I think you are right. But there is a risk of somehow, someone, gaining a strong reference to the object after the image segment was created, breaking our invariants when the segment is loaded again. An object might be (not reachable / strongly reachable / weakely reachable) from system roots and / or segment roots. This gives us 9 possibilities. Six of them are easy (and I'll not go into them). The other three are tricky: a- Not reachable from system roots. Weakely reachable from segment roots. Do not include them. It is best to run a GC before building the image segment, to get rid of them (run termination, etc). This is to avoid the risk of the object gaining somehow a strong reference after the segment is built, making the segment miss the weak ref to it. Doing this way would also mean that any objects affected by termination would be consistent, both in the image and in the segment. b- Weakely reachable from system roots. Weakely reachable from segment roots. Do not include them. If the object manages to survive by gaining a strong ref from the system roots, the weak ref will be repaired on segment load (Am I right on this?) If the original object was included in the segment, then on segment load it would point to a duplicate object that is about to be collected (and maybe terminated?) In any case, doing this way would also mean that any objects affected by termination would be consistent, both in the image and in the segment. c- Weakely reachable from system roots. Strongly reachable from segment roots. Do include them. It seems reasonable to run a GC and get rid of them after unloading the segment, to avoid the risk of the object gaining somehow a strong ref in the image, and being duplicated on segment load. But doing as I say means that we would be loading into the image an object that was already terminated, although in the state it had before running termination. Not really sure if this is ok. There could be some risk of objects in the segment being in some pre-termination state, with some objects in the image being in some after-termination state. In any case, this would suggest bad design... So perhaps it makes sense to throw an exception in these cases? I hope this rant is of use. Cheers, Juan Vuletich From jvuletich at dc.uba.ar Tue Oct 21 00:56:53 2014 From: jvuletich at dc.uba.ar (jvuletich@dc.uba.ar) Date: Tue Oct 21 00:57:01 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: Message-ID: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Hi Eliot, > Hi All, > > I want to check my understanding of reference semantics for image > segments as I'm close to completing the Spur implementation. Specifically > the question is whether objects reachable only through weak pointers > should > be included in an image segment or not. > > Remember that an image segment is created from the transitive closure of > an > Array of root objects, the *segment roots*. i.e. we can think of an image > segment as a set of objects created by tracing the object graph from the > segment roots. > > The segment always includes the segment roots. Except for the roots, > objects are excluded from the segment that are also reachable form the > roots of the system (the *system roots*, effectively the root environment, > Smalltalk, and the stack of the current process). > > Consider a weak array in the transitive closure that is not reachable from > the system roots, and hence should be included in the segment. Objects > referenced from that weak array may be in one of three categories > > - reachable from the system roots (and hence not to be included in the > segment) > - *not* reachable form the system roots, but reachable from the segment > roots via strong pointers (and hence to be included in the segment) > - *not* reachable form the system roots, *not* reachable from the segment > roots via strong pointers > > Should this last category be included or excluded from the segment? I > think that it makes no difference, and excluding them is only an > optimization. The argument is as follows. Imagine that immediately after > loading the image segment there is a garbage collection. That garbage > collection will collect all the objects in the last category as they are > only reachable from the weak arrays in the segment. Hence we are free to > follow weak references as if they are strong when we create the image > segment, leaving it to subsequent events to reclaim those objects. > > An analogous argument accounts for objects reachable from ephemerons. Is > my reasoning sound? > -- > best, > Eliot > > I think you are right. But there is a risk of somehow, someone, gaining a strong reference to the object after the image segment was created, breaking our invariants when the segment is loaded again. An object might be (not reachable / strongly reachable / weakely reachable) from system roots and / or segment roots. This gives us 9 possibilities. Six of them are easy (and I'll not go into them). The other three are tricky: a- Not reachable from system roots. Weakely reachable from segment roots. Do not include them. It is best to run a GC before building the image segment, to get rid of them (run termination, etc). This is to avoid the risk of the object gaining somehow a strong reference after the segment is built, making the segment miss the weak ref to it. Doing this way would also mean that any objects affected by termination would be consistent, both in the image and in the segment. b- Weakely reachable from system roots. Weakely reachable from segment roots. Do not include them. If the object manages to survive by gaining a strong ref from the system roots, the weak ref will be repaired on segment load (Am I right on this?) If the original object was included in the segment, then on segment load it would point to a duplicate object that is about to be collected (and maybe terminated?) In any case, doing this way would also mean that any objects affected by termination would be consistent, both in the image and in the segment. c- Weakely reachable from system roots. Strongly reachable from segment roots. Do include them. It seems reasonable to run a GC and get rid of them after unloading the segment, to avoid the risk of the object gaining somehow a strong ref in the image, and being duplicated on segment load. But doing as I say means that we would be loading into the image an object that was already terminated, although in the state it had before running termination. Not really sure if this is ok. There could be some risk of objects in the segment being in some pre-termination state, with some objects in the image being in some after-termination state. In any case, this would suggest bad design... So perhaps it makes sense to throw an exception in these cases? I hope this rant is of use. Cheers, Juan Vuletich From lewis at mail.msen.com Tue Oct 21 01:35:01 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 21 01:35:03 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: References: Message-ID: <20141021013501.GA43489@shell.msen.com> On Thu, Oct 16, 2014 at 11:51:20PM -0700, Eliot Miranda wrote: > Hi All, > > finally the Spur Squeak trunk image is updateable. Yay! > The issue > is of course that we have this tricky package situation to manage where, to > keep the two systems in sync, modifications to Collections, Compiler, > Kernel and System need to be committed from V3 and auto-edited to Spur. I > think that's too clumsy to be practicable. When I look at the Spur related changes to these four large packages, it seems to me that we might be able to reduce the scope of the problem by moving the parts that require changes into separate packages or sub-packages. The portions of these packages that need to change are not insignificant, but if they were contained within well defined package boundaries, they might become simpler to manage. To illustrate: The changes in the Collections package are almost entirely related to class Character, whose instances are immediate in the Spur format. It might make very good sense if the methods directly related to immediateness of a character were localized in a package where they can be maintained independently of all the other Collections classes and methods. Looking at it from another angle, the Kernel package is arguably too large, and if I want to make changes to Kernel-Chronology (as I have recently been doing with UTCDateAndTime just as an example), then I have problems if I want to coordinate that external package with Squeak trunk. If I also want to coordinate my little project with all the updates required for both Kernel and Kernel.spur, the situation becomes impossible. I apologize in advance because I have not really thought this through in detail, but it seems to me that a bit of pragmatic reorganization of our package structure might make the Spur transition a lot easier to manage. I note that in the past we have put energy into reorganizing our package structures in the interest of making the image more modular. That is important, but managing the transition to Spur is even more important. If improving the package structure could make this easier, then we should make it a priority. > Perhaps allowing the two > systems to fork and doing a manual merge will be acceptable, but it'll be > work to keep them in sync. I agree. I also think that this kind of maintenance work is not enjoyable, and is not likely to be kept up on an ongoing basis. So we need to think of ways for the path forward to be A) enjoyable or B) not too much work or C) all of the above :-) Dave From marianopeck at gmail.com Tue Oct 21 01:55:38 2014 From: marianopeck at gmail.com (Mariano Martinez Peck) Date: Tue Oct 21 01:55:41 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Message-ID: Just a quick note I would like to share.... For my PhD, I did investigate ImageSegment very very deeply: http://dl.acm.org/citation.cfm?id=2076323 http://www.slideshare.net/MarianoMartinezPeck/2010-smalltalkspeckobject-swapping I didn't want to write Fuel just because. I took quite a lot of time to understand how ImageSegment primitives worked. From that effort, I remember a few conclusions: 1) I found only few users of ImageSegment 2) The few users I found, were NOT using the real purpose of ImageSegment, that is, object swapping. It was used instead as an object serializer. For that, they use #writeForExportOn: which ended up using SmartRefStream for the rest of the objects. 3) I noticed I could achieve the same performance or even better with an OO serializer built at the language side, with all the benefits this means. Of course, having Cog helped here.... In the Fuel paper: http://rmod.lille.inria.fr/archives/papers/Dias12a-SPE-Fuel.pdf you can find some benchmark comparison agains IS. Also in my PhD: http://rmod.lille.inria.fr/archives/phd/PhD-2012-Martinez-Peck.pdf Cheers, On Mon, Oct 20, 2014 at 9:56 PM, wrote: > Hi Eliot, > > > Hi All, > > > > I want to check my understanding of reference semantics for image > > segments as I'm close to completing the Spur implementation. > Specifically > > the question is whether objects reachable only through weak pointers > > should > > be included in an image segment or not. > > > > Remember that an image segment is created from the transitive closure of > > an > > Array of root objects, the *segment roots*. i.e. we can think of an image > > segment as a set of objects created by tracing the object graph from the > > segment roots. > > > > The segment always includes the segment roots. Except for the roots, > > objects are excluded from the segment that are also reachable form the > > roots of the system (the *system roots*, effectively the root > environment, > > Smalltalk, and the stack of the current process). > > > > Consider a weak array in the transitive closure that is not reachable > from > > the system roots, and hence should be included in the segment. Objects > > referenced from that weak array may be in one of three categories > > > > - reachable from the system roots (and hence not to be included in the > > segment) > > - *not* reachable form the system roots, but reachable from the segment > > roots via strong pointers (and hence to be included in the segment) > > - *not* reachable form the system roots, *not* reachable from the segment > > roots via strong pointers > > > > Should this last category be included or excluded from the segment? I > > think that it makes no difference, and excluding them is only an > > optimization. The argument is as follows. Imagine that immediately > after > > loading the image segment there is a garbage collection. That garbage > > collection will collect all the objects in the last category as they are > > only reachable from the weak arrays in the segment. Hence we are free to > > follow weak references as if they are strong when we create the image > > segment, leaving it to subsequent events to reclaim those objects. > > > > An analogous argument accounts for objects reachable from ephemerons. Is > > my reasoning sound? > > -- > > best, > > Eliot > > > > > > I think you are right. But there is a risk of somehow, someone, gaining a > strong reference to the object after the image segment was created, > breaking our invariants when the segment is loaded again. > > An object might be (not reachable / strongly reachable / weakely > reachable) from system roots and / or segment roots. This gives us 9 > possibilities. > Six of them are easy (and I'll not go into them). The other three are > tricky: > > a- Not reachable from system roots. Weakely reachable from segment roots. > Do not include them. It is best to run a GC before building the image > segment, to get rid of them (run termination, etc). This is to avoid the > risk of the object gaining somehow a strong reference after the segment is > built, making the segment miss the weak ref to it. Doing this way would > also mean that any objects affected by termination would be consistent, > both in the image and in the segment. > > b- Weakely reachable from system roots. Weakely reachable from segment > roots. > Do not include them. If the object manages to survive by gaining a strong > ref from the system roots, the weak ref will be repaired on segment load > (Am I right on this?) If the original object was included in the segment, > then on segment load it would point to a duplicate object that is about to > be collected (and maybe terminated?) In any case, doing this way would also > mean that any objects affected by termination would be consistent, both in > the image and in the segment. > > c- Weakely reachable from system roots. Strongly reachable from segment > roots. > Do include them. It seems reasonable to run a GC and get rid of them after > unloading the segment, to avoid the risk of the object gaining somehow a > strong ref in the image, and being duplicated on segment load. But doing as > I say means that we would be loading into the image an object that was > already terminated, although in the state it had before running > termination. Not really sure if this is ok. There could be some risk of > objects in the segment being in some pre-termination state, with some > objects in the image being in some after-termination state. In any case, > this would suggest bad design... So perhaps it makes sense to throw an > exception in these cases? > > I hope this rant is of use. > > Cheers, > Juan Vuletich > > > > -- Mariano http://marianopeck.wordpress.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141020/7911440c/attachment.htm From eliot.miranda at gmail.com Tue Oct 21 02:18:14 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 21 02:18:16 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: <20141021013501.GA43489@shell.msen.com> References: <20141021013501.GA43489@shell.msen.com> Message-ID: Hi David, On Mon, Oct 20, 2014 at 6:35 PM, David T. Lewis wrote: > On Thu, Oct 16, 2014 at 11:51:20PM -0700, Eliot Miranda wrote: > > Hi All, > > > > finally the Spur Squeak trunk image is updateable. > > Yay! > > > The issue > > is of course that we have this tricky package situation to manage where, > to > > keep the two systems in sync, modifications to Collections, Compiler, > > Kernel and System need to be committed from V3 and auto-edited to Spur. I > > think that's too clumsy to be practicable. > > When I look at the Spur related changes to these four large packages, it > seems > to me that we might be able to reduce the scope of the problem by moving > the > parts that require changes into separate packages or sub-packages. The > portions > of these packages that need to change are not insignificant, but if they > were > contained within well defined package boundaries, they might become simpler > to manage. > > To illustrate: The changes in the Collections package are almost entirely > related to class Character, whose instances are immediate in the Spur > format. > It might make very good sense if the methods directly related to > immediateness > of a character were localized in a package where they can be maintained > independently of all the other Collections classes and methods. > > Looking at it from another angle, the Kernel package is arguably too > large, and > if I want to make changes to Kernel-Chronology (as I have recently been > doing > with UTCDateAndTime just as an > example), > then I have problems if I want to coordinate that external package with > Squeak > trunk. If I also want to coordinate my little project with all the updates > required for both Kernel and Kernel.spur, the situation becomes impossible. > > I apologize in advance because I have not really thought this through in > detail, but it seems to me that a bit of pragmatic reorganization of our > package structure might make the Spur transition a lot easier to manage. > > I note that in the past we have put energy into reorganizing our package > structures in the interest of making the image more modular. That is > important, > but managing the transition to Spur is even more important. If improving > the > package structure could make this easier, then we should make it a > priority. > While I'm happy to see packages decomposed I've chosen the approach to changing the four relevant packages Spur modifies for good reason. Essentially once we move to Spur I don't want there to be artifacts present which are simply to do with the change to Spur. So keeping Collections, Compiler, Kernel and System whole but in Spur-specific branches allows us to keep the system looking the same once we release it. Further, all the support for branching and editing these packages is now working and I'm really not keep on putting more effort into it to complicate it further. I've got lots of other things to do. So now that Spur works and is nearly ready for release can we let it be? > > Perhaps allowing the two > > systems to fork and doing a manual merge will be acceptable, but it'll be > > work to keep them in sync. > > I agree. I also think that this kind of maintenance work is not enjoyable, > and is not likely to be kept up on an ongoing basis. So we need to think > of ways for the path forward to be A) enjoyable or B) not too much work or > C) all of the above :-) > Well, we should discuss what the release criteria are at the next board meeting. We may be able to release before the end of the year, which would be great. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141020/c87f8576/attachment.htm From commits at source.squeak.org Tue Oct 21 15:16:12 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 21 15:16:15 2014 Subject: [squeak-dev] The Trunk: Nebraska-ul.38.mcz Message-ID: Levente Uzonyi uploaded a new version of Nebraska to project The Trunk: http://source.squeak.org/trunk/Nebraska-ul.38.mcz ==================== Summary ==================== Name: Nebraska-ul.38 Author: ul Time: 21 October 2014, 5:13:14.046 pm UUID: 4891da96-28c4-4a50-84d6-6dd4a8b109d0 Ancestors: Nebraska-nice.37 There's no guarantee for port 9999 being available. Use whatever port socket1 got. =============== Diff against Nebraska-nice.37 =============== Item was changed: ----- Method: ArbitraryObjectSocketTestCase>>setUp (in category 'setup') ----- setUp "it would be nice to have an in-image loopback socket, so that the tests do not need the underlying platform's sockets to behave nicely" socket1 := Socket newTCP. socket2 := Socket newTCP. socket1 listenOn: 9999. + socket2 connectTo: (NetNameResolver localHostAddress) port: socket1 port. - socket2 connectTo: (NetNameResolver localHostAddress) port: 9999. socket1 waitForConnectionFor: 60. socket2 waitForConnectionFor: 60. end1 := ArbitraryObjectSocket on: socket1. end2 := ArbitraryObjectSocket on: socket2. ! Item was changed: ----- Method: StringSocketTestCase>>setUp (in category 'running') ----- setUp "it would be nice to have an in-image loopback socket, so that the tests do not need the underlying platform's sockets to behave nicely" socket1 := Socket newTCP. socket2 := Socket newTCP. socket1 listenOn: 9999. + socket2 connectTo: (NetNameResolver localHostAddress) port: socket1 port. - socket2 connectTo: (NetNameResolver localHostAddress) port: 9999. socket1 waitForConnectionFor: 60. socket2 waitForConnectionFor: 60. end1 := StringSocket on: socket1. end2 := StringSocket on: socket2. ! From edgardec2005 at gmail.com Tue Oct 21 15:45:01 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Tue Oct 21 15:45:12 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: <7EFDF49E-397A-46E5-A4EB-087534734CCC@gmail.com> Message-ID: On 10/15/14, 11:07 PM, "Chris Cunnington" wrote: > The FunSqueak link is in the Beginners? section of the Downloads page. The > Donate button is on the homepage. > > Chris The link is for older 4.3 , not for current 4.6 Thanks for include my pet ! Edgar From brasspen at gmail.com Tue Oct 21 15:46:19 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Tue Oct 21 15:46:23 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: References: Message-ID: <0AEC8702-B382-49D6-A30D-678AD1DFC8E5@gmail.com> If you give me the link, then I?ll update it. Chris > On Oct 21, 2014, at 11:45 AM, Edgar J. De Cleene wrote: > > > > > On 10/15/14, 11:07 PM, "Chris Cunnington" wrote: > >> The FunSqueak link is in the Beginners? section of the Downloads page. The >> Donate button is on the homepage. >> >> Chris > > > The link is for older 4.3 , not for current 4.6 > > Thanks for include my pet ! > > Edgar > > > From lewis at mail.msen.com Tue Oct 21 20:45:17 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 21 20:45:20 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: References: <20141021013501.GA43489@shell.msen.com> Message-ID: <20141021204517.GA34217@shell.msen.com> On Mon, Oct 20, 2014 at 07:18:14PM -0700, Eliot Miranda wrote: > Hi David, > > On Mon, Oct 20, 2014 at 6:35 PM, David T. Lewis wrote: > > > On Thu, Oct 16, 2014 at 11:51:20PM -0700, Eliot Miranda wrote: > > > Hi All, > > > > > > finally the Spur Squeak trunk image is updateable. > > > > Yay! > > > > > The issue > > > is of course that we have this tricky package situation to manage where, > > to > > > keep the two systems in sync, modifications to Collections, Compiler, > > > Kernel and System need to be committed from V3 and auto-edited to Spur. I > > > think that's too clumsy to be practicable. > > > > When I look at the Spur related changes to these four large packages, it > > seems > > to me that we might be able to reduce the scope of the problem by moving > > the > > parts that require changes into separate packages or sub-packages. The > > portions > > of these packages that need to change are not insignificant, but if they > > were > > contained within well defined package boundaries, they might become simpler > > to manage. > > > > To illustrate: The changes in the Collections package are almost entirely > > related to class Character, whose instances are immediate in the Spur > > format. > > It might make very good sense if the methods directly related to > > immediateness > > of a character were localized in a package where they can be maintained > > independently of all the other Collections classes and methods. > > > > Looking at it from another angle, the Kernel package is arguably too > > large, and > > if I want to make changes to Kernel-Chronology (as I have recently been > > doing > > with UTCDateAndTime just as an > > example), > > then I have problems if I want to coordinate that external package with > > Squeak > > trunk. If I also want to coordinate my little project with all the updates > > required for both Kernel and Kernel.spur, the situation becomes impossible. > > > > I apologize in advance because I have not really thought this through in > > detail, but it seems to me that a bit of pragmatic reorganization of our > > package structure might make the Spur transition a lot easier to manage. > > > > I note that in the past we have put energy into reorganizing our package > > structures in the interest of making the image more modular. That is > > important, > > but managing the transition to Spur is even more important. If improving > > the > > package structure could make this easier, then we should make it a > > priority. > > > > While I'm happy to see packages decomposed I've chosen the approach to > changing the four relevant packages Spur modifies for good reason. > Essentially once we move to Spur I don't want there to be artifacts present > which are simply to do with the change to Spur. So keeping Collections, > Compiler, Kernel and System whole but in Spur-specific branches allows us > to keep the system looking the same once we release it. Further, all the > support for branching and editing these packages is now working and I'm > really not keep on putting more effort into it to complicate it further. > I've got lots of other things to do. So now that Spur works and is nearly > ready for release can we let it be? > Yes, for sure. If it does not make things easier, let's not do it. > > > > Perhaps allowing the two > > > systems to fork and doing a manual merge will be acceptable, but it'll be > > > work to keep them in sync. > > > > I agree. I also think that this kind of maintenance work is not enjoyable, > > and is not likely to be kept up on an ongoing basis. So we need to think > > of ways for the path forward to be A) enjoyable or B) not too much work or > > C) all of the above :-) > > > > Well, we should discuss what the release criteria are at the next board > meeting. We may be able to release before the end of the year, which would > be great. > Ok, good. Dave From edgardec2005 at gmail.com Tue Oct 21 20:46:26 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Tue Oct 21 20:46:43 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: <0AEC8702-B382-49D6-A30D-678AD1DFC8E5@gmail.com> Message-ID: On 10/21/14, 12:46 PM, "Chris Cunnington" wrote: > If you give me the link, then I?ll update it. > > Chris http://squeakros.org/FunSqueak4.6/FunSqueak4dot6-alpha.137921.0.zip Here you found a .image + .sources + changes Feel free to copy to squeak site Edgar From lewis at mail.msen.com Tue Oct 21 21:43:54 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 21 21:43:56 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: References: <0AEC8702-B382-49D6-A30D-678AD1DFC8E5@gmail.com> Message-ID: <20141021214354.GB39444@shell.msen.com> On Tue, Oct 21, 2014 at 05:46:26PM -0300, Edgar J. De Cleene wrote: > > On 10/21/14, 12:46 PM, "Chris Cunnington" wrote: > > > If you give me the link, then I?ll update it. > > > > Chris > > http://squeakros.org/FunSqueak4.6/FunSqueak4dot6-alpha.137921.0.zip > > Here you found a .image + .sources + changes > > Feel free to copy to squeak site > Some of Edgar's FunSqueak work is on the ftp server in ftp://ftp.squeak.org/various_images/FunSqueak/ and it would be good to put a copy of FunSqueak4dot6-alpha.137921.0.zip there as well. Even better would be if we can give Edgar write access to this directory so that he can upload his FunSqueak images from time to time. I don't know how access control works on ftp.squeak.org, but is it possible? Dave From commits at source.squeak.org Tue Oct 21 22:05:42 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 21 22:05:44 2014 Subject: [squeak-dev] The Trunk: Kernel-ul.880.mcz Message-ID: Levente Uzonyi uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-ul.880.mcz ==================== Summary ==================== Name: Kernel-ul.880 Author: ul Time: 21 October 2014, 4:56:17.427 pm UUID: 4b600072-456c-413f-8b7e-e3f1ae8340f3 Ancestors: Kernel-eem.879 Compile methods with the right trailer to avoid a #becomeForward: when the actual trailer is added. =============== Diff against Kernel-eem.879 =============== Item was changed: ----- Method: Behavior>>compile:notifying: (in category 'compiling') ----- compile: code notifying: requestor "Compile the argument, code, as source code in the context of the receiver and insEtall the result in the receiver's method dictionary. The second argument, requestor, is to be notified if an error occurs. The argument code is either a string or an object that converts to a string or a PositionableStream. This method also saves the source code." | methodAndNode | methodAndNode := self compile: code "a Text" notifying: requestor + trailer: (self defaultMethodTrailerIfLogSource: true) - trailer: self defaultMethodTrailer ifFail: [^nil]. methodAndNode method putSource: code fromParseNode: methodAndNode node inFile: 2 withPreamble: [:f | f cr; nextPut: $!!; nextChunkPut: 'Behavior method'; cr]. self addSelector: methodAndNode selector withMethod: methodAndNode method notifying: requestor. ^ methodAndNode selector! Item was added: + ----- Method: Behavior>>defaultMethodTrailerIfLogSource: (in category 'compiling') ----- + defaultMethodTrailerIfLogSource: logSource + + logSource ifFalse: [ ^self defaultMethodTrailer ]. + ^CompiledMethodTrailer sourcePointerInFile: 2! Item was changed: ----- Method: ClassDescription>>compile:classified:withStamp:notifying:logSource: (in category 'compiling') ----- compile: text classified: category withStamp: changeStamp notifying: requestor logSource: logSource + + | methodAndNode selector | + methodAndNode := self + compile: text asString + notifying: requestor + trailer: (self defaultMethodTrailerIfLogSource: logSource) + ifFail: [ ^nil ]. + selector := methodAndNode selector. - | methodAndNode | - methodAndNode := self compile: text asString notifying: requestor - trailer: self defaultMethodTrailer ifFail: [^nil]. logSource ifTrue: [ self logMethodSource: text forMethodWithNode: methodAndNode inCategory: category withStamp: changeStamp notifying: requestor. ]. + self addAndClassifySelector: selector withMethod: methodAndNode - self addAndClassifySelector: methodAndNode selector withMethod: methodAndNode method inProtocol: category notifying: requestor. + self instanceSide noteCompilationOf: selector meta: self isClassSide. + ^selector! - self instanceSide noteCompilationOf: methodAndNode selector meta: self isClassSide. - ^ methodAndNode selector! Item was changed: ----- Method: ClassDescription>>compile:environment:classified:withStamp:notifying:logSource: (in category 'compiling') ----- compile: text environment: anEnvironment classified: category withStamp: changeStamp notifying: requestor logSource: logSource | methodAndNode context methodNode | context := CompilationCue source: text class: self environment: anEnvironment requestor: requestor. methodNode := self newCompiler compile: context ifFail: [^ nil]. methodAndNode := CompiledMethodWithNode generateMethodFromNode: methodNode + trailer: (self defaultMethodTrailerIfLogSource: logSource). - trailer: self defaultMethodTrailer. logSource ifTrue: [ self logMethodSource: text forMethodWithNode: methodAndNode inCategory: category withStamp: changeStamp notifying: requestor. ]. self addAndClassifySelector: methodAndNode selector withMethod: methodAndNode method inProtocol: category notifying: requestor. self instanceSide noteCompilationOf: methodAndNode selector meta: self isClassSide. ^ methodAndNode selector! Item was changed: ----- Method: CompiledMethod>>decompileWithTemps (in category 'decompiling') ----- decompileWithTemps "Return the decompiled parse tree that represents self, but with the temp names obtained either by compiling the sourcecode, or directly if the method has temps in its trailer." | class selector tempNames source | class := self methodClass ifNil: [Object]. selector := self selector ifNil: [self defaultSelector]. self holdsTempNames ifTrue: [tempNames := self tempNamesString] ifFalse: ["No source file or no source (e.g. doits) and no temp names -- decompile without temp names " ((self fileIndex > 0 and: [(SourceFiles at: self fileIndex) isNil]) or: [(source := self getSourceFromFile) isNil]) ifTrue: [^self decompile]. tempNames := (class newCompiler parse: source asString in: class notifying: nil) + generate: CompiledMethodTrailer empty; - generate: CompiledMethodTrailer defaultMethodTrailer; schematicTempNamesString]. ^(self decompilerClass new withTempNames: tempNames) decompile: selector in: class method: self methodForDecompile! Item was added: + ----- Method: CompiledMethodTrailer class>>sourcePointerInFile: (in category 'as yet unclassified') ----- + sourcePointerInFile: fileIndex + + ^self new + sourcePointer: (SourceFiles + sourcePointerFromFileIndex: fileIndex + andPosition: (SourceFiles at: fileIndex) position); + yourself + ! From commits at source.squeak.org Tue Oct 21 22:06:17 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 21 22:06:18 2014 Subject: [squeak-dev] The Trunk: Tests-ul.304.mcz Message-ID: Levente Uzonyi uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-ul.304.mcz ==================== Summary ==================== Name: Tests-ul.304 Author: ul Time: 21 October 2014, 4:59:20.64 pm UUID: 6778c29a-0c8f-4e38-9bed-26c6720b6503 Ancestors: Tests-eem.303 Be explicit and use CompiledMethod empty. =============== Diff against Tests-eem.303 =============== Item was changed: ----- Method: BlockLocalTemporariesRemovalTest>>assert:isChangedDuringParsingTo:withRemovalOfTemporariesNamed: (in category 'test helper') ----- assert: someCode isChangedDuringParsingTo: someOtherCode withRemovalOfTemporariesNamed: someTempNames | failBlock | self sourceCode: someCode. failBlock := [ self fail ]. [ self class compile: self sourceCode notifying: self + trailer: CompiledMethodTrailer empty - trailer: self class defaultMethodTrailer ifFail: failBlock ] on: UnusedVariable do: [ : aNotification | aNotification openMenuIn: [ : options : emptyCollection : someText | aNotification resume: (someTempNames anySatisfy: [ : tempName | someText beginsWith: tempName ]) ] ]. self assert: self sourceCode = someOtherCode! From commits at source.squeak.org Tue Oct 21 22:07:03 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 21 22:07:05 2014 Subject: [squeak-dev] The Trunk: Traits-ul.303.mcz Message-ID: Levente Uzonyi uploaded a new version of Traits to project The Trunk: http://source.squeak.org/trunk/Traits-ul.303.mcz ==================== Summary ==================== Name: Traits-ul.303 Author: ul Time: 21 October 2014, 4:58:50.432 pm UUID: 2e3203a4-4362-4cf5-a69c-42e55610c23b Ancestors: Traits-topa.302 Create the compiledMethod with the right trailer. Depends on Kernel-ul.880. =============== Diff against Traits-topa.302 =============== Item was changed: ----- Method: ClassDescription>>traitAddSelector:withMethod: (in category '*Traits-NanoKernel') ----- traitAddSelector: selector withMethod: traitMethod "Add a method inherited from a trait. Recompiles to avoid sharing and implement aliasing." | oldMethod source methodNode newMethod originalSelector | oldMethod := self compiledMethodAt: selector ifAbsent:[nil]. oldMethod ifNotNil:[ "The following is an important optimization as it prevents exponential growth in recompilation. If T1 is used by T2 and T2 by T3 then (without this optimization) any change in T1 would cause all methods in T2 to be recompiled and each recompilation of a method in T2 would cause T3 to be fully recompiled. The test eliminates all such situations." (oldMethod sameTraitCodeAs: traitMethod) ifTrue:[^oldMethod]. ]. originalSelector := traitMethod selector. source := traitMethod methodClass sourceCodeAt: originalSelector. originalSelector == selector ifFalse:[ "Replace source selectors for aliases" source := self replaceSelector: originalSelector withAlias: selector in: source. ]. methodNode := self newCompiler compile: source in: self notifying: nil ifFail:[^nil]. + newMethod := methodNode generate: (self defaultMethodTrailerIfLogSource: true). - newMethod := methodNode generate: self defaultMethodTrailer. newMethod putSource: source fromParseNode: methodNode inFile: 2 withPreamble: [:f | f cr; nextPut: $!!; nextChunkPut: 'Trait method'; cr]. newMethod originalTraitMethod: traitMethod. ^super addSelectorSilently: selector withMethod: newMethod.! From commits at source.squeak.org Tue Oct 21 22:08:05 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 21 22:08:07 2014 Subject: [squeak-dev] The Trunk: Monticello-ul.602.mcz Message-ID: Levente Uzonyi uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-ul.602.mcz ==================== Summary ==================== Name: Monticello-ul.602 Author: ul Time: 21 October 2014, 4:58:16.892 pm UUID: e46b988a-988b-4d6d-9d98-e241bdd6239f Ancestors: Monticello-bf.601 Create the method with the right trailer in MethodAnnotation >> #createCompiledMethod. Depends on Kernel-ul.880. =============== Diff against Monticello-bf.601 =============== Item was changed: ----- Method: MethodAddition>>createCompiledMethod (in category 'as yet unclassified') ----- createCompiledMethod | notification | + [methodAndNode := myClass + compile: text asString + notifying: requestor + trailer: (myClass defaultMethodTrailerIfLogSource: logSource) + ifFail: [^nil]] - [methodAndNode := myClass compile: text asString notifying: requestor - trailer: myClass defaultMethodTrailer ifFail: [^nil]] on: SyntaxErrorNotification do: [:exc | notification := exc. exc pass]. notification ifNotNil: [notification newSource ifNotNil: [:newSource | text := newSource]]. selector := methodAndNode selector. compiledMethod := methodAndNode method. self writeSourceToLog. priorMethodOrNil := myClass compiledMethodAt: selector ifAbsent: [nil]. ! From lewis at mail.msen.com Tue Oct 21 22:11:18 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 21 22:11:21 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: References: <7EFDF49E-397A-46E5-A4EB-087534734CCC@gmail.com> <2D7A313F-707D-4E89-B42D-F79B37E907C2@rowledge.org> Message-ID: <20141021221118.GA45073@shell.msen.com> On Fri, Oct 17, 2014 at 02:25:57PM -0500, Chris Muller wrote: > On Wed, Oct 15, 2014 at 9:13 PM, tim Rowledge wrote: > > > > On 15-10-2014, at 7:07 PM, Chris Cunnington wrote: > > > >> The FunSqueak link is in the Beginners??? section of the Downloads page. The Donate button is on the homepage > > > > Yay! Thanks Chris. > > > > Now, everybody else:- please consider donating a few dollars/pounds/yen/euros/bolivars/escudos/whatevers. It goes towards supporting the servers that we rely upon to bring you Squeak. No money, no servers. > > Contributions are always welcome, but we are not on the verge of > losing any servers. We have an annoying expense we can get rid of by > moving remaining services off of box2 (onto box3 and box4). I decided that I should test our new Donate button on squeak.org. It turns out that the easiest way to do this is to just make a donation. So I gave it a try, making the payment through PayPal. It appears that the donation went through to SFC, with our Squeak project identified as the source of the contribution: Hello David Lewis, This email confirms that you have donated $20.00 USD to Software Freedom Conservancy using PayPal. This credit card transaction will appear on your bill as "PAYPAL *SF CNSRVNCY". ----------------------------------- Donation Details ----------------------------------- Confirmation number: 36N217491N221464B Donation amount: $20.00 USD Total: $20.00 USD Purpose: Squeak Project Donation via Software Freedom Conservancy, Inc. Reference: Squeak Contributor: David Lewis ---------------------------------------------------------------- I think that the "Squeak Project Donation" is a nice touch, since it lets SFC know that we are alive and interested in helping them to support us. Of course, more testing is always a good thing, so please do test the donate button and report back if any problems are found. Better yet, try to convince your neighbors, relatives, and former spouses to participate in load testing by making large numbers of simultaneous donations at some agreed time. Dave From tim at rowledge.org Tue Oct 21 22:20:28 2014 From: tim at rowledge.org (tim Rowledge) Date: Tue Oct 21 22:20:35 2014 Subject: [squeak-dev] FunSqueak link and Donate button added to homepage In-Reply-To: <20141021221118.GA45073@shell.msen.com> References: <7EFDF49E-397A-46E5-A4EB-087534734CCC@gmail.com> <2D7A313F-707D-4E89-B42D-F79B37E907C2@rowledge.org> <20141021221118.GA45073@shell.msen.com> Message-ID: <52A78016-FC08-4BB8-8599-6878190E4887@rowledge.org> On 21-10-2014, at 3:11 PM, David T. Lewis wrote: > Better yet, try > to convince your neighbors, relatives, and former spouses to participate And spouses of former spouses. Think of it this way; how about donating a dollar for each year you?ve used Squeak. Or even for each month? Or let?s get really radical and do a dollar for each day if you?ve released a money making product built on Squeak? tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- He fell out of the ugly tree and hit every branch on the way down. From Yoshiki.Ohshima at acm.org Tue Oct 21 23:29:53 2014 From: Yoshiki.Ohshima at acm.org (Yoshiki Ohshima) Date: Tue Oct 21 23:29:57 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: Message-ID: I'm not fully following the discussion here, but I do remember seeing the following email from Dan in 1999: http://lists.squeakfoundation.org/pipermail/squeak-dev/1999-March.txt and search for: "From DanI at wdi.disney.com Fri Mar 26 07:17:09 1999" It does not require two bits to mark. (Hopefully this email has some relevance to the discussion at hand... On Sun, Oct 19, 2014 at 6:01 PM, Eliot Miranda wrote: > Hi All, > > I want to check my understanding of reference semantics for image > segments as I'm close to completing the Spur implementation. Specifically > the question is whether objects reachable only through weak pointers should > be included in an image segment or not. > > Remember that an image segment is created from the transitive closure of an > Array of root objects, the segment roots. i.e. we can think of an image > segment as a set of objects created by tracing the object graph from the > segment roots. > > The segment always includes the segment roots. Except for the roots, > objects are excluded from the segment that are also reachable form the roots > of the system (the system roots, effectively the root environment, > Smalltalk, and the stack of the current process). > > Consider a weak array in the transitive closure that is not reachable from > the system roots, and hence should be included in the segment. Objects > referenced from that weak array may be in one of three categories > > - reachable from the system roots (and hence not to be included in the > segment) > - not reachable form the system roots, but reachable from the segment roots > via strong pointers (and hence to be included in the segment) > - not reachable form the system roots, not reachable from the segment roots > via strong pointers > > Should this last category be included or excluded from the segment? I think > that it makes no difference, and excluding them is only an optimization. > The argument is as follows. Imagine that immediately after loading the > image segment there is a garbage collection. That garbage collection will > collect all the objects in the last category as they are only reachable from > the weak arrays in the segment. Hence we are free to follow weak references > as if they are strong when we create the image segment, leaving it to > subsequent events to reclaim those objects. > > An analogous argument accounts for objects reachable from ephemerons. Is my > reasoning sound? > -- > best, > Eliot > > > -- -- Yoshiki From commits at source.squeak.org Tue Oct 21 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 21 23:55:03 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141021235502.27173.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007336.html Name: Collections-cmm.585 Ancestors: Collections-ul.584 Speed up visiting with #addNewElement:. It provides the common pattern of checking for inclusion, followed by add:, in just one scan, instead of two. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007337.html Name: Nebraska-ul.38 Ancestors: Nebraska-nice.37 There's no guarantee for port 9999 being available. Use whatever port socket1 got. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007338.html Name: Kernel-ul.880 Ancestors: Kernel-eem.879 Compile methods with the right trailer to avoid a #becomeForward: when the actual trailer is added. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007339.html Name: Tests-ul.304 Ancestors: Tests-eem.303 Be explicit and use CompiledMethod empty. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007340.html Name: Traits-ul.303 Ancestors: Traits-topa.302 Create the compiledMethod with the right trailer. Depends on Kernel-ul.880. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007341.html Name: Monticello-ul.602 Ancestors: Monticello-bf.601 Create the method with the right trailer in MethodAnnotation >> #createCompiledMethod. Depends on Kernel-ul.880. ============================================= From eliot.miranda at gmail.com Wed Oct 22 00:12:46 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 22 00:12:50 2014 Subject: [squeak-dev] compiler whitewash Message-ID: hi compiler hackers.... in Squeak trunk evaluate the following, proceeding through the warning that t appears to be uninitialized when send ifNil: | t | t ifNil: [#ignore]. 3 + 4 7 is printed between the "t" and the "ifNil:". It would be nice if it were still printed after the 3 + 4. wanna fix it? -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141021/3225c810/attachment.htm From lewis at mail.msen.com Wed Oct 22 00:17:08 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 22 00:17:12 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: Message-ID: <20141022001708.GA66477@shell.msen.com> On Tue, Oct 21, 2014 at 04:29:53PM -0700, Yoshiki Ohshima wrote: > I'm not fully following the discussion here, but I do remember seeing > the following email from Dan in 1999: > > http://lists.squeakfoundation.org/pipermail/squeak-dev/1999-March.txt > > and search for: "From DanI at wdi.disney.com Fri Mar 26 07:17:09 1999" > > It does not require two bits to mark. > > (Hopefully this email has some relevance to the discussion at hand... I don't know if it is directly relevant to the specific discussion, but it is definitely worth rereading this post from Dan. I remember being amazed at its simplicity when I first read it in fifteen years ago, and what stands out to in retrospect is that we seem to have largely overlooked what he apparently considered to be its main potential application: "Steps to Modularity - Incremental Snapshots" Thanks for the pointer :-) Dave Here is a copy of the squeak-dev post from 1999: >From DanI at wdi.disney.com Fri Mar 26 07:17:09 1999 From: DanI at wdi.disney.com (Dan Ingalls) Date: Sat Jan 28 04:56:45 2012 Subject: Steps to Modularity - Incremental Snapshots Message-ID: Folks - A week or so ago, I sent out a message describing a technique for extracting segments from the Squeak image. What I want to know is, Does anyone know of such a technique having being used previously? I figure it must be known, but I have certainly never heard of it. Please reply directly to me. To recap, here's how it works: 1. Mark the root (or roots) of the subtree desired. 2. Do a GC mark pass. SInce this stops at any marked objects, the subtree will be unmarked, "in the shadow" of its roots. 3. Copy the roots and the unmarked subtree into a byteArray (the image segment) Relocate internal pointers as you go Copy external pointers into a table of outpointers. Reinstalling a segment is incredibly simple -- all you do is remap any pointers in one pass and throw away the byteArray header! Thanks - Dan PS... Ted and I have just completed an implementation and it is great. (It will be out in updates and release 2.4 within a week). It can trace and copy a 520kb tree of over 15000 objects in about 390ms. Used for deepCopy, it is about 20 times faster than what we do currently. Used to swap segments in and out, it finally offers a realistic vehicle for breaking down Squeak's monolithic images. It's even faster than you would guess from the above. There is a fixed overhead for the full GC mark and unmark. This is 350ms on my machine (could surely be improved). It can then copy out the 520kb segment or reinstall it in about 40ms either way. From casey.obrien.r at gmail.com Wed Oct 22 04:42:59 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Wed Oct 22 04:43:05 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Message-ID: Hi Mariano, I've stripped some context here (it can be found by reading the original thread on squeak-dev) but I did want to respond to one or two things you said, so... > On Oct 20, 2014, at 6:55 PM, Mariano Martinez Peck wrote: > > 1) I found only few users of ImageSegment If by users, you mean people (as opposed to something like senders or implementors,) did you count the people using EToys? I'm afraid my memory is telling me that it's used in saving and sharing projects (I'm not sure though.) > 2) The few users I found, were NOT using the real purpose of ImageSegment, that is, object swapping. It was used instead as an object serializer. For that, they use #writeForExportOn: which ended up using SmartRefStream for the rest of the objects. Seems legit. Fair enough. > 3) I noticed I could achieve the same performance or even better with an OO serializer built at the language side, with all the benefits this means. Of course, having Cog helped here.... I suppose I'll be reading your paper then, won't I? :) Cheers, Casey From bert at freudenbergs.de Wed Oct 22 05:05:15 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Wed Oct 22 05:05:24 2014 Subject: [Vm-dev] [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Message-ID: On 20.10.2014, at 18:55, Mariano Martinez Peck wrote: > The few users I found, were NOT using the real purpose of ImageSegment, that is, object swapping. It was used instead as an object serializer. For that, they use #writeForExportOn: which ended up using SmartRefStream for the rest of the objects. Well, if you look closer, you will see that projects use image segments in two completely different ways. One is, as you say, for serialization, which is not the best use of image segments, agreed, especially with all the other logic wrapped around it. But if you enable projectsSentToDisk then entering a project will swap the previous project to disk as an image segment, allowing you to have images with very large projects without having to hold all in main memory at the same time. This uses a completely different code path and file format than regular project export. The same technique could be used to swap out arbitrary chunks of an image. - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141021/d2afed45/smime.bin From kosi.balazs at ezomer.hu Wed Oct 22 07:43:26 2014 From: kosi.balazs at ezomer.hu (=?UTF-8?B?QmFsw6F6cyBLw7NzaQ==?=) Date: Wed Oct 22 07:43:32 2014 Subject: [squeak-dev] compiler whitewash In-Reply-To: References: Message-ID: hi, I have a quick fix, tested only with your example. It just stores the original selection and restores it after the query. Change Parser >> #queryUndefined to: Parser >> queryUndefined | varStart varName originalStart originalStop | originalStart := cue requestor startIndex. originalStop := cue requestor stopIndex. varName := parseNode key. varStart := self endOfLastToken + requestorOffset - varName size + 1. cue requestor selectFrom: varStart to: varStart + varName size - 1; select. (UndefinedVariable name: varName) ifFalse: [^ self fail]. cue requestor selectFrom: originalStart to: originalStop; select. Cheers, Balazs On Wed, Oct 22, 2014 at 2:12 AM, Eliot Miranda wrote: > hi compiler hackers.... > > in Squeak trunk evaluate the following, proceeding through the warning > that t appears to be uninitialized when send ifNil: > > | t | > t ifNil: [#ignore]. > 3 + 4 > > > 7 is printed between the "t" and the "ifNil:". It would be nice if it > were still printed after the 3 + 4. wanna fix it? > -- > best, > Eliot > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141022/242915c2/attachment.htm From list at afceurope.com Wed Oct 22 09:55:59 2014 From: list at afceurope.com (Annick Fron) Date: Wed Oct 22 09:56:06 2014 Subject: [squeak-dev] Using libraries in FFI Message-ID: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> Hi, I am using a module in FFI which depends on a large library let?s say 10 dynamic .so files in a directory. How is it possible to use this library without making all symbolic links ? Annick From eliot.miranda at gmail.com Wed Oct 22 10:46:04 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 22 10:46:10 2014 Subject: [squeak-dev] Using libraries in FFI In-Reply-To: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> References: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> Message-ID: <27481657-8A8D-4350-A645-FF722E600386@gmail.com> Hi Annick, LD_LIBRARY_PATH should be set to point to the relevant directories, but this can be tricky as there is a lot if variation across Linux distros as to where libraries are kept. The squeak script that comes with the Cog VMs extends LD_LIBRARY_PATH, so if you know where your libraries are you can use the script to find the other libraries the VM needs (c library and plugins). Eliot (phone) On Oct 22, 2014, at 2:55 AM, Annick Fron wrote: > Hi, > > I am using a module in FFI which depends on a large library let?s say 10 dynamic .so files in a directory. > How is it possible to use this library without making all symbolic links ? > > Annick From list at afceurope.com Wed Oct 22 12:45:34 2014 From: list at afceurope.com (Annick Fron) Date: Wed Oct 22 12:46:17 2014 Subject: [squeak-dev] Using libraries in FFI In-Reply-To: <27481657-8A8D-4350-A645-FF722E600386@gmail.com> References: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> <27481657-8A8D-4350-A645-FF722E600386@gmail.com> Message-ID: <476D3881-5167-43E9-AC8E-04AC07E91312@afceurope.com> Hi Eliot, My problem is not with the VM, my problem is with my own library that I connect to through FFI. I know where the libraries are ! I have tried to add them in /etc/ld.so.conf.d , that does not work. I have tried export LD_LIBRARY_PATH, but somehow it erases some libraries needed by pharo. I have done sudo ldconfig ... In fact I have one library that depends from another one. In FFI I call one method which calls another method in the other library. I have tried to create symbolics links in the directory ? I have checked that nm gives the right symbol with the right type .. So I have no idea what to try now ! Annick Le 22 oct. 2014 ? 12:46, Eliot Miranda a ?crit : > Hi Annick, > > LD_LIBRARY_PATH should be set to point to the relevant directories, but this can be tricky as there is a lot if variation across Linux distros as to where libraries are kept. The squeak script that comes with the Cog VMs extends LD_LIBRARY_PATH, so if you know where your libraries are you can use the script to find the other libraries the VM needs (c library and plugins). > > Eliot (phone) > > On Oct 22, 2014, at 2:55 AM, Annick Fron wrote: > >> Hi, >> >> I am using a module in FFI which depends on a large library let?s say 10 dynamic .so files in a directory. >> How is it possible to use this library without making all symbolic links ? >> >> Annick > From list at afceurope.com Wed Oct 22 12:46:19 2014 From: list at afceurope.com (Annick Fron) Date: Wed Oct 22 12:48:03 2014 Subject: [squeak-dev] VM crash Message-ID: <9504224B-5B55-4743-9F20-1CEBCF696A3F@afceurope.com> I have an error : ? don?t know how to derive register state from a ucontext_t on this platform ? Where could that come from ? Annick From casey.obrien.r at gmail.com Wed Oct 22 13:43:33 2014 From: casey.obrien.r at gmail.com (Casey Ransberger) Date: Wed Oct 22 13:43:38 2014 Subject: [squeak-dev] [OT??] PARC code released to future history Message-ID: <7EF62487-BEFB-4B46-81D3-5141CFB234C2@gmail.com> Before we all go crazy, it's here under a non-commercial license (read: not compatible with MIT.) But for the time traveling computational anthropologists among us, this looks a lot like the mother load. So much history. http://www.computerhistory.org/_static/atchm/xerox-alto-source-code/ From marianopeck at gmail.com Wed Oct 22 15:30:15 2014 From: marianopeck at gmail.com (Mariano Martinez Peck) Date: Wed Oct 22 15:30:20 2014 Subject: [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Message-ID: On Wed, Oct 22, 2014 at 1:42 AM, Casey Ransberger wrote: > Hi Mariano, > > I've stripped some context here (it can be found by reading the original > thread on squeak-dev) but I did want to respond to one or two things you > said, so... > > > On Oct 20, 2014, at 6:55 PM, Mariano Martinez Peck < > marianopeck@gmail.com> wrote: > > > > 1) I found only few users of ImageSegment > > If by users, you mean people (as opposed to something like senders or > implementors,) did you count the people using EToys? I'm afraid my memory > is telling me that it's used in saving and sharing projects (I'm not sure > though.) > > By users I mean code...senders... and yeah, Etoys Projects was one of them. > > 2) The few users I found, were NOT using the real purpose of > ImageSegment, that is, object swapping. It was used instead as an object > serializer. For that, they use #writeForExportOn: which ended up using > SmartRefStream for the rest of the objects. > > Seems legit. Fair enough. > > > 3) I noticed I could achieve the same performance or even better with an > OO serializer built at the language side, with all the benefits this means. > Of course, having Cog helped here.... > > I suppose I'll be reading your paper then, won't I? :) > > Cheers, > > Casey > -- Mariano http://marianopeck.wordpress.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141022/617b3dcc/attachment.htm From marianopeck at gmail.com Wed Oct 22 15:32:06 2014 From: marianopeck at gmail.com (Mariano Martinez Peck) Date: Wed Oct 22 15:32:09 2014 Subject: [Vm-dev] [squeak-dev] Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Message-ID: On Wed, Oct 22, 2014 at 2:05 AM, Bert Freudenberg wrote: > > On 20.10.2014, at 18:55, Mariano Martinez Peck > wrote: > > > The few users I found, were NOT using the real purpose of ImageSegment, > that is, object swapping. It was used instead as an object serializer. For > that, they use #writeForExportOn: which ended up using SmartRefStream for > the rest of the objects. > > Well, if you look closer, you will see that projects use image segments in > two completely different ways. One is, as you say, for serialization, which > is not the best use of image segments, agreed, especially with all the > other logic wrapped around it. > > But if you enable projectsSentToDisk then entering a project will swap the > previous project to disk as an image segment, allowing you to have images > with very large projects without having to hold all in main memory at the > same time. > > This uses a completely different code path and file format than regular > project export. The same technique could be used to swap out arbitrary > chunks of an image. > > Totally agree. So it seems we agree that the key and good part of ImageSegment is that one, swapping out, but not as a general object graph serializer. -- Mariano http://marianopeck.wordpress.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141022/f8d56737/attachment.htm From craig at netjam.org Wed Oct 22 15:47:01 2014 From: craig at netjam.org (Craig Latta) Date: Wed Oct 22 15:47:12 2014 Subject: [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Message-ID: > So it seems we agree that the key and good part of ImageSegment is > that one, swapping out, but not as a general object graph serializer. Even for swapping out objects, I think putting them in their own normal object memory is a better idea, since object memories can be minimal and small. This lets you perform more sophisticated reasoning about what to do when class formats change between swap-out and swap-in (as well as other meta-operations). -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From bert at freudenbergs.de Wed Oct 22 16:05:39 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Wed Oct 22 16:05:44 2014 Subject: [squeak-dev] [OT??] PARC code released to future history In-Reply-To: <7EF62487-BEFB-4B46-81D3-5141CFB234C2@gmail.com> References: <7EF62487-BEFB-4B46-81D3-5141CFB234C2@gmail.com> Message-ID: <6F8607DB-F4F8-4B36-B968-90A3FF54BBAF@freudenbergs.de> On 22.10.2014, at 06:43, Casey Ransberger wrote: > Before we all go crazy, it's here under a non-commercial license (read: not compatible with MIT.) > > But for the time traveling computational anthropologists among us, this looks a lot like the mother load. > > So much history. > > http://www.computerhistory.org/_static/atchm/xerox-alto-source-code/ Nice! Here's the Smalltalk stuff: http://xeroxalto.computerhistory.org/xerox_alto_file_system_archive.html#Smalltalk - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141022/c5896f7a/smime.bin From bert at freudenbergs.de Wed Oct 22 16:16:30 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Wed Oct 22 16:16:35 2014 Subject: [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> Message-ID: <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> On 22.10.2014, at 08:47, Craig Latta wrote: > >> So it seems we agree that the key and good part of ImageSegment is >> that one, swapping out, but not as a general object graph serializer. > > Even for swapping out objects, I think putting them in their own > normal object memory is a better idea, since object memories can be > minimal and small. This lets you perform more sophisticated reasoning > about what to do when class formats change between swap-out and swap-in > (as well as other meta-operations). That's a different thing. Swapping is strictly about cutting up a single image into multiple segments. Proper mutation code would have to walk the whole object memory, meaning it needs to swap in all segments in turn. Which fortunately is extremely efficient, but likely still hairy enough that we're not actually using it given today's abundance of main memory. It might, however, still make a lot of sense e.g. as a deployment mechanism on mobile platforms, which still are severely memory-limited. If used strictly for deployment you don't have to worry about mutation. - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141022/803b1c3c/smime.bin From stephane.ducasse at inria.fr Wed Oct 22 18:56:52 2014 From: stephane.ducasse at inria.fr (=?windows-1252?Q?St=E9phane_Ducasse?=) Date: Wed Oct 22 18:56:58 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> Message-ID: <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> What I can tell you is that instability raised by just having one single pointer not in the root objects pointing to an element in the segment and the implication of this pointer on reloaded segments, (yes I do not want to have two objects in memory after loading) makes sure that we will not use IS primitive in Pharo in any future. For us this is a non feature. IS was a nice trick but since having a pointer to an object is so cheap and the basis of our computational model so this is lead fo unpredictable side effects. We saw that when mariano worked during the first year of his PhD (which is a kind of LOOM revisit). Stef From eliot.miranda at gmail.com Wed Oct 22 19:53:15 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 22 19:53:20 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> Message-ID: Hi Stephane, Hi All, let me talk a little about the ParcPlace experience, which led to David Leibs' parcels, whose architecture Fuel uses. In the late 80's 90's Peter Deutsch write BOSS (Binary Object Storage System), a traditional interpretive pickling system defined by a little bytecoded language. Think of a bytecode as something like "What follows is an object definition, which is its id followed by size info followed by the definitions or ids of its sub-parts, including its class", or "What follows is the id of an already defined object". So the loading interpreter looks at the next byte in the stream and that tells it what to do. So the storage is a recursive definition of a graph, much like a recursive grammar for a programming language. This approach is slow (its a bytecode interpreter) and fragile (structures in the process of being built aren't valid yet, imagine trying to take the hash of a Set that is only half-way through being materialized). But this architecture was very common at the time (I wrote something very similar). The advantage BOSS had was a clumsy hack for versioning. One could specify blocks that were supplied with the version and state of older objects, and these blocks could effect shape change etc to bring loaded instances up-to-date. David Leibs has an epiphany as, in the early 90's, ParcPlae was trying to decompose the VW image (chainsaw was the code name of the VW 2.5 release). If one groups instances by class, one can instantiate in bulk, creating all the instances of a particular class in one go, followed by all the instances of a different class, etc. Then the arc information (the pointers to objects to be stored in the loaded objects inst vars) can follow the instance information. So now the file looks like header, names of classes that are referenced (not defined), definitions of classes, definitions of instances (essentially class id, count pairs), arc information. And materializing means finding the classes in the image, creating the classes in the file, creating the instances, stitching the graph together, and then performing any post-load actions (rehashing instances, etc). Within months we merged with Digitalk (to form DarcPlace-Dodgytalk) and were introduced to TeamV's loading model which was very much like ImageSegments, being based on the VM's object format. Because an ImageSegment also has imports (references to classes and globals taken from the host system, not defined in the file) performance doesn't just depend on loading the segment into memorty. It also depends on how long it takes to search the system to find imports, etc. In practice we found that a) Parcels were 4 times faster than BOSS, and b) they were no slower than Digitalk's image segments. But being independent of the VM's heap format Parcels had BOSS's flexibility and could support shape change on load, something ImageSegments *cannot do*. I went on to extend parcels with support for shape change, plus support for partial loading of code, but I won't describe that here. Too detailed, even thought its very important. Mariano spent time talking with me and Fuel's basic architecture is that of parcels, but reimplemented to be nicer, more flexible etc. But essentially Parcels and Fuel are at their core David Leibs' invention. He came up with the ideas of a) grouping objects by class and b) separating the arcs from the nodes. Now, where ImageSegments are faster than Parcels is *not* loading. Our experience with VW vs TeamV showed us that. But they are faster in collecting the graph of objects to be included. ImageSegments are dead simple. So IMO the right architecture is to use Parcels' segregation, and Parcels' "abstract" format (independent of the heap object format) with ImageSegment's computation of the object graph. Igor Stasenko has suggested providing the tracing part of ImageSegments (Dan Ingalls' cool invention of mark the segment root objects, then mark the heap, leaving the objects to be stored unmarked in the shadow of the marked segment roots) as a separate primitive. Then this can be quickly partitioned by class and then written by Smalltalk code. The loader can then materialize objects using Smalltalk code, can deal with shape change, and not be significantly slower than image segments. Crucially this means that one has a portable, long-lived object storage format; freeing the VM to evolve its object format without breaking image segments with every change to the object format. I'd be happy to help people working on Fuel by providing that primitive for anyone who wants to try and reimplement the ImageSegment functonality (project saving, class faulting, etc) above Fuel. On Wed, Oct 22, 2014 at 11:56 AM, St?phane Ducasse < stephane.ducasse@inria.fr> wrote: > What I can tell you is that instability raised by just having one single > pointer not in the root objects > pointing to an element in the segment and the implication of this pointer > on reloaded segments, (yes I do not want to have two objects in memory > after loading) makes sure that we will not use IS primitive in Pharo in any > future. For us this is a non feature. > > IS was a nice trick but since having a pointer to an object is so cheap > and the basis of our computational model > so this is lead fo unpredictable side effects. We saw that when mariano > worked during the first year of his PhD (which is a kind of LOOM revisit). > > Stef > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141022/8c718ac2/attachment.htm From commits at source.squeak.org Wed Oct 22 19:58:22 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 22 19:58:23 2014 Subject: [squeak-dev] The Trunk: Collections.spur-cmm.585.mcz Message-ID: Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections.spur-cmm.585.mcz ==================== Summary ==================== Name: Collections.spur-cmm.585 Author: eem Time: 22 October 2014, 12:57:26.965 pm UUID: 37234cbc-0f71-434d-ac2a-69574eb38178 Ancestors: Collections-cmm.585, Collections.spur-ul.584 Collections-cmm.585 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Speed up visiting with #addNewElement:. It provides the common pattern of checking for inclusion, followed by add:, in just one scan, instead of two. =============== Diff against Collections-cmm.585 =============== Item was changed: ==== ERROR === Error: Unrecognized class type 22 October 2014 7:58:20.897 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(Character) Arguments and temporary variables: Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(Character) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Wed Oct 22 19:59:06 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 22 19:59:11 2014 Subject: [squeak-dev] The Trunk: Kernel.spur-ul.880.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel.spur-ul.880.mcz ==================== Summary ==================== Name: Kernel.spur-ul.880 Author: eem Time: 22 October 2014, 12:57:21.379 pm UUID: 3f2da5dd-ac0f-45eb-9aa1-293a0b28e134 Ancestors: Kernel-ul.880, Kernel.spur-eem.879 Kernel-ul.880 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Compile methods with the right trailer to avoid a #becomeForward: when the actual trailer is added. =============== Diff against Kernel-ul.880 =============== Item was changed: ----- Method: Behavior>>allInstances (in category 'accessing instances and variables') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + (inst == insts or: [inst == insts originalContents]) ifFalse: [insts nextPut: inst]. + inst := next]. + ^insts contents! - allInstances - "Answer a collection of all current instances of the receiver." - - | all | - all := OrderedCollection new. - self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. - ^ all asArray - ! Item was changed: ----- Method: Behavior>>allInstancesDo: (in category 'enumerating') ----- + allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst." - allInstancesDo: aBlock - "Evaluate the argument, aBlock, for each of the current instances of the - receiver. - - Because aBlock might change the class of inst (for example, using become:), - it is essential to compute next before aBlock value: inst." - | inst next | inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == nil] - whileFalse: - [ - next := inst nextInstance. - aBlock value: inst. - inst := next]! Item was added: + ----- Method: Behavior>>allInstancesOrNil (in category 'enumerating') ----- + allInstancesOrNil + "Answer all instances of the receiver, or nil if the primitive + fails, which it may be due to being out of memory." + + ^nil! Item was changed: ----- Method: Behavior>>basicNew (in category 'instance creation') ----- basicNew "Primitive. Answer an instance of the receiver (which is a class) with no + indexable variables. Fail if the class is indexable. Essential. See Object + documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run + before the method is activated. Check that space was low and retry + via handleFailingBasicNew if so." - indexable variables. Fail if the class is indexable. Essential. See Object - documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew]. + self isVariable ifTrue: [^self basicNew: 0]. + self primitiveFailed! - - self isVariable ifTrue: [ ^ self basicNew: 0 ]. - "space must be low" - OutOfMemory signal. - ^ self basicNew "retry if user proceeds" - ! Item was changed: ----- Method: Behavior>>basicNew: (in category 'instance creation') ----- + basicNew: sizeRequested + "Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run before the + method is activated. Check args and retry via handleFailingBasicNew: if they're OK." - basicNew: sizeRequested - "Primitive. Answer an instance of this class with the number - of indexable variables specified by the argument, sizeRequested. - Fail if this class is not indexable or if the argument is not a - positive Integer, or if there is not enough memory available. - Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew: sizeRequested]. - self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. - (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: - ["arg okay; space must be low." - OutOfMemory signal. - ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstance (in category 'accessing instances and variables') ----- + byteSizeOfInstance + "Answer the total memory size of an instance of the receiver." + + + self isVariable ifTrue: + [^self byteSizeOfInstanceOfSize: 0]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstanceOfSize: (in category 'accessing instances and variables') ----- + byteSizeOfInstanceOfSize: basicSize + "Answer the total memory size of an instance of the receiver + with the given number of indexable instance variables." + + + self isVariable + ifTrue: "If the primitive overflowed answer a close approximation" + [(basicSize isInteger + and: [basicSize >= 16r1000000]) ifTrue: + [^2 * (self byteSizeOfInstanceOfSize: basicSize + 1 // 2) + - (self byteSizeOfInstanceOfSize: 0)]] + ifFalse: + [basicSize = 0 ifTrue: + [^self byteSizeOfInstance]]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>elementSize (in category 'accessing instances and variables') ----- + elementSize + "Answer the size in bytes of an element in the receiver. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + instSpec < 9 ifTrue: [^Smalltalk wordSize]. + instSpec >= 16 ifTrue: [^1]. + instSpec >= 12 ifTrue: [^2]. + instSpec >= 10 ifTrue: [^4]. + ^8! Item was added: + ----- Method: Behavior>>handleFailingBasicNew (in category 'private') ----- + handleFailingBasicNew + "handleFailingBasicNew gets sent after basicNew has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew. If + handleFailingBasicNew fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + Smalltalk garbageCollect < 1048576 ifTrue: + [Smalltalk growMemoryByAtLeast: 1048576]. + ^self handleFailingFailingBasicNew "retry after global garbage collect"! Item was added: + ----- Method: Behavior>>handleFailingBasicNew: (in category 'private') ----- + handleFailingBasicNew: sizeRequested + "handleFailingBasicNew: gets sent after basicNew: has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew:. If + handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := self byteSizeOfInstanceOfSize: sizeRequested. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingBasicNew: sizeRequested! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew (in category 'private') ----- + handleFailingFailingBasicNew + "This basicNew gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low" + OutOfMemory signal. + ^self basicNew "retry if user proceeds"! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew: (in category 'private') ----- + handleFailingFailingBasicNew: sizeRequested + "This basicNew: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + ^self basicNew: sizeRequested "retry if user proceeds"! Item was added: + ----- Method: Behavior>>identityHash (in category 'comparing') ----- + identityHash + "Answer a SmallInteger whose value is related to the receiver's identity. + Behavior implements identityHash to allow the VM to use an object representation which + does not include a direct reference to an object's class in an object. If the VM is using + this implementation then classes are held in a class table and instances contain the index + of their class in the table. A class's class table index is its identityHash so that an instance + can be created without searching the table for a class's index. The VM uses this primitive + to enter the class into the class table, assigning its identityHash with an as yet unused + class table index. If this primitive fails it means that the class table is full. In Spur as of + 2014 there are 22 bits of classTable index and 22 bits of identityHash per object. + + Primitive. Essential. Do not override. See Object documentation whatIsAPrimitive." + + + self primitiveFailed! Item was changed: ----- Method: Behavior>>indexIfCompact (in category 'private') ----- indexIfCompact + "Backward compatibility with the Squeak V3 object format. + Spur does not have a distinction between compact and non-compact classes." + ^0! - "If these 5 bits are non-zero, then instances of this class - will be compact. It is crucial that there be an entry in - Smalltalk compactClassesArray for any class so optimized. - See the msgs becomeCompact and becomeUncompact." - ^ (format bitShift: -11) bitAnd: 16r1F - " - Smalltalk compactClassesArray doWithIndex: - [:c :i | c == nil ifFalse: - [c indexIfCompact = i ifFalse: [self halt]]] - "! Item was changed: ----- Method: Behavior>>instSize (in category 'testing') ----- instSize "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^format bitAnd: 16rFFFF! - (as opposed to indexed variables) of the receiver." - - self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - When we revise the image format, it should become... - ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 - Note also that every other method in this category will require - 2 bits more of right shift after the change. - " - ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! Item was changed: ----- Method: Behavior>>instSpec (in category 'testing') ----- instSpec + "Answer the instance specification part of the format that defines what kind of object + an instance of the receiver is. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^(format bitShift: -16) bitAnd: 16r1F! - ^ (format bitShift: -7) bitAnd: 16rF! Item was changed: ----- Method: Behavior>>isBits (in category 'testing') ----- isBits + "Answer whether the receiver contains just bits (not pointers). + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 7! - "Answer whether the receiver contains just bits (not pointers)." - - ^ self instSpec >= 6! Item was changed: ----- Method: Behavior>>isBytes (in category 'testing') ----- isBytes + "Answer whether the receiver has 8-bit instance variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 16! - "Answer whether the receiver has 8-bit instance variables." - - ^ self instSpec >= 8! Item was added: + ----- Method: Behavior>>isEphemeronClass (in category 'testing') ----- + isEphemeronClass + "Answer whether the receiver has ephemeral instance variables. The garbage collector will + fire (queue for finalization) any ephemeron whose first instance variable is not referenced + other than from the transitive closure of references from ephemerons. Hence referring to + an object from the first inst var of an ephemeron will cause the ephemeron to fire when + the rest of the system does not refer to the object and that object is ready to be collected. + Since references from the remaining inst vars of an ephemeron will not prevent the ephemeron + from firing, ephemerons may act as the associations in weak dictionaries such that the value + (e.g. properties attached to the key) will not prevent firing when the key is no longer referenced + other than from ephemerons. Ephemerons can therefore be used to implement instance-based + pre-mortem finalization." + ^self instSpec = 5! Item was added: + ----- Method: Behavior>>isImmediateClass (in category 'testing') ----- + isImmediateClass + "Answer whether the receiver has immediate instances. Immediate instances + store their value in their object pointer, not in an object body. Hence immediates + take no space and are immutable. The immediates are distinguished by tag bits + in the pointer. They include SmallIntegers and Characters. Hence in the 32-bit + system SmallIntegers are 31-bit signed integers and Characters are 30-bit + unsigned character codes." + ^self instSpec = 7! Item was changed: ----- Method: Behavior>>isVariable (in category 'testing') ----- isVariable + "Answer whether the receiver has indexable variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + ^instSpec >= 2 and: [instSpec <= 4 or: [instSpec >= 9]]! - "Answer whether the receiver has indexable variables." - - ^ self instSpec >= 2! Item was changed: ----- Method: Behavior>>kindOfSubclass (in category 'testing class hierarchy') ----- kindOfSubclass + "Answer a String that is the keyword that describes the receiver's kind of subclass, + either a regular subclass, a variableSubclass, a variableByteSubclass, + a variableWordSubclass, a weakSubclass, an ephemeronSubclass or an immediateSubclass. + c.f. typeOfClass" + ^self isVariable + ifTrue: + [self isBits + ifTrue: + [self isBytes + ifTrue: [' variableByteSubclass: '] + ifFalse: [' variableWordSubclass: ']] + ifFalse: + [self isWeak + ifTrue: [' weakSubclass: '] + ifFalse: [' variableSubclass: ']]] + ifFalse: + [self isImmediateClass + ifTrue: [' immediateSubclass: '] + ifFalse: + [self isEphemeronClass + ifTrue: [' ephemeronSubclass: '] + ifFalse: [' subclass: ']]]! - "Answer a String that is the keyword that describes the receiver's kind - of subclass, either a regular subclass, a variableSubclass, a - variableByteSubclass, a variableWordSubclass, or a weakSubclass." - self isWeak - ifTrue: [^ ' weakSubclass: ']. - ^ self isVariable - ifTrue: [self isBits - ifTrue: [self isBytes - ifTrue: [ ' variableByteSubclass: '] - ifFalse: [ ' variableWordSubclass: ']] - ifFalse: [ ' variableSubclass: ']] - ifFalse: [ ' subclass: ']! Item was changed: ----- Method: Behavior>>shouldNotBeRedefined (in category 'testing') ----- shouldNotBeRedefined + "Answer if the receiver should not be redefined. + The assumption is that classes in Smalltalk specialObjects and + instance-specific Behaviors should not be redefined" - "Return true if the receiver should not be redefined. - The assumption is that compact classes, - classes in Smalltalk specialObjects and - Behaviors should not be redefined" + ^(Smalltalk specialObjectsArray + identityIndexOf: self + ifAbsent: [(self isKindOf: self) ifTrue: [1] ifFalse: [0]]) ~= 0! - ^(Smalltalk compactClassesArray includes: self) - or:[(Smalltalk specialObjectsArray includes: self) - or:[self isKindOf: self]]! Item was changed: ----- Method: Behavior>>typeOfClass (in category 'accessing') ----- typeOfClass + "Answer a symbol uniquely describing the type of the receiver. c.f. kindOfSubclass" + self isBytes ifTrue: + [^self instSpec = CompiledMethod instSpec + ifTrue: [#compiledMethod] "Very special!!" + ifFalse: [#bytes]]. + (self isWords and: [self isPointers not]) ifTrue: + [^self instSpec = SmallInteger instSpec + ifTrue: [#immediate] "Very special!!" + ifFalse: [#words]]. + self isWeak ifTrue: [^#weak]. + self isVariable ifTrue: [^#variable]. + self isEphemeronClass ifTrue: [^#ephemeron]. + ^#normal! - "Answer a symbol uniquely describing the type of the receiver" - self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" - self isBytes ifTrue:[^#bytes]. - (self isWords and:[self isPointers not]) ifTrue:[^#words]. - self isWeak ifTrue:[^#weak]. - self isVariable ifTrue:[^#variable]. - ^#normal.! Item was changed: ----- Method: BlockClosure>>simulateValueWithArguments:caller: (in category 'system simulation') ----- simulateValueWithArguments: anArray caller: aContext + "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity." | newContext sz | - (anArray class ~~ Array - or: [numArgs ~= anArray size]) ifTrue: - [^ContextPart primitiveFailTokenFor: nil]. newContext := (MethodContext newForMethod: outerContext method) setSender: aContext receiver: outerContext receiver method: outerContext method closure: self startpc: startpc. + ((newContext objectClass: anArray) ~~ Array + or: [numArgs ~= anArray size]) ifTrue: + [^ContextPart primitiveFailTokenFor: nil]. sz := self basicSize. newContext stackp: sz + numArgs. 1 to: numArgs do: [:i| newContext at: i put: (anArray at: i)]. 1 to: sz do: [:i| newContext at: i + numArgs put: (self at: i)]. ^newContext! Item was added: + ----- Method: Class>>immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'subclass creation') ----- + immediateSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a new + immediate class as a subclass of an existing class (the receiver)." + ^ClassBuilder new + superclass: self + immediateSubclass: t + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>computeFormat:instSize:forSuper:ccIndex: (in category 'class format') ----- computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. + Answer the format or nil if there is any problem." - Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | type == #compiledMethod ifTrue: + [newInstSize > 0 ifTrue: + [self error: 'A compiled method class cannot have named instance variables'. + ^nil]. + ^CompiledMethod format]. - [^(CompiledMethod format - bitClear: (16r1F bitShift: 11)) - bitOr: (ccIndex bitShift: 11)]. instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). + instSize > 65535 ifTrue: - instSize > 254 ifTrue: [self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true]. type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false]. type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false]. type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false]. type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true]. + type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true]. + type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true]. + (isPointers not and: [instSize > 0]) ifTrue: + [self error: 'A non-pointer class cannot have named instance variables'. - (isPointers not and:[instSize > 0]) ifTrue: - [self error:'A non-pointer class cannot have instance variables'. ^nil]. + ^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak! - ^(self format: instSize - variable: isVar - words: isWords - pointers: isPointers - weak: isWeak) + (ccIndex bitShift: 11).! Item was changed: ----- Method: ClassBuilder>>format:variable:words:pointers:weak: (in category 'class format') ----- + format: nInstVars variable: isVar words: is32BitWords pointers: isPointers weak: isWeak + "Compute the format for the given instance specfication. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = reserved for 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | - format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak - "Compute the format for the given instance specfication." - | cClass instSpec sizeHiBits fmt | - self flag: #instSizeChange. - " - Smalltalk browseAllCallsOn: #instSizeChange. - Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. - Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. - " - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - For now the format word is... - <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> - But when we revise the image format, it should become... - <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> - " - sizeHiBits := (nInstVars+1) // 64. - cClass := 0. "for now" instSpec := isWeak + ifTrue: + [isVar + ifTrue: [4] + ifFalse: [5]] + ifFalse: + [isPointers + ifTrue: + [isVar + ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]] + ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]] + ifFalse: + [isVar + ifTrue: [is32BitWords ifTrue: [10] ifFalse: [16]] + ifFalse: [7]]]. + ^(instSpec bitShift: 16) + nInstVars! - ifTrue:[4] - ifFalse:[isPointers - ifTrue: [isVar - ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] - ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] - ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. - fmt := sizeHiBits. - fmt := (fmt bitShift: 5) + cClass. - fmt := (fmt bitShift: 4) + instSpec. - fmt := (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" - fmt := (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" - ^fmt! Item was added: + ----- Method: ClassBuilder>>superclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'public') ----- + superclass: aClass + immediateSubclass: t instanceVariableNames: f + classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a + new immediate class as a subclass of an existing class." + | env | + aClass instSize > 0 + ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields']. + aClass isVariable + ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables']. + aClass isPointers + ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields']. + "Cope with pre-environment and environment versions. Simplify asap." + env := (Smalltalk classNamed: #EnvironmentRequest) + ifNil: [aClass environment] + ifNotNil: [:erc| erc signal ifNil: [aClass environment]]. + ^self + name: t + inEnvironment: env + subclassOf: aClass + type: #immediate + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" - "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. - We can rely on two assumptions (which are critical): - #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) - #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. - Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. - " | meta | meta := oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." - [ - "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). - Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "make sure that the VM cache is clean" oldClass methodDict do: [:cm | cm flushCache]. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue: [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. oldClass updateMethodBindingsTo: oldClass binding. oldClass class updateMethodBindingsTo: oldClass class binding]. + "eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was + to ensure no old instances existed after the becomeForward:. Without the GC it was possible + to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward: + updated references from the old objects to new objects but didn't destroy the old objects. + But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."] + valueUnpreemptively! - Smalltalk garbageCollect. - - "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). - - The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: - - On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. - - Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). - - Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. - - Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." - - ] valueUnpreemptively. - ! Item was changed: ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame' poolDictionaries: '' category: 'Kernel-Methods'! + !CompiledMethod commentStamp: 'eem 8/12/2014 14:45' prior: 0! + CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. - !CompiledMethod commentStamp: 'eem 5/12/2014 18:02' prior: 0! - My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. I'm a subclass of ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. Class variables: SmallFrame - the number of stack slots in a small frame Context LargeFrame - the number of stack slots in a large frame Context PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set The current format of a CompiledMethod is as follows: header (4 or 8 bytes, SmallInteger) + literals (4 or 8 bytes each, Object, see "The last literal..." below) - literals (4 or 8 bytes each, Object) bytecodes (variable, bytes) trailer (variable, bytes) + The header is a 31-bit signed integer (a SmallInteger) in the following format: - The header is a 31-bit signed integer (a SmallInteger) with one of the two following formats, selected by the sign bit: - sign bit 0, header >= 0: - (index 0) 9 bits: main part of primitive number (#primitive) - (index 9) 8 bits: number of literals (#numLiterals) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) - (index 18) 6 bits: number of temporary variables (#numTemps) - (index 24) 4 bits: number of arguments to the method (#numArgs) - (index 28) 1 bit: high-bit of primitive number (#primitive) - (index 29) 1 bit: flag bit, ignored by the VM (#flag) - (index 30/63) sign bit: 0 selects the Primary instruction set (#signFlag) - sign bit 1, header < 0: (index 0) 16 bits: number of literals (#numLiterals) (index 16) 1 bit: has primitive + (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) + (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag). + (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4, 0 selects the primary instruction set, e.g. SqueakV3PlusClosures) (#signFlag) - (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public) - (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4) (#signFlag) - i.e. the Secondary Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode. + If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. + + The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer. + + The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be left nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.! - The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.! Item was added: + ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') ----- + handleFailingFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails then the + system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + "retry if user proceeds" + ^self newMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') ----- + handleFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after newMethod:header: has failed + and allowed a scavenging garbage collection to occur. The scavenging + collection will have happened as the VM is activating the (failing) basicNew:. + If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') ----- + installPrimaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was added: + ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') ----- + installSecondaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: ["For now the high bit of primitive no. is in the 29th bit of header" - primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits flagBit | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - "For now the high bit of the primitive no. is in a high bit of the header" - primBits := (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19). - - flagBit := flag ifTrue: [ 1 ] ifFalse: [ 0 ]. - - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits + - (flagBit bitShift: 29)! Item was changed: ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') ----- + newMethod: numberOfBytes header: headerWord - newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other + information) is specified by the headerWord (see my class comment). + The first argument specifies the number of fields for bytecodes in the + method. Fail if either argument is not a SmallInteger, or if numberOfBytes + is negative, or if memory is low. Once the header of a method is set by + this primitive, it cannot be changed to change the number of literals. + Essential. See Object documentation whatIsAPrimitive." - information) is specified the headerWord. The first argument specifies - the number of fields for bytecodes in the method. Fail if either - argument is not a SmallInteger, or if numberOfBytes is negative. Once - the header of a method is set by this primitive, it cannot be changed in - any way. Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingNewMethod: numberOfBytes header: headerWord]. - - (numberOfBytes isInteger and: - [headerWord isInteger and: - [numberOfBytes >= 0]]) ifTrue: [ - "args okay; space must be low" - OutOfMemory signal. - "retry if user proceeds" - ^ self newMethod: numberOfBytes header: headerWord - ]. ^self primitiveFailed! Item was changed: ----- Method: CompiledMethod class>>toReturnConstant:trailerBytes: (in category 'instance creation') ----- toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index - ! Item was changed: ----- Method: CompiledMethod class>>toReturnField:trailerBytes: (in category 'instance creation') ----- toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field - ! Item was changed: ----- Method: CompiledMethod class>>toReturnSelfTrailerBytes: (in category 'instance creation') ----- toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 - ! Item was added: + ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') ----- + bytecodeSetName + ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''! Item was changed: ----- Method: CompiledMethod>>headerDescription (in category 'literals') ----- headerDescription + "Answer a description containing the information about the form of the + receiver and the form of the context needed to run the receiver." - "Answer a description containing the information about the form of the - receiver and the form of the context needed to run the receiver." + ^(ByteString new: 128) writeStream + print: self header; cr; + nextPutAll: '"primitive: '; print: self primitive; cr; + nextPutAll: ' numArgs: '; print: self numArgs; cr; + nextPutAll: ' numTemps: '; print: self numTemps; cr; + nextPutAll: ' numLiterals: '; print: self numLiterals; cr; + nextPutAll: ' frameSize: '; print: self frameSize; cr; + nextPutAll: ' bytecodeSet: '; nextPutAll: self bytecodeSetName; + nextPut: $"; cr; + contents! - | s | - s := '' writeStream. - self header printOn: s. - s cr; nextPutAll: '"primitive: '. - self primitive printOn: s. - s cr; nextPutAll: ' numArgs: '. - self numArgs printOn: s. - s cr; nextPutAll: ' numTemps: '. - self numTemps printOn: s. - s cr; nextPutAll: ' numLiterals: '. - self numLiterals printOn: s. - s cr; nextPutAll: ' frameSize: '. - self frameSize printOn: s. - s cr; nextPutAll: ' isClosureCompiled: '. - self isBlueBookCompiled not printOn: s. - s nextPut: $"; cr. - ^ s contents! Item was changed: ----- Method: CompiledMethod>>numLiterals (in category 'accessing') ----- numLiterals "Answer the number of literals used by the receiver." + ^self header bitAnd: 65535! - | header | - ^(header := self header) < 0 - ifTrue: [header bitAnd: 65535] - ifFalse: [(header bitShift: -9) bitAnd: 16rFF]! Item was changed: ----- Method: CompiledMethod>>primitive (in category 'accessing') ----- primitive "Answer the primitive index associated with the receiver. + Zero indicates that this is not a primitive method." + | initialPC | + ^(self header anyMask: 65536) "Is the hasPrimitive? flag set?" + ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] + ifFalse: [0]! - Zero indicates that this is not a primitive method. - In the original header format we currently allow 10 bits of primitive index, but they are - in two places for backward compatibility. In the new format the primitive index is in the - last two bytes of a three byte callPrimitive: bytecode. The time to unpack is negligible, - since the derived primitive function pointer full index is stored in the method cache." - | header initialPC | - ^(header := self header) < 0 - ifTrue: - [(header anyMask: 65536) "Is the hasPrimitive? flag set?" - ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] - ifFalse: [0]] - ifFalse: - [(header bitAnd: 16r1FF) + ((header bitShift: -19) bitAnd: 16r200)]! Item was changed: ----- Method: ContextPart>>activateReturn:value: (in category 'private') ----- activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" + ^MethodContext + sender: self - ^ self - activateMethod: ContextPart theReturnMethod - withArgs: {value} receiver: aContext + method: MethodContext theReturnMethod + arguments: {value}! - class: aContext class! Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments + "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and + arguments are given as arguments to this message. If successful, push result and return + resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes + execution needs to be intercepted and simulated to avoid execution running away." - "Simulate a primitive method whose index is primitiveIndex. The - simulated receiver and arguments are given as arguments to this message. - If successful, push result and return resuming context, else ^ PrimitiveFailToken. - Any primitive which provokes execution needs to be intercepted and simulated - to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug + interesting code, such as the debugger itself. hence use primitive 19 with care :-)" - interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. + ((primitiveIndex between: 201 and: 222) + and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: + [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" + or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" + [^receiver simulateValueWithArguments: arguments caller: self]. + primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" + [^receiver simulateValueWithArguments: arguments first caller: self]]. - "ContextPart>>blockCopy:; simulated to get startpc right" - (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) - ifTrue: [^self push: ((BlockContext newForMethod: receiver method) - home: receiver home - startpc: pc + 2 - nargs: (arguments at: 1))]. - (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" - ifTrue: [^receiver pushArgs: arguments from: self]. - (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" - ifTrue: [^receiver pushArgs: arguments first from: self]. - primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" - ifTrue: [^self send: arguments first - to: receiver - with: arguments allButFirst - super: false]. - primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: nil]. - primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: (arguments at: 3)]. + primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [^self send: arguments first to: receiver with: arguments allButFirst super: false]. + primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. + primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. + "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. + ^(self isPrimFailToken: value) - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" - and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: (arguments at: 2) + arguments: (arguments at: 1)]. - method: arguments last - arguments: (primitiveIndex = 188 - ifTrue: [arguments at: 1] - ifFalse: [arguments allButLast])]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. - ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" - or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" - [^receiver simulateValueWithArguments: arguments caller: self]. - primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" - [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] + ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. + + ^(self isPrimFailToken: value) - ifFalse: - [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! Item was added: + ----- Method: ContextPart>>isPrimFailToken: (in category 'private') ----- + isPrimFailToken: anObject + ^(self objectClass: anObject) == Array + and: [anObject size = 2 + and: [anObject first == PrimitiveFailToken]]! Item was added: + ----- Method: ContextPart>>send:to:with:lookupIn: (in category 'controlling') ----- + send: selector to: rcvr with: arguments lookupIn: lookupClass + "Simulate the action of sending a message with selector and arguments + to rcvr. The argument, lookupClass, is the class in which to lookup the + message. This is the receiver's class for normal messages, but for super + messages it will be some specific class related to the source method." + + | meth primIndex val ctxt | + (meth := lookupClass lookupSelector: selector) ifNil: + [^self send: #doesNotUnderstand: + to: rcvr + with: {Message selector: selector arguments: arguments} + lookupIn: lookupClass]. + (primIndex := meth primitive) > 0 ifTrue: + [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments. + (self isPrimFailToken: val) ifFalse: + [^val]]. + (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue: + [^self error: 'Simulated message ', arguments first selector, ' not understood']. + ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments. + primIndex > 0 ifTrue: + [ctxt failPrimitiveWith: val]. + ^ctxt! Item was changed: ----- Method: ContextPart>>send:to:with:super: (in category 'controlling') ----- + send: selector to: rcvr with: arguments super: superFlag + "Simulate the action of sending a message with selector arguments + to rcvr. The argument, superFlag, tells whether the receiver of the + message was specified with 'super' in the source method." - send: selector to: rcvr with: args super: superFlag - "Simulate the action of sending a message with selector, selector, and - arguments, args, to receiver. The argument, superFlag, tells whether the - receiver of the message was specified with 'super' in the source method." + ^self send: selector + to: rcvr + with: arguments + lookupIn: (superFlag + ifTrue: [self method methodClassAssociation value superclass] + ifFalse: [self objectClass: rcvr])! - | class meth val ctxt | - class := superFlag - ifTrue: [self method methodClassAssociation value superclass] - ifFalse: [self objectClass: rcvr]. - meth := class lookupSelector: selector. - meth == nil ifTrue: - [^self - send: #doesNotUnderstand: - to: rcvr - with: (Array with: (Message selector: selector arguments: args)) - super: superFlag]. - val := self tryPrimitiveFor: meth receiver: rcvr args: args. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken]]) ifFalse: - [^val]. - (selector == #doesNotUnderstand: - and: [class == ProtoObject]) ifTrue: - [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood']. - ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken - and: [val last notNil - and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue: - [ctxt at: ctxt stackPtr put: val last]. - ^ctxt! Item was changed: ----- Method: ContextPart>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') ----- tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments + "Invoke the named primitive for aCompiledMethod, answering its result, or, + if the primiitve fails, answering the error code." - | selector theMethod spec receiverClass | ec ifNotNil: ["If ec is an integer other than -1 there was a problem with primitive 218, not with the external primitive itself. -1 indicates a generic failure (where ec should be nil) but ec = nil means primitive 218 is not implemented. So interpret -1 to mean the external primitive failed with a nil error code." ec isInteger ifTrue: [ec = -1 ifTrue: [ec := nil] + ifFalse: [self primitiveFailed]]]. + ^self class primitiveFailTokenFor: ec! - ifFalse: [self primitiveFailed]]. - ^{PrimitiveFailToken. ec}]. - "Assume a nil error code implies the primitive is not implemented and fall back on the old code." - "Hack. Attempt to execute the named primitive from the given compiled method" - arguments size > 8 ifTrue: - [^{PrimitiveFailToken. nil}]. - selector := #( - tryNamedPrimitive - tryNamedPrimitive: - tryNamedPrimitive:with: - tryNamedPrimitive:with:with: - tryNamedPrimitive:with:with:with: - tryNamedPrimitive:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. - receiverClass := self objectClass: aReceiver. - theMethod := receiverClass lookupSelector: selector. - theMethod == nil ifTrue: - [^{PrimitiveFailToken. nil}]. - spec := theMethod literalAt: 1. - spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. - Smalltalk unbindExternalPrimitives. - ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass! Item was added: + ----- Method: InstructionClient>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: pimIndex + "V3PlusClosures: 139 10001011 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + NewsqueakV4: 249 11111001 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + ( jjjjjjj * 256) + m=1 means inlined primitive, no hard return after execution."! Item was added: + ----- Method: InstructionPrinter>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: index + "Print the callPrimitive." + + self print: 'callPrimtive: ' , index printString! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self unusedBytecode: client at: pc - 1]. byte3 := method at: pc. pc := pc + 1. + offset = 11 ifTrue: [^client callPrimitive: byte2 + (byte3 bitShift: 8)]. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: Integer class>>initialize (in category 'class initialization') ----- + initialize + "Integer initialize" + self initializeLowBitPerByteTable! - initialize "Integer initialize" - "Ensure we have the right compact class index" - - "LPI has been a compact class forever - just ensure basic correctness" - (LargePositiveInteger indexIfCompact = 5) ifFalse:[ - (Smalltalk compactClassesArray at: 5) - ifNil:[LargePositiveInteger becomeCompactSimplyAt: 5] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - "Cog requires LNI to be compact at 4 (replacing PseudoContext)" - (LargeNegativeInteger indexIfCompact = 4) ifFalse:[ - "PseudoContext will likely get removed at some point so write this test - without introducing a hard dependency" - (Smalltalk compactClassesArray at: 4) name == #PseudoContext - ifTrue:[Smalltalk compactClassesArray at: 4 put: nil]. - (Smalltalk compactClassesArray at: 4) - ifNil:[LargeNegativeInteger becomeCompactSimplyAt: 4] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - self initializeLowBitPerByteTable - ! Item was added: + ----- Method: MethodContext class>>allInstances (in category 'enumerating') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst. + Only count until thisContext since this context has been created only to + compute the existing instances." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + insts nextPut: inst. + inst := next]. + ^insts contents! Item was changed: ----- Method: MethodContext class>>allInstancesDo: (in category 'private') ----- allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst. + Only count until thisContext since evaluation of aBlock will create new contexts." - "Only count until thisContext since evaluation of aBlock will create new contexts." - | inst next | inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == thisContext] whileFalse:[ - next := inst nextInstance. - aBlock value: inst. - inst := next] - ! Item was added: + ----- Method: MethodContext>>failPrimitiveWith: (in category 'system simulation') ----- + failPrimitiveWith: maybePrimFailToken + "The receiver is a freshly-created context on a primitive method. Skip the callPrimitive: + bytecode and store the primitive fail code if there is one and the method consumes it." + self skipCallPrimitive. + ((self isPrimFailToken: maybePrimFailToken) + and: [method encoderClass isStoreAt: pc in: method]) ifTrue: + [self at: stackp put: maybePrimFailToken last]! Item was changed: ----- Method: ProtoObject>>scaledIdentityHash (in category 'comparing') ----- scaledIdentityHash "For identityHash values returned by primitive 75, answer + such values times 2^8. Otherwise, match the existing + identityHash implementation" - such values times 2^18. Otherwise, match the existing - identityHash implementation" + ^self identityHash * 256 "bitShift: 8"! - ^self identityHash * 262144 "bitShift: 18"! Item was changed: ==== ERROR === Error: Unrecognized class type 22 October 2014 7:59:05.842 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(SmallInteger) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Wed Oct 22 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Wed Oct 22 23:55:03 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141022235502.13682.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007342.html Name: Collections.spur-cmm.585 Ancestors: Collections-cmm.585, Collections.spur-ul.584 Collections-cmm.585 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Speed up visiting with #addNewElement:. It provides the common pattern of checking for inclusion, followed by add:, in just one scan, instead of two. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007343.html Name: Kernel.spur-ul.880 Ancestors: Kernel-ul.880, Kernel.spur-eem.879 Kernel-ul.880 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Compile methods with the right trailer to avoid a #becomeForward: when the actual trailer is added. ============================================= From lewis at mail.msen.com Thu Oct 23 00:52:17 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Thu Oct 23 00:52:23 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> Message-ID: <20141023005217.GA15881@shell.msen.com> Eliot, Thanks for this background, it is very helpful and interesting. I would also like to put in a good word for Fuel. It is well designed, well documented, and well supported on Squeak and Pharo. Very high quality work. I use Fuel in RemoteTask (in package CommandShell) for inter-image communication. ReferenceStream also works, and both are supported in RemoteTask. But if you want to have a serializer that you can read and understand, I'd say that Fuel is hard to beat. I am not advocating anything with respect to image segments, project saving, and so forth, I'm just saying that Fuel is a very good thing. It works well in Squeak, and I suspect that many folks may not be aware of this. Dave On Wed, Oct 22, 2014 at 12:53:15PM -0700, Eliot Miranda wrote: > > Hi Stephane, Hi All, > > let me talk a little about the ParcPlace experience, which led to David > Leibs' parcels, whose architecture Fuel uses. > > In the late 80's 90's Peter Deutsch write BOSS (Binary Object Storage > System), a traditional interpretive pickling system defined by a little > bytecoded language. Think of a bytecode as something like "What follows is > an object definition, which is its id followed by size info followed by the > definitions or ids of its sub-parts, including its class", or "What follows > is the id of an already defined object". So the loading interpreter looks > at the next byte in the stream and that tells it what to do. So the > storage is a recursive definition of a graph, much like a recursive grammar > for a programming language. > > This approach is slow (its a bytecode interpreter) and fragile (structures > in the process of being built aren't valid yet, imagine trying to take the > hash of a Set that is only half-way through being materialized). But this > architecture was very common at the time (I wrote something very similar). > The advantage BOSS had was a clumsy hack for versioning. One could specify > blocks that were supplied with the version and state of older objects, and > these blocks could effect shape change etc to bring loaded instances > up-to-date. > > David Leibs has an epiphany as, in the early 90's, ParcPlae was trying to > decompose the VW image (chainsaw was the code name of the VW 2.5 release). > If one groups instances by class, one can instantiate in bulk, creating all > the instances of a particular class in one go, followed by all the > instances of a different class, etc. Then the arc information (the > pointers to objects to be stored in the loaded objects inst vars) can > follow the instance information. So now the file looks like header, names > of classes that are referenced (not defined), definitions of classes, > definitions of instances (essentially class id, count pairs), arc > information. And materializing means finding the classes in the image, > creating the classes in the file, creating the instances, stitching the > graph together, and then performing any post-load actions (rehashing > instances, etc). > > Within months we merged with Digitalk (to form DarcPlace-Dodgytalk) and > were introduced to TeamV's loading model which was very much like > ImageSegments, being based on the VM's object format. Because an > ImageSegment also has imports (references to classes and globals taken from > the host system, not defined in the file) performance doesn't just depend > on loading the segment into memorty. It also depends on how long it takes > to search the system to find imports, etc. In practice we found that a) > Parcels were 4 times faster than BOSS, and b) they were no slower than > Digitalk's image segments. But being independent of the VM's heap format > Parcels had BOSS's flexibility and could support shape change on load, > something ImageSegments *cannot do*. I went on to extend parcels with > support for shape change, plus support for partial loading of code, but I > won't describe that here. Too detailed, even thought its very important. > > Mariano spent time talking with me and Fuel's basic architecture is that of > parcels, but reimplemented to be nicer, more flexible etc. But essentially > Parcels and Fuel are at their core David Leibs' invention. He came up with > the ideas of a) grouping objects by class and b) separating the arcs from > the nodes. > > > Now, where ImageSegments are faster than Parcels is *not* loading. Our > experience with VW vs TeamV showed us that. But they are faster in > collecting the graph of objects to be included. ImageSegments are dead > simple. So IMO the right architecture is to use Parcels' segregation, and > Parcels' "abstract" format (independent of the heap object format) with > ImageSegment's computation of the object graph. Igor Stasenko has > suggested providing the tracing part of ImageSegments (Dan Ingalls' cool > invention of mark the segment root objects, then mark the heap, leaving the > objects to be stored unmarked in the shadow of the marked segment roots) as > a separate primitive. Then this can be quickly partitioned by class and > then written by Smalltalk code. > > The loader can then materialize objects using Smalltalk code, can deal with > shape change, and not be significantly slower than image segments. > Crucially this means that one has a portable, long-lived object storage > format; freeing the VM to evolve its object format without breaking image > segments with every change to the object format. > > I'd be happy to help people working on Fuel by providing that primitive for > anyone who wants to try and reimplement the ImageSegment functonality > (project saving, class faulting, etc) above Fuel. > > > On Wed, Oct 22, 2014 at 11:56 AM, St??phane Ducasse < > stephane.ducasse@inria.fr> wrote: > > > What I can tell you is that instability raised by just having one single > > pointer not in the root objects > > pointing to an element in the segment and the implication of this pointer > > on reloaded segments, (yes I do not want to have two objects in memory > > after loading) makes sure that we will not use IS primitive in Pharo in any > > future. For us this is a non feature. > > > > IS was a nice trick but since having a pointer to an object is so cheap > > and the basis of our computational model > > so this is lead fo unpredictable side effects. We saw that when mariano > > worked during the first year of his PhD (which is a kind of LOOM revisit). > > > > Stef > > > > > > -- > best, > Eliot From eliot.miranda at gmail.com Thu Oct 23 03:17:07 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 23 03:17:13 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: <20141023005217.GA15881@shell.msen.com> References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> <20141023005217.GA15881@shell.msen.com> Message-ID: <1422671C-0762-4D0C-975F-38AFBB79699D@gmail.com> Hi David, On Oct 22, 2014, at 5:52 PM, "David T. Lewis" wrote: > > Eliot, > > Thanks for this background, it is very helpful and interesting. > > I would also like to put in a good word for Fuel. It is well designed, well > documented, and well supported on Squeak and Pharo. Very high quality work. > > I use Fuel in RemoteTask (in package CommandShell) for inter-image communication. > ReferenceStream also works, and both are supported in RemoteTask. But if you > want to have a serializer that you can read and understand, I'd say that Fuel > is hard to beat. > > I am not advocating anything with respect to image segments, project saving, > and so forth, I'm just saying that Fuel is a very good thing. It works well > in Squeak, and I suspect that many folks may not be aware of this. Oh I agree. If only ImageSegments weren't used... :-). We use an early version of Fuel at Cadence which is essential to our system. We haven't upgraded as it "just works". > > Dave > > On Wed, Oct 22, 2014 at 12:53:15PM -0700, Eliot Miranda wrote: >> >> Hi Stephane, Hi All, >> >> let me talk a little about the ParcPlace experience, which led to David >> Leibs' parcels, whose architecture Fuel uses. >> >> In the late 80's 90's Peter Deutsch write BOSS (Binary Object Storage >> System), a traditional interpretive pickling system defined by a little >> bytecoded language. Think of a bytecode as something like "What follows is >> an object definition, which is its id followed by size info followed by the >> definitions or ids of its sub-parts, including its class", or "What follows >> is the id of an already defined object". So the loading interpreter looks >> at the next byte in the stream and that tells it what to do. So the >> storage is a recursive definition of a graph, much like a recursive grammar >> for a programming language. >> >> This approach is slow (its a bytecode interpreter) and fragile (structures >> in the process of being built aren't valid yet, imagine trying to take the >> hash of a Set that is only half-way through being materialized). But this >> architecture was very common at the time (I wrote something very similar). >> The advantage BOSS had was a clumsy hack for versioning. One could specify >> blocks that were supplied with the version and state of older objects, and >> these blocks could effect shape change etc to bring loaded instances >> up-to-date. >> >> David Leibs has an epiphany as, in the early 90's, ParcPlae was trying to >> decompose the VW image (chainsaw was the code name of the VW 2.5 release). >> If one groups instances by class, one can instantiate in bulk, creating all >> the instances of a particular class in one go, followed by all the >> instances of a different class, etc. Then the arc information (the >> pointers to objects to be stored in the loaded objects inst vars) can >> follow the instance information. So now the file looks like header, names >> of classes that are referenced (not defined), definitions of classes, >> definitions of instances (essentially class id, count pairs), arc >> information. And materializing means finding the classes in the image, >> creating the classes in the file, creating the instances, stitching the >> graph together, and then performing any post-load actions (rehashing >> instances, etc). >> >> Within months we merged with Digitalk (to form DarcPlace-Dodgytalk) and >> were introduced to TeamV's loading model which was very much like >> ImageSegments, being based on the VM's object format. Because an >> ImageSegment also has imports (references to classes and globals taken from >> the host system, not defined in the file) performance doesn't just depend >> on loading the segment into memorty. It also depends on how long it takes >> to search the system to find imports, etc. In practice we found that a) >> Parcels were 4 times faster than BOSS, and b) they were no slower than >> Digitalk's image segments. But being independent of the VM's heap format >> Parcels had BOSS's flexibility and could support shape change on load, >> something ImageSegments *cannot do*. I went on to extend parcels with >> support for shape change, plus support for partial loading of code, but I >> won't describe that here. Too detailed, even thought its very important. >> >> Mariano spent time talking with me and Fuel's basic architecture is that of >> parcels, but reimplemented to be nicer, more flexible etc. But essentially >> Parcels and Fuel are at their core David Leibs' invention. He came up with >> the ideas of a) grouping objects by class and b) separating the arcs from >> the nodes. >> >> >> Now, where ImageSegments are faster than Parcels is *not* loading. Our >> experience with VW vs TeamV showed us that. But they are faster in >> collecting the graph of objects to be included. ImageSegments are dead >> simple. So IMO the right architecture is to use Parcels' segregation, and >> Parcels' "abstract" format (independent of the heap object format) with >> ImageSegment's computation of the object graph. Igor Stasenko has >> suggested providing the tracing part of ImageSegments (Dan Ingalls' cool >> invention of mark the segment root objects, then mark the heap, leaving the >> objects to be stored unmarked in the shadow of the marked segment roots) as >> a separate primitive. Then this can be quickly partitioned by class and >> then written by Smalltalk code. >> >> The loader can then materialize objects using Smalltalk code, can deal with >> shape change, and not be significantly slower than image segments. >> Crucially this means that one has a portable, long-lived object storage >> format; freeing the VM to evolve its object format without breaking image >> segments with every change to the object format. >> >> I'd be happy to help people working on Fuel by providing that primitive for >> anyone who wants to try and reimplement the ImageSegment functonality >> (project saving, class faulting, etc) above Fuel. >> >> >> On Wed, Oct 22, 2014 at 11:56 AM, St??phane Ducasse < >> stephane.ducasse@inria.fr> wrote: >> >>> What I can tell you is that instability raised by just having one single >>> pointer not in the root objects >>> pointing to an element in the segment and the implication of this pointer >>> on reloaded segments, (yes I do not want to have two objects in memory >>> after loading) makes sure that we will not use IS primitive in Pharo in any >>> future. For us this is a non feature. >>> >>> IS was a nice trick but since having a pointer to an object is so cheap >>> and the basis of our computational model >>> so this is lead fo unpredictable side effects. We saw that when mariano >>> worked during the first year of his PhD (which is a kind of LOOM revisit). >>> >>> Stef >> >> >> >> -- >> best, >> Eliot > From eliot.miranda at gmail.com Thu Oct 23 04:01:42 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 23 04:01:48 2014 Subject: [squeak-dev] VM crash In-Reply-To: <9504224B-5B55-4743-9F20-1CEBCF696A3F@afceurope.com> References: <9504224B-5B55-4743-9F20-1CEBCF696A3F@afceurope.com> Message-ID: Hi Annick, On Wed, Oct 22, 2014 at 5:46 AM, Annick Fron wrote: > I have an error : > > ? don?t know how to derive register state from a ucontext_t on this > platform ? > That's just telling you that the VM doesn't know how to print the register state in a signal handler on this platform. What is your platform? What VM are you using? (vm -version) At least on Mac and x86 linux the VM /can/ do this, and hence print useful information when there's a crash. > Where could that come from ? > > Annick > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141022/6911a524/attachment.htm From brasspen at gmail.com Thu Oct 23 14:03:26 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Thu Oct 23 14:03:32 2014 Subject: [squeak-dev] Swiki in 4.5 running on box4 Message-ID: <50DE496C-F18E-444D-BF00-BFE11D2C1D46@gmail.com> http://box4.squeak.org:8080 I?ve got Swiki working in 4.5 running on box4. I intend next week to create a swiki account for it on box4, run it under daemontools, and copy over the ?swiki" content directory from box2 to box4. Chris (Installer ss) project: 'KomHttpServer'; install: 'KomServices-lr.21'; install: 'DynamicBindings-lr.13'; install: 'KomHttpServer-DwightManhertz.67'. (Installer ss3) project: 'SqueakServices'; install: 'Swiki'. ComSwikiLauncher openAsMorph. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/f6788fe7/attachment.htm From eliot.miranda at gmail.com Thu Oct 23 15:46:32 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 23 15:46:37 2014 Subject: [squeak-dev] Using libraries in FFI In-Reply-To: <476D3881-5167-43E9-AC8E-04AC07E91312@afceurope.com> References: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> <27481657-8A8D-4350-A645-FF722E600386@gmail.com> <476D3881-5167-43E9-AC8E-04AC07E91312@afceurope.com> Message-ID: Skipped content of type multipart/alternative-------------- next part -------------- A non-text attachment was scrubbed... Name: squeak Type: application/octet-stream Size: 2500 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/584592da/squeak.obj From eliot.miranda at gmail.com Thu Oct 23 15:49:08 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 23 15:49:10 2014 Subject: [squeak-dev] Using libraries in FFI In-Reply-To: References: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> <27481657-8A8D-4350-A645-FF722E600386@gmail.com> <476D3881-5167-43E9-AC8E-04AC07E91312@afceurope.com> Message-ID: On Thu, Oct 23, 2014 at 8:46 AM, Eliot Miranda wrote: > Hi Annick, > > On Wed, Oct 22, 2014 at 5:45 AM, Annick Fron wrote: > >> Hi Eliot, >> >> My problem is not with the VM, my problem is with my own library >> that I connect to through FFI. >> I know where the libraries are ! >> >> I have tried to add them in /etc/ld.so.conf.d , that does not work. >> I have tried export LD_LIBRARY_PATH, but somehow it erases some libraries >> needed by pharo. >> > > But if you use the script I include with my VMs it won't erase. It > extends LD_LIBRARY_PATH. Find an example attached. > Here's the operative line (the last one). PLUGINS is the directory containing VM plugins, SVMLLP is "Smalltalk VM LD_LIBRARY_PATH" and specifies the directories containing the C libraries the VM depends on (C library, libuuid, etc). LD_LIBRARY_PATH=$PLUGINS:$SVMLLP:${LD_LIBRARY_PATH} exec "$BIN/squeak" "$@" > > > >> I have done sudo ldconfig ... >> >> In fact I have one library that depends from another one. >> In FFI I call one method which calls another method in the other library. >> I have tried to create symbolics links in the directory ? >> I have checked that nm gives the right symbol with the right type .. >> >> So I have no idea what to try now ! >> >> Annick >> >> Le 22 oct. 2014 ? 12:46, Eliot Miranda a ?crit >> : >> >> > Hi Annick, >> > >> > LD_LIBRARY_PATH should be set to point to the relevant directories, >> but this can be tricky as there is a lot if variation across Linux distros >> as to where libraries are kept. The squeak script that comes with the Cog >> VMs extends LD_LIBRARY_PATH, so if you know where your libraries are you >> can use the script to find the other libraries the VM needs (c library and >> plugins). >> > >> > Eliot (phone) >> > >> > On Oct 22, 2014, at 2:55 AM, Annick Fron wrote: >> > >> >> Hi, >> >> >> >> I am using a module in FFI which depends on a large library let?s say >> 10 dynamic .so files in a directory. >> >> How is it possible to use this library without making all symbolic >> links ? >> >> >> >> Annick >> > >> >> >> > > > -- > best, > Eliot > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/163e05b1/attachment.htm From asqueaker at gmail.com Thu Oct 23 15:50:28 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 23 15:50:32 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> Message-ID: > If one groups instances by class, one can instantiate in bulk, creating all the instances of a > particular class in one go What does "instantiate in bulk" mean? Doesn't that mean one still must send #new (or #basicNew) to the class for each instance? Why would that be faster? From edw at generalmagic.at Thu Oct 23 15:59:24 2014 From: edw at generalmagic.at (Wolfgang Eder) Date: Thu Oct 23 15:59:28 2014 Subject: [squeak-dev] Using libraries in FFI In-Reply-To: References: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> <27481657-8A8D-4350-A645-FF722E600386@gmail.com> <476D3881-5167-43E9-AC8E-04AC07E91312@afceurope.com> Message-ID: Skipped content of type multipart/alternative-------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4139 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/7cd3c2a5/smime.bin From eliot.miranda at gmail.com Thu Oct 23 16:02:42 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 23 16:02:45 2014 Subject: [squeak-dev] Using libraries in FFI In-Reply-To: References: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> <27481657-8A8D-4350-A645-FF722E600386@gmail.com> <476D3881-5167-43E9-AC8E-04AC07E91312@afceurope.com> Message-ID: Hi Wolfgang, On Thu, Oct 23, 2014 at 8:59 AM, Wolfgang Eder wrote: > hi, > shouldn?t there be quotes here like such: > > LD_LIBRARY_PATH="$PLUGINS:$SVMLLP:${LD_LIBRARY_PATH}" exec "$BIN/squeak" > "$@? > yes, thanks! > > cheers wolfgang > > Am 23.10.2014 um 17:49 schrieb Eliot Miranda : > > LD_LIBRARY_PATH=$PLUGINS:$SVMLLP:${LD_LIBRARY_PATH} exec "$BIN/squeak" "$@" > > > > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/b9a9a414/attachment.htm From marcel.taeumel at student.hpi.uni-potsdam.de Thu Oct 23 16:20:46 2014 From: marcel.taeumel at student.hpi.uni-potsdam.de (Marcel Taeumel) Date: Thu Oct 23 16:23:35 2014 Subject: [squeak-dev] Re: compiler whitewash In-Reply-To: References: Message-ID: <1414081246004-4786244.post@n4.nabble.com> Would be nice if there is no warning at all if you write this kind of code. :) Best, Marcel -- View this message in context: http://forum.world.st/compiler-whitewash-tp4785831p4786244.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From asqueaker at gmail.com Thu Oct 23 16:43:11 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 23 16:43:15 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: <1422671C-0762-4D0C-975F-38AFBB79699D@gmail.com> References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> <20141023005217.GA15881@shell.msen.com> <1422671C-0762-4D0C-975F-38AFBB79699D@gmail.com> Message-ID: >> I would also like to put in a good word for Fuel. It is well designed, well >> documented, and well supported on Squeak and Pharo. Very high quality work. >> >> I use Fuel in RemoteTask (in package CommandShell) for inter-image communication. >> ReferenceStream also works, and both are supported in RemoteTask. But if you >> want to have a serializer that you can read and understand, I'd say that Fuel >> is hard to beat. >> >> I am not advocating anything with respect to image segments, project saving, >> and so forth, I'm just saying that Fuel is a very good thing. It works well >> in Squeak, and I suspect that many folks may not be aware of this. > > Oh I agree. If only ImageSegments weren't used... :-). We use an early version of Fuel at Cadence which is essential to our system. We haven't upgraded as it "just works". I'd just like to remind everyone, there is another stand-alone serializer available for Squeak called "Ma-Object-Serializer". It was developed from the ground up for _Squeak_ -- meaning, it already supports all the same Squeak-specific preserialization and postmaterialization pickling/unpickling behaviors, like for Project, etc. which used by ReferenceStream. There is nothing more that I would *love* than for interest from my fellow Squeakers to lead to significant improvements in this serializer from trying to incorporate it into your applications. I think there is some low-hanging fruit (like the nascent #addNewElement:!) to be had simply by everyone's different development views and experience. Such improvements would be directly inherited by Magma! I looked at trying to incorporate Fuel as the serializer for Magma, to take advantage of its purported speed. But one of the very first things I found was the benchmarks for "the Magma serializer" in the Fuel paper were totally bogus. I had asked Mariano to separate out initialization from serialization and materialization, but since he didn't, the numbers reported are a tiny fraction of their actual speed. I came to realize that Fuel is really targeted at just two primary use-cases: 1) saving a complete-graph and 2) loading a complete-graph. But Ma-Object-Serializer has the ability to serialize/materialize *partial* graphs by letting the user specify a TraversalStrategy, which is essential for Magma. Unfortunately, Fuel cannot do this. The other innovation of Ma-Object-Serializer is its first-class access to the object-graph **in its serialized state** in the same ways (partial or complete) like when they were Smalltalk objects. From eliot.miranda at gmail.com Thu Oct 23 17:00:49 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 23 17:00:55 2014 Subject: [squeak-dev] Re: compiler whitewash In-Reply-To: <1414081246004-4786244.post@n4.nabble.com> References: <1414081246004-4786244.post@n4.nabble.com> Message-ID: On Thu, Oct 23, 2014 at 9:20 AM, Marcel Taeumel < marcel.taeumel@student.hpi.uni-potsdam.de> wrote: > Would be nice if there is no warning at all if you write this kind of code. > :) > you mean you don't want to be warned of use of uninitialized variables or something else? If the former I disagree I find the warning very useful, and hence put up with the annoyance when I'm depending on the variable having been initialized to nil. > > Best, > Marcel > > > > -- > View this message in context: > http://forum.world.st/compiler-whitewash-tp4785831p4786244.html > Sent from the Squeak - Dev mailing list archive at Nabble.com. > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/9ada9322/attachment.htm From edgardec2005 at gmail.com Thu Oct 23 17:39:43 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Thu Oct 23 17:39:55 2014 Subject: [squeak-dev] Swiki in 4.5 running on box4 In-Reply-To: <50DE496C-F18E-444D-BF00-BFE11D2C1D46@gmail.com> Message-ID: On 10/23/14, 11:03 AM, "Chris Cunnington" wrote: > http://box4.squeak.org:8080 > > I?ve got Swiki working in 4.5 running on box4. I intend next week to create a > swiki account for it on box4, run it under daemontools, and copy over the > ?swiki" content directory from box2 to box4. > > Chris > > > (Installer ss) > project: 'KomHttpServer'; > install: 'KomServices-lr.21'; > install: 'DynamicBindings-lr.13'; > install: 'KomHttpServer-DwightManhertz.67'. > (Installer ss3) > project: 'SqueakServices'; > install: 'Swiki'. > ComSwikiLauncher openAsMorph. > > Excellent !! > I check the install on FunSqueak and add if work > > Thanks !! -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/80b19469/attachment.htm From marcel.taeumel at student.hpi.uni-potsdam.de Thu Oct 23 18:02:14 2014 From: marcel.taeumel at student.hpi.uni-potsdam.de (Marcel Taeumel) Date: Thu Oct 23 18:05:07 2014 Subject: [squeak-dev] Re: compiler whitewash In-Reply-To: References: <1414081246004-4786244.post@n4.nabble.com> Message-ID: <1414087334762-4786263.post@n4.nabble.com> In this code example, the programmer was aware if the nil-case, which is the same as uninitialized. I find it sometimes strange to have to write "x := nil." in an algorithm just to get rid of this message. In other cases, this warning is fine. :) Maybe there are some patterns that indicate that "not initialized" is totally fine. Maybe it is just the case when #ifNil: is explicitely found in the code. Best, Marcel -- View this message in context: http://forum.world.st/compiler-whitewash-tp4785831p4786263.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From marcel.taeumel at student.hpi.uni-potsdam.de Thu Oct 23 18:03:04 2014 From: marcel.taeumel at student.hpi.uni-potsdam.de (Marcel Taeumel) Date: Thu Oct 23 18:05:55 2014 Subject: [squeak-dev] Re: compiler whitewash In-Reply-To: <1414087334762-4786263.post@n4.nabble.com> References: <1414081246004-4786244.post@n4.nabble.com> <1414087334762-4786263.post@n4.nabble.com> Message-ID: <1414087384949-4786264.post@n4.nabble.com> Some addon: I personally think that all variables are initialized with "nil". :) Best, Marcel -- View this message in context: http://forum.world.st/compiler-whitewash-tp4785831p4786264.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From eliot.miranda at gmail.com Thu Oct 23 18:11:25 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu Oct 23 18:11:28 2014 Subject: [squeak-dev] Re: compiler whitewash In-Reply-To: <1414087384949-4786264.post@n4.nabble.com> References: <1414081246004-4786244.post@n4.nabble.com> <1414087334762-4786263.post@n4.nabble.com> <1414087384949-4786264.post@n4.nabble.com> Message-ID: On Thu, Oct 23, 2014 at 11:03 AM, Marcel Taeumel < marcel.taeumel@student.hpi.uni-potsdam.de> wrote: > Some addon: I personally think that all variables are initialized with > "nil". > :) > Yes they are, and its one of the nice guarantees that Smalltalk makes that all variables are initialized either to nil or, in non-object data to 0 or Character value: 0. But the compiler can't in general tell whether a reference to a variable before it is assigned to is a mistake or not. For example in this: | t | self doSomethingWith: t the compiler can't know whether t is being used correctly or not ever. It is pointless for the compiler to try and analyse any relevant implementations of doSomethingWith: looking for e.g. ifNil: guards since doSomethingWith: can be redefined. Marcel, do you have some concrete criteria for squashing the warning in certain cases? If you have a good set of criteria we can implement them, otherwise I think we have to accept the inaccuracy of the warning. > Best, > Marcel > > > > -- > View this message in context: > http://forum.world.st/compiler-whitewash-tp4785831p4786264.html > Sent from the Squeak - Dev mailing list archive at Nabble.com. > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/296cda9d/attachment.htm From edgardec2005 at gmail.com Thu Oct 23 18:58:39 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Thu Oct 23 18:58:45 2014 Subject: [squeak-dev] Swiki in 4.5 running on box4 In-Reply-To: <50DE496C-F18E-444D-BF00-BFE11D2C1D46@gmail.com> Message-ID: -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/9fdfcedc/attachment.htm From maxleske at gmail.com Thu Oct 23 19:40:51 2014 From: maxleske at gmail.com (Max Leske) Date: Thu Oct 23 19:40:55 2014 Subject: [squeak-dev] Run Spur run!! Message-ID: <27384AD4-BECF-40ED-86AF-0830F4074545@gmail.com> For those of you who missed this on IRC: henriksp: estebanlm: Care to run a small bench Cog vs Spur for me? [3:32pm] henriksp: int := ZnUTF8Encoder new. [3:32pm] henriksp: [int decodeBytes:#[67 97 115 104 44 32 108 105 107 101 32 226 130 172 44 32 105 115 32 107 105 110 103 0]] bench. [3:32pm] henriksp: had a 16x speedup with assembly implementation vs Cog, if it's 8x vs Spur, that's just really impressive [3:44pm] Craig left the chat room. (Quit: Leaving.) [3:53pm] Craig joined the chat room. [4:08pm] VitamineD joined the chat room. [4:20pm] estebanlm: checking [4:21pm] estebanlm: Cog: 167,000 per second. [4:22pm] estebanlm: Cog[Spur]: 289,000 per second. [4:23pm] estebanlm: henriksp: ping [4:33pm] tinchodias left the chat room. (Ping timeout: 245 seconds) [4:33pm] tinchodias joined the chat room. [4:34pm] henriksp: 70% more work done, nice! [5:09pm] Yay! :) From brasspen at gmail.com Thu Oct 23 20:23:37 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Thu Oct 23 20:23:43 2014 Subject: [squeak-dev] Swiki in 4.5 running on box4 In-Reply-To: References: Message-ID: > On Oct 23, 2014, at 2:58 PM, Edgar J. De Cleene wrote: > > n 10/23/14, 11:03 AM, "Chris Cunnington" wrote: > >> http://box4.squeak.org:8080 >> >> I?ve got Swiki working in 4.5 running on box4. I intend next week to create a swiki account for it on box4, run it under daemontools, and copy over the ?swiki" content directory from box2 to box4. >> >> Chris >> >> >> (Installer ss) >> project: 'KomHttpServer'; >> install: 'KomServices-lr.21'; >> install: 'DynamicBindings-lr.13'; >> install: 'KomHttpServer-DwightManhertz.67'. >> (Installer ss3) >> project: 'SqueakServices'; >> install: 'Swiki'. >> ComSwikiLauncher openAsMorph. >> >> Excellent !! >> I check the install on FunSqueak and add if work >> >> Thanks !! >> >> >> Fails to load into 4.6 as designed. >> Loads into 4.5 all in one, but http://localhost:8888/ gives me >> > Internal Server Error > Key not found: default Yea, the ?default? key in the dictionary of possible content is nil. As is the dictionary. ComSwiki is a file server. And you don?t have any files. If you want to make it work in localhost, then go here: http://wiki.squeak.org/swiki/16 Download the OneOfTheseDays.zip. Find the directory called ?swiki?. Copy that into a directory of a fresh 4.5 image and install with the Installer script. Then use the ComSwikiLauncher. Then it should work. swiki?>default?>files?>defaultScheme?>comSwiki.gif swiki?>ani swiki?>refs See what I mean? And if you do that and it doesn?t work, then you should ?SwikiShelf allInstances? and see if you have any content in the image. Try this: SwikiShelf new name: 'swiki'; storage: (XmlSwikiStorage fromDir: (FileDirectory default directoryNamed: 'swiki')); load; yourself. The ComSwikiLauncher starts it?s process with: SwikiModule class >>#swikiWebServer If all that doesn?t give you the basic Swiki in localhost:[80|8080|8888|8000] then I?ll be surprised. I can?t speak for 4.6, as no such thing has been released. I?m happy you want to run it in localhost. I thought people would find this stuff pretty dull. Chris > > KomHttpServer/7.1.3 (Mac OS) Server at 'localhost' Port 8888 > > I hacked for stop with same error in 4.6 > > Seems SwikiShelf don?t was iniatilized s should be. > > Any advice ? > > Thanks in advance > > Edgar > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141023/5349e16e/attachment.htm From marcel.taeumel at student.hpi.uni-potsdam.de Thu Oct 23 20:53:54 2014 From: marcel.taeumel at student.hpi.uni-potsdam.de (Marcel Taeumel) Date: Thu Oct 23 20:56:44 2014 Subject: [squeak-dev] Re: compiler whitewash In-Reply-To: References: <1414081246004-4786244.post@n4.nabble.com> <1414087334762-4786263.post@n4.nabble.com> <1414087384949-4786264.post@n4.nabble.com> Message-ID: <1414097634084-4786310.post@n4.nabble.com> Hmm... I agree that you cannot easily analyse statically some called method and make sense out of it considering the initialization of its arguments/receiver. But what about: | x | ... [x notNil] whileTrue: [ ... ... ifTrue: [x := #foobar]]. ... In this case, the initialization is kind of deferred in the very same method. Maybe I wrote bad Smalltalk code, but I had this several times. Finding some object in a complex structure or so... So this could be detected, right? :) [It is not that I am really that annoyed by these compiler warnings because I made them non-modal in my tools.] Best, Marcel -- View this message in context: http://forum.world.st/compiler-whitewash-tp4785831p4786310.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From marcel.taeumel at student.hpi.uni-potsdam.de Thu Oct 23 20:54:43 2014 From: marcel.taeumel at student.hpi.uni-potsdam.de (Marcel Taeumel) Date: Thu Oct 23 20:57:34 2014 Subject: [squeak-dev] Re: compiler whitewash In-Reply-To: <1414097634084-4786310.post@n4.nabble.com> References: <1414081246004-4786244.post@n4.nabble.com> <1414087334762-4786263.post@n4.nabble.com> <1414087384949-4786264.post@n4.nabble.com> <1414097634084-4786310.post@n4.nabble.com> Message-ID: <1414097683829-4786311.post@n4.nabble.com> I meant: | x | ... [x isNil] whileTrue: [ ... ... ifTrue: [x := #foobar]]. ... -- View this message in context: http://forum.world.st/compiler-whitewash-tp4785831p4786311.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From edgardec2005 at gmail.com Thu Oct 23 22:51:53 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Thu Oct 23 22:52:02 2014 Subject: [squeak-dev] Swiki in 4.5 running on box4 In-Reply-To: Message-ID: On 10/23/14, 5:23 PM, "Chris Cunnington" wrote: > I f all that doesn?t give you the basic Swiki in localhost:[80|8080|8888|8000] then I?ll be surprised. > No surprise, is running now and I learn a lot. > > I can?t speak for 4.6, as no such thing has been released. No, but hard testing on FunSqueak let's us more learning. > I?m happy you want to run it in localhost. I thought people would find this > stuff pretty dull. I develop on newer Macs and when I think is ready to web put into some my G4's Right now I have www.squeakros.org User: visita pass: (empty) Is a experiment which takes squeak swiki and convert html files to.obj format http://190.189.179.48:9090/news shows last post or pages. Uses external .js like bootstrap-3.2.0 reveal.js-2.6.2 tinymce > Chris Thanks, thanks, thanks Edgar From list at afceurope.com Fri Oct 24 08:41:47 2014 From: list at afceurope.com (Annick Fron) Date: Fri Oct 24 08:41:53 2014 Subject: [Pharo-users] [squeak-dev] Using libraries in FFI In-Reply-To: References: <6149FD93-7682-487C-8A96-1D07ECA78370@afceurope.com> <27481657-8A8D-4350-A645-FF722E600386@gmail.com> <476D3881-5167-43E9-AC8E-04AC07E91312@afceurope.com> Message-ID: Thank you ! I will try that. Annick Le 23 oct. 2014 ? 17:49, Eliot Miranda a ?crit : > > > On Thu, Oct 23, 2014 at 8:46 AM, Eliot Miranda wrote: > Hi Annick, > > On Wed, Oct 22, 2014 at 5:45 AM, Annick Fron wrote: > Hi Eliot, > > My problem is not with the VM, my problem is with my own library that I connect to through FFI. > I know where the libraries are ! > > I have tried to add them in /etc/ld.so.conf.d , that does not work. > I have tried export LD_LIBRARY_PATH, but somehow it erases some libraries needed by pharo. > > But if you use the script I include with my VMs it won't erase. It extends LD_LIBRARY_PATH. Find an example attached. > > Here's the operative line (the last one). PLUGINS is the directory containing VM plugins, SVMLLP is "Smalltalk VM LD_LIBRARY_PATH" and specifies the directories containing the C libraries the VM depends on (C library, libuuid, etc). > > LD_LIBRARY_PATH=$PLUGINS:$SVMLLP:${LD_LIBRARY_PATH} exec "$BIN/squeak" "$@" > > > > I have done sudo ldconfig ... > > In fact I have one library that depends from another one. > In FFI I call one method which calls another method in the other library. > I have tried to create symbolics links in the directory ? > I have checked that nm gives the right symbol with the right type .. > > So I have no idea what to try now ! > > Annick > > Le 22 oct. 2014 ? 12:46, Eliot Miranda a ?crit : > > > Hi Annick, > > > > LD_LIBRARY_PATH should be set to point to the relevant directories, but this can be tricky as there is a lot if variation across Linux distros as to where libraries are kept. The squeak script that comes with the Cog VMs extends LD_LIBRARY_PATH, so if you know where your libraries are you can use the script to find the other libraries the VM needs (c library and plugins). > > > > Eliot (phone) > > > > On Oct 22, 2014, at 2:55 AM, Annick Fron wrote: > > > >> Hi, > >> > >> I am using a module in FFI which depends on a large library let?s say 10 dynamic .so files in a directory. > >> How is it possible to use this library without making all symbolic links ? > >> > >> Annick > > > > > > > > -- > best, > Eliot > > > > -- > best, > Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141024/726d444b/attachment.htm From list at afceurope.com Fri Oct 24 08:42:53 2014 From: list at afceurope.com (Annick Fron) Date: Fri Oct 24 08:42:59 2014 Subject: [Pharo-users] [squeak-dev] VM crash In-Reply-To: References: <9504224B-5B55-4743-9F20-1CEBCF696A3F@afceurope.com> Message-ID: <82257587-0F85-48C9-B0F4-2051963CDC1B@afceurope.com> Hi Eliot, It seems the problem comes from my C program called by FFI. Thank you Annick Le 23 oct. 2014 ? 06:01, Eliot Miranda a ?crit : > Hi Annick, > > On Wed, Oct 22, 2014 at 5:46 AM, Annick Fron wrote: > I have an error : > > ? don?t know how to derive register state from a ucontext_t on this platform ? > > That's just telling you that the VM doesn't know how to print the register state in a signal handler on this platform. What is your platform? What VM are you using? (vm -version) At least on Mac and x86 linux the VM /can/ do this, and hence print useful information when there's a crash. > > > Where could that come from ? > > Annick > > > > -- > best, > Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141024/564c5550/attachment.htm From commits at source.squeak.org Fri Oct 24 12:50:56 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 12:50:59 2014 Subject: [squeak-dev] The Trunk: KernelTests-dtl.279.mcz Message-ID: David T. Lewis uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-dtl.279.mcz ==================== Summary ==================== Name: KernelTests-dtl.279 Author: dtl Time: 24 October 2014, 8:50:13.619 am UUID: 970b63ad-d734-48f2-843e-a225a05df399 Ancestors: KernelTests-ul.278 Add test to document a VM bug (fixed) exposed when running 68002 image format. =============== Diff against KernelTests-ul.278 =============== Item was added: + ----- Method: ClassTest>>testChangeClassOf (in category 'testing') ----- + testChangeClassOf + "Exercise primitiveChangeClass (primitive 115) for a common use case. This should pass + for any Squeak image format (but failed for image format 68002 prior to VM fix)" + + self shouldnt: [Inspector new primitiveChangeClassTo: CompiledMethodInspector new] raise: Error! From commits at source.squeak.org Fri Oct 24 14:54:09 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 14:54:10 2014 Subject: [squeak-dev] The Inbox: Kernel-ul.881.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-ul.881.mcz ==================== Summary ==================== Name: Kernel-ul.881 Author: ul Time: 24 October 2014, 12:42:02.437 am UUID: 54327457-7cbf-4c59-876e-0661c7e1142e Ancestors: Kernel-ul.880 Semaphore changes: - added indexInExternalObjectsArray instance variable, and accessors - added #excessSignals =============== Diff against Kernel-ul.880 =============== Item was changed: LinkedList subclass: #Semaphore + instanceVariableNames: 'excessSignals indexInExternalObjectsArray' - instanceVariableNames: 'excessSignals' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Processes'! !Semaphore commentStamp: '' prior: 0! I provide synchronized communication of a single bit of information (a "signal") between Processes. A signal is sent by sending the message signal and received by sending the message wait. If no signal has been sent when a wait message is sent, the sending Process will be suspended until a signal is sent.! Item was added: + ----- Method: Semaphore>>excessSignals (in category 'accessing') ----- + excessSignals + + ^excessSignals! Item was added: + ----- Method: Semaphore>>indexInExternalObjectsArray (in category 'accessing') ----- + indexInExternalObjectsArray + + ^indexInExternalObjectsArray! Item was added: + ----- Method: Semaphore>>indexInExternalObjectsArray: (in category 'accessing') ----- + indexInExternalObjectsArray: anInteger + + indexInExternalObjectsArray := anInteger! From commits at source.squeak.org Fri Oct 24 14:55:50 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 14:55:53 2014 Subject: [squeak-dev] The Inbox: System-ul.686.mcz Message-ID: A new version of System was added to project The Inbox: http://source.squeak.org/inbox/System-ul.686.mcz ==================== Summary ==================== Name: System-ul.686 Author: ul Time: 24 October 2014, 3:33:38.886 am UUID: 541b7ffb-c492-417f-b8b1-2c9de93b76a6 Ancestors: System-dtl.685 Updated ExternalSemaphoreTable to provide faster registration, and give better support to the current users. Notable changes: - the table is a separate object instead of a few class side methods, but the API is still on the class side - #newExternalSemaphore, and #newExternalSemaphores: provide easy creation and registration of Semaphores - #unregisterExternalObjects: can unregister multiple objects faster - #externalObjects will return a copy of the externalObjectsArray - better scalability - the maxExternalSemaphores VM parameter will be incremented as the externalObjectsArray grows =============== Diff against System-dtl.685 =============== Item was changed: Object subclass: #ExternalSemaphoreTable + instanceVariableNames: 'semaphore externalObjectsArray freeSlotIndexes indexesByObjects' + classVariableNames: '' - instanceVariableNames: '' - classVariableNames: 'ProtectTable' poolDictionaries: '' category: 'System-Support'! + ExternalSemaphoreTable class + instanceVariableNames: 'current'! + !ExternalSemaphoreTable commentStamp: 'ul 10/24/2014 03:24' prior: 0! + I'm an enhanced version of JMM's ExternalSemaphoreTable. Despite the name I can store any object but nil. + I'm responsible for maintaining the externalObjectsArray, which can be found at slot 39 of Smalltalk specialObjectsArray. Manipulating the array directly is highly discouraged. + It's safe to use all class-side methods in the accessing category except for #clearExternalObjects - which should only be used during image startUp - and #current, because instance-side methods are not intented to be used by external code. + + If you'd like the create one or more new Semaphores and register them for external use, then you should use either #newExternalSemaphore or #newExternalSemaphores:. If you want to unregister more than one external objects at the same time, then #unregisterExternalObjects: is the method you're looking for. + + Implementation details: + I maintain a single instance (#current), which can automatically synchronize with externalObjectsArray. + All accesses are protected by the semaphore instance variable. + To ensure fast access, I keep track of the indexes of the external objects in the externalObjectArray. For Semaphores I their indexInExternalObjectsArray instance variable. For other objects I use my own indexesByObjects IdentityDictionary. The latter could work for all objects, but the former is faster, and easier to use. + To ensure fast insertion, I keep track of the free slots of the externalObjectsArray in the freeSlotIndexes OrderedCollection. The access pattern is LIFO to avoid unnecessary growth and reordering. + I can grow the externalObjectsArray (see #ensureFreeSlot), but I never shrink it. + + Original comment: - !ExternalSemaphoreTable commentStamp: '' prior: 0! By John M McIntosh johnmci@smalltalkconsulting.com This class was written to mange the external semaphore table. When I was writing a Socket test server I discovered various race conditions on the access to the externalSemaphore table. This new class uses class side methods to restrict access using a mutex semaphore. It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary Note that in Smalltalk recreateSpecialObjectsArray we still directly play with the table.! + ExternalSemaphoreTable class + instanceVariableNames: 'current'! Item was changed: ----- Method: ExternalSemaphoreTable class>>clearExternalObjects (in category 'accessing') ----- clearExternalObjects "Clear the array of objects that have been registered for use in non-Smalltalk code." + self current clearExternalObjects - ProtectTable critical: [Smalltalk specialObjectsArray at: 39 put: Array new]. ! Item was added: + ----- Method: ExternalSemaphoreTable class>>current (in category 'accessing') ----- + current + + ^current ifNil: [ + | newInstance | + newInstance := self new. + " Check again, because another process might have registered another instance. " + current ifNil: [ current := newInstance ] ]! Item was changed: ----- Method: ExternalSemaphoreTable class>>externalObjects (in category 'accessing') ----- externalObjects + "Return a copy of the externalObjectsArray." + + ^self current externalObjects! - ^ProtectTable critical: [Smalltalk specialObjectsArray at: 39].! Item was removed: - ----- Method: ExternalSemaphoreTable class>>initialize (in category 'initialize') ----- - initialize - ProtectTable := Semaphore forMutualExclusion! Item was added: + ----- Method: ExternalSemaphoreTable class>>newExternalSemaphore (in category 'accessing') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return it." + + ^self current newExternalSemaphore! Item was added: + ----- Method: ExternalSemaphoreTable class>>newExternalSemaphores: (in category 'accessing') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing them." + + ^self current newExternalSemaphores: count! Item was changed: ----- Method: ExternalSemaphoreTable class>>registerExternalObject: (in category 'accessing') ----- registerExternalObject: anObject + "Register the given object in the external objects array and return its index. If it is already there, just return its index." + + ^self current registerExternalObject: anObject! - ^ ProtectTable critical: [self safelyRegisterExternalObject: anObject] - ! Item was added: + ----- Method: ExternalSemaphoreTable class>>reset (in category 'accessing') ----- + reset + + current := nil! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyRegisterExternalObject: (in category 'accessing') ----- - safelyRegisterExternalObject: anObject - "Register the given object in the external objects array and return its index. If it is already there, just return its index." - - | objects firstEmptyIndex obj sz newObjects | - objects := Smalltalk specialObjectsArray at: 39. - - "find the first empty slot" - firstEmptyIndex := 0. - 1 to: objects size do: [:i | - obj := objects at: i. - obj == anObject ifTrue: [^ i]. "object already there, just return its index" - (obj == nil and: [firstEmptyIndex = 0]) ifTrue: [firstEmptyIndex := i]]. - - "if no empty slots, expand the array" - firstEmptyIndex = 0 ifTrue: [ - sz := objects size. - newObjects := objects species new: sz + 20. "grow linearly" - newObjects replaceFrom: 1 to: sz with: objects startingAt: 1. - firstEmptyIndex := sz + 1. - Smalltalk specialObjectsArray at: 39 put: newObjects. - objects := newObjects]. - - objects at: firstEmptyIndex put: anObject. - ^ firstEmptyIndex - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyUnregisterExternalObject: (in category 'accessing') ----- - safelyUnregisterExternalObject: anObject - "Unregister the given object in the external objects array. Do nothing if it isn't registered. - JMM change to return if we clear the element, since it should only appear once in the array" - - | objects | - anObject ifNil: [^ self]. - objects := Smalltalk specialObjectsArray at: 39. - 1 to: objects size do: [:i | - (objects at: i) == anObject ifTrue: - [objects at: i put: nil. - ^self]]. - ! Item was changed: ----- Method: ExternalSemaphoreTable class>>unregisterExternalObject: (in category 'accessing') ----- unregisterExternalObject: anObject + "Unregister the given object from the external objects array. Do nothing if it isn't registered." + + self current unregisterExternalObject: anObject! - ProtectTable critical: [self safelyUnregisterExternalObject: anObject] - ! Item was added: + ----- Method: ExternalSemaphoreTable class>>unregisterExternalObjects: (in category 'accessing') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + self current unregisterExternalObjects: aCollection! Item was added: + ----- Method: ExternalSemaphoreTable>>clearExternalObjects (in category 'accessing') ----- + clearExternalObjects + "Clear the array of objects that have been registered for use in non-Smalltalk code." + + semaphore critical: [ + Smalltalk specialObjectsArray at: 39 put: Array new. + self synchronizeExternalObjectsArrayAndForceUpdate: false ]! Item was added: + ----- Method: ExternalSemaphoreTable>>ensureFreeSlot (in category 'private') ----- + ensureFreeSlot + "Make sure there's at least one free slot." + + | oldSize newSize newExternalObjectsArray specialObjectsArray | + freeSlotIndexes isEmpty ifFalse: [ ^self ]. + oldSize := externalObjectsArray size. + newSize := oldSize + 20. "Linear growth is not really a problem, because we never shrink the array." + newExternalObjectsArray := externalObjectsArray species new: newSize. + newExternalObjectsArray + replaceFrom: 1 + to: oldSize + with: externalObjectsArray + startingAt: 1. + specialObjectsArray := Smalltalk specialObjectsArray. + (specialObjectsArray at: 39) == externalObjectsArray + ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + ensureFreeSlot ]. + specialObjectsArray at: 39 put: newExternalObjectsArray. + externalObjectsArray := newExternalObjectsArray. + oldSize + 1 to: newSize do: [ :each | + freeSlotIndexes add: each ]. + Smalltalk maxExternalSemaphores ifNotNil: [ :maxExternalSemaphores | + "Make sure that those new external semaphores can be signaled by the VM. This is not entirely safe, but not incrementing at all is worse." + newSize > maxExternalSemaphores ifTrue: [ + Smalltalk maxExternalSemaphores: newSize ] ] + + ! Item was added: + ----- Method: ExternalSemaphoreTable>>externalObjects (in category 'accessing') ----- + externalObjects + "Return a copy of the externalObjectsArray." + + ^semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + externalObjectsArray copy ]! Item was added: + ----- Method: ExternalSemaphoreTable>>externalObjectsArray: (in category 'private') ----- + externalObjectsArray: anArray + "Update the index mapping using anArray as the new externalObjectsArray." + + externalObjectsArray := anArray. + freeSlotIndexes := OrderedCollection new: externalObjectsArray size. + indexesByObjects := IdentityDictionary new. + 1 to: externalObjectsArray size do: [ :index | + (anArray at: index) + ifNil: [ freeSlotIndexes add: index ] + ifNotNil: [ :object | + object class == Semaphore + ifTrue: [ object indexInExternalObjectsArray: index ] + ifFalse: [ indexesByObjects at: object put: index ] ] ]! Item was added: + ----- Method: ExternalSemaphoreTable>>initialize (in category 'initialize-release') ----- + initialize + + semaphore := Semaphore forMutualExclusion! Item was added: + ----- Method: ExternalSemaphoreTable>>newExternalSemaphore (in category 'accessing') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return it." + + | newSemaphore | + newSemaphore := Semaphore new. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterNewExternalSemaphore: newSemaphore ]. + ^newSemaphore! Item was added: + ----- Method: ExternalSemaphoreTable>>newExternalSemaphores: (in category 'accessing') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing them." + + | semaphores | + semaphores := Array new: count. + 1 to: count do: [ :index | + semaphores at: index put: Semaphore new ]. + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + semaphores do: [ :newSemaphore | + self safelyRegisterNewExternalSemaphore: newSemaphore ] ]. + ^semaphores! Item was added: + ----- Method: ExternalSemaphoreTable>>registerExternalObject: (in category 'accessing') ----- + registerExternalObject: anObject + "Register the given object in the external objects array and return its index. If it is already there, just return its index." + + anObject ifNil: [ ^nil ]. + ^semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyRegisterExternalObject: (in category 'private') ----- + safelyRegisterExternalObject: anObject + + | index | + anObject class == Semaphore ifTrue: [ ^self safelyRegisterExternalSemaphore: anObject ]. + (index := indexesByObjects at: anObject ifAbsent: nil) ifNotNil: [ + (externalObjectsArray at: index) == anObject ifTrue: [ ^index ]. + "indexesByObjects is out of sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterExternalObject: anObject ]. + self ensureFreeSlot. + index := freeSlotIndexes removeLast. + (externalObjectsArray at: index) ifNotNil: [ + "Free slot is not empty. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterExternalObject: anObject ]. + externalObjectsArray at: index put: anObject. + indexesByObjects at: anObject put: index. + ^index! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyRegisterExternalSemaphore: (in category 'private') ----- + safelyRegisterExternalSemaphore: aSemaphore + + aSemaphore indexInExternalObjectsArray ifNotNil: [ :index | + (externalObjectsArray at: index) == aSemaphore ifTrue: [ ^index ]. + aSemaphore indexInExternalObjectsArray: nil. "Avoid infinite recursion." + "We can be out of sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterExternalSemaphore: aSemaphore ]. + ^self safelyRegisterNewExternalSemaphore: aSemaphore! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyRegisterNewExternalSemaphore: (in category 'private') ----- + safelyRegisterNewExternalSemaphore: aSemaphore + + | index | + self ensureFreeSlot. + index := freeSlotIndexes removeLast. + (externalObjectsArray at: index) ifNotNil: [ + "Free slot is not empty. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterNewExternalSemaphore: aSemaphore ]. + aSemaphore indexInExternalObjectsArray: index. + externalObjectsArray at: index put: aSemaphore. + ^index! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyUnregisterExternalObject: (in category 'private') ----- + safelyUnregisterExternalObject: anObject + + anObject class == Semaphore ifTrue: [ ^self safelyUnregisterExternalSemaphore: anObject ]. + (indexesByObjects removeKey: anObject ifAbsent: nil) + ifNotNil: [ :index | + (externalObjectsArray at: index) == anObject ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]. + externalObjectsArray at: index put: nil. + freeSlotIndexes add: index ] + ifNil: [ + "Check if we're just out of sync." + (externalObjectsArray instVarsInclude: anObject) ifFalse: [ ^self ]. + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyUnregisterExternalSemaphore: (in category 'private') ----- + safelyUnregisterExternalSemaphore: aSemaphore + + aSemaphore indexInExternalObjectsArray + ifNotNil: [ :index | + aSemaphore indexInExternalObjectsArray: nil. "Remove the index to avoid infinite recursion." + (externalObjectsArray at: index) == aSemaphore ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalSemaphore: aSemaphore ]. + externalObjectsArray at: index put: nil. + freeSlotIndexes add: index ] + ifNil: [ + "Check if we're just out of sync." + (externalObjectsArray instVarsInclude: aSemaphore) ifFalse: [ ^self ]. + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalSemaphore: aSemaphore ]! Item was added: + ----- Method: ExternalSemaphoreTable>>synchronizeExternalObjectsArrayAndForceUpdate: (in category 'private') ----- + synchronizeExternalObjectsArrayAndForceUpdate: forceUpdate + + | actualExternalObjectsArray | + actualExternalObjectsArray := Smalltalk specialObjectsArray at: 39. + (actualExternalObjectsArray == externalObjectsArray and: [ forceUpdate not ]) + ifTrue: [ ^self ]. + self externalObjectsArray: actualExternalObjectsArray! Item was added: + ----- Method: ExternalSemaphoreTable>>unregisterExternalObject: (in category 'accessing') ----- + unregisterExternalObject: anObject + "Unregister the given object from the external objects array. Do nothing if it isn't registered." + + anObject ifNil: [ ^self ]. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalSemaphoreTable>>unregisterExternalObjects: (in category 'accessing') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + aCollection do: [ :each | + each ifNotNil: [ + self safelyUnregisterExternalObject: each ] ] ]! Item was changed: ----- Method: SmalltalkImage>>snapshot:andQuit:withExitCode:embedded: (in category 'snapshot and quit') ----- snapshot: save andQuit: quit withExitCode: exitCode embedded: embeddedFlag "Mark the changes file and close all files as part of #processShutdownList. If save is true, save the current state of this Smalltalk in the image file. If quit is true, then exit to the outer OS shell. If exitCode is not nil, then use it as exit code. The latter part of this method runs when resuming a previously saved image. This resume logic checks for a document file to process when starting up." | resuming msg | Object flushDependents. Object flushEvents. (SourceFiles at: 2) ifNotNil:[ msg := String streamContents: [ :s | s nextPutAll: '----'; nextPutAll: (save ifTrue: [ quit ifTrue: [ 'QUIT' ] ifFalse: [ 'SNAPSHOT' ] ] ifFalse: [quit ifTrue: [ 'QUIT/NOSAVE' ] ifFalse: [ 'NOP' ]]); nextPutAll: '----'; print: Date dateAndTimeNow; space; nextPutAll: (FileDirectory default localNameFor: self imageName); nextPutAll: ' priorSource: '; print: LastQuitLogPosition ]. self assureStartupStampLogged. save ifTrue: [ LastQuitLogPosition := (SourceFiles at: 2) setToEnd; position ]. self logChange: msg. Transcript cr; show: msg ]. Smalltalk processShutDownList: quit. Cursor write show. save ifTrue: [resuming := embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming := false]. quit & (resuming == false) ifTrue: [ exitCode ifNil: [ self quitPrimitive ] ifNotNil: [ self quitPrimitive: exitCode ] ]. Cursor normal show. Smalltalk setGCParameters. + resuming == true ifTrue: [ExternalSemaphoreTable clearExternalObjects]. - resuming == true ifTrue: [Smalltalk clearExternalObjects]. Smalltalk processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self recordStartupStamp]. Project current wakeUpTopWindow. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! From commits at source.squeak.org Fri Oct 24 14:56:55 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 14:56:57 2014 Subject: [squeak-dev] The Inbox: Sound-ul.39.mcz Message-ID: A new version of Sound was added to project The Inbox: http://source.squeak.org/inbox/Sound-ul.39.mcz ==================== Summary ==================== Name: Sound-ul.39 Author: ul Time: 24 October 2014, 3:35:35.769 am UUID: 1213f069-b625-4066-9ee8-8ea1619f2af0 Ancestors: Sound-nice.38 - use ExternalSemaphoreTable directly =============== Diff against Sound-nice.38 =============== Item was changed: ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') ----- startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound "Start the sound player process. Terminate the old process, if any." "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false" self stopPlayerProcess. aSound ifNil:[ActiveSounds := OrderedCollection new] ifNotNil:[ActiveSounds := OrderedCollection with: aSound]. Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4. LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize]. PlayerSemaphore := Semaphore forMutualExclusion. SamplingRate := samplesPerSecond. Stereo := stereoFlag. + ReadyForBuffer := ExternalSemaphoreTable newExternalSemaphore. - ReadyForBuffer := Semaphore new. SoundSupported := true. "Assume so" UseReadySemaphore := true. "set to false if ready semaphore not supported by VM" self primSoundStartBufferSize: Buffer stereoSampleCount rate: samplesPerSecond stereo: Stereo + semaIndex: ReadyForBuffer indexInExternalObjectsArray. - semaIndex: (Smalltalk registerExternalObject: ReadyForBuffer). "Check if sound start prim was successful" + SoundSupported ifFalse:[ + ExternalSemaphoreTable unregisterExternalObject: ReadyForBuffer. + ^self]. - SoundSupported ifFalse:[^self]. UseReadySemaphore ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess] ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess]. UseReverb ifTrue: [self startReverb]. PlayerProcess priority: Processor userInterruptPriority. PlayerProcess resume.! Item was changed: ----- Method: SoundPlayer class>>stopPlayerProcess (in category 'player process') ----- stopPlayerProcess "Stop the sound player process." "SoundPlayer stopPlayerProcess" (PlayerProcess == nil or:[PlayerProcess == Processor activeProcess]) ifFalse:[PlayerProcess terminate]. PlayerProcess := nil. self primSoundStop. ActiveSounds := OrderedCollection new. Buffer := nil. PlayerSemaphore := Semaphore forMutualExclusion. ReadyForBuffer ifNotNil: + [ExternalSemaphoreTable unregisterExternalObject: ReadyForBuffer]. - [Smalltalk unregisterExternalObject: ReadyForBuffer]. ReadyForBuffer := nil. ! Item was changed: ----- Method: SoundRecorder>>startRecording (in category 'recording controls') ----- startRecording "Turn of the sound input driver and start the recording process. Initially, recording is paused." - | semaIndex | recordLevel ifNil: [recordLevel := 0.5]. "lazy initialization" CanRecordWhilePlaying ifFalse: [SoundPlayer shutDown]. recordProcess ifNotNil: [self stopRecording]. paused := true. meteringBuffer := SoundBuffer newMonoSampleCount: 1024. meterLevel := 0. self allocateBuffer. + bufferAvailableSema := ExternalSemaphoreTable newExternalSemaphore. - bufferAvailableSema := Semaphore new. - semaIndex := Smalltalk registerExternalObject: bufferAvailableSema. self primStartRecordingDesiredSampleRate: samplingRate asInteger stereo: stereo + semaIndex: bufferAvailableSema indexInExternalObjectsArray. - semaIndex: semaIndex. RecorderActive := true. samplingRate := self primGetActualRecordingSampleRate. self primSetRecordLevel: (1000.0 * recordLevel) asInteger. recordProcess := [self recordLoop] newProcess. recordProcess priority: Processor userInterruptPriority. + recordProcess resume! - recordProcess resume. - ! Item was changed: ----- Method: SoundRecorder>>stopRecording (in category 'recording controls') ----- stopRecording "Stop the recording process and turn of the sound input driver." recordProcess ifNotNil: [recordProcess terminate]. recordProcess := nil. self primStopRecording. RecorderActive := false. + ExternalSemaphoreTable unregisterExternalObject: bufferAvailableSema. - Smalltalk unregisterExternalObject: bufferAvailableSema. ((currentBuffer ~~ nil) and: [nextIndex > 1]) ifTrue: [self emitPartialBuffer]. self initializeRecordingState. ! From commits at source.squeak.org Fri Oct 24 14:57:30 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 14:57:33 2014 Subject: [squeak-dev] The Inbox: Network-ul.153.mcz Message-ID: A new version of Network was added to project The Inbox: http://source.squeak.org/inbox/Network-ul.153.mcz ==================== Summary ==================== Name: Network-ul.153 Author: ul Time: 24 October 2014, 3:38:28.874 am UUID: 3e87044d-a929-4570-bba7-77fdb7d2bd41 Ancestors: Network-ul.152 - use the new ExternalSemaphoreTable API - unifed socket initialization - unregister ResolverSemaphore when the network initialization fails =============== Diff against Network-ul.152 =============== Item was changed: ----- Method: NetNameResolver class>>initializeNetwork (in category 'network initialization') ----- initializeNetwork "Initialize the network drivers and record the semaphore to be used by the resolver. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails." "NetNameResolver initializeNetwork" - | semaIndex | self resolverStatus = ResolverUninitialized ifFalse: [^HaveNetwork := true]. "network is already initialized" HaveNetwork := false. "in case abort" + ResolverSemaphore := ExternalSemaphoreTable newExternalSemaphore. - ResolverSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: ResolverSemaphore. "result is nil if network initialization failed, self if it succeeds" + (self primInitializeNetwork: ResolverSemaphore indexInExternalObjectsArray) + ifNil: [ + ExternalSemaphoreTable unregisterExternalObject: ResolverSemaphore. + ResolverSemaphore := nil. + NoNetworkError signal: 'failed network initialization'] - (self primInitializeNetwork: semaIndex) - ifNil: [NoNetworkError signal: 'failed network initialization'] ifNotNil: [HaveNetwork := true]. + self initializeOldNetworkFlag! - self initializeOldNetworkFlag - ! Item was changed: ----- Method: Socket>>acceptFrom: (in category 'initialize-destroy') ----- acceptFrom: aSocket "Initialize a new socket handle from an accept call" - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ + self + primAcceptFrom: aSocket socketHandle + receiveBufferSize: 8000 + sendBufSize: 8000 + semaIndex: semaphore indexInExternalObjectsArray + readSemaIndex: readSemaphore indexInExternalObjectsArray + writeSemaIndex: writeSemaphore indexInExternalObjectsArray ]! - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primAcceptFrom: aSocket socketHandle - receiveBufferSize: 8000 - sendBufSize: 8000 - semaIndex: semaIndex - readSemaIndex: readSemaIndex - writeSemaIndex: writeSemaIndex. - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>destroy (in category 'initialize-destroy') ----- destroy "Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil)." socketHandle ifNotNil: [ self isValid ifTrue: [ self primSocketDestroy: socketHandle ]. + ExternalSemaphoreTable unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore }. - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. socketHandle := nil. readSemaphore := writeSemaphore := semaphore := nil. self unregister ]! Item was changed: ----- Method: Socket>>finalize (in category 'finalization') ----- finalize + self primSocketDestroyGently: socketHandle. + ExternalSemaphoreTable unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore } - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. ! Item was changed: ----- Method: Socket>>initialize: (in category 'initialize-destroy') ----- initialize: socketType "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: 0 type: socketType receiveBufferSize: 8000 sendBufSize: 8000 + semaIndex: semaphore indexInExternalObjectsArray + readSemaIndex: readSemaphore indexInExternalObjectsArray + writeSemaIndex: writeSemaphore indexInExternalObjectsArray ]! - semaIndex: semaIndex - readSemaIndex: readSemaIndex - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>initialize:family: (in category 'initialize-destroy') ----- initialize: socketType family: family "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + NetNameResolver useOldNetwork ifTrue: [ ^self initialize: socketType ]. + self initializeSocketHandleUsing: [ - NetNameResolver useOldNetwork ifTrue: [^self initialize: socketType]. - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: family type: socketType receiveBufferSize: 8000 sendBufSize: 8000 + semaIndex: semaphore indexInExternalObjectsArray + readSemaIndex: readSemaphore indexInExternalObjectsArray + writeSemaIndex: writeSemaphore indexInExternalObjectsArray ]! - semaIndex: semaIndex - readSemaIndex: readSemaIndex - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was added: + ----- Method: Socket>>initializeSocketHandleUsing: (in category 'initialize-destroy') ----- + initializeSocketHandleUsing: aBlock + "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." + + | semaphores | + semaphores := ExternalSemaphoreTable newExternalSemaphores: 3. + semaphore := semaphores at: 1. + readSemaphore := semaphores at: 2. + writeSemaphore := semaphores at: 3. + (socketHandle := aBlock value) + ifNotNil: [ self register ] + ifNil: [ + "socket creation failed" + semaphore := readSemaphore := writeSemaphore := nil. + ExternalSemaphoreTable unregisterExternalObjects: semaphores ]! From commits at source.squeak.org Fri Oct 24 14:57:55 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 14:57:58 2014 Subject: [squeak-dev] The Inbox: Files-ul.139.mcz Message-ID: A new version of Files was added to project The Inbox: http://source.squeak.org/inbox/Files-ul.139.mcz ==================== Summary ==================== Name: Files-ul.139 Author: ul Time: 24 October 2014, 3:50:04.3 am UUID: 521172db-9620-40a3-94c4-79891c268a17 Ancestors: Files-eem.138 - use the new ExternalSemaphoreTable API =============== Diff against Files-eem.138 =============== Item was changed: ----- Method: AsyncFile>>close (in category 'as yet unclassified') ----- close fileHandle ifNil: [^ self]. "already closed" self primClose: fileHandle. + ExternalSemaphoreTable unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: semaphore. semaphore := nil. fileHandle := nil. ! Item was changed: ----- Method: AsyncFile>>open:forWrite: (in category 'as yet unclassified') ----- open: fullFileName forWrite: aBoolean "Open a file of the given name, and return a handle for that file. Answer the receiver if the primitive succeeds, nil otherwise. If openForWrite is true, then: if there is no existing file with this name, then create one else open the existing file in read-write mode otherwise: if there is an existing file with this name, then open it read-only else answer nil." "Note: if an exisiting file is opened for writing, it is NOT truncated. If truncation is desired, the file should be deleted before being opened as an asynchronous file." "Note: On some platforms (e.g., Mac), a file can only have one writer at a time." - | semaIndex | name := fullFileName. writeable := aBoolean. + semaphore := ExternalSemaphoreTable newExternalSemaphore. + fileHandle := self + primOpen: name asVmPathName + forWrite: writeable + semaIndex: semaphore indexInExternalObjectsArray. - semaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: semaIndex. fileHandle ifNil: [ + ExternalSemaphoreTable unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: semaphore. semaphore := nil. ^ nil]. ! Item was changed: ----- Method: StandardFileStream>>post:target:url:ifError: (in category 'browser requests') ----- post: data target: target url: url ifError: errorBlock "Post data to the given URL. The returned file stream contains the reply of the server. If Squeak is not running in a browser evaluate errorBlock" + | semaphore request result | - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + semaphore := ExternalSemaphoreTable newExternalSemaphore. + request := self + primURLPost: url + target: target data: data + semaIndex: semaphore indexInExternalObjectsArray. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLPost: url target: target data: data semaIndex: index. request == nil ifTrue:[ + ExternalSemaphoreTable unregisterExternalObject: semaphore. - - Smalltalk unregisterExternalObject: sema. ^errorBlock value. ] ifFalse:[ + [semaphore wait. "until something happens" - [sema wait. "until something happens" result := self primURLRequestState: request. result == nil] whileTrue. result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. ]. + ExternalSemaphoreTable unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: sema. fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. self enableReadBuffering ! Item was changed: ----- Method: StandardFileStream>>requestURL:target:ifError: (in category 'browser requests') ----- requestURL: url target: target ifError: errorBlock "Request to go to the target for the given URL. If Squeak is not running in a browser evaluate errorBlock" + | semaphore request result | - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + semaphore := ExternalSemaphoreTable newExternalSemaphore. + request := self + primURLRequest: url + target: target + semaIndex: semaphore indexInExternalObjectsArray. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url target: target semaIndex: index. request == nil ifTrue:[ + ExternalSemaphoreTable unregisterExternalObject: semaphore. - - Smalltalk unregisterExternalObject: sema. ^errorBlock value. ] ifFalse:[ + [semaphore wait. "until something happens" - [sema wait. "until something happens" result := self primURLRequestState: request. result == nil] whileTrue. self primURLRequestDestroy: request. ]. + ExternalSemaphoreTable unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: sema. fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. self enableReadBuffering ! Item was changed: ----- Method: StandardFileStream>>requestURLStream:ifError: (in category 'browser requests') ----- requestURLStream: url ifError: errorBlock "Request a FileStream for the given URL. If Squeak is not running in a browser evaluate errorBlock" "FileStream requestURLStream:'http://www.squeak.org'" + | semaphore request result | - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + semaphore := ExternalSemaphoreTable newExternalSemaphore. + request := self + primURLRequest: url + semaIndex: semaphore indexInExternalObjectsArray. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url semaIndex: index. request == nil ifTrue:[ + ExternalSemaphoreTable unregisterExternalObject: semaphore. - - Smalltalk unregisterExternalObject: sema. ^errorBlock value. ] ifFalse:[ + [semaphore wait. "until something happens" - [sema wait. "until something happens" result := self primURLRequestState: request. result == nil] whileTrue. result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. ]. + ExternalSemaphoreTable unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: sema. fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. self enableReadBuffering ! From commits at source.squeak.org Fri Oct 24 14:58:17 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 14:58:22 2014 Subject: [squeak-dev] The Inbox: Kernel-ul.882.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-ul.882.mcz ==================== Summary ==================== Name: Kernel-ul.882 Author: ul Time: 24 October 2014, 3:48:50.902 am UUID: c159ed79-5312-47fa-8d80-2e5211a377bc Ancestors: Kernel-ul.881 - use ExternalSemaphoreTable instead of Smalltalk =============== Diff against Kernel-ul.881 =============== Item was changed: ----- Method: EventSensor>>shutDown (in category 'initialize') ----- shutDown + super shutDown. EventTicklerProcess ifNotNil: [ EventTicklerProcess terminate. EventTicklerProcess := nil. ]. + inputSemaphore ifNotNil:[ + ExternalSemaphoreTable unregisterExternalObject: inputSemaphore ]. - inputSemaphore ifNotNil:[Smalltalk unregisterExternalObject: inputSemaphore]. ! Item was changed: ----- Method: EventSensor>>startUp (in category 'initialize') ----- startUp "Run the I/O process" self initialize. + self primSetInputSemaphore: (ExternalSemaphoreTable registerExternalObject: inputSemaphore). - self primSetInputSemaphore: (Smalltalk registerExternalObject: inputSemaphore). super startUp. self installEventTickler. Smalltalk isMorphic ifTrue:[self flushAllButDandDEvents]. "Attempt to discover whether the input semaphore is actually being signaled." hasInputSemaphore := false. inputSemaphore initSignals. ! From leves at elte.hu Fri Oct 24 15:22:01 2014 From: leves at elte.hu (Levente Uzonyi) Date: Fri Oct 24 15:22:07 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: Message-ID: Thanks Bert. It turned out that my image was already broken when I tried to add an instance variable to Semaphore. I've finished the implementation and uploaded it to The Inbox. The following snippet will load it into an updated Trunk image: Installer mc http: 'source.squeak.org'; project: 'inbox'; package: 'Kernel-ul.881'; package: 'System-ul.686'; package: 'Kernel-ul.882'; package: 'Sound-ul.39'; package: 'Network-ul.153'; package: 'Files-ul.139'; install I decided to go with the complex solution, which gives the best performance, and a simple API for Semaphores, but also has pretty good performance for any other object. And it's backwards compatible in almost all cases. Levente On Sun, 12 Oct 2014, Bert Freudenberg wrote: > On 12.10.2014, at 08:04, Levente Uzonyi wrote: > >> Hi, >> >> I found that the handling of external objects is suboptimal in the image, and I came up with some ideas to make it better. I have a working solution in my image, but it can be even better. >> >> It seems to me that only Semaphores are stored in the external objects array (slot 39 in the special objects array), but in practice any object can be stored there. Does it make sense to support objects of any other kind? If not, then the code could be simplified. > > Currently the VM uses the ExternalObjectsArray only for semaphores. Other objects use different mechanisms (e.g. SurfacePlugin for external forms). I'm not sure if there is a good use case for storing non-semaphores in ExternalObjectsArray, maybe ask on the vm-dev list? > >> I also thought that I'll create a special semaphore (ExternalSemaphore - >> which is a subclass of Semaphore) that knows its own index in the external objects array. This could be really handy for finding the object in the array, but the VM is not willing to signal these semaphores in the external objects array. I thought that this is because the VM doesn't know anything about this class. >> So I tried to change Semaphore itself, but after the change the VM refused to signal any semaphores in the external objects array. Changing the class back to the original didn't help either. Without looking at the VM code, I assumed that the VM will signal anything which has the class in the 19th slot of the special objects array, but that doesn't seem to be the case. >> Is there any way to make this (add an instatnce variable to Semaphore and still get signals from the VM, or use instances of a subclass of Semaphore there) work? > > The VM only checks for the exact class in slot 19, not for subclasses. Adding an inst var to Semaphore itself should be fine, but you cannot use a subclass without changing the VM. Are you sure you put the modified Semaphore class into SpecialObjectsArray after adding the inst var? > > - Bert - > > > > From brasspen at gmail.com Fri Oct 24 16:47:00 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Fri Oct 24 16:47:05 2014 Subject: [squeak-dev] editing the Squeak wiki XML file library Message-ID: https://www.dropbox.com/s/xs1gjsi93i4d7rn/pages.zip?dl=0 I was talking to Tim at CSV about the Squeak wiki and he was very interested in editing it. He has a number of ideas for pruning the Squeak wiki. As such, I provide here the entire Squeak wiki as it relates to its XML files. This is all the text content. There are no supporting files for images, code files, etc. It?s 22M if you want to download it and it opens to 6191 XML files. The latest number in box2 is 6199, so it?s almost complete. Updating the content is as easy as copying the eight missing files into your set. After describing the way the XML is laid out, Tim said: ?Well maybe we can just sed and grep away some of the pages.? Precisely. There is a caveat that you need to be aware of and Tim was aware of it: links to other pages. It?s not really a problem, I don?t think. Here?s why. Take for example a snippet from 6182.xml: !Introduction *2726* started out very useful and very popular. The links all have asterisks around them (i.e. *2726*). That?s not some pointer to an object. That?s a text reference to file named 2726.xml. Simple, right? The page formatter replaces that with the name of the file. A quick look tells me that 2726.xml is titled SqueakMap: SqueakMap SqueakMap is a tool used by the Squeak community The token is interpolated into 6182.xml when it?s formatted so the link appears as SqueakMap and it?s a hyperlink to the other file. All this to say, if Tim or others did want to edit this content, the only thing you need to be aware of before throwing out files is the numbers between the asterisks (i.e. *4444*). Say you wanted to delete 3333.xml (and it?s companion 3333.old), then you might want to do a sed/grep for *3333* over the balance of the files to look for links you have to account for. Perhaps create a script to erase those detected links in a clean way? If it?s a hyperlink in a sentence, then you?d need to replace *3333* with the token of 3333, so the sentence still read clearly. It would simply no longer be a hyperlink. So, editing this set of files is pretty trivial. I bet somebody wrote a program to create a graph showing links between XML/HTML files that could be configured to look for tokens of the description *1234*. FWIW, Chris From bert at freudenbergs.de Fri Oct 24 18:44:00 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Fri Oct 24 18:44:09 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: Message-ID: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> Your implementation looks good. But if we're changing the API, can we get around exposing ExternalSemaphoreTable to user code? It is an implementation detail, after all. E.g. for file opening: semaphore := Semaphore new. fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: semaphore registerExternalIndex. fileHandle ifNil: [ semaphore unregisterExternalIndex. semaphore := nil. ^ nil]. I'm not sure about the exact selectors, but this would make the programmer not having to deal with the implementation detail of the table at all. - Bert - On 24.10.2014, at 08:22, Levente Uzonyi wrote: > Thanks Bert. It turned out that my image was already broken when I tried to add an instance variable to Semaphore. > I've finished the implementation and uploaded it to The Inbox. The following snippet will load it into an updated Trunk image: > > Installer mc > http: 'source.squeak.org'; > project: 'inbox'; > package: 'Kernel-ul.881'; > package: 'System-ul.686'; > package: 'Kernel-ul.882'; > package: 'Sound-ul.39'; > package: 'Network-ul.153'; > package: 'Files-ul.139'; > install > > I decided to go with the complex solution, which gives the best performance, and a simple API for Semaphores, but also has pretty good performance for any other object. And it's backwards compatible in almost all cases. > > Levente > > On Sun, 12 Oct 2014, Bert Freudenberg wrote: > >> On 12.10.2014, at 08:04, Levente Uzonyi wrote: >> >>> Hi, >>> >>> I found that the handling of external objects is suboptimal in the image, and I came up with some ideas to make it better. I have a working solution in my image, but it can be even better. >>> >>> It seems to me that only Semaphores are stored in the external objects array (slot 39 in the special objects array), but in practice any object can be stored there. Does it make sense to support objects of any other kind? If not, then the code could be simplified. >> >> Currently the VM uses the ExternalObjectsArray only for semaphores. Other objects use different mechanisms (e.g. SurfacePlugin for external forms). I'm not sure if there is a good use case for storing non-semaphores in ExternalObjectsArray, maybe ask on the vm-dev list? >> >>> I also thought that I'll create a special semaphore (ExternalSemaphore - >>> which is a subclass of Semaphore) that knows its own index in the external objects array. This could be really handy for finding the object in the array, but the VM is not willing to signal these semaphores in the external objects array. I thought that this is because the VM doesn't know anything about this class. >>> So I tried to change Semaphore itself, but after the change the VM refused to signal any semaphores in the external objects array. Changing the class back to the original didn't help either. Without looking at the VM code, I assumed that the VM will signal anything which has the class in the 19th slot of the special objects array, but that doesn't seem to be the case. >>> Is there any way to make this (add an instatnce variable to Semaphore and still get signals from the VM, or use instances of a subclass of Semaphore there) work? >> >> The VM only checks for the exact class in slot 19, not for subclasses. Adding an inst var to Semaphore itself should be fine, but you cannot use a subclass without changing the VM. Are you sure you put the modified Semaphore class into SpecialObjectsArray after adding the inst var? >> >> - Bert - >> >> >> >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141024/b8598773/smime.bin From bert at freudenbergs.de Fri Oct 24 18:50:30 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Fri Oct 24 18:50:35 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> Message-ID: <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> Another thought: is it really necessary to cache the index in the semaphore? Wouldn't scanning the externalObjectsTable for self be efficient enough? It's pretty small, after all. - Bert - On 24.10.2014, at 11:44, Bert Freudenberg wrote: > Your implementation looks good. > > But if we're changing the API, can we get around exposing ExternalSemaphoreTable to user code? It is an implementation detail, after all. > > E.g. for file opening: > > semaphore := Semaphore new. > fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: semaphore registerExternalIndex. > fileHandle ifNil: [ > semaphore unregisterExternalIndex. > semaphore := nil. > ^ nil]. > > I'm not sure about the exact selectors, but this would make the programmer not having to deal with the implementation detail of the table at all. > > - Bert - > > On 24.10.2014, at 08:22, Levente Uzonyi wrote: > >> Thanks Bert. It turned out that my image was already broken when I tried to add an instance variable to Semaphore. >> I've finished the implementation and uploaded it to The Inbox. The following snippet will load it into an updated Trunk image: >> >> Installer mc >> http: 'source.squeak.org'; >> project: 'inbox'; >> package: 'Kernel-ul.881'; >> package: 'System-ul.686'; >> package: 'Kernel-ul.882'; >> package: 'Sound-ul.39'; >> package: 'Network-ul.153'; >> package: 'Files-ul.139'; >> install >> >> I decided to go with the complex solution, which gives the best performance, and a simple API for Semaphores, but also has pretty good performance for any other object. And it's backwards compatible in almost all cases. >> >> Levente >> >> On Sun, 12 Oct 2014, Bert Freudenberg wrote: >> >>> On 12.10.2014, at 08:04, Levente Uzonyi wrote: >>> >>>> Hi, >>>> >>>> I found that the handling of external objects is suboptimal in the image, and I came up with some ideas to make it better. I have a working solution in my image, but it can be even better. >>>> >>>> It seems to me that only Semaphores are stored in the external objects array (slot 39 in the special objects array), but in practice any object can be stored there. Does it make sense to support objects of any other kind? If not, then the code could be simplified. >>> >>> Currently the VM uses the ExternalObjectsArray only for semaphores. Other objects use different mechanisms (e.g. SurfacePlugin for external forms). I'm not sure if there is a good use case for storing non-semaphores in ExternalObjectsArray, maybe ask on the vm-dev list? >>> >>>> I also thought that I'll create a special semaphore (ExternalSemaphore - >>>> which is a subclass of Semaphore) that knows its own index in the external objects array. This could be really handy for finding the object in the array, but the VM is not willing to signal these semaphores in the external objects array. I thought that this is because the VM doesn't know anything about this class. >>>> So I tried to change Semaphore itself, but after the change the VM refused to signal any semaphores in the external objects array. Changing the class back to the original didn't help either. Without looking at the VM code, I assumed that the VM will signal anything which has the class in the 19th slot of the special objects array, but that doesn't seem to be the case. >>>> Is there any way to make this (add an instatnce variable to Semaphore and still get signals from the VM, or use instances of a subclass of Semaphore there) work? >>> >>> The VM only checks for the exact class in slot 19, not for subclasses. Adding an inst var to Semaphore itself should be fine, but you cannot use a subclass without changing the VM. Are you sure you put the modified Semaphore class into SpecialObjectsArray after adding the inst var? >>> >>> - Bert - >>> >>> >>> >>> >> > > > -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141024/2eded369/smime.bin From leves at elte.hu Fri Oct 24 19:52:11 2014 From: leves at elte.hu (Levente Uzonyi) Date: Fri Oct 24 19:52:17 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> Message-ID: On Fri, 24 Oct 2014, Bert Freudenberg wrote: > Another thought: is it really necessary to cache the index in the semaphore? Wouldn't scanning the externalObjectsTable for self be efficient enough? It's pretty small, after all. That's exactly what the current implementation does (scans the table), and this is what I want to avoid, because it doesn't scale. The table is small when you start your image, but it can easily grow large - especially on a server (3 semaphores per socket) - and it never gets shrinked. So once it grows, it'll stay slow "forever". And no, it's not absolutely necessary to store the index in the semaphores. The new implementation uses an IdentityDictionary to store the indexes of non-semaphores. The same method could work for semaphores too. But it's convenient to store the index in the semaphore, otherwise the method which creates and registers a new semaphore has to return two values - the index and the semaphore - which is cumbersome. It's also faster to ask for a new Semaphore from the ExternalSemaphoreTable, because that way it knows that the Semaphore is not registered. > > - Bert - > > On 24.10.2014, at 11:44, Bert Freudenberg wrote: > >> Your implementation looks good. >> >> But if we're changing the API, can we get around exposing ExternalSemaphoreTable to user code? It is an implementation detail, after all. >> >> E.g. for file opening: >> >> semaphore := Semaphore new. >> fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: semaphore registerExternalIndex. >> fileHandle ifNil: [ >> semaphore unregisterExternalIndex. >> semaphore := nil. >> ^ nil]. >> >> I'm not sure about the exact selectors, but this would make the programmer not having to deal with the implementation detail of the table at all. Yes, it's possible to extend the API by adding a few methods to Semaphore. Levente >> >> - Bert - >> >> On 24.10.2014, at 08:22, Levente Uzonyi wrote: >> >>> Thanks Bert. It turned out that my image was already broken when I tried to add an instance variable to Semaphore. >>> I've finished the implementation and uploaded it to The Inbox. The following snippet will load it into an updated Trunk image: >>> >>> Installer mc >>> http: 'source.squeak.org'; >>> project: 'inbox'; >>> package: 'Kernel-ul.881'; >>> package: 'System-ul.686'; >>> package: 'Kernel-ul.882'; >>> package: 'Sound-ul.39'; >>> package: 'Network-ul.153'; >>> package: 'Files-ul.139'; >>> install >>> >>> I decided to go with the complex solution, which gives the best performance, and a simple API for Semaphores, but also has pretty good performance for any other object. And it's backwards compatible in almost all cases. >>> >>> Levente >>> >>> On Sun, 12 Oct 2014, Bert Freudenberg wrote: >>> >>>> On 12.10.2014, at 08:04, Levente Uzonyi wrote: >>>> >>>>> Hi, >>>>> >>>>> I found that the handling of external objects is suboptimal in the image, and I came up with some ideas to make it better. I have a working solution in my image, but it can be even better. >>>>> >>>>> It seems to me that only Semaphores are stored in the external objects array (slot 39 in the special objects array), but in practice any object can be stored there. Does it make sense to support objects of any other kind? If not, then the code could be simplified. >>>> >>>> Currently the VM uses the ExternalObjectsArray only for semaphores. Other objects use different mechanisms (e.g. SurfacePlugin for external forms). I'm not sure if there is a good use case for storing non-semaphores in ExternalObjectsArray, maybe ask on the vm-dev list? >>>> >>>>> I also thought that I'll create a special semaphore (ExternalSemaphore - >>>>> which is a subclass of Semaphore) that knows its own index in the external objects array. This could be really handy for finding the object in the array, but the VM is not willing to signal these semaphores in the external objects array. I thought that this is because the VM doesn't know anything about this class. >>>>> So I tried to change Semaphore itself, but after the change the VM refused to signal any semaphores in the external objects array. Changing the class back to the original didn't help either. Without looking at the VM code, I assumed that the VM will signal anything which has the class in the 19th slot of the special objects array, but that doesn't seem to be the case. >>>>> Is there any way to make this (add an instatnce variable to Semaphore and still get signals from the VM, or use instances of a subclass of Semaphore there) work? >>>> >>>> The VM only checks for the exact class in slot 19, not for subclasses. Adding an inst var to Semaphore itself should be fine, but you cannot use a subclass without changing the VM. Are you sure you put the modified Semaphore class into SpecialObjectsArray after adding the inst var? >>>> >>>> - Bert - >>>> >>>> >>>> >>>> >>> >> >> >> > > > From lewis at mail.msen.com Fri Oct 24 23:01:56 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Fri Oct 24 23:01:59 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> Message-ID: <20141024230156.GA90281@shell.msen.com> On Fri, Oct 24, 2014 at 09:52:11PM +0200, Levente Uzonyi wrote: > On Fri, 24 Oct 2014, Bert Freudenberg wrote: > > >Another thought: is it really necessary to cache the index in the > >semaphore? Wouldn't scanning the externalObjectsTable for self be > >efficient enough? It's pretty small, after all. > > That's exactly what the current implementation does (scans the table), and > this is what I want to avoid, because it doesn't scale. The table is small > when you start your image, but it can easily grow large - especially on a > server (3 semaphores per socket) - and it never gets shrinked. So once it > grows, it'll stay slow "forever". > > And no, it's not absolutely necessary to store the index in the > semaphores. The new implementation uses an IdentityDictionary to store the > indexes of non-semaphores. The same method could work for semaphores too. > But it's convenient to store the index in the semaphore, otherwise the > method which creates and registers a new semaphore has to return two > values - the index and the semaphore - which is cumbersome. > It's also faster to ask for a new Semaphore from the > ExternalSemaphoreTable, because that way it knows that the > Semaphore is not registered. I also like the implementation overall, but it seems to me that a Semaphore should not be responsible for knowing about whether somebody used it in the external objects array. It seems more natural for ExternalSemaphoreTable to be responsible for keeping track of the relationship between semaphores and external resources. Thus I don't really like the #indexInExternalObjectsArray instance variable in Semaphore. On the other hand, in your earlier post introducing this topic, you said: > I also thought that I'll create a special semaphore (ExternalSemaphore - > which is a subclass of Semaphore) that knows its own index in the external > objects array. So IMO, maybe maybe your original concept is better, even if it requires another class. An ExternalSemaphore would be a Semaphore that knows about its place in the ExternalObjectsArray, but semaphores in general do not need to know about that. I'm not sure which would be better, but it seems to me that either ExternalSemaphoreTable should be responsible for maintaining the relationship (presumably with an IdentityDictionary), or ExternalSemaphore should be a kind of semaphore that knows something more about its place in the world. Dave From leves at elte.hu Fri Oct 24 23:07:31 2014 From: leves at elte.hu (Levente Uzonyi) Date: Fri Oct 24 23:07:35 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <20141024230156.GA90281@shell.msen.com> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141024230156.GA90281@shell.msen.com> Message-ID: On Fri, 24 Oct 2014, David T. Lewis wrote: > On Fri, Oct 24, 2014 at 09:52:11PM +0200, Levente Uzonyi wrote: >> On Fri, 24 Oct 2014, Bert Freudenberg wrote: >> >>> Another thought: is it really necessary to cache the index in the >>> semaphore? Wouldn't scanning the externalObjectsTable for self be >>> efficient enough? It's pretty small, after all. >> >> That's exactly what the current implementation does (scans the table), and >> this is what I want to avoid, because it doesn't scale. The table is small >> when you start your image, but it can easily grow large - especially on a >> server (3 semaphores per socket) - and it never gets shrinked. So once it >> grows, it'll stay slow "forever". >> >> And no, it's not absolutely necessary to store the index in the >> semaphores. The new implementation uses an IdentityDictionary to store the >> indexes of non-semaphores. The same method could work for semaphores too. >> But it's convenient to store the index in the semaphore, otherwise the >> method which creates and registers a new semaphore has to return two >> values - the index and the semaphore - which is cumbersome. >> It's also faster to ask for a new Semaphore from the >> ExternalSemaphoreTable, because that way it knows that the >> Semaphore is not registered. > > I also like the implementation overall, but it seems to me that a Semaphore > should not be responsible for knowing about whether somebody used it in the > external objects array. It seems more natural for ExternalSemaphoreTable > to be responsible for keeping track of the relationship between semaphores > and external resources. Thus I don't really like the #indexInExternalObjectsArray > instance variable in Semaphore. > > On the other hand, in your earlier post introducing this topic, you said: > >> I also thought that I'll create a special semaphore (ExternalSemaphore - >> which is a subclass of Semaphore) that knows its own index in the external >> objects array. > > So IMO, maybe maybe your original concept is better, even if it requires > another class. An ExternalSemaphore would be a Semaphore that knows about > its place in the ExternalObjectsArray, but semaphores in general do not > need to know about that. > > I'm not sure which would be better, but it seems to me that either > ExternalSemaphoreTable should be responsible for maintaining the relationship > (presumably with an IdentityDictionary), or ExternalSemaphore should be > a kind of semaphore that knows something more about its place in the world. The problem with ExternalSemaphore idea is that it requires VM changes. The VM is not willing to signal instances of non-Semaphores. AFAIK signaling is based on what's in slot 19 of the specialObjectsArray. But changing the class there is not possible, because other VM mechanisms also rely on the content of that slot. Levente > > Dave > > > From commits at source.squeak.org Fri Oct 24 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 24 23:55:04 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141024235502.20223.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007344.html Name: KernelTests-dtl.279 Ancestors: KernelTests-ul.278 Add test to document a VM bug (fixed) exposed when running 68002 image format. ============================================= From lewis at mail.msen.com Sat Oct 25 00:00:12 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sat Oct 25 00:00:15 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141024230156.GA90281@shell.msen.com> Message-ID: <20141025000012.GA3022@shell.msen.com> On Sat, Oct 25, 2014 at 01:07:31AM +0200, Levente Uzonyi wrote: > On Fri, 24 Oct 2014, David T. Lewis wrote: > > >On Fri, Oct 24, 2014 at 09:52:11PM +0200, Levente Uzonyi wrote: > >>On Fri, 24 Oct 2014, Bert Freudenberg wrote: > >> > >>>Another thought: is it really necessary to cache the index in the > >>>semaphore? Wouldn't scanning the externalObjectsTable for self be > >>>efficient enough? It's pretty small, after all. > >> > >>That's exactly what the current implementation does (scans the table), and > >>this is what I want to avoid, because it doesn't scale. The table is small > >>when you start your image, but it can easily grow large - especially on a > >>server (3 semaphores per socket) - and it never gets shrinked. So once it > >>grows, it'll stay slow "forever". > >> > >>And no, it's not absolutely necessary to store the index in the > >>semaphores. The new implementation uses an IdentityDictionary to store the > >>indexes of non-semaphores. The same method could work for semaphores too. > >>But it's convenient to store the index in the semaphore, otherwise the > >>method which creates and registers a new semaphore has to return two > >>values - the index and the semaphore - which is cumbersome. > >>It's also faster to ask for a new Semaphore from the > >>ExternalSemaphoreTable, because that way it knows that the > >>Semaphore is not registered. > > > >I also like the implementation overall, but it seems to me that a Semaphore > >should not be responsible for knowing about whether somebody used it in the > >external objects array. It seems more natural for ExternalSemaphoreTable > >to be responsible for keeping track of the relationship between semaphores > >and external resources. Thus I don't really like the > >#indexInExternalObjectsArray > >instance variable in Semaphore. > > > >On the other hand, in your earlier post introducing this topic, you said: > > > >> I also thought that I'll create a special semaphore (ExternalSemaphore - > >> which is a subclass of Semaphore) that knows its own index in the > >> external > >> objects array. > > > >So IMO, maybe maybe your original concept is better, even if it requires > >another class. An ExternalSemaphore would be a Semaphore that knows about > >its place in the ExternalObjectsArray, but semaphores in general do not > >need to know about that. > > > >I'm not sure which would be better, but it seems to me that either > >ExternalSemaphoreTable should be responsible for maintaining the > >relationship > >(presumably with an IdentityDictionary), or ExternalSemaphore should be > >a kind of semaphore that knows something more about its place in the world. > > The problem with ExternalSemaphore idea is that it requires VM changes. > The VM is not willing to signal instances of non-Semaphores. AFAIK > signaling is based on what's in slot 19 of the specialObjectsArray. But > changing the class there is not possible, because other VM mechanisms also > rely on the content of that slot. Hmm... Unfortunately you are right. InterpreterPrimitives>>primitiveSignal "synchromously signal the semaphore. This may change the active process as a result" | sema | sema := self stackTop. "rcvr" self assertClassOf: sema is: (objectMemory splObj: ClassSemaphore). self successful ifTrue: [ self synchronousSignal: sema ]. Dave From lewis at mail.msen.com Sat Oct 25 19:46:06 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sat Oct 25 19:46:09 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> Message-ID: <20141025194606.GB81717@shell.msen.com> On Fri, Oct 24, 2014 at 09:52:11PM +0200, Levente Uzonyi wrote: > On Fri, 24 Oct 2014, Bert Freudenberg wrote: > > >Another thought: is it really necessary to cache the index in the > >semaphore? Wouldn't scanning the externalObjectsTable for self be > >efficient enough? It's pretty small, after all. > > That's exactly what the current implementation does (scans the table), and > this is what I want to avoid, because it doesn't scale. The table is small > when you start your image, but it can easily grow large - especially on a > server (3 semaphores per socket) - and it never gets shrinked. So once it > grows, it'll stay slow "forever". > > And no, it's not absolutely necessary to store the index in the > semaphores. The new implementation uses an IdentityDictionary to store the > indexes of non-semaphores. The same method could work for semaphores too. > But it's convenient to store the index in the semaphore, otherwise the > method which creates and registers a new semaphore has to return two > values - the index and the semaphore - which is cumbersome. > It's also faster to ask for a new Semaphore from the > ExternalSemaphoreTable, because that way it knows that the > Semaphore is not registered. > I don't see the indexesByObjects dictionary actually being updated, except in the case of setting a new externalObjectsArray in the ExternalSemaphoreTable. I think I am overlooking something? Dave From leves at elte.hu Sat Oct 25 20:02:22 2014 From: leves at elte.hu (Levente Uzonyi) Date: Sat Oct 25 20:02:28 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <20141025194606.GB81717@shell.msen.com> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> Message-ID: On Sat, 25 Oct 2014, David T. Lewis wrote: > On Fri, Oct 24, 2014 at 09:52:11PM +0200, Levente Uzonyi wrote: >> On Fri, 24 Oct 2014, Bert Freudenberg wrote: >> >>> Another thought: is it really necessary to cache the index in the >>> semaphore? Wouldn't scanning the externalObjectsTable for self be >>> efficient enough? It's pretty small, after all. >> >> That's exactly what the current implementation does (scans the table), and >> this is what I want to avoid, because it doesn't scale. The table is small >> when you start your image, but it can easily grow large - especially on a >> server (3 semaphores per socket) - and it never gets shrinked. So once it >> grows, it'll stay slow "forever". >> >> And no, it's not absolutely necessary to store the index in the >> semaphores. The new implementation uses an IdentityDictionary to store the >> indexes of non-semaphores. The same method could work for semaphores too. >> But it's convenient to store the index in the semaphore, otherwise the >> method which creates and registers a new semaphore has to return two >> values - the index and the semaphore - which is cumbersome. >> It's also faster to ask for a new Semaphore from the >> ExternalSemaphoreTable, because that way it knows that the >> Semaphore is not registered. >> > > I don't see the indexesByObjects dictionary actually being updated, except > in the case of setting a new externalObjectsArray in the ExternalSemaphoreTable. > I think I am overlooking something? It's updated in #safelyRegisterExternalObject: and #safelyUnregisterExternalObject:, but - as the class comment states - it's only used for non-Semaphores. Based on the feedback there's too much resistance to add an instance variable to Semaphore, so I'm about to remove that part from the implementation. Levente > > Dave > > > From lewis at mail.msen.com Sat Oct 25 20:45:57 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sat Oct 25 20:46:00 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> Message-ID: <20141025204557.GA94822@shell.msen.com> On Sat, Oct 25, 2014 at 10:02:22PM +0200, Levente Uzonyi wrote: > On Sat, 25 Oct 2014, David T. Lewis wrote: > > >On Fri, Oct 24, 2014 at 09:52:11PM +0200, Levente Uzonyi wrote: > >>On Fri, 24 Oct 2014, Bert Freudenberg wrote: > >> > >>>Another thought: is it really necessary to cache the index in the > >>>semaphore? Wouldn't scanning the externalObjectsTable for self be > >>>efficient enough? It's pretty small, after all. > >> > >>That's exactly what the current implementation does (scans the table), and > >>this is what I want to avoid, because it doesn't scale. The table is small > >>when you start your image, but it can easily grow large - especially on a > >>server (3 semaphores per socket) - and it never gets shrinked. So once it > >>grows, it'll stay slow "forever". > >> > >>And no, it's not absolutely necessary to store the index in the > >>semaphores. The new implementation uses an IdentityDictionary to store the > >>indexes of non-semaphores. The same method could work for semaphores too. > >>But it's convenient to store the index in the semaphore, otherwise the > >>method which creates and registers a new semaphore has to return two > >>values - the index and the semaphore - which is cumbersome. > >>It's also faster to ask for a new Semaphore from the > >>ExternalSemaphoreTable, because that way it knows that the > >>Semaphore is not registered. > >> > > > >I don't see the indexesByObjects dictionary actually being updated, except > >in the case of setting a new externalObjectsArray in the > >ExternalSemaphoreTable. > >I think I am overlooking something? > > It's updated in #safelyRegisterExternalObject: and > #safelyUnregisterExternalObject:, but - as the class comment states - it's > only used for non-Semaphores. > > Based on the feedback there's too much resistance to add an instance > variable to Semaphore, so I'm about to remove that part from the > implementation. I don't think the instance variable is horrible, but I do think it would feel cleaner if you can do without it, so +1 if you are able to do that. Thanks Dave From eliot.miranda at gmail.com Sat Oct 25 20:51:52 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sat Oct 25 20:51:56 2014 Subject: [squeak-dev] New Cog VMs available Message-ID: ...at http://www.mirandabanda.org/files/Cog/VM/VM.r3114/. CogVM binaries as per VMMaker.oscog-eem.913/r3114 Spur: Fix baaaad bug in checking for still-married contexts in Spur. One *cannot* simply follow what is assumed to be the frameContext field of what is presumed to be a context. On Spur we need to *know* whether we have a valid frameContext field, and for that we have to know there is a valid frame. So refactor, moving isFrame:onPage: from StackInterpreterPrimitives to StackInterpreter, and use it to validate the frame pointer of a maybe married context before testing the context for being forwarded. All: Avoid cogging methods containing unknown bytecodes early in scanMethod. Use a hack to avoid a test on the common path. Fix assert fail cases in ceInterpretMethodFromPIC:receiver: Both of these together fix assert fails due to cogging methods containing unknown bytecodes. Spur: Implement image segments. Use Igor's idea of splitting the computation of the transitive closure from the writing of the image segment for simplicity, even if the two are together into a single primitive for backwards-compatibility. All: Rewrite the two image segment primitives to pass back an error code on failure, and rewrite the (New)ObjectMemory code to answer informative failure codes. Print slots of word objects in longPrintOop: Fix parenthesization bugs in validation code in some Alien plugin primtiives. Make findClassContainingMethod:startingAt: et al robust in the face of faulted-out classes (nil method dictionaries). Include the AioPlugin in the Newspeak linux VMs; recent reports indicate it's essential to good performance in recent versions of OSProcessPlugin. Unix startup script: Quote the LD_LIBRARY_PATH setting to tolerate directory names with spaces. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141025/dcb3d3ed/attachment.htm From commits at source.squeak.org Sat Oct 25 22:10:39 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 25 22:10:42 2014 Subject: [squeak-dev] The Trunk: Installer-Core-ul.395.mcz Message-ID: Levente Uzonyi uploaded a new version of Installer-Core to project The Trunk: http://source.squeak.org/trunk/Installer-Core-ul.395.mcz ==================== Summary ==================== Name: Installer-Core-ul.395 Author: ul Time: 25 October 2014, 10:46:30.418 pm UUID: 862c5471-3279-4f41-998f-9f91976860dd Ancestors: Installer-Core-nice.394 - added #squeakInbox and #squeakTrunk accessors =============== Diff against Installer-Core-nice.394 =============== Item was added: + ----- Method: Installer class>>squeakInbox (in category 'repositories') ----- + squeakInbox + + ^self squeak project: 'inbox'! Item was added: + ----- Method: Installer class>>squeakTrunk (in category 'repositories') ----- + squeakTrunk + + ^self squeak project: 'trunk'! From lewis at mail.msen.com Sat Oct 25 23:06:58 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sat Oct 25 23:07:01 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> Message-ID: <20141025230658.GA16343@shell.msen.com> On Sat, Oct 25, 2014 at 10:02:22PM +0200, Levente Uzonyi wrote: > On Sat, 25 Oct 2014, David T. Lewis wrote: > > > >I don't see the indexesByObjects dictionary actually being updated, except > >in the case of setting a new externalObjectsArray in the > >ExternalSemaphoreTable. > >I think I am overlooking something? > > It's updated in #safelyRegisterExternalObject: and > #safelyUnregisterExternalObject:, but - as the class comment states - it's > only used for non-Semaphores. Sorry, I should have looked more carefully. This works exactly as expected and as documented in the class comment: ExternalSemaphoreTable registerExternalObject: Object new. Dave From commits at source.squeak.org Sat Oct 25 23:53:44 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 25 23:53:46 2014 Subject: [squeak-dev] The Inbox: Sound-ul.40.mcz Message-ID: A new version of Sound was added to project The Inbox: http://source.squeak.org/inbox/Sound-ul.40.mcz ==================== Summary ==================== Name: Sound-ul.40 Author: ul Time: 26 October 2014, 1:43:33.816 am UUID: c4759ae3-93c9-4344-bc16-600a8e018ca6 Ancestors: Sound-nice.38 - use the new ExternalSemaphoreTable API =============== Diff against Sound-nice.38 =============== Item was changed: ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') ----- startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound "Start the sound player process. Terminate the old process, if any." "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false" self stopPlayerProcess. aSound ifNil:[ActiveSounds := OrderedCollection new] ifNotNil:[ActiveSounds := OrderedCollection with: aSound]. Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4. LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize]. PlayerSemaphore := Semaphore forMutualExclusion. SamplingRate := samplesPerSecond. Stereo := stereoFlag. - ReadyForBuffer := Semaphore new. SoundSupported := true. "Assume so" UseReadySemaphore := true. "set to false if ready semaphore not supported by VM" + ExternalSemaphoreTable newExternalSemaphoreDo: [ :semaphore :index | + ReadyForBuffer := semaphore. + self primSoundStartBufferSize: Buffer stereoSampleCount + rate: samplesPerSecond + stereo: Stereo + semaIndex: index ]. - self primSoundStartBufferSize: Buffer stereoSampleCount - rate: samplesPerSecond - stereo: Stereo - semaIndex: (Smalltalk registerExternalObject: ReadyForBuffer). "Check if sound start prim was successful" + SoundSupported ifFalse:[ + ExternalSemaphoreTable unregisterExternalObject: ReadyForBuffer. + ReadyForBuffer := nil. + ^self ]. - SoundSupported ifFalse:[^self]. UseReadySemaphore ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess] ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess]. UseReverb ifTrue: [self startReverb]. PlayerProcess priority: Processor userInterruptPriority. + PlayerProcess resume! - PlayerProcess resume.! Item was changed: ----- Method: SoundPlayer class>>stopPlayerProcess (in category 'player process') ----- stopPlayerProcess "Stop the sound player process." "SoundPlayer stopPlayerProcess" (PlayerProcess == nil or:[PlayerProcess == Processor activeProcess]) ifFalse:[PlayerProcess terminate]. PlayerProcess := nil. self primSoundStop. ActiveSounds := OrderedCollection new. Buffer := nil. PlayerSemaphore := Semaphore forMutualExclusion. ReadyForBuffer ifNotNil: + [ExternalSemaphoreTable unregisterExternalObject: ReadyForBuffer]. - [Smalltalk unregisterExternalObject: ReadyForBuffer]. ReadyForBuffer := nil. ! Item was changed: ----- Method: SoundRecorder>>startRecording (in category 'recording controls') ----- startRecording "Turn of the sound input driver and start the recording process. Initially, recording is paused." - | semaIndex | recordLevel ifNil: [recordLevel := 0.5]. "lazy initialization" CanRecordWhilePlaying ifFalse: [SoundPlayer shutDown]. recordProcess ifNotNil: [self stopRecording]. paused := true. meteringBuffer := SoundBuffer newMonoSampleCount: 1024. meterLevel := 0. self allocateBuffer. + ExternalSemaphoreTable newExternalSemaphoreDo: [ :semaphore :index | + bufferAvailableSema := semaphore. + self primStartRecordingDesiredSampleRate: samplingRate asInteger + stereo: stereo + semaIndex: index ]. - bufferAvailableSema := Semaphore new. - semaIndex := Smalltalk registerExternalObject: bufferAvailableSema. - self primStartRecordingDesiredSampleRate: samplingRate asInteger - stereo: stereo - semaIndex: semaIndex. RecorderActive := true. samplingRate := self primGetActualRecordingSampleRate. self primSetRecordLevel: (1000.0 * recordLevel) asInteger. recordProcess := [self recordLoop] newProcess. recordProcess priority: Processor userInterruptPriority. + recordProcess resume! - recordProcess resume. - ! Item was changed: ----- Method: SoundRecorder>>stopRecording (in category 'recording controls') ----- stopRecording "Stop the recording process and turn of the sound input driver." recordProcess ifNotNil: [recordProcess terminate]. recordProcess := nil. self primStopRecording. RecorderActive := false. + ExternalSemaphoreTable unregisterExternalObject: bufferAvailableSema. - Smalltalk unregisterExternalObject: bufferAvailableSema. ((currentBuffer ~~ nil) and: [nextIndex > 1]) ifTrue: [self emitPartialBuffer]. self initializeRecordingState. ! From commits at source.squeak.org Sat Oct 25 23:53:45 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 25 23:53:48 2014 Subject: [squeak-dev] The Inbox: System-ul.687.mcz Message-ID: A new version of System was added to project The Inbox: http://source.squeak.org/inbox/System-ul.687.mcz ==================== Summary ==================== Name: System-ul.687 Author: ul Time: 26 October 2014, 1:43:00.13 am UUID: 1a211671-bea3-4da5-97a1-0e95b851ef58 Ancestors: System-dtl.685 Updated ExternalSemaphoreTable to provide faster registration, and give better support to the current users. Notable changes: - the table is a separate object instead of a few class side methods, but the API is still on the class side - #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores: provide fast and easy creation and registration of Semaphores - #unregisterExternalObjects: can unregister multiple objects faster - #externalObjects will return a copy of the externalObjectsArray - better scalability - the maxExternalSemaphores VM parameter will be incremented as the externalObjectsArray grows =============== Diff against System-dtl.685 =============== Item was changed: Object subclass: #ExternalSemaphoreTable + instanceVariableNames: 'semaphore externalObjectsArray freeSlotIndexes indexesByObjects' + classVariableNames: '' - instanceVariableNames: '' - classVariableNames: 'ProtectTable' poolDictionaries: '' category: 'System-Support'! + ExternalSemaphoreTable class + instanceVariableNames: 'current'! + !ExternalSemaphoreTable commentStamp: 'ul 10/25/2014 18:03' prior: 0! + I'm an enhanced version of JMM's ExternalSemaphoreTable. Despite the name I can store any object but nil. + I'm responsible for maintaining the externalObjectsArray, which can be found at slot 39 of Smalltalk specialObjectsArray. Manipulating the array directly is highly discouraged. + It's safe to use all class-side methods in the accessing category except for #clearExternalObjects - which should only be used during image startUp - and #current, because instance-side methods are not intented to be used by external code. + + If you'd like the create one or more new Semaphores and register them for external use, then you should use either #newExternalSemaphore or #newExternalSemaphores:. If you want to unregister more than one external objects at the same time, then #unregisterExternalObjects: is the method you're looking for. + + Implementation details: + I maintain a single instance (#current), which can automatically synchronize with externalObjectsArray. + All accesses are protected by the semaphore instance variable. + To ensure fast access, I keep track of the indexes of the external objects in the externalObjectArray in my indexesByObjects IdentityDictionary. + To ensure fast insertion, I keep track of the free slots of the externalObjectsArray in the freeSlotIndexes OrderedCollection. The access pattern is LIFO to avoid unnecessary growth and reordering of the OrderedCollection. + I can grow the externalObjectsArray (see #ensureFreeSlot), but I never shrink it. + + Original comment: - !ExternalSemaphoreTable commentStamp: '' prior: 0! By John M McIntosh johnmci@smalltalkconsulting.com This class was written to mange the external semaphore table. When I was writing a Socket test server I discovered various race conditions on the access to the externalSemaphore table. This new class uses class side methods to restrict access using a mutex semaphore. It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary Note that in Smalltalk recreateSpecialObjectsArray we still directly play with the table.! + ExternalSemaphoreTable class + instanceVariableNames: 'current'! Item was added: + ----- Method: ExternalSemaphoreTable class>>cleanUp: (in category 'initialize-release') ----- + cleanUp: aggressive + "It's safe to release the instance" + + self reset! Item was changed: ----- Method: ExternalSemaphoreTable class>>clearExternalObjects (in category 'accessing') ----- clearExternalObjects "Clear the array of objects that have been registered for use in non-Smalltalk code." + self current clearExternalObjects - ProtectTable critical: [Smalltalk specialObjectsArray at: 39 put: Array new]. ! Item was added: + ----- Method: ExternalSemaphoreTable class>>current (in category 'accessing') ----- + current + + ^current ifNil: [ + | newInstance | + newInstance := self new. + " Check again, because another process might have registered another instance. " + current ifNil: [ current := newInstance ] ]! Item was changed: ----- Method: ExternalSemaphoreTable class>>externalObjects (in category 'accessing') ----- externalObjects + "Return a copy of the externalObjectsArray." + + ^self current externalObjects! - ^ProtectTable critical: [Smalltalk specialObjectsArray at: 39].! Item was removed: - ----- Method: ExternalSemaphoreTable class>>initialize (in category 'initialize') ----- - initialize - ProtectTable := Semaphore forMutualExclusion! Item was added: + ----- Method: ExternalSemaphoreTable class>>newExternalSemaphore (in category 'accessing') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return an array containing itself and its index." + + ^self current newExternalSemaphore! Item was added: + ----- Method: ExternalSemaphoreTable class>>newExternalSemaphoreDo: (in category 'accessing') ----- + newExternalSemaphoreDo: aBlock + "Create and register a new Semaphore, then evaluate aBlock with it and its index." + + ^self current newExternalSemaphoreDo: aBlock! Item was added: + ----- Method: ExternalSemaphoreTable class>>newExternalSemaphores: (in category 'accessing') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing the semaphores and their indexes in separate arrays." + + ^self current newExternalSemaphores: count! Item was changed: ----- Method: ExternalSemaphoreTable class>>registerExternalObject: (in category 'accessing') ----- registerExternalObject: anObject + "Register the given object in the external objects array and return its index. If it is already there, just return its index." + + ^self current registerExternalObject: anObject! - ^ ProtectTable critical: [self safelyRegisterExternalObject: anObject] - ! Item was added: + ----- Method: ExternalSemaphoreTable class>>reset (in category 'accessing') ----- + reset + + current := nil! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyRegisterExternalObject: (in category 'accessing') ----- - safelyRegisterExternalObject: anObject - "Register the given object in the external objects array and return its index. If it is already there, just return its index." - - | objects firstEmptyIndex obj sz newObjects | - objects := Smalltalk specialObjectsArray at: 39. - - "find the first empty slot" - firstEmptyIndex := 0. - 1 to: objects size do: [:i | - obj := objects at: i. - obj == anObject ifTrue: [^ i]. "object already there, just return its index" - (obj == nil and: [firstEmptyIndex = 0]) ifTrue: [firstEmptyIndex := i]]. - - "if no empty slots, expand the array" - firstEmptyIndex = 0 ifTrue: [ - sz := objects size. - newObjects := objects species new: sz + 20. "grow linearly" - newObjects replaceFrom: 1 to: sz with: objects startingAt: 1. - firstEmptyIndex := sz + 1. - Smalltalk specialObjectsArray at: 39 put: newObjects. - objects := newObjects]. - - objects at: firstEmptyIndex put: anObject. - ^ firstEmptyIndex - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyUnregisterExternalObject: (in category 'accessing') ----- - safelyUnregisterExternalObject: anObject - "Unregister the given object in the external objects array. Do nothing if it isn't registered. - JMM change to return if we clear the element, since it should only appear once in the array" - - | objects | - anObject ifNil: [^ self]. - objects := Smalltalk specialObjectsArray at: 39. - 1 to: objects size do: [:i | - (objects at: i) == anObject ifTrue: - [objects at: i put: nil. - ^self]]. - ! Item was changed: ----- Method: ExternalSemaphoreTable class>>unregisterExternalObject: (in category 'accessing') ----- unregisterExternalObject: anObject + "Unregister the given object from the external objects array. Do nothing if it isn't registered." + + self current unregisterExternalObject: anObject! - ProtectTable critical: [self safelyUnregisterExternalObject: anObject] - ! Item was added: + ----- Method: ExternalSemaphoreTable class>>unregisterExternalObjects: (in category 'accessing') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + self current unregisterExternalObjects: aCollection! Item was added: + ----- Method: ExternalSemaphoreTable>>clearExternalObjects (in category 'accessing') ----- + clearExternalObjects + "Clear the array of objects that have been registered for use in non-Smalltalk code." + + semaphore critical: [ + Smalltalk specialObjectsArray at: 39 put: Array new. + self + initializeCaches; + synchronizeExternalObjectsArrayAndForceUpdate: true ]! Item was added: + ----- Method: ExternalSemaphoreTable>>ensureFreeSlot (in category 'private') ----- + ensureFreeSlot + "Make sure there's at least one free slot." + + | oldSize newSize newExternalObjectsArray specialObjectsArray | + freeSlotIndexes isEmpty ifFalse: [ ^self ]. + oldSize := externalObjectsArray size. + newSize := oldSize + 20. "Linear growth is not really a problem, because we never shrink the array." + newExternalObjectsArray := externalObjectsArray species new: newSize. + newExternalObjectsArray + replaceFrom: 1 + to: oldSize + with: externalObjectsArray + startingAt: 1. + specialObjectsArray := Smalltalk specialObjectsArray. + (specialObjectsArray at: 39) == externalObjectsArray + ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + ensureFreeSlot ]. + specialObjectsArray at: 39 put: newExternalObjectsArray. + externalObjectsArray := newExternalObjectsArray. + oldSize + 1 to: newSize do: [ :each | + freeSlotIndexes add: each ]. + Smalltalk maxExternalSemaphores ifNotNil: [ :maxExternalSemaphores | + "Make sure that those new external semaphores can be signaled by the VM. This is not entirely safe, but not incrementing at all is worse." + newSize > maxExternalSemaphores ifTrue: [ + Smalltalk maxExternalSemaphores: newSize ] ] + + ! Item was added: + ----- Method: ExternalSemaphoreTable>>externalObjects (in category 'accessing') ----- + externalObjects + "Return a copy of the externalObjectsArray." + + ^semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + externalObjectsArray copy ]! Item was added: + ----- Method: ExternalSemaphoreTable>>externalObjectsArray: (in category 'private') ----- + externalObjectsArray: anArray + "Update the index mapping using anArray as the new externalObjectsArray." + + externalObjectsArray := anArray. + freeSlotIndexes reset. + indexesByObjects removeAll. + 1 to: externalObjectsArray size do: [ :index | + (anArray at: index) + ifNil: [ freeSlotIndexes add: index ] + ifNotNil: [ :object | indexesByObjects at: object put: index ] ]! Item was added: + ----- Method: ExternalSemaphoreTable>>initialize (in category 'initialize-release') ----- + initialize + + semaphore := Semaphore forMutualExclusion. + self initializeCaches! Item was added: + ----- Method: ExternalSemaphoreTable>>initializeCaches (in category 'private') ----- + initializeCaches + + freeSlotIndexes := OrderedCollection new. + indexesByObjects := IdentityDictionary new! Item was added: + ----- Method: ExternalSemaphoreTable>>newExternalSemaphore (in category 'accessing') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return an array containing itself and its index." + + | newSemaphore | + ^{ + newSemaphore := Semaphore new. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterNewExternalObject: newSemaphore ] }! Item was added: + ----- Method: ExternalSemaphoreTable>>newExternalSemaphoreDo: (in category 'accessing') ----- + newExternalSemaphoreDo: aBlock + "Create and register a new Semaphore, then evaluate aBlock with it and its index." + + | newSemaphore | + ^aBlock + value: (newSemaphore := Semaphore new) + value: (semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterNewExternalObject: newSemaphore ])! Item was added: + ----- Method: ExternalSemaphoreTable>>newExternalSemaphores: (in category 'accessing') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing the semaphores and their indexes in separate arrays." + + | semaphores indexes | + semaphores := Array new: count. + 1 to: count do: [ :index | semaphores at: index put: Semaphore new ]. + indexes := Array new: count. + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + 1 to: count do: [ :index | + indexes at: index put: ( + self safelyRegisterNewExternalObject: (semaphores at: index)) ] ]. + ^{ semaphores. indexes }! Item was added: + ----- Method: ExternalSemaphoreTable>>registerExternalObject: (in category 'accessing') ----- + registerExternalObject: anObject + "Register the given object in the external objects array and return its index. If it is already there, just return its index." + + anObject ifNil: [ ^nil ]. + ^semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyRegisterExternalObject: (in category 'private') ----- + safelyRegisterExternalObject: anObject + + | index | + (index := indexesByObjects at: anObject ifAbsent: nil) ifNotNil: [ + (externalObjectsArray at: index) == anObject ifTrue: [ ^index ]. + "indexesByObjects is out of sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterExternalObject: anObject ]. + ^self safelyRegisterNewExternalObject: anObject! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyRegisterNewExternalObject: (in category 'private') ----- + safelyRegisterNewExternalObject: anObject + + | index | + self ensureFreeSlot. + index := freeSlotIndexes removeLast. + (externalObjectsArray at: index) ifNotNil: [ + "Free slot is not empty. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterNewExternalObject: anObject ]. + externalObjectsArray at: index put: anObject. + indexesByObjects at: anObject put: index. + ^index! Item was added: + ----- Method: ExternalSemaphoreTable>>safelyUnregisterExternalObject: (in category 'private') ----- + safelyUnregisterExternalObject: anObject + + (indexesByObjects removeKey: anObject ifAbsent: nil) + ifNotNil: [ :index | + (externalObjectsArray at: index) == anObject ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]. + externalObjectsArray at: index put: nil. + freeSlotIndexes add: index ] + ifNil: [ + "Check if we're just out of sync." + (externalObjectsArray instVarsInclude: anObject) ifFalse: [ ^self ]. + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalSemaphoreTable>>synchronizeExternalObjectsArrayAndForceUpdate: (in category 'private') ----- + synchronizeExternalObjectsArrayAndForceUpdate: forceUpdate + + | actualExternalObjectsArray | + actualExternalObjectsArray := Smalltalk specialObjectsArray at: 39. + (actualExternalObjectsArray == externalObjectsArray and: [ forceUpdate not ]) + ifTrue: [ ^self ]. + self externalObjectsArray: actualExternalObjectsArray! Item was added: + ----- Method: ExternalSemaphoreTable>>unregisterExternalObject: (in category 'accessing') ----- + unregisterExternalObject: anObject + "Unregister the given object from the external objects array. Do nothing if it isn't registered." + + anObject ifNil: [ ^self ]. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalSemaphoreTable>>unregisterExternalObjects: (in category 'accessing') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + aCollection do: [ :each | + each ifNotNil: [ + self safelyUnregisterExternalObject: each ] ] ]! Item was changed: ----- Method: SmalltalkImage>>snapshot:andQuit:withExitCode:embedded: (in category 'snapshot and quit') ----- snapshot: save andQuit: quit withExitCode: exitCode embedded: embeddedFlag "Mark the changes file and close all files as part of #processShutdownList. If save is true, save the current state of this Smalltalk in the image file. If quit is true, then exit to the outer OS shell. If exitCode is not nil, then use it as exit code. The latter part of this method runs when resuming a previously saved image. This resume logic checks for a document file to process when starting up." | resuming msg | Object flushDependents. Object flushEvents. (SourceFiles at: 2) ifNotNil:[ msg := String streamContents: [ :s | s nextPutAll: '----'; nextPutAll: (save ifTrue: [ quit ifTrue: [ 'QUIT' ] ifFalse: [ 'SNAPSHOT' ] ] ifFalse: [quit ifTrue: [ 'QUIT/NOSAVE' ] ifFalse: [ 'NOP' ]]); nextPutAll: '----'; print: Date dateAndTimeNow; space; nextPutAll: (FileDirectory default localNameFor: self imageName); nextPutAll: ' priorSource: '; print: LastQuitLogPosition ]. self assureStartupStampLogged. save ifTrue: [ LastQuitLogPosition := (SourceFiles at: 2) setToEnd; position ]. self logChange: msg. Transcript cr; show: msg ]. Smalltalk processShutDownList: quit. Cursor write show. save ifTrue: [resuming := embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming := false]. quit & (resuming == false) ifTrue: [ exitCode ifNil: [ self quitPrimitive ] ifNotNil: [ self quitPrimitive: exitCode ] ]. Cursor normal show. Smalltalk setGCParameters. + resuming == true ifTrue: [ExternalSemaphoreTable clearExternalObjects]. - resuming == true ifTrue: [Smalltalk clearExternalObjects]. Smalltalk processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self recordStartupStamp]. Project current wakeUpTopWindow. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! From commits at source.squeak.org Sat Oct 25 23:54:30 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 25 23:54:32 2014 Subject: [squeak-dev] The Inbox: Network-ul.154.mcz Message-ID: A new version of Network was added to project The Inbox: http://source.squeak.org/inbox/Network-ul.154.mcz ==================== Summary ==================== Name: Network-ul.154 Author: ul Time: 26 October 2014, 1:44:11.795 am UUID: 02f2fb48-c1da-4d22-b691-8b96c1886300 Ancestors: Network-ul.152 - use the new ExternalSemaphoreTable API - unifed socket initialization - unregister ResolverSemaphore when the network initialization fails =============== Diff against Network-ul.152 =============== Item was changed: ----- Method: NetNameResolver class>>initializeNetwork (in category 'network initialization') ----- initializeNetwork "Initialize the network drivers and record the semaphore to be used by the resolver. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails." "NetNameResolver initializeNetwork" - | semaIndex | self resolverStatus = ResolverUninitialized ifFalse: [^HaveNetwork := true]. "network is already initialized" HaveNetwork := false. "in case abort" + ExternalSemaphoreTable newExternalSemaphoreDo: [ :semaphore :index | + ResolverSemaphore := semaphore. + "result is nil if network initialization failed, self if it succeeds" + (self primInitializeNetwork: index) + ifNil: [ + ExternalSemaphoreTable unregisterExternalObject: ResolverSemaphore. + ResolverSemaphore := nil. + NoNetworkError signal: 'failed network initialization'] + ifNotNil: [ HaveNetwork := true ] ]. - ResolverSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: ResolverSemaphore. + self initializeOldNetworkFlag! - "result is nil if network initialization failed, self if it succeeds" - (self primInitializeNetwork: semaIndex) - ifNil: [NoNetworkError signal: 'failed network initialization'] - ifNotNil: [HaveNetwork := true]. - - self initializeOldNetworkFlag - ! Item was changed: ----- Method: Socket>>acceptFrom: (in category 'initialize-destroy') ----- acceptFrom: aSocket "Initialize a new socket handle from an accept call" - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | + self + primAcceptFrom: aSocket socketHandle + receiveBufferSize: 8000 + sendBufSize: 8000 + semaIndex: semaIndex + readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primAcceptFrom: aSocket socketHandle - receiveBufferSize: 8000 - sendBufSize: 8000 - semaIndex: semaIndex - readSemaIndex: readSemaIndex - writeSemaIndex: writeSemaIndex. - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>destroy (in category 'initialize-destroy') ----- destroy "Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil)." socketHandle ifNotNil: [ self isValid ifTrue: [ self primSocketDestroy: socketHandle ]. + ExternalSemaphoreTable unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore }. - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. socketHandle := nil. readSemaphore := writeSemaphore := semaphore := nil. self unregister ]! Item was changed: ----- Method: Socket>>finalize (in category 'finalization') ----- finalize + self primSocketDestroyGently: socketHandle. + ExternalSemaphoreTable unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore } - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. ! Item was changed: ----- Method: Socket>>initialize: (in category 'initialize-destroy') ----- initialize: socketType "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: 0 type: socketType receiveBufferSize: 8000 sendBufSize: 8000 semaIndex: semaIndex readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>initialize:family: (in category 'initialize-destroy') ----- initialize: socketType family: family "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + NetNameResolver useOldNetwork ifTrue: [ ^self initialize: socketType ]. + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | - NetNameResolver useOldNetwork ifTrue: [^self initialize: socketType]. - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: family type: socketType receiveBufferSize: 8000 sendBufSize: 8000 semaIndex: semaIndex readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was added: + ----- Method: Socket>>initializeSocketHandleUsing: (in category 'initialize-destroy') ----- + initializeSocketHandleUsing: aBlock + "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." + + | semaphoresAndIndexes semaphores indexes | + semaphoresAndIndexes := ExternalSemaphoreTable newExternalSemaphores: 3. + semaphores := semaphoresAndIndexes at: 1. + indexes := semaphoresAndIndexes at: 2. + semaphore := semaphores at: 1. + readSemaphore := semaphores at: 2. + writeSemaphore := semaphores at: 3. + (socketHandle := aBlock valueWithArguments: indexes) + ifNotNil: [ self register ] + ifNil: [ + "socket creation failed" + semaphore := readSemaphore := writeSemaphore := nil. + ExternalSemaphoreTable unregisterExternalObjects: semaphores ]! From commits at source.squeak.org Sat Oct 25 23:54:35 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 25 23:54:40 2014 Subject: [squeak-dev] The Inbox: Kernel-ul.883.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-ul.883.mcz ==================== Summary ==================== Name: Kernel-ul.883 Author: ul Time: 26 October 2014, 1:45:11.609 am UUID: 362f65e8-603d-452d-b26d-6df0bc85022b Ancestors: Kernel-ul.880 - use ExternalSemaphoreTable instead of Smalltalk - added #excessSignals accessor to Semaphore =============== Diff against Kernel-ul.880 =============== Item was changed: ----- Method: EventSensor>>shutDown (in category 'initialize') ----- shutDown + super shutDown. EventTicklerProcess ifNotNil: [ EventTicklerProcess terminate. EventTicklerProcess := nil. ]. + inputSemaphore ifNotNil:[ + ExternalSemaphoreTable unregisterExternalObject: inputSemaphore ]. - inputSemaphore ifNotNil:[Smalltalk unregisterExternalObject: inputSemaphore]. ! Item was changed: ----- Method: EventSensor>>startUp (in category 'initialize') ----- startUp "Run the I/O process" self initialize. + self primSetInputSemaphore: (ExternalSemaphoreTable registerExternalObject: inputSemaphore). - self primSetInputSemaphore: (Smalltalk registerExternalObject: inputSemaphore). super startUp. self installEventTickler. Smalltalk isMorphic ifTrue:[self flushAllButDandDEvents]. "Attempt to discover whether the input semaphore is actually being signaled." hasInputSemaphore := false. inputSemaphore initSignals. ! Item was added: + ----- Method: Semaphore>>excessSignals (in category 'accessing') ----- + excessSignals + + ^excessSignals! From commits at source.squeak.org Sat Oct 25 23:54:51 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 25 23:54:52 2014 Subject: [squeak-dev] The Inbox: Files-ul.140.mcz Message-ID: A new version of Files was added to project The Inbox: http://source.squeak.org/inbox/Files-ul.140.mcz ==================== Summary ==================== Name: Files-ul.140 Author: ul Time: 26 October 2014, 1:45:59.442 am UUID: fd217dff-eddb-40c4-93fa-41da16965596 Ancestors: Files-eem.138 - use the new ExternalSemaphoreTable API =============== Diff against Files-eem.138 =============== Item was changed: ----- Method: AsyncFile>>close (in category 'as yet unclassified') ----- close fileHandle ifNil: [^ self]. "already closed" self primClose: fileHandle. + ExternalSemaphoreTable unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: semaphore. semaphore := nil. fileHandle := nil. ! Item was changed: ----- Method: AsyncFile>>open:forWrite: (in category 'as yet unclassified') ----- open: fullFileName forWrite: aBoolean "Open a file of the given name, and return a handle for that file. Answer the receiver if the primitive succeeds, nil otherwise. If openForWrite is true, then: if there is no existing file with this name, then create one else open the existing file in read-write mode otherwise: if there is an existing file with this name, then open it read-only else answer nil." "Note: if an exisiting file is opened for writing, it is NOT truncated. If truncation is desired, the file should be deleted before being opened as an asynchronous file." "Note: On some platforms (e.g., Mac), a file can only have one writer at a time." - | semaIndex | name := fullFileName. writeable := aBoolean. + ^ExternalSemaphoreTable newExternalSemaphoreDo: [ :newSemaphore :index | + fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: index. + fileHandle + ifNotNil: [ + semaphore := newSemaphore. + self ] + ifNil: [ + ExternalSemaphoreTable unregisterExternalObject: newSemaphore. + nil ] ]! - semaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: semaIndex. - fileHandle ifNil: [ - Smalltalk unregisterExternalObject: semaphore. - semaphore := nil. - ^ nil]. - ! Item was changed: ----- Method: StandardFileStream>>post:target:url:ifError: (in category 'browser requests') ----- post: data target: target url: url ifError: errorBlock "Post data to the given URL. The returned file stream contains the reply of the server. If Squeak is not running in a browser evaluate errorBlock" + - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + ExternalSemaphoreTable newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLPost: url target: target data: data semaIndex: index. + request ifNil: [ + ExternalSemaphoreTable unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. + result ifTrue: [ fileID := self primURLRequestFileHandle: request ]. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLPost: url target: target data: data semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. - result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. + ExternalSemaphoreTable unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! Item was changed: ----- Method: StandardFileStream>>requestURL:target:ifError: (in category 'browser requests') ----- requestURL: url target: target ifError: errorBlock "Request to go to the target for the given URL. If Squeak is not running in a browser evaluate errorBlock" - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + ExternalSemaphoreTable newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLRequest: url target: target semaIndex: index. + request ifNil: [ + ExternalSemaphoreTable unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url target: target semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. self primURLRequestDestroy: request. + ExternalSemaphoreTable unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! Item was changed: ----- Method: StandardFileStream>>requestURLStream:ifError: (in category 'browser requests') ----- requestURLStream: url ifError: errorBlock "Request a FileStream for the given URL. If Squeak is not running in a browser evaluate errorBlock" "FileStream requestURLStream:'http://www.squeak.org'" + - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + ExternalSemaphoreTable newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLRequest: url semaIndex: index. + request ifNil: [ + ExternalSemaphoreTable unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. + result ifTrue: [ fileID := self primURLRequestFileHandle: request ]. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. - result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. + ExternalSemaphoreTable unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! From commits at source.squeak.org Sat Oct 25 23:55:07 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sat Oct 25 23:55:12 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141025235507.13579.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007345.html Name: Installer-Core-ul.395 Ancestors: Installer-Core-nice.394 - added #squeakInbox and #squeakTrunk accessors ============================================= From leves at elte.hu Sun Oct 26 00:06:20 2014 From: leves at elte.hu (Levente Uzonyi) Date: Sun Oct 26 00:06:26 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <20141025204557.GA94822@shell.msen.com> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> Message-ID: I've uploaded the new versions of the packages to The Inbox, and moved the old ones to The Treated Inbox. The main difference is that the Semaphore class is not modified, and its instances are handled like any other object. There's also a new #cleanUp: method which will allow freeing up some memory. And the caches are shrinked whenever the external objects are wiped. Since Semaphores don't know their indexes anymore, the new part of the API has also changed. The following snippet will load the new versions to an up-to-date Trunk image: Installer squeakInbox package: 'System-ul.687'; package: 'Sound-ul.40'; package: 'Kernel-ul.883'; package: 'Network-ul.154'; package: 'Files-ul.140'; install Levente On Sat, 25 Oct 2014, David T. Lewis wrote: > On Sat, Oct 25, 2014 at 10:02:22PM +0200, Levente Uzonyi wrote: >> On Sat, 25 Oct 2014, David T. Lewis wrote: >> >>> On Fri, Oct 24, 2014 at 09:52:11PM +0200, Levente Uzonyi wrote: >>>> On Fri, 24 Oct 2014, Bert Freudenberg wrote: >>>> >>>>> Another thought: is it really necessary to cache the index in the >>>>> semaphore? Wouldn't scanning the externalObjectsTable for self be >>>>> efficient enough? It's pretty small, after all. >>>> >>>> That's exactly what the current implementation does (scans the table), and >>>> this is what I want to avoid, because it doesn't scale. The table is small >>>> when you start your image, but it can easily grow large - especially on a >>>> server (3 semaphores per socket) - and it never gets shrinked. So once it >>>> grows, it'll stay slow "forever". >>>> >>>> And no, it's not absolutely necessary to store the index in the >>>> semaphores. The new implementation uses an IdentityDictionary to store the >>>> indexes of non-semaphores. The same method could work for semaphores too. >>>> But it's convenient to store the index in the semaphore, otherwise the >>>> method which creates and registers a new semaphore has to return two >>>> values - the index and the semaphore - which is cumbersome. >>>> It's also faster to ask for a new Semaphore from the >>>> ExternalSemaphoreTable, because that way it knows that the >>>> Semaphore is not registered. >>>> >>> >>> I don't see the indexesByObjects dictionary actually being updated, except >>> in the case of setting a new externalObjectsArray in the >>> ExternalSemaphoreTable. >>> I think I am overlooking something? >> >> It's updated in #safelyRegisterExternalObject: and >> #safelyUnregisterExternalObject:, but - as the class comment states - it's >> only used for non-Semaphores. >> >> Based on the feedback there's too much resistance to add an instance >> variable to Semaphore, so I'm about to remove that part from the >> implementation. > > I don't think the instance variable is horrible, but I do think it would > feel cleaner if you can do without it, so +1 if you are able to do that. > > Thanks > Dave > > > From lewis at mail.msen.com Sun Oct 26 00:23:51 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sun Oct 26 00:23:54 2014 Subject: [squeak-dev] Why isn't BlockClosureTest>>testCull failing? Message-ID: <20141026002351.GA23495@shell.msen.com> If we have this: [ :x | ] value: 1 ==> nil And this: ([ :x | ] cull: 1) ==> nil But in BlockClosureTest>>testCull, we have this: self assert: 1 equals: ([ :x | ] cull: 1). The test passes. How is this possible? If I rewrite that line in the test as follows, then it fails as I would expect: foo := [ :x | ] cull: 1. self assert: 1 equals: foo. Ah, but wait. If I revert the test method back to the original, presumably recompiling it in the process, the test now fails exactly as I would have expected. The test also fails in the way I would expect in a 68002 format image, which is what prompted me to ask the question. The previous version of #testCull and related tests seem to pass and look plausibly correct to me. The current (newer) version looks wrong to me, but seems to inexplicably pass until the test is recompiled. Dave From leves at elte.hu Sun Oct 26 00:35:23 2014 From: leves at elte.hu (Levente Uzonyi) Date: Sun Oct 26 00:35:30 2014 Subject: [squeak-dev] Why isn't BlockClosureTest>>testCull failing? In-Reply-To: <20141026002351.GA23495@shell.msen.com> References: <20141026002351.GA23495@shell.msen.com> Message-ID: I think that behavior was changed not too long ago (1-2 years maybe). If you decompile the method you'll see that it's actually self assert: 1 equals: ([:x | x] cull: 1). It's because Squeak used to return the value of the last argument if the block was empty, but had arguments. The code should be self assert: nil equals: ([ :x | ] cull: 1). Levente On Sat, 25 Oct 2014, David T. Lewis wrote: > If we have this: > [ :x | ] value: 1 ==> nil > > And this: > ([ :x | ] cull: 1) ==> nil > > But in BlockClosureTest>>testCull, we have this: > > self assert: 1 equals: ([ :x | ] cull: 1). > > The test passes. How is this possible? > > If I rewrite that line in the test as follows, then it fails as I would expect: > > foo := [ :x | ] cull: 1. > self assert: 1 equals: foo. > > Ah, but wait. If I revert the test method back to the original, presumably > recompiling it in the process, the test now fails exactly as I would have > expected. > > The test also fails in the way I would expect in a 68002 format image, > which is what prompted me to ask the question. > > The previous version of #testCull and related tests seem to pass and look > plausibly correct to me. The current (newer) version looks wrong to me, but > seems to inexplicably pass until the test is recompiled. > > Dave > > > From lewis at mail.msen.com Sun Oct 26 01:06:33 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sun Oct 26 01:06:35 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> Message-ID: <20141026010633.GB23495@shell.msen.com> On Sun, Oct 26, 2014 at 02:06:20AM +0200, Levente Uzonyi wrote: > I've uploaded the new versions of the packages to The Inbox, and moved the > old ones to The Treated Inbox. > The main difference is that the Semaphore class is not modified, and its > instances are handled like any other object. There's also a new #cleanUp: > method which will allow freeing up some memory. And the caches are > shrinked whenever the external objects are wiped. > Since Semaphores don't know their indexes anymore, the new part of the API > has also changed. > The following snippet will load the new versions to an up-to-date Trunk > image: > > Installer squeakInbox > package: 'System-ul.687'; > package: 'Sound-ul.40'; > package: 'Kernel-ul.883'; > package: 'Network-ul.154'; > package: 'Files-ul.140'; > install > > > Levente > I like this a lot. Not only does it provide the ExternalSemaphoreTable improvements, but I also find that when I restart my image with OSProcess loaded, the indexesByObjects dictionary clearly shows the semaphore that was registered for the child process watcher at image startup. Thus an explorer on the ExternalSemaphoreTable will display semaphores associated with processes that wait on them, which also identifies the process waiting on that semaphore. You can see this right in the object explorer. Very nice! I note that a Semaphore can still know its external objects index by querying the ExternalSemaphoreTable: Semaphore>>externalIndex ^ExternalSemaphoreTable externalIndexFor: self ExternalSemaphoreTable class>>externalIndexFor: anObject ^self current indexesByObjects at: anObject ifAbsent: [nil] ExternalSemaphoreTable>>indexesByObjects ^indexesByObjects Dave From leves at elte.hu Sun Oct 26 02:50:36 2014 From: leves at elte.hu (Levente Uzonyi) Date: Sun Oct 26 02:50:42 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <20141026010633.GB23495@shell.msen.com> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026010633.GB23495@shell.msen.com> Message-ID: On Sat, 25 Oct 2014, David T. Lewis wrote: > On Sun, Oct 26, 2014 at 02:06:20AM +0200, Levente Uzonyi wrote: >> I've uploaded the new versions of the packages to The Inbox, and moved the >> old ones to The Treated Inbox. >> The main difference is that the Semaphore class is not modified, and its >> instances are handled like any other object. There's also a new #cleanUp: >> method which will allow freeing up some memory. And the caches are >> shrinked whenever the external objects are wiped. >> Since Semaphores don't know their indexes anymore, the new part of the API >> has also changed. >> The following snippet will load the new versions to an up-to-date Trunk >> image: >> >> Installer squeakInbox >> package: 'System-ul.687'; >> package: 'Sound-ul.40'; >> package: 'Kernel-ul.883'; >> package: 'Network-ul.154'; >> package: 'Files-ul.140'; >> install >> >> >> Levente >> > > I like this a lot. Not only does it provide the ExternalSemaphoreTable > improvements, but I also find that when I restart my image with OSProcess > loaded, the indexesByObjects dictionary clearly shows the semaphore that > was registered for the child process watcher at image startup. Thus an > explorer on the ExternalSemaphoreTable will display semaphores associated > with processes that wait on them, which also identifies the process waiting > on that semaphore. You can see this right in the object explorer. > > Very nice! > > I note that a Semaphore can still know its external objects index by > querying the ExternalSemaphoreTable: > > Semaphore>>externalIndex > ^ExternalSemaphoreTable externalIndexFor: self > > ExternalSemaphoreTable class>>externalIndexFor: anObject > ^self current indexesByObjects at: anObject ifAbsent: [nil] > > ExternalSemaphoreTable>>indexesByObjects > ^indexesByObjects It's doable, but I don't think it's useful. The index is only meaningful for the plugins. Also, most of the API could be added to Semaphore too as Bert suggested. Btw, accessing #indexesByObjects is no thread-safe this way. Levente > > Dave > > > From karlramberg at gmail.com Sun Oct 26 09:30:37 2014 From: karlramberg at gmail.com (karl ramberg) Date: Sun Oct 26 09:30:40 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> Message-ID: One aspect with Etoys projects is that they can not extend the system. It works nicely if you just use Etoys tile scripting. But if you introduce a new class in a project, loading the project in a system that do not have that class will fail. So the use of project as a distribution system of applications will be limited to a certain version of images. Karl On Wed, Oct 22, 2014 at 9:53 PM, Eliot Miranda wrote: > > Hi Stephane, Hi All, > > let me talk a little about the ParcPlace experience, which led to > David Leibs' parcels, whose architecture Fuel uses. > > In the late 80's 90's Peter Deutsch write BOSS (Binary Object Storage > System), a traditional interpretive pickling system defined by a little > bytecoded language. Think of a bytecode as something like "What follows is > an object definition, which is its id followed by size info followed by the > definitions or ids of its sub-parts, including its class", or "What follows > is the id of an already defined object". So the loading interpreter looks > at the next byte in the stream and that tells it what to do. So the > storage is a recursive definition of a graph, much like a recursive grammar > for a programming language. > > This approach is slow (its a bytecode interpreter) and fragile (structures > in the process of being built aren't valid yet, imagine trying to take the > hash of a Set that is only half-way through being materialized). But this > architecture was very common at the time (I wrote something very similar). > The advantage BOSS had was a clumsy hack for versioning. One could specify > blocks that were supplied with the version and state of older objects, and > these blocks could effect shape change etc to bring loaded instances > up-to-date. > > David Leibs has an epiphany as, in the early 90's, ParcPlae was trying to > decompose the VW image (chainsaw was the code name of the VW 2.5 release). > If one groups instances by class, one can instantiate in bulk, creating all > the instances of a particular class in one go, followed by all the > instances of a different class, etc. Then the arc information (the > pointers to objects to be stored in the loaded objects inst vars) can > follow the instance information. So now the file looks like header, names > of classes that are referenced (not defined), definitions of classes, > definitions of instances (essentially class id, count pairs), arc > information. And materializing means finding the classes in the image, > creating the classes in the file, creating the instances, stitching the > graph together, and then performing any post-load actions (rehashing > instances, etc). > > Within months we merged with Digitalk (to form DarcPlace-Dodgytalk) and > were introduced to TeamV's loading model which was very much like > ImageSegments, being based on the VM's object format. Because an > ImageSegment also has imports (references to classes and globals taken from > the host system, not defined in the file) performance doesn't just depend > on loading the segment into memorty. It also depends on how long it takes > to search the system to find imports, etc. In practice we found that a) > Parcels were 4 times faster than BOSS, and b) they were no slower than > Digitalk's image segments. But being independent of the VM's heap format > Parcels had BOSS's flexibility and could support shape change on load, > something ImageSegments *cannot do*. I went on to extend parcels with > support for shape change, plus support for partial loading of code, but I > won't describe that here. Too detailed, even thought its very important. > > Mariano spent time talking with me and Fuel's basic architecture is that > of parcels, but reimplemented to be nicer, more flexible etc. But > essentially Parcels and Fuel are at their core David Leibs' invention. He > came up with the ideas of a) grouping objects by class and b) separating > the arcs from the nodes. > > > Now, where ImageSegments are faster than Parcels is *not* loading. Our > experience with VW vs TeamV showed us that. But they are faster in > collecting the graph of objects to be included. ImageSegments are dead > simple. So IMO the right architecture is to use Parcels' segregation, and > Parcels' "abstract" format (independent of the heap object format) with > ImageSegment's computation of the object graph. Igor Stasenko has > suggested providing the tracing part of ImageSegments (Dan Ingalls' cool > invention of mark the segment root objects, then mark the heap, leaving the > objects to be stored unmarked in the shadow of the marked segment roots) as > a separate primitive. Then this can be quickly partitioned by class and > then written by Smalltalk code. > > The loader can then materialize objects using Smalltalk code, can deal > with shape change, and not be significantly slower than image segments. > Crucially this means that one has a portable, long-lived object storage > format; freeing the VM to evolve its object format without breaking image > segments with every change to the object format. > > I'd be happy to help people working on Fuel by providing that primitive > for anyone who wants to try and reimplement the ImageSegment functonality > (project saving, class faulting, etc) above Fuel. > > > On Wed, Oct 22, 2014 at 11:56 AM, St?phane Ducasse < > stephane.ducasse@inria.fr> wrote: > >> What I can tell you is that instability raised by just having one single >> pointer not in the root objects >> pointing to an element in the segment and the implication of this pointer >> on reloaded segments, (yes I do not want to have two objects in memory >> after loading) makes sure that we will not use IS primitive in Pharo in any >> future. For us this is a non feature. >> >> IS was a nice trick but since having a pointer to an object is so cheap >> and the basis of our computational model >> so this is lead fo unpredictable side effects. We saw that when mariano >> worked during the first year of his PhD (which is a kind of LOOM revisit). >> >> Stef >> > > > > -- > best, > Eliot > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141026/25b492f9/attachment-0001.htm From commits at source.squeak.org Sun Oct 26 11:02:53 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sun Oct 26 11:02:55 2014 Subject: [squeak-dev] The Trunk: Monticello-mtf.603.mcz Message-ID: Matthew Fulmer uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-mtf.603.mcz ==================== Summary ==================== Name: Monticello-mtf.603 Author: mtf Time: 26 October 2014, 6:53:22.573 am UUID: a68bf6b3-1e73-4d62-9fce-cc860422ba2e Ancestors: Monticello-ul.602 Print the right thing for class-side traits =============== Diff against Monticello-ul.602 =============== Item was changed: ----- Method: MCClassDefinition>>printClassSideDefinitionOn: (in category 'printing') ----- printClassSideDefinitionOn: stream stream nextPutAll: self className; nextPutAll: ' class '; + cr; tab. + self hasClassTraitComposition ifTrue: [ + stream + nextPutAll: 'uses: '; + nextPutAll: self classTraitCompositionString; + cr; tab ]. + stream - cr; tab; nextPutAll: 'instanceVariableNames: '; store: self classInstanceVariablesString! Item was added: + ----- Method: MCTraitDefinition>>printClassSideDefinitionOn: (in category 'printing') ----- + printClassSideDefinitionOn: stream + stream + nextPutAll: self className; + nextPutAll: ' classTrait '; + cr; tab; + nextPutAll: 'uses: '; + nextPutAll: self classTraitCompositionString! From lewis at mail.msen.com Sun Oct 26 14:32:06 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Sun Oct 26 14:32:09 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> Message-ID: <20141026143206.GA54624@shell.msen.com> On Sun, Oct 26, 2014 at 02:06:20AM +0200, Levente Uzonyi wrote: > I've uploaded the new versions of the packages to The Inbox, and moved the > old ones to The Treated Inbox. > The main difference is that the Semaphore class is not modified, and its > instances are handled like any other object. There's also a new #cleanUp: > method which will allow freeing up some memory. And the caches are > shrinked whenever the external objects are wiped. > Since Semaphores don't know their indexes anymore, the new part of the API > has also changed. > The following snippet will load the new versions to an up-to-date Trunk > image: > > Installer squeakInbox > package: 'System-ul.687'; > package: 'Sound-ul.40'; > package: 'Kernel-ul.883'; > package: 'Network-ul.154'; > package: 'Files-ul.140'; > install > This looks really good to me. I vote for moving it to trunk. Dave From bert at freudenbergs.de Sun Oct 26 15:35:54 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Sun Oct 26 15:36:01 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> Message-ID: <1B3D5F8A-BFD1-4CB6-8C99-8145983E3724@freudenbergs.de> Skipped content of type multipart/alternative-------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 6139 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141026/9c345761/smime.bin From marianopeck at gmail.com Sun Oct 26 15:41:07 2014 From: marianopeck at gmail.com (Mariano Martinez Peck) Date: Sun Oct 26 15:41:12 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: <1B3D5F8A-BFD1-4CB6-8C99-8145983E3724@freudenbergs.de> References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> <1B3D5F8A-BFD1-4CB6-8C99-8145983E3724@freudenbergs.de> Message-ID: On Sun, Oct 26, 2014 at 12:35 PM, Bert Freudenberg wrote: > > That is not a limitation of ImageSegments per se, but just how they are > used in Etoys. > > I agree at some point. But what if the serializer were able to serialize classes as well? Fuel is able to serialize classes, traits, closures, compiled methods, etc. Of course there are scenarios when this becomes complicated, but for the average it works. > - Bert - > > On 26.10.2014, at 05:30, karl ramberg wrote: > > One aspect with Etoys projects is that they can not extend the system. It > works nicely if you just use Etoys tile scripting. But if you introduce a > new class in a project, loading the project in a system that do not have > that class will fail. So the use of project as a distribution system of > applications will be limited to a certain version of images. > > Karl > > On Wed, Oct 22, 2014 at 9:53 PM, Eliot Miranda > wrote: > >> >> Hi Stephane, Hi All, >> >> let me talk a little about the ParcPlace experience, which led to >> David Leibs' parcels, whose architecture Fuel uses. >> >> In the late 80's 90's Peter Deutsch write BOSS (Binary Object Storage >> System), a traditional interpretive pickling system defined by a little >> bytecoded language. Think of a bytecode as something like "What follows is >> an object definition, which is its id followed by size info followed by the >> definitions or ids of its sub-parts, including its class", or "What follows >> is the id of an already defined object". So the loading interpreter looks >> at the next byte in the stream and that tells it what to do. So the >> storage is a recursive definition of a graph, much like a recursive grammar >> for a programming language. >> >> This approach is slow (its a bytecode interpreter) and fragile >> (structures in the process of being built aren't valid yet, imagine trying >> to take the hash of a Set that is only half-way through being >> materialized). But this architecture was very common at the time (I wrote >> something very similar). The advantage BOSS had was a clumsy hack for >> versioning. One could specify blocks that were supplied with the version >> and state of older objects, and these blocks could effect shape change etc >> to bring loaded instances up-to-date. >> >> David Leibs has an epiphany as, in the early 90's, ParcPlae was trying to >> decompose the VW image (chainsaw was the code name of the VW 2.5 release). >> If one groups instances by class, one can instantiate in bulk, creating all >> the instances of a particular class in one go, followed by all the >> instances of a different class, etc. Then the arc information (the >> pointers to objects to be stored in the loaded objects inst vars) can >> follow the instance information. So now the file looks like header, names >> of classes that are referenced (not defined), definitions of classes, >> definitions of instances (essentially class id, count pairs), arc >> information. And materializing means finding the classes in the image, >> creating the classes in the file, creating the instances, stitching the >> graph together, and then performing any post-load actions (rehashing >> instances, etc). >> >> Within months we merged with Digitalk (to form DarcPlace-Dodgytalk) and >> were introduced to TeamV's loading model which was very much like >> ImageSegments, being based on the VM's object format. Because an >> ImageSegment also has imports (references to classes and globals taken from >> the host system, not defined in the file) performance doesn't just depend >> on loading the segment into memorty. It also depends on how long it takes >> to search the system to find imports, etc. In practice we found that a) >> Parcels were 4 times faster than BOSS, and b) they were no slower than >> Digitalk's image segments. But being independent of the VM's heap format >> Parcels had BOSS's flexibility and could support shape change on load, >> something ImageSegments *cannot do*. I went on to extend parcels with >> support for shape change, plus support for partial loading of code, but I >> won't describe that here. Too detailed, even thought its very important. >> >> Mariano spent time talking with me and Fuel's basic architecture is that >> of parcels, but reimplemented to be nicer, more flexible etc. But >> essentially Parcels and Fuel are at their core David Leibs' invention. He >> came up with the ideas of a) grouping objects by class and b) separating >> the arcs from the nodes. >> >> >> Now, where ImageSegments are faster than Parcels is *not* loading. Our >> experience with VW vs TeamV showed us that. But they are faster in >> collecting the graph of objects to be included. ImageSegments are dead >> simple. So IMO the right architecture is to use Parcels' segregation, and >> Parcels' "abstract" format (independent of the heap object format) with >> ImageSegment's computation of the object graph. Igor Stasenko has >> suggested providing the tracing part of ImageSegments (Dan Ingalls' cool >> invention of mark the segment root objects, then mark the heap, leaving the >> objects to be stored unmarked in the shadow of the marked segment roots) as >> a separate primitive. Then this can be quickly partitioned by class and >> then written by Smalltalk code. >> >> The loader can then materialize objects using Smalltalk code, can deal >> with shape change, and not be significantly slower than image segments. >> Crucially this means that one has a portable, long-lived object storage >> format; freeing the VM to evolve its object format without breaking image >> segments with every change to the object format. >> >> I'd be happy to help people working on Fuel by providing that primitive >> for anyone who wants to try and reimplement the ImageSegment functonality >> (project saving, class faulting, etc) above Fuel. >> >> >> On Wed, Oct 22, 2014 at 11:56 AM, St?phane Ducasse < >> stephane.ducasse@inria.fr> wrote: >> >>> What I can tell you is that instability raised by just having one single >>> pointer not in the root objects >>> pointing to an element in the segment and the implication of this >>> pointer on reloaded segments, (yes I do not want to have two objects in >>> memory after loading) makes sure that we will not use IS primitive in Pharo >>> in any future. For us this is a non feature. >>> >>> IS was a nice trick but since having a pointer to an object is so cheap >>> and the basis of our computational model >>> so this is lead fo unpredictable side effects. We saw that when mariano >>> worked during the first year of his PhD (which is a kind of LOOM revisit). >>> >>> Stef >>> >> >> >> >> -- >> best, >> Eliot >> >> > > > -- Mariano http://marianopeck.wordpress.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141026/cd2da33c/attachment.htm From eliot.miranda at gmail.com Sun Oct 26 15:54:57 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sun Oct 26 15:55:09 2014 Subject: [Vm-dev] [squeak-dev] re: Image Segment semantics and weakness In-Reply-To: References: <51099.181.111.0.80.1413853013.squirrel@webmail.dc.uba.ar> <7F21EA53-7B02-4A8D-8253-6B0609FAC4E6@freudenbergs.de> <5A42E695-B44B-45AD-9F14-1F0772843640@inria.fr> <1B3D5F8A-BFD1-4CB6-8C99-8145983E3724@freudenbergs.de> Message-ID: On Oct 26, 2014, at 8:41 AM, Mariano Martinez Peck wrote: > > > On Sun, Oct 26, 2014 at 12:35 PM, Bert Freudenberg wrote: >> >> That is not a limitation of ImageSegments per se, but just how they are used in Etoys. > > I agree at some point. But what if the serializer were able to serialize classes as well? Fuel is able to serialize classes, traits, closures, compiled methods, etc. Of course there are scenarios when this becomes complicated, but for the average it works. There's no restriction in the kinds if object ImageSegments can store either. Including classes, contexts, etc presents no problem (*). The only real difference is that ImageSegments are tied to the VM's object representation whereas systems like Fuel are portable. That's a key advantage. (*) I realize that Cog's implementations are currently broken w.r.t. Contexts and should be fixed. Because of context-to-stack mapping the segment writer should be careful to store a married context as an in married context. Luckily this is just a small matter if programming ;-) > >> - Bert - >> >> On 26.10.2014, at 05:30, karl ramberg wrote: >> >>> One aspect with Etoys projects is that they can not extend the system. It works nicely if you just use Etoys tile scripting. But if you introduce a new class in a project, loading the project in a system that do not have that class will fail. So the use of project as a distribution system of applications will be limited to a certain version of images. >>> >>> Karl >>> >>> On Wed, Oct 22, 2014 at 9:53 PM, Eliot Miranda wrote: >>>> >>>> Hi Stephane, Hi All, >>>> >>>> let me talk a little about the ParcPlace experience, which led to David Leibs' parcels, whose architecture Fuel uses. >>>> >>>> In the late 80's 90's Peter Deutsch write BOSS (Binary Object Storage System), a traditional interpretive pickling system defined by a little bytecoded language. Think of a bytecode as something like "What follows is an object definition, which is its id followed by size info followed by the definitions or ids of its sub-parts, including its class", or "What follows is the id of an already defined object". So the loading interpreter looks at the next byte in the stream and that tells it what to do. So the storage is a recursive definition of a graph, much like a recursive grammar for a programming language. >>>> >>>> This approach is slow (its a bytecode interpreter) and fragile (structures in the process of being built aren't valid yet, imagine trying to take the hash of a Set that is only half-way through being materialized). But this architecture was very common at the time (I wrote something very similar). The advantage BOSS had was a clumsy hack for versioning. One could specify blocks that were supplied with the version and state of older objects, and these blocks could effect shape change etc to bring loaded instances up-to-date. >>>> >>>> David Leibs has an epiphany as, in the early 90's, ParcPlae was trying to decompose the VW image (chainsaw was the code name of the VW 2.5 release). If one groups instances by class, one can instantiate in bulk, creating all the instances of a particular class in one go, followed by all the instances of a different class, etc. Then the arc information (the pointers to objects to be stored in the loaded objects inst vars) can follow the instance information. So now the file looks like header, names of classes that are referenced (not defined), definitions of classes, definitions of instances (essentially class id, count pairs), arc information. And materializing means finding the classes in the image, creating the classes in the file, creating the instances, stitching the graph together, and then performing any post-load actions (rehashing instances, etc). >>>> >>>> Within months we merged with Digitalk (to form DarcPlace-Dodgytalk) and were introduced to TeamV's loading model which was very much like ImageSegments, being based on the VM's object format. Because an ImageSegment also has imports (references to classes and globals taken from the host system, not defined in the file) performance doesn't just depend on loading the segment into memorty. It also depends on how long it takes to search the system to find imports, etc. In practice we found that a) Parcels were 4 times faster than BOSS, and b) they were no slower than Digitalk's image segments. But being independent of the VM's heap format Parcels had BOSS's flexibility and could support shape change on load, something ImageSegments *cannot do*. I went on to extend parcels with support for shape change, plus support for partial loading of code, but I won't describe that here. Too detailed, even thought its very important. >>>> >>>> Mariano spent time talking with me and Fuel's basic architecture is that of parcels, but reimplemented to be nicer, more flexible etc. But essentially Parcels and Fuel are at their core David Leibs' invention. He came up with the ideas of a) grouping objects by class and b) separating the arcs from the nodes. >>>> >>>> >>>> Now, where ImageSegments are faster than Parcels is *not* loading. Our experience with VW vs TeamV showed us that. But they are faster in collecting the graph of objects to be included. ImageSegments are dead simple. So IMO the right architecture is to use Parcels' segregation, and Parcels' "abstract" format (independent of the heap object format) with ImageSegment's computation of the object graph. Igor Stasenko has suggested providing the tracing part of ImageSegments (Dan Ingalls' cool invention of mark the segment root objects, then mark the heap, leaving the objects to be stored unmarked in the shadow of the marked segment roots) as a separate primitive. Then this can be quickly partitioned by class and then written by Smalltalk code. >>>> >>>> The loader can then materialize objects using Smalltalk code, can deal with shape change, and not be significantly slower than image segments. Crucially this means that one has a portable, long-lived object storage format; freeing the VM to evolve its object format without breaking image segments with every change to the object format. >>>> >>>> I'd be happy to help people working on Fuel by providing that primitive for anyone who wants to try and reimplement the ImageSegment functonality (project saving, class faulting, etc) above Fuel. >>>> >>>> >>>> On Wed, Oct 22, 2014 at 11:56 AM, St?phane Ducasse wrote: >>>>> What I can tell you is that instability raised by just having one single pointer not in the root objects >>>>> pointing to an element in the segment and the implication of this pointer on reloaded segments, (yes I do not want to have two objects in memory after loading) makes sure that we will not use IS primitive in Pharo in any future. For us this is a non feature. >>>>> >>>>> IS was a nice trick but since having a pointer to an object is so cheap and the basis of our computational model >>>>> so this is lead fo unpredictable side effects. We saw that when mariano worked during the first year of his PhD (which is a kind of LOOM revisit). >>>>> >>>>> Stef >>>> >>>> >>>> >>>> -- >>>> best, >>>> Eliot >>> > > > > -- > Mariano > http://marianopeck.wordpress.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141026/7445e7b2/attachment.htm From bert at freudenbergs.de Sun Oct 26 16:36:13 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Sun Oct 26 16:36:19 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <20141026143206.GA54624@shell.msen.com> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026143206.GA54624@shell.msen.com> Message-ID: On 26.10.2014, at 10:32, David T. Lewis wrote: > On Sun, Oct 26, 2014 at 02:06:20AM +0200, Levente Uzonyi wrote: >> I've uploaded the new versions of the packages to The Inbox, and moved the >> old ones to The Treated Inbox. >> The main difference is that the Semaphore class is not modified, and its >> instances are handled like any other object. There's also a new #cleanUp: >> method which will allow freeing up some memory. And the caches are >> shrinked whenever the external objects are wiped. >> Since Semaphores don't know their indexes anymore, the new part of the API >> has also changed. >> The following snippet will load the new versions to an up-to-date Trunk >> image: >> >> Installer squeakInbox >> package: 'System-ul.687'; >> package: 'Sound-ul.40'; >> package: 'Kernel-ul.883'; >> package: 'Network-ul.154'; >> package: 'Files-ul.140'; >> install >> > > This looks really good to me. I vote for moving it to trunk. > > Dave Yes, the implementation itself looks good. It's just a bit unfortunate that the user code gets even less generic than it was before. - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141026/c8e300d0/smime.bin From leves at elte.hu Sun Oct 26 18:38:14 2014 From: leves at elte.hu (Levente Uzonyi) Date: Sun Oct 26 18:38:17 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026143206.GA54624@shell.msen.com> Message-ID: On Sun, 26 Oct 2014, Bert Freudenberg wrote: > > On 26.10.2014, at 10:32, David T. Lewis wrote: > >> On Sun, Oct 26, 2014 at 02:06:20AM +0200, Levente Uzonyi wrote: >>> I've uploaded the new versions of the packages to The Inbox, and moved the >>> old ones to The Treated Inbox. >>> The main difference is that the Semaphore class is not modified, and its >>> instances are handled like any other object. There's also a new #cleanUp: >>> method which will allow freeing up some memory. And the caches are >>> shrinked whenever the external objects are wiped. >>> Since Semaphores don't know their indexes anymore, the new part of the API >>> has also changed. >>> The following snippet will load the new versions to an up-to-date Trunk >>> image: >>> >>> Installer squeakInbox >>> package: 'System-ul.687'; >>> package: 'Sound-ul.40'; >>> package: 'Kernel-ul.883'; >>> package: 'Network-ul.154'; >>> package: 'Files-ul.140'; >>> install >>> >> >> This looks really good to me. I vote for moving it to trunk. >> >> Dave > > Yes, the implementation itself looks good. > > It's just a bit unfortunate that the user code gets even less generic than it was before. What do you mean by "less generic"? Is it that the code says ExternalSemaphoreTable instead of Smalltalk? The code was extracted from Smalltalk more than 14 years ago, because "It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary" I could have left all (indirect) users of the ExternalSemaphoreTable unchanged, but I think we really should make SmalltalkImage less monolithic and remove those "proxy" methods from it in the near future. The new methods give additional performance boost (because we know that the Semaphores are new, so we don't have to check if they are already included, and because we don't have to wait for the lock multiple times, when multiple Semaphores are registered or unregistered) especially for Sockets, which was the main reason I spent so much time on this. Levente > > - Bert - > > From bernhard at pieber.com Sun Oct 26 20:46:04 2014 From: bernhard at pieber.com (Bernhard Pieber) Date: Sun Oct 26 20:46:10 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: References: Message-ID: <3C93CDF6-2BC1-464D-B280-C28393F02DC2@pieber.com> This is really great news. I tried it out with the latest CogSpur VM 3114 and the latest image from October 17th. When I update Squeak it runs into Merging Collections.spur-nice.583. I wonder what to do now? All Newer and Merge? Cheers, Bernhard > Am 17.10.2014 um 08:51 schrieb Eliot Miranda : > > Hi All, > > finally the Spur Squeak trunk image is updateable. The image in http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created today and thanks to Bert Freudenberg's latest Monticello work can be updated independently of the non-Spur trunk. Spur VMs are available in http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they appear). Without wanting to appear too overconfident the Spur system looks to be ready for use apart from image segments (which I hope to have working some time next month). I'm really interested in having this stress tested by as many people as possible. Spur really does offer a significant performance and functionality improvement over the current system, but it needs testing to ensure its reliability. > > Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I hope Pharo 4 Spur will be available soon. > > As far as trunk goes, using Spur alongside non-Spur trunk is going to be difficult to manage for the near future. Right now, Spur modifies the Collections, Compiler, Kernel and System packages, and this is done by auto-editing the non-Spur versions of those packages, something I do periodically as new versions arrive. I also auto-edit trunk configurations (the part of the image update scheme that ensures packages are loaded in the right order when there are dependencies between packages) from non-Spur "update" to Spur "update.spur" forms. This at east means that Spur can keep up with trunk. But it does /not/ provide a way of committing to Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting out of sync with non-Spur trunk. Note that apart from these packages, one /can/ safely commit any other package from a Spur image to trunk. > > Right now the plan is to release both V3 (the pre-Spur format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak 5.0). This isn't my preference. I'd like to see just Spur released, once reliability is verified. But I understand the safety and backward-compatibility concerns (Spur won't be able to load V3 image segments, and vice verse). The issue is of course that we have this tricky package situation to manage where, to keep the two systems in sync, modifications to Collections, Compiler, Kernel and System need to be committed from V3 and auto-edited to Spur. I think that's too clumsy to be practicable. Perhaps allowing the two systems to fork and doing a manual merge will be acceptable, but it'll be work to keep them in sync. > -- > best, > Eliot > From eliot.miranda at gmail.com Sun Oct 26 20:49:53 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sun Oct 26 20:49:58 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: <3C93CDF6-2BC1-464D-B280-C28393F02DC2@pieber.com> References: <3C93CDF6-2BC1-464D-B280-C28393F02DC2@pieber.com> Message-ID: On Sun, Oct 26, 2014 at 1:46 PM, Bernhard Pieber wrote: > This is really great news. I tried it out with the latest CogSpur VM 3114 > and the latest image from October 17th. When I update Squeak it runs into > Merging Collections.spur-nice.583. I wonder what to do now? All Newer and > Merge? > Yes, and afterwards, if the dirty package bothers you, resolve the dirty package by manually loading the latest Spur version. This crap should be temporary. Once we release things will work out (no patching and multiple parents any more). > Cheers, > Bernhard > > > Am 17.10.2014 um 08:51 schrieb Eliot Miranda : > > > > Hi All, > > > > finally the Spur Squeak trunk image is updateable. The image in > http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created > today and thanks to Bert Freudenberg's latest Monticello work can be > updated independently of the non-Spur trunk. Spur VMs are available in > http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they > appear). Without wanting to appear too overconfident the Spur system looks > to be ready for use apart from image segments (which I hope to have working > some time next month). I'm really interested in having this stress tested > by as many people as possible. Spur really does offer a significant > performance and functionality improvement over the current system, but it > needs testing to ensure its reliability. > > > > Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I > hope Pharo 4 Spur will be available soon. > > > > As far as trunk goes, using Spur alongside non-Spur trunk is going to be > difficult to manage for the near future. Right now, Spur modifies the > Collections, Compiler, Kernel and System packages, and this is done by > auto-editing the non-Spur versions of those packages, something I do > periodically as new versions arrive. I also auto-edit trunk configurations > (the part of the image update scheme that ensures packages are loaded in > the right order when there are dependencies between packages) from non-Spur > "update" to Spur "update.spur" forms. This at east means that Spur can > keep up with trunk. But it does /not/ provide a way of committing to > Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting > out of sync with non-Spur trunk. Note that apart from these packages, one > /can/ safely commit any other package from a Spur image to trunk. > > > > Right now the plan is to release both V3 (the pre-Spur format) and Spur > versions of Squeak 4.6 (I hope it'll be called Squeak 5.0). This isn't my > preference. I'd like to see just Spur released, once reliability is > verified. But I understand the safety and backward-compatibility concerns > (Spur won't be able to load V3 image segments, and vice verse). The issue > is of course that we have this tricky package situation to manage where, to > keep the two systems in sync, modifications to Collections, Compiler, > Kernel and System need to be committed from V3 and auto-edited to Spur. I > think that's too clumsy to be practicable. Perhaps allowing the two > systems to fork and doing a manual merge will be acceptable, but it'll be > work to keep them in sync. > > -- > > best, > > Eliot > > > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141026/25795218/attachment-0001.htm From bernhard at pieber.com Sun Oct 26 22:19:39 2014 From: bernhard at pieber.com (Bernhard Pieber) Date: Sun Oct 26 22:19:44 2014 Subject: [squeak-dev] New Spur trunk image available In-Reply-To: References: <3C93CDF6-2BC1-464D-B280-C28393F02DC2@pieber.com> Message-ID: Hi Eliot, Thanks for the tip. You are right, I like my Monticello packages clean. ;-) I loaded Collections.spur-cmm.585. All clean now. I am looking forward to the release. Cheers, Bernhard > Am 26.10.2014 um 21:49 schrieb Eliot Miranda : > > On Sun, Oct 26, 2014 at 1:46 PM, Bernhard Pieber wrote: > This is really great news. I tried it out with the latest CogSpur VM 3114 and the latest image from October 17th. When I update Squeak it runs into Merging Collections.spur-nice.583. I wonder what to do now? All Newer and Merge? > > Yes, and afterwards, if the dirty package bothers you, resolve the dirty package by manually loading the latest Spur version. This crap should be temporary. Once we release things will work out (no patching and multiple parents any more). > > > Cheers, > Bernhard > > > Am 17.10.2014 um 08:51 schrieb Eliot Miranda : > > > > Hi All, > > > > finally the Spur Squeak trunk image is updateable. The image in http://www.mirandabanda.org/files/Cog/SpurImages/2014-10-16/ was created today and thanks to Bert Freudenberg's latest Monticello work can be updated independently of the non-Spur trunk. Spur VMs are available in http://www.mirandabanda.org/files/Cog/VM/VM.r3105/ (and later as they appear). Without wanting to appear too overconfident the Spur system looks to be ready for use apart from image segments (which I hope to have working some time next month). I'm really interested in having this stress tested by as many people as possible. Spur really does offer a significant performance and functionality improvement over the current system, but it needs testing to ensure its reliability. > > > > Esteban Lorenzano is hard at work on the Pharo bootstrap for Spur so I hope Pharo 4 Spur will be available soon. > > > > As far as trunk goes, using Spur alongside non-Spur trunk is going to be difficult to manage for the near future. Right now, Spur modifies the Collections, Compiler, Kernel and System packages, and this is done by auto-editing the non-Spur versions of those packages, something I do periodically as new versions arrive. I also auto-edit trunk configurations (the part of the image update scheme that ensures packages are loaded in the right order when there are dependencies between packages) from non-Spur "update" to Spur "update.spur" forms. This at east means that Spur can keep up with trunk. But it does /not/ provide a way of committing to Collections.spur, Compiler.spur, Kernel.spur or System.spur without getting out of sync with non-Spur trunk. Note that apart from these packages, one /can/ safely commit any other package from a Spur image to trunk. > > > > Right now the plan is to release both V3 (the pre-Spur format) and Spur versions of Squeak 4.6 (I hope it'll be called Squeak 5.0). This isn't my preference. I'd like to see just Spur released, once reliability is verified. But I understand the safety and backward-compatibility concerns (Spur won't be able to load V3 image segments, and vice verse). The issue is of course that we have this tricky package situation to manage where, to keep the two systems in sync, modifications to Collections, Compiler, Kernel and System need to be committed from V3 and auto-edited to Spur. I think that's too clumsy to be practicable. Perhaps allowing the two systems to fork and doing a manual merge will be acceptable, but it'll be work to keep them in sync. > > -- > > best, > > Eliot > > > > > > > > -- > best, > Eliot > From commits at source.squeak.org Sun Oct 26 23:05:03 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sun Oct 26 23:05:04 2014 Subject: [squeak-dev] The Inbox: Collections-ul.586.mcz Message-ID: A new version of Collections was added to project The Inbox: http://source.squeak.org/inbox/Collections-ul.586.mcz ==================== Summary ==================== Name: Collections-ul.586 Author: ul Time: 27 October 2014, 12:52:51.886 am UUID: 4c460675-3065-4b48-aa30-52ad67e15076 Ancestors: Collections-cmm.585 Symbol table changes: - ensure that enumerations stay consistent - avoid read-write and write-write race conditions - added a safe #condenseNewSymbols method, which is a replacement for former unsafe methods (#shutDown: and #compactSymbolTable). It's also automatically triggered whenever there are more than 1000 NewSymbols. - deprecated #compactSymbolTable - updated some comments Note that interning many symbols is a bit slower, but thread safety is more important. =============== Diff against Collections-cmm.585 =============== Item was changed: ----- Method: Symbol class>>allSymbolTablesDo: (in category 'class initialization') ----- allSymbolTablesDo: aBlock + + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + originalNewSymbols do: aBlock. + originalSymbolTable do: aBlock.! - - NewSymbols do: aBlock. - SymbolTable do: aBlock.! Item was changed: ----- Method: Symbol class>>allSymbolTablesDo:after: (in category 'class initialization') ----- allSymbolTablesDo: aBlock after: aSymbol + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + (originalNewSymbols includes: aSymbol) - (NewSymbols includes: aSymbol) ifTrue: [ + originalNewSymbols do: aBlock after: aSymbol. + originalSymbolTable do: aBlock after: aSymbol ] - NewSymbols do: aBlock after: aSymbol. - SymbolTable do: aBlock after: aSymbol ] ifFalse: [ + originalSymbolTable do: aBlock after: aSymbol. + originalNewSymbols do: aBlock after: aSymbol ] - SymbolTable do: aBlock after: aSymbol. - NewSymbols do: aBlock after: aSymbol ] ! Item was changed: ----- Method: Symbol class>>allSymbols (in category 'access') ----- allSymbols "Answer all interned symbols" + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. ^Array + new: originalNewSymbols slowSize + originalSymbolTable slowSize - new: NewSymbols slowSize + SymbolTable slowSize streamContents:[ :stream | stream + nextPutAll: originalNewSymbols; + nextPutAll: originalSymbolTable ] - nextPutAll: NewSymbols; - nextPutAll: SymbolTable ] ! Item was changed: ----- Method: Symbol class>>cleanUp (in category 'class initialization') ----- cleanUp "Flush caches" + self condenseNewSymbols! - self compactSymbolTable.! Item was changed: ----- Method: Symbol class>>compactSymbolTable (in category 'class initialization') ----- compactSymbolTable "Reduce the size of the symbol table so that it holds all existing symbols with 25% free space." + self deprecated: 'Use #condenseNewSymbols instead'. + self condenseNewSymbols! - | oldSize | - Smalltalk garbageCollect. - oldSize := SymbolTable capacity. - SymbolTable compact. - ^(oldSize - SymbolTable capacity) printString, ' slot(s) reclaimed'! Item was added: + ----- Method: Symbol class>>condenseNewSymbols (in category 'private') ----- + condenseNewSymbols + "Move all symbols from NewSymbols to SymbolTable, and compact SymbolTable." + + | originalNewSymbols originalSymbolTable newNewSymbols newSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + newNewSymbols := WeakSet new. + newSymbolTable := originalSymbolTable copy + addAll: originalNewSymbols; + compact; + yourself. + originalNewSymbols == NewSymbols ifFalse: [ + "Some other process has modified the symbols. Try again." + ^self condenseNewSymbols ]. + NewSymbols := newNewSymbols. + SymbolTable := newSymbolTable! Item was changed: ----- Method: Symbol class>>intern: (in category 'instance creation') ----- intern: aStringOrSymbol + | originalNewSymbols | + originalNewSymbols := NewSymbols. ^(self lookup: aStringOrSymbol) ifNil:[ + | aClass aSymbol newNewSymbols | - | aClass aSymbol | aStringOrSymbol isSymbol ifTrue:[ aSymbol := aStringOrSymbol. ] ifFalse:[ aClass := aStringOrSymbol isOctetString ifTrue:[ByteSymbol] ifFalse:[WideSymbol]. aSymbol := aClass new: aStringOrSymbol size. aSymbol string: aStringOrSymbol. ]. + newNewSymbols := originalNewSymbols copyWith: aSymbol. + originalNewSymbols == NewSymbols + ifTrue: [ + NewSymbols := newNewSymbols. + newNewSymbols size > 1000 ifTrue: [ self condenseNewSymbols ]. + aSymbol ] + ifFalse: [ + "Some other process has modified the symbols. Try again." + self intern: aStringOrSymbol ] ]! - NewSymbols add: aSymbol. - aSymbol].! Item was changed: ----- Method: Symbol class>>lookup: (in category 'instance creation') ----- lookup: aStringOrSymbol + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + ^(originalNewSymbols like: aStringOrSymbol) ifNil: [ + originalSymbolTable like: aStringOrSymbol ]! - ^(SymbolTable like: aStringOrSymbol) ifNil: [ - NewSymbols like: aStringOrSymbol - ]! Item was changed: ----- Method: Symbol class>>rehash (in category 'private') ----- + rehash + "Rebuild the hash table, reclaiming unreferenced Symbols. This method will intern all symbols. You're probably looking for #condenseNewSymbols instead." - rehash "Symbol rehash" - "Rebuild the hash table, reclaiming unreferenced Symbols." + | originalNewSymbols originalSymbolTable newNewSymbols newSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + newNewSymbols := WeakSet new. + newSymbolTable := WeakSet withAll: self allSubInstances. + originalNewSymbols == NewSymbols ifFalse: [ + "Some other process has modified the symbols. Try again." + ^self rehash ]. + NewSymbols := newNewSymbols. + SymbolTable := newSymbolTable! - SymbolTable := WeakSet withAll: self allSubInstances. - NewSymbols := WeakSet new.! Item was changed: ----- Method: Symbol class>>shutDown: (in category 'private') ----- shutDown: aboutToQuit + self condenseNewSymbols! - SymbolTable addAll: NewSymbols. - NewSymbols := WeakSet new.! From commits at source.squeak.org Sun Oct 26 23:55:03 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Sun Oct 26 23:55:06 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141026235503.29595.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007346.html Name: Monticello-mtf.603 Ancestors: Monticello-ul.602 Print the right thing for class-side traits ============================================= From lewis at mail.msen.com Mon Oct 27 02:32:10 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Mon Oct 27 02:32:13 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026143206.GA54624@shell.msen.com> Message-ID: <20141027023210.GA76267@shell.msen.com> On Sun, Oct 26, 2014 at 12:36:13PM -0400, Bert Freudenberg wrote: > > On 26.10.2014, at 10:32, David T. Lewis wrote: > > > On Sun, Oct 26, 2014 at 02:06:20AM +0200, Levente Uzonyi wrote: > >> I've uploaded the new versions of the packages to The Inbox, and moved the > >> old ones to The Treated Inbox. > >> The main difference is that the Semaphore class is not modified, and its > >> instances are handled like any other object. There's also a new #cleanUp: > >> method which will allow freeing up some memory. And the caches are > >> shrinked whenever the external objects are wiped. > >> Since Semaphores don't know their indexes anymore, the new part of the API > >> has also changed. > >> The following snippet will load the new versions to an up-to-date Trunk > >> image: > >> > >> Installer squeakInbox > >> package: 'System-ul.687'; > >> package: 'Sound-ul.40'; > >> package: 'Kernel-ul.883'; > >> package: 'Network-ul.154'; > >> package: 'Files-ul.140'; > >> install > >> > > > > This looks really good to me. I vote for moving it to trunk. > > > > Dave > > Yes, the implementation itself looks good. > > It's just a bit unfortunate that the user code gets even less generic than it was before. > Bert, Are you referring to user code that calls e.g. newExternalSemaphoreDo: and receives a semaphore and its index in the external table? This seems quite reasonable to me, and it reads nicely in the Network, File, and Sound code that sends it. Meanwhile, existing code such as OSProcess continues to work without modification. Dave From frank.shearar at gmail.com Mon Oct 27 08:07:34 2014 From: frank.shearar at gmail.com (Frank Shearar) Date: Mon Oct 27 08:07:41 2014 Subject: [squeak-dev] Re: New Cog VMs available In-Reply-To: References: Message-ID: On 25 October 2014 21:51, Eliot Miranda wrote: > ...at http://www.mirandabanda.org/files/Cog/VM/VM.r3114/. > > CogVM binaries as per VMMaker.oscog-eem.913/r3114 build.squeak.org duly updated! frank From commits at source.squeak.org Mon Oct 27 13:03:15 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 13:03:17 2014 Subject: [squeak-dev] The Inbox: Universes-kfr.47.mcz Message-ID: A new version of Universes was added to project The Inbox: http://source.squeak.org/inbox/Universes-kfr.47.mcz ==================== Summary ==================== Name: Universes-kfr.47 Author: kfr Time: 27 October 2014, 2:01:04.363 pm UUID: be75a4ac-e8b3-834d-af8f-23cf47fcac79 Ancestors: Universes-nice.46 Remove entries in world menu =============== Diff against Universes-nice.46 =============== Item was changed: ----- Method: UUniverseBrowser class>>unload (in category 'class initialization') ----- unload + #('Package Universe Browser' 'Universe Browser (basic)') do: [:oldName | + TheWorldMenu unregisterOpenCommand: oldName ].! - TheWorldMenu unregisterOpenCommand: 'Universe Browser (basic)'! From bert at freudenbergs.de Mon Oct 27 14:28:22 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Mon Oct 27 14:28:23 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026143206.GA54624@shell.msen.com> Message-ID: <3B1B8B07-D1A9-4B6D-927F-CD90168FE34D@freudenbergs.de> On 26.10.2014, at 14:38, Levente Uzonyi wrote: > On Sun, 26 Oct 2014, Bert Freudenberg wrote: > >> Yes, the implementation itself looks good. >> >> It's just a bit unfortunate that the user code gets even less generic than it was before. > > What do you mean by "less generic"? Is it that the code says ExternalSemaphoreTable instead of Smalltalk? Yes. > The code was extracted from Smalltalk more than 14 years ago, because > > "It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary" Delegating is cleaner indeed. You took out the delegation and made user code not use the Smalltalk facade anymore, but instead use the implementation directly. This delegates to ExternalSemaphoreTable (or anywhere else): Smalltalk unregisterExternalObject: semaphore This exposes ExternalSemaphoreTable: ExternalSemaphoreTable unregisterExternalObject: semaphore E.g., you already mentioned that "ExternalSemaphoreTable" is misnamed since it can store any object. Why spread the use of it everywhere then? If we rename it to "ExternalObjectsTable" later then we are breaking the API and have to change all senders. Much simpler to change the delegation methods. > I could have left all (indirect) users of the ExternalSemaphoreTable unchanged, but I think we really should make SmalltalkImage less monolithic and remove those "proxy" methods from it in the near future. I see nothing wrong with Smalltalk being a single facade for system services that have no obviously good home elsewhere. > The new methods give additional performance boost (because we know that the Semaphores are new, so we don't have to check if they are already included, and because we don't have to wait for the lock multiple times, when multiple Semaphores are registered or unregistered) especially for Sockets, which was the main reason I spent so much time on this. I would be surprised if the indirection itself has any real performance impact, and it's simple to add optimizing methods to the facade, too. I had suggested putting the API in Semaphore itself (maybe on the class side) but since it's not specific to Semaphores I agree it's better to put elsewhere. - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/56c4853c/smime.bin From commits at source.squeak.org Mon Oct 27 15:59:09 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 15:59:11 2014 Subject: [squeak-dev] The Inbox: Sound-ul.41.mcz Message-ID: A new version of Sound was added to project The Inbox: http://source.squeak.org/inbox/Sound-ul.41.mcz ==================== Summary ==================== Name: Sound-ul.41 Author: ul Time: 27 October 2014, 4:48:59.268 pm UUID: b700fc19-c219-47e3-bc55-4874db9dea22 Ancestors: Sound-nice.38 - use the new ExternalObjectTable API =============== Diff against Sound-nice.38 =============== Item was changed: ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') ----- startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound "Start the sound player process. Terminate the old process, if any." "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false" self stopPlayerProcess. aSound ifNil:[ActiveSounds := OrderedCollection new] ifNotNil:[ActiveSounds := OrderedCollection with: aSound]. Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4. LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize]. PlayerSemaphore := Semaphore forMutualExclusion. SamplingRate := samplesPerSecond. Stereo := stereoFlag. - ReadyForBuffer := Semaphore new. SoundSupported := true. "Assume so" UseReadySemaphore := true. "set to false if ready semaphore not supported by VM" + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + ReadyForBuffer := semaphore. + self primSoundStartBufferSize: Buffer stereoSampleCount + rate: samplesPerSecond + stereo: Stereo + semaIndex: index ]. - self primSoundStartBufferSize: Buffer stereoSampleCount - rate: samplesPerSecond - stereo: Stereo - semaIndex: (Smalltalk registerExternalObject: ReadyForBuffer). "Check if sound start prim was successful" + SoundSupported ifFalse:[ + Smalltalk unregisterExternalObject: ReadyForBuffer. + ReadyForBuffer := nil. + ^self ]. - SoundSupported ifFalse:[^self]. UseReadySemaphore ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess] ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess]. UseReverb ifTrue: [self startReverb]. PlayerProcess priority: Processor userInterruptPriority. + PlayerProcess resume! - PlayerProcess resume.! Item was changed: ----- Method: SoundRecorder>>startRecording (in category 'recording controls') ----- startRecording "Turn of the sound input driver and start the recording process. Initially, recording is paused." - | semaIndex | recordLevel ifNil: [recordLevel := 0.5]. "lazy initialization" CanRecordWhilePlaying ifFalse: [SoundPlayer shutDown]. recordProcess ifNotNil: [self stopRecording]. paused := true. meteringBuffer := SoundBuffer newMonoSampleCount: 1024. meterLevel := 0. self allocateBuffer. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + bufferAvailableSema := semaphore. + self primStartRecordingDesiredSampleRate: samplingRate asInteger + stereo: stereo + semaIndex: index ]. - bufferAvailableSema := Semaphore new. - semaIndex := Smalltalk registerExternalObject: bufferAvailableSema. - self primStartRecordingDesiredSampleRate: samplingRate asInteger - stereo: stereo - semaIndex: semaIndex. RecorderActive := true. samplingRate := self primGetActualRecordingSampleRate. self primSetRecordLevel: (1000.0 * recordLevel) asInteger. recordProcess := [self recordLoop] newProcess. recordProcess priority: Processor userInterruptPriority. + recordProcess resume! - recordProcess resume. - ! From commits at source.squeak.org Mon Oct 27 15:59:11 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 15:59:16 2014 Subject: [squeak-dev] The Inbox: System-ul.688.mcz Message-ID: A new version of System was added to project The Inbox: http://source.squeak.org/inbox/System-ul.688.mcz ==================== Summary ==================== Name: System-ul.688 Author: ul Time: 27 October 2014, 4:43:14.279 pm UUID: 77747387-55a5-4118-95b5-752979bf1cf7 Ancestors: System-dtl.685 Replaced ExternalSemaphoreTable with ExternalObjectTable to provide faster registration, and give better support to the current users of external objects. Notable changes: - the table is a separate object instead of a few class side methods - the whole API can be found in SmalltalkImage in the external objects category - #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores: provide fast and easy creation and registration of Semaphores - #unregisterExternalObjects: can unregister multiple objects faster - #externalObjects will return a copy of the externalObjectsArray - better scalability - the maxExternalSemaphores VM parameter will be incremented as the externalObjectsArray grows =============== Diff against System-dtl.685 =============== Item was added: + Object subclass: #ExternalObjectTable + instanceVariableNames: 'semaphore externalObjectsArray freeSlotIndexes indexesByObjects' + classVariableNames: '' + poolDictionaries: '' + category: 'System-Support'! + ExternalObjectTable class + instanceVariableNames: 'current'! + + !ExternalObjectTable commentStamp: 'ul 10/27/2014 16:26' prior: 0! + I'm an enhanced version of JMM's ExternalSemaphoreTable. + I'm responsible for maintaining the externalObjectsArray, which can be found at slot 39 of Smalltalk specialObjectsArray. Manipulating the array directly is highly discouraged. + + My services are available via the methods of the "external objects" category of SmalltalkImage. + + To register anObject simply use Smalltalk registerExternalObject: anObject. Use #unregisterExternalObject: to unregister it. It your responsibility to always unregister these objects. + If you'd like the create one or more new Semaphores, and register them for external use, then you should use one of #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores:. If you want to unregister more than one external objects at the same time, then #unregisterExternalObjects: is the method you're looking for. + + Implementation details: + I maintain a single instance (#current), which can automatically synchronize with externalObjectsArray. + All accesses are protected by the semaphore instance variable. + To ensure fast access, I keep track of the indexes of the external objects in the externalObjectArray in my indexesByObjects IdentityDictionary. + To ensure fast insertion, I keep track of the free slots of the externalObjectsArray in the freeSlotIndexes OrderedCollection. The access pattern is LIFO to avoid unnecessary growth and reordering of the OrderedCollection. + I can grow the externalObjectsArray (see #ensureFreeSlot), but I never shrink it.! + ExternalObjectTable class + instanceVariableNames: 'current'! Item was added: + ----- Method: ExternalObjectTable class>>cleanUp: (in category 'initialize-release') ----- + cleanUp: aggressive + "It's safe to release the instance" + + self reset! Item was added: + ----- Method: ExternalObjectTable class>>current (in category 'accessing') ----- + current + + ^current ifNil: [ + | newInstance | + newInstance := self new. + " Check again, because another process might have registered another instance. " + current ifNil: [ current := newInstance ] ]! Item was added: + ----- Method: ExternalObjectTable class>>reset (in category 'accessing') ----- + reset + + current := nil! Item was added: + ----- Method: ExternalObjectTable>>clearExternalObjects (in category 'accessing') ----- + clearExternalObjects + "Clear the array of objects that have been registered for use in non-Smalltalk code." + + semaphore critical: [ + Smalltalk specialObjectsArray at: 39 put: Array new. + self + initializeCaches; + synchronizeExternalObjectsArrayAndForceUpdate: true ]! Item was added: + ----- Method: ExternalObjectTable>>ensureFreeSlot (in category 'private') ----- + ensureFreeSlot + "Make sure there's at least one free slot." + + | oldSize newSize newExternalObjectsArray specialObjectsArray | + freeSlotIndexes isEmpty ifFalse: [ ^self ]. + oldSize := externalObjectsArray size. + newSize := oldSize + 20. "Linear growth is not really a problem, because we never shrink the array." + newExternalObjectsArray := externalObjectsArray species new: newSize. + newExternalObjectsArray + replaceFrom: 1 + to: oldSize + with: externalObjectsArray + startingAt: 1. + specialObjectsArray := Smalltalk specialObjectsArray. + (specialObjectsArray at: 39) == externalObjectsArray + ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + ensureFreeSlot ]. + specialObjectsArray at: 39 put: newExternalObjectsArray. + externalObjectsArray := newExternalObjectsArray. + newSize to: oldSize + 1 by: -1 do: [ :each | + freeSlotIndexes addFirst: each ]. + Smalltalk maxExternalSemaphores ifNotNil: [ :maxExternalSemaphores | + "Make sure that those new external semaphores can be signaled by the VM. This is not entirely safe, but not incrementing at all is worse." + newSize > maxExternalSemaphores ifTrue: [ + Smalltalk maxExternalSemaphores: newSize ] ] + + ! Item was added: + ----- Method: ExternalObjectTable>>externalObjects (in category 'accessing') ----- + externalObjects + "Return a copy of the externalObjectsArray." + + ^semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + externalObjectsArray copy ]! Item was added: + ----- Method: ExternalObjectTable>>externalObjectsArray: (in category 'private') ----- + externalObjectsArray: anArray + "Update the index mapping using anArray as the new externalObjectsArray." + + externalObjectsArray := anArray. + freeSlotIndexes reset. + indexesByObjects removeAll. + 1 to: externalObjectsArray size do: [ :index | + (anArray at: index) + ifNil: [ freeSlotIndexes addFirst: index ] + ifNotNil: [ :object | indexesByObjects at: object put: index ] ]! Item was added: + ----- Method: ExternalObjectTable>>initialize (in category 'initialize-release') ----- + initialize + + semaphore := Semaphore forMutualExclusion. + self initializeCaches! Item was added: + ----- Method: ExternalObjectTable>>initializeCaches (in category 'private') ----- + initializeCaches + + freeSlotIndexes := OrderedCollection new. + indexesByObjects := IdentityDictionary new! Item was added: + ----- Method: ExternalObjectTable>>newExternalSemaphore (in category 'accessing') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return an array containing itself and its index." + + | newSemaphore | + ^{ + newSemaphore := Semaphore new. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterNewExternalObject: newSemaphore ] }! Item was added: + ----- Method: ExternalObjectTable>>newExternalSemaphoreDo: (in category 'accessing') ----- + newExternalSemaphoreDo: aBlock + "Create and register a new Semaphore, then evaluate aBlock with it and its index." + + | newSemaphore | + ^aBlock + value: (newSemaphore := Semaphore new) + value: (semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterNewExternalObject: newSemaphore ])! Item was added: + ----- Method: ExternalObjectTable>>newExternalSemaphores: (in category 'accessing') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing the semaphores and their indexes in separate arrays." + + | semaphores indexes | + semaphores := Array new: count. + 1 to: count do: [ :index | semaphores at: index put: Semaphore new ]. + indexes := Array new: count. + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + 1 to: count do: [ :index | + indexes at: index put: ( + self safelyRegisterNewExternalObject: (semaphores at: index)) ] ]. + ^{ semaphores. indexes }! Item was added: + ----- Method: ExternalObjectTable>>registerExternalObject: (in category 'accessing') ----- + registerExternalObject: anObject + "Register the given object in the external objects array and return its index. If it is already there, just return its index." + + anObject ifNil: [ ^nil ]. + ^semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalObjectTable>>safelyRegisterExternalObject: (in category 'private') ----- + safelyRegisterExternalObject: anObject + + | index | + (index := indexesByObjects at: anObject ifAbsent: nil) ifNotNil: [ + (externalObjectsArray at: index) == anObject ifTrue: [ ^index ]. + "indexesByObjects is out of sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterExternalObject: anObject ]. + ^self safelyRegisterNewExternalObject: anObject! Item was added: + ----- Method: ExternalObjectTable>>safelyRegisterNewExternalObject: (in category 'private') ----- + safelyRegisterNewExternalObject: anObject + + | index | + self ensureFreeSlot. + index := freeSlotIndexes removeLast. + (externalObjectsArray at: index) ifNotNil: [ + "Free slot is not empty. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterNewExternalObject: anObject ]. + externalObjectsArray at: index put: anObject. + indexesByObjects at: anObject put: index. + ^index! Item was added: + ----- Method: ExternalObjectTable>>safelyUnregisterExternalObject: (in category 'private') ----- + safelyUnregisterExternalObject: anObject + + (indexesByObjects removeKey: anObject ifAbsent: nil) + ifNotNil: [ :index | + (externalObjectsArray at: index) == anObject ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]. + externalObjectsArray at: index put: nil. + freeSlotIndexes add: index ] + ifNil: [ + "Check if we're just out of sync." + (externalObjectsArray instVarsInclude: anObject) ifFalse: [ ^self ]. + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalObjectTable>>synchronizeExternalObjectsArrayAndForceUpdate: (in category 'private') ----- + synchronizeExternalObjectsArrayAndForceUpdate: forceUpdate + + | actualExternalObjectsArray | + actualExternalObjectsArray := Smalltalk specialObjectsArray at: 39. + (actualExternalObjectsArray == externalObjectsArray and: [ forceUpdate not ]) + ifTrue: [ ^self ]. + self externalObjectsArray: actualExternalObjectsArray! Item was added: + ----- Method: ExternalObjectTable>>unregisterExternalObject: (in category 'accessing') ----- + unregisterExternalObject: anObject + "Unregister the given object from the external objects array. Do nothing if it isn't registered." + + anObject ifNil: [ ^self ]. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalObjectTable>>unregisterExternalObjects: (in category 'accessing') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + aCollection do: [ :each | + each ifNotNil: [ + self safelyUnregisterExternalObject: each ] ] ]! Item was removed: - Object subclass: #ExternalSemaphoreTable - instanceVariableNames: '' - classVariableNames: 'ProtectTable' - poolDictionaries: '' - category: 'System-Support'! - - !ExternalSemaphoreTable commentStamp: '' prior: 0! - By John M McIntosh johnmci@smalltalkconsulting.com - This class was written to mange the external semaphore table. When I was writing a Socket test server I discovered various race conditions on the access to the externalSemaphore table. This new class uses class side methods to restrict access using a mutex semaphore. It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary - - Note that in Smalltalk recreateSpecialObjectsArray we still directly play with the table.! Item was removed: - ----- Method: ExternalSemaphoreTable class>>clearExternalObjects (in category 'accessing') ----- - clearExternalObjects - "Clear the array of objects that have been registered for use in non-Smalltalk code." - - ProtectTable critical: [Smalltalk specialObjectsArray at: 39 put: Array new]. - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>externalObjects (in category 'accessing') ----- - externalObjects - ^ProtectTable critical: [Smalltalk specialObjectsArray at: 39].! Item was removed: - ----- Method: ExternalSemaphoreTable class>>initialize (in category 'initialize') ----- - initialize - ProtectTable := Semaphore forMutualExclusion! Item was removed: - ----- Method: ExternalSemaphoreTable class>>registerExternalObject: (in category 'accessing') ----- - registerExternalObject: anObject - ^ ProtectTable critical: [self safelyRegisterExternalObject: anObject] - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyRegisterExternalObject: (in category 'accessing') ----- - safelyRegisterExternalObject: anObject - "Register the given object in the external objects array and return its index. If it is already there, just return its index." - - | objects firstEmptyIndex obj sz newObjects | - objects := Smalltalk specialObjectsArray at: 39. - - "find the first empty slot" - firstEmptyIndex := 0. - 1 to: objects size do: [:i | - obj := objects at: i. - obj == anObject ifTrue: [^ i]. "object already there, just return its index" - (obj == nil and: [firstEmptyIndex = 0]) ifTrue: [firstEmptyIndex := i]]. - - "if no empty slots, expand the array" - firstEmptyIndex = 0 ifTrue: [ - sz := objects size. - newObjects := objects species new: sz + 20. "grow linearly" - newObjects replaceFrom: 1 to: sz with: objects startingAt: 1. - firstEmptyIndex := sz + 1. - Smalltalk specialObjectsArray at: 39 put: newObjects. - objects := newObjects]. - - objects at: firstEmptyIndex put: anObject. - ^ firstEmptyIndex - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyUnregisterExternalObject: (in category 'accessing') ----- - safelyUnregisterExternalObject: anObject - "Unregister the given object in the external objects array. Do nothing if it isn't registered. - JMM change to return if we clear the element, since it should only appear once in the array" - - | objects | - anObject ifNil: [^ self]. - objects := Smalltalk specialObjectsArray at: 39. - 1 to: objects size do: [:i | - (objects at: i) == anObject ifTrue: - [objects at: i put: nil. - ^self]]. - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>unregisterExternalObject: (in category 'accessing') ----- - unregisterExternalObject: anObject - ProtectTable critical: [self safelyUnregisterExternalObject: anObject] - ! Item was changed: + ----- Method: SmalltalkImage>>clearExternalObjects (in category 'external objects') ----- - ----- Method: SmalltalkImage>>clearExternalObjects (in category 'special objects') ----- clearExternalObjects "Clear the array of objects that have been registered for use in non-Smalltalk code." "Smalltalk clearExternalObjects" + ExternalObjectTable current clearExternalObjects - ExternalSemaphoreTable clearExternalObjects ! Item was changed: + ----- Method: SmalltalkImage>>externalObjects (in category 'external objects') ----- - ----- Method: SmalltalkImage>>externalObjects (in category 'special objects') ----- externalObjects "Return an array of objects that have been registered for use in non-Smalltalk code. Smalltalk objects should be referrenced by external code only via indirection through this array, thus allowing the objects to move during compaction. This array can be cleared when the VM re-starts, since variables in external code do not survive snapshots. Note that external code should not attempt to access a Smalltalk object, even via this mechanism, while garbage collection is in progress." + "Note that this is just a copy of the array used by the VM." "Smalltalk externalObjects" + ^ExternalObjectTable current externalObjects - ^ ExternalSemaphoreTable externalObjects ! Item was added: + ----- Method: SmalltalkImage>>newExternalSemaphore (in category 'external objects') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return an array containing itself and its index." + + ^ExternalObjectTable current newExternalSemaphore! Item was added: + ----- Method: SmalltalkImage>>newExternalSemaphoreDo: (in category 'external objects') ----- + newExternalSemaphoreDo: aBlock + "Create and register a new Semaphore, then evaluate aBlock with it and its index." + + ^ExternalObjectTable current newExternalSemaphoreDo: aBlock! Item was added: + ----- Method: SmalltalkImage>>newExternalSemaphores: (in category 'external objects') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing the semaphores and their indexes in separate arrays." + + ^ExternalObjectTable current newExternalSemaphores: count! Item was changed: + ----- Method: SmalltalkImage>>registerExternalObject: (in category 'external objects') ----- - ----- Method: SmalltalkImage>>registerExternalObject: (in category 'special objects') ----- registerExternalObject: anObject "Register the given object in the external objects array and return its index. If it is already there, just return its index." + ^ExternalObjectTable current registerExternalObject: anObject! - ^ExternalSemaphoreTable registerExternalObject: anObject! Item was changed: + ----- Method: SmalltalkImage>>unregisterExternalObject: (in category 'external objects') ----- - ----- Method: SmalltalkImage>>unregisterExternalObject: (in category 'special objects') ----- unregisterExternalObject: anObject "Unregister the given object in the external objects array. Do nothing if it isn't registered." + ExternalObjectTable current unregisterExternalObject: anObject! - ExternalSemaphoreTable unregisterExternalObject: anObject! Item was added: + ----- Method: SmalltalkImage>>unregisterExternalObjects: (in category 'external objects') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + ExternalObjectTable current unregisterExternalObjects: aCollection! From commits at source.squeak.org Mon Oct 27 15:59:25 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 15:59:26 2014 Subject: [squeak-dev] The Inbox: Network-ul.155.mcz Message-ID: A new version of Network was added to project The Inbox: http://source.squeak.org/inbox/Network-ul.155.mcz ==================== Summary ==================== Name: Network-ul.155 Author: ul Time: 27 October 2014, 4:46:13.635 pm UUID: cf2f8a25-3525-4183-8f93-7dc5d127f22d Ancestors: Network-ul.152 - use the new ExternalObjectTable API - unifed socket initialization - unregister ResolverSemaphore when the network initialization fails =============== Diff against Network-ul.152 =============== Item was changed: ----- Method: NetNameResolver class>>initializeNetwork (in category 'network initialization') ----- initializeNetwork "Initialize the network drivers and record the semaphore to be used by the resolver. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails." "NetNameResolver initializeNetwork" - | semaIndex | self resolverStatus = ResolverUninitialized ifFalse: [^HaveNetwork := true]. "network is already initialized" HaveNetwork := false. "in case abort" + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + ResolverSemaphore := semaphore. + "result is nil if network initialization failed, self if it succeeds" + (self primInitializeNetwork: index) + ifNil: [ + Smalltalk unregisterExternalObject: ResolverSemaphore. + ResolverSemaphore := nil. + NoNetworkError signal: 'failed network initialization'] + ifNotNil: [ HaveNetwork := true ] ]. - ResolverSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: ResolverSemaphore. + self initializeOldNetworkFlag! - "result is nil if network initialization failed, self if it succeeds" - (self primInitializeNetwork: semaIndex) - ifNil: [NoNetworkError signal: 'failed network initialization'] - ifNotNil: [HaveNetwork := true]. - - self initializeOldNetworkFlag - ! Item was changed: ----- Method: Socket>>acceptFrom: (in category 'initialize-destroy') ----- acceptFrom: aSocket "Initialize a new socket handle from an accept call" - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | + self + primAcceptFrom: aSocket socketHandle + receiveBufferSize: 8000 + sendBufSize: 8000 + semaIndex: semaIndex + readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primAcceptFrom: aSocket socketHandle - receiveBufferSize: 8000 - sendBufSize: 8000 - semaIndex: semaIndex - readSemaIndex: readSemaIndex - writeSemaIndex: writeSemaIndex. - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>destroy (in category 'initialize-destroy') ----- destroy "Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil)." socketHandle ifNotNil: [ self isValid ifTrue: [ self primSocketDestroy: socketHandle ]. + Smalltalk unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore }. - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. socketHandle := nil. readSemaphore := writeSemaphore := semaphore := nil. self unregister ]! Item was changed: ----- Method: Socket>>finalize (in category 'finalization') ----- finalize + self primSocketDestroyGently: socketHandle. + Smalltalk unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore } - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. ! Item was changed: ----- Method: Socket>>initialize: (in category 'initialize-destroy') ----- initialize: socketType "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: 0 type: socketType receiveBufferSize: 8000 sendBufSize: 8000 semaIndex: semaIndex readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>initialize:family: (in category 'initialize-destroy') ----- initialize: socketType family: family "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + NetNameResolver useOldNetwork ifTrue: [ ^self initialize: socketType ]. + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | - NetNameResolver useOldNetwork ifTrue: [^self initialize: socketType]. - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: family type: socketType receiveBufferSize: 8000 sendBufSize: 8000 semaIndex: semaIndex readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was added: + ----- Method: Socket>>initializeSocketHandleUsing: (in category 'initialize-destroy') ----- + initializeSocketHandleUsing: aBlock + "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." + + | semaphoresAndIndexes semaphores indexes | + semaphoresAndIndexes := Smalltalk newExternalSemaphores: 3. + semaphores := semaphoresAndIndexes at: 1. + indexes := semaphoresAndIndexes at: 2. + semaphore := semaphores at: 1. + readSemaphore := semaphores at: 2. + writeSemaphore := semaphores at: 3. + (socketHandle := aBlock valueWithArguments: indexes) + ifNotNil: [ self register ] + ifNil: [ + "socket creation failed" + semaphore := readSemaphore := writeSemaphore := nil. + Smalltalk unregisterExternalObjects: semaphores ]! From commits at source.squeak.org Mon Oct 27 15:59:33 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 15:59:34 2014 Subject: [squeak-dev] The Inbox: Files-ul.141.mcz Message-ID: A new version of Files was added to project The Inbox: http://source.squeak.org/inbox/Files-ul.141.mcz ==================== Summary ==================== Name: Files-ul.141 Author: ul Time: 27 October 2014, 4:51:14.305 pm UUID: b0dbabfe-ce75-4f18-a82f-2f95fa8b026e Ancestors: Files-eem.138 - use the new ExternalObjectTable API =============== Diff against Files-eem.138 =============== Item was changed: ----- Method: AsyncFile>>open:forWrite: (in category 'as yet unclassified') ----- open: fullFileName forWrite: aBoolean "Open a file of the given name, and return a handle for that file. Answer the receiver if the primitive succeeds, nil otherwise. If openForWrite is true, then: if there is no existing file with this name, then create one else open the existing file in read-write mode otherwise: if there is an existing file with this name, then open it read-only else answer nil." "Note: if an exisiting file is opened for writing, it is NOT truncated. If truncation is desired, the file should be deleted before being opened as an asynchronous file." "Note: On some platforms (e.g., Mac), a file can only have one writer at a time." - | semaIndex | name := fullFileName. writeable := aBoolean. + ^Smalltalk newExternalSemaphoreDo: [ :newSemaphore :index | + fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: index. + fileHandle + ifNotNil: [ + semaphore := newSemaphore. + self ] + ifNil: [ + Smalltalk unregisterExternalObject: newSemaphore. + nil ] ]! - semaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: semaIndex. - fileHandle ifNil: [ - Smalltalk unregisterExternalObject: semaphore. - semaphore := nil. - ^ nil]. - ! Item was changed: ----- Method: StandardFileStream>>post:target:url:ifError: (in category 'browser requests') ----- post: data target: target url: url ifError: errorBlock "Post data to the given URL. The returned file stream contains the reply of the server. If Squeak is not running in a browser evaluate errorBlock" + - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLPost: url target: target data: data semaIndex: index. + request ifNil: [ + Smalltalk unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. + result ifTrue: [ fileID := self primURLRequestFileHandle: request ]. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLPost: url target: target data: data semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. - result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. + Smalltalk unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! Item was changed: ----- Method: StandardFileStream>>requestURL:target:ifError: (in category 'browser requests') ----- requestURL: url target: target ifError: errorBlock "Request to go to the target for the given URL. If Squeak is not running in a browser evaluate errorBlock" - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLRequest: url target: target semaIndex: index. + request ifNil: [ + Smalltalk unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url target: target semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. self primURLRequestDestroy: request. + Smalltalk unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! Item was changed: ----- Method: StandardFileStream>>requestURLStream:ifError: (in category 'browser requests') ----- requestURLStream: url ifError: errorBlock "Request a FileStream for the given URL. If Squeak is not running in a browser evaluate errorBlock" "FileStream requestURLStream:'http://www.squeak.org'" + - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLRequest: url semaIndex: index. + request ifNil: [ + Smalltalk unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. + result ifTrue: [ fileID := self primURLRequestFileHandle: request ]. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. - result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. + Smalltalk unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! From brasspen at gmail.com Mon Oct 27 16:00:54 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Mon Oct 27 16:01:10 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One Message-ID: https://www.dropbox.com/s/09rbm70rj86cqr1/ComSwiki4.5.zip?dl=0 I put the ComSwiki in a 4.5 All-In-One with the swiki directory of files. If you double click, it?ll open up the image. From there a person can press start on the ComSwikiLauncher and go to localhost:8888 to see it running. I was reading ?Squeak: Open Personal Computing And Multimedia? recently and Dan Ingalls said some people downloaded the ComSwiki not for Squeak but to have a wiki (?Back To The Future Once More?). Sounded like it was an app to draw people to the language. I intend to add a link on the homepage under FunSqueak to ComSwiki4.5. It can be downloaded above. If it doesn?t work or people don?t think I should make this publicly available from the homepage, please let me know. Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/ae4e8b8a/attachment.htm From leves at elte.hu Mon Oct 27 16:01:34 2014 From: leves at elte.hu (Levente Uzonyi) Date: Mon Oct 27 16:01:51 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <3B1B8B07-D1A9-4B6D-927F-CD90168FE34D@freudenbergs.de> References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026143206.GA54624@shell.msen.com> <3B1B8B07-D1A9-4B6D-927F-CD90168FE34D@freudenbergs.de> Message-ID: Good points. I've uploaded new versions to The Inbox: Installer squeakInbox package: 'System-ul.688'; package: 'Sound-ul.41'; package: 'Network-ul.155'; package: 'Files-ul.141'; install. The new class is called ExternalObjectTable. ExternalSemaphoreTable is gone. All API is in SmalltalkImage in a separate category named external objects. Levente On Mon, 27 Oct 2014, Bert Freudenberg wrote: > On 26.10.2014, at 14:38, Levente Uzonyi wrote: > >> On Sun, 26 Oct 2014, Bert Freudenberg wrote: >> >>> Yes, the implementation itself looks good. >>> >>> It's just a bit unfortunate that the user code gets even less generic than it was before. >> >> What do you mean by "less generic"? Is it that the code says ExternalSemaphoreTable instead of Smalltalk? > > Yes. > >> The code was extracted from Smalltalk more than 14 years ago, because >> >> "It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary" > > Delegating is cleaner indeed. You took out the delegation and made user code not use the Smalltalk facade anymore, but instead use the implementation directly. > > This delegates to ExternalSemaphoreTable (or anywhere else): > > Smalltalk unregisterExternalObject: semaphore > > This exposes ExternalSemaphoreTable: > > ExternalSemaphoreTable unregisterExternalObject: semaphore > > E.g., you already mentioned that "ExternalSemaphoreTable" is misnamed since it can store any object. Why spread the use of it everywhere then? If we rename it to "ExternalObjectsTable" later then we are breaking the API and have to change all senders. Much simpler to change the delegation methods. > >> I could have left all (indirect) users of the ExternalSemaphoreTable unchanged, but I think we really should make SmalltalkImage less monolithic and remove those "proxy" methods from it in the near future. > > I see nothing wrong with Smalltalk being a single facade for system services that have no obviously good home elsewhere. > >> The new methods give additional performance boost (because we know that the Semaphores are new, so we don't have to check if they are already included, and because we don't have to wait for the lock multiple times, when multiple Semaphores are registered or unregistered) especially for Sockets, which was the main reason I spent so much time on this. > > I would be surprised if the indirection itself has any real performance impact, and it's simple to add optimizing methods to the facade, too. > > I had suggested putting the API in Semaphore itself (maybe on the class side) but since it's not specific to Semaphores I agree it's better to put elsewhere. > > - Bert - > > > > From eliot.miranda at gmail.com Mon Oct 27 16:07:17 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 27 16:07:28 2014 Subject: [squeak-dev] Re: [Pharo-dev] Should literals be immutable ? In-Reply-To: References: Message-ID: <0D540870-5387-4F62-A089-113A3F69BEDC@gmail.com> Hi Cl?ment, IMO literals should be immutable all the time, and IMO the best way is via a per-object isImmutable bit. We implemented this for VW in 7.0 and it was a positive experience. I've implemented the "create an immutable subclass for each literal class" and it has lots of problems (thing printString or storeString having to produce something like 'an immutable string' asMutableString for a normal string). The per-object bit has other uses too. Object databases such as GemStone can use it to make write-through scheme efficient. The only problem we had was dealing with broken user code that was depending on mutable literals. This is of course a bug, but folks thought we shouldn't just break user code so Alan Knight provided a system setting that write a warning to the transcript and updated the literal instead if raising an error. That's easy to do, if IMO dubious. Fixing the code is as easy as sending copy to the literal in question, the copy being mutable. Now I implemented the per-object bit for the Newspeak interpreter WM so you'll find lots of the necessary work is there waiting to be ported to the Stack and Cog VMs. I've not had the time to implement the JIT support to catch inst var and at:put: writes to immutables. But it shouldn't be too much work. Volunteers? Eliot (phone) On Oct 27, 2014, at 8:22 AM, Cl?ment Bera wrote: > Hey guys, > > I was discussing about methods like that with Marcus: > > MyClass>>foo > #(false) first > ifFalse: [ > 'first call since compilation' logCr. > #(false) at: 1 put: true ] > ifTrue: [ 'other calls' logCr ] > > DoIt: > 4 timesRepeat: [MyClass new foo ] > > Transcript: > 'first call since compilation' > 'other calls' > 'other calls' > 'other calls' > > In the sista image/VM, we are most probably going with Eliot to implement a slow path when you edit the literal of a method (deoptimizing the method) so we can consider that the literals are immutable in the generic case (and if it's not true, execution falls back to a slow path). > > But I was thinking, does it worth it to implement the slow path ? > Couldn't we just put literals as immutable all the time ? > The methods as the one shown before would not work any more. But does someone use it ? > > ... > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/1e7c7e67/attachment.htm From bert at freudenbergs.de Mon Oct 27 16:19:33 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Mon Oct 27 16:19:34 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: References: <4F7857A9-7D67-44C6-A797-F32B6DE8B5FC@freudenbergs.de> <2BF190F8-F973-4E3E-843A-69C7E2F5924B@freudenbergs.de> <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026143206.GA54624@shell.msen.com> <3B1B8B07-D1A9-4B6D-927F-CD90168FE34D@freudenbergs.de> Message-ID: <15140949-FFBE-4D82-AA5A-C53BA5A67AB6@freudenbergs.de> Ship it :) - Bert - On 27.10.2014, at 12:01, Levente Uzonyi wrote: > Good points. I've uploaded new versions to The Inbox: > > Installer squeakInbox > package: 'System-ul.688'; > package: 'Sound-ul.41'; > package: 'Network-ul.155'; > package: 'Files-ul.141'; > install. > > The new class is called ExternalObjectTable. ExternalSemaphoreTable is gone. All API is in SmalltalkImage in a separate category named external objects. > > > Levente > > On Mon, 27 Oct 2014, Bert Freudenberg wrote: > >> On 26.10.2014, at 14:38, Levente Uzonyi wrote: >> >>> On Sun, 26 Oct 2014, Bert Freudenberg wrote: >>> >>>> Yes, the implementation itself looks good. >>>> >>>> It's just a bit unfortunate that the user code gets even less generic than it was before. >>> >>> What do you mean by "less generic"? Is it that the code says ExternalSemaphoreTable instead of Smalltalk? >> >> Yes. >> >>> The code was extracted from Smalltalk more than 14 years ago, because >>> >>> "It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary" >> >> Delegating is cleaner indeed. You took out the delegation and made user code not use the Smalltalk facade anymore, but instead use the implementation directly. >> >> This delegates to ExternalSemaphoreTable (or anywhere else): >> >> Smalltalk unregisterExternalObject: semaphore >> >> This exposes ExternalSemaphoreTable: >> >> ExternalSemaphoreTable unregisterExternalObject: semaphore >> >> E.g., you already mentioned that "ExternalSemaphoreTable" is misnamed since it can store any object. Why spread the use of it everywhere then? If we rename it to "ExternalObjectsTable" later then we are breaking the API and have to change all senders. Much simpler to change the delegation methods. >> >>> I could have left all (indirect) users of the ExternalSemaphoreTable unchanged, but I think we really should make SmalltalkImage less monolithic and remove those "proxy" methods from it in the near future. >> >> I see nothing wrong with Smalltalk being a single facade for system services that have no obviously good home elsewhere. >> >>> The new methods give additional performance boost (because we know that the Semaphores are new, so we don't have to check if they are already included, and because we don't have to wait for the lock multiple times, when multiple Semaphores are registered or unregistered) especially for Sockets, which was the main reason I spent so much time on this. >> >> I would be surprised if the indirection itself has any real performance impact, and it's simple to add optimizing methods to the facade, too. >> >> I had suggested putting the API in Semaphore itself (maybe on the class side) but since it's not specific to Semaphores I agree it's better to put elsewhere. >> >> - Bert - >> >> >> >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/96a6809a/smime.bin From eliot.miranda at gmail.com Mon Oct 27 16:23:31 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 27 16:23:35 2014 Subject: [squeak-dev] Re: [Pharo-dev] Should literals be immutable ? In-Reply-To: References: Message-ID: On Mon, Oct 27, 2014 at 9:19 AM, Levente Uzonyi wrote: > On Mon, 27 Oct 2014, Cl?ment Bera wrote: > > Hey guys, >> I was discussing about methods like that with Marcus: >> >> MyClass>>foo >> #(false) first >> ifFalse: [ >> 'first call since compilation' logCr. >> #(false) at: 1 put: true ] >> ifTrue: [ 'other calls' logCr ] >> >> DoIt: >> 4 timesRepeat: [MyClass new foo ] >> >> Transcript: >> 'first call since compilation' >> 'other calls' >> 'other calls' >> 'other calls' >> >> In the sista image/VM, we are most probably going with Eliot to implement >> a slow path when you edit the literal of a method (deoptimizing the method) >> so we can consider that the literals are immutable in the >> generic case (and if it's not true, execution falls back to a slow path). >> >> But I was thinking, does it worth it to implement the slow path ? >> Couldn't we just put literals as immutable all the time ? >> The methods as the one shown before would not work any more. But does >> someone use it ? >> > > This method was used in Seaside (or some Seaside extension) to cache the > contents of files in methods. > > By the way, how would you ensure immutability? > See my message earlier in the thread. Via a per-object isImmutable bit. > I mean, how would you prevent something like this? > > MyClass >> foo > > ^#('placeHolder') > > And then > > (((MyClass >> #foo) literalAt: 1) at: 1) becomeForward: Object new > > > Levente > > P.S.: why isn't this on the vm-dev list? > > >> ... >> >> >> -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/d80515e5/attachment.htm From leves at elte.hu Mon Oct 27 16:55:16 2014 From: leves at elte.hu (Levente Uzonyi) Date: Mon Oct 27 16:55:25 2014 Subject: [squeak-dev] Re: [Vm-dev] Re: [Pharo-dev] Should literals be immutable ? In-Reply-To: References: Message-ID: On Mon, 27 Oct 2014, Eliot Miranda wrote: > See my message earlier in the thread.? Via a per-object isImmutable bit. So you would set the bit for the CompiledMethod and all literals (including sub-arrays, floats, integers, booleans etc)? Does the set immutability bit also mean that the object can't be swapped with #become:? Levente From eliot.miranda at gmail.com Mon Oct 27 17:35:49 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 27 17:35:59 2014 Subject: [squeak-dev] Re: [Vm-dev] Re: [Pharo-dev] Should literals be immutable ? In-Reply-To: References: Message-ID: On Mon, Oct 27, 2014 at 9:55 AM, Levente Uzonyi wrote: > > On Mon, 27 Oct 2014, Eliot Miranda wrote: > > See my message earlier in the thread. Via a per-object isImmutable bit. >> > > So you would set the bit for the CompiledMethod and all literals > (including sub-arrays, floats, integers, booleans etc)? > The literals, definitely. Whether the bit is set for compiled methods or not depends on things like how easy you want to be able to update the source pointer or add/delete properties. > > Does the set immutability bit also mean that the object can't be swapped > with #become:? > That's debatable, but in VW we disallowed two-way become: and allowed one-way become: for immutables. I think that's right. one-way become is about references to objects, two-way become is about changing objects themselves. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/3d0fe0bc/attachment-0001.htm From edgardec2005 at gmail.com Mon Oct 27 18:57:38 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Mon Oct 27 18:57:48 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: Message-ID: On 10/27/14, 1:00 PM, "Chris Cunnington" wrote: > https://www.dropbox.com/s/09rbm70rj86cqr1/ComSwiki4.5.zip?dl=0 > > I put the ComSwiki in a 4.5 All-In-One with the swiki directory of files. If > you double click, it?ll open up the image. From there a person can press start > on the ComSwikiLauncher and go to localhost:8888 to see it running. I was > reading ?Squeak: Open Personal Computing And Multimedia? recently and Dan > Ingalls said some people downloaded the ComSwiki not for Squeak but to have a > wiki (?Back To The Future Once More?). Sounded like it was an app to draw > people to the language. > > I intend to add a link on the homepage under FunSqueak to ComSwiki4.5. It can > be downloaded above. If it doesn?t work or people don?t think I should make > this publicly available from the homepage, please let me know. > > Chris > > The ani folder is not deployds, but you can see itj in the swiki browser. Edgar -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/6aebc9f0/attachment.htm From leves at elte.hu Mon Oct 27 19:12:34 2014 From: leves at elte.hu (Levente Uzonyi) Date: Mon Oct 27 19:12:43 2014 Subject: [squeak-dev] Re: [Vm-dev] Re: [Pharo-dev] Should literals be immutable ? In-Reply-To: References: Message-ID: On Mon, 27 Oct 2014, Eliot Miranda wrote: >> So you would set the bit for the CompiledMethod and all literals (including sub-arrays, floats, integers, booleans etc)? > > The literals, definitely.? Whether the bit is set for compiled methods or not depends on things like how easy you want to be able to update the source pointer or add/delete properties. If the CompiledMethod itself is not immutable, then one can replace its top level literals easily. If it's immutable, then the system will face all kind of problems, like adding the correct trailer during method installation. You could say "no problem, I'll use #becomeForward: to do it, it's fast in Spur", but that's what my other question is about. >? >> Does the set immutability bit also mean that the object can't be swapped with #become:? > > That's debatable, but in VW we disallowed two-way become: and allowed one-way become: for immutables.? I think that's right. ?one-way become is about references to objects, two-way become is about changing objects themselves.? It's not about #become: vs #becomeForward:. If objects with the immutable bit set can be replaced with #becomeForward:, then the literals are not really immutable, because they can be changed. If you also want to check if there are immutable objects pointing to the object which is about to be replaced, then the performance of #becomeForward: would become as slow as in the non-Spur VMs. Levente From brasspen at gmail.com Mon Oct 27 19:20:05 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Mon Oct 27 19:20:09 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: References: Message-ID: <78AE9527-6409-4851-8F21-E8A041C7FE2E@gmail.com> > On Oct 27, 2014, at 2:57 PM, Edgar J. De Cleene wrote: > > > > > On 10/27/14, 1:00 PM, "Chris Cunnington" wrote: > >> https://www.dropbox.com/s/09rbm70rj86cqr1/ComSwiki4.5.zip?dl=0 >> >> I put the ComSwiki in a 4.5 All-In-One with the swiki directory of files. If you double click, it?ll open up the image. From there a person can press start on the ComSwikiLauncher and go to localhost:8888 to see it running. I was reading ?Squeak: Open Personal Computing And Multimedia? recently and Dan Ingalls said some people downloaded the ComSwiki not for Squeak but to have a wiki (?Back To The Future Once More?). Sounded like it was an app to draw people to the language. >> >> I intend to add a link on the homepage under FunSqueak to ComSwiki4.5. It can be downloaded above. If it doesn?t work or people don?t think I should make this publicly available from the homepage, please let me know. >> >> Chris >> >> The ani folder is not deployds, but you can see itj in the swiki browser. > > > Edgar > OK, you opened the SwikiBrowser, perhaps with this: (SwikiBrowser asMorphOnShelf: SwikiShelf allInstances first) openInWorld and the ?ani? is present. Hmm, that?s true. I see it as well. The SwikiBrowser shows all the files in the ?swiki? folder regardless of whether they are used or not. It just shows files. I guess if the ani is not showing up then it?s a configuration thing. Not essential, I don?t suppose, though. The ?ani? is a different version of the same kind of wiki seen in ?refs?. Thanks for pointing it out. I?ll have to figure out how to switch between the two or have both at the same time. Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/3aa3981a/attachment.htm From eliot.miranda at gmail.com Mon Oct 27 19:28:40 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon Oct 27 19:28:56 2014 Subject: [squeak-dev] Re: [Vm-dev] Re: [Pharo-dev] Should literals be immutable ? In-Reply-To: References: Message-ID: On Mon, Oct 27, 2014 at 12:12 PM, Levente Uzonyi wrote: > > On Mon, 27 Oct 2014, Eliot Miranda wrote: > > So you would set the bit for the CompiledMethod and all literals >>> (including sub-arrays, floats, integers, booleans etc)? >>> >> >> The literals, definitely. Whether the bit is set for compiled methods or >> not depends on things like how easy you want to be able to update the >> source pointer or add/delete properties. >> > > If the CompiledMethod itself is not immutable, then one can replace its > top level literals easily. > If it's immutable, then the system will face all kind of problems, like > adding the correct trailer during method installation. > You could say "no problem, I'll use #becomeForward: to do it, it's fast in > Spur", but that's what my other question is about. > > >> >>> Does the set immutability bit also mean that the object can't be >>> swapped with #become:? >>> >> >> That's debatable, but in VW we disallowed two-way become: and allowed >> one-way become: for immutables. I think that's right. one-way become is >> about references to objects, two-way become is about changing objects >> themselves. >> > > It's not about #become: vs #becomeForward:. If objects with the immutable > bit set can be replaced with #becomeForward:, then the literals are not > really immutable, because they can be changed. > If you also want to check if there are immutable objects pointing to the > object which is about to be replaced, then the performance of > #becomeForward: would become as slow as in the non-Spur VMs. > I disagree. It's about an incremental improvement. A per-object immutability bit used to protect against direct alteration of literals works. Right now there's nothing to stop one recompiling a method, and per-object immutability doesn't change that. So mutable compiled methods are tolerable (at least in VW we kept methods mutable). But having the bit stop direct modification of literals is goodness, not to be avoided because it doesn't prevent more exotic modification via become. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/50584223/attachment.htm From edgardec2005 at gmail.com Mon Oct 27 20:26:06 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Mon Oct 27 20:26:17 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: <78AE9527-6409-4851-8F21-E8A041C7FE2E@gmail.com> Message-ID: On 10/27/14, 4:20 PM, "Chris Cunnington" wrote: >> OK, you opened the SwikiBrowser, perhaps with this: >> >> (SwikiBrowser asMorphOnShelf: SwikiShelf allInstances first) openInWorld >> >> and the ?ani? is present. Hmm, that?s true. I see it as well. The >> SwikiBrowser shows all the files in the ?swiki? folder regardless of whether >> they are used or not. It just shows files. >> I guess if the ani is not showing up then it?s a configuration thing. Not >> essential, I don?t suppose, though. The ?ani? is a different version of the >> same kind of wiki seen in ?refs?. >> Thanks for pointing it out. I?ll have to figure out how to switch between the >> two or have both at the same time. >> >> Chris The point in cuestion is ani is the last and cute version of Swiki. If you don?t have it, can?t inherit of this See http://190.189.179.48:8888/ is served by very old SqueakLight. If you plan resurrect and develop ComSwiki, I can help with how to have tons of js, css, etc like tinymce, bootstrap, others free cute doing visual impact to user. http://190.189.179.48:9090/ user: visita pass: (nothing here) It?s old Sblog and old Swiki served on tp of HV2 Edgar -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/f97e089e/attachment.htm From leves at elte.hu Mon Oct 27 20:46:52 2014 From: leves at elte.hu (Levente Uzonyi) Date: Mon Oct 27 20:46:59 2014 Subject: [squeak-dev] Re: [Vm-dev] Re: [Pharo-dev] Should literals be immutable ? In-Reply-To: References: Message-ID: On Mon, 27 Oct 2014, Eliot Miranda wrote: > I disagree.? It's about an incremental improvement.? A per-object immutability bit used to protect against direct alteration of literals works.? Right now there's nothing to stop one recompiling a method, and per-object immutability doesn't change that.? So mutable compiled methods are tolerable (at least in VW we kept methods mutable).? But having the bit stop direct modification of literals is goodness, not to be avoided because it doesn't prevent more exotic modification via become. But if you allow mutable CompiledMethods, then Clement's example can be rewritten as: MyClass >> #foo ^#(false) first ifFalse: [ 'first call since compilation' logCr. thisContext method in: [ :method | (method literalAt: (method literals indexOf: #(false)) put: { true }) ] ] ifTrue: [ 'other calls' logCr ] (#becomeForward: could also be used on the literal). How will you avoid implementing the deoptimization of the method (the slow path) when this is possible? Levente From commits at source.squeak.org Mon Oct 27 20:52:32 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 20:52:35 2014 Subject: [squeak-dev] The Trunk: Collections-ul.586.mcz Message-ID: Levente Uzonyi uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-ul.586.mcz ==================== Summary ==================== Name: Collections-ul.586 Author: ul Time: 27 October 2014, 12:52:51.886 am UUID: 4c460675-3065-4b48-aa30-52ad67e15076 Ancestors: Collections-cmm.585 Symbol table changes: - ensure that enumerations stay consistent - avoid read-write and write-write race conditions - added a safe #condenseNewSymbols method, which is a replacement for former unsafe methods (#shutDown: and #compactSymbolTable). It's also automatically triggered whenever there are more than 1000 NewSymbols. - deprecated #compactSymbolTable - updated some comments Note that interning many symbols is a bit slower, but thread safety is more important. =============== Diff against Collections-cmm.585 =============== Item was changed: ----- Method: Symbol class>>allSymbolTablesDo: (in category 'class initialization') ----- allSymbolTablesDo: aBlock + + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + originalNewSymbols do: aBlock. + originalSymbolTable do: aBlock.! - - NewSymbols do: aBlock. - SymbolTable do: aBlock.! Item was changed: ----- Method: Symbol class>>allSymbolTablesDo:after: (in category 'class initialization') ----- allSymbolTablesDo: aBlock after: aSymbol + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + (originalNewSymbols includes: aSymbol) - (NewSymbols includes: aSymbol) ifTrue: [ + originalNewSymbols do: aBlock after: aSymbol. + originalSymbolTable do: aBlock after: aSymbol ] - NewSymbols do: aBlock after: aSymbol. - SymbolTable do: aBlock after: aSymbol ] ifFalse: [ + originalSymbolTable do: aBlock after: aSymbol. + originalNewSymbols do: aBlock after: aSymbol ] - SymbolTable do: aBlock after: aSymbol. - NewSymbols do: aBlock after: aSymbol ] ! Item was changed: ----- Method: Symbol class>>allSymbols (in category 'access') ----- allSymbols "Answer all interned symbols" + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. ^Array + new: originalNewSymbols slowSize + originalSymbolTable slowSize - new: NewSymbols slowSize + SymbolTable slowSize streamContents:[ :stream | stream + nextPutAll: originalNewSymbols; + nextPutAll: originalSymbolTable ] - nextPutAll: NewSymbols; - nextPutAll: SymbolTable ] ! Item was changed: ----- Method: Symbol class>>cleanUp (in category 'class initialization') ----- cleanUp "Flush caches" + self condenseNewSymbols! - self compactSymbolTable.! Item was changed: ----- Method: Symbol class>>compactSymbolTable (in category 'class initialization') ----- compactSymbolTable "Reduce the size of the symbol table so that it holds all existing symbols with 25% free space." + self deprecated: 'Use #condenseNewSymbols instead'. + self condenseNewSymbols! - | oldSize | - Smalltalk garbageCollect. - oldSize := SymbolTable capacity. - SymbolTable compact. - ^(oldSize - SymbolTable capacity) printString, ' slot(s) reclaimed'! Item was added: + ----- Method: Symbol class>>condenseNewSymbols (in category 'private') ----- + condenseNewSymbols + "Move all symbols from NewSymbols to SymbolTable, and compact SymbolTable." + + | originalNewSymbols originalSymbolTable newNewSymbols newSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + newNewSymbols := WeakSet new. + newSymbolTable := originalSymbolTable copy + addAll: originalNewSymbols; + compact; + yourself. + originalNewSymbols == NewSymbols ifFalse: [ + "Some other process has modified the symbols. Try again." + ^self condenseNewSymbols ]. + NewSymbols := newNewSymbols. + SymbolTable := newSymbolTable! Item was changed: ----- Method: Symbol class>>intern: (in category 'instance creation') ----- intern: aStringOrSymbol + | originalNewSymbols | + originalNewSymbols := NewSymbols. ^(self lookup: aStringOrSymbol) ifNil:[ + | aClass aSymbol newNewSymbols | - | aClass aSymbol | aStringOrSymbol isSymbol ifTrue:[ aSymbol := aStringOrSymbol. ] ifFalse:[ aClass := aStringOrSymbol isOctetString ifTrue:[ByteSymbol] ifFalse:[WideSymbol]. aSymbol := aClass new: aStringOrSymbol size. aSymbol string: aStringOrSymbol. ]. + newNewSymbols := originalNewSymbols copyWith: aSymbol. + originalNewSymbols == NewSymbols + ifTrue: [ + NewSymbols := newNewSymbols. + newNewSymbols size > 1000 ifTrue: [ self condenseNewSymbols ]. + aSymbol ] + ifFalse: [ + "Some other process has modified the symbols. Try again." + self intern: aStringOrSymbol ] ]! - NewSymbols add: aSymbol. - aSymbol].! Item was changed: ----- Method: Symbol class>>lookup: (in category 'instance creation') ----- lookup: aStringOrSymbol + | originalNewSymbols originalSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + ^(originalNewSymbols like: aStringOrSymbol) ifNil: [ + originalSymbolTable like: aStringOrSymbol ]! - ^(SymbolTable like: aStringOrSymbol) ifNil: [ - NewSymbols like: aStringOrSymbol - ]! Item was changed: ----- Method: Symbol class>>rehash (in category 'private') ----- + rehash + "Rebuild the hash table, reclaiming unreferenced Symbols. This method will intern all symbols. You're probably looking for #condenseNewSymbols instead." - rehash "Symbol rehash" - "Rebuild the hash table, reclaiming unreferenced Symbols." + | originalNewSymbols originalSymbolTable newNewSymbols newSymbolTable | + originalNewSymbols := NewSymbols. + originalSymbolTable := SymbolTable. + newNewSymbols := WeakSet new. + newSymbolTable := WeakSet withAll: self allSubInstances. + originalNewSymbols == NewSymbols ifFalse: [ + "Some other process has modified the symbols. Try again." + ^self rehash ]. + NewSymbols := newNewSymbols. + SymbolTable := newSymbolTable! - SymbolTable := WeakSet withAll: self allSubInstances. - NewSymbols := WeakSet new.! Item was changed: ----- Method: Symbol class>>shutDown: (in category 'private') ----- shutDown: aboutToQuit + self condenseNewSymbols! - SymbolTable addAll: NewSymbols. - NewSymbols := WeakSet new.! From tim at rowledge.org Mon Oct 27 20:52:41 2014 From: tim at rowledge.org (tim Rowledge) Date: Mon Oct 27 20:52:48 2014 Subject: [squeak-dev] Color>>quickHighLight: problems with transparent images Message-ID: The Color>>quickHighLight: method is ancient and appears to be wrong when using ?modern? pixel values where 0 is transparent and 16r1 is black. The use case is getting a decently visible colour for a cursor when painted onto an arbitrarily coloured background image. Strictly speaking a bitwise reverse isn?t a perceptually reliable algorithm but it is at least quick and usually tolerable. Consider the following code - |bitBlt bufferForm| bufferForm := Form extent: 100@20 depth: 32. bufferForm fillWhite. bitBlt := (BitBlt toForm: bufferForm) clipRect: bufferForm boundingBox; fillColor: (Color quickHighLight: bufferForm depth); combinationRule: Form reverse. bitBlt destRect: (0@0 extent: (bufferForm width /2) @bufferForm height); copyBits. bufferForm displayOn: Display at: 0@0 rule: Form paint What one wants to see is a patch in the top left of the Display with a 50x20 black area and a 50x20 white area. You get 50x20 transparent (ie nothing visible) and 50x20 white. If we change the code to |bitBlt bufferForm| bufferForm := Form extent: 100@20 depth: 32. bufferForm fillWhite. bitBlt := (BitBlt toForm: bufferForm) clipRect: bufferForm boundingBox; fillColor: (Bitmap with: 16rFFFFFFFE); combinationRule: Form reverse. bitBlt destRect: (0@0 extent: (bufferForm width /2) @bufferForm height); copyBits. bufferForm displayOn: Display at: 0@0 rule: Form paint ? then we see what we wanted. I?m not completely convinced that changing the Color>>initializeHighLights method to - initializeHighLights "Create a set of Bitmaps for quickly reversing areas of the screen without converting colors. " "Color initializeHighLights" | t | t := Array new: 32. t at: 1 put: (Bitmap with: 16rFFFFFFFF). t at: 2 put: (Bitmap with: 16rFFFFFFFF). t at: 4 put: (Bitmap with: 16r55555555). t at: 8 put: (Bitmap with: 16r7070707). t at: 16 put: (Bitmap with: 16rFFFFFFFF). t at: 32 put: (Bitmap with: 16rFFFFFFFE). HighLightBitmaps := t. ? is completely correct, but it might be. Does the 16bpp case need changing? Is there a bitblt rule I?m unaware of that does things better? tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Fac ut vivas. = Get a life. From commits at source.squeak.org Mon Oct 27 20:53:16 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 20:53:18 2014 Subject: [squeak-dev] The Trunk: System-ul.688.mcz Message-ID: Levente Uzonyi uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-ul.688.mcz ==================== Summary ==================== Name: System-ul.688 Author: ul Time: 27 October 2014, 4:43:14.279 pm UUID: 77747387-55a5-4118-95b5-752979bf1cf7 Ancestors: System-dtl.685 Replaced ExternalSemaphoreTable with ExternalObjectTable to provide faster registration, and give better support to the current users of external objects. Notable changes: - the table is a separate object instead of a few class side methods - the whole API can be found in SmalltalkImage in the external objects category - #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores: provide fast and easy creation and registration of Semaphores - #unregisterExternalObjects: can unregister multiple objects faster - #externalObjects will return a copy of the externalObjectsArray - better scalability - the maxExternalSemaphores VM parameter will be incremented as the externalObjectsArray grows =============== Diff against System-dtl.685 =============== Item was added: + Object subclass: #ExternalObjectTable + instanceVariableNames: 'semaphore externalObjectsArray freeSlotIndexes indexesByObjects' + classVariableNames: '' + poolDictionaries: '' + category: 'System-Support'! + ExternalObjectTable class + instanceVariableNames: 'current'! + + !ExternalObjectTable commentStamp: 'ul 10/27/2014 16:26' prior: 0! + I'm an enhanced version of JMM's ExternalSemaphoreTable. + I'm responsible for maintaining the externalObjectsArray, which can be found at slot 39 of Smalltalk specialObjectsArray. Manipulating the array directly is highly discouraged. + + My services are available via the methods of the "external objects" category of SmalltalkImage. + + To register anObject simply use Smalltalk registerExternalObject: anObject. Use #unregisterExternalObject: to unregister it. It your responsibility to always unregister these objects. + If you'd like the create one or more new Semaphores, and register them for external use, then you should use one of #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores:. If you want to unregister more than one external objects at the same time, then #unregisterExternalObjects: is the method you're looking for. + + Implementation details: + I maintain a single instance (#current), which can automatically synchronize with externalObjectsArray. + All accesses are protected by the semaphore instance variable. + To ensure fast access, I keep track of the indexes of the external objects in the externalObjectArray in my indexesByObjects IdentityDictionary. + To ensure fast insertion, I keep track of the free slots of the externalObjectsArray in the freeSlotIndexes OrderedCollection. The access pattern is LIFO to avoid unnecessary growth and reordering of the OrderedCollection. + I can grow the externalObjectsArray (see #ensureFreeSlot), but I never shrink it.! + ExternalObjectTable class + instanceVariableNames: 'current'! Item was added: + ----- Method: ExternalObjectTable class>>cleanUp: (in category 'initialize-release') ----- + cleanUp: aggressive + "It's safe to release the instance" + + self reset! Item was added: + ----- Method: ExternalObjectTable class>>current (in category 'accessing') ----- + current + + ^current ifNil: [ + | newInstance | + newInstance := self new. + " Check again, because another process might have registered another instance. " + current ifNil: [ current := newInstance ] ]! Item was added: + ----- Method: ExternalObjectTable class>>reset (in category 'accessing') ----- + reset + + current := nil! Item was added: + ----- Method: ExternalObjectTable>>clearExternalObjects (in category 'accessing') ----- + clearExternalObjects + "Clear the array of objects that have been registered for use in non-Smalltalk code." + + semaphore critical: [ + Smalltalk specialObjectsArray at: 39 put: Array new. + self + initializeCaches; + synchronizeExternalObjectsArrayAndForceUpdate: true ]! Item was added: + ----- Method: ExternalObjectTable>>ensureFreeSlot (in category 'private') ----- + ensureFreeSlot + "Make sure there's at least one free slot." + + | oldSize newSize newExternalObjectsArray specialObjectsArray | + freeSlotIndexes isEmpty ifFalse: [ ^self ]. + oldSize := externalObjectsArray size. + newSize := oldSize + 20. "Linear growth is not really a problem, because we never shrink the array." + newExternalObjectsArray := externalObjectsArray species new: newSize. + newExternalObjectsArray + replaceFrom: 1 + to: oldSize + with: externalObjectsArray + startingAt: 1. + specialObjectsArray := Smalltalk specialObjectsArray. + (specialObjectsArray at: 39) == externalObjectsArray + ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + ensureFreeSlot ]. + specialObjectsArray at: 39 put: newExternalObjectsArray. + externalObjectsArray := newExternalObjectsArray. + newSize to: oldSize + 1 by: -1 do: [ :each | + freeSlotIndexes addFirst: each ]. + Smalltalk maxExternalSemaphores ifNotNil: [ :maxExternalSemaphores | + "Make sure that those new external semaphores can be signaled by the VM. This is not entirely safe, but not incrementing at all is worse." + newSize > maxExternalSemaphores ifTrue: [ + Smalltalk maxExternalSemaphores: newSize ] ] + + ! Item was added: + ----- Method: ExternalObjectTable>>externalObjects (in category 'accessing') ----- + externalObjects + "Return a copy of the externalObjectsArray." + + ^semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + externalObjectsArray copy ]! Item was added: + ----- Method: ExternalObjectTable>>externalObjectsArray: (in category 'private') ----- + externalObjectsArray: anArray + "Update the index mapping using anArray as the new externalObjectsArray." + + externalObjectsArray := anArray. + freeSlotIndexes reset. + indexesByObjects removeAll. + 1 to: externalObjectsArray size do: [ :index | + (anArray at: index) + ifNil: [ freeSlotIndexes addFirst: index ] + ifNotNil: [ :object | indexesByObjects at: object put: index ] ]! Item was added: + ----- Method: ExternalObjectTable>>initialize (in category 'initialize-release') ----- + initialize + + semaphore := Semaphore forMutualExclusion. + self initializeCaches! Item was added: + ----- Method: ExternalObjectTable>>initializeCaches (in category 'private') ----- + initializeCaches + + freeSlotIndexes := OrderedCollection new. + indexesByObjects := IdentityDictionary new! Item was added: + ----- Method: ExternalObjectTable>>newExternalSemaphore (in category 'accessing') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return an array containing itself and its index." + + | newSemaphore | + ^{ + newSemaphore := Semaphore new. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterNewExternalObject: newSemaphore ] }! Item was added: + ----- Method: ExternalObjectTable>>newExternalSemaphoreDo: (in category 'accessing') ----- + newExternalSemaphoreDo: aBlock + "Create and register a new Semaphore, then evaluate aBlock with it and its index." + + | newSemaphore | + ^aBlock + value: (newSemaphore := Semaphore new) + value: (semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterNewExternalObject: newSemaphore ])! Item was added: + ----- Method: ExternalObjectTable>>newExternalSemaphores: (in category 'accessing') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing the semaphores and their indexes in separate arrays." + + | semaphores indexes | + semaphores := Array new: count. + 1 to: count do: [ :index | semaphores at: index put: Semaphore new ]. + indexes := Array new: count. + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + 1 to: count do: [ :index | + indexes at: index put: ( + self safelyRegisterNewExternalObject: (semaphores at: index)) ] ]. + ^{ semaphores. indexes }! Item was added: + ----- Method: ExternalObjectTable>>registerExternalObject: (in category 'accessing') ----- + registerExternalObject: anObject + "Register the given object in the external objects array and return its index. If it is already there, just return its index." + + anObject ifNil: [ ^nil ]. + ^semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyRegisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalObjectTable>>safelyRegisterExternalObject: (in category 'private') ----- + safelyRegisterExternalObject: anObject + + | index | + (index := indexesByObjects at: anObject ifAbsent: nil) ifNotNil: [ + (externalObjectsArray at: index) == anObject ifTrue: [ ^index ]. + "indexesByObjects is out of sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterExternalObject: anObject ]. + ^self safelyRegisterNewExternalObject: anObject! Item was added: + ----- Method: ExternalObjectTable>>safelyRegisterNewExternalObject: (in category 'private') ----- + safelyRegisterNewExternalObject: anObject + + | index | + self ensureFreeSlot. + index := freeSlotIndexes removeLast. + (externalObjectsArray at: index) ifNotNil: [ + "Free slot is not empty. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyRegisterNewExternalObject: anObject ]. + externalObjectsArray at: index put: anObject. + indexesByObjects at: anObject put: index. + ^index! Item was added: + ----- Method: ExternalObjectTable>>safelyUnregisterExternalObject: (in category 'private') ----- + safelyUnregisterExternalObject: anObject + + (indexesByObjects removeKey: anObject ifAbsent: nil) + ifNotNil: [ :index | + (externalObjectsArray at: index) == anObject ifFalse: [ + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]. + externalObjectsArray at: index put: nil. + freeSlotIndexes add: index ] + ifNil: [ + "Check if we're just out of sync." + (externalObjectsArray instVarsInclude: anObject) ifFalse: [ ^self ]. + "We're not in sync. Try again." + ^self + synchronizeExternalObjectsArrayAndForceUpdate: true; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalObjectTable>>synchronizeExternalObjectsArrayAndForceUpdate: (in category 'private') ----- + synchronizeExternalObjectsArrayAndForceUpdate: forceUpdate + + | actualExternalObjectsArray | + actualExternalObjectsArray := Smalltalk specialObjectsArray at: 39. + (actualExternalObjectsArray == externalObjectsArray and: [ forceUpdate not ]) + ifTrue: [ ^self ]. + self externalObjectsArray: actualExternalObjectsArray! Item was added: + ----- Method: ExternalObjectTable>>unregisterExternalObject: (in category 'accessing') ----- + unregisterExternalObject: anObject + "Unregister the given object from the external objects array. Do nothing if it isn't registered." + + anObject ifNil: [ ^self ]. + semaphore critical: [ + self + synchronizeExternalObjectsArrayAndForceUpdate: false; + safelyUnregisterExternalObject: anObject ]! Item was added: + ----- Method: ExternalObjectTable>>unregisterExternalObjects: (in category 'accessing') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + semaphore critical: [ + self synchronizeExternalObjectsArrayAndForceUpdate: false. + aCollection do: [ :each | + each ifNotNil: [ + self safelyUnregisterExternalObject: each ] ] ]! Item was removed: - Object subclass: #ExternalSemaphoreTable - instanceVariableNames: '' - classVariableNames: 'ProtectTable' - poolDictionaries: '' - category: 'System-Support'! - - !ExternalSemaphoreTable commentStamp: '' prior: 0! - By John M McIntosh johnmci@smalltalkconsulting.com - This class was written to mange the external semaphore table. When I was writing a Socket test server I discovered various race conditions on the access to the externalSemaphore table. This new class uses class side methods to restrict access using a mutex semaphore. It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary - - Note that in Smalltalk recreateSpecialObjectsArray we still directly play with the table.! Item was removed: - ----- Method: ExternalSemaphoreTable class>>clearExternalObjects (in category 'accessing') ----- - clearExternalObjects - "Clear the array of objects that have been registered for use in non-Smalltalk code." - - ProtectTable critical: [Smalltalk specialObjectsArray at: 39 put: Array new]. - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>externalObjects (in category 'accessing') ----- - externalObjects - ^ProtectTable critical: [Smalltalk specialObjectsArray at: 39].! Item was removed: - ----- Method: ExternalSemaphoreTable class>>initialize (in category 'initialize') ----- - initialize - ProtectTable := Semaphore forMutualExclusion! Item was removed: - ----- Method: ExternalSemaphoreTable class>>registerExternalObject: (in category 'accessing') ----- - registerExternalObject: anObject - ^ ProtectTable critical: [self safelyRegisterExternalObject: anObject] - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyRegisterExternalObject: (in category 'accessing') ----- - safelyRegisterExternalObject: anObject - "Register the given object in the external objects array and return its index. If it is already there, just return its index." - - | objects firstEmptyIndex obj sz newObjects | - objects := Smalltalk specialObjectsArray at: 39. - - "find the first empty slot" - firstEmptyIndex := 0. - 1 to: objects size do: [:i | - obj := objects at: i. - obj == anObject ifTrue: [^ i]. "object already there, just return its index" - (obj == nil and: [firstEmptyIndex = 0]) ifTrue: [firstEmptyIndex := i]]. - - "if no empty slots, expand the array" - firstEmptyIndex = 0 ifTrue: [ - sz := objects size. - newObjects := objects species new: sz + 20. "grow linearly" - newObjects replaceFrom: 1 to: sz with: objects startingAt: 1. - firstEmptyIndex := sz + 1. - Smalltalk specialObjectsArray at: 39 put: newObjects. - objects := newObjects]. - - objects at: firstEmptyIndex put: anObject. - ^ firstEmptyIndex - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>safelyUnregisterExternalObject: (in category 'accessing') ----- - safelyUnregisterExternalObject: anObject - "Unregister the given object in the external objects array. Do nothing if it isn't registered. - JMM change to return if we clear the element, since it should only appear once in the array" - - | objects | - anObject ifNil: [^ self]. - objects := Smalltalk specialObjectsArray at: 39. - 1 to: objects size do: [:i | - (objects at: i) == anObject ifTrue: - [objects at: i put: nil. - ^self]]. - ! Item was removed: - ----- Method: ExternalSemaphoreTable class>>unregisterExternalObject: (in category 'accessing') ----- - unregisterExternalObject: anObject - ProtectTable critical: [self safelyUnregisterExternalObject: anObject] - ! Item was changed: + ----- Method: SmalltalkImage>>clearExternalObjects (in category 'external objects') ----- - ----- Method: SmalltalkImage>>clearExternalObjects (in category 'special objects') ----- clearExternalObjects "Clear the array of objects that have been registered for use in non-Smalltalk code." "Smalltalk clearExternalObjects" + ExternalObjectTable current clearExternalObjects - ExternalSemaphoreTable clearExternalObjects ! Item was changed: + ----- Method: SmalltalkImage>>externalObjects (in category 'external objects') ----- - ----- Method: SmalltalkImage>>externalObjects (in category 'special objects') ----- externalObjects "Return an array of objects that have been registered for use in non-Smalltalk code. Smalltalk objects should be referrenced by external code only via indirection through this array, thus allowing the objects to move during compaction. This array can be cleared when the VM re-starts, since variables in external code do not survive snapshots. Note that external code should not attempt to access a Smalltalk object, even via this mechanism, while garbage collection is in progress." + "Note that this is just a copy of the array used by the VM." "Smalltalk externalObjects" + ^ExternalObjectTable current externalObjects - ^ ExternalSemaphoreTable externalObjects ! Item was added: + ----- Method: SmalltalkImage>>newExternalSemaphore (in category 'external objects') ----- + newExternalSemaphore + "Create and register a new Semaphore, and return an array containing itself and its index." + + ^ExternalObjectTable current newExternalSemaphore! Item was added: + ----- Method: SmalltalkImage>>newExternalSemaphoreDo: (in category 'external objects') ----- + newExternalSemaphoreDo: aBlock + "Create and register a new Semaphore, then evaluate aBlock with it and its index." + + ^ExternalObjectTable current newExternalSemaphoreDo: aBlock! Item was added: + ----- Method: SmalltalkImage>>newExternalSemaphores: (in category 'external objects') ----- + newExternalSemaphores: count + "Create and register multiple Semaphores, and return an array containing the semaphores and their indexes in separate arrays." + + ^ExternalObjectTable current newExternalSemaphores: count! Item was changed: + ----- Method: SmalltalkImage>>registerExternalObject: (in category 'external objects') ----- - ----- Method: SmalltalkImage>>registerExternalObject: (in category 'special objects') ----- registerExternalObject: anObject "Register the given object in the external objects array and return its index. If it is already there, just return its index." + ^ExternalObjectTable current registerExternalObject: anObject! - ^ExternalSemaphoreTable registerExternalObject: anObject! Item was changed: + ----- Method: SmalltalkImage>>unregisterExternalObject: (in category 'external objects') ----- - ----- Method: SmalltalkImage>>unregisterExternalObject: (in category 'special objects') ----- unregisterExternalObject: anObject "Unregister the given object in the external objects array. Do nothing if it isn't registered." + ExternalObjectTable current unregisterExternalObject: anObject! - ExternalSemaphoreTable unregisterExternalObject: anObject! Item was added: + ----- Method: SmalltalkImage>>unregisterExternalObjects: (in category 'external objects') ----- + unregisterExternalObjects: aCollection + "Unregister the given objects from the external objects array. Do nothing if they aren't registered." + + ExternalObjectTable current unregisterExternalObjects: aCollection! From commits at source.squeak.org Mon Oct 27 20:54:12 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 20:54:14 2014 Subject: [squeak-dev] The Trunk: KernelTests-nice.280.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.280.mcz ==================== Summary ==================== Name: KernelTests-nice.280 Author: nice Time: 27 October 2014, 9:53:44.861 pm UUID: fc50e9f5-10d8-45d8-8c9e-e80806596878 Ancestors: KernelTests-dtl.279 Two more expectations for float literal equality: - zero and negativeZero are equal but not #literalEqual: - nan are not equals but can be #literalEqual: Thanks to Kris Gybels for reporting this case at https://pharo.fogbugz.com/f/cases/14316/ =============== Diff against KernelTests-dtl.279 =============== Item was added: + ----- Method: FloatTest>>testLiteralEqualityOfNan (in category 'testing compare') ----- + testLiteralEqualityOfNan + | nan | + nan := Float nan. + self assert: (nan literalEqual: nan) + description: 'Float nan is not equal to itself, though it is literally equal'.! Item was added: + ----- Method: FloatTest>>testLiteralEqualityOfZeroAndNegativeZero (in category 'testing compare') ----- + testLiteralEqualityOfZeroAndNegativeZero + self assert: -1 + equals: (Compiler evaluate: '1>2 ifTrue: [0.0] ifFalse: [-0.0]') sign + description: 'Float zero and negativeZero are not literally substituable'.! From brasspen at gmail.com Mon Oct 27 20:55:08 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Mon Oct 27 20:55:12 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: References: Message-ID: > On Oct 27, 2014, at 4:26 PM, Edgar J. De Cleene wrote: > > > > > On 10/27/14, 4:20 PM, "Chris Cunnington" wrote: > >>> OK, you opened the SwikiBrowser, perhaps with this: >>> >>> (SwikiBrowser asMorphOnShelf: SwikiShelf allInstances first) openInWorld >>> >>> and the ?ani? is present. Hmm, that?s true. I see it as well. The SwikiBrowser shows all the files in the ?swiki? folder regardless of whether they are used or not. It just shows files. >>> I guess if the ani is not showing up then it?s a configuration thing. Not essential, I don?t suppose, though. The ?ani? is a different version of the same kind of wiki seen in ?refs?. >>> Thanks for pointing it out. I?ll have to figure out how to switch between the two or have both at the same time. >>> >>> Chris > > > The point in cuestion is ani is the last and cute version of Swiki. > If you don?t have it, can?t inherit of this > > See http://190.189.179.48:8888/ is served by very old SqueakLight. > > If you plan resurrect and develop ComSwiki, I can help with how to have tons of js, css, etc like tinymce, bootstrap, others free cute doing visual impact to user. > > http://190.189.179.48:9090/ > user: visita > pass: (nothing here) > > It?s old Sblog and old Swiki served on tp of HV2 > > Edgar > Wow. This stuff looks great. I?m glad someone has lots of knowledge of how to use the Swiki. I?m not going to pretend I do. There?s quite a lot to it. And, yes, your help would be great. I?m impressed you have Bootstrap on a Swiki. Time to start editing and adding to the Swiki Swiki, I guess. Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/75358a59/attachment.htm From commits at source.squeak.org Mon Oct 27 21:00:40 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 21:00:41 2014 Subject: [squeak-dev] The Trunk: Kernel-nice.881.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.881.mcz ==================== Summary ==================== Name: Kernel-nice.881 Author: nice Time: 27 October 2014, 9:59:32.033 pm UUID: 3a3a0a22-ab12-4838-8606-250c9e58cf76 Ancestors: Kernel-ul.880 Fix Float literal equality: 0.0 and -0.0 are not the same Float... =============== Diff against Kernel-ul.880 =============== Item was added: + ----- Method: Float>>literalEqual: (in category 'comparing') ----- + literalEqual: aFloat + "Two float literals can be replaced by a single one only if their representation have the same bits. + For example, zero and negativeZero are equal, but not literally equal." + + ^self class == aFloat class and: [(self at: 1) = (aFloat at: 1) and: [(self at: 2) = (aFloat at: 2)]]! From nicolas.cellier.aka.nice at gmail.com Mon Oct 27 21:13:44 2014 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon Oct 27 21:13:48 2014 Subject: [squeak-dev] The Trunk: KernelTests-nice.280.mcz In-Reply-To: <544eb107.6201980a.0cd3.4279SMTPIN_ADDED_MISSING@mx.google.com> References: <544eb107.6201980a.0cd3.4279SMTPIN_ADDED_MISSING@mx.google.com> Message-ID: Once upon a Time, there could have been a literal nan... Yes, in Squeak 3.8 or 3.9 when formed thru ('0.' , (String new: 320 withAll: $0) , '1e321') - see http://bugs.squeak.org/view.php?id=6982 Let's consider this case rare and accidental... Now, even if literalEqualityOfNan is a bit like unreachable, let's consider this as a future proof test... 2014-10-27 21:53 GMT+01:00 : > Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: > http://source.squeak.org/trunk/KernelTests-nice.280.mcz > > ==================== Summary ==================== > > Name: KernelTests-nice.280 > Author: nice > Time: 27 October 2014, 9:53:44.861 pm > UUID: fc50e9f5-10d8-45d8-8c9e-e80806596878 > Ancestors: KernelTests-dtl.279 > > Two more expectations for float literal equality: > - zero and negativeZero are equal but not #literalEqual: > - nan are not equals but can be #literalEqual: > > Thanks to Kris Gybels for reporting this case at > https://pharo.fogbugz.com/f/cases/14316/ > > =============== Diff against KernelTests-dtl.279 =============== > > Item was added: > + ----- Method: FloatTest>>testLiteralEqualityOfNan (in category 'testing > compare') ----- > + testLiteralEqualityOfNan > + | nan | > + nan := Float nan. > + self assert: (nan literalEqual: nan) > + description: 'Float nan is not equal to itself, though it > is literally equal'.! > > Item was added: > + ----- Method: FloatTest>>testLiteralEqualityOfZeroAndNegativeZero (in > category 'testing compare') ----- > + testLiteralEqualityOfZeroAndNegativeZero > + self assert: -1 > + equals: (Compiler evaluate: '1>2 ifTrue: [0.0] ifFalse: > [-0.0]') sign > + description: 'Float zero and negativeZero are not > literally substituable'.! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141027/74c68bde/attachment.htm From commits at source.squeak.org Mon Oct 27 21:15:01 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 21:15:04 2014 Subject: [squeak-dev] The Trunk: Files-ul.141.mcz Message-ID: Levente Uzonyi uploaded a new version of Files to project The Trunk: http://source.squeak.org/trunk/Files-ul.141.mcz ==================== Summary ==================== Name: Files-ul.141 Author: ul Time: 27 October 2014, 4:51:14.305 pm UUID: b0dbabfe-ce75-4f18-a82f-2f95fa8b026e Ancestors: Files-eem.138 - use the new ExternalObjectTable API =============== Diff against Files-eem.138 =============== Item was changed: ----- Method: AsyncFile>>open:forWrite: (in category 'as yet unclassified') ----- open: fullFileName forWrite: aBoolean "Open a file of the given name, and return a handle for that file. Answer the receiver if the primitive succeeds, nil otherwise. If openForWrite is true, then: if there is no existing file with this name, then create one else open the existing file in read-write mode otherwise: if there is an existing file with this name, then open it read-only else answer nil." "Note: if an exisiting file is opened for writing, it is NOT truncated. If truncation is desired, the file should be deleted before being opened as an asynchronous file." "Note: On some platforms (e.g., Mac), a file can only have one writer at a time." - | semaIndex | name := fullFileName. writeable := aBoolean. + ^Smalltalk newExternalSemaphoreDo: [ :newSemaphore :index | + fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: index. + fileHandle + ifNotNil: [ + semaphore := newSemaphore. + self ] + ifNil: [ + Smalltalk unregisterExternalObject: newSemaphore. + nil ] ]! - semaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - fileHandle := self primOpen: name asVmPathName forWrite: writeable semaIndex: semaIndex. - fileHandle ifNil: [ - Smalltalk unregisterExternalObject: semaphore. - semaphore := nil. - ^ nil]. - ! Item was changed: ----- Method: StandardFileStream>>post:target:url:ifError: (in category 'browser requests') ----- post: data target: target url: url ifError: errorBlock "Post data to the given URL. The returned file stream contains the reply of the server. If Squeak is not running in a browser evaluate errorBlock" + - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLPost: url target: target data: data semaIndex: index. + request ifNil: [ + Smalltalk unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. + result ifTrue: [ fileID := self primURLRequestFileHandle: request ]. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLPost: url target: target data: data semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. - result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. + Smalltalk unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! Item was changed: ----- Method: StandardFileStream>>requestURL:target:ifError: (in category 'browser requests') ----- requestURL: url target: target ifError: errorBlock "Request to go to the target for the given URL. If Squeak is not running in a browser evaluate errorBlock" - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLRequest: url target: target semaIndex: index. + request ifNil: [ + Smalltalk unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url target: target semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. self primURLRequestDestroy: request. + Smalltalk unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! Item was changed: ----- Method: StandardFileStream>>requestURLStream:ifError: (in category 'browser requests') ----- requestURLStream: url ifError: errorBlock "Request a FileStream for the given URL. If Squeak is not running in a browser evaluate errorBlock" "FileStream requestURLStream:'http://www.squeak.org'" + - | sema index request result | self waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value]. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + | request result | + request := self primURLRequest: url semaIndex: index. + request ifNil: [ + Smalltalk unregisterExternalObject: semaphore. + ^errorBlock value ]. + [ semaphore wait. "until something happens" + result := self primURLRequestState: request. + result == nil ] whileTrue. + result ifTrue: [ fileID := self primURLRequestFileHandle: request ]. - sema := Semaphore new. - index := Smalltalk registerExternalObject: sema. - request := self primURLRequest: url semaIndex: index. - request == nil ifTrue:[ - - Smalltalk unregisterExternalObject: sema. - ^errorBlock value. - ] ifFalse:[ - [sema wait. "until something happens" - result := self primURLRequestState: request. - result == nil] whileTrue. - result ifTrue:[fileID := self primURLRequestFileHandle: request]. self primURLRequestDestroy: request. + Smalltalk unregisterExternalObject: semaphore ]. + fileID ifNil: [ ^nil ]. - ]. - Smalltalk unregisterExternalObject: sema. - fileID == nil ifTrue:[^nil]. self register. name := url. rwmode := false. buffer1 := String new: 1. + self enableReadBuffering! - self enableReadBuffering - ! From commits at source.squeak.org Mon Oct 27 21:15:40 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 21:15:42 2014 Subject: [squeak-dev] The Trunk: Network-ul.155.mcz Message-ID: Levente Uzonyi uploaded a new version of Network to project The Trunk: http://source.squeak.org/trunk/Network-ul.155.mcz ==================== Summary ==================== Name: Network-ul.155 Author: ul Time: 27 October 2014, 4:46:13.635 pm UUID: cf2f8a25-3525-4183-8f93-7dc5d127f22d Ancestors: Network-ul.152 - use the new ExternalObjectTable API - unifed socket initialization - unregister ResolverSemaphore when the network initialization fails =============== Diff against Network-ul.152 =============== Item was changed: ----- Method: NetNameResolver class>>initializeNetwork (in category 'network initialization') ----- initializeNetwork "Initialize the network drivers and record the semaphore to be used by the resolver. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails." "NetNameResolver initializeNetwork" - | semaIndex | self resolverStatus = ResolverUninitialized ifFalse: [^HaveNetwork := true]. "network is already initialized" HaveNetwork := false. "in case abort" + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + ResolverSemaphore := semaphore. + "result is nil if network initialization failed, self if it succeeds" + (self primInitializeNetwork: index) + ifNil: [ + Smalltalk unregisterExternalObject: ResolverSemaphore. + ResolverSemaphore := nil. + NoNetworkError signal: 'failed network initialization'] + ifNotNil: [ HaveNetwork := true ] ]. - ResolverSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: ResolverSemaphore. + self initializeOldNetworkFlag! - "result is nil if network initialization failed, self if it succeeds" - (self primInitializeNetwork: semaIndex) - ifNil: [NoNetworkError signal: 'failed network initialization'] - ifNotNil: [HaveNetwork := true]. - - self initializeOldNetworkFlag - ! Item was changed: ----- Method: Socket>>acceptFrom: (in category 'initialize-destroy') ----- acceptFrom: aSocket "Initialize a new socket handle from an accept call" - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | + self + primAcceptFrom: aSocket socketHandle + receiveBufferSize: 8000 + sendBufSize: 8000 + semaIndex: semaIndex + readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primAcceptFrom: aSocket socketHandle - receiveBufferSize: 8000 - sendBufSize: 8000 - semaIndex: semaIndex - readSemaIndex: readSemaIndex - writeSemaIndex: writeSemaIndex. - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>destroy (in category 'initialize-destroy') ----- destroy "Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil)." socketHandle ifNotNil: [ self isValid ifTrue: [ self primSocketDestroy: socketHandle ]. + Smalltalk unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore }. - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. socketHandle := nil. readSemaphore := writeSemaphore := semaphore := nil. self unregister ]! Item was changed: ----- Method: Socket>>finalize (in category 'finalization') ----- finalize + self primSocketDestroyGently: socketHandle. + Smalltalk unregisterExternalObjects: { + semaphore. + readSemaphore. + writeSemaphore } - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. ! Item was changed: ----- Method: Socket>>initialize: (in category 'initialize-destroy') ----- initialize: socketType "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: 0 type: socketType receiveBufferSize: 8000 sendBufSize: 8000 semaIndex: semaIndex readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was changed: ----- Method: Socket>>initialize:family: (in category 'initialize-destroy') ----- initialize: socketType family: family "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." - | semaIndex readSemaIndex writeSemaIndex | + NetNameResolver useOldNetwork ifTrue: [ ^self initialize: socketType ]. + self initializeSocketHandleUsing: [ :semaIndex :readSemaIndex :writeSemaIndex | - NetNameResolver useOldNetwork ifTrue: [^self initialize: socketType]. - semaphore := Semaphore new. - readSemaphore := Semaphore new. - writeSemaphore := Semaphore new. - semaIndex := Smalltalk registerExternalObject: semaphore. - readSemaIndex := Smalltalk registerExternalObject: readSemaphore. - writeSemaIndex := Smalltalk registerExternalObject: writeSemaphore. - socketHandle := self primSocketCreateNetwork: family type: socketType receiveBufferSize: 8000 sendBufSize: 8000 semaIndex: semaIndex readSemaIndex: readSemaIndex + writeSemaIndex: writeSemaIndex ]! - writeSemaIndex: writeSemaIndex. - - socketHandle - ifNotNil: [ self register ] - ifNil: [ "socket creation failed" - Smalltalk unregisterExternalObject: semaphore. - Smalltalk unregisterExternalObject: readSemaphore. - Smalltalk unregisterExternalObject: writeSemaphore. - readSemaphore := writeSemaphore := semaphore := nil ] - ! Item was added: + ----- Method: Socket>>initializeSocketHandleUsing: (in category 'initialize-destroy') ----- + initializeSocketHandleUsing: aBlock + "Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil." + + | semaphoresAndIndexes semaphores indexes | + semaphoresAndIndexes := Smalltalk newExternalSemaphores: 3. + semaphores := semaphoresAndIndexes at: 1. + indexes := semaphoresAndIndexes at: 2. + semaphore := semaphores at: 1. + readSemaphore := semaphores at: 2. + writeSemaphore := semaphores at: 3. + (socketHandle := aBlock valueWithArguments: indexes) + ifNotNil: [ self register ] + ifNil: [ + "socket creation failed" + semaphore := readSemaphore := writeSemaphore := nil. + Smalltalk unregisterExternalObjects: semaphores ]! From commits at source.squeak.org Mon Oct 27 21:15:48 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 21:15:52 2014 Subject: [squeak-dev] The Trunk: Sound-ul.41.mcz Message-ID: Levente Uzonyi uploaded a new version of Sound to project The Trunk: http://source.squeak.org/trunk/Sound-ul.41.mcz ==================== Summary ==================== Name: Sound-ul.41 Author: ul Time: 27 October 2014, 4:48:59.268 pm UUID: b700fc19-c219-47e3-bc55-4874db9dea22 Ancestors: Sound-nice.38 - use the new ExternalObjectTable API =============== Diff against Sound-nice.38 =============== Item was changed: ----- Method: SoundPlayer class>>startPlayerProcessBufferSize:rate:stereo:sound: (in category 'player process') ----- startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound "Start the sound player process. Terminate the old process, if any." "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false" self stopPlayerProcess. aSound ifNil:[ActiveSounds := OrderedCollection new] ifNotNil:[ActiveSounds := OrderedCollection with: aSound]. Buffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4. LastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize]. PlayerSemaphore := Semaphore forMutualExclusion. SamplingRate := samplesPerSecond. Stereo := stereoFlag. - ReadyForBuffer := Semaphore new. SoundSupported := true. "Assume so" UseReadySemaphore := true. "set to false if ready semaphore not supported by VM" + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + ReadyForBuffer := semaphore. + self primSoundStartBufferSize: Buffer stereoSampleCount + rate: samplesPerSecond + stereo: Stereo + semaIndex: index ]. - self primSoundStartBufferSize: Buffer stereoSampleCount - rate: samplesPerSecond - stereo: Stereo - semaIndex: (Smalltalk registerExternalObject: ReadyForBuffer). "Check if sound start prim was successful" + SoundSupported ifFalse:[ + Smalltalk unregisterExternalObject: ReadyForBuffer. + ReadyForBuffer := nil. + ^self ]. - SoundSupported ifFalse:[^self]. UseReadySemaphore ifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess] ifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess]. UseReverb ifTrue: [self startReverb]. PlayerProcess priority: Processor userInterruptPriority. + PlayerProcess resume! - PlayerProcess resume.! Item was changed: ----- Method: SoundRecorder>>startRecording (in category 'recording controls') ----- startRecording "Turn of the sound input driver and start the recording process. Initially, recording is paused." - | semaIndex | recordLevel ifNil: [recordLevel := 0.5]. "lazy initialization" CanRecordWhilePlaying ifFalse: [SoundPlayer shutDown]. recordProcess ifNotNil: [self stopRecording]. paused := true. meteringBuffer := SoundBuffer newMonoSampleCount: 1024. meterLevel := 0. self allocateBuffer. + Smalltalk newExternalSemaphoreDo: [ :semaphore :index | + bufferAvailableSema := semaphore. + self primStartRecordingDesiredSampleRate: samplingRate asInteger + stereo: stereo + semaIndex: index ]. - bufferAvailableSema := Semaphore new. - semaIndex := Smalltalk registerExternalObject: bufferAvailableSema. - self primStartRecordingDesiredSampleRate: samplingRate asInteger - stereo: stereo - semaIndex: semaIndex. RecorderActive := true. samplingRate := self primGetActualRecordingSampleRate. self primSetRecordLevel: (1000.0 * recordLevel) asInteger. recordProcess := [self recordLoop] newProcess. recordProcess priority: Processor userInterruptPriority. + recordProcess resume! - recordProcess resume. - ! From commits at source.squeak.org Mon Oct 27 23:55:06 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Mon Oct 27 23:55:09 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141027235506.29718.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007347.html Name: Collections-ul.586 Ancestors: Collections-cmm.585 Symbol table changes: - ensure that enumerations stay consistent - avoid read-write and write-write race conditions - added a safe #condenseNewSymbols method, which is a replacement for former unsafe methods (#shutDown: and #compactSymbolTable). It's also automatically triggered whenever there are more than 1000 NewSymbols. - deprecated #compactSymbolTable - updated some comments Note that interning many symbols is a bit slower, but thread safety is more important. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007348.html Name: System-ul.688 Ancestors: System-dtl.685 Replaced ExternalSemaphoreTable with ExternalObjectTable to provide faster registration, and give better support to the current users of external objects. Notable changes: - the table is a separate object instead of a few class side methods - the whole API can be found in SmalltalkImage in the external objects category - #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores: provide fast and easy creation and registration of Semaphores - #unregisterExternalObjects: can unregister multiple objects faster - #externalObjects will return a copy of the externalObjectsArray - better scalability - the maxExternalSemaphores VM parameter will be incremented as the externalObjectsArray grows ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007349.html Name: KernelTests-nice.280 Ancestors: KernelTests-dtl.279 Two more expectations for float literal equality: - zero and negativeZero are equal but not #literalEqual: - nan are not equals but can be #literalEqual: Thanks to Kris Gybels for reporting this case at https://pharo.fogbugz.com/f/cases/14316/ ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007350.html Name: Kernel-nice.881 Ancestors: Kernel-ul.880 Fix Float literal equality: 0.0 and -0.0 are not the same Float... ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007351.html Name: Files-ul.141 Ancestors: Files-eem.138 - use the new ExternalObjectTable API ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007352.html Name: Network-ul.155 Ancestors: Network-ul.152 - use the new ExternalObjectTable API - unifed socket initialization - unregister ResolverSemaphore when the network initialization fails ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007353.html Name: Sound-ul.41 Ancestors: Sound-nice.38 - use the new ExternalObjectTable API ============================================= From lewis at mail.msen.com Tue Oct 28 01:31:11 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 28 01:31:14 2014 Subject: [squeak-dev] Questions about external objects In-Reply-To: <15140949-FFBE-4D82-AA5A-C53BA5A67AB6@freudenbergs.de> References: <20141025194606.GB81717@shell.msen.com> <20141025204557.GA94822@shell.msen.com> <20141026143206.GA54624@shell.msen.com> <3B1B8B07-D1A9-4B6D-927F-CD90168FE34D@freudenbergs.de> <15140949-FFBE-4D82-AA5A-C53BA5A67AB6@freudenbergs.de> Message-ID: <20141028013111.GA27128@shell.msen.com> On Mon, Oct 27, 2014 at 12:19:33PM -0400, Bert Freudenberg wrote: > > On 27.10.2014, at 12:01, Levente Uzonyi wrote: > > > Good points. I've uploaded new versions to The Inbox: > > > > Installer squeakInbox > > package: 'System-ul.688'; > > package: 'Sound-ul.41'; > > package: 'Network-ul.155'; > > package: 'Files-ul.141'; > > install. > > > > The new class is called ExternalObjectTable. ExternalSemaphoreTable is gone. All API is in SmalltalkImage in a separate category named external objects. > > > > Levente > > Ship it :) > > - Bert - Excellent. Thank you Levente! Dave From edgardec2005 at gmail.com Tue Oct 28 08:32:04 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Tue Oct 28 08:32:17 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: Message-ID: On 10/27/14, 5:55 PM, "Chris Cunnington" wrote: >> Edgar >> >> Wow. This stuff looks great. I?m glad someone has lots of knowledge of how to >> use the Swiki. I?m not going to pretend I do. There?s quite a lot to it. >> And, yes, your help would be great. I?m impressed you have Bootstrap on a >> Swiki. >> Time to start editing and adding to the Swiki Swiki, I guess. >> >> Chris Ok, I check for start with a Bootstrap bar on top your All in One. Send to youfor review, enhance, etc when ready. Edgar -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/05329f78/attachment.htm From craig at netjam.org Tue Oct 28 08:51:31 2014 From: craig at netjam.org (Craig Latta) Date: Tue Oct 28 08:51:50 2014 Subject: [squeak-dev] the current README for the Context (Spoon) IDE Message-ID: Hi all-- Comments appreciated. Spoon is now Context, and this is the README for the IDE app. It's snuck into the all-in-one structure at the topmost possible point, and, while it has a captive audience, describes a Smalltalk system from the beginning. http://thiscontext.com/2014/10/27/the-ide-app-readme thanks, -C -- Craig Latta netjam.org +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) From edgardec2005 at gmail.com Tue Oct 28 12:57:17 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Tue Oct 28 12:57:32 2014 Subject: [squeak-dev] the current README for the Context (Spoon) IDE In-Reply-To: Message-ID: On 10/28/14, 5:51 AM, "Craig Latta" wrote: > > Hi all-- > > Comments appreciated. Spoon is now Context, and this is the README > for the IDE app. It's snuck into the all-in-one structure at the topmost > possible point, and, while it has a captive audience, describes a > Smalltalk system from the beginning. > > http://thiscontext.com/2014/10/27/the-ide-app-readme > > > thanks, > > -C > > -- > Craig Latta > netjam.org > +31 6 2757 7177 (SMS ok) > + 1 415 287 3547 (no SMS) > > Thanks for this Craig, I try to made time to Spoon ASAP Edgar @morplenauta en twitter From edgardec2005 at gmail.com Tue Oct 28 14:14:40 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Tue Oct 28 14:14:51 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: Message-ID: > On 10/27/14, 5:55 PM, "Chris Cunnington" wrote: > > Edgar > > Wow. This stuff looks great. I?m glad someone has lots of knowledge of how to > use the Swiki. I?m not going to pretend I do. There?s quite a lot to it. > And, yes, your help would be great. I?m impressed you have Bootstrap on a > Swiki. > Time to start editing and adding to the Swiki Swiki, I guess. > > Chris > > > Ok, I check for start with a Bootstrap bar on top your All in One. > Send to youfor review, enhance, etc when ready. > > Edgar I think maybe is time to move to newer and cute web frameworks. Consider look http://190.189.179.48:7070/browse, courtesy of last of our cousins of Pharo. Maybe have more sense build on top of this ? ComSwiki was the state of art back in 2006, but not now Edgar From jeff.gonis at gmail.com Tue Oct 28 14:21:53 2014 From: jeff.gonis at gmail.com (Jeff Gonis) Date: Tue Oct 28 14:21:58 2014 Subject: [squeak-dev] Updating 4.5 or getting a recent build of 4.6 Message-ID: Hi Folks, I have had some time recently and decided to get back into Squeak. I grabbed Eliot's latest cog vm for windows and went to update my 4.5 image from the trunk. I hit a VM crash after a minute or two of processing updates. Trying several other vintages of Eliot's vm did not help, and I also went to the Squeak ftp site and grabbed the image in the 4.6 folder and attempted to update that and ran into the same problem. I am pretty sure this crash is the crash that was discussed on the list a while ago with a corrupted mcm/mcz file. I thought that it had been resolved, but maybe I misunderstood, or maybe I am missing a step here. Anyway, the TL;DR of this mail is: How do I avoid crashing the vm when updating from the trunk on windows, or is there a place to grab a more recent vm that can be updated safely. Figuring out either of these will work for me. I am happy to post the crash dump if that will help. Thanks for any and all help! Jeff -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/dc14225d/attachment.htm From cunningham.cb at gmail.com Tue Oct 28 14:28:09 2014 From: cunningham.cb at gmail.com (Chris Cunningham) Date: Tue Oct 28 14:28:12 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: References: Message-ID: On Tue, Oct 28, 2014 at 7:14 AM, Edgar J. De Cleene wrote: > > On 10/27/14, 5:55 PM, "Chris Cunnington" wrote: > > > > Edgar > > > > Wow. This stuff looks great. I?m glad someone has lots of knowledge of > how to > > use the Swiki. I?m not going to pretend I do. There?s quite a lot to it. > > And, yes, your help would be great. I?m impressed you have Bootstrap on a > > Swiki. > > Time to start editing and adding to the Swiki Swiki, I guess. > > > > Chris > > > > > > Ok, I check for start with a Bootstrap bar on top your All in One. > > Send to youfor review, enhance, etc when ready. > > > > Edgar > > I think maybe is time to move to newer and cute web frameworks. > Consider look http://190.189.179.48:7070/browse, courtesy of last of our > cousins of Pharo. > > Maybe have more sense build on top of this ? > > ComSwiki was the state of art back in 2006, but not now > > True, but I still have a swiki running at work from back in '98. It was upgraded to squeak 3.7 at some point, but it just keeps on working. New is fun, and often very useful. But solid is really nice - especially when you don't want to worry about it. -cbc -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/9e2b1824/attachment.htm From edgardec2005 at gmail.com Tue Oct 28 15:03:47 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Tue Oct 28 15:03:57 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: Message-ID: On 10/28/14, 11:28 AM, "Chris Cunningham" wrote: >> True, but I still have a swiki running at work from back in '98.? It was >> upgraded to squeak 3.7 at some point, but it just keeps on working. >> New is fun, and often very useful.? But solid is really nice - especially >> when you don't want to worry about it. >> >> -cbc Ok, but you can migrate as me. http://190.189.179.48:8086/ It?s from 2010. .image is my fork of Cuis Visually looks like real swiki, but all is HV2. And if not sell to you, always test what you do. Edgar -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/c258d4a0/attachment.htm From brasspen at gmail.com Tue Oct 28 15:11:41 2014 From: brasspen at gmail.com (Chris Cunnington) Date: Tue Oct 28 15:11:54 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: References: Message-ID: <90770656-612F-4D7E-B320-196785CA971C@gmail.com> > On Oct 28, 2014, at 10:14 AM, Edgar J. De Cleene wrote: > >> On 10/27/14, 5:55 PM, "Chris Cunnington" wrote: >> >> Edgar >> >> Wow. This stuff looks great. I?m glad someone has lots of knowledge of how to >> use the Swiki. I?m not going to pretend I do. There?s quite a lot to it. >> And, yes, your help would be great. I?m impressed you have Bootstrap on a >> Swiki. >> Time to start editing and adding to the Swiki Swiki, I guess. >> >> Chris >> >> >> Ok, I check for start with a Bootstrap bar on top your All in One. >> Send to youfor review, enhance, etc when ready. >> >> Edgar > > I think maybe is time to move to newer and cute web frameworks. > Consider look http://190.189.179.48:7070/browse, courtesy of last of our > cousins of Pharo. > Maybe have more sense build on top of this ? No. > > ComSwiki was the state of art back in 2006, but not now More like 2002. I refer you to ?Squeak- Multimedia and Personal Computing? (And if people want to read about Flow sockets and streams which power Spoon/Context, they can do so on pp. 170-173). > Edgar What are we trying to accomplish here? Why revisit the ComSwiki? Because it is the institutional memory of the Squeak community online. It is over ten years of articles. Over 6000. We want to preserve that. We want to build on that. In some ways, what I?m about to say is similar to the recent discussion about ImageSegments. There are two things to consider here: the data; and, the application. Ultimately we don?t care about ComSwiki or XML files. We do care about the institutional memory of the community. That?s the priority. Let?s look at data. These articles are in XML files. People here sneer at XML. Good for them. But notice that these files have lasted a decade. That?s incredible. Show me any data gathered by Pier or SmallWiki or TinyWiki that has lasted a decade. Nowhere to be found. Before Lukas was Mr. Seaside, he was Mr. Wiki. He didn?t like XML. At all. He stored everything in some binary blob. If I give you a random binary blob from ten years ago, how well is it going to explain itself? If I give you an image segment from a decade ago, you wouldn?t know where to start. XML explains itself. Very clearly. Mark Guzdial made an informed decision to keep documents independent of applications. In the Relax NG book from O?Reilly that arrived yesterday on my doorstep (?Relax NG?, 2004) it says exactly that on pg. 3. That is a powerful principal of the Swiki design. It has served us well. Lukas can come back from Google right now and say it?s not useful. Avi could show up and talk about Image Segments and DabbleDB and I don?t think they could refute how useful this principal is. You could probably say the same thing about Fuel. It?s the reason SQL is popular. We are making the ComSwiki backward compatible. If it ain?t broke don?t fix it. The Swiki is remarkably well designed and remarkably reliable and has a clear separation between application and data. The ComSwiki can be superseded but there in no need to do that anything faster than a snail?s pace because it just works. Chris From marcel.taeumel at student.hpi.uni-potsdam.de Tue Oct 28 16:00:02 2014 From: marcel.taeumel at student.hpi.uni-potsdam.de (Marcel Taeumel) Date: Tue Oct 28 16:03:30 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: Message-ID: <1414512002967-4787221.post@n4.nabble.com> Did you try updating from the trunk image instead of the 4.5 image? http://ftp.squeak.org/trunk/ Best, Marcel -- View this message in context: http://forum.world.st/Updating-4-5-or-getting-a-recent-build-of-4-6-tp4787197p4787221.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From marcel.taeumel at student.hpi.uni-potsdam.de Tue Oct 28 16:01:23 2014 From: marcel.taeumel at student.hpi.uni-potsdam.de (Marcel Taeumel) Date: Tue Oct 28 16:04:48 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: <1414512002967-4787221.post@n4.nabble.com> References: <1414512002967-4787221.post@n4.nabble.com> Message-ID: <1414512083084-4787222.post@n4.nabble.com> Oops, directly jumped to the "TL;DR" part. :D Okay, we need to fix the process of entering the trunk path... Downloading the trunk image and updating it should work fine. Best, Marcel -- View this message in context: http://forum.world.st/Updating-4-5-or-getting-a-recent-build-of-4-6-tp4787197p4787222.html Sent from the Squeak - Dev mailing list archive at Nabble.com. From jeff.gonis at gmail.com Tue Oct 28 16:32:57 2014 From: jeff.gonis at gmail.com (Jeff Gonis) Date: Tue Oct 28 16:33:00 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: <1414512083084-4787222.post@n4.nabble.com> References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: Hi Marcel, I was pretty sure that I had tried that file, but grabbed it from that link just to be sure and tried to update again, and unfortunately no luck. Here is a link to the crash dump file that is generated: https://www.dropbox.com/s/tu8wmro478xmt1t/crash.dmp?dl=0 At least for myself, all I do to reproduce is open the image using the latest Cog, go to the world menu and hit update. Thanks for any and all help, Jeff -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/739dca54/attachment.htm From commits at source.squeak.org Tue Oct 28 17:24:08 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 28 17:24:11 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz Message-ID: Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections.spur-ul.586.mcz ==================== Summary ==================== Name: Collections.spur-ul.586 Author: eem Time: 28 October 2014, 10:22:44.764 am UUID: 2412b3e4-6494-45ce-b462-0a783482d92b Ancestors: Collections-ul.586, Collections.spur-cmm.585 Collections-ul.586 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Symbol table changes: - ensure that enumerations stay consistent - avoid read-write and write-write race conditions - added a safe #condenseNewSymbols method, which is a replacement for former unsafe methods (#shutDown: and #compactSymbolTable). It's also automatically triggered whenever there are more than 1000 NewSymbols. - deprecated #compactSymbolTable - updated some comments Note that interning many symbols is a bit slower, but thread safety is more important. =============== Diff against Collections-ul.586 =============== Item was changed: ==== ERROR === Error: Unrecognized class type 28 October 2014 5:24:06.757 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(Character) Arguments and temporary variables: Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(Character) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #Character superclassName: #Magnitude variables: an OrderedCollection(a MCClassVariableDefinition(CharacterTable) a M...etc... category: #'Collections-Strings' type: #immediate comment: 'I represent a character by storing its associated Unicode as an unsig...etc... commentStamp: 'eem 8/12/2014 14:53' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(Character) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Tue Oct 28 17:25:23 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 28 17:25:27 2014 Subject: [squeak-dev] The Trunk: Kernel.spur-nice.881.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel.spur-nice.881.mcz ==================== Summary ==================== Name: Kernel.spur-nice.881 Author: eem Time: 28 October 2014, 10:22:38.95 am UUID: d96ffb68-fcf0-476b-98b7-34088386d9f6 Ancestors: Kernel-nice.881, Kernel.spur-ul.880 Kernel-nice.881 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Fix Float literal equality: 0.0 and -0.0 are not the same Float... =============== Diff against Kernel-nice.881 =============== Item was changed: ----- Method: Behavior>>allInstances (in category 'accessing instances and variables') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + (inst == insts or: [inst == insts originalContents]) ifFalse: [insts nextPut: inst]. + inst := next]. + ^insts contents! - allInstances - "Answer a collection of all current instances of the receiver." - - | all | - all := OrderedCollection new. - self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. - ^ all asArray - ! Item was changed: ----- Method: Behavior>>allInstancesDo: (in category 'enumerating') ----- + allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst." - allInstancesDo: aBlock - "Evaluate the argument, aBlock, for each of the current instances of the - receiver. - - Because aBlock might change the class of inst (for example, using become:), - it is essential to compute next before aBlock value: inst." - | inst next | inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == nil] - whileFalse: - [ - next := inst nextInstance. - aBlock value: inst. - inst := next]! Item was added: + ----- Method: Behavior>>allInstancesOrNil (in category 'enumerating') ----- + allInstancesOrNil + "Answer all instances of the receiver, or nil if the primitive + fails, which it may be due to being out of memory." + + ^nil! Item was changed: ----- Method: Behavior>>basicNew (in category 'instance creation') ----- basicNew "Primitive. Answer an instance of the receiver (which is a class) with no + indexable variables. Fail if the class is indexable. Essential. See Object + documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run + before the method is activated. Check that space was low and retry + via handleFailingBasicNew if so." - indexable variables. Fail if the class is indexable. Essential. See Object - documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew]. + self isVariable ifTrue: [^self basicNew: 0]. + self primitiveFailed! - - self isVariable ifTrue: [ ^ self basicNew: 0 ]. - "space must be low" - OutOfMemory signal. - ^ self basicNew "retry if user proceeds" - ! Item was changed: ----- Method: Behavior>>basicNew: (in category 'instance creation') ----- + basicNew: sizeRequested + "Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run before the + method is activated. Check args and retry via handleFailingBasicNew: if they're OK." - basicNew: sizeRequested - "Primitive. Answer an instance of this class with the number - of indexable variables specified by the argument, sizeRequested. - Fail if this class is not indexable or if the argument is not a - positive Integer, or if there is not enough memory available. - Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew: sizeRequested]. - self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. - (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: - ["arg okay; space must be low." - OutOfMemory signal. - ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstance (in category 'accessing instances and variables') ----- + byteSizeOfInstance + "Answer the total memory size of an instance of the receiver." + + + self isVariable ifTrue: + [^self byteSizeOfInstanceOfSize: 0]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstanceOfSize: (in category 'accessing instances and variables') ----- + byteSizeOfInstanceOfSize: basicSize + "Answer the total memory size of an instance of the receiver + with the given number of indexable instance variables." + + + self isVariable + ifTrue: "If the primitive overflowed answer a close approximation" + [(basicSize isInteger + and: [basicSize >= 16r1000000]) ifTrue: + [^2 * (self byteSizeOfInstanceOfSize: basicSize + 1 // 2) + - (self byteSizeOfInstanceOfSize: 0)]] + ifFalse: + [basicSize = 0 ifTrue: + [^self byteSizeOfInstance]]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>elementSize (in category 'accessing instances and variables') ----- + elementSize + "Answer the size in bytes of an element in the receiver. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + instSpec < 9 ifTrue: [^Smalltalk wordSize]. + instSpec >= 16 ifTrue: [^1]. + instSpec >= 12 ifTrue: [^2]. + instSpec >= 10 ifTrue: [^4]. + ^8! Item was added: + ----- Method: Behavior>>handleFailingBasicNew (in category 'private') ----- + handleFailingBasicNew + "handleFailingBasicNew gets sent after basicNew has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew. If + handleFailingBasicNew fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + Smalltalk garbageCollect < 1048576 ifTrue: + [Smalltalk growMemoryByAtLeast: 1048576]. + ^self handleFailingFailingBasicNew "retry after global garbage collect"! Item was added: + ----- Method: Behavior>>handleFailingBasicNew: (in category 'private') ----- + handleFailingBasicNew: sizeRequested + "handleFailingBasicNew: gets sent after basicNew: has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew:. If + handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := self byteSizeOfInstanceOfSize: sizeRequested. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingBasicNew: sizeRequested! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew (in category 'private') ----- + handleFailingFailingBasicNew + "This basicNew gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low" + OutOfMemory signal. + ^self basicNew "retry if user proceeds"! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew: (in category 'private') ----- + handleFailingFailingBasicNew: sizeRequested + "This basicNew: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + ^self basicNew: sizeRequested "retry if user proceeds"! Item was added: + ----- Method: Behavior>>identityHash (in category 'comparing') ----- + identityHash + "Answer a SmallInteger whose value is related to the receiver's identity. + Behavior implements identityHash to allow the VM to use an object representation which + does not include a direct reference to an object's class in an object. If the VM is using + this implementation then classes are held in a class table and instances contain the index + of their class in the table. A class's class table index is its identityHash so that an instance + can be created without searching the table for a class's index. The VM uses this primitive + to enter the class into the class table, assigning its identityHash with an as yet unused + class table index. If this primitive fails it means that the class table is full. In Spur as of + 2014 there are 22 bits of classTable index and 22 bits of identityHash per object. + + Primitive. Essential. Do not override. See Object documentation whatIsAPrimitive." + + + self primitiveFailed! Item was changed: ----- Method: Behavior>>indexIfCompact (in category 'private') ----- indexIfCompact + "Backward compatibility with the Squeak V3 object format. + Spur does not have a distinction between compact and non-compact classes." + ^0! - "If these 5 bits are non-zero, then instances of this class - will be compact. It is crucial that there be an entry in - Smalltalk compactClassesArray for any class so optimized. - See the msgs becomeCompact and becomeUncompact." - ^ (format bitShift: -11) bitAnd: 16r1F - " - Smalltalk compactClassesArray doWithIndex: - [:c :i | c == nil ifFalse: - [c indexIfCompact = i ifFalse: [self halt]]] - "! Item was changed: ----- Method: Behavior>>instSize (in category 'testing') ----- instSize "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^format bitAnd: 16rFFFF! - (as opposed to indexed variables) of the receiver." - - self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - When we revise the image format, it should become... - ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 - Note also that every other method in this category will require - 2 bits more of right shift after the change. - " - ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! Item was changed: ----- Method: Behavior>>instSpec (in category 'testing') ----- instSpec + "Answer the instance specification part of the format that defines what kind of object + an instance of the receiver is. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^(format bitShift: -16) bitAnd: 16r1F! - ^ (format bitShift: -7) bitAnd: 16rF! Item was changed: ----- Method: Behavior>>isBits (in category 'testing') ----- isBits + "Answer whether the receiver contains just bits (not pointers). + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 7! - "Answer whether the receiver contains just bits (not pointers)." - - ^ self instSpec >= 6! Item was changed: ----- Method: Behavior>>isBytes (in category 'testing') ----- isBytes + "Answer whether the receiver has 8-bit instance variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 16! - "Answer whether the receiver has 8-bit instance variables." - - ^ self instSpec >= 8! Item was added: + ----- Method: Behavior>>isEphemeronClass (in category 'testing') ----- + isEphemeronClass + "Answer whether the receiver has ephemeral instance variables. The garbage collector will + fire (queue for finalization) any ephemeron whose first instance variable is not referenced + other than from the transitive closure of references from ephemerons. Hence referring to + an object from the first inst var of an ephemeron will cause the ephemeron to fire when + the rest of the system does not refer to the object and that object is ready to be collected. + Since references from the remaining inst vars of an ephemeron will not prevent the ephemeron + from firing, ephemerons may act as the associations in weak dictionaries such that the value + (e.g. properties attached to the key) will not prevent firing when the key is no longer referenced + other than from ephemerons. Ephemerons can therefore be used to implement instance-based + pre-mortem finalization." + ^self instSpec = 5! Item was added: + ----- Method: Behavior>>isImmediateClass (in category 'testing') ----- + isImmediateClass + "Answer whether the receiver has immediate instances. Immediate instances + store their value in their object pointer, not in an object body. Hence immediates + take no space and are immutable. The immediates are distinguished by tag bits + in the pointer. They include SmallIntegers and Characters. Hence in the 32-bit + system SmallIntegers are 31-bit signed integers and Characters are 30-bit + unsigned character codes." + ^self instSpec = 7! Item was changed: ----- Method: Behavior>>isVariable (in category 'testing') ----- isVariable + "Answer whether the receiver has indexable variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + ^instSpec >= 2 and: [instSpec <= 4 or: [instSpec >= 9]]! - "Answer whether the receiver has indexable variables." - - ^ self instSpec >= 2! Item was changed: ----- Method: Behavior>>kindOfSubclass (in category 'testing class hierarchy') ----- kindOfSubclass + "Answer a String that is the keyword that describes the receiver's kind of subclass, + either a regular subclass, a variableSubclass, a variableByteSubclass, + a variableWordSubclass, a weakSubclass, an ephemeronSubclass or an immediateSubclass. + c.f. typeOfClass" + ^self isVariable + ifTrue: + [self isBits + ifTrue: + [self isBytes + ifTrue: [' variableByteSubclass: '] + ifFalse: [' variableWordSubclass: ']] + ifFalse: + [self isWeak + ifTrue: [' weakSubclass: '] + ifFalse: [' variableSubclass: ']]] + ifFalse: + [self isImmediateClass + ifTrue: [' immediateSubclass: '] + ifFalse: + [self isEphemeronClass + ifTrue: [' ephemeronSubclass: '] + ifFalse: [' subclass: ']]]! - "Answer a String that is the keyword that describes the receiver's kind - of subclass, either a regular subclass, a variableSubclass, a - variableByteSubclass, a variableWordSubclass, or a weakSubclass." - self isWeak - ifTrue: [^ ' weakSubclass: ']. - ^ self isVariable - ifTrue: [self isBits - ifTrue: [self isBytes - ifTrue: [ ' variableByteSubclass: '] - ifFalse: [ ' variableWordSubclass: ']] - ifFalse: [ ' variableSubclass: ']] - ifFalse: [ ' subclass: ']! Item was changed: ----- Method: Behavior>>shouldNotBeRedefined (in category 'testing') ----- shouldNotBeRedefined + "Answer if the receiver should not be redefined. + The assumption is that classes in Smalltalk specialObjects and + instance-specific Behaviors should not be redefined" - "Return true if the receiver should not be redefined. - The assumption is that compact classes, - classes in Smalltalk specialObjects and - Behaviors should not be redefined" + ^(Smalltalk specialObjectsArray + identityIndexOf: self + ifAbsent: [(self isKindOf: self) ifTrue: [1] ifFalse: [0]]) ~= 0! - ^(Smalltalk compactClassesArray includes: self) - or:[(Smalltalk specialObjectsArray includes: self) - or:[self isKindOf: self]]! Item was changed: ----- Method: Behavior>>typeOfClass (in category 'accessing') ----- typeOfClass + "Answer a symbol uniquely describing the type of the receiver. c.f. kindOfSubclass" + self isBytes ifTrue: + [^self instSpec = CompiledMethod instSpec + ifTrue: [#compiledMethod] "Very special!!" + ifFalse: [#bytes]]. + (self isWords and: [self isPointers not]) ifTrue: + [^self instSpec = SmallInteger instSpec + ifTrue: [#immediate] "Very special!!" + ifFalse: [#words]]. + self isWeak ifTrue: [^#weak]. + self isVariable ifTrue: [^#variable]. + self isEphemeronClass ifTrue: [^#ephemeron]. + ^#normal! - "Answer a symbol uniquely describing the type of the receiver" - self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" - self isBytes ifTrue:[^#bytes]. - (self isWords and:[self isPointers not]) ifTrue:[^#words]. - self isWeak ifTrue:[^#weak]. - self isVariable ifTrue:[^#variable]. - ^#normal.! Item was changed: ----- Method: BlockClosure>>simulateValueWithArguments:caller: (in category 'system simulation') ----- simulateValueWithArguments: anArray caller: aContext + "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity." | newContext sz | - (anArray class ~~ Array - or: [numArgs ~= anArray size]) ifTrue: - [^ContextPart primitiveFailTokenFor: nil]. newContext := (MethodContext newForMethod: outerContext method) setSender: aContext receiver: outerContext receiver method: outerContext method closure: self startpc: startpc. + ((newContext objectClass: anArray) ~~ Array + or: [numArgs ~= anArray size]) ifTrue: + [^ContextPart primitiveFailTokenFor: nil]. sz := self basicSize. newContext stackp: sz + numArgs. 1 to: numArgs do: [:i| newContext at: i put: (anArray at: i)]. 1 to: sz do: [:i| newContext at: i + numArgs put: (self at: i)]. ^newContext! Item was added: + ----- Method: Class>>immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'subclass creation') ----- + immediateSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a new + immediate class as a subclass of an existing class (the receiver)." + ^ClassBuilder new + superclass: self + immediateSubclass: t + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>computeFormat:instSize:forSuper:ccIndex: (in category 'class format') ----- computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. + Answer the format or nil if there is any problem." - Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | type == #compiledMethod ifTrue: + [newInstSize > 0 ifTrue: + [self error: 'A compiled method class cannot have named instance variables'. + ^nil]. + ^CompiledMethod format]. - [^(CompiledMethod format - bitClear: (16r1F bitShift: 11)) - bitOr: (ccIndex bitShift: 11)]. instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). + instSize > 65535 ifTrue: - instSize > 254 ifTrue: [self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true]. type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false]. type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false]. type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false]. type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true]. + type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true]. + type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true]. + (isPointers not and: [instSize > 0]) ifTrue: + [self error: 'A non-pointer class cannot have named instance variables'. - (isPointers not and:[instSize > 0]) ifTrue: - [self error:'A non-pointer class cannot have instance variables'. ^nil]. + ^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak! - ^(self format: instSize - variable: isVar - words: isWords - pointers: isPointers - weak: isWeak) + (ccIndex bitShift: 11).! Item was changed: ----- Method: ClassBuilder>>format:variable:words:pointers:weak: (in category 'class format') ----- + format: nInstVars variable: isVar words: is32BitWords pointers: isPointers weak: isWeak + "Compute the format for the given instance specfication. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = reserved for 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | - format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak - "Compute the format for the given instance specfication." - | cClass instSpec sizeHiBits fmt | - self flag: #instSizeChange. - " - Smalltalk browseAllCallsOn: #instSizeChange. - Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. - Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. - " - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - For now the format word is... - <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> - But when we revise the image format, it should become... - <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> - " - sizeHiBits := (nInstVars+1) // 64. - cClass := 0. "for now" instSpec := isWeak + ifTrue: + [isVar + ifTrue: [4] + ifFalse: [5]] + ifFalse: + [isPointers + ifTrue: + [isVar + ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]] + ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]] + ifFalse: + [isVar + ifTrue: [is32BitWords ifTrue: [10] ifFalse: [16]] + ifFalse: [7]]]. + ^(instSpec bitShift: 16) + nInstVars! - ifTrue:[4] - ifFalse:[isPointers - ifTrue: [isVar - ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] - ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] - ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. - fmt := sizeHiBits. - fmt := (fmt bitShift: 5) + cClass. - fmt := (fmt bitShift: 4) + instSpec. - fmt := (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" - fmt := (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" - ^fmt! Item was added: + ----- Method: ClassBuilder>>superclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'public') ----- + superclass: aClass + immediateSubclass: t instanceVariableNames: f + classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a + new immediate class as a subclass of an existing class." + | env | + aClass instSize > 0 + ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields']. + aClass isVariable + ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables']. + aClass isPointers + ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields']. + "Cope with pre-environment and environment versions. Simplify asap." + env := (Smalltalk classNamed: #EnvironmentRequest) + ifNil: [aClass environment] + ifNotNil: [:erc| erc signal ifNil: [aClass environment]]. + ^self + name: t + inEnvironment: env + subclassOf: aClass + type: #immediate + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" - "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. - We can rely on two assumptions (which are critical): - #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) - #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. - Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. - " | meta | meta := oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." - [ - "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). - Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "make sure that the VM cache is clean" oldClass methodDict do: [:cm | cm flushCache]. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue: [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. oldClass updateMethodBindingsTo: oldClass binding. oldClass class updateMethodBindingsTo: oldClass class binding]. + "eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was + to ensure no old instances existed after the becomeForward:. Without the GC it was possible + to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward: + updated references from the old objects to new objects but didn't destroy the old objects. + But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."] + valueUnpreemptively! - Smalltalk garbageCollect. - - "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). - - The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: - - On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. - - Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). - - Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. - - Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." - - ] valueUnpreemptively. - ! Item was changed: ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame' poolDictionaries: '' category: 'Kernel-Methods'! + !CompiledMethod commentStamp: 'eem 8/12/2014 14:45' prior: 0! + CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. - !CompiledMethod commentStamp: 'eem 5/12/2014 18:02' prior: 0! - My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. I'm a subclass of ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. Class variables: SmallFrame - the number of stack slots in a small frame Context LargeFrame - the number of stack slots in a large frame Context PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set The current format of a CompiledMethod is as follows: header (4 or 8 bytes, SmallInteger) + literals (4 or 8 bytes each, Object, see "The last literal..." below) - literals (4 or 8 bytes each, Object) bytecodes (variable, bytes) trailer (variable, bytes) + The header is a 31-bit signed integer (a SmallInteger) in the following format: - The header is a 31-bit signed integer (a SmallInteger) with one of the two following formats, selected by the sign bit: - sign bit 0, header >= 0: - (index 0) 9 bits: main part of primitive number (#primitive) - (index 9) 8 bits: number of literals (#numLiterals) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) - (index 18) 6 bits: number of temporary variables (#numTemps) - (index 24) 4 bits: number of arguments to the method (#numArgs) - (index 28) 1 bit: high-bit of primitive number (#primitive) - (index 29) 1 bit: flag bit, ignored by the VM (#flag) - (index 30/63) sign bit: 0 selects the Primary instruction set (#signFlag) - sign bit 1, header < 0: (index 0) 16 bits: number of literals (#numLiterals) (index 16) 1 bit: has primitive + (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) + (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag). + (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4, 0 selects the primary instruction set, e.g. SqueakV3PlusClosures) (#signFlag) - (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public) - (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4) (#signFlag) - i.e. the Secondary Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode. + If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. + + The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer. + + The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be left nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.! - The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.! Item was added: + ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') ----- + handleFailingFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails then the + system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + "retry if user proceeds" + ^self newMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') ----- + handleFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after newMethod:header: has failed + and allowed a scavenging garbage collection to occur. The scavenging + collection will have happened as the VM is activating the (failing) basicNew:. + If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') ----- + installPrimaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was added: + ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') ----- + installSecondaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: ["For now the high bit of primitive no. is in the 29th bit of header" - primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits flagBit | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - "For now the high bit of the primitive no. is in a high bit of the header" - primBits := (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19). - - flagBit := flag ifTrue: [ 1 ] ifFalse: [ 0 ]. - - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits + - (flagBit bitShift: 29)! Item was changed: ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') ----- + newMethod: numberOfBytes header: headerWord - newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other + information) is specified by the headerWord (see my class comment). + The first argument specifies the number of fields for bytecodes in the + method. Fail if either argument is not a SmallInteger, or if numberOfBytes + is negative, or if memory is low. Once the header of a method is set by + this primitive, it cannot be changed to change the number of literals. + Essential. See Object documentation whatIsAPrimitive." - information) is specified the headerWord. The first argument specifies - the number of fields for bytecodes in the method. Fail if either - argument is not a SmallInteger, or if numberOfBytes is negative. Once - the header of a method is set by this primitive, it cannot be changed in - any way. Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingNewMethod: numberOfBytes header: headerWord]. - - (numberOfBytes isInteger and: - [headerWord isInteger and: - [numberOfBytes >= 0]]) ifTrue: [ - "args okay; space must be low" - OutOfMemory signal. - "retry if user proceeds" - ^ self newMethod: numberOfBytes header: headerWord - ]. ^self primitiveFailed! Item was changed: ----- Method: CompiledMethod class>>toReturnConstant:trailerBytes: (in category 'instance creation') ----- toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index - ! Item was changed: ----- Method: CompiledMethod class>>toReturnField:trailerBytes: (in category 'instance creation') ----- toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field - ! Item was changed: ----- Method: CompiledMethod class>>toReturnSelfTrailerBytes: (in category 'instance creation') ----- toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 - ! Item was added: + ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') ----- + bytecodeSetName + ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''! Item was changed: ----- Method: CompiledMethod>>headerDescription (in category 'literals') ----- headerDescription + "Answer a description containing the information about the form of the + receiver and the form of the context needed to run the receiver." - "Answer a description containing the information about the form of the - receiver and the form of the context needed to run the receiver." + ^(ByteString new: 128) writeStream + print: self header; cr; + nextPutAll: '"primitive: '; print: self primitive; cr; + nextPutAll: ' numArgs: '; print: self numArgs; cr; + nextPutAll: ' numTemps: '; print: self numTemps; cr; + nextPutAll: ' numLiterals: '; print: self numLiterals; cr; + nextPutAll: ' frameSize: '; print: self frameSize; cr; + nextPutAll: ' bytecodeSet: '; nextPutAll: self bytecodeSetName; + nextPut: $"; cr; + contents! - | s | - s := '' writeStream. - self header printOn: s. - s cr; nextPutAll: '"primitive: '. - self primitive printOn: s. - s cr; nextPutAll: ' numArgs: '. - self numArgs printOn: s. - s cr; nextPutAll: ' numTemps: '. - self numTemps printOn: s. - s cr; nextPutAll: ' numLiterals: '. - self numLiterals printOn: s. - s cr; nextPutAll: ' frameSize: '. - self frameSize printOn: s. - s cr; nextPutAll: ' isClosureCompiled: '. - self isBlueBookCompiled not printOn: s. - s nextPut: $"; cr. - ^ s contents! Item was changed: ----- Method: CompiledMethod>>numLiterals (in category 'accessing') ----- numLiterals "Answer the number of literals used by the receiver." + ^self header bitAnd: 65535! - | header | - ^(header := self header) < 0 - ifTrue: [header bitAnd: 65535] - ifFalse: [(header bitShift: -9) bitAnd: 16rFF]! Item was changed: ----- Method: CompiledMethod>>primitive (in category 'accessing') ----- primitive "Answer the primitive index associated with the receiver. + Zero indicates that this is not a primitive method." + | initialPC | + ^(self header anyMask: 65536) "Is the hasPrimitive? flag set?" + ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] + ifFalse: [0]! - Zero indicates that this is not a primitive method. - In the original header format we currently allow 10 bits of primitive index, but they are - in two places for backward compatibility. In the new format the primitive index is in the - last two bytes of a three byte callPrimitive: bytecode. The time to unpack is negligible, - since the derived primitive function pointer full index is stored in the method cache." - | header initialPC | - ^(header := self header) < 0 - ifTrue: - [(header anyMask: 65536) "Is the hasPrimitive? flag set?" - ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] - ifFalse: [0]] - ifFalse: - [(header bitAnd: 16r1FF) + ((header bitShift: -19) bitAnd: 16r200)]! Item was changed: ----- Method: ContextPart>>activateReturn:value: (in category 'private') ----- activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" + ^MethodContext + sender: self - ^ self - activateMethod: ContextPart theReturnMethod - withArgs: {value} receiver: aContext + method: MethodContext theReturnMethod + arguments: {value}! - class: aContext class! Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments + "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and + arguments are given as arguments to this message. If successful, push result and return + resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes + execution needs to be intercepted and simulated to avoid execution running away." - "Simulate a primitive method whose index is primitiveIndex. The - simulated receiver and arguments are given as arguments to this message. - If successful, push result and return resuming context, else ^ PrimitiveFailToken. - Any primitive which provokes execution needs to be intercepted and simulated - to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug + interesting code, such as the debugger itself. hence use primitive 19 with care :-)" - interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. + ((primitiveIndex between: 201 and: 222) + and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: + [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" + or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" + [^receiver simulateValueWithArguments: arguments caller: self]. + primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" + [^receiver simulateValueWithArguments: arguments first caller: self]]. - "ContextPart>>blockCopy:; simulated to get startpc right" - (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) - ifTrue: [^self push: ((BlockContext newForMethod: receiver method) - home: receiver home - startpc: pc + 2 - nargs: (arguments at: 1))]. - (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" - ifTrue: [^receiver pushArgs: arguments from: self]. - (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" - ifTrue: [^receiver pushArgs: arguments first from: self]. - primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" - ifTrue: [^self send: arguments first - to: receiver - with: arguments allButFirst - super: false]. - primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: nil]. - primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: (arguments at: 3)]. + primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [^self send: arguments first to: receiver with: arguments allButFirst super: false]. + primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. + primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. + "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. + ^(self isPrimFailToken: value) - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" - and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: (arguments at: 2) + arguments: (arguments at: 1)]. - method: arguments last - arguments: (primitiveIndex = 188 - ifTrue: [arguments at: 1] - ifFalse: [arguments allButLast])]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. - ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" - or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" - [^receiver simulateValueWithArguments: arguments caller: self]. - primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" - [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] + ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. + + ^(self isPrimFailToken: value) - ifFalse: - [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! Item was added: + ----- Method: ContextPart>>isPrimFailToken: (in category 'private') ----- + isPrimFailToken: anObject + ^(self objectClass: anObject) == Array + and: [anObject size = 2 + and: [anObject first == PrimitiveFailToken]]! Item was added: + ----- Method: ContextPart>>send:to:with:lookupIn: (in category 'controlling') ----- + send: selector to: rcvr with: arguments lookupIn: lookupClass + "Simulate the action of sending a message with selector and arguments + to rcvr. The argument, lookupClass, is the class in which to lookup the + message. This is the receiver's class for normal messages, but for super + messages it will be some specific class related to the source method." + + | meth primIndex val ctxt | + (meth := lookupClass lookupSelector: selector) ifNil: + [^self send: #doesNotUnderstand: + to: rcvr + with: {Message selector: selector arguments: arguments} + lookupIn: lookupClass]. + (primIndex := meth primitive) > 0 ifTrue: + [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments. + (self isPrimFailToken: val) ifFalse: + [^val]]. + (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue: + [^self error: 'Simulated message ', arguments first selector, ' not understood']. + ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments. + primIndex > 0 ifTrue: + [ctxt failPrimitiveWith: val]. + ^ctxt! Item was changed: ----- Method: ContextPart>>send:to:with:super: (in category 'controlling') ----- + send: selector to: rcvr with: arguments super: superFlag + "Simulate the action of sending a message with selector arguments + to rcvr. The argument, superFlag, tells whether the receiver of the + message was specified with 'super' in the source method." - send: selector to: rcvr with: args super: superFlag - "Simulate the action of sending a message with selector, selector, and - arguments, args, to receiver. The argument, superFlag, tells whether the - receiver of the message was specified with 'super' in the source method." + ^self send: selector + to: rcvr + with: arguments + lookupIn: (superFlag + ifTrue: [self method methodClassAssociation value superclass] + ifFalse: [self objectClass: rcvr])! - | class meth val ctxt | - class := superFlag - ifTrue: [self method methodClassAssociation value superclass] - ifFalse: [self objectClass: rcvr]. - meth := class lookupSelector: selector. - meth == nil ifTrue: - [^self - send: #doesNotUnderstand: - to: rcvr - with: (Array with: (Message selector: selector arguments: args)) - super: superFlag]. - val := self tryPrimitiveFor: meth receiver: rcvr args: args. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken]]) ifFalse: - [^val]. - (selector == #doesNotUnderstand: - and: [class == ProtoObject]) ifTrue: - [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood']. - ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken - and: [val last notNil - and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue: - [ctxt at: ctxt stackPtr put: val last]. - ^ctxt! Item was changed: ----- Method: ContextPart>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') ----- tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments + "Invoke the named primitive for aCompiledMethod, answering its result, or, + if the primiitve fails, answering the error code." - | selector theMethod spec receiverClass | ec ifNotNil: ["If ec is an integer other than -1 there was a problem with primitive 218, not with the external primitive itself. -1 indicates a generic failure (where ec should be nil) but ec = nil means primitive 218 is not implemented. So interpret -1 to mean the external primitive failed with a nil error code." ec isInteger ifTrue: [ec = -1 ifTrue: [ec := nil] + ifFalse: [self primitiveFailed]]]. + ^self class primitiveFailTokenFor: ec! - ifFalse: [self primitiveFailed]]. - ^{PrimitiveFailToken. ec}]. - "Assume a nil error code implies the primitive is not implemented and fall back on the old code." - "Hack. Attempt to execute the named primitive from the given compiled method" - arguments size > 8 ifTrue: - [^{PrimitiveFailToken. nil}]. - selector := #( - tryNamedPrimitive - tryNamedPrimitive: - tryNamedPrimitive:with: - tryNamedPrimitive:with:with: - tryNamedPrimitive:with:with:with: - tryNamedPrimitive:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. - receiverClass := self objectClass: aReceiver. - theMethod := receiverClass lookupSelector: selector. - theMethod == nil ifTrue: - [^{PrimitiveFailToken. nil}]. - spec := theMethod literalAt: 1. - spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. - Smalltalk unbindExternalPrimitives. - ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass! Item was added: + ----- Method: InstructionClient>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: pimIndex + "V3PlusClosures: 139 10001011 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + NewsqueakV4: 249 11111001 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + ( jjjjjjj * 256) + m=1 means inlined primitive, no hard return after execution."! Item was added: + ----- Method: InstructionPrinter>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: index + "Print the callPrimitive." + + self print: 'callPrimtive: ' , index printString! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self unusedBytecode: client at: pc - 1]. byte3 := method at: pc. pc := pc + 1. + offset = 11 ifTrue: [^client callPrimitive: byte2 + (byte3 bitShift: 8)]. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: Integer class>>initialize (in category 'class initialization') ----- + initialize + "Integer initialize" + self initializeLowBitPerByteTable! - initialize "Integer initialize" - "Ensure we have the right compact class index" - - "LPI has been a compact class forever - just ensure basic correctness" - (LargePositiveInteger indexIfCompact = 5) ifFalse:[ - (Smalltalk compactClassesArray at: 5) - ifNil:[LargePositiveInteger becomeCompactSimplyAt: 5] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - "Cog requires LNI to be compact at 4 (replacing PseudoContext)" - (LargeNegativeInteger indexIfCompact = 4) ifFalse:[ - "PseudoContext will likely get removed at some point so write this test - without introducing a hard dependency" - (Smalltalk compactClassesArray at: 4) name == #PseudoContext - ifTrue:[Smalltalk compactClassesArray at: 4 put: nil]. - (Smalltalk compactClassesArray at: 4) - ifNil:[LargeNegativeInteger becomeCompactSimplyAt: 4] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - self initializeLowBitPerByteTable - ! Item was added: + ----- Method: MethodContext class>>allInstances (in category 'enumerating') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst. + Only count until thisContext since this context has been created only to + compute the existing instances." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + insts nextPut: inst. + inst := next]. + ^insts contents! Item was changed: ----- Method: MethodContext class>>allInstancesDo: (in category 'private') ----- allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst. + Only count until thisContext since evaluation of aBlock will create new contexts." - "Only count until thisContext since evaluation of aBlock will create new contexts." - | inst next | inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == thisContext] whileFalse:[ - next := inst nextInstance. - aBlock value: inst. - inst := next] - ! Item was added: + ----- Method: MethodContext>>failPrimitiveWith: (in category 'system simulation') ----- + failPrimitiveWith: maybePrimFailToken + "The receiver is a freshly-created context on a primitive method. Skip the callPrimitive: + bytecode and store the primitive fail code if there is one and the method consumes it." + self skipCallPrimitive. + ((self isPrimFailToken: maybePrimFailToken) + and: [method encoderClass isStoreAt: pc in: method]) ifTrue: + [self at: stackp put: maybePrimFailToken last]! Item was changed: ----- Method: ProtoObject>>scaledIdentityHash (in category 'comparing') ----- scaledIdentityHash "For identityHash values returned by primitive 75, answer + such values times 2^8. Otherwise, match the existing + identityHash implementation" - such values times 2^18. Otherwise, match the existing - identityHash implementation" + ^self identityHash * 256 "bitShift: 8"! - ^self identityHash * 262144 "bitShift: 18"! Item was changed: ==== ERROR === Error: Unrecognized class type 28 October 2014 5:25:22.335 pm VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(SmallInteger) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From commits at source.squeak.org Tue Oct 28 17:25:24 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 28 17:25:31 2014 Subject: [squeak-dev] The Trunk: System.spur-ul.688.mcz Message-ID: Eliot Miranda uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System.spur-ul.688.mcz ==================== Summary ==================== Name: System.spur-ul.688 Author: eem Time: 28 October 2014, 10:22:53.8 am UUID: c6eab688-9271-4843-8d27-b050cd98ef4d Ancestors: System-ul.688, System.spur-dtl.685 System-ul.688 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Replaced ExternalSemaphoreTable with ExternalObjectTable to provide faster registration, and give better support to the current users of external objects. Notable changes: - the table is a separate object instead of a few class side methods - the whole API can be found in SmalltalkImage in the external objects category - #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores: provide fast and easy creation and registration of Semaphores - #unregisterExternalObjects: can unregister multiple objects faster - #externalObjects will return a copy of the externalObjectsArray - better scalability - the maxExternalSemaphores VM parameter will be incremented as the externalObjectsArray grows =============== Diff against System-ul.688 =============== Item was changed: ----- Method: SmalltalkImage>>compactClassesArray (in category 'special objects') ----- compactClassesArray "Smalltalk compactClassesArray" + "Backward-compatibility support. Spur does not have compact classes." + ^{}! - "Return the array of 31 classes whose instances may be - represented compactly" - ^ self specialObjectsArray at: 29! Item was added: + ----- Method: SmalltalkImage>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Essential. Fail if no memory is available." + + (numBytes isInteger and: [numBytes > 0]) ifTrue: + [OutOfMemory signal]. + ^self primitiveFailed! Item was added: + ----- Method: SmalltalkImage>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was changed: ----- Method: SmalltalkImage>>recreateSpecialObjectsArray (in category 'special objects') ----- recreateSpecialObjectsArray "Smalltalk recreateSpecialObjectsArray" "To external package developers: **** DO NOT OVERRIDE THIS METHOD. ***** If you are writing a plugin and need additional special object(s) for your own use, use addGCRoot() function and use own, separate special objects registry " "The Special Objects Array is an array of objects used by the Squeak virtual machine. Its contents are critical and accesses to it by the VM are unchecked, so don't even think of playing here unless you know what you are doing." | newArray | + newArray := Array new: 60. - newArray := Array new: 58. "Nil false and true get used throughout the interpreter" newArray at: 1 put: nil. newArray at: 2 put: false. newArray at: 3 put: true. "This association holds the active process (a ProcessScheduler)" newArray at: 4 put: (self specialObjectsArray at: 4) "(self bindingOf: #Processor) but it answers an Alias". "Numerous classes below used for type checking and instantiation" newArray at: 5 put: Bitmap. newArray at: 6 put: SmallInteger. newArray at: 7 put: ByteString. newArray at: 8 put: Array. newArray at: 9 put: Smalltalk. newArray at: 10 put: Float. + newArray at: 11 put: (self globals at: #MethodContext ifAbsent: [self globals at: #Context]). + newArray at: 12 put: nil. "was BlockContext." - newArray at: 11 put: MethodContext. - newArray at: 12 put: BlockContext. newArray at: 13 put: Point. newArray at: 14 put: LargePositiveInteger. newArray at: 15 put: Display. newArray at: 16 put: Message. newArray at: 17 put: CompiledMethod. + newArray at: 18 put: ((self specialObjectsArray at: 18) ifNil: [Semaphore new]). "low space Semaphore" - newArray at: 18 put: (self specialObjectsArray at: 18). - "(low space Semaphore)" newArray at: 19 put: Semaphore. newArray at: 20 put: Character. newArray at: 21 put: #doesNotUnderstand:. newArray at: 22 put: #cannotReturn:. newArray at: 23 put: nil. "This is the process signalling low space." "An array of the 32 selectors that are compiled as special bytecodes, paired alternately with the number of arguments each takes." newArray at: 24 put: #( #+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0 ). "An array of the 255 Characters in ascii order. + Cog inlines table into machine code at: prim so do not regenerate it. + This is nil in Spur, which has immediate Characters." - Cog inlines table into machine code at: prim so do not regenerate it." newArray at: 25 put: (self specialObjectsArray at: 25). newArray at: 26 put: #mustBeBoolean. newArray at: 27 put: ByteArray. newArray at: 28 put: Process. + "An array of up to 31 classes whose instances will have compact headers; an empty array in Spur" - "An array of up to 31 classes whose instances will have compact headers" newArray at: 29 put: self compactClassesArray. + newArray at: 30 put: ((self specialObjectsArray at: 30) ifNil: [Semaphore new]). "delay Semaphore" + newArray at: 31 put: ((self specialObjectsArray at: 31) ifNil: [Semaphore new]). "user interrupt Semaphore" - newArray at: 30 put: (self specialObjectsArray at: 30). "(delay Semaphore)" - newArray at: 31 put: (self specialObjectsArray at: 31). "(user interrupt Semaphore)" "Entries 32 - 34 unreferenced. Previously these contained prototype instances to be copied for fast initialization" + newArray at: 32 put: nil. "was the prototype Float" + newArray at: 33 put: nil. "was the prototype 4-byte LargePositiveInteger" + newArray at: 34 put: nil. "was the prototype Point" - newArray at: 32 put: nil. "was (Float new: 2)" - newArray at: 33 put: nil. "was (LargePositiveInteger new: 4)" - newArray at: 34 put: nil. "was Point new" newArray at: 35 put: #cannotInterpret:. + newArray at: 36 put: nil. "was the prototype MethodContext" - "Note: This must be fixed once we start using context prototypes (yeah, right)" - "(MethodContext new: CompiledMethod fullFrameSize)." - newArray at: 36 put: (self specialObjectsArray at: 36). "Is the prototype MethodContext (unused by the VM)" newArray at: 37 put: BlockClosure. + newArray at: 38 put: nil. "was the prototype BlockContext" - "(BlockContext new: CompiledMethod fullFrameSize)." - newArray at: 38 put: (self specialObjectsArray at: 38). "Is the prototype BlockContext (unused by the VM)" "array of objects referred to by external code" + newArray at: 39 put: (self specialObjectsArray at: 39). "external semaphores" - newArray at: 39 put: (self specialObjectsArray at: 39). "preserve external semaphores" newArray at: 40 put: nil. "Reserved for Mutex in Cog VMs" + newArray at: 41 put: ((self specialObjectsArray at: 41) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT" + newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). "finalization Semaphore" - newArray at: 41 put: nil. "Reserved for a LinkedList instance for overlapped calls in CogMT" - "finalization Semaphore" - newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). newArray at: 43 put: LargeNegativeInteger. "External objects for callout. Note: Written so that one can actually completely remove the FFI." newArray at: 44 put: (self at: #ExternalAddress ifAbsent: []). newArray at: 45 put: (self at: #ExternalStructure ifAbsent: []). newArray at: 46 put: (self at: #ExternalData ifAbsent: []). newArray at: 47 put: (self at: #ExternalFunction ifAbsent: []). newArray at: 48 put: (self at: #ExternalLibrary ifAbsent: []). newArray at: 49 put: #aboutToReturn:through:. newArray at: 50 put: #run:with:in:. "51 reserved for immutability message" + newArray at: 51 put: #attemptToAssign:withIndex:. - "newArray at: 51 put: #attemptToAssign:withIndex:." - newArray at: 51 put: (self specialObjectsArray at: 51 ifAbsent: []). newArray at: 52 put: #(nil "nil => generic error" #'bad receiver' #'bad argument' #'bad index' #'bad number of arguments' #'inappropriate operation' #'unsupported operation' #'no modification' #'insufficient object memory' #'insufficient C memory' #'not found' #'bad method' #'internal error in named primitive machinery' #'object may move' #'resource limit exceeded' + #'object is pinned' #'primitive write beyond end of object'). - #'object is pinned'). "53 to 55 are for Alien" newArray at: 53 put: (self at: #Alien ifAbsent: []). + newArray at: 54 put: #invokeCallbackContext:. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." - newArray at: 54 put: #invokeCallbackContext::. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks." newArray at: 55 put: (self at: #UnsafeAlien ifAbsent: []). + "Used to be WeakFinalizationList for WeakFinalizationList hasNewFinalization, obsoleted by ephemeron support." + newArray at: 56 put: nil. - "Weak reference finalization" - newArray at: 56 put: (self at: #WeakFinalizationList ifAbsent: []). "reserved for foreign callback process" newArray at: 57 put: (self specialObjectsArray at: 57 ifAbsent: []). newArray at: 58 put: #unusedBytecode. + "59 reserved for Sista counter tripped message" + newArray at: 59 put: #conditionalBranchCounterTrippedOn:. + "60 reserved for Sista class trap message" + newArray at: 60 put: #classTrapFor:. "Now replace the interpreter's reference in one atomic operation" + self specialObjectsArray becomeForward: newArray! - self specialObjectsArray becomeForward: newArray - ! Item was changed: ----- Method: SmalltalkImage>>setGCParameters (in category 'snapshot and quit') ----- setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" - "Adjust the VM's default GC parameters to avoid premature tenuring." + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! - self vmParameterAt: 5 put: 4000. "do an incremental GC after this many allocations" - self vmParameterAt: 6 put: 2000. "tenure when more than this many objects survive the GC" - ! Item was changed: ----- Method: SpaceTally>>spaceForInstancesOf: (in category 'instance size') ----- spaceForInstancesOf: aClass + "Answer a pair of the number of bytes consumed by all instances of the + given class, including their object headers, and the number of instances." - "Answer the number of bytes consumed by all instances of the given class, including their object headers and the number of instances." + | instances total | + instances := aClass allInstances. + instances isEmpty ifTrue: [^#(0 0)]. - | smallHeaderSize instVarBytes isVariable bytesPerElement total lastInstance instance instanceCount | - instance := aClass someInstance ifNil: [ ^#(0 0) ]. - smallHeaderSize := aClass isCompact ifTrue: [ 4 ] ifFalse: [ 8 ]. - instVarBytes := aClass instSize * 4. - isVariable := aClass isVariable. - bytesPerElement := isVariable - ifFalse: [ 0 ] - ifTrue: [ aClass isBytes ifTrue: [ 1 ] ifFalse: [ 4 ] ]. total := 0. + aClass isVariable + ifTrue: + [instances do: + [:i| total := total + (aClass byteSizeOfInstanceOfSize: i basicSize)]] + ifFalse: + [total := instances size * aClass byteSizeOfInstance]. + ^{ total. instances size }! - instanceCount := 0. - "A modified version of #allInstancesDo: is inlined here. It avoids an infinite loop when another process is creating new instances of aClass." - self flag: #allInstancesDo:. - lastInstance := - aClass == CompiledMethod "CompiledMethod has special format, see its class comment" - ifTrue: [aClass new] - ifFalse: [aClass basicNew]. - [ instance == lastInstance ] whileFalse: [ - | contentBytes headerBytes | - contentBytes := instVarBytes + (isVariable - ifFalse: [ 0 ] - ifTrue: [ instance basicSize * bytesPerElement ]). - headerBytes := contentBytes > 255 - ifTrue: [ 12 ] - ifFalse: [ smallHeaderSize ]. - total := total + headerBytes + (contentBytes roundUpTo: 4). - instanceCount := instanceCount + 1. - instance := instance nextInstance ]. - ^{ total. instanceCount }! Item was added: + ----- Method: SystemDictionary>>growMemoryByAtLeast: (in category 'memory space') ----- + growMemoryByAtLeast: numBytes + "Grow memory by at least the requested number of bytes. + Primitive. Fail if no memory is available. Essential." + + ^(numBytes isInteger and: [numBytes > 0]) + ifTrue: [OutOfMemory signal] + ifFalse: [self primitiveFailed]! Item was added: + ----- Method: SystemDictionary>>maxIdentityHash (in category 'system attributes') ----- + maxIdentityHash + "Answer the maximum identityHash value supported by the VM." + + ^self primitiveFailed! Item was added: + ----- Method: SystemDictionary>>setGCParameters (in category 'snapshot and quit') ----- + setGCParameters + "Adjust the VM's default GC parameters to avoid too much tenuring. + Maybe this should be left to the VM?" + + | proportion edenSize survivorSize averageObjectSize numObjects | + proportion := 0.9. "tenure when 90% of pastSpace is full" + edenSize := SmalltalkImage current vmParameterAt: 44. + survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)" + averageObjectSize := 8 * self wordSize. "a good approximation" + numObjects := (proportion * survivorSize / averageObjectSize) rounded. + SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"! Item was added: + ----- Method: SystemNavigation>>allObjects (in category 'query') ----- + allObjects + "Answer an Array of all objects in the system. Fail if + there isn't enough memory to instantiate the result." + + ^self primitiveFailed! Item was changed: ----- Method: SystemNavigation>>allObjectsDo: (in category 'query') ----- allObjectsDo: aBlock + "Evaluate the argument, aBlock, for each object in the system, excluding immediates + such as SmallInteger and Character." + self allObjectsOrNil + ifNotNil: [:allObjects| allObjects do: aBlock] + ifNil: + ["Fall back on the old single object primitive code. With closures, this needs + to use an end marker (lastObject) since activation of the block will create + new contexts and cause an infinite loop. The lastObject must be created + before calling someObject, so that the VM can settle the enumeration (e.g. + by flushing new space) as a side effect of someObject" + | object lastObject | + lastObject := Object new. + object := self someObject. + [lastObject == object or: [0 == object]] whileFalse: + [aBlock value: object. + object := object nextObject]]! - "Evaluate the argument, aBlock, for each object in the system - excluding SmallIntegers. With closures, this needs to use an end - marker (lastObject) since activation of the block will create new - contexts and cause an infinite loop." - | object lastObject | - object := self someObject. - lastObject := Object new. - [lastObject == object or: [0 == object]] - whileFalse: [aBlock value: object. - object := object nextObject]! Item was added: + ----- Method: SystemNavigation>>allObjectsOrNil (in category 'query') ----- + allObjectsOrNil + "Answer an Array of all objects in the system. Fail if there isn't + enough memory to instantiate the result and answer nil." + + ^nil! From Das.Linux at gmx.de Tue Oct 28 17:39:30 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Tue Oct 28 17:39:34 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz Message-ID: On 28.10.2014, at 17:23, commits@source.squeak.org wrote: > Item was changed: > ==== ERROR === > > Error: Unrecognized class type Well, this is gonna be interesting in the future. Are SPUR MCZs now completely incompatible to non-spur MCZs? This would be terrible? From tim at rowledge.org Tue Oct 28 18:32:55 2014 From: tim at rowledge.org (tim Rowledge) Date: Tue Oct 28 18:33:00 2014 Subject: [squeak-dev] Getting events to 'buried' Morphs Message-ID: <866FAAC8-6F73-4087-AEA4-F636962BD1E8@rowledge.org> Here?s a fun problem. In the Ancient Days of say 2002-ish when electricity came in little bags delivered to your door by Gnomes, you could add a BorderedMorph in front of another morph, completely overlaying it, and still get the events in the underlying morph. This is being used in old Scratch code to put a warning rectangle around a block. Do that in the current morphic world and no events get to the underlying morph. That?s a bit of a problem in some cases. Are there any already provided ways to get around this? I?ve considered making the border out of four separate morphs, maybe a subclass of BorderedMorph that somehow doesn?t block events, but it seems like something somebody else might have battled before. tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: CPE: Create Parity Error From leves at elte.hu Tue Oct 28 19:28:18 2014 From: leves at elte.hu (Levente Uzonyi) Date: Tue Oct 28 19:28:20 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz In-Reply-To: References: Message-ID: On Tue, 28 Oct 2014, Tobias Pape wrote: > > On 28.10.2014, at 17:23, commits@source.squeak.org wrote: > >> Item was changed: >> ==== ERROR === >> >> Error: Unrecognized class type > > Well, this is gonna be interesting in the future. > Are SPUR MCZs now completely incompatible to non-spur MCZs? > > This would be terrible? > No, but Spur has new class formats which are not recognized by SqueakSource. I shouldn't be hard to fix it for someone who knows how SqueakSource works, and what the new formats are. Levente From Das.Linux at gmx.de Tue Oct 28 19:31:47 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Tue Oct 28 19:31:51 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz In-Reply-To: References: Message-ID: <7FAD51D7-C89A-4730-B7F8-E1ED13CF9162@gmx.de> On 28.10.2014, at 20:28, Levente Uzonyi wrote: > On Tue, 28 Oct 2014, Tobias Pape wrote: > >> >> On 28.10.2014, at 17:23, commits@source.squeak.org wrote: >> >>> Item was changed: >>> ==== ERROR === >>> >>> Error: Unrecognized class type >> >> Well, this is gonna be interesting in the future. >> Are SPUR MCZs now completely incompatible to non-spur MCZs? >> >> This would be terrible? >> > > No, but Spur has new class formats which are not recognized by SqueakSource. I shouldn't be hard to fix it for someone who knows how SqueakSource works, and what the new formats are. SqueakSource uses the available Monticello. This obviously means that the ?old? monticello is incompatible to the Class formats of SPUR, right? From bert at freudenbergs.de Tue Oct 28 19:59:27 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Tue Oct 28 19:59:33 2014 Subject: [squeak-dev] Getting events to 'buried' Morphs In-Reply-To: <866FAAC8-6F73-4087-AEA4-F636962BD1E8@rowledge.org> References: <866FAAC8-6F73-4087-AEA4-F636962BD1E8@rowledge.org> Message-ID: <1B594349-4516-468D-B12E-00C15D40E6EE@freudenbergs.de> On 28.10.2014, at 14:32, tim Rowledge wrote: > Here?s a fun problem. > > In the Ancient Days of say 2002-ish when electricity came in little bags delivered to your door by Gnomes, you could add a BorderedMorph in front of another morph, completely overlaying it, and still get the events in the underlying morph. This is being used in old Scratch code to put a warning rectangle around a block. Do that in the current morphic world and no events get to the underlying morph. That?s a bit of a problem in some cases. > > Are there any already provided ways to get around this? I?ve considered making the border out of four separate morphs, maybe a subclass of BorderedMorph that somehow doesn?t block events, but it seems like something somebody else might have battled before. Lock it. - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/75f964ac/smime.bin From tim at rowledge.org Tue Oct 28 20:10:38 2014 From: tim at rowledge.org (tim Rowledge) Date: Tue Oct 28 20:10:47 2014 Subject: [squeak-dev] Getting events to 'buried' Morphs In-Reply-To: <1B594349-4516-468D-B12E-00C15D40E6EE@freudenbergs.de> References: <866FAAC8-6F73-4087-AEA4-F636962BD1E8@rowledge.org> <1B594349-4516-468D-B12E-00C15D40E6EE@freudenbergs.de> Message-ID: <43C853AD-B774-4455-BA77-EEE92A398035@rowledge.org> On 28-10-2014, at 12:59 PM, Bert Freudenberg wrote: > On 28.10.2014, at 14:32, tim Rowledge wrote: > >> Here?s a fun problem. >> >> In the Ancient Days of say 2002-ish when electricity came in little bags delivered to your door by Gnomes, you could add a BorderedMorph in front of another morph, completely overlaying it, and still get the events in the underlying morph. This is being used in old Scratch code to put a warning rectangle around a block. Do that in the current morphic world and no events get to the underlying morph. That?s a bit of a problem in some cases. >> >> Are there any already provided ways to get around this? I?ve considered making the border out of four separate morphs, maybe a subclass of BorderedMorph that somehow doesn?t block events, but it seems like something somebody else might have battled before. > > Lock it. Huh. Fascinating; it certainly works but it isn?t exactly an obvious name. Ta! tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim M$ are grinning pigs in a sea of buggy code - The Inquirer From edgardec2005 at gmail.com Tue Oct 28 20:25:35 2014 From: edgardec2005 at gmail.com (Edgar J. De Cleene) Date: Tue Oct 28 20:25:49 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: <90770656-612F-4D7E-B320-196785CA971C@gmail.com> Message-ID: On 10/28/14, 12:11 PM, "Chris Cunnington" wrote: > What are we trying to accomplish here? Why revisit the ComSwiki? > Because it is the institutional memory of the Squeak community online. It is > over ten years of articles. Over 6000. > We want to preserve that. We want to build on that. > > In some ways, what I?m about to say is similar to the recent discussion about > ImageSegments. > > There are two things to consider here: the data; and, the application. > > Ultimately we don?t care about ComSwiki or XML files. We do care about the > institutional memory of the community. That?s the priority. > > Let?s look at data. These articles are in XML files. People here sneer at XML. > Good for them. But notice that these files have lasted a decade. That?s > incredible. Show me any data gathered by Pier or SmallWiki or TinyWiki that > has lasted a decade. Nowhere to be found. > > Before Lukas was Mr. Seaside, he was Mr. Wiki. He didn?t like XML. At all. He > stored everything in some binary blob. If I give you a random binary blob from > ten years ago, how well is it going to explain itself? If I give you an image > segment from a decade ago, you wouldn?t know where to start. XML explains > itself. Very clearly. Mark Guzdial made an informed decision to keep documents > independent of applications. In the Relax NG book from O?Reilly that arrived > yesterday on my doorstep (?Relax NG?, 2004) it says exactly that on pg. 3. > > That is a powerful principal of the Swiki design. It has served us well. Lukas > can come back from Google right now and say it?s not useful. Avi could show up > and talk about Image Segments and DabbleDB and I don?t think they could refute > how useful this principal is. You could probably say the same thing about > Fuel. It?s the reason SQL is popular. > > We are making the ComSwiki backward compatible. If it ain?t broke don?t fix > it. The Swiki is remarkably well designed and remarkably reliable and has a > clear separation between application and data. > > The ComSwiki can be superseded but there in no need to do that anything faster > than a snail?s pace because it just works. > > Chris +1 From eliot.miranda at gmail.com Tue Oct 28 21:31:38 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 28 21:31:44 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz In-Reply-To: <7FAD51D7-C89A-4730-B7F8-E1ED13CF9162@gmx.de> References: <7FAD51D7-C89A-4730-B7F8-E1ED13CF9162@gmx.de> Message-ID: On Tue, Oct 28, 2014 at 12:31 PM, Tobias Pape wrote: > > On 28.10.2014, at 20:28, Levente Uzonyi wrote: > > > On Tue, 28 Oct 2014, Tobias Pape wrote: > > > >> > >> On 28.10.2014, at 17:23, commits@source.squeak.org wrote: > >> > >>> Item was changed: > >>> ==== ERROR === > >>> > >>> Error: Unrecognized class type > >> > >> Well, this is gonna be interesting in the future. > >> Are SPUR MCZs now completely incompatible to non-spur MCZs? > >> > >> This would be terrible? > >> > > > > No, but Spur has new class formats which are not recognized by > SqueakSource. I shouldn't be hard to fix it for someone who knows how > SqueakSource works, and what the new formats are. > > SqueakSource uses the available Monticello. > This obviously means that the ?old? monticello is incompatible to > the Class formats of SPUR, right? > Arguably. But simply update Monticello to Monticello-eem.592 or later and there's no problem. Can we not do that for the SqueakSource image? -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/a027a3e5/attachment.htm From Das.Linux at gmx.de Tue Oct 28 22:03:31 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Tue Oct 28 22:03:37 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz In-Reply-To: References: <7FAD51D7-C89A-4730-B7F8-E1ED13CF9162@gmx.de> Message-ID: <4775FCEA-1846-4745-BEAA-254D75EB4548@gmx.de> On 28.10.2014, at 22:31, Eliot Miranda wrote: > On Tue, Oct 28, 2014 at 12:31 PM, Tobias Pape wrote: > > On 28.10.2014, at 20:28, Levente Uzonyi wrote: > > > On Tue, 28 Oct 2014, Tobias Pape wrote: > > > >> > >> On 28.10.2014, at 17:23, commits@source.squeak.org wrote: > >> > >>> Item was changed: > >>> ==== ERROR === > >>> > >>> Error: Unrecognized class type > >> > >> Well, this is gonna be interesting in the future. > >> Are SPUR MCZs now completely incompatible to non-spur MCZs? > >> > >> This would be terrible? > >> > > > > No, but Spur has new class formats which are not recognized by SqueakSource. I shouldn't be hard to fix it for someone who knows how SqueakSource works, and what the new formats are. > > SqueakSource uses the available Monticello. > This obviously means that the ?old? monticello is incompatible to > the Class formats of SPUR, right? > > Arguably. But simply update Monticello to Monticello-eem.592 or later and there's no problem. Can we not do that for the SqueakSource image? Should be possible. But I have no access to it. While we are at it; can we make provisions for GemStone class formats? They differ ever so slightly and it is really hard to keep all in sync. We now have: Squeak/Pharo Class formats (ca Squeak 3.8 - Squeak 4.6/Pharo3.0) Squeak/Pharo SPUR Class Formats (current and possibly onward) GemStone class formats (somewhat mapped from the squeak ones) I did a bit of coding for the gemstone monticello version about one or two years back and the mapping between the known monticello class formats and gemstone class formats is a little fragile, I think. Best -Tobias From eliot.miranda at gmail.com Tue Oct 28 22:21:15 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue Oct 28 22:21:18 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz In-Reply-To: <4775FCEA-1846-4745-BEAA-254D75EB4548@gmx.de> References: <7FAD51D7-C89A-4730-B7F8-E1ED13CF9162@gmx.de> <4775FCEA-1846-4745-BEAA-254D75EB4548@gmx.de> Message-ID: Hi Tobias, On Tue, Oct 28, 2014 at 3:03 PM, Tobias Pape wrote: > > On 28.10.2014, at 22:31, Eliot Miranda wrote: > > > On Tue, Oct 28, 2014 at 12:31 PM, Tobias Pape wrote: > > > > On 28.10.2014, at 20:28, Levente Uzonyi wrote: > > > > > On Tue, 28 Oct 2014, Tobias Pape wrote: > > > > > >> > > >> On 28.10.2014, at 17:23, commits@source.squeak.org wrote: > > >> > > >>> Item was changed: > > >>> ==== ERROR === > > >>> > > >>> Error: Unrecognized class type > > >> > > >> Well, this is gonna be interesting in the future. > > >> Are SPUR MCZs now completely incompatible to non-spur MCZs? > > >> > > >> This would be terrible? > > >> > > > > > > No, but Spur has new class formats which are not recognized by > SqueakSource. I shouldn't be hard to fix it for someone who knows how > SqueakSource works, and what the new formats are. > > > > SqueakSource uses the available Monticello. > > This obviously means that the ?old? monticello is incompatible to > > the Class formats of SPUR, right? > > > > Arguably. But simply update Monticello to Monticello-eem.592 or later > and there's no problem. Can we not do that for the SqueakSource image? > > > Should be possible. But I have no access to it. > > While we are at it; can we make provisions for > GemStone class formats? They differ ever so slightly > and it is really hard to keep all in sync. > I wouldn't know, but perhaps you could take a look? I had to do very little to support a new format. The one method I needed to modify was MCClassDefinition>>#kindOfSubclass We now have: > Squeak/Pharo Class formats (ca Squeak 3.8 - Squeak 4.6/Pharo3.0) > Squeak/Pharo SPUR Class Formats (current and possibly onward) GemStone class formats (somewhat mapped from the squeak ones) > > I did a bit of coding for the gemstone monticello version about one or > two years back and the mapping between the known monticello class formats > and gemstone class formats is a little fragile, I think. > > Best > -Tobias > > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141028/0528af12/attachment.htm From lewis at mail.msen.com Tue Oct 28 23:17:36 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 28 23:17:39 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz In-Reply-To: References: <7FAD51D7-C89A-4730-B7F8-E1ED13CF9162@gmx.de> Message-ID: <20141028231736.GA37952@shell.msen.com> On Tue, Oct 28, 2014 at 02:31:38PM -0700, Eliot Miranda wrote: > On Tue, Oct 28, 2014 at 12:31 PM, Tobias Pape wrote: > > > > > On 28.10.2014, at 20:28, Levente Uzonyi wrote: > > > > > On Tue, 28 Oct 2014, Tobias Pape wrote: > > > > > >> > > >> On 28.10.2014, at 17:23, commits@source.squeak.org wrote: > > >> > > >>> Item was changed: > > >>> ==== ERROR === > > >>> > > >>> Error: Unrecognized class type > > >> > > >> Well, this is gonna be interesting in the future. > > >> Are SPUR MCZs now completely incompatible to non-spur MCZs? > > >> > > >> This would be terrible??? > > >> > > > > > > No, but Spur has new class formats which are not recognized by > > SqueakSource. I shouldn't be hard to fix it for someone who knows how > > SqueakSource works, and what the new formats are. > > > > SqueakSource uses the available Monticello. > > This obviously means that the ???old??? monticello is incompatible to > > the Class formats of SPUR, right? > > > > Arguably. But simply update Monticello to Monticello-eem.592 or later and > there's no problem. Can we not do that for the SqueakSource image? > Good question. We should try it and find out. The source.squeak.org and squeaksource.com servers are now running on pretty much the same image, so if we can fix it for one we will fix it for both. I'll try to look into this soon if noone else gets to it first. Dave From lewis at mail.msen.com Tue Oct 28 23:39:41 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Tue Oct 28 23:39:44 2014 Subject: [squeak-dev] The Trunk: Collections.spur-ul.586.mcz In-Reply-To: References: <7FAD51D7-C89A-4730-B7F8-E1ED13CF9162@gmx.de> <4775FCEA-1846-4745-BEAA-254D75EB4548@gmx.de> Message-ID: <20141028233941.GB37952@shell.msen.com> On Tue, Oct 28, 2014 at 03:21:15PM -0700, Eliot Miranda wrote: > Hi Tobias, > > On Tue, Oct 28, 2014 at 3:03 PM, Tobias Pape wrote: > > > > > On 28.10.2014, at 22:31, Eliot Miranda wrote: > > > > > On Tue, Oct 28, 2014 at 12:31 PM, Tobias Pape wrote: > > > > > > On 28.10.2014, at 20:28, Levente Uzonyi wrote: > > > > > > > On Tue, 28 Oct 2014, Tobias Pape wrote: > > > > > > > >> > > > >> On 28.10.2014, at 17:23, commits@source.squeak.org wrote: > > > >> > > > >>> Item was changed: > > > >>> ==== ERROR === > > > >>> > > > >>> Error: Unrecognized class type > > > >> > > > >> Well, this is gonna be interesting in the future. > > > >> Are SPUR MCZs now completely incompatible to non-spur MCZs? > > > >> > > > >> This would be terrible??? > > > >> > > > > > > > > No, but Spur has new class formats which are not recognized by > > SqueakSource. I shouldn't be hard to fix it for someone who knows how > > SqueakSource works, and what the new formats are. > > > > > > SqueakSource uses the available Monticello. > > > This obviously means that the ???old??? monticello is incompatible to > > > the Class formats of SPUR, right? > > > > > > Arguably. But simply update Monticello to Monticello-eem.592 or later > > and there's no problem. Can we not do that for the SqueakSource image? > > > > > > Should be possible. But I have no access to it. > > > > While we are at it; can we make provisions for > > GemStone class formats? They differ ever so slightly > > and it is really hard to keep all in sync. > > > > I wouldn't know, but perhaps you could take a look? I had to do very > little to support a new format. The one method I needed to modify was > MCClassDefinition>>#kindOfSubclass Tobias, If you do anything with this, please let me know if I can help. Your own work on SqueakSource is more advanced than whatever we are currently running on squeak.org and squeaksource.com, but if you want or need access to those images I'll make sure you can get a copy. I don't think that we should make them publicly downloadable because they may contain passwords and personal information. Note that I am not really a squeaksource expert, I'm just trying to keep squeaksource.com running reliably. I'll try to update Monticello in a copy of the existing squeaksource.com image, but if you have something better that includes Gemstone support I would be happy to follow your lead if possible. Dave From commits at source.squeak.org Tue Oct 28 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Tue Oct 28 23:55:05 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141028235502.19135.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007354.html Name: Collections.spur-ul.586 Ancestors: Collections-ul.586, Collections.spur-cmm.585 Collections-ul.586 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Symbol table changes: - ensure that enumerations stay consistent - avoid read-write and write-write race conditions - added a safe #condenseNewSymbols method, which is a replacement for former unsafe methods (#shutDown: and #compactSymbolTable). It's also automatically triggered whenever there are more than 1000 NewSymbols. - deprecated #compactSymbolTable - updated some comments Note that interning many symbols is a bit slower, but thread safety is more important. ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007355.html Name: Kernel.spur-nice.881 Ancestors: Kernel-nice.881, Kernel.spur-ul.880 Kernel-nice.881 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Fix Float literal equality: 0.0 and -0.0 are not the same Float... ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007356.html Name: System.spur-ul.688 Ancestors: System-ul.688, System.spur-dtl.685 System-ul.688 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 Replaced ExternalSemaphoreTable with ExternalObjectTable to provide faster registration, and give better support to the current users of external objects. Notable changes: - the table is a separate object instead of a few class side methods - the whole API can be found in SmalltalkImage in the external objects category - #newExternalSemaphore, #newExternalSemaphoreDo: and #newExternalSemaphores: provide fast and easy creation and registration of Semaphores - #unregisterExternalObjects: can unregister multiple objects faster - #externalObjects will return a copy of the externalObjectsArray - better scalability - the maxExternalSemaphores VM parameter will be incremented as the externalObjectsArray grows ============================================= From list at afceurope.com Wed Oct 29 10:59:08 2014 From: list at afceurope.com (Annick Fron) Date: Wed Oct 29 10:59:17 2014 Subject: [squeak-dev] FFI structs Message-ID: <8347C5A6-FF04-4EB4-B874-4BB22AC6171F@afceurope.com> I I have a C struct with a char* struct result { char* time } I define an ExternalStructure in FFI , with one field of type char* (note that the syntax char [5] is not accepted ! ). defineFields generates the accessors time and time: If I use time: ?05:45? I get an error. How do I set a string value in an ExternalStructure ? Annick From hannes.hirzel at gmail.com Wed Oct 29 14:50:31 2014 From: hannes.hirzel at gmail.com (H. Hirzel) Date: Wed Oct 29 14:50:34 2014 Subject: [squeak-dev] ComSwiki4.5 in the All-In-One In-Reply-To: References: <90770656-612F-4D7E-B320-196785CA971C@gmail.com> Message-ID: Chris What you wrote about the XML files and the long term preservation of institutional memory is very well observed and summarized. Thank you for bringing up this issue. Actually I wonder why this idea of packing the Swiki XML files together with the Wiki software into an All-In-One package did not come up earlier..... --Hannes On 10/28/14, Edgar J. De Cleene wrote: > On 10/28/14, 12:11 PM, "Chris Cunnington" wrote: > >> What are we trying to accomplish here? Why revisit the ComSwiki? >> Because it is the institutional memory of the Squeak community online. It >> is >> over ten years of articles. Over 6000. >> We want to preserve that. We want to build on that. >> >> In some ways, what I?m about to say is similar to the recent discussion >> about >> ImageSegments. >> >> There are two things to consider here: the data; and, the application. >> >> Ultimately we don?t care about ComSwiki or XML files. We do care about >> the >> institutional memory of the community. That?s the priority. >> >> Let?s look at data. These articles are in XML files. People here sneer at >> XML. >> Good for them. But notice that these files have lasted a decade. That?s >> incredible. Show me any data gathered by Pier or SmallWiki or TinyWiki >> that >> has lasted a decade. Nowhere to be found. >> >> Before Lukas was Mr. Seaside, he was Mr. Wiki. He didn?t like XML. At all. >> He >> stored everything in some binary blob. If I give you a random binary blob >> from >> ten years ago, how well is it going to explain itself? If I give you an >> image >> segment from a decade ago, you wouldn?t know where to start. XML explains >> itself. Very clearly. Mark Guzdial made an informed decision to keep >> documents >> independent of applications. In the Relax NG book from O?Reilly that >> arrived >> yesterday on my doorstep (?Relax NG?, 2004) it says exactly that on pg. >> 3. >> >> That is a powerful principal of the Swiki design. It has served us well. >> Lukas >> can come back from Google right now and say it?s not useful. Avi could >> show up >> and talk about Image Segments and DabbleDB and I don?t think they could >> refute >> how useful this principal is. You could probably say the same thing about >> Fuel. It?s the reason SQL is popular. >> >> We are making the ComSwiki backward compatible. If it ain?t broke don?t >> fix >> it. The Swiki is remarkably well designed and remarkably reliable and has >> a >> clear separation between application and data. >> >> The ComSwiki can be superseded but there in no need to do that anything >> faster >> than a snail?s pace because it just works. >> >> Chris > +1 > > > > From bert at freudenbergs.de Wed Oct 29 15:48:19 2014 From: bert at freudenbergs.de (Bert Freudenberg) Date: Wed Oct 29 15:48:24 2014 Subject: [squeak-dev] FFI structs In-Reply-To: <8347C5A6-FF04-4EB4-B874-4BB22AC6171F@afceurope.com> References: <8347C5A6-FF04-4EB4-B874-4BB22AC6171F@afceurope.com> Message-ID: <703E1721-362D-41F1-8BA0-4A4EFF96A041@freudenbergs.de> On 29.10.2014, at 06:59, Annick Fron wrote: > I I have a C struct with a char* > > struct result { > char* time } > > I define an ExternalStructure in FFI , with one field of type char* (note that the syntax char [5] is not accepted ! ). > > defineFields generates the accessors time and time: > > If I use > time: ?05:45? > > I get an error. > How do I set a string value in an ExternalStructure ? > > Annick Just like in C. You need to create a pointer to a char array and store that. Which means you need to allocate some bytes (ExternalAddress allocate: byteSize + 1), copy your string there (byteAt:put:), add a terminating 0 byte, then store the address of that in your struct. Be sure to free the memory allocated when you're done. I think there used to be a helper function for that but I can't find it (only found fromCString). - Bert - -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4142 bytes Desc: not available Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141029/5ba038c5/smime.bin From ma.chris.m at gmail.com Wed Oct 29 18:53:27 2014 From: ma.chris.m at gmail.com (Chris Muller) Date: Wed Oct 29 18:53:30 2014 Subject: [squeak-dev] Urgent: how to define a global? Message-ID: Trying to debug a server, need to define a global OrderedCollection "X" which I want to put debugging objects into. In a workspace, I type: X := OrderedCollection new System asks me to correct or define a global. I choose to define a global. But I still cannot access X. It keeps asking me to correct or define a global. Yippee, great thing to happen at 4am when you just need to debug something! Digging in shows that when I try to access X, it ends up looking in Smalltalk environment 'bindings' IdentityDictionary, but when I defined X, it put the binding #X=>nil into Smalltalk environment 'declarations' only. I don't know what 'declarations' vs. 'bindings' are and I don't care, I just need to be able to define the global, could someone pelase tell me the proper fix? a) Defining X should put it in 'bindings' instead of 'declarations'? b) Accessing X should access from 'declarations' instead of 'bindings'? c) Defining X should put it in BOTH 'declarations' and 'bindings'? From nicolas.cellier.aka.nice at gmail.com Wed Oct 29 19:21:57 2014 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed Oct 29 19:22:00 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: I've asked several questions about this a few months ago (dig squeak-dev if you wish, i'm in a hurry...) No answer. You made an effort to comment the classes, but Colin did completely change the implementation without updating the comment... Now who knows what's in the mind of the conceptor? It's like the fresh environment is abandonware... 2014-10-29 19:53 GMT+01:00 Chris Muller : > Trying to debug a server, need to define a global OrderedCollection > "X" which I want to put debugging objects into. In a workspace, I > type: > > X := OrderedCollection new > > System asks me to correct or define a global. I choose to define a global. > > But I still cannot access X. It keeps asking me to correct or define > a global. Yippee, great thing to happen at 4am when you just need to > debug something! > > Digging in shows that when I try to access X, it ends up looking in > Smalltalk environment 'bindings' IdentityDictionary, but when I > defined X, it put the binding #X=>nil into Smalltalk environment > 'declarations' only. > > I don't know what 'declarations' vs. 'bindings' are and I don't care, > I just need to be able to define the global, could someone pelase tell > me the proper fix? > > a) Defining X should put it in 'bindings' instead of 'declarations'? > b) Accessing X should access from 'declarations' instead of 'bindings'? > c) Defining X should put it in BOTH 'declarations' and 'bindings'? > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141029/ddc281f1/attachment.htm From jeff.gonis at gmail.com Wed Oct 29 20:06:43 2014 From: jeff.gonis at gmail.com (Jeff Gonis) Date: Wed Oct 29 20:06:47 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: Hi Folks, Just wanted to PING the list again to see if anyone had any feedback. Am I just seeing a crash that no one else is seeing and it is something with my setup, is there a safe VM version that people are using to update from the trunk image, and is anyone else able to grab the image that Marcel posted and do a successful update on the trunk? I am just playing around with the image Marcel posted and it is just fine for getting work done, but my OCD tendencies flare up a bit knowing that I am not working with fully updated code. Any help or at least just letting me know that this is a problem on my end rather than the trunk would be greatly appreciated. Thanks, Jeff From eliot.miranda at gmail.com Wed Oct 29 20:19:31 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 29 20:19:36 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: Hi Jeff, On Wed, Oct 29, 2014 at 1:06 PM, Jeff Gonis wrote: > Hi Folks, > > Just wanted to PING the list again to see if anyone had any feedback. > Am I just seeing a crash that no one else is seeing and it is > something with my setup, is there a safe VM version that people are > using to update from the trunk image, and is anyone else able to grab > the image that Marcel posted and do a successful update on the trunk? > > I am just playing around with the image Marcel posted and it is just > fine for getting work done, but my OCD tendencies flare up a bit > knowing that I am not working with fully updated code. > > Any help or at least just letting me know that this is a problem on my > end rather than the trunk would be greatly appreciated. > I'm not sure whats going on. Perhaps your image has got into a strange state. I have no problems updating the 4.5 image from the all-in-one to trunk as part of the Spur image bootstrap. See http://www.squeakvm.org/svn/squeak/branches/Cog/image/buildspurtrunkimage.sh/ You might try checking-out http://www.squeakvm.org/svn/squeak/branches/Cog/image and running the script to check. The script downloads an up-to-date VM, the All-in-one, changes the update repository, updates, then builds a VMMaker image and then uses that to convert the updated trunk to Spur. This has been working well for a couple of months. HTH -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141029/22c2a160/attachment.htm From lewis at mail.msen.com Wed Oct 29 20:24:11 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 29 20:24:17 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: <42049.136.2.1.102.1414614251.squirrel@webmail.msen.com> Hi Jeff, Nice to see you on the list, and sorry for not responding earlier. I am fairly sure that we had some things screwed up in the update stream (since resolved) and you are experiencing the effects of that. I have a feeling that most of us working with trunk images we are keeping up to date with the stream, and we may have neglected to go back and fix up whatever update maps needed to be patched in order to work around the problem. I don't know if this will make any difference, but the latest version of the traditional interpreter VM for Windows is at http://www.squeakvm.org/win32/ http://www.squeakvm.org/win32/release/Squeak4.10.2-2612.win32-i386.zip > Hi Folks, > > Just wanted to PING the list again to see if anyone had any feedback. > Am I just seeing a crash that no one else is seeing and it is > something with my setup, is there a safe VM version that people are > using to update from the trunk image, and is anyone else able to grab > the image that Marcel posted and do a successful update on the trunk? > > I am just playing around with the image Marcel posted and it is just > fine for getting work done, but my OCD tendencies flare up a bit > knowing that I am not working with fully updated code. > > Any help or at least just letting me know that this is a problem on my > end rather than the trunk would be greatly appreciated. > > Thanks, > Jeff > From lewis at mail.msen.com Wed Oct 29 20:27:32 2014 From: lewis at mail.msen.com (David T. Lewis) Date: Wed Oct 29 20:27:36 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: <42049.136.2.1.102.1414614251.squirrel@webmail.msen.com> References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> <42049.136.2.1.102.1414614251.squirrel@webmail.msen.com> Message-ID: <62027.136.2.1.102.1414614452.squirrel@webmail.msen.com> Sorry, I hit "send" by accident. What I meant to say is that the interpreter VM may get you past the crash that you experienced, or it might just crash differently. If you have the patience you can give it a try and see if it helps. Either way, I'm pretty sure that the problem is in the update stream as opposed to the VM. Dave > Hi Jeff, > > Nice to see you on the list, and sorry for not responding earlier. > > I am fairly sure that we had some things screwed up in the update stream > (since resolved) and you are experiencing the effects of that. I have a > feeling that most of us working with trunk images we are keeping up to > date with the stream, and we may have neglected to go back and fix up > whatever update maps needed to be patched in order to work around the > problem. > > I don't know if this will make any difference, but the latest version of > the traditional interpreter VM for Windows is at > > http://www.squeakvm.org/win32/ > http://www.squeakvm.org/win32/release/Squeak4.10.2-2612.win32-i386.zip > > >> Hi Folks, >> >> Just wanted to PING the list again to see if anyone had any feedback. >> Am I just seeing a crash that no one else is seeing and it is >> something with my setup, is there a safe VM version that people are >> using to update from the trunk image, and is anyone else able to grab >> the image that Marcel posted and do a successful update on the trunk? >> >> I am just playing around with the image Marcel posted and it is just >> fine for getting work done, but my OCD tendencies flare up a bit >> knowing that I am not working with fully updated code. >> >> Any help or at least just letting me know that this is a problem on my >> end rather than the trunk would be greatly appreciated. >> >> Thanks, >> Jeff >> > > > From leves at elte.hu Wed Oct 29 20:43:32 2014 From: leves at elte.hu (Levente Uzonyi) Date: Wed Oct 29 20:43:41 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: On Wed, 29 Oct 2014, Chris Muller wrote: > Trying to debug a server, need to define a global OrderedCollection > "X" which I want to put debugging objects into. In a workspace, I > type: > > X := OrderedCollection new > > System asks me to correct or define a global. I choose to define a global. > > But I still cannot access X. It keeps asking me to correct or define > a global. Yippee, great thing to happen at 4am when you just need to > debug something! > > Digging in shows that when I try to access X, it ends up looking in > Smalltalk environment 'bindings' IdentityDictionary, but when I > defined X, it put the binding #X=>nil into Smalltalk environment > 'declarations' only. > > I don't know what 'declarations' vs. 'bindings' are and I don't care, > I just need to be able to define the global, could someone pelase tell > me the proper fix? This has always worked for me: Smalltalk at: #X put: OrderedCollection new. > > a) Defining X should put it in 'bindings' instead of 'declarations'? IIRC bindings are all bindings available in the Environment, while declarations are the locally declared bindings. So it should be present in both of them. Howeverbindings is currently filled up lazily, that's why your binding might be missing from it. > b) Accessing X should access from 'declarations' instead of 'bindings'? No. See above why. > c) Defining X should put it in BOTH 'declarations' and 'bindings'? Yes. See above why. :) Levente > > From djm1329 at san.rr.com Wed Oct 29 20:45:59 2014 From: djm1329 at san.rr.com (Douglas McPherson) Date: Wed Oct 29 20:46:03 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: Message-ID: <20141029204559.24HL7.284277.root@cdptpa-web09> ---- Eliot Miranda wrote: > Hi Jeff, > > On Wed, Oct 29, 2014 at 1:06 PM, Jeff Gonis wrote: > > > Hi Folks, > > > > Just wanted to PING the list again to see if anyone had any feedback. > > Am I just seeing a crash that no one else is seeing and it is > > something with my setup, is there a safe VM version that people are > > using to update from the trunk image, and is anyone else able to grab > > the image that Marcel posted and do a successful update on the trunk? > > > > I am just playing around with the image Marcel posted and it is just > > fine for getting work done, but my OCD tendencies flare up a bit > > knowing that I am not working with fully updated code. > > > > Any help or at least just letting me know that this is a problem on my > > end rather than the trunk would be greatly appreciated. > > > > I'm not sure whats going on. Perhaps your image has got into a strange > state. I have no problems updating the 4.5 image from the all-in-one to > trunk as part of the Spur image bootstrap. See > http://www.squeakvm.org/svn/squeak/branches/Cog/image/buildspurtrunkimage.sh/ > You might try checking-out > http://www.squeakvm.org/svn/squeak/branches/Cog/image and running the > script to check. The script downloads an up-to-date VM, the All-in-one, > changes the update repository, updates, then builds a VMMaker image and > then uses that to convert the updated trunk to Spur. This has been working > well for a couple of months. > > HTH Just a caveat about the scripts Eliot mentions. Due to recent flux in the layout of the All-in-One, [at least some of] the scripts stopped working. See http://lists.squeakfoundation.org/pipermail/vm-dev/2014-October/016726.html Doug > -- > best, > Eliot From leves at elte.hu Wed Oct 29 21:24:20 2014 From: leves at elte.hu (Levente Uzonyi) Date: Wed Oct 29 21:24:31 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: On Wed, 29 Oct 2014, Jeff Gonis wrote: > Hi Folks, > > Just wanted to PING the list again to see if anyone had any feedback. > Am I just seeing a crash that no one else is seeing and it is > something with my setup, is there a safe VM version that people are > using to update from the trunk image, and is anyone else able to grab > the image that Marcel posted and do a successful update on the trunk? I've checked your crash.dmp, and it looks interesting, especially this part: Stack backtrace: [80126560] ??? + 0 in (null) [8008DE63] next: + 107 in CogCode [7FFF07C8] ceReturnToInterpreterTrampoline + 0 in CogCode [7FFF06F8] ceBaseFrameReturnTrampoline + 0 in CogCode Smalltalk stack dump: 0x99553c M SocketStream>receiveData: 0x812fa8ac: a(n) SocketStream 0x99555c M SocketStream>next: 0x812fa8ac: a(n) SocketStream 0x9955ac I HTTPSocket class>httpRequest:url:headers:content:response: 0x80513ad0: a(n) HTTPSocket class 0x995cc0 I HTTPSocket class>httpGetDocument:args:accept:request: 0x80513ad0: a(n) HTTPSocket class 0x995cec M HTTPSocket class>httpGet:args:accept:request: 0x80513ad0: a(n) HTTPSocket class 0x995d24 I HTTPSocket class>httpGet:args:user:passwd: 0x80513ad0: a(n) HTTPSocket class 0x995d54 M [] in MCHttpRepository>readStreamForFileNamed:do: 0x80dfe9d8: a(n) MCHttpRepository 0x995d70 M BlockClosure>on:do: 0x812e22e4: a(n) BlockClosure 0x995d98 M [] in MCHttpRepository>displayProgress:during: 0x80dfe9d8: a(n) MCHttpRepository 0x995dc0 M [] in MorphicUIManager>displayProgress:at:from:to:during: 0x8057fb00: a(n) MorphicUIManager 0x812e9b08 w BlockClosure>on:do: I can't tell what went wrong, but it doesn't seem like it's related to the ZipPlugin changes. Can you tell how far the update process can go? (which update map, and which package is being installed when the crash happens) Does it always crash at the same point? Levente > > I am just playing around with the image Marcel posted and it is just > fine for getting work done, but my OCD tendencies flare up a bit > knowing that I am not working with fully updated code. > > Any help or at least just letting me know that this is a problem on my > end rather than the trunk would be greatly appreciated. > > Thanks, > Jeff > > From jeff.gonis at gmail.com Wed Oct 29 22:03:42 2014 From: jeff.gonis at gmail.com (Jeff Gonis) Date: Wed Oct 29 22:03:45 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: On Wed, Oct 29, 2014 at 3:24 PM, Levente Uzonyi wrote: > > > I've checked your crash.dmp, and it looks interesting, especially this part: > > Stack backtrace: > [80126560] ??? + 0 in (null) > [8008DE63] next: + 107 in CogCode > [7FFF07C8] ceReturnToInterpreterTrampoline + 0 in CogCode > [7FFF06F8] ceBaseFrameReturnTrampoline + 0 in CogCode > > Smalltalk stack dump: > 0x99553c M SocketStream>receiveData: 0x812fa8ac: a(n) SocketStream > 0x99555c M SocketStream>next: 0x812fa8ac: a(n) SocketStream > 0x9955ac I HTTPSocket class>httpRequest:url:headers:content:response: > 0x80513ad0: a(n) HTTPSocket class > 0x995cc0 I HTTPSocket class>httpGetDocument:args:accept:request: > 0x80513ad0: a(n) HTTPSocket class > 0x995cec M HTTPSocket class>httpGet:args:accept:request: 0x80513ad0: a(n) > HTTPSocket class > 0x995d24 I HTTPSocket class>httpGet:args:user:passwd: 0x80513ad0: a(n) > HTTPSocket class > 0x995d54 M [] in MCHttpRepository>readStreamForFileNamed:do: 0x80dfe9d8: > a(n) MCHttpRepository > 0x995d70 M BlockClosure>on:do: 0x812e22e4: a(n) BlockClosure > 0x995d98 M [] in MCHttpRepository>displayProgress:during: 0x80dfe9d8: a(n) > MCHttpRepository > 0x995dc0 M [] in MorphicUIManager>displayProgress:at:from:to:during: > 0x8057fb00: a(n) MorphicUIManager > 0x812e9b08 w BlockClosure>on:do: > > I can't tell what went wrong, but it doesn't seem like it's related to the > ZipPlugin changes. > Can you tell how far the update process can go? (which update map, and which > package is being installed when the crash happens) > Does it always crash at the same point? > > > Levente > > > Hi Levente, So I might not be able to recreate that exact crash because following David's advice and using the Interpreter VM caused the update to succeed. Prior to that however, it appeared to always crash in the same location in a repeatable fashion. Interestingly, after completing the update with the Interpreter VM and quitting without saving, the update proceeds using the same image and the cog VM. Could some sort of caching of packages be the problem here and completing the update successfully changes this? Of course this fact makes it hard to reproduce the issue using the image I was talking about, as it now works, but I will attempt to see if I have any other images that I can reproduce the issue with and I will post another crash dump and details if I am successful. Thanks to everyone for your help! Jeff From nicolas.cellier.aka.nice at gmail.com Wed Oct 29 22:06:41 2014 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed Oct 29 22:06:45 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: So after some digging i found those questions aimed at resolving failing tests http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-May/178411.html http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-April/177744.html If someone can propose partial answers, it will benefit to the environment science 2014-10-29 20:21 GMT+01:00 Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com>: > I've asked several questions about this a few months ago (dig squeak-dev > if you wish, i'm in a hurry...) > No answer. > You made an effort to comment the classes, but Colin did completely change > the implementation without updating the comment... > Now who knows what's in the mind of the conceptor? > It's like the fresh environment is abandonware... > > > 2014-10-29 19:53 GMT+01:00 Chris Muller : > >> Trying to debug a server, need to define a global OrderedCollection >> "X" which I want to put debugging objects into. In a workspace, I >> type: >> >> X := OrderedCollection new >> >> System asks me to correct or define a global. I choose to define a >> global. >> >> But I still cannot access X. It keeps asking me to correct or define >> a global. Yippee, great thing to happen at 4am when you just need to >> debug something! >> >> Digging in shows that when I try to access X, it ends up looking in >> Smalltalk environment 'bindings' IdentityDictionary, but when I >> defined X, it put the binding #X=>nil into Smalltalk environment >> 'declarations' only. >> >> I don't know what 'declarations' vs. 'bindings' are and I don't care, >> I just need to be able to define the global, could someone pelase tell >> me the proper fix? >> >> a) Defining X should put it in 'bindings' instead of 'declarations'? >> b) Accessing X should access from 'declarations' instead of 'bindings'? >> c) Defining X should put it in BOTH 'declarations' and 'bindings'? >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141029/0e8949d8/attachment.htm From eliot.miranda at gmail.com Wed Oct 29 22:44:57 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed Oct 29 22:45:00 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: Hi Jeff, whenever you, or anyone, has an mage that repeatably crashes the VM, I'd appreciate you keeping a copy. I may not have time to look at it, it may not be a VM bug, but if the copy isn't taken we'll never know... On Wed, Oct 29, 2014 at 3:03 PM, Jeff Gonis wrote: > On Wed, Oct 29, 2014 at 3:24 PM, Levente Uzonyi wrote: > > > > > > I've checked your crash.dmp, and it looks interesting, especially this > part: > > > > Stack backtrace: > > [80126560] ??? + 0 in (null) > > [8008DE63] next: + 107 in CogCode > > [7FFF07C8] ceReturnToInterpreterTrampoline + 0 in CogCode > > [7FFF06F8] ceBaseFrameReturnTrampoline + 0 in CogCode > > > > Smalltalk stack dump: > > 0x99553c M SocketStream>receiveData: 0x812fa8ac: a(n) SocketStream > > 0x99555c M SocketStream>next: 0x812fa8ac: a(n) SocketStream > > 0x9955ac I HTTPSocket class>httpRequest:url:headers:content:response: > > 0x80513ad0: a(n) HTTPSocket class > > 0x995cc0 I HTTPSocket class>httpGetDocument:args:accept:request: > > 0x80513ad0: a(n) HTTPSocket class > > 0x995cec M HTTPSocket class>httpGet:args:accept:request: 0x80513ad0: > a(n) > > HTTPSocket class > > 0x995d24 I HTTPSocket class>httpGet:args:user:passwd: 0x80513ad0: a(n) > > HTTPSocket class > > 0x995d54 M [] in MCHttpRepository>readStreamForFileNamed:do: > 0x80dfe9d8: > > a(n) MCHttpRepository > > 0x995d70 M BlockClosure>on:do: 0x812e22e4: a(n) BlockClosure > > 0x995d98 M [] in MCHttpRepository>displayProgress:during: 0x80dfe9d8: > a(n) > > MCHttpRepository > > 0x995dc0 M [] in MorphicUIManager>displayProgress:at:from:to:during: > > 0x8057fb00: a(n) MorphicUIManager > > 0x812e9b08 w BlockClosure>on:do: > > > > I can't tell what went wrong, but it doesn't seem like it's related to > the > > ZipPlugin changes. > > Can you tell how far the update process can go? (which update map, and > which > > package is being installed when the crash happens) > > Does it always crash at the same point? > > > > > > Levente > > > > > > > > Hi Levente, > > So I might not be able to recreate that exact crash because following > David's advice and using the Interpreter VM caused the update to > succeed. Prior to that however, it appeared to always crash in the > same location in a repeatable fashion. Interestingly, after > completing the update with the Interpreter VM and quitting without > saving, the update proceeds using the same image and the cog VM. Could > some sort of caching of packages be the problem here and completing > the update successfully changes this? > > Of course this fact makes it hard to reproduce the issue using the > image I was talking about, as it now works, but I will attempt to see > if I have any other images that I can reproduce the issue with and I > will post another crash dump and details if I am successful. > > Thanks to everyone for your help! > Jeff > > -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141029/b9753c4f/attachment.htm From jeff.gonis at gmail.com Wed Oct 29 23:20:44 2014 From: jeff.gonis at gmail.com (Jeff Gonis) Date: Wed Oct 29 23:20:47 2014 Subject: [squeak-dev] Re: Updating 4.5 or getting a recent build of 4.6 In-Reply-To: References: <1414512002967-4787221.post@n4.nabble.com> <1414512083084-4787222.post@n4.nabble.com> Message-ID: Hi Eliot, I will try to get some images together for you that are reproducible, but in the meantime I have to head out for the evening. One thing I have noticed, looking through the crash dumps generated for all of the crashes I have seen is that either at the very end of the primitive trace, or 2 or 3 calls from the end of the primitive trace in every single crash has been **CompactCode** This is the only similarity between the cases in terms of the primitive trace that I can see so far, because the stack dump has had a variety of different methods being processed at the time. I will work to get a reproducible image for you, but in the meantime I thought that might twig something for you. Thanks for your time, Jeff On Wed, Oct 29, 2014 at 4:44 PM, Eliot Miranda wrote: > Hi Jeff, > > whenever you, or anyone, has an mage that repeatably crashes the VM, I'd > appreciate you keeping a copy. I may not have time to look at it, it may > not be a VM bug, but if the copy isn't taken we'll never know... > From commits at source.squeak.org Thu Oct 30 00:06:53 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 30 00:06:56 2014 Subject: [squeak-dev] The Trunk: KernelTests-dtl.281.mcz Message-ID: David T. Lewis uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-dtl.281.mcz ==================== Summary ==================== Name: KernelTests-dtl.281 Author: dtl Time: 29 October 2014, 8:00:05.411 pm UUID: 4e5a309c-94d6-4dad-bc92-0dfa1d0ac7a5 Ancestors: KernelTests-nice.280 Fix testCull methods to correspond to current behavior of block closures. Existing test failures were masked by test methods that required recompilation. Reference squeak-dev: Date: Sun, 26 Oct 2014 02:35:23 +0200 (CEST) From: Levente Uzonyi To: The general-purpose Squeak developers list Subject: Re: [squeak-dev] Why isn't BlockClosureTest>>testCull failing? I think that behavior was changed not too long ago (1-2 years maybe). If you decompile the method you'll see that it's actually self assert: 1 equals: ([:x | x] cull: 1). It's because Squeak used to return the value of the last argument if the block was empty, but had arguments. The code should be self assert: nil equals: ([ :x | ] cull: 1). Levente On Sat, 25 Oct 2014, David T. Lewis wrote: >If we have this: > [ :x | ] value: 1 ==> nil > >And this: > ([ :x | ] cull: 1) ==> nil > >But in BlockClosureTest>>testCull, we have this: > > self assert: 1 equals: ([ :x | ] cull: 1). > >The test passes. How is this possible? =============== Diff against KernelTests-nice.280 =============== Item was changed: ----- Method: BlockClosureTest>>testCull (in category 'tests - evaluating') ----- testCull self assert: nil equals: ([ ] cull: 1). + self assert: nil equals: ([ :x | ] cull: 1). + self assert: 1 equals: ([ :x | x ] cull: 1). - self assert: 1 equals: ([ :x | ] cull: 1). self should: [ [ :x :y | ] cull: 1 ] raise: Error. self should: [ [ :x :y :z | ] cull: 1 ] raise: Error. self should: [ [ :x :y :z :a | ] cull: 1 ] raise: Error. self should: [ [ :x :y :z :a :b | ] cull: 1 ] raise: Error. self assert: ([ 0 ] cull: 1) = 0. self assert: ([ :x | x ] cull: 1) = 1 ! Item was changed: ----- Method: BlockClosureTest>>testCullCull (in category 'tests - evaluating') ----- testCullCull self assert: nil equals: ([ ] cull: 1 cull: 2). + + self assert: nil equals: ([ :x | ] cull: 1 cull: 2). + self assert: 1 equals: ([ :x | x ] cull: 1 cull: 2). + + self assert: nil equals: ([ :x :y | ] cull: 1 cull: 2). + self assert: 1 equals: ([ :x :y | x ] cull: 1 cull: 2). + self assert: 2 equals: ([ :x :y | y ] cull: 1 cull: 2). + - self assert: 1 equals: ([ :x | ] cull: 1 cull: 2). - self assert: 2 equals: ([ :x :y | ] cull: 1 cull: 2). self should: [ [ :x :y :z | ] cull: 1 cull: 2 ] raise: Error. self should: [ [ :x :y :z :a | ] cull: 1 cull: 2 ] raise: Error. self should: [ [ :x :y :z :a :b | ] cull: 1 cull: 2 ] raise: Error. self assert: ([ 0 ] cull: 1 cull: 2) = 0. self assert: ([ :x | x ] cull: 1 cull: 2) = 1. self assert: ([ :x :y | y ] cull: 1 cull: 2) = 2. ! Item was changed: ----- Method: BlockClosureTest>>testCullCullCull (in category 'tests - evaluating') ----- testCullCullCull self assert: nil equals: ([ ] cull: 1 cull: 2 cull: 3). + + self assert: nil equals: ([ :x | ] cull: 1 cull: 2 cull: 3). + self assert: 1 equals: ([ :x | x ] cull: 1 cull: 2 cull: 3). + + self assert: nil equals: ([ :x :y | ] cull: 1 cull: 2 cull: 3). + self assert: 1 equals: ([ :x :y | x ] cull: 1 cull: 2 cull: 3). + self assert: 2 equals: ([ :x :y | y ] cull: 1 cull: 2 cull: 3). + + self assert: nil equals: ([ :x :y :z | ] cull: 1 cull: 2 cull: 3). + self assert: 1 equals: ([ :x :y :z | x ] cull: 1 cull: 2 cull: 3). + self assert: 2 equals: ([ :x :y :z | y ] cull: 1 cull: 2 cull: 3). + self assert: 3 equals: ([ :x :y :z | z ] cull: 1 cull: 2 cull: 3). + - self assert: 1 equals: ([ :x | ] cull: 1 cull: 2 cull: 3). - self assert: 2 equals: ([ :x :y | ] cull: 1 cull: 2 cull: 3). - self assert: 3 equals: ([ :x :y :z | ] cull: 1 cull: 2 cull: 3). self should: [ [ :x :y :z :a | ] cull: 1 cull: 2 cull: 3 ] raise: Error. self should: [ [ :x :y :z :a :b | ] cull: 1 cull: 2 cull: 3 ] raise: Error. self assert: ([ 0 ] cull: 1 cull: 2 cull: 3) = 0. self assert: ([ :x | x ] cull: 1 cull: 2 cull: 3) = 1. self assert: ([ :x :y | y ] cull: 1 cull: 2 cull: 3) = 2. self assert: ([ :x :y :z | z ] cull: 1 cull: 2 cull: 3) = 3. ! Item was changed: ----- Method: BlockClosureTest>>testCullCullCullCull (in category 'tests - evaluating') ----- testCullCullCullCull self assert: nil equals: ([ ] cull: 1 cull: 2 cull: 3 cull: 4). + + self assert: nil equals: ([ :x | ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 1 equals: ([ :x | x ] cull: 1 cull: 2 cull: 3 cull: 4). + + self assert: nil equals: ([ :x :y | ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 1 equals: ([ :x :y | x ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 2 equals: ([ :x :y | y ] cull: 1 cull: 2 cull: 3 cull: 4). + + self assert: nil equals: ([ :x :y :z | ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 1 equals: ([ :x :y :z | x ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 2 equals: ([ :x :y :z | y ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 3 equals: ([ :x :y :z | z ] cull: 1 cull: 2 cull: 3 cull: 4). + + self assert: nil equals: ([ :x :y :z :a | ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 1 equals: ([ :x :y :z :a | x ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 2 equals: ([ :x :y :z :a | y ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 3 equals: ([ :x :y :z :a | z ] cull: 1 cull: 2 cull: 3 cull: 4). + self assert: 4 equals: ([ :x :y :z :a | a ] cull: 1 cull: 2 cull: 3 cull: 4). + - self assert: 1 equals: ([ :x | ] cull: 1 cull: 2 cull: 3 cull: 4). - self assert: 2 equals: ([ :x :y | ] cull: 1 cull: 2 cull: 3 cull: 4). - self assert: 3 equals: ([ :x :y :z | ] cull: 1 cull: 2 cull: 3 cull: 4). - self assert: 4 equals: ([ :x :y :z :a | ] cull: 1 cull: 2 cull: 3 cull: 4). self should: [ [ :x :y :z :a :b | ] cull: 1 cull: 2 cull: 3 cull: 4 ] raise: Error. self assert: ([ 0 ] cull: 1 cull: 2 cull: 3 cull: 4) = 0. self assert: ([ :x | x ] cull: 1 cull: 2 cull: 3 cull: 4) = 1. self assert: ([ :x :y | y ] cull: 1 cull: 2 cull: 3 cull: 4) = 2. self assert: ([ :x :y :z | z ] cull: 1 cull: 2 cull: 3 cull: 4) = 3. self assert: ([ :x :y :z :a | a ] cull: 1 cull: 2 cull: 3 cull: 4) = 4.! From asqueaker at gmail.com Thu Oct 30 18:27:11 2014 From: asqueaker at gmail.com (Chris Muller) Date: Thu Oct 30 18:27:14 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: Thanks guys, those both helped. After defining X I found I could do a "Smalltalk importSelf" to get it copied into the 'bindings' Dictionary. My image is only slightly old but now I see I can define a global just fine in a trunk image so maybe I'll try to see what the difference that it works there but not in mine if it happens again.. On Wed, Oct 29, 2014 at 5:06 PM, Nicolas Cellier wrote: > So after some digging i found those questions aimed at resolving failing > tests > > http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-May/178411.html > http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-April/177744.html > > If someone can propose partial answers, it will benefit to the environment > science > > 2014-10-29 20:21 GMT+01:00 Nicolas Cellier > : >> >> I've asked several questions about this a few months ago (dig squeak-dev >> if you wish, i'm in a hurry...) >> No answer. >> You made an effort to comment the classes, but Colin did completely change >> the implementation without updating the comment... >> Now who knows what's in the mind of the conceptor? >> It's like the fresh environment is abandonware... >> >> >> 2014-10-29 19:53 GMT+01:00 Chris Muller : >>> >>> Trying to debug a server, need to define a global OrderedCollection >>> "X" which I want to put debugging objects into. In a workspace, I >>> type: >>> >>> X := OrderedCollection new >>> >>> System asks me to correct or define a global. I choose to define a >>> global. >>> >>> But I still cannot access X. It keeps asking me to correct or define >>> a global. Yippee, great thing to happen at 4am when you just need to >>> debug something! >>> >>> Digging in shows that when I try to access X, it ends up looking in >>> Smalltalk environment 'bindings' IdentityDictionary, but when I >>> defined X, it put the binding #X=>nil into Smalltalk environment >>> 'declarations' only. >>> >>> I don't know what 'declarations' vs. 'bindings' are and I don't care, >>> I just need to be able to define the global, could someone pelase tell >>> me the proper fix? >>> >>> a) Defining X should put it in 'bindings' instead of 'declarations'? >>> b) Accessing X should access from 'declarations' instead of 'bindings'? >>> c) Defining X should put it in BOTH 'declarations' and 'bindings'? >>> >> > > > > From leves at elte.hu Thu Oct 30 22:28:24 2014 From: leves at elte.hu (Levente Uzonyi) Date: Thu Oct 30 22:28:30 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: On Thu, 30 Oct 2014, Chris Muller wrote: > Thanks guys, those both helped. After defining X I found I could do a > "Smalltalk importSelf" to get it copied into the 'bindings' > Dictionary. #importSelf is not what you want do, because that'll add the same policy to your environment again. Levente > > My image is only slightly old but now I see I can define a global just > fine in a trunk image so maybe I'll try to see what the difference > that it works there but not in mine if it happens again.. > > On Wed, Oct 29, 2014 at 5:06 PM, Nicolas Cellier > wrote: >> So after some digging i found those questions aimed at resolving failing >> tests >> >> http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-May/178411.html >> http://lists.squeakfoundation.org/pipermail/squeak-dev/2014-April/177744.html >> >> If someone can propose partial answers, it will benefit to the environment >> science >> >> 2014-10-29 20:21 GMT+01:00 Nicolas Cellier >> : >>> >>> I've asked several questions about this a few months ago (dig squeak-dev >>> if you wish, i'm in a hurry...) >>> No answer. >>> You made an effort to comment the classes, but Colin did completely change >>> the implementation without updating the comment... >>> Now who knows what's in the mind of the conceptor? >>> It's like the fresh environment is abandonware... >>> >>> >>> 2014-10-29 19:53 GMT+01:00 Chris Muller : >>>> >>>> Trying to debug a server, need to define a global OrderedCollection >>>> "X" which I want to put debugging objects into. In a workspace, I >>>> type: >>>> >>>> X := OrderedCollection new >>>> >>>> System asks me to correct or define a global. I choose to define a >>>> global. >>>> >>>> But I still cannot access X. It keeps asking me to correct or define >>>> a global. Yippee, great thing to happen at 4am when you just need to >>>> debug something! >>>> >>>> Digging in shows that when I try to access X, it ends up looking in >>>> Smalltalk environment 'bindings' IdentityDictionary, but when I >>>> defined X, it put the binding #X=>nil into Smalltalk environment >>>> 'declarations' only. >>>> >>>> I don't know what 'declarations' vs. 'bindings' are and I don't care, >>>> I just need to be able to define the global, could someone pelase tell >>>> me the proper fix? >>>> >>>> a) Defining X should put it in 'bindings' instead of 'declarations'? >>>> b) Accessing X should access from 'declarations' instead of 'bindings'? >>>> c) Defining X should put it in BOTH 'declarations' and 'bindings'? >>>> >>> >> >> >> >> > > From commits at source.squeak.org Thu Oct 30 23:32:31 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 30 23:32:33 2014 Subject: [squeak-dev] The Trunk: Kernel-nice.882.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.882.mcz ==================== Summary ==================== Name: Kernel-nice.882 Author: nice Time: 31 October 2014, 12:31:24.415 am UUID: 89313c71-97fc-41a3-b2b5-0fccac4b81c9 Ancestors: Kernel-nice.881 No need to query which selector isDoIt, because DoIt methods are not installed anymore in the methodDictionary (for a few years yet). =============== Diff against Kernel-nice.881 =============== Item was changed: ----- Method: Behavior>>unreferencedInstanceVariables (in category 'user interface') ----- unreferencedInstanceVariables "Return a list of the instance variables defined in the receiver which are not referenced in the receiver or any of its subclasses." + ^ self instVarNames select: - ^ self instVarNames reject: [:ivn | + self withAllSubclasses allSatisfy: + [:class | (class whichSelectorsAccess: ivn) isEmpty]]! - self withAllSubclasses anySatisfy: - [:class | (class whichSelectorsAccess: ivn) anySatisfy: - [:sel | sel isDoIt not]]]! From commits at source.squeak.org Thu Oct 30 23:55:02 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Thu Oct 30 23:55:03 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141030235502.4527.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007357.html Name: KernelTests-dtl.281 Ancestors: KernelTests-nice.280 Fix testCull methods to correspond to current behavior of block closures. Existing test failures were masked by test methods that required recompilation. Reference squeak-dev: Date: Sun, 26 Oct 2014 02:35:23 +0200 (CEST) From: Levente Uzonyi To: The general-purpose Squeak developers list Subject: Re: [squeak-dev] Why isn't BlockClosureTest>>testCull failing? I think that behavior was changed not too long ago (1-2 years maybe). If you decompile the method you'll see that it's actually self assert: 1 equals: ([:x | x] cull: 1). It's because Squeak used to return the value of the last argument if the block was empty, but had arguments. The code should be self assert: nil equals: ([ :x | ] cull: 1). Levente On Sat, 25 Oct 2014, David T. Lewis wrote: >If we have this: > [ :x | ] value: 1 ==> nil > >And this: > ([ :x | ] cull: 1) ==> nil > >But in BlockClosureTest>>testCull, we have this: > > self assert: 1 equals: ([ :x | ] cull: 1). > >The test passes. How is this possible? ============================================= http://lists.squeakfoundation.org/pipermail/packages/2014-October/007358.html Name: Kernel-nice.882 Ancestors: Kernel-nice.881 No need to query which selector isDoIt, because DoIt methods are not installed anymore in the methodDictionary (for a few years yet). ============================================= From commits at source.squeak.org Fri Oct 31 00:06:15 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 31 00:06:17 2014 Subject: [squeak-dev] The Trunk: Kernel.spur-nice.882.mcz Message-ID: Eliot Miranda uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel.spur-nice.882.mcz ==================== Summary ==================== Name: Kernel.spur-nice.882 Author: eem Time: 30 October 2014, 5:04:17.119 pm UUID: 2490972b-eac2-4c2e-83f3-2f022e23ce03 Ancestors: Kernel-nice.882, Kernel.spur-nice.881 Kernel-nice.882 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 No need to query which selector isDoIt, because DoIt methods are not installed anymore in the methodDictionary (for a few years yet). =============== Diff against Kernel-nice.882 =============== Item was changed: ----- Method: Behavior>>allInstances (in category 'accessing instances and variables') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + (inst == insts or: [inst == insts originalContents]) ifFalse: [insts nextPut: inst]. + inst := next]. + ^insts contents! - allInstances - "Answer a collection of all current instances of the receiver." - - | all | - all := OrderedCollection new. - self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. - ^ all asArray - ! Item was changed: ----- Method: Behavior>>allInstancesDo: (in category 'enumerating') ----- + allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst." - allInstancesDo: aBlock - "Evaluate the argument, aBlock, for each of the current instances of the - receiver. - - Because aBlock might change the class of inst (for example, using become:), - it is essential to compute next before aBlock value: inst." - | inst next | inst := self someInstance. + [inst == nil] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == nil] - whileFalse: - [ - next := inst nextInstance. - aBlock value: inst. - inst := next]! Item was added: + ----- Method: Behavior>>allInstancesOrNil (in category 'enumerating') ----- + allInstancesOrNil + "Answer all instances of the receiver, or nil if the primitive + fails, which it may be due to being out of memory." + + ^nil! Item was changed: ----- Method: Behavior>>basicNew (in category 'instance creation') ----- basicNew "Primitive. Answer an instance of the receiver (which is a class) with no + indexable variables. Fail if the class is indexable. Essential. See Object + documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run + before the method is activated. Check that space was low and retry + via handleFailingBasicNew if so." - indexable variables. Fail if the class is indexable. Essential. See Object - documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew]. + self isVariable ifTrue: [^self basicNew: 0]. + self primitiveFailed! - - self isVariable ifTrue: [ ^ self basicNew: 0 ]. - "space must be low" - OutOfMemory signal. - ^ self basicNew "retry if user proceeds" - ! Item was changed: ----- Method: Behavior>>basicNew: (in category 'instance creation') ----- + basicNew: sizeRequested + "Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive. + + If the primitive fails because space is low then the scavenger will run before the + method is activated. Check args and retry via handleFailingBasicNew: if they're OK." - basicNew: sizeRequested - "Primitive. Answer an instance of this class with the number - of indexable variables specified by the argument, sizeRequested. - Fail if this class is not indexable or if the argument is not a - positive Integer, or if there is not enough memory available. - Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingBasicNew: sizeRequested]. - self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. - (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: - ["arg okay; space must be low." - OutOfMemory signal. - ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstance (in category 'accessing instances and variables') ----- + byteSizeOfInstance + "Answer the total memory size of an instance of the receiver." + + + self isVariable ifTrue: + [^self byteSizeOfInstanceOfSize: 0]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>byteSizeOfInstanceOfSize: (in category 'accessing instances and variables') ----- + byteSizeOfInstanceOfSize: basicSize + "Answer the total memory size of an instance of the receiver + with the given number of indexable instance variables." + + + self isVariable + ifTrue: "If the primitive overflowed answer a close approximation" + [(basicSize isInteger + and: [basicSize >= 16r1000000]) ifTrue: + [^2 * (self byteSizeOfInstanceOfSize: basicSize + 1 // 2) + - (self byteSizeOfInstanceOfSize: 0)]] + ifFalse: + [basicSize = 0 ifTrue: + [^self byteSizeOfInstance]]. + self primitiveFailed! Item was added: + ----- Method: Behavior>>elementSize (in category 'accessing instances and variables') ----- + elementSize + "Answer the size in bytes of an element in the receiver. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + instSpec < 9 ifTrue: [^Smalltalk wordSize]. + instSpec >= 16 ifTrue: [^1]. + instSpec >= 12 ifTrue: [^2]. + instSpec >= 10 ifTrue: [^4]. + ^8! Item was added: + ----- Method: Behavior>>handleFailingBasicNew (in category 'private') ----- + handleFailingBasicNew + "handleFailingBasicNew gets sent after basicNew has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew. If + handleFailingBasicNew fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + Smalltalk garbageCollect < 1048576 ifTrue: + [Smalltalk growMemoryByAtLeast: 1048576]. + ^self handleFailingFailingBasicNew "retry after global garbage collect"! Item was added: + ----- Method: Behavior>>handleFailingBasicNew: (in category 'private') ----- + handleFailingBasicNew: sizeRequested + "handleFailingBasicNew: gets sent after basicNew: has failed and allowed + a scavenging garbage collection to occur. The scavenging collection + will have happened as the VM is activating the (failing) basicNew:. If + handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := self byteSizeOfInstanceOfSize: sizeRequested. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingBasicNew: sizeRequested! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew (in category 'private') ----- + handleFailingFailingBasicNew + "This basicNew gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low" + OutOfMemory signal. + ^self basicNew "retry if user proceeds"! Item was added: + ----- Method: Behavior>>handleFailingFailingBasicNew: (in category 'private') ----- + handleFailingFailingBasicNew: sizeRequested + "This basicNew: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails + then the system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable + variables specified by the argument, sizeRequested. Fail if this class is not + indexable or if the argument is not a positive Integer, or if there is not + enough memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + ^self basicNew: sizeRequested "retry if user proceeds"! Item was added: + ----- Method: Behavior>>identityHash (in category 'comparing') ----- + identityHash + "Answer a SmallInteger whose value is related to the receiver's identity. + Behavior implements identityHash to allow the VM to use an object representation which + does not include a direct reference to an object's class in an object. If the VM is using + this implementation then classes are held in a class table and instances contain the index + of their class in the table. A class's class table index is its identityHash so that an instance + can be created without searching the table for a class's index. The VM uses this primitive + to enter the class into the class table, assigning its identityHash with an as yet unused + class table index. If this primitive fails it means that the class table is full. In Spur as of + 2014 there are 22 bits of classTable index and 22 bits of identityHash per object. + + Primitive. Essential. Do not override. See Object documentation whatIsAPrimitive." + + + self primitiveFailed! Item was changed: ----- Method: Behavior>>indexIfCompact (in category 'private') ----- indexIfCompact + "Backward compatibility with the Squeak V3 object format. + Spur does not have a distinction between compact and non-compact classes." + ^0! - "If these 5 bits are non-zero, then instances of this class - will be compact. It is crucial that there be an entry in - Smalltalk compactClassesArray for any class so optimized. - See the msgs becomeCompact and becomeUncompact." - ^ (format bitShift: -11) bitAnd: 16r1F - " - Smalltalk compactClassesArray doWithIndex: - [:c :i | c == nil ifFalse: - [c indexIfCompact = i ifFalse: [self halt]]] - "! Item was changed: ----- Method: Behavior>>instSize (in category 'testing') ----- instSize "Answer the number of named instance variables + (as opposed to indexed variables) of the receiver. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size>" + ^format bitAnd: 16rFFFF! - (as opposed to indexed variables) of the receiver." - - self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - When we revise the image format, it should become... - ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 - Note also that every other method in this category will require - 2 bits more of right shift after the change. - " - ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! Item was changed: ----- Method: Behavior>>instSpec (in category 'testing') ----- instSpec + "Answer the instance specification part of the format that defines what kind of object + an instance of the receiver is. The formats are + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^(format bitShift: -16) bitAnd: 16r1F! - ^ (format bitShift: -7) bitAnd: 16rF! Item was changed: ----- Method: Behavior>>isBits (in category 'testing') ----- isBits + "Answer whether the receiver contains just bits (not pointers). + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 7! - "Answer whether the receiver contains just bits (not pointers)." - - ^ self instSpec >= 6! Item was changed: ----- Method: Behavior>>isBytes (in category 'testing') ----- isBytes + "Answer whether the receiver has 8-bit instance variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + ^self instSpec >= 16! - "Answer whether the receiver has 8-bit instance variables." - - ^ self instSpec >= 8! Item was added: + ----- Method: Behavior>>isEphemeronClass (in category 'testing') ----- + isEphemeronClass + "Answer whether the receiver has ephemeral instance variables. The garbage collector will + fire (queue for finalization) any ephemeron whose first instance variable is not referenced + other than from the transitive closure of references from ephemerons. Hence referring to + an object from the first inst var of an ephemeron will cause the ephemeron to fire when + the rest of the system does not refer to the object and that object is ready to be collected. + Since references from the remaining inst vars of an ephemeron will not prevent the ephemeron + from firing, ephemerons may act as the associations in weak dictionaries such that the value + (e.g. properties attached to the key) will not prevent firing when the key is no longer referenced + other than from ephemerons. Ephemerons can therefore be used to implement instance-based + pre-mortem finalization." + ^self instSpec = 5! Item was added: + ----- Method: Behavior>>isImmediateClass (in category 'testing') ----- + isImmediateClass + "Answer whether the receiver has immediate instances. Immediate instances + store their value in their object pointer, not in an object body. Hence immediates + take no space and are immutable. The immediates are distinguished by tag bits + in the pointer. They include SmallIntegers and Characters. Hence in the 32-bit + system SmallIntegers are 31-bit signed integers and Characters are 30-bit + unsigned character codes." + ^self instSpec = 7! Item was changed: ----- Method: Behavior>>isVariable (in category 'testing') ----- isVariable + "Answer whether the receiver has indexable variables. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | + instSpec := self instSpec. + ^instSpec >= 2 and: [instSpec <= 4 or: [instSpec >= 9]]! - "Answer whether the receiver has indexable variables." - - ^ self instSpec >= 2! Item was changed: ----- Method: Behavior>>kindOfSubclass (in category 'testing class hierarchy') ----- kindOfSubclass + "Answer a String that is the keyword that describes the receiver's kind of subclass, + either a regular subclass, a variableSubclass, a variableByteSubclass, + a variableWordSubclass, a weakSubclass, an ephemeronSubclass or an immediateSubclass. + c.f. typeOfClass" + ^self isVariable + ifTrue: + [self isBits + ifTrue: + [self isBytes + ifTrue: [' variableByteSubclass: '] + ifFalse: [' variableWordSubclass: ']] + ifFalse: + [self isWeak + ifTrue: [' weakSubclass: '] + ifFalse: [' variableSubclass: ']]] + ifFalse: + [self isImmediateClass + ifTrue: [' immediateSubclass: '] + ifFalse: + [self isEphemeronClass + ifTrue: [' ephemeronSubclass: '] + ifFalse: [' subclass: ']]]! - "Answer a String that is the keyword that describes the receiver's kind - of subclass, either a regular subclass, a variableSubclass, a - variableByteSubclass, a variableWordSubclass, or a weakSubclass." - self isWeak - ifTrue: [^ ' weakSubclass: ']. - ^ self isVariable - ifTrue: [self isBits - ifTrue: [self isBytes - ifTrue: [ ' variableByteSubclass: '] - ifFalse: [ ' variableWordSubclass: ']] - ifFalse: [ ' variableSubclass: ']] - ifFalse: [ ' subclass: ']! Item was changed: ----- Method: Behavior>>shouldNotBeRedefined (in category 'testing') ----- shouldNotBeRedefined + "Answer if the receiver should not be redefined. + The assumption is that classes in Smalltalk specialObjects and + instance-specific Behaviors should not be redefined" - "Return true if the receiver should not be redefined. - The assumption is that compact classes, - classes in Smalltalk specialObjects and - Behaviors should not be redefined" + ^(Smalltalk specialObjectsArray + identityIndexOf: self + ifAbsent: [(self isKindOf: self) ifTrue: [1] ifFalse: [0]]) ~= 0! - ^(Smalltalk compactClassesArray includes: self) - or:[(Smalltalk specialObjectsArray includes: self) - or:[self isKindOf: self]]! Item was changed: ----- Method: Behavior>>typeOfClass (in category 'accessing') ----- typeOfClass + "Answer a symbol uniquely describing the type of the receiver. c.f. kindOfSubclass" + self isBytes ifTrue: + [^self instSpec = CompiledMethod instSpec + ifTrue: [#compiledMethod] "Very special!!" + ifFalse: [#bytes]]. + (self isWords and: [self isPointers not]) ifTrue: + [^self instSpec = SmallInteger instSpec + ifTrue: [#immediate] "Very special!!" + ifFalse: [#words]]. + self isWeak ifTrue: [^#weak]. + self isVariable ifTrue: [^#variable]. + self isEphemeronClass ifTrue: [^#ephemeron]. + ^#normal! - "Answer a symbol uniquely describing the type of the receiver" - self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" - self isBytes ifTrue:[^#bytes]. - (self isWords and:[self isPointers not]) ifTrue:[^#words]. - self isWeak ifTrue:[^#weak]. - self isVariable ifTrue:[^#variable]. - ^#normal.! Item was changed: ----- Method: BlockClosure>>simulateValueWithArguments:caller: (in category 'system simulation') ----- simulateValueWithArguments: anArray caller: aContext + "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity." | newContext sz | - (anArray class ~~ Array - or: [numArgs ~= anArray size]) ifTrue: - [^ContextPart primitiveFailTokenFor: nil]. newContext := (MethodContext newForMethod: outerContext method) setSender: aContext receiver: outerContext receiver method: outerContext method closure: self startpc: startpc. + ((newContext objectClass: anArray) ~~ Array + or: [numArgs ~= anArray size]) ifTrue: + [^ContextPart primitiveFailTokenFor: nil]. sz := self basicSize. newContext stackp: sz + numArgs. 1 to: numArgs do: [:i| newContext at: i put: (anArray at: i)]. 1 to: sz do: [:i| newContext at: i + numArgs put: (self at: i)]. ^newContext! Item was added: + ----- Method: Class>>immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'subclass creation') ----- + immediateSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a new + immediate class as a subclass of an existing class (the receiver)." + ^ClassBuilder new + superclass: self + immediateSubclass: t + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>computeFormat:instSize:forSuper:ccIndex: (in category 'class format') ----- computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. + Answer the format or nil if there is any problem." - Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | type == #compiledMethod ifTrue: + [newInstSize > 0 ifTrue: + [self error: 'A compiled method class cannot have named instance variables'. + ^nil]. + ^CompiledMethod format]. - [^(CompiledMethod format - bitClear: (16r1F bitShift: 11)) - bitOr: (ccIndex bitShift: 11)]. instSize := newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). + instSize > 65535 ifTrue: - instSize > 254 ifTrue: [self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #normal ifTrue:[isVar := isWeak := false. isWords := isPointers := true]. type == #bytes ifTrue:[isVar := true. isWords := isPointers := isWeak := false]. type == #words ifTrue:[isVar := isWords := true. isPointers := isWeak := false]. type == #variable ifTrue:[isVar := isPointers := isWords := true. isWeak := false]. type == #weak ifTrue:[isVar := isWeak := isWords := isPointers := true]. + type == #ephemeron ifTrue:[isVar := false. isWeak := isWords := isPointers := true]. + type == #immediate ifTrue:[isVar := isWeak := isPointers := false. isWords := true]. + (isPointers not and: [instSize > 0]) ifTrue: + [self error: 'A non-pointer class cannot have named instance variables'. - (isPointers not and:[instSize > 0]) ifTrue: - [self error:'A non-pointer class cannot have instance variables'. ^nil]. + ^self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak! - ^(self format: instSize - variable: isVar - words: isWords - pointers: isPointers - weak: isWeak) + (ccIndex bitShift: 11).! Item was changed: ----- Method: ClassBuilder>>format:variable:words:pointers:weak: (in category 'class format') ----- + format: nInstVars variable: isVar words: is32BitWords pointers: isPointers weak: isWeak + "Compute the format for the given instance specfication. + Above Cog Spur the class format is + <5 bits inst spec><16 bits inst size> + where the 5-bit inst spec is + 0 = 0 sized objects (UndefinedObject True False et al) + 1 = non-indexable objects with inst vars (Point et al) + 2 = indexable objects with no inst vars (Array et al) + 3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al) + 4 = weak indexable objects with inst vars (WeakArray et al) + 5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron) + 6 = unused + 7 = immediates (SmallInteger, Character) + 8 = unused + 9 = reserved for 64-bit indexable + 10-11 = 32-bit indexable (Bitmap) + 12-15 = 16-bit indexable + 16-23 = 8-bit indexable + 24-31 = compiled methods (CompiledMethod)" + | instSpec | - format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak - "Compute the format for the given instance specfication." - | cClass instSpec sizeHiBits fmt | - self flag: #instSizeChange. - " - Smalltalk browseAllCallsOn: #instSizeChange. - Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. - Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. - " - " - NOTE: This code supports the backward-compatible extension to 8 bits of instSize. - For now the format word is... - <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> - But when we revise the image format, it should become... - <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> - " - sizeHiBits := (nInstVars+1) // 64. - cClass := 0. "for now" instSpec := isWeak + ifTrue: + [isVar + ifTrue: [4] + ifFalse: [5]] + ifFalse: + [isPointers + ifTrue: + [isVar + ifTrue: [nInstVars > 0 ifTrue: [3] ifFalse: [2]] + ifFalse: [nInstVars > 0 ifTrue: [1] ifFalse: [0]]] + ifFalse: + [isVar + ifTrue: [is32BitWords ifTrue: [10] ifFalse: [16]] + ifFalse: [7]]]. + ^(instSpec bitShift: 16) + nInstVars! - ifTrue:[4] - ifFalse:[isPointers - ifTrue: [isVar - ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] - ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] - ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. - fmt := sizeHiBits. - fmt := (fmt bitShift: 5) + cClass. - fmt := (fmt bitShift: 4) + instSpec. - fmt := (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" - fmt := (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" - ^fmt! Item was added: + ----- Method: ClassBuilder>>superclass:immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: (in category 'public') ----- + superclass: aClass + immediateSubclass: t instanceVariableNames: f + classVariableNames: d poolDictionaries: s category: cat + "This is the standard initialization message for creating a + new immediate class as a subclass of an existing class." + | env | + aClass instSize > 0 + ifTrue: [^self error: 'cannot make an immediate subclass of a class with named fields']. + aClass isVariable + ifTrue: [^self error: 'cannot make an immediate subclass of a class with indexed instance variables']. + aClass isPointers + ifFalse: [^self error: 'cannot make an immediate subclass of a class without pointer fields']. + "Cope with pre-environment and environment versions. Simplify asap." + env := (Smalltalk classNamed: #EnvironmentRequest) + ifNil: [aClass environment] + ifNotNil: [:erc| erc signal ifNil: [aClass environment]]. + ^self + name: t + inEnvironment: env + subclassOf: aClass + type: #immediate + instanceVariableNames: f + classVariableNames: d + poolDictionaries: s + category: cat! Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" - "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. - We can rely on two assumptions (which are critical): - #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) - #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. - Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. - " | meta | meta := oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." - [ - "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). - Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "make sure that the VM cache is clean" oldClass methodDict do: [:cm | cm flushCache]. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue: [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. oldClass updateMethodBindingsTo: oldClass binding. oldClass class updateMethodBindingsTo: oldClass class binding]. + "eem 5/31/2014 07:22 At this point there used to be a garbage collect whose purpose was + to ensure no old instances existed after the becomeForward:. Without the GC it was possible + to resurrect old instances using e.g. allInstancesDo:. This was because the becomeForward: + updated references from the old objects to new objects but didn't destroy the old objects. + But as of late 2013/early 2014 becomeForward: has been modified to free all the old objects."] + valueUnpreemptively! - Smalltalk garbageCollect. - - "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). - - The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: - - On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. - - Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). - - Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. - - Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." - - ] valueUnpreemptively. - ! Item was changed: ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame' poolDictionaries: '' category: 'Kernel-Methods'! + !CompiledMethod commentStamp: 'eem 8/12/2014 14:45' prior: 0! + CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. - !CompiledMethod commentStamp: 'eem 5/12/2014 18:02' prior: 0! - My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. I'm a subclass of ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray. Class variables: SmallFrame - the number of stack slots in a small frame Context LargeFrame - the number of stack slots in a large frame Context PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set The current format of a CompiledMethod is as follows: header (4 or 8 bytes, SmallInteger) + literals (4 or 8 bytes each, Object, see "The last literal..." below) - literals (4 or 8 bytes each, Object) bytecodes (variable, bytes) trailer (variable, bytes) + The header is a 31-bit signed integer (a SmallInteger) in the following format: - The header is a 31-bit signed integer (a SmallInteger) with one of the two following formats, selected by the sign bit: - sign bit 0, header >= 0: - (index 0) 9 bits: main part of primitive number (#primitive) - (index 9) 8 bits: number of literals (#numLiterals) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) - (index 18) 6 bits: number of temporary variables (#numTemps) - (index 24) 4 bits: number of arguments to the method (#numArgs) - (index 28) 1 bit: high-bit of primitive number (#primitive) - (index 29) 1 bit: flag bit, ignored by the VM (#flag) - (index 30/63) sign bit: 0 selects the Primary instruction set (#signFlag) - sign bit 1, header < 0: (index 0) 16 bits: number of literals (#numLiterals) (index 16) 1 bit: has primitive + (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame) - (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) + (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag). + (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4, 0 selects the primary instruction set, e.g. SqueakV3PlusClosures) (#signFlag) - (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public) - (index 30/63) sign bit: 1 selects the Secondary instruction set (e.g. NewsqueakV4) (#signFlag) - i.e. the Secondary Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode. + If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. + + The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer. + + The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be left nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.! - The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.! Item was added: + ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') ----- + handleFailingFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after handleFailingBasicNew: has done a full + garbage collection and possibly grown memory. If this basicNew: fails then the + system really is low on space, so raise the OutOfMemory signal. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + "space must be low." + OutOfMemory signal. + "retry if user proceeds" + ^self newMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') ----- + handleFailingNewMethod: numberOfBytes header: headerWord + "This newMethod:header: gets sent after newMethod:header: has failed + and allowed a scavenging garbage collection to occur. The scavenging + collection will have happened as the VM is activating the (failing) basicNew:. + If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient + space and a global garbage collection is required. Retry after garbage + collecting and growing memory if necessary. + + Primitive. Answer an instance of this class with the number of indexable variables + specified by the argument, headerWord, and the number of bytecodes specified + by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes + is negative, or if the receiver is not a CompiledMethod class, or if there is not enough + memory available. Essential. See Object documentation whatIsAPrimitive." + + + | bytesRequested | + bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16. + Smalltalk garbageCollect < bytesRequested ifTrue: + [Smalltalk growMemoryByAtLeast: bytesRequested]. + "retry after global garbage collect and possible grow" + ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord! Item was added: + ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') ----- + installPrimaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was added: + ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') ----- + installSecondaryBytecodeSet: aBytecodeEncoderSubclass + PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue: + [^self]. + (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse: + [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder']. + (self allSubInstances + detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]] + ifNone: []) ifNotNil: + [Warning signal: 'There are existing CompiledMethods with a different encoderClass.']. + SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. - primBits := primitiveIndex <= 16r1FF - ifTrue: [primitiveIndex] - ifFalse: ["For now the high bit of primitive no. is in the 29th bit of header" - primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large']. - (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits! Item was changed: ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') ----- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." + | method pc | + nArgs > 15 ifTrue: + [^self error: 'Cannot compile -- too many arguments']. - | largeBit primBits flagBit | nTemps > 63 ifTrue: + [^self error: 'Cannot compile -- too many temporary variables']. + nLits > 65535 ifTrue: + [^self error: 'Cannot compile -- too many literals']. - [^ self error: 'Cannot compile -- too many temporary variables']. - nLits > 255 ifTrue: - [^ self error: 'Cannot compile -- too many literals']. - largeBit := (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. + method := trailer + createMethod: numberOfBytes + class: self + header: (nArgs bitShift: 24) + + (nTemps bitShift: 18) + + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0]) + + nLits + + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]) + + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]). + primitiveIndex > 0 ifTrue: + [pc := method initialPC. + method + at: pc + 0 put: method encoderClass callPrimitiveCode; + at: pc + 1 put: (primitiveIndex bitAnd: 16rFF); + at: pc + 2 put: (primitiveIndex bitShift: -8)]. + ^method! - "For now the high bit of the primitive no. is in a high bit of the header" - primBits := (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19). - - flagBit := flag ifTrue: [ 1 ] ifFalse: [ 0 ]. - - ^trailer - createMethod: numberOfBytes - class: self - header: (nArgs bitShift: 24) + - (nTemps bitShift: 18) + - (largeBit bitShift: 17) + - (nLits bitShift: 9) + - primBits + - (flagBit bitShift: 29)! Item was changed: ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') ----- + newMethod: numberOfBytes header: headerWord - newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other + information) is specified by the headerWord (see my class comment). + The first argument specifies the number of fields for bytecodes in the + method. Fail if either argument is not a SmallInteger, or if numberOfBytes + is negative, or if memory is low. Once the header of a method is set by + this primitive, it cannot be changed to change the number of literals. + Essential. See Object documentation whatIsAPrimitive." - information) is specified the headerWord. The first argument specifies - the number of fields for bytecodes in the method. Fail if either - argument is not a SmallInteger, or if numberOfBytes is negative. Once - the header of a method is set by this primitive, it cannot be changed in - any way. Essential. See Object documentation whatIsAPrimitive." + + ec == #'insufficient object memory' ifTrue: + [^self handleFailingNewMethod: numberOfBytes header: headerWord]. - - (numberOfBytes isInteger and: - [headerWord isInteger and: - [numberOfBytes >= 0]]) ifTrue: [ - "args okay; space must be low" - OutOfMemory signal. - "retry if user proceeds" - ^ self newMethod: numberOfBytes header: headerWord - ]. ^self primitiveFailed! Item was changed: ----- Method: CompiledMethod class>>toReturnConstant:trailerBytes: (in category 'instance creation') ----- toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 + index - ! Item was changed: ----- Method: CompiledMethod class>>toReturnField:trailerBytes: (in category 'instance creation') ----- toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 264 + field - ! Item was changed: ----- Method: CompiledMethod class>>toReturnSelfTrailerBytes: (in category 'instance creation') ----- toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." + ^self newBytes: 3 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256! - ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 2 primitive: 256 - ! Item was added: + ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') ----- + bytecodeSetName + ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''! Item was changed: ----- Method: CompiledMethod>>headerDescription (in category 'literals') ----- headerDescription + "Answer a description containing the information about the form of the + receiver and the form of the context needed to run the receiver." - "Answer a description containing the information about the form of the - receiver and the form of the context needed to run the receiver." + ^(ByteString new: 128) writeStream + print: self header; cr; + nextPutAll: '"primitive: '; print: self primitive; cr; + nextPutAll: ' numArgs: '; print: self numArgs; cr; + nextPutAll: ' numTemps: '; print: self numTemps; cr; + nextPutAll: ' numLiterals: '; print: self numLiterals; cr; + nextPutAll: ' frameSize: '; print: self frameSize; cr; + nextPutAll: ' bytecodeSet: '; nextPutAll: self bytecodeSetName; + nextPut: $"; cr; + contents! - | s | - s := '' writeStream. - self header printOn: s. - s cr; nextPutAll: '"primitive: '. - self primitive printOn: s. - s cr; nextPutAll: ' numArgs: '. - self numArgs printOn: s. - s cr; nextPutAll: ' numTemps: '. - self numTemps printOn: s. - s cr; nextPutAll: ' numLiterals: '. - self numLiterals printOn: s. - s cr; nextPutAll: ' frameSize: '. - self frameSize printOn: s. - s cr; nextPutAll: ' isClosureCompiled: '. - self isBlueBookCompiled not printOn: s. - s nextPut: $"; cr. - ^ s contents! Item was changed: ----- Method: CompiledMethod>>numLiterals (in category 'accessing') ----- numLiterals "Answer the number of literals used by the receiver." + ^self header bitAnd: 65535! - | header | - ^(header := self header) < 0 - ifTrue: [header bitAnd: 65535] - ifFalse: [(header bitShift: -9) bitAnd: 16rFF]! Item was changed: ----- Method: CompiledMethod>>primitive (in category 'accessing') ----- primitive "Answer the primitive index associated with the receiver. + Zero indicates that this is not a primitive method." + | initialPC | + ^(self header anyMask: 65536) "Is the hasPrimitive? flag set?" + ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] + ifFalse: [0]! - Zero indicates that this is not a primitive method. - In the original header format we currently allow 10 bits of primitive index, but they are - in two places for backward compatibility. In the new format the primitive index is in the - last two bytes of a three byte callPrimitive: bytecode. The time to unpack is negligible, - since the derived primitive function pointer full index is stored in the method cache." - | header initialPC | - ^(header := self header) < 0 - ifTrue: - [(header anyMask: 65536) "Is the hasPrimitive? flag set?" - ifTrue: [(self at: (initialPC := self initialPC) + 1) + ((self at: initialPC + 2) bitShift: 8)] - ifFalse: [0]] - ifFalse: - [(header bitAnd: 16r1FF) + ((header bitShift: -19) bitAnd: 16r200)]! Item was changed: ----- Method: ContextPart>>activateReturn:value: (in category 'private') ----- activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" + ^MethodContext + sender: self - ^ self - activateMethod: ContextPart theReturnMethod - withArgs: {value} receiver: aContext + method: MethodContext theReturnMethod + arguments: {value}! - class: aContext class! Item was changed: ----- Method: ContextPart>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments + "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and + arguments are given as arguments to this message. If successful, push result and return + resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes + execution needs to be intercepted and simulated to avoid execution running away." - "Simulate a primitive method whose index is primitiveIndex. The - simulated receiver and arguments are given as arguments to this message. - If successful, push result and return resuming context, else ^ PrimitiveFailToken. - Any primitive which provokes execution needs to be intercepted and simulated - to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug + interesting code, such as the debugger itself. hence use primitive 19 with care :-)" - interesting code, such as the debugger itself. hence use primtiive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ToolSet debugContext: self label:'Code simulation error' contents: nil]. + ((primitiveIndex between: 201 and: 222) + and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: + [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" + or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" + [^receiver simulateValueWithArguments: arguments caller: self]. + primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" + [^receiver simulateValueWithArguments: arguments first caller: self]]. - "ContextPart>>blockCopy:; simulated to get startpc right" - (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) - ifTrue: [^self push: ((BlockContext newForMethod: receiver method) - home: receiver home - startpc: pc + 2 - nargs: (arguments at: 1))]. - (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]" - ifTrue: [^receiver pushArgs: arguments from: self]. - (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:" - ifTrue: [^receiver pushArgs: arguments first from: self]. - primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]" - ifTrue: [^self send: arguments first - to: receiver - with: arguments allButFirst - super: false]. - primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: nil]. - primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" - ifTrue: [^self send: arguments first - to: receiver - with: (arguments at: 2) - startClass: (arguments at: 3)]. + primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [^self send: arguments first to: receiver with: arguments allButFirst super: false]. + primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. + primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. + "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| active effective | active := Processor activeProcess. effective := active effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. + ^(self isPrimFailToken: value) - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]]. + primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" - ((primitiveIndex = 188 or: [primitiveIndex = 189]) "eem 10/6/2014 16:14 Object>>with:*executeMethod:" - and: [arguments last isQuick not]) ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:" [^MethodContext sender: self receiver: receiver + method: (arguments at: 2) + arguments: (arguments at: 1)]. - method: arguments last - arguments: (primitiveIndex = 188 - ifTrue: [arguments at: 1] - ifFalse: [arguments allButLast])]. "Closure primitives" (primitiveIndex = 200 and: [self == receiver]) ifTrue: "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right" [^self push: (BlockClosure outerContext: receiver startpc: pc + 2 numArgs: arguments first copiedValues: arguments last)]. - ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]" - or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]" - [^receiver simulateValueWithArguments: arguments caller: self]. - primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:" - [^receiver simulateValueWithArguments: arguments first caller: self]. primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 2 and: [arguments first isInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^ContextPart primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] + ifFalse: [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. + + ^(self isPrimFailToken: value) - ifFalse: - [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. - ^((self objectClass: value) == Array - and: [value size = 2 - and: [value first == PrimitiveFailToken]]) ifTrue: [value] ifFalse: [self push: value]! Item was added: + ----- Method: ContextPart>>isPrimFailToken: (in category 'private') ----- + isPrimFailToken: anObject + ^(self objectClass: anObject) == Array + and: [anObject size = 2 + and: [anObject first == PrimitiveFailToken]]! Item was added: + ----- Method: ContextPart>>send:to:with:lookupIn: (in category 'controlling') ----- + send: selector to: rcvr with: arguments lookupIn: lookupClass + "Simulate the action of sending a message with selector and arguments + to rcvr. The argument, lookupClass, is the class in which to lookup the + message. This is the receiver's class for normal messages, but for super + messages it will be some specific class related to the source method." + + | meth primIndex val ctxt | + (meth := lookupClass lookupSelector: selector) ifNil: + [^self send: #doesNotUnderstand: + to: rcvr + with: {Message selector: selector arguments: arguments} + lookupIn: lookupClass]. + (primIndex := meth primitive) > 0 ifTrue: + [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments. + (self isPrimFailToken: val) ifFalse: + [^val]]. + (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue: + [^self error: 'Simulated message ', arguments first selector, ' not understood']. + ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments. + primIndex > 0 ifTrue: + [ctxt failPrimitiveWith: val]. + ^ctxt! Item was changed: ----- Method: ContextPart>>send:to:with:super: (in category 'controlling') ----- + send: selector to: rcvr with: arguments super: superFlag + "Simulate the action of sending a message with selector arguments + to rcvr. The argument, superFlag, tells whether the receiver of the + message was specified with 'super' in the source method." - send: selector to: rcvr with: args super: superFlag - "Simulate the action of sending a message with selector, selector, and - arguments, args, to receiver. The argument, superFlag, tells whether the - receiver of the message was specified with 'super' in the source method." + ^self send: selector + to: rcvr + with: arguments + lookupIn: (superFlag + ifTrue: [self method methodClassAssociation value superclass] + ifFalse: [self objectClass: rcvr])! - | class meth val ctxt | - class := superFlag - ifTrue: [self method methodClassAssociation value superclass] - ifFalse: [self objectClass: rcvr]. - meth := class lookupSelector: selector. - meth == nil ifTrue: - [^self - send: #doesNotUnderstand: - to: rcvr - with: (Array with: (Message selector: selector arguments: args)) - super: superFlag]. - val := self tryPrimitiveFor: meth receiver: rcvr args: args. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken]]) ifFalse: - [^val]. - (selector == #doesNotUnderstand: - and: [class == ProtoObject]) ifTrue: - [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood']. - ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class. - ((self objectClass: val) == Array - and: [val size = 2 - and: [val first == PrimitiveFailToken - and: [val last notNil - and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue: - [ctxt at: ctxt stackPtr put: val last]. - ^ctxt! Item was changed: ----- Method: ContextPart>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') ----- tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments + "Invoke the named primitive for aCompiledMethod, answering its result, or, + if the primiitve fails, answering the error code." - | selector theMethod spec receiverClass | ec ifNotNil: ["If ec is an integer other than -1 there was a problem with primitive 218, not with the external primitive itself. -1 indicates a generic failure (where ec should be nil) but ec = nil means primitive 218 is not implemented. So interpret -1 to mean the external primitive failed with a nil error code." ec isInteger ifTrue: [ec = -1 ifTrue: [ec := nil] + ifFalse: [self primitiveFailed]]]. + ^self class primitiveFailTokenFor: ec! - ifFalse: [self primitiveFailed]]. - ^{PrimitiveFailToken. ec}]. - "Assume a nil error code implies the primitive is not implemented and fall back on the old code." - "Hack. Attempt to execute the named primitive from the given compiled method" - arguments size > 8 ifTrue: - [^{PrimitiveFailToken. nil}]. - selector := #( - tryNamedPrimitive - tryNamedPrimitive: - tryNamedPrimitive:with: - tryNamedPrimitive:with:with: - tryNamedPrimitive:with:with:with: - tryNamedPrimitive:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with: - tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. - receiverClass := self objectClass: aReceiver. - theMethod := receiverClass lookupSelector: selector. - theMethod == nil ifTrue: - [^{PrimitiveFailToken. nil}]. - spec := theMethod literalAt: 1. - spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. - Smalltalk unbindExternalPrimitives. - ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass! Item was added: + ----- Method: InstructionClient>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: pimIndex + "V3PlusClosures: 139 10001011 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + NewsqueakV4: 249 11111001 iiiiiiii jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256) + SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + ( jjjjjjj * 256) + m=1 means inlined primitive, no hard return after execution."! Item was added: + ----- Method: InstructionPrinter>>callPrimitive: (in category 'instruction decoding') ----- + callPrimitive: index + "Print the callPrimitive." + + self print: 'callPrimtive: ' , index printString! Item was changed: ----- Method: InstructionStream>>interpretV3ClosuresExtension:in:for: (in category 'decoding - private - v3 plus closures') ----- interpretV3ClosuresExtension: offset in: method for: client | type offset2 byte2 byte3 byte4 | offset <= 6 ifTrue: ["Extended op codes 128-134" byte2 := method at: pc. pc := pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type := byte2 // 64. offset2 := byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^client pushReceiverVariable: offset2]. type = 1 ifTrue: [^client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 := method at: pc. pc := pc + 1. type := byte2 // 32. type = 0 ifTrue: [^client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^client pushReceiverVariable: byte3]. type = 3 ifTrue: [^client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^client doPop]. offset = 8 ifTrue: [^client doDup]. offset = 9 ifTrue: [^client pushActiveContext]. byte2 := method at: pc. pc := pc + 1. offset = 10 ifTrue: [^byte2 < 128 ifTrue: [client pushNewArrayOfSize: byte2] ifFalse: [client pushConsArrayWithElements: byte2 - 128]]. - offset = 11 ifTrue: [^self unusedBytecode: client at: pc - 1]. byte3 := method at: pc. pc := pc + 1. + offset = 11 ifTrue: [^client callPrimitive: byte2 + (byte3 bitShift: 8)]. offset = 12 ifTrue: [^client pushRemoteTemp: byte2 inVectorAt: byte3]. offset = 13 ifTrue: [^client storeIntoRemoteTemp: byte2 inVectorAt: byte3]. offset = 14 ifTrue: [^client popIntoRemoteTemp: byte2 inVectorAt: byte3]. "offset = 15" byte4 := method at: pc. pc := pc + 1. ^client pushClosureCopyNumCopiedValues: (byte2 bitShift: -4) numArgs: (byte2 bitAnd: 16rF) blockSize: (byte3 * 256) + byte4! Item was changed: ----- Method: Integer class>>initialize (in category 'class initialization') ----- + initialize + "Integer initialize" + self initializeLowBitPerByteTable! - initialize "Integer initialize" - "Ensure we have the right compact class index" - - "LPI has been a compact class forever - just ensure basic correctness" - (LargePositiveInteger indexIfCompact = 5) ifFalse:[ - (Smalltalk compactClassesArray at: 5) - ifNil:[LargePositiveInteger becomeCompactSimplyAt: 5] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - "Cog requires LNI to be compact at 4 (replacing PseudoContext)" - (LargeNegativeInteger indexIfCompact = 4) ifFalse:[ - "PseudoContext will likely get removed at some point so write this test - without introducing a hard dependency" - (Smalltalk compactClassesArray at: 4) name == #PseudoContext - ifTrue:[Smalltalk compactClassesArray at: 4 put: nil]. - (Smalltalk compactClassesArray at: 4) - ifNil:[LargeNegativeInteger becomeCompactSimplyAt: 4] - ifNotNil:[self error: 'Unexpected compact class setup']]. - - self initializeLowBitPerByteTable - ! Item was added: + ----- Method: MethodContext class>>allInstances (in category 'enumerating') ----- + allInstances + "Answer all instances of the receiver." + + "The primitive can fail because memory is low. If so, fall back on the old + enumeration code, which gives the system a chance to GC and/or grow. + Because aBlock might change the class of inst (for example, using become:), + it is essential to compute next before aBlock value: inst. + Only count until thisContext since this context has been created only to + compute the existing instances." + | inst insts next | + insts := WriteStream on: (Array new: 64). + inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + insts nextPut: inst. + inst := next]. + ^insts contents! Item was changed: ----- Method: MethodContext class>>allInstancesDo: (in category 'private') ----- allInstancesDo: aBlock + "Evaluate aBlock with each of the current instances of the receiver." + | instances inst next | + instances := self allInstancesOrNil. + instances ifNotNil: + [instances do: aBlock. + ^self]. + "allInstancesOrNil can fail because memory is low. If so, fall back on the old + enumeration code. Because aBlock might change the class of inst (for example, + using become:), it is essential to compute next before aBlock value: inst. + Only count until thisContext since evaluation of aBlock will create new contexts." - "Only count until thisContext since evaluation of aBlock will create new contexts." - | inst next | inst := self someInstance. + [inst == thisContext or: [inst == nil]] whileFalse: + [next := inst nextInstance. + aBlock value: inst. + inst := next]! - [inst == thisContext] whileFalse:[ - next := inst nextInstance. - aBlock value: inst. - inst := next] - ! Item was added: + ----- Method: MethodContext>>failPrimitiveWith: (in category 'system simulation') ----- + failPrimitiveWith: maybePrimFailToken + "The receiver is a freshly-created context on a primitive method. Skip the callPrimitive: + bytecode and store the primitive fail code if there is one and the method consumes it." + self skipCallPrimitive. + ((self isPrimFailToken: maybePrimFailToken) + and: [method encoderClass isStoreAt: pc in: method]) ifTrue: + [self at: stackp put: maybePrimFailToken last]! Item was changed: ----- Method: ProtoObject>>scaledIdentityHash (in category 'comparing') ----- scaledIdentityHash "For identityHash values returned by primitive 75, answer + such values times 2^8. Otherwise, match the existing + identityHash implementation" - such values times 2^18. Otherwise, match the existing - identityHash implementation" + ^self identityHash * 256 "bitShift: 8"! - ^self identityHash * 262144 "bitShift: 18"! Item was changed: ==== ERROR === Error: Unrecognized class type 31 October 2014 12:06:14.228 am VM: unix - a SmalltalkImage Image: Squeak3.11alpha [latest update: #8824] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/squeaksource Trusted Dir /home/squeaksource/secure Untrusted Dir /home/squeaksource/My Squeak MCClassDefinition(Object)>>error: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: aString: 'Unrecognized class type' Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>kindOfSubclass Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil MCClassDefinition>>printDefinitionOn: Receiver: a MCClassDefinition(SmallInteger) Arguments and temporary variables: stream: a WriteStream Receiver's instance variables: name: #SmallInteger superclassName: #Integer variables: an OrderedCollection() category: #'Kernel-Numbers' type: #immediate comment: 'My instances are 31-bit numbers, stored in twos complement form. The ...etc... commentStamp: 'eem 8/12/2014 14:54' traitComposition: nil classTraitComposition: nil [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: Receiver: a MCDiffyTextWriter Arguments and temporary variables: definition: a WriteStream s: a MCClassDefinition(SmallInteger) Receiver's instance variables: stream: a WriteStream initStream: nil --- The full stack --- MCClassDefinition(Object)>>error: MCClassDefinition>>kindOfSubclass MCClassDefinition>>printDefinitionOn: [] in MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>chunkContents: MCDiffyTextWriter(MCStWriter)>>writeClassDefinition: MCDiffyTextWriter(MCStWriter)>>visitClassDefinition: MCClassDefinition>>accept: [] in MCDiffyTextWriter(MCTextWriter)>>visitInFork: String class(SequenceableCollection class)>>new:streamContents: String class(SequenceableCollection class)>>streamContents: MCDiffyTextWriter(MCTextWriter)>>visitInFork: MCDiffyTextWriter>>writePatchFrom:to: MCDiffyTextWriter>>writeModification: [] in MCDiffyTextWriter>>writePatch: SortedCollection(OrderedCollection)>>do: MCDiffyTextWriter>>writePatch: SSDiffyTextWriter>>writePatch: [] in SSDiffyTextWriter>>writeVersion:for: BlockClosure>>on:do: SSDiffyTextWriter>>writeVersion:for: [] in SSEMailSubscription>>versionAdded:to: BlockClosure>>on:do: SSEMailSubscription>>versionAdded:to: [] in [] in SSProject>>versionAdded: [] in BlockClosure>>newProcess From ma.chris.m at gmail.com Fri Oct 31 01:10:41 2014 From: ma.chris.m at gmail.com (Chris Muller) Date: Fri Oct 31 01:10:43 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: On Thu, Oct 30, 2014 at 5:28 PM, Levente Uzonyi wrote: > On Thu, 30 Oct 2014, Chris Muller wrote: > >> Thanks guys, those both helped. After defining X I found I could do a >> "Smalltalk importSelf" to get it copied into the 'bindings' >> Dictionary. > > > #importSelf is not what you want do, because that'll add the same policy to > your environment again. Oh wow, and it even will allow duplicates..(!?) I didn't even notice that because I was just interested in the second part of that method. I was just operating as a Smalltalker; backtracing what was causing my #X lookup problem, and found it was because it wasn't in 'bindings'. So I browsed who ever adds anything into 'bindings'? Only #importSelf and #showBinding:. So to get the "side-effect" I wanted, I inadvertently also added a second BindingPolicy. I manually removed the duplicate BindingPolicy, thanks for the heads-up. I think Squeak's frameworks should be implemented in a way that caters to its own IDE, so Smalltalker's can figure things out by those normal tracing activities (senders, references, implementors). #importSelf seems like a not-so-good method. From eliot.miranda at gmail.com Fri Oct 31 21:29:08 2014 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri Oct 31 21:29:13 2014 Subject: [squeak-dev] Nw Cog VMs available Message-ID: ...at http://www.mirandabanda.org/files/Cog/VM/VM.r3120/. These contain a few important bug fixes to Spur which will increase stability. CogVM binaries as per VMMaker.oscog-eem.916 Spur: Reimplement deriving the accessorDepth and retrying primitives on primitive failure machinery. Always take the primitive index from newMethod (setting newMethod to a SmallInteger for primitiveDoPrimitiveWithArgs. Have the Cogit always set primitiveFunctionPointer and newMethod for the retry. Add isNonInteger(Non)Immediate: and use it in several of the integer conversion routines that were missing code to exclude Character immediates, with fatal consequences. With these changes the Pharo 4 test suite runs without crashing on the latest Pharo Spur boot image. Fix processWeakSurvivor: so that it answers whether a weak object refers to a young object. The old version only scanned weak fields, ignoring refs to young objs from strong fields. Move check for valid classes from findClassOfMethod: forReceiver: into findClassContainingMethod:startingAt:, hence making findClassOfMethod:forReceiver: et al more robust. Implement safe access to contexts and methods when creating image segments (since internally married contexts and jitted methods have hidden state encoded in odd ways). As a result: Fix baaad bug in SpurMemoryManager>>lastPointerOf: for contexts, caused by transcription from (New)ObjectMemory where the method works on a wing and a prayer because BaseHeaderSize = BytesPerOop. And I can't be arsed to fix it. Fix baaad bug in accessibleObjectAfter: and add an assert to primitiveNextObject to catch similar bugs. Can now enumerate objects in new space, which will sort-of work, but code should really use allObjects. Will fix at the image level as time allows. Eliminate isInSurvivorSpace: in favour of the identical isInPastSpace:. All: Refactor decoding of context instruction pointers so there is only one copy of the code. -- best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141031/121bdf9a/attachment.htm From nicolas.cellier.aka.nice at gmail.com Fri Oct 31 22:04:49 2014 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri Oct 31 22:04:53 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: Yeah, I also already noticed about these nested nested nested policies... All this is far from obvious and the comments do not help ;) Still on the same subject there is also this previous analysis in http://source.squeak.org/inbox/Kernel-nice.798.diff which explains how you can have access to the environment of your superclass... I don't know if it is still true, but for me, the fact that I couldn't correct this was not a sign of good health. 2014-10-31 2:10 GMT+01:00 Chris Muller : > On Thu, Oct 30, 2014 at 5:28 PM, Levente Uzonyi wrote: > > On Thu, 30 Oct 2014, Chris Muller wrote: > > > >> Thanks guys, those both helped. After defining X I found I could do a > >> "Smalltalk importSelf" to get it copied into the 'bindings' > >> Dictionary. > > > > > > #importSelf is not what you want do, because that'll add the same policy > to > > your environment again. > > Oh wow, and it even will allow duplicates..(!?) I didn't even notice > that because I was just interested in the second part of that method. > > I was just operating as a Smalltalker; backtracing what was causing my > #X lookup problem, and found it was because it wasn't in 'bindings'. > So I browsed who ever adds anything into 'bindings'? Only #importSelf > and #showBinding:. So to get the "side-effect" I wanted, I > inadvertently also added a second BindingPolicy. I manually removed > the duplicate BindingPolicy, thanks for the heads-up. > > I think Squeak's frameworks should be implemented in a way that caters > to its own IDE, so Smalltalker's can figure things out by those normal > tracing activities (senders, references, implementors). #importSelf > seems like a not-so-good method. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141031/4c44f360/attachment.htm From Das.Linux at gmx.de Fri Oct 31 22:13:24 2014 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri Oct 31 22:13:28 2014 Subject: [squeak-dev] Urgent: how to define a global? In-Reply-To: References: Message-ID: <9B63A61C-A8A6-41F5-A55F-A604C9A46245@gmx.de> Hi, Is anybody able to summon Colin on this whole issue? It would be too bad if one of the 4.5 killer features actually isn't killing but dead? Best -Tobias On 31.10.2014, at 23:04, Nicolas Cellier wrote: > Yeah, I also already noticed about these nested nested nested policies... > All this is far from obvious and the comments do not help ;) > > Still on the same subject there is also this previous analysis in http://source.squeak.org/inbox/Kernel-nice.798.diff which explains how you can have access to the environment of your superclass... I don't know if it is still true, but for me, the fact that I couldn't correct this was not a sign of good health. > > 2014-10-31 2:10 GMT+01:00 Chris Muller : > On Thu, Oct 30, 2014 at 5:28 PM, Levente Uzonyi wrote: > > On Thu, 30 Oct 2014, Chris Muller wrote: > > > >> Thanks guys, those both helped. After defining X I found I could do a > >> "Smalltalk importSelf" to get it copied into the 'bindings' > >> Dictionary. > > > > > > #importSelf is not what you want do, because that'll add the same policy to > > your environment again. > > Oh wow, and it even will allow duplicates..(!?) I didn't even notice > that because I was just interested in the second part of that method. > > I was just operating as a Smalltalker; backtracing what was causing my > #X lookup problem, and found it was because it wasn't in 'bindings'. > So I browsed who ever adds anything into 'bindings'? Only #importSelf > and #showBinding:. So to get the "side-effect" I wanted, I > inadvertently also added a second BindingPolicy. I manually removed > the duplicate BindingPolicy, thanks for the heads-up. > > I think Squeak's frameworks should be implemented in a way that caters > to its own IDE, so Smalltalker's can figure things out by those normal > tracing activities (senders, references, implementors). #importSelf > seems like a not-so-good method. From alf.mmm.cat at gmail.com Fri Oct 31 22:23:02 2014 From: alf.mmm.cat at gmail.com (Alain Rastoul) Date: Fri Oct 31 22:30:07 2014 Subject: [squeak-dev] Re: FFI structs In-Reply-To: <8347C5A6-FF04-4EB4-B874-4BB22AC6171F@afceurope.com> References: <8347C5A6-FF04-4EB4-B874-4BB22AC6171F@afceurope.com> Message-ID: Hi Annick, you can't pass smalltalk strings or objects to ffi as parameters, you have to allocate the buffer member of your structure on the external heap ( plus to avoid being gc'd before ffi call) with ExternalAddress allocate: fill your buffer with byteAt:put: method, and release this memory with free when you have finished. not sure, but you could try something like: s := '05:45' copyWith: (Character value: 0). a := ExternalAddress allocate: s size. s asByteArray withIndexDo: [ :b :i | a byteAt: i put: b ]. myStruct time: a. ... call your ffi ... a free Regards, Alain Le 29/10/2014 11:59, Annick Fron a ?crit : > I I have a C struct with a char* > > struct result { > char* time } > > I define an ExternalStructure in FFI , with one field of type char* (note that the syntax char [5] is not accepted ! ). > > defineFields generates the accessors time and time: > > If I use > time: ?05:45? > > I get an error. > How do I set a string value in an ExternalStructure ? > > Annick > > > > > From commits at source.squeak.org Fri Oct 31 23:55:03 2014 From: commits at source.squeak.org (commits@source.squeak.org) Date: Fri Oct 31 23:55:04 2014 Subject: [squeak-dev] Daily Commit Log Message-ID: <20141031235503.2768.qmail@box2.squeakfoundation.org> Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours: http://lists.squeakfoundation.org/pipermail/packages/2014-October/007359.html Name: Kernel.spur-nice.882 Ancestors: Kernel-nice.882, Kernel.spur-nice.881 Kernel-nice.882 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.212 No need to query which selector isDoIt, because DoIt methods are not installed anymore in the methodDictionary (for a few years yet). =============================================