Global objects should be able to use TLCs to allocate from different blocks from...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Feb 2018 03:50:30 +0000 (03:50 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Feb 2018 03:50:30 +0000 (03:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182227

Source/JavaScriptCore:

Reviewed by JF Bastien.

This uses TLCs to create at least `minimumDistanceBetweenCellsFromDifferenOrigins` bytes of
distance between objects from different origins, using the following combination of things. For
short lets refer to that constant as K.

- Since r227721, LargeAllocation puts K bytes padding at the end of each allocation.

- Since r227718, MarkedBlock puts at least K bytes in its footer.

- Since r227617, global objects can have their own TLCs, which make them allocate from a
  different set of blocks than other global objects. The TLC of a global object comes into
  effect when you enter the VM via that global object.

- With this change, TLCs and blocks both have security origins. A TLC will only use blocks that
  share the same security origin or empty blocks (in which case we zero the block and change
  its security origin).

WebCore determines the TLC-GlobalObject mapping. By default, global objects would simply use
the VM's default TLC. WebCore makes it so that DOM windows (but not worker global objects) get
a TLC based on their document's SecurityOrigin.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* heap/BlockDirectory.cpp:
(JSC::BlockDirectory::findBlockForAllocation):
(JSC::BlockDirectory::prepareForAllocation):
* heap/BlockDirectory.h:
* heap/LocalAllocator.cpp:
(JSC::LocalAllocator::LocalAllocator):
(JSC::LocalAllocator::reset):
(JSC::LocalAllocator::~LocalAllocator):
(JSC::LocalAllocator::allocateSlowCase):
(JSC::LocalAllocator::tryAllocateWithoutCollecting):
* heap/LocalAllocator.h:
(JSC::LocalAllocator::tlc const):
* heap/MarkStackMergingConstraint.cpp:
* heap/MarkStackMergingConstraint.h:
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::Handle::associateWithOrigin):
* heap/MarkedBlock.h:
(JSC::MarkedBlock::Handle::securityOriginToken const):
* heap/SecurityOriginToken.cpp: Added.
(JSC::uniqueSecurityOriginToken):
* heap/SecurityOriginToken.h: Added.
* heap/ThreadLocalCache.cpp:
(JSC::ThreadLocalCache::create):
(JSC::ThreadLocalCache::ThreadLocalCache):
(JSC::ThreadLocalCache::allocateData):
(JSC::ThreadLocalCache::installSlow):
* heap/ThreadLocalCache.h:
(JSC::ThreadLocalCache::securityOriginToken const):
* heap/ThreadLocalCacheInlines.h:
(JSC::ThreadLocalCache::install):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::JSGlobalObject):
(JSC::JSGlobalObject::createThreadLocalCache):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::threadLocalCache):
(JSC::JSGlobalObject::threadLocalCache const): Deleted.
* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::VMEntryScope):
(JSC::VMEntryScope::~VMEntryScope):
* runtime/VMEntryScope.h:

Source/WebCore:

Reviewed by Daniel Bates and Chris Dumez.

No new tests because no change in behavior.

Adopt JSC TLC API to put distance between objects from different security origins. WebCore has
a subclass of ThreadLocalCache that supports hash-consing based on the relevant origin data
using the existing SecurityOriginHash. It's Document's job to initiate this, but all of the
logic is in WebCore::OriginThreadLocalCache.

Workers don't opt into this. They just get the VM's default TLC all the time.

* ForwardingHeaders/heap/ThreadLocalCache.h: Added.
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::JSDOMGlobalObject):
* bindings/js/JSDOMGlobalObject.h:
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::JSDOMWindowBase):
* dom/Document.cpp:
(WebCore::Document::initSecurityContext):
(WebCore::Document::threadLocalCache):
* dom/Document.h:
* page/OriginThreadLocalCache.cpp: Added.
(WebCore::threadLocalCacheMap):
(WebCore::OriginThreadLocalCache::create):
(WebCore::OriginThreadLocalCache::~OriginThreadLocalCache):
(WebCore::OriginThreadLocalCache::OriginThreadLocalCache):
* page/OriginThreadLocalCache.h: Added.
* page/SecurityOrigin.cpp:
(WebCore::SecurityOrigin::passesFileCheck const):
(WebCore::SecurityOrigin::setEnforcesFilePathSeparation):
(WebCore::SecurityOrigin::toString const):
(WebCore::SecurityOrigin::enforceFilePathSeparation): Deleted.
* page/SecurityOrigin.h:
(WebCore::SecurityOrigin::enforcesFilePathSeparation const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228149 268f45cc-cd09-0410-ab3c-d52691b4dbfc

33 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/heap/BlockDirectory.cpp
Source/JavaScriptCore/heap/BlockDirectory.h
Source/JavaScriptCore/heap/LocalAllocator.cpp
Source/JavaScriptCore/heap/LocalAllocator.h
Source/JavaScriptCore/heap/MarkStackMergingConstraint.cpp
Source/JavaScriptCore/heap/MarkStackMergingConstraint.h
Source/JavaScriptCore/heap/MarkedBlock.cpp
Source/JavaScriptCore/heap/MarkedBlock.h
Source/JavaScriptCore/heap/SecurityOriginToken.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/SecurityOriginToken.h [new file with mode: 0644]
Source/JavaScriptCore/heap/ThreadLocalCache.cpp
Source/JavaScriptCore/heap/ThreadLocalCache.h
Source/JavaScriptCore/heap/ThreadLocalCacheInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/VMEntryScope.cpp
Source/JavaScriptCore/runtime/VMEntryScope.h
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/heap/ThreadLocalCache.h [new file with mode: 0644]
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
Source/WebCore/bindings/js/JSDOMGlobalObject.h
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/page/OriginThreadLocalCache.cpp [new file with mode: 0644]
Source/WebCore/page/OriginThreadLocalCache.h [new file with mode: 0644]
Source/WebCore/page/SecurityOrigin.cpp
Source/WebCore/page/SecurityOrigin.h

index f155c4f..0f7e1e4 100644 (file)
@@ -513,6 +513,7 @@ set(JavaScriptCore_FORWARDING_HEADERS
     heap/MutatorState.h
     heap/RegisterState.h
     heap/RunningScope.h
+    heap/SecurityOriginToken.h
     heap/SimpleMarkingConstraint.h
     heap/SlotVisitor.h
     heap/SlotVisitorInlines.h
index 4944595..40d2def 100644 (file)
@@ -1,3 +1,73 @@
+2018-01-28  Filip Pizlo  <fpizlo@apple.com>
+
+        Global objects should be able to use TLCs to allocate from different blocks from each other
+        https://bugs.webkit.org/show_bug.cgi?id=182227
+
+        Reviewed by JF Bastien.
+        
+        This uses TLCs to create at least `minimumDistanceBetweenCellsFromDifferenOrigins` bytes of
+        distance between objects from different origins, using the following combination of things. For
+        short lets refer to that constant as K.
+        
+        - Since r227721, LargeAllocation puts K bytes padding at the end of each allocation.
+        
+        - Since r227718, MarkedBlock puts at least K bytes in its footer.
+        
+        - Since r227617, global objects can have their own TLCs, which make them allocate from a
+          different set of blocks than other global objects. The TLC of a global object comes into
+          effect when you enter the VM via that global object.
+        
+        - With this change, TLCs and blocks both have security origins. A TLC will only use blocks that
+          share the same security origin or empty blocks (in which case we zero the block and change
+          its security origin).
+        
+        WebCore determines the TLC-GlobalObject mapping. By default, global objects would simply use
+        the VM's default TLC. WebCore makes it so that DOM windows (but not worker global objects) get
+        a TLC based on their document's SecurityOrigin.
+        
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * heap/BlockDirectory.cpp:
+        (JSC::BlockDirectory::findBlockForAllocation):
+        (JSC::BlockDirectory::prepareForAllocation):
+        * heap/BlockDirectory.h:
+        * heap/LocalAllocator.cpp:
+        (JSC::LocalAllocator::LocalAllocator):
+        (JSC::LocalAllocator::reset):
+        (JSC::LocalAllocator::~LocalAllocator):
+        (JSC::LocalAllocator::allocateSlowCase):
+        (JSC::LocalAllocator::tryAllocateWithoutCollecting):
+        * heap/LocalAllocator.h:
+        (JSC::LocalAllocator::tlc const):
+        * heap/MarkStackMergingConstraint.cpp:
+        * heap/MarkStackMergingConstraint.h:
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::Handle::associateWithOrigin):
+        * heap/MarkedBlock.h:
+        (JSC::MarkedBlock::Handle::securityOriginToken const):
+        * heap/SecurityOriginToken.cpp: Added.
+        (JSC::uniqueSecurityOriginToken):
+        * heap/SecurityOriginToken.h: Added.
+        * heap/ThreadLocalCache.cpp:
+        (JSC::ThreadLocalCache::create):
+        (JSC::ThreadLocalCache::ThreadLocalCache):
+        (JSC::ThreadLocalCache::allocateData):
+        (JSC::ThreadLocalCache::installSlow):
+        * heap/ThreadLocalCache.h:
+        (JSC::ThreadLocalCache::securityOriginToken const):
+        * heap/ThreadLocalCacheInlines.h:
+        (JSC::ThreadLocalCache::install):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::JSGlobalObject):
+        (JSC::JSGlobalObject::createThreadLocalCache):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::threadLocalCache):
+        (JSC::JSGlobalObject::threadLocalCache const): Deleted.
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::VMEntryScope):
+        (JSC::VMEntryScope::~VMEntryScope):
+        * runtime/VMEntryScope.h:
+
 2018-02-05  Don Olmstead  <don.olmstead@sony.com>
 
         JavaScriptCore files should not be included relatively
