Bug 177907 - The prototype cache should be aware of the Executable it generates a Structure for
Summary: The prototype cache should be aware of the Executable it generates a Structur...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Saam Barati
URL:
Keywords: InRadar
: 177952 (view as bug list)
Depends on: 177987
Blocks:
  Show dependency treegraph
 
Reported: 2017-10-04 17:37 PDT by Saam Barati
Modified: 2017-10-10 00:59 PDT (History)
14 users (show)

See Also:


Attachments
WIP (13.54 KB, patch)
2017-10-05 19:20 PDT, Saam Barati
no flags Details | Formatted Diff | Diff
WIP (44.79 KB, patch)
2017-10-09 13:08 PDT, Saam Barati
no flags Details | Formatted Diff | Diff
WIP (44.77 KB, patch)
2017-10-09 13:12 PDT, Saam Barati
no flags Details | Formatted Diff | Diff
WIP (44.81 KB, patch)
2017-10-09 15:04 PDT, Saam Barati
no flags Details | Formatted Diff | Diff
patch (48.77 KB, patch)
2017-10-09 19:04 PDT, Saam Barati
fpizlo: review+
Details | Formatted Diff | Diff
patch for landing (46.84 KB, patch)
2017-10-09 23:14 PDT, Saam Barati
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Saam Barati 2017-10-04 17:37:18 PDT
Keith found a bug. Basically, we null out the JSObject*'s prototype pointer in the prototype map for poly proto today. This may cause one Executable to end up with a Structure* meant for the create_this of a separate Executable. This mean's it'll have the wrong InlineWatchpointSet&, causing it to potentially pessimize another executable's allocation.
Comment 1 Saam Barati 2017-10-05 12:43:48 PDT
(In reply to Saam Barati from comment #0)
> Keith found a bug. Basically, we null out the JSObject*'s prototype pointer
> in the prototype map for poly proto today. This may cause one Executable to
> end up with a Structure* meant for the create_this of a separate Executable.
> This mean's it'll have the wrong InlineWatchpointSet&, causing it to
> potentially pessimize another executable's allocation.

My analysis is slightly wrong here. An executable will write over another executable's poly proto watchpoint if the prototypes happen to be the same.
Comment 2 Saam Barati 2017-10-05 12:45:17 PDT
(In reply to Saam Barati from comment #1)
> (In reply to Saam Barati from comment #0)
> > Keith found a bug. Basically, we null out the JSObject*'s prototype pointer
> > in the prototype map for poly proto today. This may cause one Executable to
> > end up with a Structure* meant for the create_this of a separate Executable.
> > This mean's it'll have the wrong InlineWatchpointSet&, causing it to
> > potentially pessimize another executable's allocation.
> 
> My analysis is slightly wrong here. An executable will write over another
> executable's poly proto watchpoint if the prototypes happen to be the same.
And the other inputs also have to be the same to the prototype structure cache.

So something like this I think:

let p = {};

function foo() {
    class C {
        constructor() { this.x = 20; }
    };
    C.prototype = p;
}

function bar() {
    class C {
        constructor() { this.x = 20; }
    };
    C.prototype = p;
}

foo();
bar();
Comment 3 Saam Barati 2017-10-05 15:57:43 PDT
*** Bug 177952 has been marked as a duplicate of this bug. ***
Comment 4 Saam Barati 2017-10-05 19:20:07 PDT
Created attachment 322967 [details]
WIP

Waiting on experimental results for:
https://bugs.webkit.org/show_bug.cgi?id=177987
Comment 5 Filip Pizlo 2017-10-07 12:21:38 PDT
Comment on attachment 322967 [details]
WIP

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

> Source/JavaScriptCore/heap/Heap.cpp:1414
> +    vm()->prototypeMap.removeDeadEntries();

I don't think it's necessary.

> Source/JavaScriptCore/runtime/PrototypeMap.cpp:40
> +    PrototypeMapKey key { makePolyProtoStructure ? nullptr : prototype, inlineCapacity, classInfo, globalObject, executable };

Why can't you just make the first field be a prototype-or-executable field?

> Source/JavaScriptCore/runtime/PrototypeMap.cpp:104
> +bool PrototypeMapKey::isDead()
> +{
> +    return (m_prototype && !Heap::isMarked(m_prototype))
> +        || (m_globalObject && !Heap::isMarked(m_globalObject))
> +        || (m_executable && !Heap::isMarked(m_executable));
> +}
> +
> +void PrototypeMap::removeDeadEntries()
> +{
> +    m_prototypes.removeIf([&] (JSObject* object) {
> +        return !Heap::isMarked(object);
> +    });
> +
> +    m_structures.removeIf([&] (auto& entry) {
> +        Structure* structure = entry.value;
> +        return !Heap::isMarked(structure) || entry.key.isDead();
> +    });

I was wrong about us needing this.  The lifetime of the structure takes care of everything for us, since the key is a bunch of raw pointers.
Comment 6 Saam Barati 2017-10-07 18:08:24 PDT
Comment on attachment 322967 [details]
WIP

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

>> Source/JavaScriptCore/runtime/PrototypeMap.cpp:104
>> +    });
> 
> I was wrong about us needing this.  The lifetime of the structure takes care of everything for us, since the key is a bunch of raw pointers.

We don’t need it in ToT, however, I think we need it with this patch. The Structure won’t keep the Executable alive
Comment 7 Saam Barati 2017-10-09 12:30:57 PDT
Comment on attachment 322967 [details]
WIP

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

>> Source/JavaScriptCore/runtime/PrototypeMap.cpp:40
>> +    PrototypeMapKey key { makePolyProtoStructure ? nullptr : prototype, inlineCapacity, classInfo, globalObject, executable };
> 
> Why can't you just make the first field be a prototype-or-executable field?

Yeah we can do this.
Comment 8 Saam Barati 2017-10-09 13:08:47 PDT
Created attachment 323201 [details]
WIP
Comment 9 Build Bot 2017-10-09 13:11:35 PDT
Attachment 323201 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/runtime/StructureCache.cpp:30:  Alphabetical sorting problem.  [build/include_order] [4]
ERROR: Source/JavaScriptCore/runtime/VM.h:51:  Alphabetical sorting problem.  [build/include_order] [4]
Total errors found: 2 in 17 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 10 Saam Barati 2017-10-09 13:12:51 PDT
Created attachment 323205 [details]
WIP
Comment 11 Build Bot 2017-10-09 13:14:23 PDT
Attachment 323205 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/runtime/StructureCache.cpp:30:  Alphabetical sorting problem.  [build/include_order] [4]
ERROR: Source/JavaScriptCore/runtime/VM.h:51:  Alphabetical sorting problem.  [build/include_order] [4]
Total errors found: 2 in 17 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 12 Saam Barati 2017-10-09 15:04:40 PDT
Created attachment 323229 [details]
WIP
Comment 13 Build Bot 2017-10-09 15:52:43 PDT
Attachment 323229 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/runtime/StructureCache.cpp:30:  Alphabetical sorting problem.  [build/include_order] [4]
ERROR: Source/JavaScriptCore/runtime/VM.h:51:  Alphabetical sorting problem.  [build/include_order] [4]
Total errors found: 2 in 17 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 14 Saam Barati 2017-10-09 16:39:10 PDT
Comment on attachment 322967 [details]
WIP

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

>>> Source/JavaScriptCore/runtime/PrototypeMap.cpp:40
>>> +    PrototypeMapKey key { makePolyProtoStructure ? nullptr : prototype, inlineCapacity, classInfo, globalObject, executable };
>> 
>> Why can't you just make the first field be a prototype-or-executable field?
> 
> Yeah we can do this.

No, we actually can't do this. This is the whole point of the patch. We must ensure that we get different structures before determining that we go poly proto. The chains of structures generating from the create_this belonging to the bytecode of an Executable must have different poly proto watchpoints.
Comment 15 Saam Barati 2017-10-09 19:04:01 PDT
Created attachment 323268 [details]
patch
Comment 16 Build Bot 2017-10-09 19:05:02 PDT
Attachment 323268 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/runtime/StructureCache.cpp:30:  Alphabetical sorting problem.  [build/include_order] [4]
ERROR: Source/JavaScriptCore/runtime/VM.h:51:  Alphabetical sorting problem.  [build/include_order] [4]
Total errors found: 2 in 20 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 17 Saam Barati 2017-10-09 19:07:04 PDT
Comment on attachment 323268 [details]
patch

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

> Source/JavaScriptCore/runtime/StructureCache.h:44
> -    explicit PrototypeMap(VM& vm)
> +    StructureCache(VM& vm)

I'll add bad explicit here.
Comment 18 Saam Barati 2017-10-09 23:14:39 PDT
Created attachment 323283 [details]
patch for landing
Comment 19 Build Bot 2017-10-09 23:16:05 PDT
Attachment 323283 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/runtime/StructureCache.cpp:30:  Alphabetical sorting problem.  [build/include_order] [4]
Total errors found: 1 in 19 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 20 WebKit Commit Bot 2017-10-10 00:58:31 PDT
Comment on attachment 323283 [details]
patch for landing

Clearing flags on attachment: 323283

Committed r223125: <http://trac.webkit.org/changeset/223125>
Comment 21 WebKit Commit Bot 2017-10-10 00:58:33 PDT
All reviewed patches have been landed.  Closing bug.
Comment 22 Radar WebKit Bug Importer 2017-10-10 00:59:40 PDT
<rdar://problem/34905866>