X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..2656c66b5b30d5597e842a751c7f19ad6c2fe31a:/runtime/ArgList.h diff --git a/runtime/ArgList.h b/runtime/ArgList.h index 3c82561..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, 2009 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,207 +22,162 @@ #ifndef ArgList_h #define ArgList_h +#include "CallFrame.h" #include "Register.h" - #include -#include #include namespace JSC { - - class MarkedArgumentBuffer : 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. - MarkedArgumentBuffer() - : m_isUsingInlineBuffer(true) - , 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. - MarkedArgumentBuffer(Register* buffer, size_t size) - : m_buffer(buffer) - , m_size(size) - , m_isUsingInlineBuffer(true) - , 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 - } - - ~MarkedArgumentBuffer() - { - if (m_markSet) - m_markSet->remove(this); - } - - size_t size() const { return m_size; } - bool isEmpty() const { return !m_size; } - - JSValue at(size_t i) const - { - if (i < m_size) - return m_buffer[i].jsValue(); - return jsUndefined(); - } - - void clear() - { - m_vector.clear(); - m_buffer = 0; - m_size = 0; - } - - void append(JSValue v) - { - ASSERT(!m_isReadOnly); - - if (m_isUsingInlineBuffer && 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; - m_isUsingInlineBuffer = false; - } - } - - void removeLast() - { - ASSERT(m_size); - m_size--; - m_vector.removeLast(); - } - - JSValue last() - { - ASSERT(m_size); - return m_buffer[m_size - 1].jsValue(); - } - - 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&); +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(); - private: - void slowAppend(JSValue); + 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)); + } - Register* m_buffer; - size_t m_size; - bool m_isUsingInlineBuffer; - - VectorType m_vector; - ListSet* m_markSet; -#ifndef NDEBUG - bool m_isReadOnly; -#endif - - private: - // Prohibits new / delete, which would break GC. - friend class JSGlobalData; + static void markLists(HeapRootVisitor&, ListSet&); + +private: + JS_EXPORT_PRIVATE void slowAppend(JSValue); - 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 JIT; - public: - typedef JSValue* iterator; - typedef const JSValue* const_iterator; - - ArgList() - : m_args(0) - , m_argCount(0) - { - } + EncodedJSValue& slotFor(int item) const + { + return m_buffer[item]; + } - ArgList(JSValue* args, unsigned argCount) - : m_args(args) - , m_argCount(argCount) - { - } + EncodedJSValue* mallocBase() + { + if (m_capacity == static_cast(inlineCapacity)) + return 0; + return &slotFor(0); + } - ArgList(Register* args, int argCount) - : m_args(reinterpret_cast(args)) - , m_argCount(argCount) - { - ASSERT(argCount >= 0); - } - - ArgList(const MarkedArgumentBuffer& args) - : m_args(reinterpret_cast(const_cast(args.begin()))) - , m_argCount(args.size()) - { - } - - JSValue at(size_t idx) const - { - if (idx < m_argCount) - return m_args[idx]; + 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(); - } - - bool isEmpty() const { return !m_argCount; } + return m_args[i]; + } - size_t size() const { return m_argCount; } - - iterator begin() { return m_args; } - iterator end() { return m_args + m_argCount; } + bool isEmpty() const { return !m_argCount; } + size_t size() const { return m_argCount; } - const_iterator begin() const { return m_args; } - const_iterator end() const { return m_args + m_argCount; } - - void getSlice(int startIndex, ArgList& result) const; - private: - JSValue* m_args; - size_t 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