Title: [215885] trunk/Source/_javascript_Core
Revision
215885
Author
mark....@apple.com
Date
2017-04-27 12:24:07 -0700 (Thu, 27 Apr 2017)

Log Message

Audit and fix incorrect uses of JSArray::tryCreateForInitializationPrivate().
https://bugs.webkit.org/show_bug.cgi?id=171344
<rdar://problem/31352667>

Reviewed by Filip Pizlo.

JSArray::tryCreateForInitializationPrivate() should only be used in performance
critical paths, and should always be used with care because it creates an
uninitialized object that needs to be initialized by its client before the object
can be released into the system.  Before the object is fully initialized:
a. the client should not re-enter the VM to execute JS code, and
b. GC should not run.

This is because until the object is fully initialized, it is an inconsistent
state that the GC and JS code will not be happy about.

In this patch, we do the following:

1. Renamed JSArray::tryCreateForInitializationPrivate() to
   JSArray::tryCreateUninitializedRestricted() because "private" is a bit ambiguous
   and can be confused with APIs that are called freely within WebKit but are
   not meant for clients of WebKit.  In this case, we intend for use of this API
   to be restricted to only a few carefully considered and crafted cases.

2. Introduce the ObjectInitializationScope RAII object which covers the period
   when the uninitialized object is created and gets initialized.

   ObjectInitializationScope will asserts that either the object is created
   fully initialized (in the case where the object structure is not an "original"
   structure) or if created uninitialized, is fully initialized at the end of
   the scope.

   If the object is created uninitialized, the ObjectInitializationScope also
   ensures that we do not GC nor re-enter the VM to execute JS code.  This is
   achieved by enabling DisallowGC and DisallowVMReentry scopes.

   tryCreateUninitializedRestricted() and initializeIndex() now requires an
   ObjectInitializationScope instance.  The ObjectInitializationScope replaces
   the VM& argument because it can be used to pass the VM& itself.  This is a
   small optimization that makes passing the ObjectInitializationScope free even
   on release builds.

3. Factored a DisallowScope out of DisallowGC, and make DisallowGC extend it.
   Introduce a DisallowVMReentry class that extends DisallowScope.

4. Fixed a bug found by the ObjectInitializationScope.  The bug is that there are
   scenarios where the structure passed to tryCreateUninitializedRestricted()
   that may not be an "original" structure.  As a result, initializeIndex() would
   end up allocating new structures, and therefore trigger a GC.

   The fix is to detect that the structure passed to tryCreateUninitializedRestricted()
   is not an "original" one, and pre-initialize the array with 0s.

   This bug was detected by existing tests. Hence, no new test needed.

5. Replaced all inappropriate uses of tryCreateUninitializedRestricted() with
   tryCreate().  Inappropriate uses here means code that is not in performance
   critical paths.

   Similarly, replaced accompanying uses of initializeIndex() with putDirectIndex().

   This patch is performance neutral (according to the JSC command line benchmarks).

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* dfg/DFGOperations.cpp:
* ftl/FTLOperations.cpp:
(JSC::FTL::operationMaterializeObjectInOSR):
* heap/DeferGC.cpp:
* heap/DeferGC.h:
(JSC::DisallowGC::DisallowGC):
(JSC::DisallowGC::initialize):
(JSC::DisallowGC::scopeReentryCount):
(JSC::DisallowGC::setScopeReentryCount):
(JSC::DisallowGC::~DisallowGC): Deleted.
(JSC::DisallowGC::isGCDisallowedOnCurrentThread): Deleted.
* heap/GCDeferralContextInlines.h:
(JSC::GCDeferralContext::~GCDeferralContext):
* heap/Heap.cpp:
(JSC::Heap::collectIfNecessaryOrDefer):
* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoPrivateFuncConcatMemcpy):
* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::createWithInlineFrame):
(JSC::ClonedArguments::createByCopyingFrom):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/DisallowScope.h: Added.
(JSC::DisallowScope::DisallowScope):
(JSC::DisallowScope::~DisallowScope):
(JSC::DisallowScope::isInEffectOnCurrentThread):
(JSC::DisallowScope::enable):
(JSC::DisallowScope::enterScope):
(JSC::DisallowScope::exitScope):
* runtime/DisallowVMReentry.cpp: Added.
* runtime/DisallowVMReentry.h: Added.
(JSC::DisallowVMReentry::DisallowVMReentry):
(JSC::DisallowVMReentry::initialize):
(JSC::DisallowVMReentry::scopeReentryCount):
(JSC::DisallowVMReentry::setScopeReentryCount):
* runtime/InitializeThreading.cpp:
(JSC::initializeThreading):
* runtime/JSArray.cpp:
(JSC::JSArray::tryCreateUninitializedRestricted):
(JSC::JSArray::fastSlice):
(JSC::JSArray::tryCreateForInitializationPrivate): Deleted.
* runtime/JSArray.h:
(JSC::JSArray::tryCreateUninitializedRestricted):
(JSC::JSArray::tryCreate):
(JSC::constructArray):
(JSC::constructArrayNegativeIndexed):
(JSC::JSArray::tryCreateForInitializationPrivate): Deleted.
(JSC::createArrayButterfly): Deleted.
* runtime/JSCellInlines.h:
(JSC::allocateCell):
* runtime/JSObject.h:
(JSC::JSObject::initializeIndex):
(JSC::JSObject::initializeIndexWithoutBarrier):
* runtime/ObjectInitializationScope.cpp: Added.
(JSC::ObjectInitializationScope::ObjectInitializationScope):
(JSC::ObjectInitializationScope::~ObjectInitializationScope):
(JSC::ObjectInitializationScope::notifyAllocated):
(JSC::ObjectInitializationScope::verifyPropertiesAreInitialized):
* runtime/ObjectInitializationScope.h: Added.
(JSC::ObjectInitializationScope::ObjectInitializationScope):
(JSC::ObjectInitializationScope::vm):
(JSC::ObjectInitializationScope::notifyAllocated):
* runtime/Operations.h:
(JSC::isScribbledValue):
(JSC::scribble):
* runtime/RegExpMatchesArray.cpp:
(JSC::createEmptyRegExpMatchesArray):
* runtime/RegExpMatchesArray.h:
(JSC::tryCreateUninitializedRegExpMatchesArray):
(JSC::createRegExpMatchesArray):
* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::VMEntryScope):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (215884 => 215885)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2017-04-27 19:24:07 UTC (rev 215885)
@@ -713,6 +713,7 @@
     runtime/DirectArguments.cpp
     runtime/DirectArgumentsOffset.cpp
     runtime/DirectEvalExecutable.cpp
+    runtime/DisallowVMReentry.cpp
     runtime/DumpContext.cpp
     runtime/ECMAScriptSpecInternalFunctions.cpp
     runtime/Error.cpp
@@ -852,6 +853,7 @@
     runtime/NumberObject.cpp
     runtime/NumberPrototype.cpp
     runtime/ObjectConstructor.cpp
+    runtime/ObjectInitializationScope.cpp
     runtime/ObjectPrototype.cpp
     runtime/Operations.cpp
     runtime/Options.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (215884 => 215885)


