[JSC] Remove LocalScope
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Jan 2018 15:54:40 +0000 (15:54 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Jan 2018 15:54:40 +0000 (15:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181206

Reviewed by Geoffrey Garen.

The last user of HandleStack and LocalScope is JSON. But MarkedArgumentBuffer is enough for their use.
This patch changes JSON parsing and stringifying to using MarkedArgumentBuffer. And remove HandleStack
and LocalScope.

We make Stringifier and Walker WTF_FORBID_HEAP_ALLOCATION to place them on the stack. So they can hold
JSObject* directly in their fields.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* heap/HandleStack.cpp: Removed.
* heap/HandleStack.h: Removed.
* heap/Heap.cpp:
(JSC::Heap::addCoreConstraints):
* heap/Heap.h:
(JSC::Heap::handleSet):
(JSC::Heap::handleStack): Deleted.
* heap/Local.h: Removed.
* heap/LocalScope.h: Removed.
* runtime/JSONObject.cpp:
(JSC::Stringifier::Holder::object const):
(JSC::gap):
(JSC::Stringifier::Stringifier):
(JSC::Stringifier::stringify):
(JSC::Stringifier::appendStringifiedValue):
(JSC::Stringifier::Holder::Holder):
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::Walker):
(JSC::Walker::callReviver):
(JSC::Walker::walk):
(JSC::JSONProtoFuncParse):
(JSC::JSONProtoFuncStringify):
(JSC::JSONParse):
(JSC::JSONStringify):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/heap/HandleStack.cpp [deleted file]
Source/JavaScriptCore/heap/HandleStack.h [deleted file]
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/Local.h [deleted file]
Source/JavaScriptCore/heap/LocalScope.h [deleted file]
Source/JavaScriptCore/runtime/JSONObject.cpp

index 65b9eeb..c12bd49 100644 (file)
@@ -1,5 +1,46 @@
 2018-01-04  Yusuke Suzuki  <utatane.tea@gmail.com>
 
+        [JSC] Remove LocalScope
+        https://bugs.webkit.org/show_bug.cgi?id=181206
+
+        Reviewed by Geoffrey Garen.
+
+        The last user of HandleStack and LocalScope is JSON. But MarkedArgumentBuffer is enough for their use.
+        This patch changes JSON parsing and stringifying to using MarkedArgumentBuffer. And remove HandleStack
+        and LocalScope.
+
+        We make Stringifier and Walker WTF_FORBID_HEAP_ALLOCATION to place them on the stack. So they can hold
+        JSObject* directly in their fields.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * heap/HandleStack.cpp: Removed.
+        * heap/HandleStack.h: Removed.
+        * heap/Heap.cpp:
+        (JSC::Heap::addCoreConstraints):
+        * heap/Heap.h:
+        (JSC::Heap::handleSet):
+        (JSC::Heap::handleStack): Deleted.
+        * heap/Local.h: Removed.
+        * heap/LocalScope.h: Removed.
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::Holder::object const):
+        (JSC::gap):
+        (JSC::Stringifier::Stringifier):
+        (JSC::Stringifier::stringify):
+        (JSC::Stringifier::appendStringifiedValue):
+        (JSC::Stringifier::Holder::Holder):
+        (JSC::Stringifier::Holder::appendNextProperty):
+        (JSC::Walker::Walker):
+        (JSC::Walker::callReviver):
+        (JSC::Walker::walk):
+        (JSC::JSONProtoFuncParse):
+        (JSC::JSONProtoFuncStringify):
+        (JSC::JSONParse):
+        (JSC::JSONStringify):
+
+2018-01-04  Yusuke Suzuki  <utatane.tea@gmail.com>
+
         [FTL] Optimize ObjectAllocationSinking mergePointerSets by using removeIf
         https://bugs.webkit.org/show_bug.cgi?id=180238
 
index b0fc57d..4b43dc1 100644 (file)
                142D6F1213539A4100B02E86 /* MarkStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 142D6F0F13539A4100B02E86 /* MarkStack.h */; settings = {ATTRIBUTES = (Private, ); }; };
                142E3134134FF0A600AFADB5 /* Handle.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E312B134FF0A600AFADB5 /* Handle.h */; settings = {ATTRIBUTES = (Private, ); }; };
                142E3136134FF0A600AFADB5 /* HandleSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E312D134FF0A600AFADB5 /* HandleSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               142E3138134FF0A600AFADB5 /* HandleStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E312F134FF0A600AFADB5 /* HandleStack.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               142E3139134FF0A600AFADB5 /* Local.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3130134FF0A600AFADB5 /* Local.h */; };
