X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/runtime/ArgList.h?ds=sidebyside diff --git a/runtime/ArgList.h b/runtime/ArgList.h index a1763e0..9aafc90 100644 --- a/runtime/ArgList.h +++ b/runtime/ArgList.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008 Apple Computer, Inc. + * Copyright (C) 2003, 2007, 2008, 2009 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 @@ -22,139 +22,162 @@ #ifndef ArgList_h #define ArgList_h -#include "JSImmediate.h" +#include "CallFrame.h" #include "Register.h" - #include -#include #include namespace JSC { - - class ArgList : Noncopyable { - private: - static const unsigned inlineCapacity = 8; - typedef Vector VectorType; - typedef HashSet ListSet; - - public: - typedef VectorType::iterator iterator; - typedef VectorType::const_iterator const_iterator; - - // Constructor for a read-write list, to which you may append values. - // FIXME: Remove all clients of this API, then remove this API. - ArgList() - : m_markSet(0) -#ifndef NDEBUG - , m_isReadOnly(false) -#endif - { - m_buffer = m_vector.data(); - m_size = 0; - } - - // Constructor for a read-only list whose data has already been allocated elsewhere. - ArgList(Register* buffer, size_t size) - : m_buffer(buffer) - , m_size(size) - , m_markSet(0) -#ifndef NDEBUG - , m_isReadOnly(true) -#endif - { - } - - void initialize(Register* buffer, size_t size) - { - ASSERT(!m_markSet); - ASSERT(isEmpty()); - - m_buffer = buffer; - m_size = size; -#ifndef NDEBUG - m_isReadOnly = true; -#endif - } - - ~ArgList() - { - if (m_markSet) - m_markSet->remove(this); - } - - size_t size() const { return m_size; } - bool isEmpty() const { return !m_size; } - - JSValuePtr at(ExecState* exec, size_t i) const - { - if (i < m_size) - return m_buffer[i].jsValue(exec); + +class SlotVisitor; + +class MarkedArgumentBuffer { + WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer); + friend class VM; + friend class ArgList; + +private: + static const size_t inlineCapacity = 8; + typedef HashSet ListSet; + +public: + // Constructor for a read-write list, to which you may append values. + // FIXME: Remove all clients of this API, then remove this API. + MarkedArgumentBuffer() + : m_size(0) + , m_capacity(inlineCapacity) + , m_buffer(m_inlineBuffer) + , m_markSet(0) + { + } + + ~MarkedArgumentBuffer() + { + if (m_markSet) + m_markSet->remove(this); + + if (EncodedJSValue* base = mallocBase()) + delete [] base; + } + + size_t size() const { return m_size; } + bool isEmpty() const { return !m_size; } + + JSValue at(int i) const + { + if (i >= m_size) return jsUndefined(); - } - - void clear() - { - m_vector.clear(); - m_buffer = 0; - m_size = 0; - } - - void append(JSValuePtr v) - { - ASSERT(!m_isReadOnly); - - if (m_size < inlineCapacity) { - m_vector.uncheckedAppend(v); - ++m_size; - } else { - // Putting this case all in one function measurably improves - // the performance of the fast "just append to inline buffer" case. - slowAppend(v); - ++m_size; - } - } - - void getSlice(int startIndex, ArgList& result) const; - - iterator begin() { return m_buffer; } - iterator end() { return m_buffer + m_size; } - - const_iterator begin() const { return m_buffer; } - const_iterator end() const { return m_buffer + m_size; } - - static void markLists(ListSet&); - - private: - void slowAppend(JSValuePtr); + + return JSValue::decode(slotFor(i)); + } + + void clear() + { + m_size = 0; + } + + void append(JSValue v) + { + if (m_size >= m_capacity) + return slowAppend(v); + + slotFor(m_size) = JSValue::encode(v); + ++m_size; + } + + void removeLast() + { + ASSERT(m_size); + m_size--; + } + + JSValue last() + { + ASSERT(m_size); + return JSValue::decode(slotFor(m_size - 1)); + } + + static void markLists(HeapRootVisitor&, ListSet&); + +private: + JS_EXPORT_PRIVATE void slowAppend(JSValue); + + EncodedJSValue& slotFor(int item) const + { + return m_buffer[item]; + } - Register* m_buffer; - size_t m_size; - - VectorType m_vector; - ListSet* m_markSet; -#ifndef NDEBUG - bool m_isReadOnly; -#endif - - private: - // Prohibits new / delete, which would break GC. - friend class JSGlobalData; + EncodedJSValue* mallocBase() + { + if (m_capacity == static_cast(inlineCapacity)) + return 0; + return &slotFor(0); + } - void* operator new(size_t size) - { - return fastMalloc(size); - } - void operator delete(void* p) - { - fastFree(p); - } - - void* operator new[](size_t); - void operator delete[](void*); - - void* operator new(size_t, void*); - void operator delete(void*, size_t); - }; + int m_size; + int m_capacity; + EncodedJSValue m_inlineBuffer[inlineCapacity]; + EncodedJSValue* m_buffer; + ListSet* m_markSet; + +private: + // Prohibits new / delete, which would break GC. + void* operator new(size_t size) + { + return fastMalloc(size); + } + void operator delete(void* p) + { + fastFree(p); + } + + void* operator new[](size_t); + void operator delete[](void*); + + void* operator new(size_t, void*); + void operator delete(void*, size_t); +}; + +class ArgList { + friend class Interpreter; + friend class JIT; +public: + ArgList() + : m_args(0) + , m_argCount(0) + { + } + + ArgList(ExecState* exec) + : m_args(reinterpret_cast(&exec[CallFrame::argumentOffset(0)])) + , m_argCount(exec->argumentCount()) + { + } + + ArgList(const MarkedArgumentBuffer& args) + : m_args(reinterpret_cast(args.m_buffer)) + , m_argCount(args.size()) + { + } + + JSValue at(int i) const + { + if (i >= m_argCount) + return jsUndefined(); + return m_args[i]; + } + + bool isEmpty() const { return !m_argCount; } + size_t size() const { return m_argCount; } + + JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const; + +private: + JSValue* data() const { return m_args; } + + JSValue* m_args; + int m_argCount; +}; } // namespace JSC