--- trunk/Source/_javascript_Core/ChangeLog	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1,3 +1,143 @@
+2017-04-27  Mark Lam  <mark....@apple.com>
+
+        Audit and fix incorrect uses of JSArray::tryCreateForInitializationPrivate().
+        https://bugs.webkit.org/show_bug.cgi?id=171344
+        <rdar://problem/31352667>
+
+        Reviewed by Filip Pizlo.
+
+        JSArray::tryCreateForInitializationPrivate() should only be used in performance
+        critical paths, and should always be used with care because it creates an
+        uninitialized object that needs to be initialized by its client before the object
+        can be released into the system.  Before the object is fully initialized:
+        a. the client should not re-enter the VM to execute JS code, and
+        b. GC should not run.
+
+        This is because until the object is fully initialized, it is an inconsistent
+        state that the GC and JS code will not be happy about.
+
+        In this patch, we do the following:
+
+        1. Renamed JSArray::tryCreateForInitializationPrivate() to
+           JSArray::tryCreateUninitializedRestricted() because "private" is a bit ambiguous
+           and can be confused with APIs that are called freely within WebKit but are
+           not meant for clients of WebKit.  In this case, we intend for use of this API
+           to be restricted to only a few carefully considered and crafted cases.
+
+        2. Introduce the ObjectInitializationScope RAII object which covers the period
+           when the uninitialized object is created and gets initialized.
+
+           ObjectInitializationScope will asserts that either the object is created
+           fully initialized (in the case where the object structure is not an "original"
+           structure) or if created uninitialized, is fully initialized at the end of
+           the scope.
+
+           If the object is created uninitialized, the ObjectInitializationScope also
+           ensures that we do not GC nor re-enter the VM to execute JS code.  This is
+           achieved by enabling DisallowGC and DisallowVMReentry scopes.
+
+           tryCreateUninitializedRestricted() and initializeIndex() now requires an
+           ObjectInitializationScope instance.  The ObjectInitializationScope replaces
+           the VM& argument because it can be used to pass the VM& itself.  This is a
+           small optimization that makes passing the ObjectInitializationScope free even
+           on release builds.
+
+        3. Factored a DisallowScope out of DisallowGC, and make DisallowGC extend it.
+           Introduce a DisallowVMReentry class that extends DisallowScope.
+
+        4. Fixed a bug found by the ObjectInitializationScope.  The bug is that there are
+           scenarios where the structure passed to tryCreateUninitializedRestricted()
+           that may not be an "original" structure.  As a result, initializeIndex() would
+           end up allocating new structures, and therefore trigger a GC.
+
+           The fix is to detect that the structure passed to tryCreateUninitializedRestricted()
+           is not an "original" one, and pre-initialize the array with 0s.
+
+           This bug was detected by existing tests. Hence, no new test needed.
+
+        5. Replaced all inappropriate uses of tryCreateUninitializedRestricted() with
+           tryCreate().  Inappropriate uses here means code that is not in performance
+           critical paths.
+
+           Similarly, replaced accompanying uses of initializeIndex() with putDirectIndex().
+
+           This patch is performance neutral (according to the JSC command line benchmarks).
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * dfg/DFGOperations.cpp:
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::operationMaterializeObjectInOSR):
+        * heap/DeferGC.cpp:
+        * heap/DeferGC.h:
+        (JSC::DisallowGC::DisallowGC):
+        (JSC::DisallowGC::initialize):
+        (JSC::DisallowGC::scopeReentryCount):
+        (JSC::DisallowGC::setScopeReentryCount):
+        (JSC::DisallowGC::~DisallowGC): Deleted.
+        (JSC::DisallowGC::isGCDisallowedOnCurrentThread): Deleted.
+        * heap/GCDeferralContextInlines.h:
+        (JSC::GCDeferralContext::~GCDeferralContext):
+        * heap/Heap.cpp:
+        (JSC::Heap::collectIfNecessaryOrDefer):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::arrayProtoPrivateFuncConcatMemcpy):
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::createWithInlineFrame):
+        (JSC::ClonedArguments::createByCopyingFrom):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/DisallowScope.h: Added.
+        (JSC::DisallowScope::DisallowScope):
+        (JSC::DisallowScope::~DisallowScope):
+        (JSC::DisallowScope::isInEffectOnCurrentThread):
+        (JSC::DisallowScope::enable):
+        (JSC::DisallowScope::enterScope):
+        (JSC::DisallowScope::exitScope):
+        * runtime/DisallowVMReentry.cpp: Added.
+        * runtime/DisallowVMReentry.h: Added.
+        (JSC::DisallowVMReentry::DisallowVMReentry):
+        (JSC::DisallowVMReentry::initialize):
+        (JSC::DisallowVMReentry::scopeReentryCount):
+        (JSC::DisallowVMReentry::setScopeReentryCount):
+        * runtime/InitializeThreading.cpp:
+        (JSC::initializeThreading):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::tryCreateUninitializedRestricted):
+        (JSC::JSArray::fastSlice):
+        (JSC::JSArray::tryCreateForInitializationPrivate): Deleted.
+        * runtime/JSArray.h:
+        (JSC::JSArray::tryCreateUninitializedRestricted):
+        (JSC::JSArray::tryCreate):
+        (JSC::constructArray):
+        (JSC::constructArrayNegativeIndexed):
+        (JSC::JSArray::tryCreateForInitializationPrivate): Deleted.
+        (JSC::createArrayButterfly): Deleted.
+        * runtime/JSCellInlines.h:
+        (JSC::allocateCell):
+        * runtime/JSObject.h:
+        (JSC::JSObject::initializeIndex):
+        (JSC::JSObject::initializeIndexWithoutBarrier):
+        * runtime/ObjectInitializationScope.cpp: Added.
+        (JSC::ObjectInitializationScope::ObjectInitializationScope):
+        (JSC::ObjectInitializationScope::~ObjectInitializationScope):
+        (JSC::ObjectInitializationScope::notifyAllocated):
+        (JSC::ObjectInitializationScope::verifyPropertiesAreInitialized):
+        * runtime/ObjectInitializationScope.h: Added.
+        (JSC::ObjectInitializationScope::ObjectInitializationScope):
+        (JSC::ObjectInitializationScope::vm):
+        (JSC::ObjectInitializationScope::notifyAllocated):
+        * runtime/Operations.h:
+        (JSC::isScribbledValue):
+        (JSC::scribble):
+        * runtime/RegExpMatchesArray.cpp:
+        (JSC::createEmptyRegExpMatchesArray):
+        * runtime/RegExpMatchesArray.h:
+        (JSC::tryCreateUninitializedRegExpMatchesArray):
+        (JSC::createRegExpMatchesArray):
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::VMEntryScope):
+
 2017-04-27  Carlos Garcia Campos  <cgar...@igalia.com>
 
         [GTK] Remote inspector should support inspecting targets with previous version of backend commands

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (215884 => 215885)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-04-27 19:24:07 UTC (rev 215885)
@@ -2445,11 +2445,16 @@
 		FE3A06BF1C11041600390FDD /* JITRightShiftGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE3A06B81C1103D900390FDD /* JITRightShiftGenerator.cpp */; };
 		FE3A06C01C11041A00390FDD /* JITRightShiftGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3A06B91C1103D900390FDD /* JITRightShiftGenerator.h */; };
 		FE4238901BE18C3C00514737 /* JITSubGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE42388F1BE18C1200514737 /* JITSubGenerator.cpp */; };
+		FE48E6381EB118D2005D7A96 /* ObjectInitializationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE48E6361EB1188F005D7A96 /* ObjectInitializationScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		FE48E6391EB118D9005D7A96 /* ObjectInitializationScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE48E6371EB118AD005D7A96 /* ObjectInitializationScope.cpp */; };
 		FE4BFF2B1AD476E700088F87 /* FunctionOverrides.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */; };
 		FE4BFF2C1AD476E700088F87 /* FunctionOverrides.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */; };
 		FE4D55B81AE716CA0052E459 /* IterationStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4D55B71AE716CA0052E459 /* IterationStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5068641AE246390009DAB7 /* DeferredSourceDump.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FE5068671AE25E280009DAB7 /* DeferredSourceDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */; };