-               142E313A134FF0A600AFADB5 /* LocalScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3131134FF0A600AFADB5 /* LocalScope.h */; };
                142E313B134FF0A600AFADB5 /* Strong.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3132134FF0A600AFADB5 /* Strong.h */; settings = {ATTRIBUTES = (Private, ); }; };
                142E313C134FF0A600AFADB5 /* Weak.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3133134FF0A600AFADB5 /* Weak.h */; settings = {ATTRIBUTES = (Private, ); }; };
                14386A751DD69895008652C4 /* DirectEvalExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14386A731DD69895008652C4 /* DirectEvalExecutable.h */; settings = {ATTRIBUTES = (Private, ); }; };
                142E312B134FF0A600AFADB5 /* Handle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Handle.h; sourceTree = "<group>"; };
                142E312C134FF0A600AFADB5 /* HandleSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HandleSet.cpp; sourceTree = "<group>"; };
                142E312D134FF0A600AFADB5 /* HandleSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandleSet.h; sourceTree = "<group>"; };
-               142E312E134FF0A600AFADB5 /* HandleStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HandleStack.cpp; sourceTree = "<group>"; };
-               142E312F134FF0A600AFADB5 /* HandleStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandleStack.h; sourceTree = "<group>"; };
-               142E3130134FF0A600AFADB5 /* Local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Local.h; sourceTree = "<group>"; };
-               142E3131134FF0A600AFADB5 /* LocalScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalScope.h; sourceTree = "<group>"; };
                142E3132134FF0A600AFADB5 /* Strong.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Strong.h; sourceTree = "<group>"; };
                142E3133134FF0A600AFADB5 /* Weak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Weak.h; sourceTree = "<group>"; };
                14386A721DD69895008652C4 /* DirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectEvalExecutable.cpp; sourceTree = "<group>"; };
                                C283190116FE533E00157BFD /* HandleBlockInlines.h */,
                                142E312C134FF0A600AFADB5 /* HandleSet.cpp */,
                                142E312D134FF0A600AFADB5 /* HandleSet.h */,
-                               142E312E134FF0A600AFADB5 /* HandleStack.cpp */,
-                               142E312F134FF0A600AFADB5 /* HandleStack.h */,
                                146FA5A81378F6B0003627A3 /* HandleTypes.h */,
                                14BA7A9513AADFF8005B7C2C /* Heap.cpp */,
                                14BA7A9613AADFF8005B7C2C /* Heap.h */,
                                0F070A451D543A89006E7232 /* LargeAllocation.cpp */,
                                0F070A461D543A89006E7232 /* LargeAllocation.h */,
                                0F431736146BAC65007E3890 /* ListableHandler.h */,
-                               142E3130134FF0A600AFADB5 /* Local.h */,
-                               142E3131134FF0A600AFADB5 /* LocalScope.h */,
                                0F208AD61DF0925A007D3269 /* LockDuringMarking.h */,
                                14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */,
                                14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */,
                                C283190216FE533E00157BFD /* HandleBlockInlines.h in Headers */,
                                0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */,
                                142E3136134FF0A600AFADB5 /* HandleSet.h in Headers */,
-                               142E3138134FF0A600AFADB5 /* HandleStack.h in Headers */,
                                1478297B1379E8A800A7C2A3 /* HandleTypes.h in Headers */,
                                79A090801D768465008B889B /* HashMapImpl.h in Headers */,
                                79DFCBDB1D88C59600527D03 /* HasOwnPropertyCache.h in Headers */,
                                53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */,
                                0F4680A514BA7F8D00BFE272 /* LLIntSlowPaths.h in Headers */,
                                0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */,
-                               142E3139134FF0A600AFADB5 /* Local.h in Headers */,
-                               142E313A134FF0A600AFADB5 /* LocalScope.h in Headers */,
                                0F208AD71DF0925D007D3269 /* LockDuringMarking.h in Headers */,
                                BC18C4370E16F5CD00B34460 /* Lookup.h in Headers */,
                                0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */,
index 4ca910f..2c1eba8 100644 (file)
@@ -484,7 +484,6 @@ heap/GCLogging.cpp
 heap/GCRequest.cpp
 heap/GigacageAlignedMemoryAllocator.cpp
 heap/HandleSet.cpp
-heap/HandleStack.cpp
 heap/Heap.cpp
 heap/HeapCell.cpp
 heap/HeapCellType.cpp
