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
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 */,
heap/GCRequest.cpp
heap/GigacageAlignedMemoryAllocator.cpp
heap/HandleSet.cpp
-heap/HandleStack.cpp
heap/Heap.cpp
heap/HeapCell.cpp
heap/HeapCellType.cpp
+++ /dev/null
-/*
- * 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;
-}
-
-}
+++ /dev/null
-/*
- * 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
"Sh", "Strong Handles",
[this] (SlotVisitor& slotVisitor) {
m_handleSet.visitStrongHandles(slotVisitor);
- m_handleStack.visit(slotVisitor);
},
ConstraintVolatility::GreyedByExecution);
#include "GCIncomingRefCountedSet.h"
#include "GCRequest.h"
#include "HandleSet.h"
-#include "HandleStack.h"
#include "HeapFinalizerCallback.h"
#include "HeapObserver.h"
#include "ListableHandler.h"
template<typename Functor> void forEachCodeBlockIgnoringJITPlans(const AbstractLocker& codeBlockSetLocker, const Functor&);
HandleSet* handleSet() { return &m_handleSet; }
- HandleStack* handleStack() { return &m_handleStack; }
void willStartIterating();
void didFinishIterating();
Lock m_parallelSlotVisitorLock;
HandleSet m_handleSet;
- HandleStack m_handleStack;
std::unique_ptr<CodeBlockSet> m_codeBlocks;
std::unique_ptr<JITStubRoutineSet> m_jitStubRoutines;
FinalizerOwner m_finalizerOwner;
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
#include "JSArray.h"
#include "JSGlobalObject.h"
#include "LiteralParser.h"
-#include "Local.h"
-#include "LocalScope.h"
#include "Lookup.h"
#include "ObjectConstructor.h"
#include "JSCInlines.h"
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;
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;
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);
// 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 --------------------------------
// ------------------------------ 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)
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;
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)
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);
}
}
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;
RETURN_IF_EXCEPTION(scope, StringifyFailed);
RETURN_IF_EXCEPTION(scope, StringifyFailed);
m_holderStack.removeLast();
+ m_objectStack.removeLast();
} while (!m_holderStack.isEmpty());
return StringifySucceeded;
}
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)
{
}
-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)
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);
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();
}
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();
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);
// 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)
{
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;
};
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;
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;
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())
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());
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;
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);
StringView view = viewWithString.view;
JSValue unfiltered;
- LocalScope localScope(vm);
if (view.is8Bit()) {
LiteralParser<LChar> jsonParser(exec, view.characters8(), view.length(), StrictJSON);
unfiltered = jsonParser.tryLiteralParse();
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
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();
{
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);