summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/bytecompiler
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /JavaScriptCore/bytecompiler
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2
Merge in WebKit r47029.
Diffstat (limited to 'JavaScriptCore/bytecompiler')
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.cpp109
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.h32
-rw-r--r--JavaScriptCore/bytecompiler/RegisterID.h2
-rw-r--r--JavaScriptCore/bytecompiler/SegmentedVector.h170
4 files changed, 48 insertions, 265 deletions
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 21a3016..59537b6 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -196,17 +196,10 @@ bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, R
return result.second;
}
-void BytecodeGenerator::allocateConstants(size_t count)
+void BytecodeGenerator::preserveLastVar()
{
- m_codeBlock->m_numConstants = count;
- if (!count)
- return;
-
- m_nextConstantIndex = m_calleeRegisters.size();
-
- for (size_t i = 0; i < count; ++i)
- newRegister();
- m_lastConstant = &m_calleeRegisters.last();
+ if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
+ m_lastVar = &m_calleeRegisters.last();
}
BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
@@ -222,6 +215,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
, m_baseScopeDepth(0)
, m_codeType(GlobalCode)
, m_nextGlobalIndex(-1)
+ , m_nextConstantOffset(0)
, m_globalConstantIndex(0)
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
@@ -272,7 +266,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
if (!globalObject->hasProperty(exec, varStack[i].first))
newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
- allocateConstants(programNode->neededConstants());
+ preserveLastVar();
for (size_t i = 0; i < newVars.size(); ++i)
emitLoad(newVars[i], jsUndefined());
@@ -290,7 +284,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
}
- allocateConstants(programNode->neededConstants());
+ preserveLastVar();
}
}
@@ -305,6 +299,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
, m_dynamicScopeDepth(0)
, m_baseScopeDepth(0)
, m_codeType(FunctionCode)
+ , m_nextConstantOffset(0)
, m_globalConstantIndex(0)
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
@@ -332,7 +327,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
} else
emitOpcode(op_enter);
- if (usesArguments) {
+ if (usesArguments) {
emitOpcode(op_init_arguments);
// The debugger currently retrieves the arguments object from an activation rather than pulling
@@ -372,7 +367,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
for (size_t i = 0; i < parameterCount; ++i)
addParameter(parameters[i]);
- allocateConstants(functionBody->neededConstants());
+ preserveLastVar();
}
BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
@@ -387,6 +382,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
, m_dynamicScopeDepth(0)
, m_baseScopeDepth(codeBlock->baseScopeDepth())
, m_codeType(EvalCode)
+ , m_nextConstantOffset(0)
, m_globalConstantIndex(0)
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
@@ -401,7 +397,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
codeBlock->setGlobalData(m_globalData);
m_codeBlock->m_numParameters = 1; // Allocate space for "this"
- allocateConstants(evalNode->neededConstants());
+ preserveLastVar();
}
RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
@@ -525,7 +521,7 @@ PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, c
m_labelScopes.removeLast();
// Allocate new label scope.
- LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : 0); // Only loops have continue targets.
+ LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
m_labelScopes.append(scope);
return &m_labelScopes.last();
}
@@ -791,34 +787,19 @@ unsigned BytecodeGenerator::addConstant(const Identifier& ident)
return result.first->second;
}
-RegisterID* BytecodeGenerator::addConstant(JSValue v)
+RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
{
- pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantIndex);
- if (result.second) {
- RegisterID& constant = m_calleeRegisters[m_nextConstantIndex];
-
- ++m_nextConstantIndex;
+ int index = m_nextConstantOffset;
+ pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
+ if (result.second) {
+ m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
+ ++m_nextConstantOffset;
m_codeBlock->addConstantRegister(JSValue(v));
- return &constant;
- }
-
- return &registerFor(result.first->second);
-}
-
-unsigned BytecodeGenerator::addUnexpectedConstant(JSValue v)
-{
- return m_codeBlock->addUnexpectedConstant(v);
-}
+ } else
+ index = result.first->second;
-RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst, JSObject* globalObject)
-{
- if (!m_globalConstantIndex)
- m_globalConstantIndex = m_codeBlock->addUnexpectedConstant(globalObject);
- emitOpcode(op_unexpected_load);
- instructions().append(dst->index());
- instructions().append(m_globalConstantIndex);
- return dst;
+ return &m_constantPoolRegisters[index];
}
unsigned BytecodeGenerator::addRegExp(RegExp* r)
@@ -880,9 +861,8 @@ RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst,
instructions().append(src2->index());
if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
- opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub) {
+ opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
instructions().append(types.toInt());
- }
return dst;
}
@@ -898,8 +878,8 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst
if (src1->index() == dstIndex
&& src1->isTemporary()
&& m_codeBlock->isConstantRegisterIndex(src2->index())
- && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue().isString()) {
- const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue())->value();
+ && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
+ const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->value();
if (value == "undefined") {
rewindUnaryOp();
emitOpcode(op_is_undefined);
@@ -979,28 +959,12 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& ident
RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
{
- RegisterID* constantID = addConstant(v);
+ RegisterID* constantID = addConstantValue(v);
if (dst)
return emitMove(dst, constantID);
return constantID;
}
-RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b)
-{
- emitOpcode(op_unexpected_load);
- instructions().append(dst->index());
- instructions().append(addUnexpectedConstant(jsBoolean(b)));
- return dst;
-}
-
-RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d)
-{
- emitOpcode(op_unexpected_load);
- instructions().append(dst->index());
- instructions().append(addUnexpectedConstant(jsNumber(globalData(), d)));
- return dst;
-}
-
bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject)
{
// Cases where we cannot statically optimize the lookup.
@@ -1169,7 +1133,7 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier
}
// Global object is the base
- return emitLoadGlobalObject(dst, globalObject);
+ return emitLoad(dst, JSValue(globalObject));
}
RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
@@ -1196,7 +1160,7 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
}
// Global object is the base
- emitLoadGlobalObject(baseDst, globalObject);
+ emitLoad(baseDst, JSValue(globalObject));
if (index != missingSymbolMarker() && !forceGlobalResolve) {
// Directly index the property lookup across multiple scopes.
@@ -1218,15 +1182,6 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
return baseDst;
}
-RegisterID* BytecodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
-{
- emitOpcode(op_resolve_func);
- instructions().append(baseDst->index());
- instructions().append(funcDst->index());
- instructions().append(addConstant(property));
- return baseDst;
-}
-
void BytecodeGenerator::emitMethodCheck()
{
emitOpcode(op_method_check);
@@ -1235,7 +1190,7 @@ void BytecodeGenerator::emitMethodCheck()
RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
#if ENABLE(JIT)
- m_codeBlock->addStructureStubInfo(StructureStubInfo(op_get_by_id));
+ m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
#else
m_codeBlock->addPropertyAccessInstruction(instructions().size());
#endif
@@ -1254,7 +1209,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
{
#if ENABLE(JIT)
- m_codeBlock->addStructureStubInfo(StructureStubInfo(op_put_by_id));
+ m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
#else
m_codeBlock->addPropertyAccessInstruction(instructions().size());
#endif
@@ -1815,7 +1770,7 @@ RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID*
RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
{
#if ENABLE(JIT)
- HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, MacroAssembler::CodeLocationLabel() };
+ HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
#else
HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
#endif
@@ -1831,7 +1786,7 @@ RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSV
emitOpcode(op_new_error);
instructions().append(dst->index());
instructions().append(static_cast<int>(type));
- instructions().append(addUnexpectedConstant(message));
+ instructions().append(addConstantValue(message)->index());
return dst;
}
@@ -1840,6 +1795,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst,
emitOpcode(op_jsr);
instructions().append(retAddrDst->index());
instructions().append(finally->offsetFrom(instructions().size()));
+ emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
return finally;
}
@@ -1893,7 +1849,6 @@ static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t
ASSERT(node->isNumber());
double value = static_cast<NumberNode*>(node)->value();
int32_t key = static_cast<int32_t>(value);
- ASSERT(JSValue::makeInt32Fast(key) && (JSValue::makeInt32Fast(key).getInt32Fast() == value));
ASSERT(key == value);
ASSERT(key >= min);
ASSERT(key <= max);
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 6813d69..c273597 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -37,11 +37,12 @@
#include "LabelScope.h"
#include "Interpreter.h"
#include "RegisterID.h"
-#include "SegmentedVector.h"
#include "SymbolTable.h"
#include "Debugger.h"
#include "Nodes.h"
+#include <wtf/FastAllocBase.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/SegmentedVector.h>
#include <wtf/Vector.h>
namespace JSC {
@@ -60,7 +61,7 @@ namespace JSC {
FinallyContext finallyContext;
};
- class BytecodeGenerator {
+ class BytecodeGenerator : public WTF::FastAllocBase {
public:
typedef DeclarationStacks::VarStack VarStack;
typedef DeclarationStacks::FunctionStack FunctionStack;
@@ -244,9 +245,6 @@ namespace JSC {
RegisterID* emitLoad(RegisterID* dst, double);
RegisterID* emitLoad(RegisterID* dst, const Identifier&);
RegisterID* emitLoad(RegisterID* dst, JSValue);
- RegisterID* emitUnexpectedLoad(RegisterID* dst, bool);
- RegisterID* emitUnexpectedLoad(RegisterID* dst, double);
- RegisterID* emitLoadGlobalObject(RegisterID* dst, JSObject* globalObject);
RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
@@ -278,7 +276,6 @@ namespace JSC {
RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
- RegisterID* emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property);
void emitMethodCheck();
@@ -357,7 +354,7 @@ namespace JSC {
PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
- typedef HashMap<EncodedJSValue, unsigned, PtrHash<EncodedJSValue>, JSValueHashTraits> JSValueMap;
+ typedef HashMap<EncodedJSValue, unsigned, EncodedJSValueHash, EncodedJSValueHashTraits> JSValueMap;
struct IdentifierMapIndexHashTraits {
typedef int TraitType;
@@ -398,7 +395,7 @@ namespace JSC {
RegisterID* addParameter(const Identifier&);
- void allocateConstants(size_t);
+ void preserveLastVar();
RegisterID& registerFor(int index)
{
@@ -419,8 +416,7 @@ namespace JSC {
unsigned addConstant(FuncDeclNode*);
unsigned addConstant(FuncExprNode*);
unsigned addConstant(const Identifier&);
- RegisterID* addConstant(JSValue);
- unsigned addUnexpectedConstant(JSValue);
+ RegisterID* addConstantValue(JSValue);
unsigned addRegExp(RegExp*);
Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
@@ -449,12 +445,13 @@ namespace JSC {
RegisterID m_thisRegister;
RegisterID m_argumentsRegister;
int m_activationRegisterIndex;
- SegmentedVector<RegisterID, 32> m_calleeRegisters;
- SegmentedVector<RegisterID, 32> m_parameters;
- SegmentedVector<RegisterID, 32> m_globals;
- SegmentedVector<Label, 32> m_labels;
- SegmentedVector<LabelScope, 8> m_labelScopes;
- RefPtr<RegisterID> m_lastConstant;
+ WTF::SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
+ WTF::SegmentedVector<RegisterID, 32> m_calleeRegisters;
+ WTF::SegmentedVector<RegisterID, 32> m_parameters;
+ WTF::SegmentedVector<RegisterID, 32> m_globals;
+ WTF::SegmentedVector<Label, 32> m_labels;
+ WTF::SegmentedVector<LabelScope, 8> m_labelScopes;
+ RefPtr<RegisterID> m_lastVar;
int m_finallyDepth;
int m_dynamicScopeDepth;
int m_baseScopeDepth;
@@ -465,7 +462,8 @@ namespace JSC {
int m_nextGlobalIndex;
int m_nextParameterIndex;
- int m_nextConstantIndex;
+ int m_firstConstantIndex;
+ int m_nextConstantOffset;
unsigned m_globalConstantIndex;
int m_globalVarStorageOffset;
diff --git a/JavaScriptCore/bytecompiler/RegisterID.h b/JavaScriptCore/bytecompiler/RegisterID.h
index 0223c2a..3532ad8 100644
--- a/JavaScriptCore/bytecompiler/RegisterID.h
+++ b/JavaScriptCore/bytecompiler/RegisterID.h
@@ -35,7 +35,7 @@
namespace JSC {
- class RegisterID : Noncopyable {
+ class RegisterID : public Noncopyable {
public:
RegisterID()
: m_refCount(0)
diff --git a/JavaScriptCore/bytecompiler/SegmentedVector.h b/JavaScriptCore/bytecompiler/SegmentedVector.h
deleted file mode 100644
index bbab04f..0000000
--- a/JavaScriptCore/bytecompiler/SegmentedVector.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.
- */
-
-#ifndef SegmentedVector_h
-#define SegmentedVector_h
-
-#include <wtf/Vector.h>
-
-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()
- : m_size(0)
- {
- m_segments.append(&m_inlineSegment);
- }
-
- ~SegmentedVector()
- {
- deleteAllSegments();
- }
-
- size_t size() const { return m_size; }
-
- T& at(size_t index)
- {
- if (index < SegmentSize)
- return m_inlineSegment[index];
- return segmentFor(index)->at(subscriptFor(index));
- }
-
- T& operator[](size_t index)
- {
- return at(index);
- }
-
- T& last()
- {
- return at(size() - 1);
- }
-
- template <typename U> void append(const U& value)
- {
- ++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);
- }
-
- void removeLast()
- {
- if (m_size <= SegmentSize)
- m_inlineSegment.removeLast();
- else
- segmentFor(m_size - 1)->removeLast();
- --m_size;
- }
-
- void grow(size_t size)
- {
- ASSERT(size > m_size);
- ensureSegmentsFor(size);
- m_size = size;
- }
-
- void clear()
- {
- deleteAllSegments();
- m_segments.resize(1);
- m_inlineSegment.clear();
- m_size = 0;
- }
-
- private:
- typedef Vector<T, SegmentSize> Segment;
-
- void deleteAllSegments()
- {
- // 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];
- }
-
- bool segmentExistsFor(size_t index)
- {
- 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);
- }
-
- 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);
- }
-
- size_t m_size;
- Segment m_inlineSegment;
- Vector<Segment*, 32> m_segments;
- };
-
-} // namespace JSC
-
-#endif // SegmentedVector_h