diff --git a/Source/JavaScriptCore/heap/HandleStack.cpp b/Source/JavaScriptCore/heap/HandleStack.cpp
deleted file mode 100644 (file)
index 30c0d1f..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010-2016 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 "HandleStack.h"
-
-#include "JSObject.h"
-#include "JSCInlines.h"
-
-namespace JSC {
-
-HandleStack::HandleStack()
-#ifndef NDEBUG
-    : m_scopeDepth(0)
-#endif
-{
-    grow();
-}
-
-void HandleStack::visit(SlotVisitor& visitor)
-{
-    const Vector<HandleSlot>& blocks = m_blockStack.blocks();
-    size_t blockLength = m_blockStack.blockLength;
-
-    int end = blocks.size() - 1;
-    for (int i = 0; i < end; ++i) {
-        HandleSlot block = blocks[i];
-        visitor.appendUnbarriered(block, blockLength);
-    }
-    HandleSlot block = blocks[end];
-    visitor.appendUnbarriered(block, m_frame.m_next - block);
-}
-
-void HandleStack::grow()
-{
-    HandleSlot block = m_blockStack.grow();
-    m_frame.m_next = block;
-    m_frame.m_end = block + m_blockStack.blockLength;
-}
-
-}
diff --git a/Source/JavaScriptCore/heap/HandleStack.h b/Source/JavaScriptCore/heap/HandleStack.h
deleted file mode 100644 (file)
index dc14864..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2010-2016 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.
- */
-
-#pragma once
-
-#include <wtf/Assertions.h>
-#include <wtf/BlockStack.h>
-#include "Handle.h"
-
-namespace JSC {
-
-class LocalScope;
-class SlotVisitor;
-
-class HandleStack {
-public:
-    class Frame {
-    public:
-        HandleSlot m_next;
-        HandleSlot m_end;
-    };
-
-    HandleStack();
-    
-    void enterScope(Frame&);
-    void leaveScope(Frame&);
-
-    HandleSlot push();
-
-    void visit(SlotVisitor&);
-
-private:
-    JS_EXPORT_PRIVATE void grow();
-    void zapTo(Frame&);
-    HandleSlot findFirstAfter(HandleSlot);
-
-#ifndef NDEBUG
-    size_t m_scopeDepth;
-#endif
-    BlockStack<JSValue> m_blockStack;
-    Frame m_frame;
-};
-
-inline void HandleStack::enterScope(Frame& lastFrame)
-{
-#ifndef NDEBUG
-    ++m_scopeDepth;
-#endif
-
-    lastFrame = m_frame;
-}
-
-
-
-inline void HandleStack::zapTo(Frame& lastFrame)
-{
-#ifdef NDEBUG
-    UNUSED_PARAM(lastFrame);
-#else
-    const Vector<HandleSlot>& blocks = m_blockStack.blocks();
-    
-    if (lastFrame.m_end != m_frame.m_end) { // Zapping to a frame in a different block.
-        int i = blocks.size() - 1;
-        for ( ; blocks[i] + m_blockStack.blockLength != lastFrame.m_end; --i) {
-            for (int j = m_blockStack.blockLength - 1; j >= 0; --j)
-                blocks[i][j] = JSValue();
-        }
-        
-        for (HandleSlot it = blocks[i] + m_blockStack.blockLength - 1; it != lastFrame.m_next - 1; --it)
-            *it = JSValue();
-        
-        return;
-    }
-    
-    for (HandleSlot it = m_frame.m_next - 1; it != lastFrame.m_next - 1; --it)
-        *it = JSValue();
-#endif
-}
-
-inline void HandleStack::leaveScope(Frame& lastFrame)
-{
-#ifndef NDEBUG
-    --m_scopeDepth;
-#endif
-
-    zapTo(lastFrame);
-
-    if (lastFrame.m_end != m_frame.m_end) // Popping to a frame in a different block.
-        m_blockStack.shrink(lastFrame.m_end);
-
-    m_frame = lastFrame;
-}
-
-inline HandleSlot HandleStack::push()
-{
-    ASSERT(m_scopeDepth); // Creating a Local outside of a LocalScope is a memory leak.
-    if (m_frame.m_next == m_frame.m_end)
-        grow();
-    return m_frame.m_next++;
-}
-
-} // namespace JSC
index 4ea898e..89273a7 100644 (file)
@@ -2665,7 +2665,6 @@ void Heap::addCoreConstraints()
         "Sh", "Strong Handles",
         [this] (SlotVisitor& slotVisitor) {
             m_handleSet.visitStrongHandles(slotVisitor);
-            m_handleStack.visit(slotVisitor);
         },
         ConstraintVolatility::GreyedByExecution);
     
index bf92580..ac31cd4 100644 (file)
@@ -30,7 +30,6 @@
 #include "GCIncomingRefCountedSet.h"
 #include "GCRequest.h"
 #include "HandleSet.h"
-#include "HandleStack.h"
 #include "HeapFinalizerCallback.h"
 #include "HeapObserver.h"
 #include "ListableHandler.h"
@@ -238,7 +237,6 @@ public:
     template<typename Functor> void forEachCodeBlockIgnoringJITPlans(const AbstractLocker& codeBlockSetLocker, const Functor&);
 
     HandleSet* handleSet() { return &m_handleSet; }
