<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>GrantRi's WebLog [MS] : Work</title><link>http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx</link><description>Tags: Work</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Remodel Marches On</title><link>http://blogs.msdn.com/grantri/archive/2005/06/15/429654.aspx</link><pubDate>Thu, 16 Jun 2005 06:59:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:429654</guid><dc:creator>grantri</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/grantri/comments/429654.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=429654</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=429654</wfw:comment><description>&lt;P&gt;Well, my house is half torn apart and the new parts are about half-built.&amp;nbsp; There's not much to talk about here at work, as we're busy finishing off the last few bugs and getting everything up to snuff.&amp;nbsp; The question in my mind is which will finish first, my house or Whidbey...&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=429654" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/House+and+Home/default.aspx">House and Home</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>I've run out of ideas again</title><link>http://blogs.msdn.com/grantri/archive/2004/12/01/273265.aspx</link><pubDate>Wed, 01 Dec 2004 20:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:273265</guid><dc:creator>grantri</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/grantri/comments/273265.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=273265</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=273265</wfw:comment><description>&lt;p&gt;In case you haven't noticed, I've run out of ideas to write about.&amp;nbsp; I'm sure there's still a few things I know that I haven't explained, btu I can't remember them...&lt;/p&gt; &lt;p&gt;If you've been dying to know something about the C# compiler, ALink, CLR file formats, 64-bit JITs, please ask,a nd I'll see what I can do.&lt;/p&gt; &lt;p&gt;--Grant&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=273265" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Good post on running/writing/compiling managed binaries as 32-bit or 64-bit</title><link>http://blogs.msdn.com/grantri/archive/2004/10/15/243036.aspx</link><pubDate>Fri, 15 Oct 2004 20:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:243036</guid><dc:creator>grantri</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/grantri/comments/243036.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=243036</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=243036</wfw:comment><description>&lt;p&gt;&lt;a id="viewpost" href="/joshwil/archive/2004/10/15/243019.aspx"&gt;How the OS Loader will force .Net v1.0/1.1 executables to run under WOW64 on a 64-Bit Machine&lt;/a&gt; (http://blogs.msdn.com/joshwil/archive/2004/10/15/243019.aspx)&lt;/p&gt; &lt;p&gt;In General I think all of Josh's recent posts are worth a read.&lt;/p&gt;--Grant&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=243036" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Some Clarifications</title><link>http://blogs.msdn.com/grantri/archive/2004/09/15/230117.aspx</link><pubDate>Wed, 15 Sep 2004 20:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:230117</guid><dc:creator>grantri</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/grantri/comments/230117.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=230117</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=230117</wfw:comment><description>&lt;p&gt;In my previous post &lt;A href="http://blogs.msdn.com/grantri/archive/2004/09/07/226355.aspx"&gt;The problem with being second&lt;/a&gt;, it seems like there was a lot of confusion.&amp;nbsp; I'm going to attempt to clarify some of that.&amp;nbsp; The heart of that post was meant to point out that people/developers don't always how close or far they are from a spec, until somebody else tries to implement the spec and they compare the two implementations.&lt;/p&gt; &lt;p&gt;#1 Although I was referring to the ECMA and all that it allowed as far as runtime/JIT optimizations, that's not exactly the same as what Microsoft will ship.&amp;nbsp; As many of you pointed out, it would break way to much of existing code.&amp;nbsp; I would personally argue that it was already broken and you just didn't know it yet, but that's an argument not worth having.&amp;nbsp; Microsoft really does value backwards compatibility and thus we won't ship until we've figured out a way to not break customers (think about how many windows APIs maintain backwards compatibility so that old programs that relied on bugs still work, this will be just another example).&lt;/p&gt; &lt;p&gt;#2 A few people my have interpreted my statements about testers as somehow negative.&amp;nbsp; It was not meant that way.&amp;nbsp; This is my public apology to all testers.&amp;nbsp; I was using testers as an example because they're our 'first' customers.&amp;nbsp; They see our code and its results before anybody else. In general I think testers on compilers, JITs, and runtimes are&amp;nbsp;very smart and&amp;nbsp;technically adept to be able to understand, test and break this stuff.&amp;nbsp; I can't speak for all teams, but the ones I've had experience with, the testers are a vital part of the development cycle, and I enjoy a good 2 way relationship with them, where they are my peers.&lt;/p&gt; &lt;p&gt;--Grant&lt;/p&gt; &lt;p&gt;[corrected some mis-spellings]&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=230117" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>64bit versus 32bit</title><link>http://blogs.msdn.com/grantri/archive/2004/09/07/226386.aspx</link><pubDate>Tue, 07 Sep 2004 17:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:226386</guid><dc:creator>grantri</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/grantri/comments/226386.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=226386</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=226386</wfw:comment><description>&lt;p&gt;&lt;em&gt;&lt;font size="2"&gt;Please don't start a flame war over this.&amp;nbsp; It is meant as more of a Dilbert-style post with just the slightest bit of real technical content.&lt;/font&gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;64-bit machines are twice as fast as 32-bit machines because they have more bits.&lt;/p&gt; &lt;p&gt;Believe it or not there are still some people inside and outside Microsoft that believe this.&amp;nbsp; They're probably the same folks that believe a 4GHz P4 is twice as fast as a 2GHz P4.&amp;nbsp; Wouldn't it be nice if all that was really true?&lt;/p&gt; &lt;p&gt;I really do love my 64-bit machines.&amp;nbsp; One of them I run with a 32-bit OS, the other with a 64-bit OS.&amp;nbsp; They're both really fast at real world developer tasks despite their seemingly slow clocks.&amp;nbsp; They're not twice as fast, but they might be if you figure out a way to factor in their inherent disadvantage: all the pointers are twice as big.&amp;nbsp; Depending on your data structures, that could be a pretty big disadvantage.&lt;/p&gt; &lt;p&gt;--Grant&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=226386" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>The problem with being second</title><link>http://blogs.msdn.com/grantri/archive/2004/09/07/226355.aspx</link><pubDate>Tue, 07 Sep 2004 17:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:226355</guid><dc:creator>grantri</dc:creator><slash:comments>28</slash:comments><comments>http://blogs.msdn.com/grantri/comments/226355.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=226355</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=226355</wfw:comment><description>&lt;p&gt;First, hats off to the &lt;a href="http://www.mono-project.com/about/index.html"&gt;Mono team&lt;/a&gt;.&amp;nbsp; I think they've done a great job at writing some great software, but also at proving that evil MS really does know how to produce a truly common language runtime that can be properly standardized and ported to other platforms and&amp;nbsp;languages.&lt;/p&gt; &lt;p&gt;Now for the meat of my blog.&amp;nbsp; Working on the AMD64 JIT for the runtime is really fun, but it has a few downsides.&amp;nbsp; You we are the 'second' JIT that MS has written.&amp;nbsp; As such the knee-jerk reaction of testers is not to consult the spec and see if what we're doing is different, but acceptable.&amp;nbsp; Instead they blindly compare it to the first JIT (the x86 JIT) and if it's different and it breaks their test, it must be wrong.&amp;nbsp; As we all know, 2 different implementations of the same spec are going to behave differently.&lt;/p&gt; &lt;p&gt;The biggest difference I see is that the AMD64 JIT has borrowed a lot of code and optimizations from the native AMD64 compiler.&amp;nbsp; Because of this, we perform some optimizations that are 100% legal according to the CLR spec, but that are certainly unexpected by those who have been using the x86 JIT for a while.&amp;nbsp; Almost all of these examples stem from end users not writing proper thread safe code.&lt;/p&gt; &lt;p&gt;Here's a real example from System.Collections.Hashtable:&lt;/p&gt; &lt;p&gt;&lt;code&gt;private bucket[] buckets;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;public virtual bool ContainsKey(Object key) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (key == null) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint seed;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint incr;&lt;br /&gt;&lt;strong&gt;&lt;font color="#008000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Take a snapshot of buckets, in case another thread resizes table&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bucket[] lbuckets = buckets;&lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint hashcode = InitHash(key, &lt;strong&gt;lbuckets.Length&lt;/strong&gt;, out seed, out incr);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int&amp;nbsp; ntry = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bucket b;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int bucketNumber = (int) (seed % (uint)&lt;strong&gt;lbuckets.Length&lt;/strong&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; do {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b = &lt;strong&gt;lbuckets&lt;/strong&gt;[bucketNumber];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (b.key == null) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (((b.hash_coll &amp;amp;&amp;nbsp; 0x7FFFFFFF) == hashcode) &amp;amp;&amp;amp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; KeyEquals (b.key, key))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bucketNumber = (int) (((long)bucketNumber + incr)% (uint)&lt;strong&gt;lbuckets.Length&lt;/strong&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } while (b.hash_coll &amp;lt; 0 &amp;amp;&amp;amp; ++ntry &amp;lt; lbuckets.Length);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;I added the emphasis.&amp;nbsp; Notice the comment that indicates the code is assuming that &lt;code&gt;this.buckets&lt;/code&gt; will change on another thread. With the x86 JIT, simply copying the member into a local was enough.&amp;nbsp; However, the AMD64 JIT applied some simple copy-propagation to this code and realized that since the this pointer was already enregistered, it was easy to access &lt;code&gt;this.buckets&lt;/code&gt; as a simple indirection. So the AMD64 JIT completely ignores the local copy.&amp;nbsp;At this point some of you might be thinking that was an illegal optimization.&amp;nbsp; It's not.&amp;nbsp; Go read the specs and study your compiler theory.&lt;/p&gt; &lt;p&gt;There is exactly one thing needed to correct this method.&amp;nbsp; Its the volatile keyword.&amp;nbsp; By simply marking the buckets member as being volatile, then the JIT &lt;strong&gt;cannot&lt;/strong&gt; add or remove reads or writes to it, thus it cannot copy-prop.&lt;/p&gt; &lt;p&gt;As a side note, I believe this code really is fine even if the buckets array does get bigger on another thread.&amp;nbsp; It would only have a problem it buckets got smaller after bucketNumber was calculated, but before it was used to index into the array.&amp;nbsp; Don't quote me on this, but&amp;nbsp;I vaguely remember that Hashtable never does resize smaller, so this really is a total non-issue, but still a good example.&lt;/p&gt; &lt;p&gt;--Grant&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=226355" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Shameless Plug</title><link>http://blogs.msdn.com/grantri/archive/2004/08/12/213661.aspx</link><pubDate>Thu, 12 Aug 2004 18:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:213661</guid><dc:creator>grantri</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/grantri/comments/213661.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=213661</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=213661</wfw:comment><description>&lt;p&gt;Personally I think the MS marketing team really did rop the ball.&amp;nbsp; They we're so busy promoting .NET that when VC 7.0 (aka 2002) and VC 7.1 (2003) shipped they forgot to mention all the tons of cool purely-native improvements in the product.&amp;nbsp; Well now in Whidbey (8.0 Beta 1 is availible for &lt;a href="http://lab.msdn.microsoft.com/express/visualc/"&gt;download&lt;/a&gt;), they've finally got the right idea.&amp;nbsp; Yes, we're still doing a&amp;nbsp;lot of cool .NET stuff for C++ (so you can play with the hardware &lt;strong&gt;and&lt;/strong&gt; enjoy a garbage collector), but we're also taking some time to mention all the other &lt;a href="http://lab.msdn.microsoft.com/library/en-us/dv_vcedit/html/11321bfc-2def-4d4d-89f9-db8d5635e797.asp"&gt;stuff&lt;/a&gt; that's been done: better standards conformance, better native code-gen, support for the latest instruction sets and processors, more secure CRT APIs, jsut to name a few.&lt;/p&gt; &lt;p&gt;Anyway, some people in the VC org have put together an online chat where you ask real MS workers about the next version of VC!&lt;/p&gt; &lt;div dir="ltr"&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt; &lt;hr id="null" /&gt; &lt;/span&gt;&lt;/font&gt;&lt;/div&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p class="MsoNormal"&gt;&lt;b&gt;&lt;font face="Times New Roman" size="3"&gt;&lt;span style="FONT-WEIGHT: bold; FONT-SIZE: 12pt"&gt;Online Chat: Visual C++ 2005 Beta&lt;/span&gt;&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Join the Visual C++ team to discuss your questions and comments on the Beta &lt;br /&gt;release of Visual C++ 2005. Whether you are a first-time user of the Visual &lt;br /&gt;C++ Express Edition Beta (&lt;font size="2"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;&lt;a title="http" href="http://lab.msdn.microsoft.com/express/visualc"&gt;&lt;font title="http" size="3"&gt;&lt;span title="http" style="FONT-SIZE: 12pt"&gt;http://lab.msdn.microsoft.com/express/visualc&lt;/span&gt;&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/font&gt;) or &lt;br /&gt;an experienced developer exploring the full Visual Studio 2005 suite, we &lt;br /&gt;want to answer your questions to provide you with a smooth development &lt;br /&gt;experience. So please bring your questions and issues to our attention and &lt;br /&gt;get the answers you need from the Visual C++ team.&lt;br /&gt;&lt;br /&gt;August 19, 2004&lt;br /&gt;12:00 - 1:00 P.M. Pacific time&lt;br /&gt;3:00 - 4:00 P.M. Eastern time&lt;br /&gt;19:00 - 20:00 GMT&lt;br /&gt;&lt;br /&gt;Chat time for cities world-wide:&lt;br /&gt;&lt;font size="2"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;&lt;a title="http" href="http://www.timeanddate.com/worldclock/fixedtime.html?day=19&amp;amp;month=8&amp;amp;year=2004&amp;amp;hour=12&amp;amp;min=0&amp;amp;sec=0&amp;amp;p1=234&amp;amp;sort=1"&gt;&lt;font title="http" size="3"&gt;&lt;span title="http" style="FONT-SIZE: 12pt"&gt;http://www.timeanddate.com/worldclock/fixedtime.html?day=19&amp;amp;month=8&amp;amp;year=2004&amp;amp;hour=12&amp;amp;min=0&amp;amp;sec=0&amp;amp;p1=234&amp;amp;sort=1&lt;/span&gt;&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/font&gt;To add this chat to you calendar:&lt;br /&gt;&lt;font size="2"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;&lt;a title="http" href="http://msdn.microsoft.com/chats/outlook_reminders/MSDN_VC2005B_Aug19_04.ics"&gt;&lt;font title="http" size="3"&gt;&lt;span title="http" style="FONT-SIZE: 12pt"&gt;http://msdn.microsoft.com/chats/outlook_reminders/MSDN_VC2005B_Aug19_04.ics&lt;/span&gt;&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/font&gt;For more info on MSDN chats, including other upcoming developer chats, chat&lt;br /&gt;archives, and other info see &lt;font size="2"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;&lt;a title="http" href="http://www.msdn.microsoft.com/chats"&gt;&lt;font title="http" size="3"&gt;&lt;span title="http" style="FONT-SIZE: 12pt"&gt;http://www.msdn.microsoft.com/chats&lt;/span&gt;&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;font size="2"&gt;&lt;span style="FONT-SIZE: 10pt"&gt; &lt;p class="MsoNormal" dir="ltr" style="MARGIN-RIGHT: 0px"&gt;&lt;font size="3"&gt; &lt;hr id="null" /&gt; &lt;/font&gt;&lt;/p&gt; &lt;p class="MsoNormal" dir="ltr" style="MARGIN-RIGHT: 0px"&gt;&lt;font size="3"&gt;--Grant&lt;/font&gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=213661" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Trade-offs</title><link>http://blogs.msdn.com/grantri/archive/2004/08/05/209059.aspx</link><pubDate>Thu, 05 Aug 2004 17:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:209059</guid><dc:creator>grantri</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/grantri/comments/209059.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=209059</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=209059</wfw:comment><description>&lt;P&gt;It seems like a lot of the time we (as software developers) are forced to make trade-offs.&amp;nbsp; Choosing between 2 algorithms that solve the same problem, but with different characteristics.&amp;nbsp; Sometimes it's an easy choice: option #1 is O(1) and option #2 is O(n^3).&amp;nbsp; Sometimes we're forced to compare apples and oranges: option #1 runs as O(1), but uses memory as O(n^2) and option #2 runs as O(n) and uses memory as O(n).&lt;/P&gt;
&lt;P&gt;The thing I've been pondering lately is if we should be always striving to make the best trade-offs, or if we should we be redefining the problems so that it's always an easy choice?&lt;/P&gt;
&lt;P&gt;The current problem I struggling with in the compiler space is accuracy versus effeciency.&amp;nbsp; Specifically in the case of exceptional flow control.&amp;nbsp; Everbody would love a compiler that modelled the control flow of exceptions smartly enough to be able to do really advanced optimizations (dead-store, common sub-expression elimination, constant propigation, SSA, etc.) across&amp;nbsp; try/catch/finally blocks (and of course get it right).&amp;nbsp; However properly modelling such flow often results in some very comples flow graphs that tend kill the throughput of most optimizers especially if the algorithms happens to be O(n) or greater where n is the number of edges.&lt;/P&gt;
&lt;P&gt;So basically we're looking at several ideas that are 'accurate enough' to do al of the desired optimizations while still not bloating the flow graph with a large number of edges that would slow down those optimizations.&amp;nbsp; Of course even in that statement, we need to clearly define what 'accurate enough' is and how fast is fast.&amp;nbsp; Thos terms change greatly between different compilers (JIT, pre-JIT, stand-alone compiler, etc.)&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=209059" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Why doesn't the C# compiler accept /resource:*.resources?</title><link>http://blogs.msdn.com/grantri/archive/2004/07/19/187811.aspx</link><pubDate>Mon, 19 Jul 2004 20:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:187811</guid><dc:creator>grantri</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/grantri/comments/187811.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=187811</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=187811</wfw:comment><description>&lt;P&gt;Well, here I am finally getting back to this.&lt;/P&gt;
&lt;P&gt;In my &lt;A href="http://blogs.msdn.com/grantri/archive/2004/04/05/108049.aspx"&gt;previous post&lt;/A&gt;&amp;nbsp;on resources, I glossed over one issue.&amp;nbsp; Not all managed resources are exactly what they seem.&amp;nbsp; Specifically at the metadata/compiler level, there is a table that simply points to the resource and gives it a name.&amp;nbsp; This is very similar to how Win32 native resources work.&amp;nbsp; A lot of managed code &lt;EM&gt;assumes&lt;/EM&gt; that data stored there is a .resources file.&amp;nbsp; There is actually a magic cookie value that is at the very beginning of the header for .resources files, but that's not exactly a guarantee that what follows really is a .resources file.&amp;nbsp; That is why the compiler and ALink allow you to embed anything you want as a resource.&amp;nbsp; Likewise &lt;A href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemreflectionassemblyclassgetmanifestresourcestreamtopic1.asp"&gt;Assembly.GetManifestResourceStream&lt;/A&gt;, returns just a stream.&amp;nbsp; You have to know what data is in the stream.&lt;/P&gt;
&lt;P&gt;As a side note, given this architecture, it seems like the metadata for 'managed' resources adds no value over the existing native Win32 resource format.&amp;nbsp; So it seems like another case of &lt;A href="http://blogs.msdn.com/grantri/archive/2004/06/03/147941.aspx"&gt;NIH&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Way back before we actually had a good idea of what an assembly was (and before we had any tools that created them) the frameworks team just used raw .resources files sitting on the disk in the application directory.&amp;nbsp; When they moved over to real assemblies, they decided to keep the same&amp;nbsp;naming scheme.&amp;nbsp; This led the compiler team (well basically just me) to come up with the novel idea of using the resource's filename as the default name for the resource.&amp;nbsp; That way they didn't have to type the filename twice.&lt;/P&gt;
&lt;P&gt;The problem here is that we weren't thinking about the big picture and how this would look to an end user who hadn't seen the intermediate steps.&amp;nbsp; As a convention most people name their source files according to the class inside it.&amp;nbsp; Thus it would make sense to name a .resource file after the resources inside it, but that doesn't mean we should default it.&amp;nbsp; In fact if I were to do it all over again I would make 2 big changes:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Never default the name, always make it explicit.&amp;nbsp; However, place the name of the resources somehow in the .resources and .resx file itself, rather than on the command-line.&amp;nbsp; Then the designers could do proper code-spit without relying on things like the default namespace or the hidden correlation between the class name and the .resources name.&amp;nbsp; Also we wouldn't have to have a long ugly command-line option to specify the name.&lt;/LI&gt;
&lt;LI&gt;Get rid of the metadata for managed resources, and just use native Win32 resources.&amp;nbsp; Yes the .resources file would still be embedded in the .rsrc section, but we wouldn't need all new tools and APIs to deal with managed resources versus native resources.&amp;nbsp; You also wouldn't have ugly discrepancies like when you set the icon for your main form, but forget to set it as the application icon (which gets it into the Win32 resources, which is where the OS/shell looks).&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;I still think it would be possible to have managed resource embedded into the .rsrc section, but since they store things in different formats (like icons) it wouldn't help much.&lt;/P&gt;
&lt;P&gt;Basically given the fact that I wanted resource names to be explicit, thats the main reason I pushed for not allowing wildcards.&amp;nbsp; There was also the confusion about whether wildcards should be applied recursively.&amp;nbsp; So I guess the end result was that nobody foresaw a huge customer demand, and the few people that cared (like me) seemed moderately opposed.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=187811" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Resources/default.aspx">Resources</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Alignment</title><link>http://blogs.msdn.com/grantri/archive/2004/07/14/183524.aspx</link><pubDate>Wed, 14 Jul 2004 22:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:183524</guid><dc:creator>grantri</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/grantri/comments/183524.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=183524</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=183524</wfw:comment><description>&lt;P&gt;I've seen this come up in conversations a few times so I thought others might be interested in it too.&lt;/P&gt;
&lt;P&gt;First off, I think since the large majority of us use x86-based processors we forget that one day in our CS or EE class where they talked about alignment.&amp;nbsp; So technically this should just be a refresher course.&amp;nbsp; The reason it needs refreshing is because x86 is letting it's market dominance slip and more and more of us are wanting our apps to run on other processors.&amp;nbsp; Also remember that &lt;EM&gt;most&lt;/EM&gt; of this doesn't apply to managed code, but &lt;EM&gt;&lt;STRONG&gt;some&lt;/STRONG&gt;&lt;/EM&gt; of it does, so don't just stop reading because you use C# and or VB and never use pointers.&lt;/P&gt;
&lt;P&gt;From here on out I'm going to use ARM-based chips as my example just because I know the most about them.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;What is Alignment?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The easiest way to think of it is that all of your computer's memory is just one big array of a given type (starting at address 0), and thus every time you read or write memory, you're just reading or writing from the array.&amp;nbsp; In the case of 32-bit integers, this means that you'll never need the lower order 2 bits of any address because they'll always be zero.&amp;nbsp; In the case of 64-bit integers, the low order 3 bits will always be zero.&amp;nbsp; The reason for this lies all the way down at the CPU level.&lt;/P&gt;
&lt;P&gt;Many (maybe even all) CPUs offer instructions to load&amp;nbsp;difference sized&amp;nbsp;values from a memory address into a register.&amp;nbsp; For ARM-based chips this is ld (for load dword, 4 bytes), lh (load half-word, 2 bytes), lb (load byte).&amp;nbsp; The ARM CPU further restricts that the address used for the loads must be properly aligned according to the data being loaded.&amp;nbsp; For DWORDs, the address must be 4-byte aligned (the low-order 2 buts must be 0), for WORDs it must be 2-byte aligned (the low-order bit must be 0), etc.&amp;nbsp; If the address is not properly aligned, the CPU will throw and exception (similar to how fp-exceptions occur or divide-by-zero, etc.).&amp;nbsp; My best guess for why they do it is because they want to make sure that all 4 bytes of a DWORD are in the same page, or something to do with the memory bus, etc.&amp;nbsp; Consider loading a DWORD from 0xFFFFFFFE: Byte 0 is at 0xFFFFFFFE, Byte 1 is at 0xFFFFFFFF, Byte 2 is at 0x00000000, and Byte 3 is at 0x00000001!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Why is Alignment Important?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The short answer is that if you violate alignment your application will get an exception if you run it on just about any other CPU besides x86.&amp;nbsp; This includes PocketPCs, a ton of WindowsCE devices, IA64-based machines, etc.&amp;nbsp; Now for the interesting part: even on x86 alignment matters.&amp;nbsp; Several of the MMX, SSE, and SSE/2 instructions perform significantly better if the memory addresses involved are properly aligned, and some of them will even raise exceptions in certain modes!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;So how to 'Align' everything?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The easiest way is to just not fool with the compiler/OS.&amp;nbsp; The compiler will automatically layout locals and parameters on properly aligned addresses.&amp;nbsp; The same goes for malloc, realloc, new, etc.&amp;nbsp; The problem arises when you allocate one thing, but then treat it like something else.&amp;nbsp; The simple case is that you allocate an array&amp;nbsp;of 2 shorts (16-bit integers), and then cast it to a pointer to an int (32-bit integer).&amp;nbsp; Here you are playing Russian Roulette and have a 50% chance of getting an alignment fault.&amp;nbsp; The reason is that any even address is properly aligned for shorts, but only half of those addresses are properly aligned for ints.&amp;nbsp; Some memory allocators try to help by always aligning everything to the maximum alignment, but that needlessly wastes memory.&lt;/P&gt;
&lt;P&gt;If you do need to treat something as 2 different types, then create a union so the compiler knows about it.&amp;nbsp; Then the compiler will always align it to the maximum alignment needed for any of the union members.&lt;/P&gt;
&lt;P&gt;The other big way to unalign something is to override the compiler's default layout mechanism.&amp;nbsp; In C# this is done using &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeinteropserviceslayoutkindclasstopic.asp"&gt;LayoutKind.Explicit&lt;/A&gt;, in C++ it's done by anything that messes with the default packing size (&lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/pragm_22.asp"&gt;#pragma pack&lt;/A&gt; and related).&amp;nbsp; When you do this the compiler/OS will properly align the start of the struct, but you are responsible for making sure that the interior members are properly aligned.&amp;nbsp; Example:&lt;/P&gt;
&lt;P&gt;struct MisAligned {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte someValue;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int someOtherValue;&lt;BR&gt;};&lt;/P&gt;
&lt;P&gt;By default someValue will be at offset 0, and someOtherValue will be at offset 4.&amp;nbsp; Yes, that 'wastes'&amp;nbsp; 3 bytes for each MisAligned struct, but that often isn't a big deal.&amp;nbsp; If you mess with the packing size, like set it down to 1, someOtherValue will be at offset 1.&amp;nbsp; This means that someOtherValue will always be at an odd offset and thus always cause an alignment fault!&lt;/P&gt;
&lt;P&gt;So the rule is don't mess with how the compiler lays out fields in a struct.&amp;nbsp; If you need to pack more data into less space, re-arrange the data so the compiler doesn't have to waste space on padding.&amp;nbsp; The easiest way to do this is to always organize your fields according to size: largest to smallest.&amp;nbsp; For C++ this applies to classes and structs.&amp;nbsp; For managed code (C# and VB) this really only applies to structs.&amp;nbsp; The reason is that classes default to LayoutKind.Auto which means that the runtime is free to reorder the fields within the type.&amp;nbsp; The runtime currently orders fields to get minimal padding.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;What if I have to have unaligned data?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Well, needless to say there are situations where data is going to be unaligned.&amp;nbsp; The most common case is reading stuff off of disk or networks where data has been tightly packed.&amp;nbsp; For C++ you simply need to declare pointers using the UNALIGNED macro (like&amp;nbsp;int UNALIGNED * pui).&amp;nbsp; Then when the compiler generates code to dereference this pointer it will generate code to do the right thing and not cause an alignment fault even if the address is not properly aligned.&lt;/P&gt;
&lt;P&gt;At this point one might ask why&amp;nbsp;aren't all pointers marked as UNALIGNED?&amp;nbsp; The short answer is that it's slower.&amp;nbsp; Some CPUs help by having unaligned variants of all load and store instructions.&amp;nbsp; These variants are generally slower than&amp;nbsp;their aligned counter parts but not too bad (if you want to find out how bad find a PocketPC and run some tests, but remember this is entirely CPU dependent).&amp;nbsp; Other CPUs force the compiler to just generate a byte-by-byte load or store and possibly waste several registers in the process (sort of like a memcpy from a register to memory).&amp;nbsp; This I think is the slowest, but again it is entirely architecture dependent.&lt;/P&gt;
&lt;P&gt;It is a macro so that your code is more portable.&amp;nbsp; On alignment sensitive architectures, it is defined to be __unaligned, otherwise it is just ignored.&lt;/P&gt;
&lt;P&gt;MSIL took a different approach.&amp;nbsp; Instead of decorating a pointer, it modifies the actual load or store opcodes with an &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemreflectionemitopcodesclassunalignedtopic.asp"&gt;unaligned&lt;/A&gt; opcode prefix.&amp;nbsp; This prefix instructs the JIT/runtime to generate the proper code just like the native compiler does for the UNALIGNED macro.&amp;nbsp; Unfortunately the C# language designers chose not to complicate the C# language in any way to expose this.&amp;nbsp; So if you want to load or store unaligned data in C# you'll have to use something else (there was talk about adding helper routines to mscorlib.dll to do the unaligned load or store), or manually do the byte-by-byte load or store.&lt;/P&gt;
&lt;P&gt;Here's a good random &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcepbguide5/html/wce50conAvoidingAlignmentErrors.asp"&gt;link&lt;/A&gt; with more docs on the subject.&lt;/P&gt;
&lt;P&gt;Hope you enjoyed the reading, and possibly learned a few things.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=183524" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Command-line Trivia</title><link>http://blogs.msdn.com/grantri/archive/2004/07/08/177513.aspx</link><pubDate>Thu, 08 Jul 2004 17:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:177513</guid><dc:creator>grantri</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/grantri/comments/177513.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=177513</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=177513</wfw:comment><description>&lt;P&gt;So many people have wondered why the C# compiler isn't smarter about some of it's command-line arguments.&amp;nbsp; Here's a summary of the type of questions I hope to answer in this post:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Why doesn't the C# compiler accept /reference:*.dll?&lt;/LI&gt;
&lt;LI&gt;Why doesn't the C# compiler accept /addmodule:*.*?&lt;/LI&gt;
&lt;LI&gt;Why doesn't the C# compiler just automatically add all the dependencies? Or if I'm only using a.dll, why do I have to reference b.dll?&lt;/LI&gt;
&lt;LI&gt;Why do I have to add /reference:MyAssembly.dll, but not /reference:System.dll&lt;/LI&gt;
&lt;LI&gt;Why doesn't the C# compiler accept /resource:*.resources?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Basically it's because of our premise that our developers/users are smart and don't like too much black magic going on under the covers.&amp;nbsp; We thought that developers would always want to know &lt;STRONG&gt;exactly&lt;/STRONG&gt; what their dependencies are.&amp;nbsp; By forcing you to put each dependency on the command-line you have to think up front what your dependencies are.&amp;nbsp; Wild-cards do not help that.&lt;/P&gt;
&lt;P&gt;The second issue arises from lookup rules.&amp;nbsp; In the native world, C/C++ programmers use the LIB environment variable to tell the linker where to go looking for LIB files (The C# compiler also uses the environment variable to find references).&amp;nbsp; Classic VB users would just open the add component dialog box, which basically walked HKEY_CLASSES_ROOT for all registered COM/ActiveX type libraries, objects and interfaces.&amp;nbsp; The down-side to the VB model was that developers often had no way of knowing which components he or she had rights to redistribute.&amp;nbsp; So that is one reason why the C# compiler &lt;STRONG&gt;never&lt;/STRONG&gt; looks in the GAC for references.&amp;nbsp; Our model is &amp;#8220;GAC is for runtime, use someplace else for compile-time&amp;#8220;.&amp;nbsp; That's why the framework SDK installs assemblies like System.dll into 2 places: the GAC for runtime and the SDK directory for compile-time.&lt;/P&gt;
&lt;P&gt;Does anybody really fully understand fusion's complicated lookup/binding rules? Especially when you throw in machine, user, application and publisher policy?&amp;nbsp; I don't.&amp;nbsp; Every time they're explained to me, they all seem to have good reasons and make sense for applications, but not for developers.&amp;nbsp; Instead we went with a classical path-based lookup.&amp;nbsp; MSDN clearly explains which directories the compiler will search and in what order in &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cscomp/html/vclrflibspecifyassemblyreferencelocations.asp"&gt;this article&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;As far as assembly dependencies go the compiler possibly could do better, but it would end up having rules very similar to fusion.&amp;nbsp; The simplest problem is that there is no guaranteed relationship between an assembly name and the actual file name for that assembly.&amp;nbsp; I think that's one reason why fusion has such complex rules.&amp;nbsp; Thus to look up second order dependencies the compiler would either need to rely on fusion (which we already decided was bad) or put in some black magic of our own.&amp;nbsp; The decision was to put the developer in change and force them to declare exactly which files to use as dependencies.&lt;/P&gt;
&lt;P&gt;For module dependencies it gets even harder.&amp;nbsp; With module dependencies I suppose we could do slightly better.&amp;nbsp; However multi-file assemblies are extremely rare and the metadata doesn't help us out as much as we'd like.&amp;nbsp; Now unlike assembly references, module references actually contain the filename.&amp;nbsp; The problem arises because the ModuleRef table also stores other stuff, like all the filenames from DllImportAttributes.&amp;nbsp; Thus there's no easy way to determine the difference between a dependent managed module and a native dependency that's not part of the assembly (like kernel32.dll for instance).&amp;nbsp; Also when building an assembly it is possible that not all the modules will be referenced.&amp;nbsp; So again we decided to put the programmer in change and make you explicitly list all of them.&lt;/P&gt;
&lt;P&gt;Many of you have noticed that you never need to explicitly reference Microsoft assemblies like mscorlib.dll or System.dll.&amp;nbsp; The main reason I guess is because we're self-centered.&amp;nbsp; Well I guess not completely because we do have some almost good reasons.&lt;/P&gt;
&lt;P&gt;First I'll get to mscorlib.dll.&amp;nbsp; In case you haven't noticed there a few types the compiler just &lt;STRONG&gt;needs&lt;/STRONG&gt; regardless of what you're compiling.&amp;nbsp; These include (this is by no means a complete list)&amp;nbsp;System.Int32, System.Object, System.String, System.Delegate, System.Enum, etc.&amp;nbsp; All of these are in mscorlib.dll.&amp;nbsp; Because these always have to be there, everybody (except those actually building mscorlib.dll) need to reference mscorlib.dll, so the compiler tries to save you a little redundancy by always implicitly referencing mscorlib.dll.&amp;nbsp; If you don't want it, you have to turn it off with &lt;A href="http://msdn.microsoft.com/library/en-us/cscomp/html/vcrefNostdlibDoNotImportStandardLibrary.asp"&gt;/nostdlib&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Now for System.dll and it's friends.&amp;nbsp; Here is where i think we might have gone a little overboard.&amp;nbsp; Even though we wanted you the developer to have total control of your dependencies, it became a little unwieldy to compile simple winforms apps from the command-line.&amp;nbsp; At one point we had up-wards of 40 different assemblies you needed to reference!&amp;nbsp; Since we already had response files we thought we make a 'default' response file that just&amp;nbsp;referenced all of those assemblies, since &lt;EM&gt;everybody wants them&lt;/EM&gt; (sarcasm intended).&amp;nbsp; So we created a default response file that always gets used in every command-line compilation unless turned off with &lt;A href="http://msdn.microsoft.com/library/en-us/cscomp/html/vclrfNoconfigIgnoreCscrsp.asp"&gt;/noconfig&lt;/A&gt;.&amp;nbsp; Please go look in your runtime directory right now at csc.rsp (it's right next to csc.exe).&amp;nbsp; Please take some time to edit it to suite your needs, it can save you a lot of typing!&amp;nbsp; Go ahead and add you favorite references, and remove the ones you don't want.&amp;nbsp; Also feel free to add flags to adjust the default command-line options.&amp;nbsp; You can always override them by using the opposite flag on the actual command-line.&lt;/P&gt;
&lt;P&gt;The resources question is just going to have to wait for another day.&amp;nbsp; I think it really is worthy of it's own post.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=177513" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Multi-file Assemblies: What and How</title><link>http://blogs.msdn.com/grantri/archive/2004/07/07/175745.aspx</link><pubDate>Wed, 07 Jul 2004 21:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:175745</guid><dc:creator>grantri</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/grantri/comments/175745.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=175745</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=175745</wfw:comment><description>&lt;P&gt;I intentionally left out the 'why' because only you as developer on your own product can decide why a given programming feature should or shouldn't be used.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;First the easy part: What&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Multi-file assemblies are simply assemblies that consist of more than one file.&amp;nbsp; That begs the question of what is an assembly.&amp;nbsp; Although I've seen several very amorphous descriptions of what an assembly is&amp;nbsp; logically or theoretically, from my pragmatic compiler background I prefer to describe it how I see it literally.&amp;nbsp; An assembly is a grouping of 1 or more files, where exactly one of those files contains an assembly manifest.&lt;/P&gt;
&lt;P&gt;Now I know that there exists such things a native manifests, but in this case, I'm referring to the AssemblyDef record in normal metadata.&amp;nbsp; If you run ildasm, it will be the details of the tree node named &amp;#8220;MANIFEST&amp;#8221;.&amp;nbsp; There is a section that begins with &amp;#8220;.assembly 'SomeName' { ... } &amp;#8220;.&amp;nbsp; That same manifest will also contain a list of FileDef records that list what other files physically constitute the assembly.&amp;nbsp; The interesting tidbit here is that the files within the assembly that do not contain the manifest also do not contain any back-pointers to the assembly that they 'belong' to.&amp;nbsp; Thus a single file can be a part of several different assemblies, but don't do it because it will cause tons of other problems down the road.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;How:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;There are several ways to create a multi-file assembly.&amp;nbsp; None of them can be done inside the IDE with C# or VB.NET without special build rules or custom actions.&amp;nbsp; (Yes C++ &lt;EM&gt;can&lt;/EM&gt; do it inside the IDE).&amp;nbsp; So from here on out I will assume everybody knows how to use the command-line tools.&lt;/P&gt;
&lt;P&gt;First you need to build a file without an assembly manifest for C# and VB.NET just use &amp;#8220;/target:module&amp;#8221;.&amp;nbsp; The next step is to include that module into an assembly.&amp;nbsp; This is where things get a little tricky, and due to my lack of complete knowledge, I'll limit myself to C#.&amp;nbsp; First of all there is no tool that MS sells that will allow you to modify an assembly once it has been built.&amp;nbsp; There are type identity issues, code-signing issues, etc.&amp;nbsp; You always need to save building the manifest file (the file that contains the assembly manifest) until the very last step.&amp;nbsp; You can include an existing module into an assembly as you build it by simply adding &amp;#8220;/addmodule:&amp;lt;module name&amp;gt;&amp;#8221; to your command line.&amp;nbsp; However the compiler is just plain not as efficient as it could be if you did things slightly differently.&lt;/P&gt;
&lt;P&gt;Did you know the C# compiler allows you to produce multiple output files in a single compilation?&amp;nbsp; It does.&amp;nbsp; The gotcha is that it will only produce one assembly, so if you have multiple &amp;#8220;/out&amp;#8221; or &amp;#8220;/target&amp;#8221; switches on the same command-line, you're building a multi-file assembly!&amp;nbsp; This is logically the same as doing the 2 step &amp;#8220;/target:module&amp;#8221; and then &amp;#8220;/addmodule:&amp;#8221;, except the compiler is slightly more efficient in some of the metadata.&lt;/P&gt;
&lt;P&gt;If you're really desperate to show off your geek-ness, you can build a multi-file assembly using al.exe, but it's not worth it.&amp;nbsp; See my previous &lt;A href="http://blogs.msdn.com/grantri/archive/2004/04/12/111875.aspx"&gt;post&lt;/A&gt; on why you should use csc.exe instead.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Why:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;OK so I changed my mind, I will give you a few possible reasons for why you might want to use multi-file assemblies.&amp;nbsp; Just remember though that these are just &lt;EM&gt;possible&lt;/EM&gt; reasons.&amp;nbsp; You still must think and decide for yourself in &lt;STRONG&gt;your&lt;/STRONG&gt; situation!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Multi-language assemblies&lt;/STRONG&gt;: this I think is the biggest possible reason.&amp;nbsp; Maybe some of your programmers only know VB, maybe you need to interop with some old C/C++ code.&amp;nbsp; The list goes on forever because there are an infinite number of reasons why you might want to write part of your application in different languages.&amp;nbsp; Now you could put each language in&amp;nbsp;its own assembly, but then you get stuck with a poor organization model, and the choice of making certain things public when they really shouldn't be&amp;nbsp; and trying to compensate by using fancy security or obfuscation.&amp;nbsp; As I pointed out in another &lt;A href="http://blogs.msdn.com/grantri/archive/2004/06/01/145724.aspx"&gt;post&lt;/A&gt;, this reason is going away (now you can have multi-language single-file assemblies)!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Incremental Download&lt;/STRONG&gt;: back when we were still trying to figure out what exactly an assembly was, this was the poster-child example for multi-file assemblies.&amp;nbsp; Now I think it was really more of a straw-man.&amp;nbsp; Either way I'm not even sure we actually support it, but the original idea was that in a Internet or web-based application you would put the 'common-use' code in one file and the less-used code in another file.&amp;nbsp; That way user that only needed MyReallySmallReallyFast90PercentCase functionality got it, and weren't punished with long download times&amp;nbsp;for MyReallyBigAndSlow10PercentCase that few people needed.&amp;nbsp; The app would download the small part, start running, and only download the other files (that contained the potentially bigger, and less frequently needed code) as needed.&amp;nbsp; It seems like a great idea on paper, but now that more and more people have broadband, I seriously question its value.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Linked Resources&lt;/STRONG&gt;: the idea here was that you had some file that was logically part of your assembly, but needed to be it's own file for some reason, possibly because some native API needed to read it and only accepted a file name argument.&amp;nbsp; Possibly because the file was itself a native DLL.&amp;nbsp; Possibly because you want the user to be able to modify it (like a splash screen bitmap or something).&amp;nbsp; At one point in the design we even had a flag on the FileDef record indicating that a given file was 'modifiable'.&amp;nbsp; I don't think that flag survived, and I know there's know way to set it with C#, VB, C++, or ALink.&amp;nbsp; This I think actually has some merit, but it is definitely not common.&lt;/P&gt;
&lt;P&gt;If you've got another good reason for multi-file assemblies, speak up, I'd love to hear about it.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=175745" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/ALink/default.aspx">ALink</category><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Exception Handling (Part 2 of 2)</title><link>http://blogs.msdn.com/grantri/archive/2004/06/28/167964.aspx</link><pubDate>Mon, 28 Jun 2004 17:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:167964</guid><dc:creator>grantri</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/grantri/comments/167964.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=167964</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=167964</wfw:comment><description>&lt;P&gt;Sorry it took so long to get to part 2.&lt;/P&gt;
&lt;P&gt;First up is the unwind info (I think it's the .XDATA, but don't quote me).&amp;nbsp; Basically there is a set of opcode sequences that are allowed in the prologue and epilogue, and there is some info in the describes what is happening in the prologue.&amp;nbsp; The OS can read that data (the unwind info) and figure out what registers were saved, the frame size, if there's a frame pointer register, and how big the prologue is, etc.&amp;nbsp; Each processor defines different things to store in the unwind info.&lt;/P&gt;
&lt;P&gt;Second is the exception info (I think it's the .PDATA).&amp;nbsp; This describes a bunch or ranges: the range of protected code (usually called a try body in high-level languages like C# or C++), the protector (the catch or finally body), a filter (like in VB.NET or SEH where you can have actual code executed to determine is a catch body is appropriate).&amp;nbsp; There is also usually a spot reserved int he PDATA for language specific stuff to be passed to the personality routine.&lt;/P&gt;
&lt;P&gt;So what happens when an exception is thrown?&amp;nbsp; Well on x86 the OS just walks the 'linked-list' of exception information stored at FS:[0], and calls the personality routine or filters (I'm a little fuzzy here)&amp;nbsp;to see if they want to 'catch' the exception.&amp;nbsp; On IA64 and AMD64 the OS has to walk the .PDATA.&amp;nbsp; Once the a handler is found the first pass has ended and a second pass begins.&amp;nbsp; All stack frames between where the exception occurred and the handler are unwound.&amp;nbsp; This is a joint effort between the OS and the personality routine.&amp;nbsp; The personality routine is responsible for running things like destructors and finally clauses at each stack level (like when you have nested try/finally blocks).&amp;nbsp; The OS does the physical unwinding by changing the stack pointer, frame pointer, instruction pointer, and restoring saved registers, accordingly.&amp;nbsp; I have no clue how this works on x86, but for AMD64 and IA64, the OS reads the XDATA and figures out what to do (generally this is just undoing the prologue).&lt;/P&gt;
&lt;P&gt;So the real point of all this was to see the differences.&amp;nbsp; In the code, for x86 the entry of a try body results in pushing a new exception record pointer into FS:[0].&amp;nbsp; This is generally just 2 opcodes: one to store the existing pointer into the new record, and one change FS:[0] to point&amp;nbsp;to the new record.&amp;nbsp; The end of the try body is indicated by restoring FS:[0]&amp;nbsp; to it's original value (popping the head off of the linked list).&lt;/P&gt;
&lt;P&gt;For AMD64 and IA64 there is &lt;STRONG&gt;nothing&lt;/STRONG&gt; in the code that indicates the start or end of a try body.&amp;nbsp; This seems like it would be better.&amp;nbsp; For the general case I think it is.&amp;nbsp; The ugly part comes into play when the try body doesn't exit normally (you have a goto or leave from inside the try body to someplace other than the end of the try/catch or try/finally block).&amp;nbsp; For x86 this just means you pop the exception record in more than one place, but for AMD64 and IA64 this means extra PDATA (and possibly XDATA).&amp;nbsp; Since everything is range based, and there's no way to encode something like &amp;#8220;everything in this range except the 5 sub-ranges&amp;#8221;, you end up breaking the range into a bunch of smaller ranges and duplicating all the handler info.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=167964" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Exception Handling (Part 1 of 2)</title><link>http://blogs.msdn.com/grantri/archive/2004/06/21/161868.aspx</link><pubDate>Tue, 22 Jun 2004 00:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:161868</guid><dc:creator>grantri</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/grantri/comments/161868.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=161868</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=161868</wfw:comment><description>&lt;P&gt;Anybody that done any programming on .NET has probably used some EH at least once or twice.&amp;nbsp; It all seems pretty natural and straight forward.&amp;nbsp; Well, I'm glad we can fool so many of you into thinking it's easy.&lt;/P&gt;
&lt;P&gt;What follows is a gross-over-simplification of EH, but still useful if you know nothing about EH.&lt;/P&gt;
&lt;P&gt;The short explanation is that the OS takes care of actually unwinding the stack, but relies on something called a 'Personality Routine' to determine what stuff to do at each stack level (like execute a finally, call a C++ destructor, etc.).&amp;nbsp; For x86 the OS and personality routines rely on an exception record stack that is&amp;nbsp;pointed to by&amp;nbsp;FS:[0].&amp;nbsp; Well on IA64 and AMD64 (and a few other architectures), it's a little different.&amp;nbsp; They are table based.&lt;/P&gt;
&lt;P&gt;With the stack based approach you actually have&amp;nbsp;instructions in your code that push and pop the exception state (like which finallys or catches to execute).&amp;nbsp; These correlate very nicely with some of the semantics .NET has.&amp;nbsp; The down side is that the pushing and popping seems rather inefficient, when simple static analysis can dictate what the EH stack would look like at any given point.&lt;/P&gt;
&lt;P&gt;So then we have PDATA and XDATA.&amp;nbsp; I don't know much about the exact difference (one is used more for unwinding info, the other more for exception info).&amp;nbsp; The general idea is to have a bunch of tables that state at a given&amp;nbsp;instruction address, here are the EH clauses that are in effect.&lt;/P&gt;
&lt;P&gt;I relate all this because I've recently been working on a bug where in certain cases the wrong&amp;nbsp;EH clause was being called.&amp;nbsp; This was a direct result of put opcodes in the wrong protected region (or to state it differently, having the protected regions protect too much).&amp;nbsp; This gets particularly interesting when you consider asynchronous EH (like ThreadAbortException).&lt;/P&gt;
&lt;P&gt;Hopefully tomorrow, I can finish this off.&amp;nbsp; Either way I think the real geeks will find this interesting.&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=161868" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item><item><title>Am I really this popular?</title><link>http://blogs.msdn.com/grantri/archive/2004/06/03/148050.aspx</link><pubDate>Thu, 03 Jun 2004 23:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:148050</guid><dc:creator>grantri</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/grantri/comments/148050.aspx</comments><wfw:commentRss>http://blogs.msdn.com/grantri/commentrss.aspx?PostID=148050</wfw:commentRss><wfw:comment>http://blogs.msdn.com/grantri/rsscomments.aspx?PostID=148050</wfw:comment><description>&lt;P&gt;I've noticed a lot of my links come from searches (primarily google).&amp;nbsp; Is that because I'm actually answering a lot of releavant information that people want to know?&amp;nbsp; Is it possibly because I happen to use all the magic keywords so that google pushes me to the top of its list?&lt;/P&gt;
&lt;P&gt;--Grant&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=148050" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/grantri/archive/tags/Work/default.aspx">Work</category></item></channel></rss>