index de3e290..a8e3442 100644 (file)
                0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A451460CBAB00131F8F /* ValueRecovery.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A461460CBAB00131F8F /* VirtualRegister.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A4A1460CD6B00131F8F /* DataFormat.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F42B3C3201EC9FF00357031 /* SecurityOriginToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F42B3C2201EC9FD00357031 /* SecurityOriginToken.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F431738146BAC69007E3890 /* ListableHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F431736146BAC65007E3890 /* ListableHandler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */; };
                0F45703D1BE45F0A0062A629 /* AirReportUsedRegisters.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */; };
                0F426A451460CBAB00131F8F /* ValueRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueRecovery.h; sourceTree = "<group>"; };
                0F426A461460CBAB00131F8F /* VirtualRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VirtualRegister.h; sourceTree = "<group>"; };
                0F426A4A1460CD6B00131F8F /* DataFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataFormat.h; sourceTree = "<group>"; };
+               0F42B3C0201EB50900357031 /* Allocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Allocator.cpp; sourceTree = "<group>"; };
+               0F42B3C2201EC9FD00357031 /* SecurityOriginToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityOriginToken.h; sourceTree = "<group>"; };
                0F431736146BAC65007E3890 /* ListableHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ListableHandler.h; sourceTree = "<group>"; };
                0F4570361BE44C910062A629 /* AirEliminateDeadCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirEliminateDeadCode.cpp; path = b3/air/AirEliminateDeadCode.cpp; sourceTree = "<group>"; };
                0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirEliminateDeadCode.h; path = b3/air/AirEliminateDeadCode.h; sourceTree = "<group>"; };
                142E312A134FF0A600AFADB5 /* heap */ = {
                        isa = PBXGroup;
                        children = (
-                               0F75A054200D25EF0038E2CF /* Allocator.h */,
-                               0F75A05D200D25F10038E2CF /* AllocatorInlines.h */,
-                               0F75A059200D25F00038E2CF /* LocalAllocator.cpp */,
-                               0F75A057200D25F00038E2CF /* LocalAllocator.h */,
-                               0F75A05A200D25F00038E2CF /* LocalAllocatorInlines.h */,
-                               0F75A058200D25F00038E2CF /* ThreadLocalCache.cpp */,
-                               0F75A055200D25EF0038E2CF /* ThreadLocalCache.h */,
-                               0F75A056200D25EF0038E2CF /* ThreadLocalCacheInlines.h */,
-                               0F75A05B200D25F10038E2CF /* ThreadLocalCacheLayout.cpp */,
-                               0F75A05C200D25F10038E2CF /* ThreadLocalCacheLayout.h */,
                                0FEC3C501F33A41600F59B6C /* AlignedMemoryAllocator.cpp */,
                                0FEC3C511F33A41600F59B6C /* AlignedMemoryAllocator.h */,
                                0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */,
                                0FDCE11B1FAE61F4006F3901 /* AllocationFailureMode.h */,
+                               0F42B3C0201EB50900357031 /* Allocator.cpp */,
+                               0F75A054200D25EF0038E2CF /* Allocator.h */,
                                0F30CB5D1FCE46B4004B5323 /* AllocatorForMode.h */,
+                               0F75A05D200D25F10038E2CF /* AllocatorInlines.h */,
                                0FB4677E1FDDA6E5003FCB09 /* AtomIndices.h */,
                                C2B916C414DA040C00CBAC86 /* BlockDirectory.cpp */,
                                C2B916C114DA014E00CBAC86 /* BlockDirectory.h */,
                                0F070A451D543A89006E7232 /* LargeAllocation.cpp */,
                                0F070A461D543A89006E7232 /* LargeAllocation.h */,
                                0F431736146BAC65007E3890 /* ListableHandler.h */,
+                               0F75A059200D25F00038E2CF /* LocalAllocator.cpp */,
+                               0F75A057200D25F00038E2CF /* LocalAllocator.h */,
+                               0F75A05A200D25F00038E2CF /* LocalAllocatorInlines.h */,
                                0F208AD61DF0925A007D3269 /* LockDuringMarking.h */,
                                14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */,
                                14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */,
                                0FD0E5EF1E46BF230006AB08 /* RegisterState.h */,
                                0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */,
                                0F2C63A91E4FA42C00C13839 /* RunningScope.h */,
+                               0F42B3C2201EC9FD00357031 /* SecurityOriginToken.h */,
                                0F4D8C761FCA3CF2001D32AC /* SimpleMarkingConstraint.cpp */,
                                0F4D8C771FCA3CF3001D32AC /* SimpleMarkingConstraint.h */,
                                C225494215F7DBAA0065E898 /* SlotVisitor.cpp */,
                                0FD79A2C1EBBBDB200DA88D3 /* Synchronousness.h */,
                                0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */,
                                0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */,
+                               0F75A058200D25F00038E2CF /* ThreadLocalCache.cpp */,
+                               0F75A055200D25EF0038E2CF /* ThreadLocalCache.h */,
+                               0F75A056200D25EF0038E2CF /* ThreadLocalCacheInlines.h */,
+                               0F75A05B200D25F10038E2CF /* ThreadLocalCacheLayout.cpp */,
+                               0F75A05C200D25F10038E2CF /* ThreadLocalCacheLayout.h */,
                                141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,
                                0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */,
                                0F4D8C721FC7A973001D32AC /* VisitCounter.h */,
                                0F7C39FF1C90C55B00480151 /* DFGOpInfo.h in Headers */,
                                A7D89CFE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h in Headers */,
                                0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */,
+                               0F42B3C3201EC9FF00357031 /* SecurityOriginToken.h in Headers */,
                                0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
                                0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
                                0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */,
index 86f56c1..8198802 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 Apple Inc. All rights reserved.
+// Copyright (C) 2017-2018 Apple Inc. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions
@@ -512,6 +512,7 @@ heap/MarkingConstraintSet.cpp
 heap/MarkingConstraintSolver.cpp
 heap/MutatorScheduler.cpp
 heap/MutatorState.cpp
+heap/SecurityOriginToken.cpp
 heap/SimpleMarkingConstraint.cpp
 heap/SlotVisitor.cpp
 heap/SpaceTimeMutatorScheduler.cpp
index dd89707..8446077 100644 (file)
@@ -33,6 +33,7 @@
 #include "JSCInlines.h"
 #include "MarkedBlockInlines.h"
 #include "SuperSampler.h"
+#include "ThreadLocalCacheInlines.h"
 #include "VM.h"
 #include <wtf/CurrentTime.h>
 
@@ -80,14 +81,20 @@ MarkedBlock::Handle* BlockDirectory::findEmptyBlockToSteal()
     return m_blocks[m_emptyCursor];
 }
 
-MarkedBlock::Handle* BlockDirectory::findBlockForAllocation()
+MarkedBlock::Handle* BlockDirectory::findBlockForAllocation(LocalAllocator& allocator)
 {
-    m_allocationCursor = (m_canAllocateButNotEmpty | m_empty).findBit(m_allocationCursor, true);
-    if (m_allocationCursor >= m_blocks.size())
-        return nullptr;
-    
-    setIsCanAllocateButNotEmpty(NoLockingNecessary, m_allocationCursor, false);
-    return m_blocks[m_allocationCursor];
+    for (;;) {
+        allocator.m_allocationCursor = (m_canAllocateButNotEmpty | m_empty).findBit(allocator.m_allocationCursor, true);
+        if (allocator.m_allocationCursor >= m_blocks.size())
+            return nullptr;
+        
+        size_t blockIndex = allocator.m_allocationCursor++;
+        MarkedBlock::Handle* result = m_blocks[blockIndex];
+        if (result->securityOriginToken() == allocator.tlc()->securityOriginToken()) {
+            setIsCanAllocateButNotEmpty(NoLockingNecessary, blockIndex, false);
+            return result;
+        }
+    }
 }
 
 MarkedBlock::Handle* BlockDirectory::tryAllocateBlock()
@@ -183,8 +190,6 @@ void BlockDirectory::prepareForAllocation()
             allocator->prepareForAllocation();
         });
     