-    HandleStack* handleStack() { return &m_handleStack; }
 
     void willStartIterating();
     void didFinishIterating();
@@ -605,7 +603,6 @@ private:
     Lock m_parallelSlotVisitorLock;
     
     HandleSet m_handleSet;
-    HandleStack m_handleStack;
     std::unique_ptr<CodeBlockSet> m_codeBlocks;
     std::unique_ptr<JITStubRoutineSet> m_jitStubRoutines;
     FinalizerOwner m_finalizerOwner;
diff --git a/Source/JavaScriptCore/heap/Local.h b/Source/JavaScriptCore/heap/Local.h
deleted file mode 100644 (file)
index a0aadbe..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#pragma once
-
-#include "Handle.h"
-#include "VM.h"
-
-/*
-    A strongly referenced handle whose lifetime is temporary, limited to a given
-    LocalScope. Use Locals for local values on the stack. It is an error to
-    create a Local outside of any LocalScope.
-*/
-
-namespace JSC {
-
-template <typename T> class Local : public Handle<T> {
-    friend class LocalScope;
-    using Handle<T>::slot;
-
-public:
-    typedef typename Handle<T>::ExternalType ExternalType;
-
-    Local(VM&, ExternalType = ExternalType());
-    Local(VM&, Handle<T>);
-    Local(const Local<T>&); // Adopting constructor. Used to return a Local to a calling function.
-
-    Local& operator=(ExternalType);
-    Local& operator=(Handle<T>);
-
-private:
-    Local(HandleSlot, ExternalType); // Used by LocalScope::release() to move a Local to a containing scope.
-    void set(ExternalType);
-};
-
-template <typename T> inline Local<T>::Local(VM& vm, ExternalType value)
-    : Handle<T>(vm.heap.handleStack()->push())
-{
-    set(value);
-}
-
-template <typename T> inline Local<T>::Local(VM& vm, Handle<T> other)
-    : Handle<T>(vm.heap.handleStack()->push())
-{
-    set(other.get());
-}
-
-template <typename T> inline Local<T>::Local(const Local<T>& other)
-    : Handle<T>(other.slot())
-{
-    const_cast<Local<T>&>(other).setSlot(0); // Prevent accidental sharing.
-}
-
-template <typename T> inline Local<T>::Local(HandleSlot slot, ExternalType value)
-    : Handle<T>(slot, value)
-{
-}
-
-template <typename T> inline Local<T>& Local<T>::operator=(ExternalType value)
-{
-    set(value);
-    return *this;
-}
-
-template <typename T> inline Local<T>& Local<T>::operator=(Handle<T> other)
-{
-    set(other.get());
-    return *this;
-}
-
-template <typename T> inline void Local<T>::set(ExternalType externalType)
-{
-    ASSERT(slot());
-    *slot() = externalType;
-}
-
-
-template <typename T, unsigned inlineCapacity = 0> class LocalStack {
-    typedef typename Handle<T>::ExternalType ExternalType;
-public:
-    LocalStack(VM& vm)
-        : m_vm(vm)
-        , m_count(0)
-    {
-    }
-
-    ExternalType peek() const
-    {
-        ASSERT(m_count > 0);
-        return m_stack[m_count - 1].get();
-    }
-
-    ExternalType pop()
-    {
-        ASSERT(m_count > 0);
-        return m_stack[--m_count].get();
-    }
-
-    void push(ExternalType value)
-    {
-        if (m_count == m_stack.size())
-            m_stack.append(Local<T>(m_vm, value));
-        else
-            m_stack[m_count] = value;
-        m_count++;
-    }
-
-    bool isEmpty() const { return !m_count; }
-    unsigned size() const { return m_count; }
-
-private:
-    VM& m_vm;
-    Vector<Local<T>, inlineCapacity> m_stack;
-    unsigned m_count;
-};
-
-} // namespace JSC
-
-namespace WTF {
-
-template<typename T> struct VectorTraits<JSC::Local<T>> : SimpleClassVectorTraits {
-    static const bool needsDestruction = false;
-    static const bool canInitializeWithMemset = false;
-    static const bool canCompareWithMemcmp = false;
-};
-
-} // namespace WTF
diff --git a/Source/JavaScriptCore/heap/LocalScope.h b/Source/JavaScriptCore/heap/LocalScope.h
deleted file mode 100644 (file)
index f17f9f9..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#pragma once
-
-#include "HandleStack.h"
-#include "Local.h"
-
-namespace JSC {
-/*  
-    A LocalScope is a temporary scope in which Locals are allocated. When a
-    LocalScope goes out of scope, all the Locals created in it are destroyed.
-
-    LocalScope is similar in concept to NSAutoreleasePool.
-*/
-
-class VM;
-
-class LocalScope {
-public:
-    explicit LocalScope(VM&);
-    ~LocalScope();
-    
-    template <typename T> Local<T> release(Local<T>); // Destroys all other locals in the scope.
-
-private:
-    HandleStack* m_handleStack;
-    HandleStack::Frame m_lastFrame;
-};
-
-inline LocalScope::LocalScope(VM& vm)
-    : m_handleStack(vm.heap.handleStack())
-{
-    m_handleStack->enterScope(m_lastFrame);
-}
-
-inline LocalScope::~LocalScope()
-{
-    m_handleStack->leaveScope(m_lastFrame);
-}
-
-template <typename T> Local<T> LocalScope::release(Local<T> local)
-{
-    typename Local<T>::ExternalType ptr = local.get();
-
-    m_handleStack->leaveScope(m_lastFrame);
-    HandleSlot slot = m_handleStack->push();
-    m_handleStack->enterScope(m_lastFrame);
-
-    return Local<T>(slot, ptr);
-}
-
-} // namespace JSC
index dc5a5d6..ecdbd03 100644 (file)
@@ -33,8 +33,6 @@
 #include "JSArray.h"
 #include "JSGlobalObject.h"
 #include "LiteralParser.h"
