Bug 156378 - tryGetById should be supported by the DFG/FTL
Summary: tryGetById should be supported by the DFG/FTL
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Keith Miller
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-04-07 16:40 PDT by Keith Miller
Modified: 2016-08-16 16:59 PDT (History)
5 users (show)

See Also:


Attachments
Patch (27.36 KB, patch)
2016-04-07 16:49 PDT, Keith Miller
no flags Details | Formatted Diff | Diff
Patch (40.74 KB, patch)
2016-04-08 14:28 PDT, Keith Miller
no flags Details | Formatted Diff | Diff
Patch (39.99 KB, patch)
2016-04-08 16:20 PDT, Keith Miller
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Keith Miller 2016-04-07 16:40:51 PDT
tryGetById should be supported by the DFG/FTL
Comment 1 Keith Miller 2016-04-07 16:49:00 PDT
Created attachment 275959 [details]
Patch
Comment 2 Geoffrey Garen 2016-04-08 11:16:27 PDT
/Volumes/Data/EWS/WebKit/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:979:66: error: cannot initialize a parameter of type 'GPRReg' (aka 'RegisterID') with an rvalue of type 'unsigned int'
        cachedGetById(node->origin.semantic, baseGPR, resultGPR, node->identifierNumber(), JITCompiler::Jump(), DontSpill, AccessType::GetPure);
                                                                 ^~~~~~~~~~~~~~~~~~~~~~~~
Comment 3 Keith Miller 2016-04-08 14:28:51 PDT
Created attachment 276043 [details]
Patch
Comment 4 Mark Lam 2016-04-08 15:39:57 PDT
Comment on attachment 276043 [details]
Patch

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

> Source/JavaScriptCore/ChangeLog:11
> +        we do not profile the result type. This profiling is unnessary for the current

typo: /unnessary/unnecessary/.
Comment 5 Filip Pizlo 2016-04-08 15:45:42 PDT
Comment on attachment 276043 [details]
Patch

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

I think you should reduce the code duplication in ByteCodeParser.

> Source/JavaScriptCore/bytecode/GetByIdStatus.cpp:78
> -    if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length))
> +    if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length) || instruction[0].u.opcode == LLInt::getOpcode(op_try_get_by_id))

Can you provide clarity on why you return NoInformation when LLInt saw a try_get_by_id?

> Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:1969
> +        forNode(node).makeBytecodeTop();

Why isn't this makeHeapTop()?  Can TryGetById return the empty value?  If not, then this should be HeapTop.

Also, it seems like you should add folding here that is like the folding we do in GetById.  If you don't add it, then please add a FIXME to that effect and link it to a bug!

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2889
> +void ByteCodeParser::handleTryGetById(int destinationOperand, Node* base, unsigned identifierNumber, const GetByIdStatus& getByIdStatus)

This method looks like it duplicates a *ton* of code with handleGetById.  Please try to make them common.

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2896
> +    if (!getByIdStatus.isSimple() || !getByIdStatus.numVariants() || !Options::useAccessInlining()) {
> +        set(VirtualRegister(destinationOperand),
> +            addToGraph(TryGetById, OpInfo(identifierNumber), OpInfo(SpecBytecodeTop), base));
> +        return;
> +    }

This is identical to the first case in handleGetById.

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2904
> +        if (!isFTL(m_graph.m_plan.mode)
> +            || !Options::usePolymorphicAccessInlining()) {
> +            set(VirtualRegister(destinationOperand),
> +                addToGraph(TryGetById, OpInfo(identifierNumber), OpInfo(SpecBytecodeTop), base));
> +            return;
> +        }

Identical.

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2932
> +        // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
> +        //    optimal, if there is some rarely executed case in the chain that requires a lot
> +        //    of checks and those checks are not watchpointable.
> +        for (const GetByIdVariant& variant : getByIdStatus.variants()) {
> +            ASSERT(variant.intrinsic() == NoIntrinsic);
> +
> +            if (variant.conditionSet().isEmpty()) {
> +                cases.append(MultiGetByOffsetCase(
> +                    variant.structureSet(),
> +                    GetByOffsetMethod::load(variant.offset())));
> +                continue;
> +            }
> +
> +            GetByOffsetMethod method = planLoad(variant.conditionSet());
> +            if (!method) {
> +                set(VirtualRegister(destinationOperand),
> +                    addToGraph(TryGetById, OpInfo(identifierNumber), OpInfo(SpecBytecodeTop), base));
> +                return;
> +            }
> +
> +            cases.append(MultiGetByOffsetCase(variant.structureSet(), method));
> +        }
> +
> +        if (m_graph.compilation())
> +            m_graph.compilation()->noticeInlinedGetById();

