Bug 144731

Summary: Special-case Int32 values in JSON.stringify().
Product: WebKit Reporter: Andreas Kling <kling>
Component: JavaScriptCoreAssignee: Andreas Kling <kling>
Status: RESOLVED FIXED    
Severity: Normal CC: benjamin, ggaren, kling, msaboff
Priority: P2 Keywords: Performance
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch none

Description Andreas Kling 2015-05-07 01:43:19 PDT
We should have a fast-path in JSON.stringify() for Int32 values.
Comment 1 Andreas Kling 2015-05-07 01:46:10 PDT
Created attachment 252580 [details]
Patch

Boom:

json-stringify-tinderbox        60.176+-8.602      ^      39.277+-1.632         ^ definitely 1.5321x faster
Comment 2 Michael Saboff 2015-05-07 07:50:44 PDT
Comment on attachment 252580 [details]
Patch

r=me
Comment 3 Andreas Kling 2015-05-07 08:58:01 PDT
Comment on attachment 252580 [details]
Patch

Clearing flags on attachment: 252580

Committed r183928: <http://trac.webkit.org/changeset/183928>
Comment 4 Andreas Kling 2015-05-07 08:58:06 PDT
All reviewed patches have been landed.  Closing bug.
Comment 5 Darin Adler 2015-05-07 09:14:27 PDT
Comment on attachment 252580 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=252580&action=review

> Source/JavaScriptCore/runtime/JSONObject.cpp:403
>      if (value.isNumber()) {
> -        double number = value.asNumber();
> -        if (!std::isfinite(number))
> -            builder.appendLiteral("null");
> -        else
> -            builder.appendECMAScriptNumber(number);
> +        if (value.isInt32())
> +            builder.appendNumber(value.asInt32());
> +        else {
> +            double number = value.asNumber();
> +            if (!std::isfinite(number))
> +                builder.appendLiteral("null");
> +            else
> +                builder.appendECMAScriptNumber(number);
> +        }
>          return StringifySucceeded;
>      }

Would we get better code by writing these two separately? I ask because isNumber() is really just isInt32() || isDouble(). And if isDouble() is true then we can call asDouble(). Maybe the compiler will fold everything for us and remove all the dead code, but I think it would be nicer to just write it out like this:

    if (value.isInt32()) {
        builder.appendNumber(value.asInt32());
        return StringifySucceeded;
    }

    if (value.isDouble()) {
        double number = value.asDouble();
        if (!std::isfinite(number))
            builder.appendLiteral("null");
        else
            builder.appendECMAScriptNumber(number);
        return StringifySucceeded;
    }
Comment 6 Geoffrey Garen 2015-05-07 11:25:15 PDT
c:\cygwin\home\buildbot\webkit\webkitbuild\release\include\private\javascriptcore\X86Assembler.h(1811): error C2039: 'twoByteOp64' : is not a member of 'JSC::X86Assembler::X86InstructionFormatter' [C:\cygwin\home\buildbot\WebKit\Source\JavaScriptCore\JavaScriptCore.vcxproj\LLInt\LLIntOffsetsExtractor\LLIntOffsetsExtractor.vcxproj]
          c:\cygwin\home\buildbot\webkit\webkitbuild\release\include\private\javascriptcore\X86Assembler.h(2332) : see declaration of 'JSC::X86Assembler::X86InstructionFormatter'
Comment 7 Geoffrey Garen 2015-05-07 11:25:39 PDT
Oops! Wrong bug :(.