-#include "Local.h"
-#include "LocalScope.h"
 #include "Lookup.h"
 #include "ObjectConstructor.h"
 #include "JSCInlines.h"
@@ -84,26 +82,25 @@ private:
 
 class Stringifier {
     WTF_MAKE_NONCOPYABLE(Stringifier);
+    WTF_FORBID_HEAP_ALLOCATION;
 public:
-    Stringifier(ExecState*, const Local<Unknown>& replacer, const Local<Unknown>& space);
-    Local<Unknown> stringify(Handle<Unknown>);
-
-    void visitAggregate(SlotVisitor&);
+    Stringifier(ExecState*, JSValue replacer, JSValue space);
+    JSValue stringify(JSValue);
 
 private:
     class Holder {
     public:
         enum RootHolderTag { RootHolder };
-        Holder(VM&, ExecState*, JSObject*);
-        Holder(RootHolderTag, VM&, JSObject*);
+        Holder(ExecState*, JSObject*);
+        Holder(RootHolderTag, JSObject*);
 
-        JSObject* object() const { return m_object.get(); }
+        JSObject* object() const { return m_object; }
         bool isArray() const { return m_isArray; }
 
         bool appendNextProperty(Stringifier&, StringBuilder&);
 
     private:
-        Local<JSObject> m_object;
+        JSObject* m_object;
         const bool m_isArray;
         const bool m_isJSArray;
         unsigned m_index;
@@ -125,13 +122,14 @@ private:
     void startNewLine(StringBuilder&) const;
 
     ExecState* const m_exec;
-    const Local<Unknown> m_replacer;
+    JSValue m_replacer;
     bool m_usingArrayReplacer;
     PropertyNameArray m_arrayReplacerPropertyNames;
     CallType m_replacerCallType;
     CallData m_replacerCallData;
     String m_gap;
 
+    MarkedArgumentBuffer m_objectStack;
     Vector<Holder, 16, UnsafeVectorOverflow> m_holderStack;
     String m_repeatedGap;
     String m_indent;
@@ -176,7 +174,7 @@ static inline String gap(ExecState* exec, JSValue space)
             count = 0;
         else
             count = static_cast<int>(spaceCount);
-        UChar spaces[maxGapLength];
+        char spaces[maxGapLength];
         for (int i = 0; i < count; ++i)
             spaces[i] = ' ';
         return String(spaces, count);
@@ -184,10 +182,9 @@ static inline String gap(ExecState* exec, JSValue space)
 
     // If the space value is a string, use it as the gap string, otherwise use no gap string.
     String spaces = space.getString(exec);
-    if (spaces.length() > maxGapLength) {
-        spaces = spaces.substringSharingImpl(0, maxGapLength);
-    }
-    return spaces;
+    if (spaces.length() <= maxGapLength)
+        return spaces;
+    return spaces.substringSharingImpl(0, maxGapLength);
 }
 
 // ------------------------------ PropertyNameForFunctionCall --------------------------------
@@ -220,7 +217,7 @@ JSValue PropertyNameForFunctionCall::value(ExecState* exec) const
 
 // ------------------------------ Stringifier --------------------------------
 
-Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const Local<Unknown>& space)
+Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
     : m_exec(exec)
     , m_replacer(replacer)
     , m_usingArrayReplacer(false)
@@ -230,16 +227,17 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    m_gap = gap(exec, space.get());
+    m_gap = gap(exec, space);
     if (UNLIKELY(scope.exception()))
         return;
 
     if (!m_replacer.isObject())
         return;
 