+		FE54DEFB1E8C6D8800A892C5 /* DisallowVMReentry.h in Headers */ = {isa = PBXBuildFile; fileRef = FE54DEFA1E8C6D7200A892C5 /* DisallowVMReentry.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		FE54DEFD1E8C6E3700A892C5 /* DisallowVMReentry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE54DEFC1E8C6DFF00A892C5 /* DisallowVMReentry.cpp */; };
+		FE54DEFF1E8D76FA00A892C5 /* DisallowScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE54DEFE1E8D742800A892C5 /* DisallowScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FE5628CD1E99512D00C49E45 /* AirPrintSpecial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5628CB1E99512400C49E45 /* AirPrintSpecial.cpp */; };
 		FE5628CE1E99513200C49E45 /* AirPrintSpecial.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5628CC1E99512400C49E45 /* AirPrintSpecial.h */; };
 		FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; };
@@ -5080,11 +5085,16 @@
 		FE3A06B81C1103D900390FDD /* JITRightShiftGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITRightShiftGenerator.cpp; sourceTree = "<group>"; };
 		FE3A06B91C1103D900390FDD /* JITRightShiftGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITRightShiftGenerator.h; sourceTree = "<group>"; };
 		FE42388F1BE18C1200514737 /* JITSubGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITSubGenerator.cpp; sourceTree = "<group>"; };
+		FE48E6361EB1188F005D7A96 /* ObjectInitializationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectInitializationScope.h; sourceTree = "<group>"; };
+		FE48E6371EB118AD005D7A96 /* ObjectInitializationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectInitializationScope.cpp; sourceTree = "<group>"; };
 		FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionOverrides.cpp; sourceTree = "<group>"; };
 		FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionOverrides.h; sourceTree = "<group>"; };
 		FE4D55B71AE716CA0052E459 /* IterationStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IterationStatus.h; sourceTree = "<group>"; };
 		FE5068641AE246390009DAB7 /* DeferredSourceDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeferredSourceDump.h; sourceTree = "<group>"; };
 		FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeferredSourceDump.cpp; sourceTree = "<group>"; };
+		FE54DEFA1E8C6D7200A892C5 /* DisallowVMReentry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisallowVMReentry.h; sourceTree = "<group>"; };
+		FE54DEFC1E8C6DFF00A892C5 /* DisallowVMReentry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisallowVMReentry.cpp; sourceTree = "<group>"; };
+		FE54DEFE1E8D742800A892C5 /* DisallowScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisallowScope.h; sourceTree = "<group>"; };
 		FE5628CB1E99512400C49E45 /* AirPrintSpecial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirPrintSpecial.cpp; path = b3/air/AirPrintSpecial.cpp; sourceTree = "<group>"; };
 		FE5628CC1E99512400C49E45 /* AirPrintSpecial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirPrintSpecial.h; path = b3/air/AirPrintSpecial.h; sourceTree = "<group>"; };
 		FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; };
@@ -6562,6 +6572,9 @@
 				0FE0500E1AA9091100D33B33 /* DirectArgumentsOffset.h */,
 				14386A721DD69895008652C4 /* DirectEvalExecutable.cpp */,
 				14386A731DD69895008652C4 /* DirectEvalExecutable.h */,
+				FE54DEFE1E8D742800A892C5 /* DisallowScope.h */,
+				FE54DEFC1E8C6DFF00A892C5 /* DisallowVMReentry.cpp */,
+				FE54DEFA1E8C6D7200A892C5 /* DisallowVMReentry.h */,
 				A70447EB17A0BD7000F5898E /* DumpContext.cpp */,
 				A70447EC17A0BD7000F5898E /* DumpContext.h */,
 				FE318FDD1CAC8C5300DFCC54 /* ECMAScriptSpecInternalFunctions.cpp */,
@@ -6891,6 +6904,8 @@
 				142D3938103E4560007DCB52 /* NumericStrings.h */,
 				BC2680C60E16D4E900A06E92 /* ObjectConstructor.cpp */,
 				BC2680C70E16D4E900A06E92 /* ObjectConstructor.h */,
+				FE48E6371EB118AD005D7A96 /* ObjectInitializationScope.cpp */,
+				FE48E6361EB1188F005D7A96 /* ObjectInitializationScope.h */,
 				BC2680C80E16D4E900A06E92 /* ObjectPrototype.cpp */,
 				BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */,
 				F692A8770255597D01FF60F7 /* Operations.cpp */,
@@ -8133,6 +8148,7 @@
 				5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */,
 				0FEC856E1BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h in Headers */,
 				0FEC85701BDACDC70080FF74 /* AirArg.h in Headers */,
+				FE48E6381EB118D2005D7A96 /* ObjectInitializationScope.h in Headers */,
 				0F64EAF31C4ECD0600621E9B /* AirArgInlines.h in Headers */,
 				0FEC85721BDACDC70080FF74 /* AirBasicBlock.h in Headers */,
 				0FB3878E1BFBC44D00E3AB1E /* AirBlockWorklist.h in Headers */,
@@ -8184,6 +8200,7 @@
 				79ABB17E1E5CCB570045B9A6 /* AirDisassembler.h in Headers */,
 				53529A4C1C457B75000B49C6 /* APIUtils.h in Headers */,
 				BCF605140E203EF800B9A64D /* ArgList.h in Headers */,
+				FE54DEFF1E8D76FA00A892C5 /* DisallowScope.h in Headers */,
 				0FE050141AA9091100D33B33 /* ArgumentsMode.h in Headers */,
 				79A228361D35D71F00D8E067 /* ArithProfile.h in Headers */,
 				0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */,
@@ -9498,6 +9515,7 @@
 				AD2FCC181DB59CB200B3E736 /* WebAssemblyInstanceConstructor.lut.h in Headers */,
 				AD2FCBF31DB58DAD00B3E736 /* WebAssemblyInstancePrototype.h in Headers */,
 				AD2FCC191DB59CB200B3E736 /* WebAssemblyInstancePrototype.lut.h in Headers */,
+				FE54DEFB1E8C6D8800A892C5 /* DisallowVMReentry.h in Headers */,
 				ADE8029A1E08F1DE0058DE78 /* WebAssemblyLinkErrorConstructor.h in Headers */,
 				7965C2171E5D799600B7591D /* AirAllocateRegistersByGraphColoring.h in Headers */,
 				ADE8029C1E08F1DE0058DE78 /* WebAssemblyLinkErrorPrototype.h in Headers */,
@@ -10048,6 +10066,7 @@
 				0FEC857B1BDACDC70080FF74 /* AirHandleCalleeSaves.cpp in Sources */,
 				0FEC857D1BDACDC70080FF74 /* AirInsertionSet.cpp in Sources */,
 				0FEC857F1BDACDC70080FF74 /* AirInst.cpp in Sources */,
+				FE48E6391EB118D9005D7A96 /* ObjectInitializationScope.cpp in Sources */,
 				0FDF67D61D9DC440001B9825 /* AirKind.cpp in Sources */,
 				0FE34C191C4B39AE0003A512 /* AirLogRegisterPressure.cpp in Sources */,
 				0F61832E1C45BF070072450B /* AirLowerAfterRegAlloc.cpp in Sources */,
