On Jul 19, 2012, at 2:58 PM, Balazs Kelemen <kbal...@webkit.org> wrote:

> On 07/19/2012 11:27 PM, Maciej Stachowiak wrote:
>> On Jul 10, 2012, at 8:52 AM, Brady Eidson<beid...@apple.com>  wrote:
>> 
>>> On Jul 10, 2012, at 5:25 AM, Alexis Menard<alexis.men...@openbossa.org>  
>>> wrote:
>>> 
>>>> On Mon, Jul 9, 2012 at 6:53 PM, Brady Eidson<beid...@apple.com>  wrote:
>>>>> On Jul 9, 2012, at 2:43 PM, Alexis Menard<alexis.men...@openbossa.org>  
>>>>> wrote:
>>>>> 
>>>>>> Hi,
>>>>>> 
>>>>>> For those who "secretly" use printf debugging :). I know the
>>>>>> recommended way is to use a debugger and it's not the point of this
>>>>>> discussion.
>>>>> A lot of us do this, and sometimes it's necessary.  I agree with the 
>>>>> gripe and support adding something easier.
>>>>> 
>>>>>> So I propose wtf() and its stream operator.
>>>>>> 
>>>>>> Usage :
>>>>>> 
>>>>>> wtf()<<"Hello"<<"World"<<3<<4.53322323; will output : Hello World 3 
>>>>>> 4.53322
>>>>> There is no reason to bring in stream operators - that are willfully 
>>>>> absent from WebCore - just for debugging.
>>>>> 
>>>> But it's really nice for that purpose, and somehow match std::cout
>>> And we quite purposefully don't use std::cout in the project.
>>> 
>>>>> Overloading functions works just as well.
>>>> I'm not sure to understand what you mean hereā€¦
>>> I mean relying on C++'s overloading of functions for the different types 
>>> you'd like to printf debug.
>>> 
>>> void debug(WebCore::String&);
>>> void debug(WebCore::Frame*);
>>> void debug(WebCore::Node*);
>>> 
>>> etc etc etc.
>>> 
>>> debug(someFrame);
>>> debug(someNode);
>>> debug(someString);
>>> 
>>> Especially that last one would help me from remembering how to type 
>>> "printf("%s", someString.utf8().data())" which is all I've ever really 
>>> wanted.
>> In principle, we could also have this support multiple arguments, so you 
>> could write:
>> 
>> debug("frame: ", someFrame, " node: ", someNode, " string", someString);
>> 
>> This would be no more verbose than the<<  style, but could compile to a 
>> single function call at the call site and therefore could be relatively 
>> compact. I would find this easier to deal with than a unary function or a 
>> printf-style format string. The way you'd do this is by defining template 
>> functions which call a unary overloaded function for each argument:
>> 
>> template<typename A, typename B>  debug(A a, B b)
>> {
>>     debug(a);
>>     debug(b);
>> }
>> 
>> template<typename A, typename B, typename C>  debug(A a, B b, C c)
>> {
>>     debug(a);
>>     debug(b);
>>     debug(c);
>> }
>> 
>> template<typename A, typename B, typename C, typename D>  debug(A a, B b, C 
>> c, D d)
>> {
>>     debug(a);
>>     debug(b);
>>     debug(c);
>>     debug(d);
>> }
>> 
>> ... and so on up to some reasonable number of arguments.
> 
> 
> But neither these compile to a single function call. Or we could define 
> simple inline debug() overrides but we could also do that with the stream 
> operator. And anyway, if the actual calls are not supposed to land than it 
> doesn't matter how compact it is. For me the stream operator is a bit nicer.

This goal of not landing the actual calls is nice in theory, but we quickly 
found in JSC that it's impractical.  We did this for a while: each time someone 
needed to debug something, they'd add some printf's, find the bug, delete the 
printf's, land the change.  Then the next person to debug the code would add in 
the same printf's, find another bug, delete those printf's again, and land the 
change.  Rinse and repeat.  This got horrible very quickly.

So instead, we decided on the dataLog() API, and made the policy that for any 
sizeable set of dataLog() calls that were found to be useful for a particular 
debugging task, we would encapsulate them behind a dump() method on the 
relevant class and land that method along with the fixes.  The thing that we 
would _not_ land is the call to the dump() method.  The point being that it's 
easier to add back in the call to dump(), than it is to add back in all of the 
calls to dataLog().  And even in some cases, we did land the call to dump(), 
behind a check of some flag that can be flipped in one .cpp file or via an 
environment variable, or even via a command-line switch if you wanted to go so 
far.

We've found that this is nicer in the long term and has sped up debugging for a 
lot of common scenarios.

Thus, I tend to think that we want to come up with a debug printing API that 
produces sufficiently compact code that this is practical.  I kind of like 
Maciej's approach; I think it could work, though you risk template bloat.  A 
good compiler and linker will probably reduce that bloat, but such things are 
imperfect.

It's also possible that our obsession with ensuring that the debug code (i.e. 
the innards of the dump() methods) is compact is unfounded.  With the dataLog() 
API I found that it generally adds much less than 1% to the size of the 
JavaScriptCore library, so we declared victory.  But maybe we can give 
ourselves more latitude and use a nicer API.

In summary, I'm not arguing against having a nicer debug API than the current 
dataLog(); I'm arguing quite the opposite: that we should investigate such an 
API, and that the API should be robust enough that we land not just the API but 
also allow for the landing of dump() methods for classes that webkittens find 
themselves having to frequently add printf-style debugging to.

-F


> 
> -kbalazs
> _______________________________________________
> webkit-dev mailing list
> webkit-dev@lists.webkit.org
> http://lists.webkit.org/mailman/listinfo/webkit-dev

_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-dev

Reply via email to