diff options
Diffstat (limited to 'JavaScriptCore')
-rw-r--r-- | JavaScriptCore/VM/CodeGenerator.cpp | 4 | ||||
-rw-r--r-- | JavaScriptCore/VM/Machine.h | 13 | ||||
-rw-r--r-- | JavaScriptCore/VM/SegmentedVector.h | 174 | ||||
-rw-r--r-- | JavaScriptCore/kjs/config.h | 1 |
4 files changed, 102 insertions, 90 deletions
diff --git a/JavaScriptCore/VM/CodeGenerator.cpp b/JavaScriptCore/VM/CodeGenerator.cpp index 2cbf59f..3bfea93 100644 --- a/JavaScriptCore/VM/CodeGenerator.cpp +++ b/JavaScriptCore/VM/CodeGenerator.cpp @@ -226,7 +226,7 @@ CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->numParameters - registerFile->size(); // Add previously defined symbols to bookkeeping. - m_globals.resize(symbolTable->size()); + m_globals.grow(symbolTable->size()); SymbolTable::iterator end = symbolTable->end(); for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it) registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset); @@ -322,7 +322,7 @@ CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* deb const Identifier* parameters = functionBody->parameters(); size_t parameterCount = functionBody->parameterCount(); m_nextParameter = -RegisterFile::CallFrameHeaderSize - parameterCount - 1; - m_parameters.resize(1 + parameterCount); // reserve space for "this" + m_parameters.grow(1 + parameterCount); // reserve space for "this" // Add "this" as a parameter m_thisRegister.setIndex(m_nextParameter); diff --git a/JavaScriptCore/VM/Machine.h b/JavaScriptCore/VM/Machine.h index 9ae4d25..6cb8aaa 100644 --- a/JavaScriptCore/VM/Machine.h +++ b/JavaScriptCore/VM/Machine.h @@ -36,6 +36,10 @@ #include "RegisterFile.h" #include <wtf/HashMap.h> +#ifdef ANDROID_INSTRUMENT +#include "TimeCounter.h" +#endif + namespace JSC { class CodeBlock; @@ -145,7 +149,10 @@ namespace JSC { { if (!m_timeoutCheckCount) resetTimeoutCheck(); - +#ifdef ANDROID_INSTRUMENT + if (!m_timeoutCheckCount) + android::TimeCounter::start(android::TimeCounter::JavaScriptTimeCounter); +#endif ++m_timeoutCheckCount; } @@ -153,6 +160,10 @@ namespace JSC { { ASSERT(m_timeoutCheckCount); --m_timeoutCheckCount; +#ifdef ANDROID_INSTRUMENT + if (!m_timeoutCheckCount) + android::TimeCounter::record(android::TimeCounter::JavaScriptTimeCounter, __FUNCTION__); +#endif } inline void initTimeout() diff --git a/JavaScriptCore/VM/SegmentedVector.h b/JavaScriptCore/VM/SegmentedVector.h index 36ffee0..bbab04f 100644 --- a/JavaScriptCore/VM/SegmentedVector.h +++ b/JavaScriptCore/VM/SegmentedVector.h @@ -33,6 +33,9 @@ namespace JSC { + // SegmentedVector is just like Vector, but it doesn't move the values + // stored in its buffer when it grows. Therefore, it is safe to keep + // pointers into a SegmentedVector. template <typename T, size_t SegmentSize> class SegmentedVector { public: SegmentedVector() @@ -43,121 +46,120 @@ namespace JSC { ~SegmentedVector() { - for (size_t i = 1; i < m_segments.size(); i++) - delete m_segments[i]; + deleteAllSegments(); } - T& last() + size_t size() const { return m_size; } + + T& at(size_t index) { - ASSERT(m_size); - return m_segments.last()->last(); + if (index < SegmentSize) + return m_inlineSegment[index]; + return segmentFor(index)->at(subscriptFor(index)); } - template <typename U> void append(const U& value) + T& operator[](size_t index) { - if (!(m_size % SegmentSize) && m_size) - m_segments.append(new Segment); - m_segments.last()->uncheckedAppend(value); - m_size++; + return at(index); } - void removeLast() + T& last() + { + return at(size() - 1); + } + + template <typename U> void append(const U& value) { - ASSERT(m_size); - m_size--; - m_segments.last()->removeLast(); - if (!(m_size % SegmentSize) && m_size >= SegmentSize) { - delete m_segments.last(); - m_segments.removeLast(); + ++m_size; + + if (m_size <= SegmentSize) { + m_inlineSegment.uncheckedAppend(value); + return; } + + if (!segmentExistsFor(m_size - 1)) + m_segments.append(new Segment); + segmentFor(m_size - 1)->uncheckedAppend(value); } - size_t size() const + void removeLast() { - return m_size; + if (m_size <= SegmentSize) + m_inlineSegment.removeLast(); + else + segmentFor(m_size - 1)->removeLast(); + --m_size; } - T& operator[](size_t index) + void grow(size_t size) { - ASSERT(index < m_size); - if (index < SegmentSize) - return m_inlineSegment[index]; - return m_segments[index / SegmentSize]->at(index % SegmentSize); + ASSERT(size > m_size); + ensureSegmentsFor(size); + m_size = size; } - void resize(size_t size) + void clear() { - if (size < m_size) - shrink(size); - else if (size > m_size) - grow(size); - ASSERT(size == m_size); + deleteAllSegments(); + m_segments.resize(1); + m_inlineSegment.clear(); + m_size = 0; } private: - void shrink(size_t size) + typedef Vector<T, SegmentSize> Segment; + + void deleteAllSegments() { - ASSERT(size < m_size); - size_t numSegments = size / SegmentSize; - size_t extra = size % SegmentSize; - if (extra) - numSegments++; - if (!numSegments) { - for (size_t i = 1; i < m_segments.size(); i++) - delete m_segments[i]; - m_segments.resize(1); - m_inlineSegment.resize(0); - return; - } - - for (size_t i = numSegments; i < m_segments.size(); i++) + // Skip the first segment, because it's our inline segment, which was + // not created by new. + for (size_t i = 1; i < m_segments.size(); i++) delete m_segments[i]; - - m_segments.resize(numSegments); - if (extra) - m_segments.last()->resize(extra); - m_size = size; } - - void grow(size_t size) + + bool segmentExistsFor(size_t index) { - ASSERT(size > m_size); - if (size <= SegmentSize) { - m_inlineSegment.resize(size); - m_size = size; - return; - } - - size_t numSegments = size / SegmentSize; - size_t extra = size % SegmentSize; - if (extra) - numSegments++; - size_t oldSize = m_segments.size(); - - if (numSegments == oldSize) { - m_segments.last()->resize(extra); - m_size = size; - return; - } - - m_segments.last()->resize(SegmentSize); - - m_segments.resize(numSegments); - - ASSERT(oldSize < m_segments.size()); - for (size_t i = oldSize; i < (numSegments - 1); i++) { - Segment* segment = new Segment; - segment->resize(SegmentSize); - m_segments[i] = segment; - } + return index / SegmentSize < m_segments.size(); + } + + Segment* segmentFor(size_t index) + { + return m_segments[index / SegmentSize]; + } + + size_t subscriptFor(size_t index) + { + return index % SegmentSize; + } + + void ensureSegmentsFor(size_t size) + { + size_t segmentCount = m_size / SegmentSize; + if (m_size % SegmentSize) + ++segmentCount; + segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment. + + size_t neededSegmentCount = size / SegmentSize; + if (size % SegmentSize) + ++neededSegmentCount; + + // Fill up to N - 1 segments. + size_t end = neededSegmentCount - 1; + for (size_t i = segmentCount - 1; i < end; ++i) + ensureSegment(i, SegmentSize); + + // Grow segment N to accomodate the remainder. + ensureSegment(end, subscriptFor(size - 1) + 1); + } - Segment* segment = new Segment; - segment->resize(extra ? extra : SegmentSize); - m_segments[numSegments - 1] = segment; - m_size = size; + void ensureSegment(size_t segmentIndex, size_t size) + { + ASSERT(segmentIndex <= m_segments.size()); + if (segmentIndex == m_segments.size()) + m_segments.append(new Segment); + m_segments[segmentIndex]->grow(size); } - typedef Vector<T, SegmentSize> Segment; size_t m_size; Segment m_inlineSegment; Vector<Segment*, 32> m_segments; diff --git a/JavaScriptCore/kjs/config.h b/JavaScriptCore/kjs/config.h index 80a3798..53bc0a9 100644 --- a/JavaScriptCore/kjs/config.h +++ b/JavaScriptCore/kjs/config.h @@ -28,7 +28,6 @@ #if PLATFORM(ANDROID) #define ANDROID_MOBILE // change can be merged back to WebKit.org for MOBILE -//#define ANDROID_INSTRUMENT #endif #if PLATFORM(WIN_OS) |