-    m_allocationCursor = 0;
-    m_emptyCursor = 0;
     m_unsweptCursor = 0;
     
     m_eden.clearAll();
index 00dcd23..e78db56 100644 (file)
@@ -43,6 +43,7 @@ class Heap;
 class IsoCellSet;
 class MarkedSpace;
 class LLIntOffsetsExtractor;
+class ThreadLocalCache;
 class ThreadLocalCacheLayout;
 
 #define FOR_EACH_BLOCK_DIRECTORY_BIT(macro) \
@@ -162,12 +163,13 @@ public:
     void dumpBits(PrintStream& = WTF::dataFile());
     
 private:
-    friend class LocalAllocator;
     friend class IsoCellSet;
+    friend class LocalAllocator;
+    friend class LocalSideAllocator;
     friend class MarkedBlock;
     friend class ThreadLocalCacheLayout;
     
-    MarkedBlock::Handle* findBlockForAllocation();
+    MarkedBlock::Handle* findBlockForAllocation(LocalAllocator&);
     
     MarkedBlock::Handle* tryAllocateBlock();
     
@@ -184,8 +186,7 @@ private:
     
     // After you do something to a block based on one of these cursors, you clear the bit in the
     // corresponding bitvector and leave the cursor where it was.
-    size_t m_allocationCursor { 0 }; // Points to the next block that is a candidate for allocation.
-    size_t m_emptyCursor { 0 }; // Points to the next block that is a candidate for empty allocation (allocating in empty blocks).
+    size_t m_emptyCursor { 0 };
     size_t m_unsweptCursor { 0 }; // Points to the next block that is a candidate for incremental sweeping.
     
     unsigned m_cellSize;