-    if (m_replacer.asObject()->inherits(vm, JSArray::info())) {
+    JSObject* replacerObject = asObject(m_replacer);
+    if (replacerObject->inherits(vm, JSArray::info())) {
         m_usingArrayReplacer = true;
-        Handle<JSObject> array = m_replacer.asObject();
+        JSArray* array = jsCast<JSArray*>(replacerObject);
         unsigned length = array->get(exec, vm.propertyNames->length).toUInt32(exec);
         if (UNLIKELY(scope.exception()))
             return;
@@ -259,28 +257,28 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const
         return;
     }
 
-    m_replacerCallType = m_replacer.asObject()->methodTable(vm)->getCallData(m_replacer.asObject().get(), m_replacerCallData);
+    m_replacerCallType = replacerObject->methodTable(vm)->getCallData(replacerObject, m_replacerCallData);
 }
 
-Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
+JSValue Stringifier::stringify(JSValue value)
 {
     VM& vm = m_exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* object = constructEmptyObject(m_exec);
-    RETURN_IF_EXCEPTION(scope, Local<Unknown>(vm, jsNull()));
+    RETURN_IF_EXCEPTION(scope, jsNull());
 
     PropertyNameForFunctionCall emptyPropertyName(vm.propertyNames->emptyIdentifier);
-    object->putDirect(vm, vm.propertyNames->emptyIdentifier, value.get());
+    object->putDirect(vm, vm.propertyNames->emptyIdentifier, value);
 
     StringBuilder result;
-    Holder root(Holder::RootHolder, vm, object);
-    auto stringifyResult = appendStringifiedValue(result, value.get(), root, emptyPropertyName);
+    Holder root(Holder::RootHolder, object);
+    auto stringifyResult = appendStringifiedValue(result, value, root, emptyPropertyName);
     EXCEPTION_ASSERT(!scope.exception() || (stringifyResult != StringifySucceeded));
     if (UNLIKELY(stringifyResult != StringifySucceeded))
-        return Local<Unknown>(vm, jsUndefined());
+        return jsUndefined();
 
     scope.release();
-    return Local<Unknown>(vm, jsString(m_exec, result.toString()));
+    return jsString(m_exec, result.toString());
 }
 
 ALWAYS_INLINE JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionCall& propertyName)
@@ -332,7 +330,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
         args.append(propertyName.value(m_exec));
         args.append(value);
         ASSERT(!args.hasOverflowed());
-        value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder.object(), args);
+        value = call(m_exec, m_replacer, m_replacerCallType, m_replacerCallData, holder.object(), args);
         RETURN_IF_EXCEPTION(scope, StringifyFailed);
     }
 
@@ -399,7 +397,8 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
     }
 
     bool holderStackWasEmpty = m_holderStack.isEmpty();
-    m_holderStack.append(Holder(vm, m_exec, object));
+    m_holderStack.append(Holder(m_exec, object));
+    m_objectStack.appendWithCrashOnOverflow(object);
     RETURN_IF_EXCEPTION(scope, StringifyFailed);
     if (!holderStackWasEmpty)
         return StringifySucceeded;
@@ -409,6 +408,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
             RETURN_IF_EXCEPTION(scope, StringifyFailed);
         RETURN_IF_EXCEPTION(scope, StringifyFailed);
         m_holderStack.removeLast();
+        m_objectStack.removeLast();
     } while (!m_holderStack.isEmpty());
     return StringifySucceeded;
 }
@@ -442,8 +442,8 @@ inline void Stringifier::startNewLine(StringBuilder& builder) const
     builder.append(m_indent);
 }
 
-inline Stringifier::Holder::Holder(VM& vm, ExecState* exec, JSObject* object)
-    : m_object(vm, object)
+inline Stringifier::Holder::Holder(ExecState* exec, JSObject* object)
+    : m_object(object)
     , m_isArray(JSC::isArray(exec, object))
     , m_isJSArray(m_isArray && isJSArray(object))
     , m_index(0)
@@ -453,8 +453,8 @@ inline Stringifier::Holder::Holder(VM& vm, ExecState* exec, JSObject* object)
 {
 }
 
-inline Stringifier::Holder::Holder(RootHolderTag, VM& vm, JSObject* object)
-    : m_object(vm, object)
+inline Stringifier::Holder::Holder(RootHolderTag, JSObject* object)
+    : m_object(object)
     , m_isArray(false)
     , m_isJSArray(false)
     , m_index(0)
