Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 1 participants
- 144619 messages
Re: [Pharo-dev] Do we remove infiniteForm support?
by Denis Kudriashov
I always wondering how anybody can write such code with smalltalk
2014-06-26 0:43 GMT+04:00 stepharo <stepharo(a)free.fr>:
> because when I see code like that, it makes me sick!
> I wonder also when we migrate to Athens if we will not rewrite all that
> anyway.
>
> fillRectangle: aRectangle basicFillStyle: aFillStyle
> "Fill the given rectangle with the given, non-composite, fill style."
>
> | pattern |
>
> (aFillStyle isKindOf: InfiniteForm) ifTrue: [
> ^self infiniteFillRectangle: aRectangle fillStyle: aFillStyle
> ].
>
> (aFillStyle isSolidFill)
> ifTrue:[^self fillRectangle: aRectangle color: aFillStyle asColor].
>
> "We have a very special case for filling with infinite forms"
> (aFillStyle isBitmapFill and:[aFillStyle origin = (0@0)]) ifTrue:[
> pattern := aFillStyle form.
> (aFillStyle direction = (pattern width @ 0)
> and:[aFillStyle normal = (0@pattern height)]) ifTrue:[
> "Can use an InfiniteForm"
> ^self fillRectangle: aRectangle color: (InfiniteForm with:
> pattern)].
> ].
> "Use a BalloonCanvas instead"
> self balloonFillRectangle: aRectangle fillStyle: aFillStyle.
>
>
June 27, 2014
Re: [Pharo-dev] Improving Pharo By Example
by kilon alios
you are very fast, great work Damien !
On Fri, Jun 27, 2014 at 7:31 PM, Damien Cassou <damien.cassou(a)gmail.com>
wrote:
> On Fri, Jun 27, 2014 at 3:19 PM, kilon alios <kilon.alios(a)gmail.com>
> wrote:
> > finished Chapter 4. Damien your automatic conversion tool worked very
> well
> > for me, it has been a huge boost to my workflow, there are problems with
> it
> > that I keep reporting to its github repo . I definitely see if these
> minor
> > problems are removed that the automatic conversion will do 90% of the
> work
> > for you. I am sure these problems will be fixed very soon.
>
>
> I've fixed all your conversion bugs. The only remaining problem is for
> Emacs syntax highlighting.
>
> Thank you for reporting
>
> --
> Damien Cassou
> http://damiencassou.seasidehosting.st
>
> "Success is the ability to go from one failure to another without
> losing enthusiasm."
> Winston Churchill
>
>
June 27, 2014
Re: [Pharo-dev] Some assembly for a friday afternoon
by Igor Stasenko
Don't compare with smalltalk, compare with C! :)
On 27 June 2014 19:23, phil(a)highoctane.be <phil(a)highoctane.be> wrote:
> Impressive numbers and a nice examplz to grasp lots of NB/Asm details.
> Le 27 juin 2014 18:55, "Henrik Johansen" <henrik.s.johansen(a)veloxit.no> a
> écrit :
>
> >
> > Soo, I started dabbling with the thing I talked about before last
> summer, letting String parameters in NB calls have an encoding: option.
> > (Thereâs already a slice in inbox to allow optional values other than
> true/false)
> >
> > Thought Iâd start with decoding; hereâs a small preview of the part
> which does the actual decoding, after needed string class has has been
> determined and instantiated.
> > While itâs a fallback path for when the platform doesnât support SSE or
> other batch operations, itâs still using some neat tricks (imho) I thought
> others might enjoy on a Friday afternoon :)
> >
> > emitStandardDecodeUTF8CharactersFrom: aSource to: aDestination
> withCharSize: aCharSize scratchReg: scratchReg using: aGenerator
> > "Emit decoding using only standard x86 ops"
> > "We have already found what String class is needed for decoding
> aSource, and created an instance of the proper size"
> > "This implementation focuses on minimizing jumps and register
> usage, at the cost of loading from source one byte at a time.
> > "Input:
> > aSource - memory pointer to C-string with UTF8 bytes
> > aDestination - memoryPointer to first var field of
> String instance
> > scratchReg - a register which will be modified while
> decoding
> >
> > aCharSize - The size in bytes of each character in our
> destination string, known at emission time
> >
> > Clobbers: scratchReg
> > aSource and aDestination will end up pointing to end of strings"
> >
> > | asm scratch32 sLowByte sHighByte loop done oneByte twoBytes
> threeBytes |
> >
> > asm := aGenerator asm.
> > loop := asm uniqueLabelName: 'utf8DecodeLoop'.
> > done := asm uniqueLabelName: 'utf8DecodingDone'.
> > scratch32 := scratchReg as32.
> > sLowByte := scratch32 as8.
> > sHighByte := sLowByte asHighByte.
> >
> > asm label: loop.
> > "Unroll the inner loop as many times as we want, or, well, at
> least as many times as the backwards jump will allow us to"
> > 8 timesRepeat:[
> > oneByte := asm uniqueLabelName: 'utf8OneByteDecode'.
> > twoBytes := asm uniqueLabelName: 'utf8TwoByteDecode'.
> > threeBytes := asm uniqueLabelName: 'utf8ThreeByteDecode'.
> > asm xor: scratch32 with:scratch32.
> > asm or: sLowByte with: aSource ptr8.
> > asm cmp: sLowByte with: 0.
> > asm je: done.
> > asm add: aSource with: 1.
> > asm test: sLowByte with: 2r10000000 asUImm8.
> > asm jz: oneByte.
> > "We have a header, place its data bits as initial high byte
> value"
> > asm shl: scratch32 with: 8.
> > asm xor: sHighByte with: 2r11000000 asUImm8. "Strip 2 byte
> header"
> > asm test: sHighByte with: 2r00100000.
> > asm jz: twoBytes.
> > aCharSize > 1 ifTrue: [
> > asm xor: sHighByte with: 2r00100000. "Strip 3 byte header"
> > asm test: sHighByte with: 2r000100000.
> > asm jz: threeBytes.
> > "This is a 4-byte character"
> > asm xor: sHighByte with:2r00010000."Strip 4 byte header"
> > "Read one trailing byte, remove the header, and shift the data
> out of low byte"
> > asm or: sLowByte with: aSource ptr8.
> > asm shl: sLowByte with:2.
> > asm shl: scratch32 with: 6.
> > asm add: aSource with: 1.
> > asm label: threeBytes.
> > "Read one trailing byte, remove the header, and shift the data
> out of low byte"
> > asm or: sLowByte with: aSource ptr8.
> > asm shl: sLowByte with:2.
> > asm shl: scratch32 with: 6.
> > asm add: aSource with: 1.
> > ].
> > asm label: twoBytes.
> > "Read last trailing byte, remove header, and shift the data bits
> into proper place"
> > asm or: sLowByte with: aSource ptr8.
> > asm shl: sLowByte with:2.
> > asm shr: scratch32 with: 2.
> > asm add: aSource with: 1.
> > asm label: oneByte.
> > asm mov: (aDestination ptr size: aCharSize) with: (scratch32 as:
> aCharSize).
> > asm add: aDestination with: aCharSize.].
> > asm jmp: loop.
> > asm label: done.
> >
> > And the relevant test code for that:
> >
> > testStandardDecodeWide
> > | bytes string |
> > "bytes := (ZnUTF8Encoder new encodeString: 'Cash, like â¬, is
> king'), #[0]."
> > bytes := #[67 97 115 104 44 32 108 105 107 101 32 226 130 172 44
> 32 105 115 32 107 105 110 103 0].
> > string := WideString new: bytes size - 1.
> > self testStandardDecode: bytes toWideString: string.
> > ^ string
> >
> > testStandardDecode: utf8Bytes toWideString:aString
> > <primitive: #primitiveNativeCall module: #NativeBoostPlugin>
> > ^ self nbCallout
> > function: #(void #(char* utf8Bytes, char* aString ))
> > emit: [ :gen :proxy :asm |
> > asm pop: asm EBX;
> > pop: asm ECX.
> > self emitStandardDecodeUTF8CharactersFrom: asm
> EBX to: asm ECX withCharSize: 4 scratchReg: asm EAX using: gen.
> > asm mov: EAX with: gen proxy nilObject ]
> >
> > Which, though itâs currently cheating by pre-knowledn string class/size,
> isnât alot of overhead:
> > ext := NBExternalString new.
> > [ext testStandardDecodeWide] bench '5,030,000 per second.' '5,080,000
> per second.' '5,190,000 per second.â
> > Compared to an equivalent to testStandardDecodeWide, with emitStandardâ¦
> removed from the primitive:
> > [ext testEmptyDecode] bench '5,850,000 per second.' '5,800,000 per
> second.' '5,640,000 per second.'
> >
> > ⦠or compared to doing the decoding in image after the call:
> > int := ZnUTF8Encoder new.
> > [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 '130,000 per second.' '131,000 per
> second.' '132,000 per second.â
> >
> > Cheers,
> > Henry
> >
>
>
--
Best regards,
Igor Stasenko.
June 27, 2014
Re: [Pharo-dev] Some assembly for a friday afternoon
by Sven Van Caekenberghe
Nice, could be very useful, slow UTF8 encoding/decoding is a potential bottleneck.
On 27 Jun 2014, at 19:23, phil(a)highoctane.be wrote:
> Impressive numbers and a nice examplz to grasp lots of NB/Asm details.
> Le 27 juin 2014 18:55, "Henrik Johansen" <henrik.s.johansen(a)veloxit.no> a écrit :
> >
> > Soo, I started dabbling with the thing I talked about before last summer, letting String parameters in NB calls have an encoding: option.
> > (Thereâs already a slice in inbox to allow optional values other than true/false)
> >
> > Thought Iâd start with decoding; hereâs a small preview of the part which does the actual decoding, after needed string class has has been determined and instantiated.
> > While itâs a fallback path for when the platform doesnât support SSE or other batch operations, itâs still using some neat tricks (imho) I thought others might enjoy on a Friday afternoon :)
> >
> > emitStandardDecodeUTF8CharactersFrom: aSource to: aDestination withCharSize: aCharSize scratchReg: scratchReg using: aGenerator
> > "Emit decoding using only standard x86 ops"
> > "We have already found what String class is needed for decoding aSource, and created an instance of the proper size"
> > "This implementation focuses on minimizing jumps and register usage, at the cost of loading from source one byte at a time.
> > "Input:
> > aSource - memory pointer to C-string with UTF8 bytes
> > aDestination - memoryPointer to first var field of String instance
> > scratchReg - a register which will be modified while decoding
> >
> > aCharSize - The size in bytes of each character in our destination string, known at emission time
> >
> > Clobbers: scratchReg
> > aSource and aDestination will end up pointing to end of strings"
> >
> > | asm scratch32 sLowByte sHighByte loop done oneByte twoBytes threeBytes |
> >
> > asm := aGenerator asm.
> > loop := asm uniqueLabelName: 'utf8DecodeLoop'.
> > done := asm uniqueLabelName: 'utf8DecodingDone'.
> > scratch32 := scratchReg as32.
> > sLowByte := scratch32 as8.
> > sHighByte := sLowByte asHighByte.
> >
> > asm label: loop.
> > "Unroll the inner loop as many times as we want, or, well, at least as many times as the backwards jump will allow us to"
> > 8 timesRepeat:[
> > oneByte := asm uniqueLabelName: 'utf8OneByteDecode'.
> > twoBytes := asm uniqueLabelName: 'utf8TwoByteDecode'.
> > threeBytes := asm uniqueLabelName: 'utf8ThreeByteDecode'.
> > asm xor: scratch32 with:scratch32.
> > asm or: sLowByte with: aSource ptr8.
> > asm cmp: sLowByte with: 0.
> > asm je: done.
> > asm add: aSource with: 1.
> > asm test: sLowByte with: 2r10000000 asUImm8.
> > asm jz: oneByte.
> > "We have a header, place its data bits as initial high byte value"
> > asm shl: scratch32 with: 8.
> > asm xor: sHighByte with: 2r11000000 asUImm8. "Strip 2 byte header"
> > asm test: sHighByte with: 2r00100000.
> > asm jz: twoBytes.
> > aCharSize > 1 ifTrue: [
> > asm xor: sHighByte with: 2r00100000. "Strip 3 byte header"
> > asm test: sHighByte with: 2r000100000.
> > asm jz: threeBytes.
> > "This is a 4-byte character"
> > asm xor: sHighByte with:2r00010000."Strip 4 byte header"
> > "Read one trailing byte, remove the header, and shift the data out of low byte"
> > asm or: sLowByte with: aSource ptr8.
> > asm shl: sLowByte with:2.
> > asm shl: scratch32 with: 6.
> > asm add: aSource with: 1.
> > asm label: threeBytes.
> > "Read one trailing byte, remove the header, and shift the data out of low byte"
> > asm or: sLowByte with: aSource ptr8.
> > asm shl: sLowByte with:2.
> > asm shl: scratch32 with: 6.
> > asm add: aSource with: 1.
> > ].
> > asm label: twoBytes.
> > "Read last trailing byte, remove header, and shift the data bits into proper place"
> > asm or: sLowByte with: aSource ptr8.
> > asm shl: sLowByte with:2.
> > asm shr: scratch32 with: 2.
> > asm add: aSource with: 1.
> > asm label: oneByte.
> > asm mov: (aDestination ptr size: aCharSize) with: (scratch32 as: aCharSize).
> > asm add: aDestination with: aCharSize.].
> > asm jmp: loop.
> > asm label: done.
> >
> > And the relevant test code for that:
> >
> > testStandardDecodeWide
> > | bytes string |
> > "bytes := (ZnUTF8Encoder new encodeString: 'Cash, like â¬, is king'), #[0]."
> > bytes := #[67 97 115 104 44 32 108 105 107 101 32 226 130 172 44 32 105 115 32 107 105 110 103 0].
> > string := WideString new: bytes size - 1.
> > self testStandardDecode: bytes toWideString: string.
> > ^ string
> >
> > testStandardDecode: utf8Bytes toWideString:aString
> > <primitive: #primitiveNativeCall module: #NativeBoostPlugin>
> > ^ self nbCallout
> > function: #(void #(char* utf8Bytes, char* aString ))
> > emit: [ :gen :proxy :asm |
> > asm pop: asm EBX;
> > pop: asm ECX.
> > self emitStandardDecodeUTF8CharactersFrom: asm EBX to: asm ECX withCharSize: 4 scratchReg: asm EAX using: gen.
> > asm mov: EAX with: gen proxy nilObject ]
> >
> > Which, though itâs currently cheating by pre-knowledn string class/size, isnât alot of overhead:
> > ext := NBExternalString new.
> > [ext testStandardDecodeWide] bench '5,030,000 per second.' '5,080,000 per second.' '5,190,000 per second.â
> > Compared to an equivalent to testStandardDecodeWide, with emitStandard⦠removed from the primitive:
> > [ext testEmptyDecode] bench '5,850,000 per second.' '5,800,000 per second.' '5,640,000 per second.'
> >
> > ⦠or compared to doing the decoding in image after the call:
> > int := ZnUTF8Encoder new.
> > [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 '130,000 per second.' '131,000 per second.' '132,000 per second.â
> >
> > Cheers,
> > Henry
> >
June 27, 2014
Re: [Pharo-dev] Some assembly for a friday afternoon
by phil@highoctane.be
Impressive numbers and a nice examplz to grasp lots of NB/Asm details.
Le 27 juin 2014 18:55, "Henrik Johansen" <henrik.s.johansen(a)veloxit.no> a
écrit :
>
> Soo, I started dabbling with the thing I talked about before last summer,
letting String parameters in NB calls have an encoding: option.
> (Thereâs already a slice in inbox to allow optional values other than
true/false)
>
> Thought Iâd start with decoding; hereâs a small preview of the part which
does the actual decoding, after needed string class has has been determined
and instantiated.
> While itâs a fallback path for when the platform doesnât support SSE or
other batch operations, itâs still using some neat tricks (imho) I thought
others might enjoy on a Friday afternoon :)
>
> emitStandardDecodeUTF8CharactersFrom: aSource to: aDestination
withCharSize: aCharSize scratchReg: scratchReg using: aGenerator
> "Emit decoding using only standard x86 ops"
> "We have already found what String class is needed for decoding
aSource, and created an instance of the proper size"
> "This implementation focuses on minimizing jumps and register
usage, at the cost of loading from source one byte at a time.
> "Input:
> aSource - memory pointer to C-string with UTF8 bytes
> aDestination - memoryPointer to first var field of String
instance
> scratchReg - a register which will be modified while
decoding
>
> aCharSize - The size in bytes of each character in our
destination string, known at emission time
>
> Clobbers: scratchReg
> aSource and aDestination will end up pointing to end of strings"
>
> | asm scratch32 sLowByte sHighByte loop done oneByte twoBytes
threeBytes |
>
> asm := aGenerator asm.
> loop := asm uniqueLabelName: 'utf8DecodeLoop'.
> done := asm uniqueLabelName: 'utf8DecodingDone'.
> scratch32 := scratchReg as32.
> sLowByte := scratch32 as8.
> sHighByte := sLowByte asHighByte.
>
> asm label: loop.
> "Unroll the inner loop as many times as we want, or, well, at
least as many times as the backwards jump will allow us to"
> 8 timesRepeat:[
> oneByte := asm uniqueLabelName: 'utf8OneByteDecode'.
> twoBytes := asm uniqueLabelName: 'utf8TwoByteDecode'.
> threeBytes := asm uniqueLabelName: 'utf8ThreeByteDecode'.
> asm xor: scratch32 with:scratch32.
> asm or: sLowByte with: aSource ptr8.
> asm cmp: sLowByte with: 0.
> asm je: done.
> asm add: aSource with: 1.
> asm test: sLowByte with: 2r10000000 asUImm8.
> asm jz: oneByte.
> "We have a header, place its data bits as initial high byte value"
> asm shl: scratch32 with: 8.
> asm xor: sHighByte with: 2r11000000 asUImm8. "Strip 2 byte header"
> asm test: sHighByte with: 2r00100000.
> asm jz: twoBytes.
> aCharSize > 1 ifTrue: [
> asm xor: sHighByte with: 2r00100000. "Strip 3 byte header"
> asm test: sHighByte with: 2r000100000.
> asm jz: threeBytes.
> "This is a 4-byte character"
> asm xor: sHighByte with:2r00010000."Strip 4 byte header"
> "Read one trailing byte, remove the header, and shift the data
out of low byte"
> asm or: sLowByte with: aSource ptr8.
> asm shl: sLowByte with:2.
> asm shl: scratch32 with: 6.
> asm add: aSource with: 1.
> asm label: threeBytes.
> "Read one trailing byte, remove the header, and shift the data
out of low byte"
> asm or: sLowByte with: aSource ptr8.
> asm shl: sLowByte with:2.
> asm shl: scratch32 with: 6.
> asm add: aSource with: 1.
> ].
> asm label: twoBytes.
> "Read last trailing byte, remove header, and shift the data bits
into proper place"
> asm or: sLowByte with: aSource ptr8.
> asm shl: sLowByte with:2.
> asm shr: scratch32 with: 2.
> asm add: aSource with: 1.
> asm label: oneByte.
> asm mov: (aDestination ptr size: aCharSize) with: (scratch32 as:
aCharSize).
> asm add: aDestination with: aCharSize.].
> asm jmp: loop.
> asm label: done.
>
> And the relevant test code for that:
>
> testStandardDecodeWide
> | bytes string |
> "bytes := (ZnUTF8Encoder new encodeString: 'Cash, like â¬, is
king'), #[0]."
> bytes := #[67 97 115 104 44 32 108 105 107 101 32 226 130 172 44
32 105 115 32 107 105 110 103 0].
> string := WideString new: bytes size - 1.
> self testStandardDecode: bytes toWideString: string.
> ^ string
>
> testStandardDecode: utf8Bytes toWideString:aString
> <primitive: #primitiveNativeCall module: #NativeBoostPlugin>
> ^ self nbCallout
> function: #(void #(char* utf8Bytes, char* aString ))
> emit: [ :gen :proxy :asm |
> asm pop: asm EBX;
> pop: asm ECX.
> self emitStandardDecodeUTF8CharactersFrom: asm
EBX to: asm ECX withCharSize: 4 scratchReg: asm EAX using: gen.
> asm mov: EAX with: gen proxy nilObject ]
>
> Which, though itâs currently cheating by pre-knowledn string class/size,
isnât alot of overhead:
> ext := NBExternalString new.
> [ext testStandardDecodeWide] bench '5,030,000 per second.' '5,080,000
per second.' '5,190,000 per second.â
> Compared to an equivalent to testStandardDecodeWide, with emitStandardâ¦
removed from the primitive:
> [ext testEmptyDecode] bench '5,850,000 per second.' '5,800,000 per
second.' '5,640,000 per second.'
>
> ⦠or compared to doing the decoding in image after the call:
> int := ZnUTF8Encoder new.
> [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 '130,000 per second.' '131,000 per
second.' '132,000 per second.â
>
> Cheers,
> Henry
>
June 27, 2014
Some assembly for a friday afternoon
by Henrik Johansen
Soo, I started dabbling with the thing I talked about before last summer, letting String parameters in NB calls have an encoding: option.
(Thereâs already a slice in inbox to allow optional values other than true/false)
Thought Iâd start with decoding; hereâs a small preview of the part which does the actual decoding, after needed string class has has been determined and instantiated.
While itâs a fallback path for when the platform doesnât support SSE or other batch operations, itâs still using some neat tricks (imho) I thought others might enjoy on a Friday afternoon :)
emitStandardDecodeUTF8CharactersFrom: aSource to: aDestination withCharSize: aCharSize scratchReg: scratchReg using: aGenerator
"Emit decoding using only standard x86 ops"
"We have already found what String class is needed for decoding aSource, and created an instance of the proper size"
"This implementation focuses on minimizing jumps and register usage, at the cost of loading from source one byte at a time.
"Input:
aSource - memory pointer to C-string with UTF8 bytes
aDestination - memoryPointer to first var field of String instance
scratchReg - a register which will be modified while decoding
aCharSize - The size in bytes of each character in our destination string, known at emission time
Clobbers: scratchReg
aSource and aDestination will end up pointing to end of strings"
| asm scratch32 sLowByte sHighByte loop done oneByte twoBytes threeBytes |
asm := aGenerator asm.
loop := asm uniqueLabelName: 'utf8DecodeLoop'.
done := asm uniqueLabelName: 'utf8DecodingDone'.
scratch32 := scratchReg as32.
sLowByte := scratch32 as8.
sHighByte := sLowByte asHighByte.
asm label: loop.
"Unroll the inner loop as many times as we want, or, well, at least as many times as the backwards jump will allow us to"
8 timesRepeat:[
oneByte := asm uniqueLabelName: 'utf8OneByteDecode'.
twoBytes := asm uniqueLabelName: 'utf8TwoByteDecode'.
threeBytes := asm uniqueLabelName: 'utf8ThreeByteDecode'.
asm xor: scratch32 with:scratch32.
asm or: sLowByte with: aSource ptr8.
asm cmp: sLowByte with: 0.
asm je: done.
asm add: aSource with: 1.
asm test: sLowByte with: 2r10000000 asUImm8.
asm jz: oneByte.
"We have a header, place its data bits as initial high byte value"
asm shl: scratch32 with: 8.
asm xor: sHighByte with: 2r11000000 asUImm8. "Strip 2 byte header"
asm test: sHighByte with: 2r00100000.
asm jz: twoBytes.
aCharSize > 1 ifTrue: [
asm xor: sHighByte with: 2r00100000. "Strip 3 byte header"
asm test: sHighByte with: 2r000100000.
asm jz: threeBytes.
"This is a 4-byte character"
asm xor: sHighByte with:2r00010000."Strip 4 byte header"
"Read one trailing byte, remove the header, and shift the data out of low byte"
asm or: sLowByte with: aSource ptr8.
asm shl: sLowByte with:2.
asm shl: scratch32 with: 6.
asm add: aSource with: 1.
asm label: threeBytes.
"Read one trailing byte, remove the header, and shift the data out of low byte"
asm or: sLowByte with: aSource ptr8.
asm shl: sLowByte with:2.
asm shl: scratch32 with: 6.
asm add: aSource with: 1.
].
asm label: twoBytes.
"Read last trailing byte, remove header, and shift the data bits into proper place"
asm or: sLowByte with: aSource ptr8.
asm shl: sLowByte with:2.
asm shr: scratch32 with: 2.
asm add: aSource with: 1.
asm label: oneByte.
asm mov: (aDestination ptr size: aCharSize) with: (scratch32 as: aCharSize).
asm add: aDestination with: aCharSize.].
asm jmp: loop.
asm label: done.
And the relevant test code for that:
testStandardDecodeWide
| bytes string |
"bytes := (ZnUTF8Encoder new encodeString: 'Cash, like â¬, is king'), #[0]."
bytes := #[67 97 115 104 44 32 108 105 107 101 32 226 130 172 44 32 105 115 32 107 105 110 103 0].
string := WideString new: bytes size - 1.
self testStandardDecode: bytes toWideString: string.
^ string
testStandardDecode: utf8Bytes toWideString:aString
<primitive: #primitiveNativeCall module: #NativeBoostPlugin>
^ self nbCallout
function: #(void #(char* utf8Bytes, char* aString ))
emit: [ :gen :proxy :asm |
asm pop: asm EBX;
pop: asm ECX.
self emitStandardDecodeUTF8CharactersFrom: asm EBX to: asm ECX withCharSize: 4 scratchReg: asm EAX using: gen.
asm mov: EAX with: gen proxy nilObject ]
Which, though itâs currently cheating by pre-knowledn string class/size, isnât alot of overhead:
ext := NBExternalString new.
[ext testStandardDecodeWide] bench '5,030,000 per second.' '5,080,000 per second.' '5,190,000 per second.â
Compared to an equivalent to testStandardDecodeWide, with emitStandard⦠removed from the primitive:
[ext testEmptyDecode] bench '5,850,000 per second.' '5,800,000 per second.' '5,640,000 per second.'
⦠or compared to doing the decoding in image after the call:
int := ZnUTF8Encoder new.
[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 '130,000 per second.' '131,000 per second.' '132,000 per second.â
Cheers,
Henry
June 27, 2014
Re: [Pharo-dev] Improving Pharo By Example
by Damien Cassou
On Fri, Jun 27, 2014 at 3:19 PM, kilon alios <kilon.alios(a)gmail.com> wrote:
> finished Chapter 4. Damien your automatic conversion tool worked very well
> for me, it has been a huge boost to my workflow, there are problems with it
> that I keep reporting to its github repo . I definitely see if these minor
> problems are removed that the automatic conversion will do 90% of the work
> for you. I am sure these problems will be fixed very soon.
I've fixed all your conversion bugs. The only remaining problem is for
Emacs syntax highlighting.
Thank you for reporting
--
Damien Cassou
http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without
losing enthusiasm."
Winston Churchill
June 27, 2014
[pharo-project/pharo-core]
by GitHub
Branch: refs/tags/40051
Home: https://github.com/pharo-project/pharo-core
June 27, 2014
[pharo-project/pharo-core] 661e32: 40051
by GitHub
Branch: refs/heads/4.0
Home: https://github.com/pharo-project/pharo-core
Commit: 661e3292a610f67f3a2d796ff1239899e7063c39
https://github.com/pharo-project/pharo-core/commit/661e3292a610f67f3a2d796f…
Author: Jenkins Build Server <board(a)pharo-project.org>
Date: 2014-06-27 (Fri, 27 Jun 2014)
Changed paths:
R RecentSubmissions.package/AbstractMethodReferenceConverter.class/class/as yet unclassified/methodReference_referencesList_.st
A RecentSubmissions.package/AbstractMethodReferenceConverter.class/class/instance creation/methodReference_referencesList_.st
R RecentSubmissions.package/MessageList.class/class/toBeRemovedWithStringHolder/isPseudoSelector_.st
M RecentSubmissions.package/MessageList.class/definition.st
M RecentSubmissions.package/MessageList.class/instance/initialization/initialize.st
R RecentSubmissions.package/MessageListBrowser.class/class/deprecated/byClassOn_.st
R RecentSubmissions.package/MessageListBrowser.class/class/deprecated/byDateDescendingOn_.st
M RecentSubmissions.package/MessageListBrowser.class/instance/items addition/addAllItems_.st
M RecentSubmissions.package/MessageListBrowser.class/instance/private/format_.st
M RecentSubmissions.package/MessageListBrowser.class/instance/t - accessing/rootItems.st
M RecentSubmissions.package/MessageListBrowser.class/instance/tree/getMethod_ifAbsent_.st
R RecentSubmissions.package/VersionMethodReferenceConverter.class/instance/initialization/handleStringSearch.st
A ScriptLoader40.package/ScriptLoader.class/instance/pharo - scripts/script51.st
A ScriptLoader40.package/ScriptLoader.class/instance/pharo - updates/update40051.st
M ScriptLoader40.package/ScriptLoader.class/instance/public/commentForCurrentUpdate.st
R Tools.package/AbstractMethodConverter.class/instance/initialization/canCompile.st
R Tools.package/AbstractMethodConverter.class/instance/initialization/handleStringSearch.st
M Tools.package/AbstractTool.class/instance/class/moveInNewPackage_.st
M Tools.package/Browser.class/instance/drag and drop/dragPassengerFor_inMorph_.st
M Tools.package/Browser.class/instance/message functions/shiftedMessageListMenu_.st
R Tools.package/CodeHolder.class/class/as yet unclassified/decorateBrowserButtons.st
R Tools.package/CodeHolder.class/class/as yet unclassified/decorateBrowserButtons_.st
A Tools.package/CodeHolder.class/class/settings/decorateBrowserButtons.st
A Tools.package/CodeHolder.class/class/settings/decorateBrowserButtons_.st
M Tools.package/CodeHolder.class/instance/traits/spawnHierarchy.st
R Tools.package/DynamicMessageImplementor.class/instance/evaluating-private/argumentNamePrefixOf_.st
R Tools.package/SourceMethodConverter.class/instance/initialization/canCompile.st
R Tools.package/TimeStampMethodConverter.class/instance/initialization/handleStringSearch.st
Log Message:
-----------
40051
13428 Small code critique cleanup of RecentSubmissions
https://pharo.fogbugz.com/f/cases/13428
13427 Small code critique clean of Tools
https://pharo.fogbugz.com/f/cases/13427
http://files.pharo.org/image/40/40051.zip
June 27, 2014
[pharo-project/pharo-core]
by GitHub
Branch: refs/tags/40050
Home: https://github.com/pharo-project/pharo-core
June 27, 2014