index 6e38f32..514d088 100644 (file)
@@ -32,8 +32,9 @@
 
 namespace JSC {
 
-LocalAllocator::LocalAllocator(BlockDirectory* directory)
-    : m_directory(directory)
+LocalAllocator::LocalAllocator(ThreadLocalCache* tlc, BlockDirectory* directory)
+    : m_tlc(tlc)
+    , m_directory(directory)
     , m_cellSize(directory->m_cellSize)
     , m_freeList(m_cellSize)
 {
@@ -42,11 +43,13 @@ LocalAllocator::LocalAllocator(BlockDirectory* directory)
 }
 
 LocalAllocator::LocalAllocator(LocalAllocator&& other)
-    : m_directory(other.m_directory)
+    : m_tlc(other.m_tlc)
+    , m_directory(other.m_directory)
     , m_cellSize(other.m_cellSize)
     , m_freeList(WTFMove(other.m_freeList))
     , m_currentBlock(other.m_currentBlock)
     , m_lastActiveBlock(other.m_lastActiveBlock)
+    , m_allocationCursor(other.m_allocationCursor)
 {
     other.reset();
     if (other.isOnList()) {
@@ -61,6 +64,7 @@ void LocalAllocator::reset()
     m_freeList.clear();
     m_currentBlock = nullptr;
     m_lastActiveBlock = nullptr;
+    m_allocationCursor = 0;
 }
 
 LocalAllocator::~LocalAllocator()
@@ -80,6 +84,15 @@ LocalAllocator::~LocalAllocator()
     //   that it is not reachable. Therefore, the TLC should still be in a fully reset state at the
     //   time of destruction because for it to get into any other state, someone must have allocated
     //   in it (which is impossible because it's supposedly unreachable).
+    //
+    // My biggest worry with these assertions is that there will be some TLC that gets set as the
+    // current one but then never reset, and in the meantime the global object that owns it gets
+    // destroyed.
+    //
+    // Note that if we did hold onto some memory and we wanted to return it then this could be weird.
+    // We would potentially have to stopAllocating(). That would mean having to return a block to the
+    // BlockDirectory. It's not clear that the BlockDirectory is prepared to handle that during
+    // sweeping another block, for example.
     bool ok = true;
     if (!m_freeList.allocationWillFail()) {
         dataLog("FATAL: ", RawPointer(this), "->~LocalAllocator has non-empty free-list.\n");
@@ -164,6 +177,7 @@ void* LocalAllocator::allocateSlowCase(GCDeferralContext* deferralContext, Alloc
         else
             return nullptr;
     }
+    block->associateWithOrigin(m_tlc->securityOriginToken());
     m_directory->addBlock(block);
     result = allocateIn(block);
     ASSERT(result);
@@ -201,7 +215,7 @@ void* LocalAllocator::tryAllocateWithoutCollecting()
     ASSERT(m_freeList.allocationWillFail());
     
     for (;;) {
-        MarkedBlock::Handle* block = m_directory->findBlockForAllocation();
+        MarkedBlock::Handle* block = m_directory->findBlockForAllocation(*this);
         if (!block)
             break;
 
@@ -220,6 +234,7 @@ void* LocalAllocator::tryAllocateWithoutCollecting()
             // because there is a remote chance that a block may have both canAllocateButNotEmpty
             // and empty set at the same time.
             block->removeFromDirectory();
+            block->associateWithOrigin(m_tlc->securityOriginToken());
             m_directory->addBlock(block);
             return allocateIn(block);
         }
index 37db973..98a260a 100644 (file)
@@ -33,12 +33,13 @@ namespace JSC {
 
 class BlockDirectory;
 class GCDeferralContext;
+class ThreadLocalCache;
 
 class LocalAllocator : public BasicRawSentinelNode<LocalAllocator> {
     WTF_MAKE_NONCOPYABLE(LocalAllocator);
     
 public:
-    LocalAllocator(BlockDirectory*);
+    LocalAllocator(ThreadLocalCache*, BlockDirectory*);
     LocalAllocator(LocalAllocator&&);
     ~LocalAllocator();
     
@@ -53,8 +54,12 @@ public:
     static ptrdiff_t offsetOfCellSize();
     
     bool isFreeListedCell(const void*) const;
+    
+    ThreadLocalCache* tlc() const { return m_tlc; }
 
 private:
+    friend class BlockDirectory;
+    
     void reset();
     JS_EXPORT_PRIVATE void* allocateSlowCase(GCDeferralContext*, AllocationFailureMode failureMode);
     void didConsumeFreeList();
@@ -63,11 +68,16 @@ private:
     void* allocateIn(MarkedBlock::Handle*);
     ALWAYS_INLINE void doTestCollectionsIfNeeded(GCDeferralContext*);
 
+    ThreadLocalCache* m_tlc;
     BlockDirectory* m_directory;
     unsigned m_cellSize;
     FreeList m_freeList;
     MarkedBlock::Handle* m_currentBlock { nullptr };
     MarkedBlock::Handle* m_lastActiveBlock { nullptr };
+    
+    // After you do something to a block based on one of these cursors, you clear the bit in the
+    // corresponding bitvector and leave the cursor where it was.
+    size_t m_allocationCursor { 0 }; // Points to the next block that is a candidate for allocation.
 };
 
 inline ptrdiff_t LocalAllocator::offsetOfFreeList()
index b3eb45b..01a1fda 100644 (file)
@@ -26,6 +26,9 @@
 #include "config.h"
 #include "MarkStackMergingConstraint.h"
 
+#include "GCSegmentedArrayInlines.h"
+#include "JSCInlines.h"
+
 namespace JSC {
 
 MarkStackMergingConstraint::MarkStackMergingConstraint(Heap& heap)
index 29d36e5..e993574 100644 (file)
@@ -29,6 +29,9 @@
 
 namespace JSC {
 
+class Heap;
+class SlotVisitor;
+
 class MarkStackMergingConstraint : public MarkingConstraint {
 public:
     MarkStackMergingConstraint(Heap&);
index b3a5911..f6a4cb7 100644 (file)
@@ -488,6 +488,15 @@ bool MarkedBlock::Handle::isFreeListedCell(const void* target) const
     return m_directory->isFreeListedCell(target);
 }
 
+void MarkedBlock::Handle::associateWithOrigin(SecurityOriginToken securityOriginToken)
+{
+    if (m_securityOriginToken == securityOriginToken)
+        return;
+    
+    memset(&block(), 0, endAtom * atomSize);
+    m_securityOriginToken = securityOriginToken;
+}
+
 } // namespace JSC
 
 namespace WTF {
index 7d14eec..fd6f87c 100644 (file)
@@ -25,6 +25,7 @@
 #include "DestructionMode.h"
 #include "HeapCell.h"
 #include "IterationStatus.h"
+#include "SecurityOriginToken.h"
 #include "WeakSet.h"
 #include <wtf/Atomics.h>
 #include <wtf/Bitmap.h>
@@ -194,6 +195,9 @@ public:
         
         void dumpState(PrintStream&);
         
+        void associateWithOrigin(SecurityOriginToken);
+        SecurityOriginToken securityOriginToken() const { return m_securityOriginToken; }
+        
     private:
         Handle(Heap&, AlignedMemoryAllocator*, void*);
         
@@ -229,6 +233,8 @@ public:
         WeakSet m_weakSet;
         
         MarkedBlock* m_block { nullptr };
+        
+        SecurityOriginToken m_securityOriginToken { 0 };
     };
 
 private:    
diff --git a/Source/JavaScriptCore/heap/SecurityOriginToken.cpp b/Source/JavaScriptCore/heap/SecurityOriginToken.cpp
new file mode 100644 (file)
index 0000000..28f4bef
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "SecurityOriginToken.h"
+
+#include <wtf/Atomics.h>
+
+namespace JSC {
+
+SecurityOriginToken uniqueSecurityOriginToken()
+{
+    static SecurityOriginToken counter;
+    return WTF::atomicExchangeAdd(&counter, 1) + 1;
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/heap/SecurityOriginToken.h b/Source/JavaScriptCore/heap/SecurityOriginToken.h
new file mode 100644 (file)
index 0000000..34c1d9e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+namespace JSC {
+
+typedef uint64_t SecurityOriginToken;
+
+JS_EXPORT_PRIVATE SecurityOriginToken uniqueSecurityOriginToken();
+
+} // namespace JSC
+
index 6eb1d81..8b61905 100644 (file)
 
 namespace JSC {
 
-RefPtr<ThreadLocalCache> ThreadLocalCache::create(Heap& heap)
+RefPtr<ThreadLocalCache> ThreadLocalCache::create(Heap& heap, SecurityOriginToken securityOriginToken)
 {
-    return adoptRef(new ThreadLocalCache(heap));
+    return adoptRef(new ThreadLocalCache(heap, securityOriginToken));
 }
 
-ThreadLocalCache::ThreadLocalCache(Heap& heap)
+ThreadLocalCache::ThreadLocalCache(Heap& heap, SecurityOriginToken securityOriginToken)
     : m_heap(heap)
+    , m_securityOriginToken(securityOriginToken)
 {
     m_data = allocateData();
 }
@@ -59,7 +60,7 @@ ThreadLocalCache::Data* ThreadLocalCache::allocateData()
     for (size_t offset = 0; offset < oldSize; offset += sizeof(LocalAllocator))
         new (&allocator(*result, offset)) LocalAllocator(WTFMove(allocator(*m_data, offset)));
     for (size_t offset = oldSize; offset < layout.size; offset += sizeof(LocalAllocator))
-        new (&allocator(*result, offset)) LocalAllocator(layout.directories[offset / sizeof(LocalAllocator)]);
+        new (&allocator(*result, offset)) LocalAllocator(this, layout.directories[offset / sizeof(LocalAllocator)]);
     return result;
 }
 
@@ -70,7 +71,7 @@ void ThreadLocalCache::destroyData(Data* data)
     fastFree(data);
 }
 
-void ThreadLocalCache::installSlow(VM& vm)
+void ThreadLocalCache::installSlow(VM& vm, RefPtr<ThreadLocalCache>* previous)
 {
 #if USE(FAST_TLS_FOR_TLC)
     static std::once_flag onceFlag;
@@ -83,8 +84,13 @@ void ThreadLocalCache::installSlow(VM& vm)
     
     ref();
     
-    if (RefPtr<ThreadLocalCache> oldCache = get(vm))
-        oldCache->deref();
+    if (ThreadLocalCache::Data* oldCacheData = getImpl(vm)) {
+        ThreadLocalCache* oldCache = oldCacheData->cache;
+        if (previous)
+            *previous = adoptRef(oldCache);
+        else
+            oldCache->deref();
+    }
     
     installData(vm, m_data);
 }
index 76403ca..2d8d067 100644 (file)
 
 #pragma once
 
+#include "AllocationFailureMode.h"
+#include "LocalAllocator.h"
+#include "SecurityOriginToken.h"
 #include <wtf/FastMalloc.h>
 #include <wtf/FastTLS.h>
 #include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Vector.h>
 
 namespace JSC {
 
@@ -39,9 +43,9 @@ class ThreadLocalCache : public ThreadSafeRefCounted<ThreadLocalCache> {
     WTF_MAKE_FAST_ALLOCATED;
     
 public:
-    static RefPtr<ThreadLocalCache> create(Heap&);
+    JS_EXPORT_PRIVATE static RefPtr<ThreadLocalCache> create(Heap&, SecurityOriginToken = uniqueSecurityOriginToken());
     
-    JS_EXPORT_PRIVATE ~ThreadLocalCache();
+    JS_EXPORT_PRIVATE virtual ~ThreadLocalCache();
 
     static RefPtr<ThreadLocalCache> get(VM&);
     
@@ -49,7 +53,7 @@ public:
     // optimizing for the case that you're just installing the cache that is already installed. This
     // assumes a relatively small number of caches or low chance of actual context switch combined
     // with possibly high rate of "I may have context switched" sites that call this out of paranoia.
-    void install(VM&);
+    void install(VM&, RefPtr<ThreadLocalCache>* = nullptr);
     
     static LocalAllocator& allocator(VM&, size_t offset);
     
@@ -59,11 +63,14 @@ public:
     static ptrdiff_t offsetOfSizeInData() { return OBJECT_OFFSETOF(Data, size); }
     static ptrdiff_t offsetOfFirstAllocatorInData() { return OBJECT_OFFSETOF(Data, allocator); }
     
+    SecurityOriginToken securityOriginToken() const { return m_securityOriginToken; }
+
+protected:    
+    JS_EXPORT_PRIVATE ThreadLocalCache(Heap&, SecurityOriginToken);
+    
 private:
     friend class VM;
     
-    ThreadLocalCache(Heap&);
-    
     struct Data {
         size_t size;
         ThreadLocalCache* cache;
@@ -76,7 +83,7 @@ private:
     void destroyData(Data*);
     static LocalAllocator& allocator(Data& data, size_t offset);
 
-    void installSlow(VM&);
+    void installSlow(VM&, RefPtr<ThreadLocalCache>*);
     static void installData(VM&, Data*);
     
     LocalAllocator& allocatorSlow(VM&, size_t offset);
@@ -91,6 +98,8 @@ private:
     // it's correct for immortal caches.
     Heap& m_heap;
     Data* m_data { nullptr };
+    
+    SecurityOriginToken m_securityOriginToken;
 
 #if USE(FAST_TLS_FOR_TLC)
     static const pthread_key_t tlsKey = WTF_GC_TLC_KEY;
index 2234f44..b64f978 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "ThreadLocalCache.h"
+#include "VM.h"
 
 namespace JSC {
 
@@ -47,11 +48,14 @@ inline RefPtr<ThreadLocalCache> ThreadLocalCache::get(VM& vm)
     return nullptr;
 }
 
-inline void ThreadLocalCache::install(VM& vm)
+inline void ThreadLocalCache::install(VM& vm, RefPtr<ThreadLocalCache>* previous)
 {
-    if (getImpl(vm) == m_data)
+    if (getImpl(vm) == m_data) {
+        if (previous)
+            *previous = nullptr;
         return;
-    installSlow(vm);
+    }
+    installSlow(vm, previous);
 }
 
 inline LocalAllocator& ThreadLocalCache::allocator(VM& vm, size_t offset)
index 1a7eb81..d696128 100644 (file)
@@ -491,7 +491,7 @@ public:
     const RuntimeFlags& runtimeFlags() const { return m_runtimeFlags; }
 
 protected:
-    JS_EXPORT_PRIVATE explicit JSGlobalObject(VM&, Structure*, const GlobalObjectMethodTable* = 0, RefPtr<ThreadLocalCache> = nullptr);
+    JS_EXPORT_PRIVATE explicit JSGlobalObject(VM&, Structure*, const GlobalObjectMethodTable* = nullptr, RefPtr<ThreadLocalCache> = nullptr);
 
     JS_EXPORT_PRIVATE void finishCreation(VM&);
 
index 4ce5ef9..a06166a 100644 (file)
@@ -41,7 +41,7 @@ VMEntryScope::VMEntryScope(VM& vm, JSGlobalObject* globalObject)
     : m_vm(vm)
     , m_globalObject(globalObject)
 {
-    globalObject->threadLocalCache().install(vm);
+    globalObject->threadLocalCache().install(vm, &m_previousTLC);
     ASSERT(!DisallowVMReentry::isInEffectOnCurrentThread());
     ASSERT(Thread::current().stack().isGrowingDownward());
     if (!vm.entryScope) {
@@ -71,11 +71,14 @@ void VMEntryScope::addDidPopListener(std::function<void ()> listener)
 
 VMEntryScope::~VMEntryScope()
 {
+    if (m_previousTLC)
+        m_previousTLC->install(m_vm);
+    
     if (m_vm.entryScope != this)
         return;
 
     TracePoint(VMEntryScopeEnd);
-
+    
     if (m_vm.watchdog())
         m_vm.watchdog()->exitedVM();
 
index c2971f6..2993b3d 100644 (file)
@@ -31,6 +31,7 @@
 namespace JSC {
 
 class JSGlobalObject;
+class ThreadLocalCache;
 class VM;
 
 class VMEntryScope {
@@ -47,6 +48,7 @@ private:
     VM& m_vm;
     JSGlobalObject* m_globalObject;
     Vector<std::function<void ()>> m_didPopListeners;
+    RefPtr<ThreadLocalCache> m_previousTLC;
 };
 
 } // namespace JSC
index eb7416e..1788f76 100644 (file)
@@ -1,3 +1,45 @@
+2018-02-05  Filip Pizlo  <fpizlo@apple.com>
+
+        Global objects should be able to use TLCs to allocate from different blocks from each other
+        https://bugs.webkit.org/show_bug.cgi?id=182227
+
+        Reviewed by Daniel Bates and Chris Dumez.
+
+        No new tests because no change in behavior.
+        
+        Adopt JSC TLC API to put distance between objects from different security origins. WebCore has
+        a subclass of ThreadLocalCache that supports hash-consing based on the relevant origin data
+        using the existing SecurityOriginHash. It's Document's job to initiate this, but all of the
+        logic is in WebCore::OriginThreadLocalCache.
+        
+        Workers don't opt into this. They just get the VM's default TLC all the time.
+
+        * ForwardingHeaders/heap/ThreadLocalCache.h: Added.
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::JSDOMGlobalObject):
+        * bindings/js/JSDOMGlobalObject.h:
+        * bindings/js/JSDOMWindowBase.cpp:
+        (WebCore::JSDOMWindowBase::JSDOMWindowBase):
+        * dom/Document.cpp:
+        (WebCore::Document::initSecurityContext):
+        (WebCore::Document::threadLocalCache):
+        * dom/Document.h:
+        * page/OriginThreadLocalCache.cpp: Added.
+        (WebCore::threadLocalCacheMap):
+        (WebCore::OriginThreadLocalCache::create):
+        (WebCore::OriginThreadLocalCache::~OriginThreadLocalCache):
+        (WebCore::OriginThreadLocalCache::OriginThreadLocalCache):
+        * page/OriginThreadLocalCache.h: Added.
+        * page/SecurityOrigin.cpp:
+        (WebCore::SecurityOrigin::passesFileCheck const):
+        (WebCore::SecurityOrigin::setEnforcesFilePathSeparation):
+        (WebCore::SecurityOrigin::toString const):
+        (WebCore::SecurityOrigin::enforceFilePathSeparation): Deleted.
+        * page/SecurityOrigin.h:
+        (WebCore::SecurityOrigin::enforcesFilePathSeparation const):
+
 2018-02-05  Per Arne Vollan  <pvollan@apple.com>
 
         [Win] Release assert failed under NetworkStateNotifier::singleton.
diff --git a/Source/WebCore/ForwardingHeaders/heap/ThreadLocalCache.h b/Source/WebCore/ForwardingHeaders/heap/ThreadLocalCache.h
new file mode 100644 (file)
index 0000000..89d47fb
--- /dev/null
@@ -0,0 +1,2 @@
+#pragma once
+#include <JavaScriptCore/ThreadLocalCache.h>
index 017256e..7188924 100644 (file)
@@ -1334,6 +1334,7 @@ page/MouseEventWithHitTestResults.cpp
 page/Navigator.cpp
 page/NavigatorBase.cpp
 page/OriginAccessEntry.cpp
+page/OriginThreadLocalCache.cpp
 page/Page.cpp
 page/PageConfiguration.cpp
 page/PageConsoleClient.cpp
index db04aab..a682f29 100644 (file)
                0F580CFF0F12DE9B0051D689 /* RenderLayerBacking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F580CFB0F12DE9B0051D689 /* RenderLayerBacking.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F580FA31496939100FB5BD8 /* WebTiledBackingLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F580FA11496939100FB5BD8 /* WebTiledBackingLayer.h */; };
                0F580FAF149800D400FB5BD8 /* AnimationUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F580FAE149800D400FB5BD8 /* AnimationUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F5B408A20212F770080F913 /* OriginThreadLocalCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5B408820212F730080F913 /* OriginThreadLocalCache.h */; };
                0F5B7A5510F65D7A00376302 /* RenderEmbeddedObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5B7A5310F65D7A00376302 /* RenderEmbeddedObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F5E200618E771FC003EC3E5 /* PlatformCAAnimationCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E200518E771FC003EC3E5 /* PlatformCAAnimationCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F605AED15F94848004DF0C0 /* ScrollingConstraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F605AEB15F94848004DF0C0 /* ScrollingConstraints.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F580FA11496939100FB5BD8 /* WebTiledBackingLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebTiledBackingLayer.h; sourceTree = "<group>"; };
                0F580FA21496939100FB5BD8 /* WebTiledBackingLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebTiledBackingLayer.mm; sourceTree = "<group>"; };
                0F580FAE149800D400FB5BD8 /* AnimationUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationUtilities.h; sourceTree = "<group>"; };
+               0F5B408820212F730080F913 /* OriginThreadLocalCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OriginThreadLocalCache.h; sourceTree = "<group>"; };
+               0F5B408920212F730080F913 /* OriginThreadLocalCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OriginThreadLocalCache.cpp; sourceTree = "<group>"; };
                0F5B7A5210F65D7A00376302 /* RenderEmbeddedObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderEmbeddedObject.cpp; sourceTree = "<group>"; };
                0F5B7A5310F65D7A00376302 /* RenderEmbeddedObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderEmbeddedObject.h; sourceTree = "<group>"; };
                0F5E200518E771FC003EC3E5 /* PlatformCAAnimationCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformCAAnimationCocoa.h; sourceTree = "<group>"; };
                8AF4E55411DC5A36000ED3DE /* PerformanceNavigation.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PerformanceNavigation.idl; sourceTree = "<group>"; };
                8AF4E55911DC5A63000ED3DE /* PerformanceTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PerformanceTiming.h; sourceTree = "<group>"; };
                8AF4E55A11DC5A63000ED3DE /* PerformanceTiming.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PerformanceTiming.idl; sourceTree = "<group>"; };
-               8E33CD93201A29C100E39093 /* GapLength.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GapLength.cpp; sourceTree = "<group>"; };
                8BD37A67201BB39C0011734A /* ReadableStreamChunk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadableStreamChunk.h; sourceTree = "<group>"; };
+               8E33CD93201A29C100E39093 /* GapLength.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GapLength.cpp; sourceTree = "<group>"; };
                8E4C96D81AD4483500365A50 /* JSFetchResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFetchResponse.cpp; sourceTree = "<group>"; };
                8E4C96D91AD4483500365A50 /* JSFetchResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFetchResponse.h; sourceTree = "<group>"; };
                8EC6C961201A250100FBFA53 /* GapLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GapLength.h; sourceTree = "<group>"; };
                                5182C24B1F313AE00059BA7C /* NavigatorServiceWorker.idl */,
                                00146288103CD1DE000B20DB /* OriginAccessEntry.cpp */,
                                00146289103CD1DE000B20DB /* OriginAccessEntry.h */,
+                               0F5B408920212F730080F913 /* OriginThreadLocalCache.cpp */,
+                               0F5B408820212F730080F913 /* OriginThreadLocalCache.h */,
                                65FEA86809833ADE00BED4AB /* Page.cpp */,
                                65A21467097A329100B9050A /* Page.h */,
                                CD5E5B601A15F156000C609E /* PageConfiguration.cpp */,
                                07969DC217D14151007FF842 /* JSRTCStatsReport.h in Headers */,
                                5E2C436C1BCF071E0001E2BC /* JSRTCTrackEvent.h in Headers */,
                                BCEC01C30C274DDD009F4EC9 /* JSScreen.h in Headers */,
+                               0F5B408A20212F770080F913 /* OriginThreadLocalCache.h in Headers */,
                                FDA15ECE12B03F61003A583A /* JSScriptProcessorNode.h in Headers */,
                                834476EF1DA5BC5E002B6ED2 /* JSScrollToOptions.h in Headers */,
                                CED06AD11C77754800FDFAF1 /* JSSecurityPolicyViolationEvent.h in Headers */,
index 4d1ef94..312c8e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2018 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -56,8 +56,8 @@ EncodedJSValue JSC_HOST_CALL isReadableByteStreamAPIEnabled(ExecState*);
 
 const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", &JSGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDOMGlobalObject) };
 
-JSDOMGlobalObject::JSDOMGlobalObject(VM& vm, Structure* structure, Ref<DOMWrapperWorld>&& world, const GlobalObjectMethodTable* globalObjectMethodTable)
-    : JSGlobalObject(vm, structure, globalObjectMethodTable)
+JSDOMGlobalObject::JSDOMGlobalObject(VM& vm, Structure* structure, Ref<DOMWrapperWorld>&& world, const GlobalObjectMethodTable* globalObjectMethodTable, RefPtr<JSC::ThreadLocalCache>&& threadLocalCache)
+    : JSGlobalObject(vm, structure, globalObjectMethodTable, WTFMove(threadLocalCache))
     , m_currentEvent(0)
     , m_world(WTFMove(world))
     , m_worldIsNormal(m_world->isNormal())
index d32a6b8..21fa4be 100644 (file)
@@ -30,6 +30,7 @@
 #include "WebCoreJSBuiltinInternals.h"
 #include <heap/HeapInlines.h>
 #include <heap/LockDuringMarking.h>
+#include <heap/ThreadLocalCache.h>
 #include <runtime/JSGlobalObject.h>
 #include <runtime/StructureInlines.h>
 
@@ -50,7 +51,7 @@ class WEBCORE_EXPORT JSDOMGlobalObject : public JSC::JSGlobalObject {
 protected:
     struct JSDOMGlobalObjectData;
 
-    JSDOMGlobalObject(JSC::VM&, JSC::Structure*, Ref<DOMWrapperWorld>&&, const JSC::GlobalObjectMethodTable* = 0);
+    JSDOMGlobalObject(JSC::VM&, JSC::Structure*, Ref<DOMWrapperWorld>&&, const JSC::GlobalObjectMethodTable* = nullptr, RefPtr<JSC::ThreadLocalCache>&& = nullptr);
     static void destroy(JSC::JSCell*);
     void finishCreation(JSC::VM&);
     void finishCreation(JSC::VM&, JSC::JSObject*);
index e365551..9bc5a68 100644 (file)
@@ -79,7 +79,7 @@ const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = {
 };
 
 JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, RefPtr<DOMWindow>&& window, JSDOMWindowProxy* proxy)
-    : JSDOMGlobalObject(vm, structure, proxy->world(), &s_globalObjectMethodTable)
+    : JSDOMGlobalObject(vm, structure, proxy->world(), &s_globalObjectMethodTable, window ? &window->document()->threadLocalCache() : nullptr)
     , m_windowCloseWatchpoints((window && window->frame()) ? IsWatched : IsInvalidated)
     , m_wrapped(WTFMove(window))
     , m_proxy(proxy)
index b40ab56..08507f5 100644 (file)
@@ -3,7 +3,7 @@
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
  *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2018 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 #include "NavigationDisabler.h"
 #include "NavigationScheduler.h"
 #include "NestingLevelIncrementer.h"
-
 #include "NodeIterator.h"
 #include "NodeRareData.h"
 #include "NodeWithIndex.h"
 #include "OriginAccessEntry.h"
+#include "OriginThreadLocalCache.h"
 #include "OverflowEvent.h"
 #include "PageConsoleClient.h"
 #include "PageGroup.h"
 #include <ctime>
 #include <inspector/ConsoleMessage.h>
 #include <inspector/ScriptCallStack.h>
+#include <runtime/VM.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/Language.h>
 #include <wtf/NeverDestroyed.h>
@@ -5548,7 +5549,7 @@ void Document::initSecurityContext()
             // Some clients want local URLs to have even tighter restrictions by default, and not be able to access other local files.
             // FIXME 81578: The naming of this is confusing. Files with restricted access to other local files
             // still can have other privileges that can be remembered, thereby not making them unique origins.
-            securityOrigin().enforceFilePathSeparation();
+            securityOrigin().setEnforcesFilePathSeparation();
         }
     }
     securityOrigin().setStorageBlockingPolicy(settings().storageBlockingPolicy());
@@ -7740,4 +7741,16 @@ void Document::setServiceWorkerConnection(SWClientConnection* serviceWorkerConne
 }
 #endif
 
+JSC::ThreadLocalCache& Document::threadLocalCache()
+{
+    if (!m_threadLocalCache) {
+        SecurityOrigin& origin = securityOrigin();
+        if (origin.isUnique() || (origin.isLocal() && origin.enforcesFilePathSeparation()))
+            m_threadLocalCache = JSC::ThreadLocalCache::create(commonVM().heap);
+        else
+            m_threadLocalCache = OriginThreadLocalCache::create(origin);
+    }
+    return *m_threadLocalCache;
+}
+
 } // namespace WebCore
index 04a6aa6..a055372 100644 (file)
@@ -51,6 +51,7 @@
 #include "UserActionElementSet.h"
 #include "ViewportArguments.h"
 #include "VisibilityState.h"
+#include <heap/ThreadLocalCache.h>
 #include <pal/SessionID.h>
 #include <wtf/Deque.h>
 #include <wtf/Forward.h>
@@ -1411,6 +1412,8 @@ public:
     bool handlingTouchEvent() const { return m_handlingTouchEvent; }
 #endif
 
+    JSC::ThreadLocalCache& threadLocalCache();
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
@@ -1895,6 +1898,8 @@ private:
 #endif
 
     HashSet<ApplicationStateChangeListener*> m_applicationStateChangeListeners;
+    
+    RefPtr<JSC::ThreadLocalCache> m_threadLocalCache;
 };
 
 Element* eventTargetElementForDocument(Document*);
diff --git a/Source/WebCore/page/OriginThreadLocalCache.cpp b/Source/WebCore/page/OriginThreadLocalCache.cpp
new file mode 100644 (file)
index 0000000..c2775a0
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "OriginThreadLocalCache.h"
+
+#include "CommonVM.h"
+#include "SecurityOriginHash.h"
+#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+typedef HashMap<RefPtr<SecurityOrigin>, OriginThreadLocalCache*> ThreadLocalCacheMap;
+
+static ThreadLocalCacheMap& threadLocalCacheMap()
+{
+    static NeverDestroyed<ThreadLocalCacheMap> map;
+    return map;
+}
+
+Ref<OriginThreadLocalCache> OriginThreadLocalCache::create(SecurityOrigin& key)
+{
+    auto iter = threadLocalCacheMap().find(&key);
+    if (iter != threadLocalCacheMap().end())
+        return *iter->value;
+    
+    return adoptRef(*new OriginThreadLocalCache(key));
+}
+
+OriginThreadLocalCache::~OriginThreadLocalCache()
+{
+    bool result = threadLocalCacheMap().remove(m_key);
+    RELEASE_ASSERT(result);
+}
+
+OriginThreadLocalCache::OriginThreadLocalCache(SecurityOrigin& key)
+    : ThreadLocalCache(commonVM().heap, JSC::uniqueSecurityOriginToken())
+    , m_key(&key)
+{
+    auto result = threadLocalCacheMap().add(&key, this);
+    RELEASE_ASSERT(result);
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/page/OriginThreadLocalCache.h b/Source/WebCore/page/OriginThreadLocalCache.h
new file mode 100644 (file)
index 0000000..141cc68
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#include "SecurityOrigin.h"
+#include <heap/ThreadLocalCache.h>
+
+namespace WebCore {
+
+class OriginThreadLocalCache final : public JSC::ThreadLocalCache {
+public:
+    static Ref<OriginThreadLocalCache> create(SecurityOrigin&);
+    
+    ~OriginThreadLocalCache() override;
+
+private:
+    explicit OriginThreadLocalCache(SecurityOrigin&);
+    
+    RefPtr<SecurityOrigin> m_key;
+};
+
+} // namespace WebCore
+
index 9d2e5cc..e41af37 100644 (file)
@@ -180,7 +180,7 @@ SecurityOrigin::SecurityOrigin(const SecurityOrigin* other)
     , m_domainWasSetInDOM { other->m_domainWasSetInDOM }
     , m_canLoadLocalResources { other->m_canLoadLocalResources }
     , m_storageBlockingPolicy { other->m_storageBlockingPolicy }
-    , m_enforceFilePathSeparation { other->m_enforceFilePathSeparation }
+    , m_enforcesFilePathSeparation { other->m_enforcesFilePathSeparation }
     , m_needsStorageAccessFromFileURLsQuirk { other->m_needsStorageAccessFromFileURLsQuirk }
     , m_isPotentiallyTrustworthy { other->m_isPotentiallyTrustworthy }
 {
@@ -283,7 +283,7 @@ bool SecurityOrigin::passesFileCheck(const SecurityOrigin& other) const
 {
     ASSERT(isLocal() && other.isLocal());
 
-    return !m_enforceFilePathSeparation && !other.m_enforceFilePathSeparation;
+    return !m_enforcesFilePathSeparation && !other.m_enforcesFilePathSeparation;
 }
 
 bool SecurityOrigin::canRequest(const URL& url) const
@@ -453,10 +453,10 @@ String SecurityOrigin::domainForCachePartition() const
     return emptyString();
 }
 
-void SecurityOrigin::enforceFilePathSeparation()
+void SecurityOrigin::setEnforcesFilePathSeparation()
 {
     ASSERT(isLocal());
-    m_enforceFilePathSeparation = true;
+    m_enforcesFilePathSeparation = true;
 }
 
 bool SecurityOrigin::isLocal() const
@@ -468,7 +468,7 @@ String SecurityOrigin::toString() const
 {
     if (isUnique())
         return ASCIILiteral("null");
-    if (m_protocol == "file" && m_enforceFilePathSeparation)
+    if (m_protocol == "file" && m_enforcesFilePathSeparation)
         return ASCIILiteral("null");
     return toRawString();
 }
index ee10b7e..160d7ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -165,7 +165,8 @@ public:
     // Marks a file:// origin as being in a domain defined by its path.
     // FIXME 81578: The naming of this is confusing. Files with restricted access to other local files
     // still can have other privileges that can be remembered, thereby not making them unique.
-    void enforceFilePathSeparation();
+    void setEnforcesFilePathSeparation();
+    bool enforcesFilePathSeparation() const { return m_enforcesFilePathSeparation; }
 
     // Convert this SecurityOrigin into a string. The string
     // representation of a SecurityOrigin is similar to a URL, except it
@@ -229,7 +230,7 @@ private:
     bool m_domainWasSetInDOM { false };
     bool m_canLoadLocalResources { false };
     StorageBlockingPolicy m_storageBlockingPolicy { AllowAllStorage };
-    bool m_enforceFilePathSeparation { false };
+    bool m_enforcesFilePathSeparation { false };
     bool m_needsStorageAccessFromFileURLsQuirk { false };
     bool m_isPotentiallyTrustworthy { false };
 };