So very identical.

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2940
> +        // 2) Emit a MultiGetByOffset
> +        MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
> +        data->cases = cases;
> +        data->identifierNumber = identifierNumber;
> +        set(VirtualRegister(destinationOperand),
> +            addToGraph(MultiGetByOffset, OpInfo(data), OpInfo(SpecBytecodeTop), base));
> +        return;

Identical.

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2957
> +    if (m_graph.compilation())
> +        m_graph.compilation()->noticeInlinedGetById();
> +    set(VirtualRegister(destinationOperand), loadedValue);
> +}

Looks like this is the only place where this is different from handleGetById.  Basically, you want handleGetById to have a flag or something that tells it that it's the Try variant, and then you want handleGetById to return early here.

> Source/JavaScriptCore/dfg/DFGClobberize.h:859
> +    case TryGetById: {
> +        read(JSCell_structureID);
> +        read(JSObject_butterfly);
> +        AbstractHeap heap(NamedProperties, node->identifierNumber());
> +        read(heap);
> +        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node));
> +        return;
> +    }

Are you sure about this?  Can't TryGetById call any arbitrary GetOwnPropertySlot?

I think that the more conservative thing to do for now is remove the def() and make this read(Heap).
Comment 6 Keith Miller 2016-04-08 15:58:01 PDT
Comment on attachment 276043 [details]
Patch

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

>> Source/JavaScriptCore/bytecode/GetByIdStatus.cpp:78
>> +    if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length) || instruction[0].u.opcode == LLInt::getOpcode(op_try_get_by_id))
> 
> Can you provide clarity on why you return NoInformation when LLInt saw a try_get_by_id?

Because we don't have an LLInt cache for TryGetById. In the long run I do think that an LLInt cache should be added.

>> Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:1969
>> +        forNode(node).makeBytecodeTop();
> 
> Why isn't this makeHeapTop()?  Can TryGetById return the empty value?  If not, then this should be HeapTop.
> 
> Also, it seems like you should add folding here that is like the folding we do in GetById.  If you don't add it, then please add a FIXME to that effect and link it to a bug!

Yeah, it should be HeapTop. I will fix.

The folding that we do here will not help any current uses of this operation since they all use values on the prototype. I'll create a bug though.

>> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2889
>> +void ByteCodeParser::handleTryGetById(int destinationOperand, Node* base, unsigned identifierNumber, const GetByIdStatus& getByIdStatus)
> 
> This method looks like it duplicates a *ton* of code with handleGetById.  Please try to make them common.

Yeah, you are probably right. I will change it.

>> Source/JavaScriptCore/dfg/DFGClobberize.h:859
>> +    }
> 
> Are you sure about this?  Can't TryGetById call any arbitrary GetOwnPropertySlot?
> 
> I think that the more conservative thing to do for now is remove the def() and make this read(Heap).

Changed.
Comment 7 Keith Miller 2016-04-08 16:20:49 PDT
Created attachment 276051 [details]
Patch
Comment 8 WebKit Commit Bot 2016-04-09 20:38:43 PDT
Comment on attachment 276051 [details]
Patch

Clearing flags on attachment: 276051

Committed r199279: <http://trac.webkit.org/changeset/199279>
Comment 9 WebKit Commit Bot 2016-04-09 20:38:46 PDT
All reviewed patches have been landed.  Closing bug.
Comment 10 Filip Pizlo 2016-08-16 16:59:17 PDT
Comment on attachment 276051 [details]
Patch

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

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:3867
> +            handleGetById(currentInstruction[1].u.operand, SpecHeapTop, base, identifierNumber, getByIdStatus, AccessType::GetPure);

You should be able to produce a type prediction here.

Filed: https://bugs.webkit.org/show_bug.cgi?id=160921

> Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:177
> +            changed |= setPrediction(SpecBytecodeTop);

It's wrong to ever use any of the Top's in prediction propagation phase.  This tells the prediction propagator that this node will *definitely* return values of all types, which causes us to assume the worst for all downstream code.

Filed: https://bugs.webkit.org/show_bug.cgi?id=160921