@@ -10476,6 +10495,7 @@
 				142E3135134FF0A600AFADB5 /* HandleSet.cpp in Sources */,
 				142E3137134FF0A600AFADB5 /* HandleStack.cpp in Sources */,
 				79A0907F1D768465008B889B /* HashMapImpl.cpp in Sources */,
+				FE54DEFD1E8C6E3700A892C5 /* DisallowVMReentry.cpp in Sources */,
 				14BA7A9713AADFF8005B7C2C /* Heap.cpp in Sources */,
 				DC3D2B0C1D34377000BA918C /* HeapCell.cpp in Sources */,
 				0F32BD101BB34F190093A57F /* HeapHelperPool.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1438,7 +1438,7 @@
         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
         CallFrame::argumentOffset(0);
     for (unsigned i = length; i--;)
-        result->initializeIndex(vm, i, arguments[i].jsValue());
+        result->putDirectIndex(exec, i, arguments[i].jsValue());
 
     
     return result;
@@ -2085,7 +2085,7 @@
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
 
-    JSArray* result = JSArray::tryCreateForInitializationPrivate(vm, structure, length);
+    JSArray* result = JSArray::tryCreate(vm, structure, length);
     if (UNLIKELY(!result)) {
         throwOutOfMemoryError(exec, scope);
         return nullptr;
@@ -2098,12 +2098,12 @@
         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
             // We are spreading.
             for (unsigned i = 0; i < array->size(); i++) {
-                result->initializeIndex(vm, index, array->get(i));
+                result->putDirectIndex(exec, index, array->get(i));
                 ++index;
             }
         } else {
             // We are not spreading.
-            result->initializeIndex(vm, index, value);
+            result->putDirectIndex(exec, index, value);
             ++index;
         }
     }

Modified: trunk/Source/_javascript_Core/ftl/FTLOperations.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/ftl/FTLOperations.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/ftl/FTLOperations.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -352,7 +352,7 @@
                 unsigned index = property.location().info();
                 if (index >= length)
                     continue;
-                result->initializeIndex(vm, index, JSValue::decode(values[i]));
+                result->putDirectIndex(exec, index, JSValue::decode(values[i]));
             }
             
             return result;
@@ -364,9 +364,9 @@
             ASSERT(argumentCount > 0);
             unsigned arraySize = (argumentCount - 1) > numberOfArgumentsToSkip ? argumentCount - 1 - numberOfArgumentsToSkip : 0;
 
-            // FIXME: we should throw an out of memory error here if tryCreateForInitializationPrivate() fails.
+            // FIXME: we should throw an out of memory error here if tryCreate() fails.
             // https://bugs.webkit.org/show_bug.cgi?id=169784
-            JSArray* array = JSArray::tryCreateForInitializationPrivate(vm, structure, arraySize);
+            JSArray* array = JSArray::tryCreate(vm, structure, arraySize);
             RELEASE_ASSERT(array);
 
             for (unsigned i = materialization->properties().size(); i--;) {
@@ -380,7 +380,7 @@
                 unsigned arrayIndex = argIndex - numberOfArgumentsToSkip;
                 if (arrayIndex >= arraySize)
                     continue;
-                array->initializeIndex(vm, arrayIndex, JSValue::decode(values[i]));
+                array->putDirectIndex(exec, arrayIndex, JSValue::decode(values[i]));
             }
 
 #if !ASSERT_DISABLED
@@ -455,10 +455,10 @@
             }
         }
 
-        // FIXME: we should throw an out of memory error here if checkedArraySize has hasOverflowed() or tryCreateForInitializationPrivate() fails.
+        // FIXME: we should throw an out of memory error here if checkedArraySize has hasOverflowed() or tryCreate() fails.
         // https://bugs.webkit.org/show_bug.cgi?id=169784
         unsigned arraySize = checkedArraySize.unsafeGet(); // Crashes if overflowed.
-        JSArray* result = JSArray::tryCreateForInitializationPrivate(vm, structure, arraySize);
+        JSArray* result = JSArray::tryCreate(vm, structure, arraySize);
         RELEASE_ASSERT(result);
 
 #if !ASSERT_DISABLED
@@ -493,12 +493,12 @@
             if (JSFixedArray* fixedArray = jsDynamicCast<JSFixedArray*>(vm, value)) {
                 for (unsigned i = 0; i < fixedArray->size(); i++) {
                     ASSERT(fixedArray->get(i));
-                    result->initializeIndex(vm, arrayIndex, fixedArray->get(i));
+                    result->putDirectIndex(exec, arrayIndex, fixedArray->get(i));
                     ++arrayIndex;
                 }
             } else {
                 // We are not spreading.
-                result->initializeIndex(vm, arrayIndex, value);
+                result->putDirectIndex(exec, arrayIndex, value);
                 ++arrayIndex;
             }
         }

Modified: trunk/Source/_javascript_Core/heap/DeferGC.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/heap/DeferGC.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/heap/DeferGC.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,7 +31,7 @@
 namespace JSC {
 
 #ifndef NDEBUG
-WTF::ThreadSpecificKey DisallowGC::s_isGCDisallowedOnCurrentThread = 0;
+WTF::ThreadSpecificKey DisallowGC::s_scopeReentryCount = 0;
 #endif
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/DeferGC.h (215884 => 215885)


--- trunk/Source/_javascript_Core/heap/DeferGC.h	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/heap/DeferGC.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "DisallowScope.h"
 #include "Heap.h"
 #include <wtf/Noncopyable.h>
 #include <wtf/ThreadSpecific.h>
@@ -67,41 +68,41 @@
     Heap& m_heap;
 };
 
-class DisallowGC {
+class DisallowGC : public DisallowScope<DisallowGC> {
     WTF_MAKE_NONCOPYABLE(DisallowGC);
+    typedef DisallowScope<DisallowGC> Base;
 public:
-    DisallowGC()
-    {
-#ifndef NDEBUG
-        WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(true));
-#endif
-    }
+#ifdef NDEBUG
 
-    ~DisallowGC()
+    ALWAYS_INLINE DisallowGC(bool = false) { }
+    ALWAYS_INLINE static void initialize() { }
+
+#else // not NDEBUG
+
+    DisallowGC(bool enabled = true)
+        : Base(enabled)
+    { }
+
+    static void initialize()
     {
-#ifndef NDEBUG
-        WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(false));
-#endif
+        WTF::threadSpecificKeyCreate(&s_scopeReentryCount, 0);
     }
 
-    static bool isGCDisallowedOnCurrentThread()
+private:
+    static uintptr_t scopeReentryCount()
     {
-#ifndef NDEBUG
-        return !!WTF::threadSpecificGet(s_isGCDisallowedOnCurrentThread);
-#else
-        return false;
-#endif
+        return reinterpret_cast<uintptr_t>(WTF::threadSpecificGet(s_scopeReentryCount));
     }
-    static void initialize()
+    static void setScopeReentryCount(uintptr_t value)
     {
-#ifndef NDEBUG
-        WTF::threadSpecificKeyCreate(&s_isGCDisallowedOnCurrentThread, 0);
-#endif
+        WTF::threadSpecificSet(s_scopeReentryCount, reinterpret_cast<void*>(value));
     }
+    
+    JS_EXPORT_PRIVATE static WTF::ThreadSpecificKey s_scopeReentryCount;
 
-#ifndef NDEBUG
-    JS_EXPORT_PRIVATE static WTF::ThreadSpecificKey s_isGCDisallowedOnCurrentThread;
-#endif
+#endif // NDEBUG
+    
+    friend class DisallowScope<DisallowGC>;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/GCDeferralContextInlines.h (215884 => 215885)


--- trunk/Source/_javascript_Core/heap/GCDeferralContextInlines.h	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/heap/GCDeferralContextInlines.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,7 +37,7 @@
 
 ALWAYS_INLINE GCDeferralContext::~GCDeferralContext()
 {
-    ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
+    ASSERT(!DisallowGC::isInEffectOnCurrentThread());
 #if ENABLE(GC_VALIDATION)
     ASSERT(!m_heap.vm()->isInitializingObject());
 #endif

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -2454,7 +2454,7 @@
 
 void Heap::collectIfNecessaryOrDefer(GCDeferralContext* deferralContext)
 {
-    ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
+    ASSERT(deferralContext || isDeferred() || !DisallowGC::isInEffectOnCurrentThread());
 
     if (!m_isSafeToCollect)
         return;

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1314,7 +1314,8 @@
         return JSValue::encode(jsNull());
 
     ASSERT(!lexicalGlobalObject->isHavingABadTime());
-    JSArray* result = JSArray::tryCreateForInitializationPrivate(vm, resultStructure, resultSize);
+    ObjectInitializationScope initializationScope(vm);
+    JSArray* result = JSArray::tryCreateUninitializedRestricted(initializationScope, resultStructure, resultSize);
     if (UNLIKELY(!result)) {
         throwOutOfMemoryError(exec, scope);
         return encodedJSValue();

Modified: trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -87,8 +87,6 @@
 
 ClonedArguments* ClonedArguments::createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode)
 {
-    VM& vm = myFrame->vm();
-    
     JSFunction* callee;
     
     if (inlineCallFrame)
@@ -110,13 +108,13 @@
             result = createEmpty(myFrame, callee, length);
 
             for (unsigned i = length; i--;)
-                result->initializeIndex(vm, i, inlineCallFrame->arguments[i + 1].recover(targetFrame));
+                result->putDirectIndex(myFrame, i, inlineCallFrame->arguments[i + 1].recover(targetFrame));
         } else {
             length = targetFrame->argumentCount();
             result = createEmpty(myFrame, callee, length);
 
             for (unsigned i = length; i--;)
-                result->initializeIndex(vm, i, targetFrame->uncheckedArgument(i));
+                result->putDirectIndex(myFrame, i, targetFrame->uncheckedArgument(i));
         }
         break;
     }
@@ -127,7 +125,7 @@
     } }
 
     ASSERT(myFrame->lexicalGlobalObject()->clonedArgumentsStructure() == result->structure());
-    ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType()));
+    ASSERT(!result->structure()->needsSlowPutIndexing() || shouldUseSlowPut(result->structure()->indexingType()));
     return result;
 }
 
@@ -146,7 +144,7 @@
     ClonedArguments* result = createEmpty(vm, structure, callee, length);
     
     for (unsigned i = length; i--;)
-        result->initializeIndex(vm, i, argumentStart[i].jsValue());
+        result->putDirectIndex(exec, i, argumentStart[i].jsValue());
     ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType()));
     return result;
 }

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1009,7 +1009,7 @@
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
 
-    JSArray* result = JSArray::tryCreateForInitializationPrivate(vm, structure, arraySize);
+    JSArray* result = JSArray::tryCreate(vm, structure, arraySize);
     if (UNLIKELY(!result))
         THROW(createOutOfMemoryError(exec));
     CHECK_EXCEPTION();
@@ -1022,12 +1022,12 @@
             JSFixedArray* array = jsCast<JSFixedArray*>(value);
             for (unsigned i = 0; i < array->size(); i++) {
                 RELEASE_ASSERT(array->get(i));
-                result->initializeIndex(vm, index, array->get(i));
+                result->putDirectIndex(exec, index, array->get(i));
                 ++index;
             }
         } else {
             // We are not spreading.
-            result->initializeIndex(vm, index, value);
+            result->putDirectIndex(exec, index, value);
             ++index;
         }
     }

Added: trunk/Source/_javascript_Core/runtime/DisallowScope.h (0 => 215885)


--- trunk/Source/_javascript_Core/runtime/DisallowScope.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/DisallowScope.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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 <wtf/Noncopyable.h>
+
+namespace JSC {
+
+template<class T>
+class DisallowScope {
+    WTF_MAKE_NONCOPYABLE(DisallowScope);
+public:
+#ifdef NDEBUG
+
+    ALWAYS_INLINE DisallowScope(bool = false) { }
+    ALWAYS_INLINE ~DisallowScope() { }
+    ALWAYS_INLINE static bool isInEffectOnCurrentThread() { return false; }
+    ALWAYS_INLINE void enable() { }
+
+#else // not NDEBUG
+
+    DisallowScope(bool enabled = true)
+    {
+        m_isEnabled = enabled;
+        if (m_isEnabled)
+            enterScope();
+    }
+
+    ~DisallowScope()
+    {
+        if (m_isEnabled)
+            exitScope();
+    }
+
+    static bool isInEffectOnCurrentThread()
+    {
+        return !!T::scopeReentryCount();
+    }
+
+    void enable()
+    {
+        m_isEnabled = true;
+        enterScope();
+    }
+
+private:
+    void enterScope()
+    {
+        auto count = T::scopeReentryCount();
+        T::setScopeReentryCount(++count);
+    }
+
+    void exitScope()
+    {
+        auto count = T::scopeReentryCount();
+        ASSERT(count);
+        T::setScopeReentryCount(--count);
+    }
+
+    bool m_isEnabled;
+#endif // NDEBUG
+};
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/DisallowVMReentry.cpp (0 => 215885)


--- trunk/Source/_javascript_Core/runtime/DisallowVMReentry.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/DisallowVMReentry.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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. AND ITS CONTRIBUTORS ``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 ITS 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 "DisallowVMReentry.h"
+
+#include "JSCInlines.h"
+
+namespace JSC {
+    
+#ifndef NDEBUG
+WTF::ThreadSpecificKey DisallowVMReentry::s_scopeReentryCount = 0;
+#endif
+    
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/DisallowVMReentry.h (0 => 215885)


--- trunk/Source/_javascript_Core/runtime/DisallowVMReentry.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/DisallowVMReentry.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 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 "DisallowScope.h"
+#include <wtf/ThreadSpecific.h>
+
+namespace JSC {
+
+class DisallowVMReentry : public DisallowScope<DisallowVMReentry> {
+    WTF_MAKE_NONCOPYABLE(DisallowVMReentry);
+    typedef DisallowScope<DisallowVMReentry> Base;
+public:
+#ifdef NDEBUG
+
+    ALWAYS_INLINE DisallowVMReentry(bool = false) { }
+    ALWAYS_INLINE static void initialize() { }
+
+#else // not NDEBUG
+
+    DisallowVMReentry(bool enabled = true)
+        : Base(enabled)
+    { }
+
+    static void initialize()
+    {
+        WTF::threadSpecificKeyCreate(&s_scopeReentryCount, 0);
+    }
+
+private:
+    static uintptr_t scopeReentryCount()
+    {
+        return reinterpret_cast<uintptr_t>(WTF::threadSpecificGet(s_scopeReentryCount));
+    }
+    static void setScopeReentryCount(uintptr_t value)
+    {
+        WTF::threadSpecificSet(s_scopeReentryCount, reinterpret_cast<void*>(value));
+    }
+
+    JS_EXPORT_PRIVATE static WTF::ThreadSpecificKey s_scopeReentryCount;
+
+#endif // NDEBUG
+
+    friend class DisallowScope<DisallowVMReentry>;
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -29,6 +29,7 @@
 #include "config.h"
 #include "InitializeThreading.h"
 
+#include "DisallowVMReentry.h"
 #include "ExecutableAllocator.h"
 #include "Heap.h"
 #include "Identifier.h"
@@ -71,6 +72,7 @@
         LLInt::initialize();
 #ifndef NDEBUG
         DisallowGC::initialize();
+        DisallowVMReentry::initialize();
 #endif
         initializeSuperSampler();
         WTFThreadData& threadData = wtfThreadData();

Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/JSArray.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -60,11 +60,15 @@
     return butterfly;
 }
 
-JSArray* JSArray::tryCreateForInitializationPrivate(VM& vm, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength)
+JSArray* JSArray::tryCreateUninitializedRestricted(ObjectInitializationScope& scope, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength)
 {
+    VM& vm = scope.vm();
+
     if (UNLIKELY(initialLength > MAX_STORAGE_VECTOR_LENGTH))
         return 0;
 
+    JSGlobalObject* globalObject = structure->globalObject();
+    bool createUninitialized = globalObject->isOriginalArrayStructure(structure);
     unsigned outOfLineStorage = structure->outOfLineCapacity();
 
     Butterfly* butterfly;
@@ -83,29 +87,34 @@
         butterfly = Butterfly::fromBase(temp, 0, outOfLineStorage);
         butterfly->setVectorLength(vectorLength);
         butterfly->setPublicLength(initialLength);
+        unsigned i = (createUninitialized ? initialLength : 0);
         if (hasDouble(indexingType)) {
-            for (unsigned i = initialLength; i < vectorLength; ++i)
+            for (; i < vectorLength; ++i)
                 butterfly->contiguousDouble()[i] = PNaN;
         } else {
-            for (unsigned i = initialLength; i < vectorLength; ++i)
+            for (; i < vectorLength; ++i)
                 butterfly->contiguous()[i].clear();
         }
     } else {
-        unsigned vectorLength = ArrayStorage::optimalVectorLength(0, structure, initialLength);
-        void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(0, outOfLineStorage, true, ArrayStorage::sizeFor(vectorLength)));
+        static const unsigned indexBias = 0;
+        unsigned vectorLength = ArrayStorage::optimalVectorLength(indexBias, structure, initialLength);
+        void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(indexBias, outOfLineStorage, true, ArrayStorage::sizeFor(vectorLength)));
         if (UNLIKELY(!temp))
             return nullptr;
-        butterfly = Butterfly::fromBase(temp, 0, outOfLineStorage);
+        butterfly = Butterfly::fromBase(temp, indexBias, outOfLineStorage);
         *butterfly->indexingHeader() = indexingHeaderForArrayStorage(initialLength, vectorLength);
         ArrayStorage* storage = butterfly->arrayStorage();
-        storage->m_indexBias = 0;
+        storage->m_indexBias = indexBias;
         storage->m_sparseMap.clear();
         storage->m_numValuesInVector = initialLength;
-        for (unsigned i = initialLength; i < vectorLength; ++i)
+        unsigned i = (createUninitialized ? initialLength : 0);
+        for (; i < vectorLength; ++i)
             storage->m_vector[i].clear();
     }
 
-    return createWithButterfly(vm, deferralContext, structure, butterfly);
+    JSArray* result = createWithButterfly(vm, deferralContext, structure, butterfly);
+    scope.notifyAllocated(result, createUninitialized);
+    return result;
 }
 
 void JSArray::setLengthWritable(ExecState* exec, bool writable)
@@ -873,7 +882,8 @@
             return nullptr;
 
         ASSERT(!lexicalGlobalObject->isHavingABadTime());
-        JSArray* resultArray = JSArray::tryCreateForInitializationPrivate(vm, resultStructure, count);
+        ObjectInitializationScope scope(vm);
+        JSArray* resultArray = JSArray::tryCreateUninitializedRestricted(scope, resultStructure, count);
         if (UNLIKELY(!resultArray))
             return nullptr;
 

Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/JSArray.h	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -56,18 +56,24 @@
     static JSArray* create(VM&, Structure*, unsigned initialLength = 0);
     static JSArray* createWithButterfly(VM&, GCDeferralContext*, Structure*, Butterfly*);
 
-    // tryCreateForInitializationPrivate is used for fast construction of arrays whose size and
-    // contents are known at time of creation. This should be considered a private API.
+    // tryCreateUninitializedRestricted is used for fast construction of arrays whose size and
+    // contents are known at time of creation. This is a restricted API for careful use only in
+    // performance critical code paths. If you don't have a good reason to use it, you probably
+    // shouldn't use it. Instead, you should go with
+    //   - JSArray::tryCreate() or JSArray::create() instead of tryCreateUninitializedRestricted(), and
+    //   - putDirectIndex() instead of initializeIndex().
+    //
     // Clients of this interface must:
     //   - null-check the result (indicating out of memory, or otherwise unable to allocate vector).
     //   - call 'initializeIndex' for all properties in sequence, for 0 <= i < initialLength.
     //   - Provide a valid GCDefferalContext* if they might garbage collect when initializing properties,
     //     otherwise the caller can provide a null GCDefferalContext*.
+    //   - Provide a local stack instance of ObjectInitializationScope at the call site.
     //
-    JS_EXPORT_PRIVATE static JSArray* tryCreateForInitializationPrivate(VM&, GCDeferralContext*, Structure*, unsigned initialLength);
-    static JSArray* tryCreateForInitializationPrivate(VM& vm, Structure* structure, unsigned initialLength)
+    JS_EXPORT_PRIVATE static JSArray* tryCreateUninitializedRestricted(ObjectInitializationScope&, GCDeferralContext*, Structure*, unsigned initialLength);
+    static JSArray* tryCreateUninitializedRestricted(ObjectInitializationScope& scope, Structure* structure, unsigned initialLength)
     {
-        return tryCreateForInitializationPrivate(vm, nullptr, structure, initialLength);
+        return tryCreateUninitializedRestricted(scope, nullptr, structure, initialLength);
     }
 
     JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool throwException);
@@ -204,13 +210,6 @@
     return butterfly;
 }
 
-inline Butterfly* createArrayButterfly(VM& vm, JSCell* intendedOwner, unsigned initialLength)
-{
-    Butterfly* result = tryCreateArrayButterfly(vm, intendedOwner, initialLength);
-    RELEASE_ASSERT(result);
-    return result;
-}
-
 Butterfly* createArrayButterflyInDictionaryIndexingMode(
     VM&, JSCell* intendedOwner, unsigned initialLength);
 
@@ -227,8 +226,8 @@
             || hasDouble(indexingType)
             || hasContiguous(indexingType));
 
-        if (initialLength > MAX_STORAGE_VECTOR_LENGTH)
-            return 0;
+        if (UNLIKELY(initialLength > MAX_STORAGE_VECTOR_LENGTH))
+            return nullptr;
 
         unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, initialLength);
         void* temp = vm.auxiliarySpace.tryAllocate(nullptr, Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)));
@@ -245,7 +244,7 @@
         ASSERT(
             indexingType == ArrayWithSlowPutArrayStorage
             || indexingType == ArrayWithArrayStorage);
-        butterfly = tryCreateArrayButterfly(vm, 0, initialLength);
+        butterfly = tryCreateArrayButterfly(vm, nullptr, initialLength);
         if (!butterfly)
             return nullptr;
         for (unsigned i = 0; i < BASE_ARRAY_STORAGE_VECTOR_LEN; ++i)
@@ -295,7 +294,8 @@
 {
     VM& vm = exec->vm();
     unsigned length = values.size();
-    JSArray* array = JSArray::tryCreateForInitializationPrivate(vm, arrayStructure, length);
+    ObjectInitializationScope scope(vm);
+    JSArray* array = JSArray::tryCreateUninitializedRestricted(scope, arrayStructure, length);
 
     // FIXME: we should probably throw an out of memory error here, but
     // when making this change we should check that all clients of this
@@ -304,7 +304,7 @@
     RELEASE_ASSERT(array);
 
     for (unsigned i = 0; i < length; ++i)
-        array->initializeIndex(vm, i, values.at(i));
+        array->initializeIndex(scope, i, values.at(i));
     return array;
 }
     
@@ -311,7 +311,8 @@
 inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const JSValue* values, unsigned length)
 {
     VM& vm = exec->vm();
-    JSArray* array = JSArray::tryCreateForInitializationPrivate(vm, arrayStructure, length);
+    ObjectInitializationScope scope(vm);
+    JSArray* array = JSArray::tryCreateUninitializedRestricted(scope, arrayStructure, length);
 
     // FIXME: we should probably throw an out of memory error here, but
     // when making this change we should check that all clients of this
@@ -320,7 +321,7 @@
     RELEASE_ASSERT(array);
 
     for (unsigned i = 0; i < length; ++i)
-        array->initializeIndex(vm, i, values[i]);
+        array->initializeIndex(scope, i, values[i]);
     return array;
 }
 
@@ -327,7 +328,8 @@
 inline JSArray* constructArrayNegativeIndexed(ExecState* exec, Structure* arrayStructure, const JSValue* values, unsigned length)
 {
     VM& vm = exec->vm();
-    JSArray* array = JSArray::tryCreateForInitializationPrivate(vm, arrayStructure, length);
+    ObjectInitializationScope scope(vm);
+    JSArray* array = JSArray::tryCreateUninitializedRestricted(scope, arrayStructure, length);
 
     // FIXME: we should probably throw an out of memory error here, but
     // when making this change we should check that all clients of this
@@ -336,7 +338,7 @@
     RELEASE_ASSERT(array);
 
     for (int i = 0; i < static_cast<int>(length); ++i)
-        array->initializeIndex(vm, i, values[-i]);
+        array->initializeIndex(scope, i, values[-i]);
     return array;
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSCellInlines.h (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/JSCellInlines.h	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/JSCellInlines.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -145,7 +145,7 @@
 template<typename T>
 void* allocateCell(Heap& heap, size_t size)
 {
-    ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
+    ASSERT(!DisallowGC::isInEffectOnCurrentThread());
     ASSERT(size >= sizeof(T));
     JSCell* result = static_cast<JSCell*>(subspaceFor<T>(*heap.vm())->allocate(size));
 #if ENABLE(GC_VALIDATION)

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -36,6 +36,7 @@
 #include "Heap.h"
 #include "IndexingHeaderInlines.h"
 #include "JSCell.h"
+#include "ObjectInitializationScope.h"
 #include "PropertySlot.h"
 #include "PropertyStorage.h"
 #include "PutDirectIndexMode.h"
@@ -420,15 +421,16 @@
         }
     }
 
-    void initializeIndex(VM& vm, unsigned i, JSValue v)
+    void initializeIndex(ObjectInitializationScope& scope, unsigned i, JSValue v)
     {
-        initializeIndex(vm, i, v, indexingType());
+        initializeIndex(scope, i, v, indexingType());
     }
 
     // NOTE: Clients of this method may call it more than once for any index, and this is supposed
     // to work.
-    ALWAYS_INLINE void initializeIndex(VM& vm, unsigned i, JSValue v, IndexingType indexingType)
+    ALWAYS_INLINE void initializeIndex(ObjectInitializationScope& scope, unsigned i, JSValue v, IndexingType indexingType)
     {
+        VM& vm = scope.vm();
         Butterfly* butterfly = m_butterfly.get();
         switch (indexingType) {
         case ALL_UNDECIDED_INDEXING_TYPES: {
@@ -477,14 +479,14 @@
         }
     }
         
-    void initializeIndexWithoutBarrier(unsigned i, JSValue v)
+    void initializeIndexWithoutBarrier(ObjectInitializationScope& scope, unsigned i, JSValue v)
     {
-        initializeIndexWithoutBarrier(i, v, indexingType());
+        initializeIndexWithoutBarrier(scope, i, v, indexingType());
     }
 
     // This version of initializeIndex is for cases where you know that you will not need any
     // barriers. This implies not having any data format conversions.
-    ALWAYS_INLINE void initializeIndexWithoutBarrier(unsigned i, JSValue v, IndexingType indexingType)
+    ALWAYS_INLINE void initializeIndexWithoutBarrier(ObjectInitializationScope&, unsigned i, JSValue v, IndexingType indexingType)
     {
         Butterfly* butterfly = m_butterfly.get();
         switch (indexingType) {

Added: trunk/Source/_javascript_Core/runtime/ObjectInitializationScope.cpp (0 => 215885)


--- trunk/Source/_javascript_Core/runtime/ObjectInitializationScope.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ObjectInitializationScope.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 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 "ObjectInitializationScope.h"
+
+#include "JSObject.h"
+#include "Operations.h"
+
+namespace JSC {
+
+#ifndef NDEBUG
+ObjectInitializationScope::ObjectInitializationScope(VM& vm)
+    : m_vm(vm)
+    , m_disallowGC(false)
+    , m_disallowVMReentry(false)
+{
+}
+
+ObjectInitializationScope::~ObjectInitializationScope()
+{
+    if (!m_object)
+        return;
+    verifyPropertiesAreInitialized(m_object);
+}
+
+void ObjectInitializationScope::notifyAllocated(JSObject* object, bool wasCreatedUninitialized)
+{
+    if (wasCreatedUninitialized) {
+        m_disallowGC.enable();
+        m_disallowVMReentry.enable();
+        m_object = object;
+    } else
+        verifyPropertiesAreInitialized(object);
+}
+
+void ObjectInitializationScope::verifyPropertiesAreInitialized(JSObject* object)
+{
+    Butterfly* butterfly = object->butterfly();
+    IndexingType indexingType = object->structure(m_vm)->indexingType();
+    unsigned vectorLength = butterfly->vectorLength();
+    if (UNLIKELY(hasUndecided(indexingType))) {
+        // Nothing to verify.
+    } else if (LIKELY(!hasAnyArrayStorage(indexingType))) {
+        auto data = ""
+        for (unsigned i = 0; i < vectorLength; ++i)
+            ASSERT(!isScribbledValue(data[i].get()));
+    } else {
+        ArrayStorage* storage = butterfly->arrayStorage();
+        for (unsigned i = 0; i < vectorLength; ++i)
+            ASSERT(!isScribbledValue(storage->m_vector[i].get()));
+    }
+}
+#endif
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/ObjectInitializationScope.h (0 => 215885)


--- trunk/Source/_javascript_Core/runtime/ObjectInitializationScope.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ObjectInitializationScope.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 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 "DeferGC.h"
+#include "DisallowVMReentry.h"
+
+namespace JSC {
+
+class VM;
+class JSObject;
+
+#ifdef NDEBUG
+
+class ObjectInitializationScope {
+public:
+    ALWAYS_INLINE ObjectInitializationScope(VM& vm)
+        : m_vm(vm)
+    { }
+
+    ALWAYS_INLINE VM& vm() const { return m_vm; }
+    ALWAYS_INLINE void notifyAllocated(JSObject*, bool) { }
+
+private:
+    VM& m_vm;
+};
+
+#else // not NDEBUG
+
+class ObjectInitializationScope {
+public:
+    JS_EXPORT_PRIVATE ObjectInitializationScope(VM&);
+    JS_EXPORT_PRIVATE ~ObjectInitializationScope();
+
+    VM& vm() const { return m_vm; }
+    void notifyAllocated(JSObject*, bool wasCreatedUninitialized);
+
+private:
+    void verifyPropertiesAreInitialized(JSObject*);
+
+    VM& m_vm;
+    DisallowGC m_disallowGC;
+    DisallowVMReentry m_disallowVMReentry;
+    JSObject* m_object { nullptr };
+};
+
+#endif // NDEBUG
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/Operations.h (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/Operations.h	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/Operations.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- *  Copyright (C) 2002, 2005-2009, 2013-2014, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2002-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -261,12 +261,18 @@
     return !ASSERT_DISABLED || Options::scribbleFreeCells();
 }
 
+#define SCRIBBLE_WORD static_cast<intptr_t>(0xbadbeef0)
+
+inline bool isScribbledValue(JSValue value)
+{
+    return JSValue::encode(value) == JSValue::encode(bitwise_cast<JSCell*>(SCRIBBLE_WORD));
+}
+
 inline void scribble(void* base, size_t size)
 {
     for (size_t i = size / sizeof(EncodedJSValue); i--;) {
         // Use a 16-byte aligned value to ensure that it passes the cell check.
-        static_cast<EncodedJSValue*>(base)[i] = JSValue::encode(
-            bitwise_cast<JSCell*>(static_cast<intptr_t>(0xbadbeef0)));
+        static_cast<EncodedJSValue*>(base)[i] = JSValue::encode(bitwise_cast<JSCell*>(SCRIBBLE_WORD));
     }
 }
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,7 +39,8 @@
     GCDeferralContext deferralContext(vm.heap);
     
     if (UNLIKELY(globalObject->isHavingABadTime())) {
-        array = JSArray::tryCreateForInitializationPrivate(vm, &deferralContext, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
+        ObjectInitializationScope scope(vm);
+        array = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
         // FIXME: we should probably throw an out of memory error here, but
         // when making this change we should check that all clients of this
         // function will correctly handle an exception being thrown from here.
@@ -46,21 +47,22 @@
         // https://bugs.webkit.org/show_bug.cgi?id=169786
         RELEASE_ASSERT(array);
 
-        array->initializeIndexWithoutBarrier(0, jsEmptyString(&vm));
+        array->initializeIndexWithoutBarrier(scope, 0, jsEmptyString(&vm));
         
         if (unsigned numSubpatterns = regExp->numSubpatterns()) {
             for (unsigned i = 1; i <= numSubpatterns; ++i)
-                array->initializeIndexWithoutBarrier(i, jsUndefined());
+                array->initializeIndexWithoutBarrier(scope, i, jsUndefined());
         }
     } else {
-        array = tryCreateUninitializedRegExpMatchesArray(vm, &deferralContext, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
+        ObjectInitializationScope scope(vm);
+        array = tryCreateUninitializedRegExpMatchesArray(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
         RELEASE_ASSERT(array);
         
-        array->initializeIndexWithoutBarrier(0, jsEmptyString(&vm), ArrayWithContiguous);
+        array->initializeIndexWithoutBarrier(scope, 0, jsEmptyString(&vm), ArrayWithContiguous);
         
         if (unsigned numSubpatterns = regExp->numSubpatterns()) {
             for (unsigned i = 1; i <= numSubpatterns; ++i)
-                array->initializeIndexWithoutBarrier(i, jsUndefined(), ArrayWithContiguous);
+                array->initializeIndexWithoutBarrier(scope, i, jsUndefined(), ArrayWithContiguous);
         }
     }
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h	2017-04-27 19:24:07 UTC (rev 215885)
@@ -32,23 +32,29 @@
 static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100;
 static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101;
 
-ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(VM& vm, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength)
+ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(ObjectInitializationScope& scope, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength)
 {
+    VM& vm = scope.vm();
     unsigned vectorLength = initialLength;
     if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
         return 0;
 
+    JSGlobalObject* globalObject = structure->globalObject();
+    bool createUninitialized = globalObject->isOriginalArrayStructure(structure);
     void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
-    if (!temp)
+    if (UNLIKELY(!temp))
         return nullptr;
     Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
     butterfly->setVectorLength(vectorLength);
     butterfly->setPublicLength(initialLength);
-    
-    for (unsigned i = initialLength; i < vectorLength; ++i)
+
+    unsigned i = (createUninitialized ? initialLength : 0);
+    for (; i < vectorLength; ++i)
         butterfly->contiguous()[i].clear();
-    
-    return JSArray::createWithButterfly(vm, deferralContext, structure, butterfly);
+
+    JSArray* result = JSArray::createWithButterfly(vm, deferralContext, structure, butterfly);
+    scope.notifyAllocated(result, createUninitialized);
+    return result;
 }
 
 ALWAYS_INLINE JSArray* createRegExpMatchesArray(
@@ -80,7 +86,8 @@
     GCDeferralContext deferralContext(vm.heap);
     
     if (UNLIKELY(globalObject->isHavingABadTime())) {
-        array = JSArray::tryCreateForInitializationPrivate(vm, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1);
+        ObjectInitializationScope scope(vm);
+        array = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1);
         // FIXME: we should probably throw an out of memory error here, but
         // when making this change we should check that all clients of this
         // function will correctly handle an exception being thrown from here.
@@ -89,7 +96,7 @@
 
         setProperties();
         
-        array->initializeIndexWithoutBarrier(0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start));
+        array->initializeIndexWithoutBarrier(scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start));
         
         for (unsigned i = 1; i <= numSubpatterns; ++i) {
             int start = subpatternResults[2 * i];
@@ -98,10 +105,11 @@
                 value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
             else
                 value = jsUndefined();
-            array->initializeIndexWithoutBarrier(i, value);
+            array->initializeIndexWithoutBarrier(scope, i, value);
         }
     } else {
-        array = tryCreateUninitializedRegExpMatchesArray(vm, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1);
+        ObjectInitializationScope scope(vm);
+        array = tryCreateUninitializedRegExpMatchesArray(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1);
         RELEASE_ASSERT(array);
         
         setProperties();
@@ -108,7 +116,7 @@
         
         // Now the object is safe to scan by GC.
 
-        array->initializeIndexWithoutBarrier(0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous);
+        array->initializeIndexWithoutBarrier(scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous);
         
         for (unsigned i = 1; i <= numSubpatterns; ++i) {
             int start = subpatternResults[2 * i];
@@ -117,7 +125,7 @@
                 value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
             else
                 value = jsUndefined();
-            array->initializeIndexWithoutBarrier(i, value, ArrayWithContiguous);
+            array->initializeIndexWithoutBarrier(scope, i, value, ArrayWithContiguous);
         }
     }
     return array;

Modified: trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp (215884 => 215885)


--- trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2017-04-27 19:08:22 UTC (rev 215884)
+++ trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2017-04-27 19:24:07 UTC (rev 215885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "VMEntryScope.h"
 
+#include "DisallowVMReentry.h"
 #include "Options.h"
 #include "SamplingProfiler.h"
 #include "VM.h"
@@ -39,6 +40,7 @@
     : m_vm(vm)
     , m_globalObject(globalObject)
 {
+    ASSERT(!DisallowVMReentry::isInEffectOnCurrentThread());
     ASSERT(wtfThreadData().stack().isGrowingDownward());
     if (!vm.entryScope) {
         vm.entryScope = this;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to