@@ -476,7 +476,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
     if (!m_index) {
         if (m_isArray) {
             if (m_isJSArray)
-                m_size = asArray(m_object.get())->length();
+                m_size = asArray(m_object)->length();
             else {
                 JSValue value = m_object->get(exec, vm.propertyNames->length);
                 RETURN_IF_EXCEPTION(scope, false);
@@ -489,7 +489,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
                 m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data();
             else {
                 PropertyNameArray objectPropertyNames(&vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
-                m_object->methodTable(vm)->getOwnPropertyNames(m_object.get(), exec, objectPropertyNames, EnumerationMode());
+                m_object->methodTable(vm)->getOwnPropertyNames(m_object, exec, objectPropertyNames, EnumerationMode());
                 RETURN_IF_EXCEPTION(scope, false);
                 m_propertyNames = objectPropertyNames.releaseData();
             }
@@ -515,11 +515,11 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
     if (m_isArray) {
         // Get the value.
         JSValue value;
-        if (m_isJSArray && asArray(m_object.get())->canGetIndexQuickly(index))
-            value = asArray(m_object.get())->getIndexQuickly(index);
+        if (m_isJSArray && asArray(m_object)->canGetIndexQuickly(index))
+            value = asArray(m_object)->getIndexQuickly(index);
         else {
-            PropertySlot slot(m_object.get(), PropertySlot::InternalMethodType::Get);
-            if (m_object->methodTable(vm)->getOwnPropertySlotByIndex(m_object.get(), exec, index, slot))
+            PropertySlot slot(m_object, PropertySlot::InternalMethodType::Get);
+            if (m_object->methodTable(vm)->getOwnPropertySlotByIndex(m_object, exec, index, slot))
                 value = slot.getValue(exec, index);
             else
                 value = jsUndefined();
@@ -536,9 +536,9 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
         ASSERT(stringifyResult != StringifyFailedDueToUndefinedOrSymbolValue);
     } else {
         // Get the value.
-        PropertySlot slot(m_object.get(), PropertySlot::InternalMethodType::Get);
+        PropertySlot slot(m_object, PropertySlot::InternalMethodType::Get);
         Identifier& propertyName = m_propertyNames->propertyNameVector()[index];
-        if (!m_object->methodTable(vm)->getOwnPropertySlot(m_object.get(), exec, propertyName, slot))
+        if (!m_object->methodTable(vm)->getOwnPropertySlot(m_object, exec, propertyName, slot))
             return true;
         JSValue value = slot.getValue(exec, propertyName);
         RETURN_IF_EXCEPTION(scope, false);
@@ -596,10 +596,12 @@ const ClassInfo JSONObject::s_info = { "JSON", &JSNonFinalObject::s_info, &jsonT
 // ECMA 15.8
 
 class Walker {
+    WTF_MAKE_NONCOPYABLE(Walker);
+    WTF_FORBID_HEAP_ALLOCATION;
 public:
-    Walker(ExecState* exec, Handle<JSObject> function, CallType callType, CallData callData)
+    Walker(ExecState* exec, JSObject* function, CallType callType, CallData callData)
         : m_exec(exec)
-        , m_function(exec->vm(), function)
+        , m_function(function)
         , m_callType(callType)
         , m_callData(callData)
     {
@@ -612,13 +614,13 @@ private:
         args.append(property);
         args.append(unfiltered);
         ASSERT(!args.hasOverflowed());
-        return call(m_exec, m_function.get(), m_callType, m_callData, thisObj, args);
+        return call(m_exec, m_function, m_callType, m_callData, thisObj, args);
     }
 
     friend class Holder;
 
     ExecState* m_exec;
-    Local<JSObject> m_function;
+    JSObject* m_function;
     CallType m_callType;
     CallData m_callData;
 };
@@ -634,8 +636,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
 
     Vector<PropertyNameArray, 16, UnsafeVectorOverflow> propertyStack;
     Vector<uint32_t, 16, UnsafeVectorOverflow> indexStack;
-    LocalStack<JSObject, 16> objectStack(vm);
-    LocalStack<JSArray, 16> arrayStack(vm);
+    MarkedArgumentBuffer markedStack;
     Vector<unsigned, 16, UnsafeVectorOverflow> arrayLengthStack;
     
     Vector<WalkerState, 16, UnsafeVectorOverflow> stateStack;
@@ -649,23 +650,23 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
                 ASSERT(isJSArray(asObject(inValue)) || asObject(inValue)->inherits(vm, JSArray::info()));
-                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
+                if (markedStack.size() > maximumFilterRecursion)
                     return throwStackOverflowError(m_exec, scope);
 
                 JSArray* array = asArray(inValue);
-                arrayStack.push(array);
+                markedStack.appendWithCrashOnOverflow(array);
                 arrayLengthStack.append(array->length());
                 indexStack.append(0);
             }
             arrayStartVisitMember:
             FALLTHROUGH;
             case ArrayStartVisitMember: {
-                JSArray* array = arrayStack.peek();
+                JSArray* array = jsCast<JSArray*>(markedStack.last());
                 uint32_t index = indexStack.last();
                 unsigned arrayLength = arrayLengthStack.last();
                 if (index == arrayLength) {
                     outValue = array;
-                    arrayStack.pop();
+                    markedStack.removeLast();
                     arrayLengthStack.removeLast();
                     indexStack.removeLast();
                     break;
@@ -689,7 +690,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 FALLTHROUGH;
             }
             case ArrayEndVisitMember: {
-                JSArray* array = arrayStack.peek();
+                JSArray* array = jsCast<JSArray*>(markedStack.last());
                 JSValue filteredValue = callReviver(array, jsString(m_exec, String::number(indexStack.last())), outValue);
                 RETURN_IF_EXCEPTION(scope, { });
                 if (filteredValue.isUndefined())
@@ -704,11 +705,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             case ObjectStartState: {
                 ASSERT(inValue.isObject());
                 ASSERT(!isJSArray(asObject(inValue)) && !asObject(inValue)->inherits(vm, JSArray::info()));
-                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
+                if (markedStack.size() > maximumFilterRecursion)
                     return throwStackOverflowError(m_exec, scope);
 
                 JSObject* object = asObject(inValue);
-                objectStack.push(object);
+                markedStack.appendWithCrashOnOverflow(object);
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(&vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude));
                 object->methodTable(vm)->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
@@ -717,12 +718,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             objectStartVisitMember:
             FALLTHROUGH;
             case ObjectStartVisitMember: {
-                JSObject* object = objectStack.peek();
+                JSObject* object = jsCast<JSObject*>(markedStack.last());
                 uint32_t index = indexStack.last();
                 PropertyNameArray& properties = propertyStack.last();
                 if (index == properties.size()) {
                     outValue = object;
-                    objectStack.pop();
+                    markedStack.removeLast();
                     indexStack.removeLast();
                     propertyStack.removeLast();
                     break;
@@ -744,7 +745,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 FALLTHROUGH;
             }
             case ObjectEndVisitMember: {
-                JSObject* object = objectStack.peek();
+                JSObject* object = jsCast<JSObject*>(markedStack.last());
                 Identifier prop = propertyStack.last()[indexStack.last()];
                 PutPropertySlot slot(object);
                 JSValue filteredValue = callReviver(object, jsString(m_exec, prop.string()), outValue);
@@ -795,7 +796,6 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
     StringView view = viewWithString.view;
 
     JSValue unfiltered;
-    LocalScope localScope(vm);
     if (view.is8Bit()) {
         LiteralParser<LChar> jsonParser(exec, view.characters8(), view.length(), StrictJSON);
         unfiltered = jsonParser.tryLiteralParse();
@@ -823,7 +823,8 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
     if (callType == CallType::None)
         return JSValue::encode(unfiltered);
     scope.release();
-    return JSValue::encode(Walker(exec, Local<JSObject>(vm, asObject(function)), callType, callData).walk(unfiltered));
+    Walker walker(exec, asObject(function), callType, callData);
+    return JSValue::encode(walker.walk(unfiltered));
 }
 
 // ECMA-262 v5 15.12.3
@@ -834,21 +835,14 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec)
 
     if (!exec->argumentCount())
         return throwVMError(exec, scope, createError(exec, ASCIILiteral("No input to stringify")));
-    LocalScope localScope(vm);
-    Local<Unknown> value(vm, exec->uncheckedArgument(0));
-    Local<Unknown> replacer(vm, exec->argument(1));
-    Local<Unknown> space(vm, exec->argument(2));
-    Stringifier stringifier(exec, replacer, space);
+    Stringifier stringifier(exec, exec->argument(1), exec->argument(2));
     RETURN_IF_EXCEPTION(scope, { });
     scope.release();
-    JSValue result = stringifier.stringify(value).get();
-    return JSValue::encode(result);
+    return JSValue::encode(stringifier.stringify(exec->uncheckedArgument(0)));
 }
 
 JSValue JSONParse(ExecState* exec, const String& json)
 {
-    LocalScope scope(exec->vm());
-
     if (json.isNull())
         return JSValue();
 
@@ -865,10 +859,9 @@ String JSONStringify(ExecState* exec, JSValue value, unsigned indent)
 {
     VM& vm = exec->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
-    LocalScope scope(vm);
-    Stringifier stringifier(exec, Local<Unknown>(vm, jsNull()), Local<Unknown>(vm, jsNumber(indent)));
+    Stringifier stringifier(exec, jsNull(), jsNumber(indent));
     RETURN_IF_EXCEPTION(throwScope, { });
-    Local<Unknown> result = stringifier.stringify(Local<Unknown>(vm, value));
+    JSValue result = stringifier.stringify(value);
     if (UNLIKELY(throwScope.exception()) || result.isUndefinedOrNull())
         return String();
     return result.getString(exec);