summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-16 16:25:10 +0100
committerBen Murdoch <benm@google.com>2011-05-23 18:54:14 +0100
commitab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb (patch)
treedb769fadd053248f85db67434a5b275224defef7 /Source/JavaScriptCore/runtime
parent52e2557aeb8477967e97fd24f20f8f407a10fa15 (diff)
downloadexternal_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.zip
external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.gz
external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.bz2
Merge WebKit at r76408: Initial merge by git.
Change-Id: I5b91decbd693ccbf5c1b8354b37cd68cc9a1ea53
Diffstat (limited to 'Source/JavaScriptCore/runtime')
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.h4
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.h5
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.cpp44
-rw-r--r--Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h4
-rw-r--r--Source/JavaScriptCore/runtime/CommonIdentifiers.h3
-rw-r--r--Source/JavaScriptCore/runtime/ErrorPrototype.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/Heap.cpp43
-rw-r--r--Source/JavaScriptCore/runtime/Heap.h7
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.cpp17
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h5
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp20
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h3
-rw-r--r--Source/JavaScriptCore/runtime/JSLock.h6
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/Lookup.h3
-rw-r--r--Source/JavaScriptCore/runtime/MachineStackMarker.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/MachineStackMarker.h13
-rw-r--r--Source/JavaScriptCore/runtime/MarkStack.h18
-rw-r--r--Source/JavaScriptCore/runtime/MarkedSpace.cpp30
-rw-r--r--Source/JavaScriptCore/runtime/MarkedSpace.h9
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.h10
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChain.h5
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.h3
-rw-r--r--Source/JavaScriptCore/runtime/StringRecursionChecker.cpp38
-rw-r--r--Source/JavaScriptCore/runtime/StringRecursionChecker.h79
-rw-r--r--Source/JavaScriptCore/runtime/SymbolTable.h1
-rw-r--r--Source/JavaScriptCore/runtime/WeakGCMap.h3
-rw-r--r--Source/JavaScriptCore/runtime/WeakGCPtr.h4
33 files changed, 292 insertions, 151 deletions
diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h
index cd563a2..57e3c20 100644
--- a/Source/JavaScriptCore/runtime/ArgList.h
+++ b/Source/JavaScriptCore/runtime/ArgList.h
@@ -25,14 +25,14 @@
#include "CallFrame.h"
#include "Register.h"
#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
namespace JSC {
class MarkStack;
- class MarkedArgumentBuffer : public Noncopyable {
+ class MarkedArgumentBuffer {
+ WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
private:
static const unsigned inlineCapacity = 8;
typedef Vector<Register, inlineCapacity> VectorType;
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h
index 715a2ac..fe900a2 100644
--- a/Source/JavaScriptCore/runtime/Arguments.h
+++ b/Source/JavaScriptCore/runtime/Arguments.h
@@ -33,7 +33,10 @@
namespace JSC {
- struct ArgumentsData : Noncopyable {
+ struct ArgumentsData {
+ WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED;
+ public:
+ ArgumentsData() { }
JSActivation* activation;
unsigned numParameters;
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
index ab0c3d4..7615ffc 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2003 Peter Kelly (pmk@post.com)
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
*
@@ -32,6 +32,7 @@
#include "Lookup.h"
#include "ObjectPrototype.h"
#include "Operations.h"
+#include "StringRecursionChecker.h"
#include <algorithm>
#include <wtf/Assertions.h>
#include <wtf/HashSet.h>
@@ -168,15 +169,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
return throwVMTypeError(exec);
JSArray* thisObj = asArray(thisValue);
- HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
- if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) {
- if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth)
- return throwVMError(exec, createStackOverflowError(exec));
- }
-
- bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
- if (alreadyVisited)
- return JSValue::encode(jsEmptyString(exec)); // return an empty string, avoiding infinite recursion.
+ StringRecursionChecker checker(exec, thisObj);
+ if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+ return earlyReturnValue;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
unsigned totalSize = length ? length - 1 : 0;
@@ -209,7 +204,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
if (exec->hadException())
break;
}
- arrayVisitedElements.remove(thisObj);
if (!totalSize)
return JSValue::encode(jsEmptyString(exec));
Vector<UChar> buffer;
@@ -234,15 +228,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
return throwVMTypeError(exec);
JSObject* thisObj = asArray(thisValue);
- HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
- if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) {
- if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth)
- return throwVMError(exec, createStackOverflowError(exec));
- }
-
- bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
- if (alreadyVisited)
- return JSValue::encode(jsEmptyString(exec)); // return an empty string, avoding infinite recursion.
+ StringRecursionChecker checker(exec, thisObj);
+ if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+ return earlyReturnValue;
JSStringBuilder strBuffer;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
@@ -264,7 +252,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
strBuffer.append(str);
}
}
- arrayVisitedElements.remove(thisObj);
+
return JSValue::encode(strBuffer.build(exec));
}
@@ -272,15 +260,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
- HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
- if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) {
- if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth)
- return throwVMError(exec, createStackOverflowError(exec));
- }
-
- bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
- if (alreadyVisited)
- return JSValue::encode(jsEmptyString(exec)); // return an empty string, avoding infinite recursion.
+ StringRecursionChecker checker(exec, thisObj);
+ if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+ return earlyReturnValue;
JSStringBuilder strBuffer;
@@ -335,7 +317,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
if (!element.isUndefinedOrNull())
strBuffer.append(element.toString(exec));
}
- arrayVisitedElements.remove(thisObj);
+
return JSValue::encode(strBuffer.build(exec));
}
diff --git a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
index 74089a5..db2d1d7 100644
--- a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
+++ b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
@@ -27,12 +27,12 @@
#ifndef BatchedTransitionOptimizer_h
#define BatchedTransitionOptimizer_h
-#include <wtf/Noncopyable.h>
#include "JSObject.h"
namespace JSC {
- class BatchedTransitionOptimizer : public Noncopyable {
+ class BatchedTransitionOptimizer {
+ WTF_MAKE_NONCOPYABLE(BatchedTransitionOptimizer);
public:
BatchedTransitionOptimizer(JSObject* object)
: m_object(object)
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
index 1e22b6a..6587a8f 100644
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -84,7 +84,8 @@
namespace JSC {
- class CommonIdentifiers : public Noncopyable {
+ class CommonIdentifiers {
+ WTF_MAKE_NONCOPYABLE(CommonIdentifiers); WTF_MAKE_FAST_ALLOCATED;
private:
CommonIdentifiers(JSGlobalData*);
friend class JSGlobalData;
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
index d18e7d8..d8fc829 100644
--- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -26,6 +26,7 @@
#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
#include "PrototypeFunction.h"
+#include "StringRecursionChecker.h"
#include "UString.h"
namespace JSC {
@@ -47,6 +48,11 @@ ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, No
EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+
+ StringRecursionChecker checker(exec, thisObj);
+ if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+ return earlyReturnValue;
+
JSValue name = thisObj->get(exec, exec->propertyNames().name);
JSValue message = thisObj->get(exec, exec->propertyNames().message);
diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp
index a224ee0..3966324 100644
--- a/Source/JavaScriptCore/runtime/Heap.cpp
+++ b/Source/JavaScriptCore/runtime/Heap.cpp
@@ -41,7 +41,8 @@ Heap::Heap(JSGlobalData* globalData)
, m_markListSet(0)
, m_activityCallback(DefaultGCActivityCallback::create(this))
, m_globalData(globalData)
- , m_machineStackMarker(&globalData->heap)
+ , m_machineStackMarker(this)
+ , m_markStack(globalData->jsArrayVPtr)
, m_extraCost(0)
{
(*m_activityCallback)();
@@ -93,12 +94,6 @@ void Heap::recordExtraCost(size_t cost)
if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.size() / 2) {
JAVASCRIPTCORE_GC_BEGIN();
- // If the last iteration through the heap deallocated blocks, we need
- // to clean up remaining garbage before marking. Otherwise, the conservative
- // marking mechanism might follow a pointer to unmapped memory.
- if (m_markedSpace.didShrink())
- m_markedSpace.sweep();
-
markRoots();
JAVASCRIPTCORE_GC_MARKED();
@@ -152,9 +147,9 @@ void* Heap::allocate(size_t s)
return result;
}
-void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
+void Heap::markConservatively(ConservativeSet& conservativeSet, void* start, void* end)
{
- m_markedSpace.markConservatively(markStack, start, end);
+ m_markedSpace.markConservatively(conservativeSet, start, end);
}
void Heap::updateWeakGCHandles()
@@ -212,10 +207,8 @@ bool Heap::unprotect(JSValue k)
void Heap::markProtectedObjects(MarkStack& markStack)
{
ProtectCountSet::iterator end = m_protectedValues.end();
- for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
+ for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
markStack.append(it->first);
- markStack.drain();
- }
}
void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
@@ -238,10 +231,10 @@ void Heap::markTempSortVectors(MarkStack& markStack)
Vector<ValueStringPair>* tempSortingVector = *it;
Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
- for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt)
+ for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
if (vectorIt->first)
markStack.append(vectorIt->first);
- markStack.drain();
+ }
}
}
@@ -260,20 +253,27 @@ void Heap::markRoots()
m_operationInProgress = Collection;
- MarkStack& markStack = m_globalData->markStack;
+ // We gather the conservative set before clearing mark bits, because
+ // conservative gathering uses the mark bits from our last mark pass to
+ // determine whether a reference is valid.
+ ConservativeSet conservativeSet;
+ m_machineStackMarker.markMachineStackConservatively(conservativeSet);
+ m_globalData->interpreter->registerFile().markCallFrames(conservativeSet, this);
// Reset mark bits.
m_markedSpace.clearMarkBits();
- // Mark stack roots.
- m_machineStackMarker.markMachineStackConservatively(markStack);
- m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
+ MarkStack& markStack = m_markStack;
+ conservativeSet.mark(markStack);
+ markStack.drain();
// Mark explicitly registered roots.
markProtectedObjects(markStack);
+ markStack.drain();
// Mark temporary vector for Array sorting
markTempSortVectors(markStack);
+ markStack.drain();
// Mark misc. other roots.
if (m_markListSet && m_markListSet->size())
@@ -282,6 +282,7 @@ void Heap::markRoots()
markStack.append(m_globalData->exception);
if (m_globalData->firstStringifierToMark)
JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
+ markStack.drain();
// Mark the small strings cache last, since it will clear itself if nothing
// else has marked it.
@@ -392,12 +393,6 @@ void Heap::collectAllGarbage()
ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
JAVASCRIPTCORE_GC_BEGIN();
- // If the last iteration through the heap deallocated blocks, we need
- // to clean up remaining garbage before marking. Otherwise, the conservative
- // marking mechanism might follow a pointer to unmapped memory.
- if (m_markedSpace.didShrink())
- m_markedSpace.sweep();
-
markRoots();
JAVASCRIPTCORE_GC_MARKED();
diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h
index 243bba3..f7f4deb 100644
--- a/Source/JavaScriptCore/runtime/Heap.h
+++ b/Source/JavaScriptCore/runtime/Heap.h
@@ -22,6 +22,7 @@
#ifndef Heap_h
#define Heap_h
+#include "MarkStack.h"
#include "MarkedSpace.h"
#include <wtf/Forward.h>
#include <wtf/HashSet.h>
@@ -45,7 +46,8 @@ namespace JSC {
enum OperationInProgress { NoOperation, Allocation, Collection };
- class Heap : public Noncopyable {
+ class Heap {
+ WTF_MAKE_NONCOPYABLE(Heap);
public:
void destroy();
@@ -86,7 +88,7 @@ namespace JSC {
WeakGCHandle* addWeakGCHandle(JSCell*);
- void markConservatively(MarkStack&, void* start, void* end);
+ void markConservatively(ConservativeSet&, void* start, void* end);
void pushTempSortVector(WTF::Vector<ValueStringPair>*);
void popTempSortVector(WTF::Vector<ValueStringPair>*);
@@ -130,6 +132,7 @@ namespace JSC {
JSGlobalData* m_globalData;
MachineStackMarker m_machineStackMarker;
+ MarkStack m_markStack;
size_t m_extraCost;
};
diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp
index 1147858..428403d 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.cpp
+++ b/Source/JavaScriptCore/runtime/JSActivation.cpp
@@ -53,6 +53,7 @@ void JSActivation::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
+ // No need to mark our registers if they're still in the RegisterFile.
Register* registerArray = d()->registerArray.get();
if (!registerArray)
return;
@@ -202,14 +203,16 @@ JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identi
JSActivation* activation = asActivation(slotBase);
CallFrame* callFrame = CallFrame::create(activation->d()->registers);
int argumentsRegister = activation->d()->functionExecutable->generatedBytecode().argumentsRegister();
- if (!callFrame->uncheckedR(argumentsRegister).jsValue()) {
- JSValue arguments = JSValue(new (callFrame) Arguments(callFrame));
- callFrame->uncheckedR(argumentsRegister) = arguments;
- callFrame->uncheckedR(unmodifiedArgumentsRegister(argumentsRegister)) = arguments;
- }
+ if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue())
+ return arguments;
+ int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
- ASSERT(callFrame->uncheckedR(argumentsRegister).jsValue().inherits(&Arguments::info));
- return callFrame->uncheckedR(argumentsRegister).jsValue();
+ JSValue arguments = JSValue(new (callFrame) Arguments(callFrame));
+ callFrame->uncheckedR(argumentsRegister) = arguments;
+ callFrame->uncheckedR(realArgumentsRegister) = arguments;
+
+ ASSERT(callFrame->uncheckedR(realArgumentsRegister).jsValue().inherits(&Arguments::info));
+ return callFrame->uncheckedR(realArgumentsRegister).jsValue();
}
// These two functions serve the purpose of isolating the common case from a
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index f20a9a4..3928c82 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -143,7 +143,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, head(0)
, dynamicGlobalObject(0)
, firstStringifierToMark(0)
- , markStack(jsArrayVPtr)
, cachedUTCOffset(NaN)
, maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
, m_regExpCache(new RegExpCache(this))
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index a24732a..31f41e9 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -35,7 +35,6 @@
#include "ExecutableAllocator.h"
#include "JITStubs.h"
#include "JSValue.h"
-#include "MarkStack.h"
#include "NumericStrings.h"
#include "SmallStrings.h"
#include "Terminator.h"
@@ -214,12 +213,10 @@ namespace JSC {
JSGlobalObject* head;
JSGlobalObject* dynamicGlobalObject;
- HashSet<JSObject*> arrayVisitedElements;
+ HashSet<JSObject*> stringRecursionCheckVisitedObjects;
Stringifier* firstStringifierToMark;
- MarkStack markStack;
-
double cachedUTCOffset;
DSTOffsetCache dstOffsetCache;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 408aea7..9b67dbb 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -349,10 +349,6 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
(*it)->markAggregate(markStack);
- RegisterFile& registerFile = globalData().interpreter->registerFile();
- if (registerFile.globalObject() == this)
- registerFile.markGlobals(markStack, &globalData().heap);
-
markIfNeeded(markStack, d()->regExpConstructor);
markIfNeeded(markStack, d()->errorConstructor);
markIfNeeded(markStack, d()->evalErrorConstructor);
@@ -397,12 +393,16 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
// No need to mark the other structures, because their prototypes are all
// guaranteed to be referenced elsewhere.
- Register* registerArray = d()->registerArray.get();
- if (!registerArray)
- return;
-
- size_t size = d()->registerArraySize;
- markStack.appendValues(reinterpret_cast<JSValue*>(registerArray), size);
+ if (d()->registerArray) {
+ // Outside the execution of global code, when our variables are torn off,
+ // we can mark the torn-off array.
+ markStack.appendValues(d()->registerArray.get(), d()->registerArraySize);
+ } else if (d()->registers) {
+ // During execution of global code, when our variables are in the register file,
+ // the symbol table tells us how many variables there are, and registers
+ // points to where they end, and the registers used for execution begin.
+ markStack.appendValues(d()->registers - symbolTable().size(), symbolTable().size());
+ }
}
ExecState* JSGlobalObject::globalExec()
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index a22b0aa..24bc2f8 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -465,7 +465,8 @@ namespace JSC {
return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
}
- class DynamicGlobalObjectScope : public Noncopyable {
+ class DynamicGlobalObjectScope {
+ WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
public:
DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject);
diff --git a/Source/JavaScriptCore/runtime/JSLock.h b/Source/JavaScriptCore/runtime/JSLock.h
index 05b388c..7b07b4f 100644
--- a/Source/JavaScriptCore/runtime/JSLock.h
+++ b/Source/JavaScriptCore/runtime/JSLock.h
@@ -53,7 +53,8 @@ namespace JSC {
enum JSLockBehavior { SilenceAssertionsOnly, LockForReal };
- class JSLock : public Noncopyable {
+ class JSLock {
+ WTF_MAKE_NONCOPYABLE(JSLock);
public:
JSLock(ExecState*);
JSLock(JSGlobalData*);
@@ -89,7 +90,8 @@ namespace JSC {
JSLockBehavior m_lockBehavior;
- class DropAllLocks : public Noncopyable {
+ class DropAllLocks {
+ WTF_MAKE_NONCOPYABLE(DropAllLocks);
public:
DropAllLocks(ExecState* exec);
DropAllLocks(JSLockBehavior);
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index 9e63027..df4be52 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -70,7 +70,8 @@ private:
mutable JSValue m_value;
};
-class Stringifier : public Noncopyable {
+class Stringifier {
+ WTF_MAKE_NONCOPYABLE(Stringifier);
public:
Stringifier(ExecState*, JSValue replacer, JSValue space);
~Stringifier();
diff --git a/Source/JavaScriptCore/runtime/Lookup.h b/Source/JavaScriptCore/runtime/Lookup.h
index 9bc81d4..0d6d98f 100644
--- a/Source/JavaScriptCore/runtime/Lookup.h
+++ b/Source/JavaScriptCore/runtime/Lookup.h
@@ -53,7 +53,8 @@ namespace JSC {
typedef PropertySlot::GetValueFunc GetFunction;
typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
- class HashEntry : public FastAllocBase {
+ class HashEntry {
+ WTF_MAKE_FAST_ALLOCATED;
public:
void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2
#if ENABLE(JIT)
diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
index b4a1936..e52f402 100644
--- a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
+++ b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
@@ -194,10 +194,9 @@ void MachineStackMarker::unregisterThread()
#endif
-void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(MarkStack& markStack)
+void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(ConservativeSet& conservativeSet)
{
- m_heap->markConservatively(markStack, m_heap->globalData()->stack().current(), m_heap->globalData()->stack().origin());
- markStack.drain();
+ m_heap->markConservatively(conservativeSet, m_heap->globalData()->stack().current(), m_heap->globalData()->stack().origin());
}
#if COMPILER(GCC)
@@ -206,7 +205,7 @@ void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(Ma
#define REGISTER_BUFFER_ALIGNMENT
#endif
-void MachineStackMarker::markCurrentThreadConservatively(MarkStack& markStack)
+void MachineStackMarker::markCurrentThreadConservatively(ConservativeSet& conservativeSet)
{
// setjmp forces volatile registers onto the stack
jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
@@ -219,7 +218,7 @@ void MachineStackMarker::markCurrentThreadConservatively(MarkStack& markStack)
#pragma warning(pop)
#endif
- markCurrentThreadConservativelyInternal(markStack);
+ markCurrentThreadConservativelyInternal(conservativeSet);
}
#if ENABLE(JSC_MULTIPLE_THREADS)
@@ -351,7 +350,7 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
#endif
}
-void MachineStackMarker::markOtherThreadConservatively(MarkStack& markStack, Thread* thread)
+void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conservativeSet, Thread* thread)
{
suspendThread(thread->platformThread);
@@ -359,21 +358,19 @@ void MachineStackMarker::markOtherThreadConservatively(MarkStack& markStack, Thr
size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
// mark the thread's registers
- m_heap->markConservatively(markStack, static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
- markStack.drain();
+ m_heap->markConservatively(conservativeSet, static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
void* stackPointer = otherThreadStackPointer(regs);
- m_heap->markConservatively(markStack, stackPointer, thread->stackBase);
- markStack.drain();
+ m_heap->markConservatively(conservativeSet, stackPointer, thread->stackBase);
resumeThread(thread->platformThread);
}
#endif
-void MachineStackMarker::markMachineStackConservatively(MarkStack& markStack)
+void MachineStackMarker::markMachineStackConservatively(ConservativeSet& conservativeSet)
{
- markCurrentThreadConservatively(markStack);
+ markCurrentThreadConservatively(conservativeSet);
#if ENABLE(JSC_MULTIPLE_THREADS)
@@ -391,7 +388,7 @@ void MachineStackMarker::markMachineStackConservatively(MarkStack& markStack)
// and since this is a shared heap, they are real locks.
for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
if (!pthread_equal(thread->posixThread, pthread_self()))
- markOtherThreadConservatively(markStack, thread);
+ markOtherThreadConservatively(conservativeSet, thread);
}
#ifndef NDEBUG
fastMallocAllow();
diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.h b/Source/JavaScriptCore/runtime/MachineStackMarker.h
index e80fe05..8afdb46 100644
--- a/Source/JavaScriptCore/runtime/MachineStackMarker.h
+++ b/Source/JavaScriptCore/runtime/MachineStackMarker.h
@@ -32,14 +32,15 @@
namespace JSC {
class Heap;
- class MarkStack;
+ class ConservativeSet;
- class MachineStackMarker : public Noncopyable {
+ class MachineStackMarker {
+ WTF_MAKE_NONCOPYABLE(MachineStackMarker);
public:
MachineStackMarker(Heap*);
~MachineStackMarker();
- void markMachineStackConservatively(MarkStack&);
+ void markMachineStackConservatively(ConservativeSet&);
#if ENABLE(JSC_MULTIPLE_THREADS)
void makeUsableFromMultipleThreads();
@@ -47,8 +48,8 @@ namespace JSC {
#endif
private:
- void markCurrentThreadConservatively(MarkStack&);
- void markCurrentThreadConservativelyInternal(MarkStack&);
+ void markCurrentThreadConservatively(ConservativeSet&);
+ void markCurrentThreadConservativelyInternal(ConservativeSet&);
#if ENABLE(JSC_MULTIPLE_THREADS)
class Thread;
@@ -56,7 +57,7 @@ namespace JSC {
static void unregisterThread(void*);
void unregisterThread();
- void markOtherThreadConservatively(MarkStack&, Thread*);
+ void markOtherThreadConservatively(ConservativeSet&, Thread*);
#endif
Heap* m_heap;
diff --git a/Source/JavaScriptCore/runtime/MarkStack.h b/Source/JavaScriptCore/runtime/MarkStack.h
index 7bccadf..7946e65 100644
--- a/Source/JavaScriptCore/runtime/MarkStack.h
+++ b/Source/JavaScriptCore/runtime/MarkStack.h
@@ -27,6 +27,7 @@
#define MarkStack_h
#include "JSValue.h"
+#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
#include <wtf/OSAllocator.h>
@@ -37,7 +38,8 @@ namespace JSC {
enum MarkSetProperties { MayContainNullValues, NoNullValues };
- class MarkStack : Noncopyable {
+ class MarkStack {
+ WTF_MAKE_NONCOPYABLE(MarkStack);
public:
MarkStack(void* jsArrayVPtr)
: m_jsArrayVPtr(jsArrayVPtr)
@@ -185,6 +187,20 @@ namespace JSC {
bool m_isDraining;
#endif
};
+
+ class ConservativeSet {
+ public:
+ void add(JSCell* cell) { m_set.add(cell); }
+ void mark(MarkStack& markStack)
+ {
+ HashSet<JSCell*>::iterator end = m_set.end();
+ for (HashSet<JSCell*>::iterator it = m_set.begin(); it != end; ++it)
+ markStack.append(*it);
+ }
+
+ private:
+ HashSet<JSCell*> m_set;
+ };
}
#endif
diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp
index 4bc3c18..036c8f0 100644
--- a/Source/JavaScriptCore/runtime/MarkedSpace.cpp
+++ b/Source/JavaScriptCore/runtime/MarkedSpace.cpp
@@ -108,8 +108,6 @@ NEVER_INLINE CollectorBlock* MarkedSpace::allocateBlock()
NEVER_INLINE void MarkedSpace::freeBlock(size_t block)
{
- m_heap.didShrink = true;
-
ObjectIterator it(m_heap, block);
ObjectIterator end(m_heap, block + 1);
for ( ; it != end; ++it)
@@ -162,8 +160,6 @@ void* MarkedSpace::allocate(size_t s)
void MarkedSpace::resizeBlocks()
{
- m_heap.didShrink = false;
-
size_t usedCellCount = markedCells();
size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount);
size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock;
@@ -222,7 +218,7 @@ static inline bool isPossibleCell(void* p)
return isCellAligned(p) && p;
}
-void MarkedSpace::markConservatively(MarkStack& markStack, void* start, void* end)
+void MarkedSpace::markConservatively(ConservativeSet& conservativeSet, void* start, void* end)
{
#if OS(WINCE)
if (start > end) {
@@ -244,7 +240,6 @@ void MarkedSpace::markConservatively(MarkStack& markStack, void* start, void* en
while (p != e) {
char* x = *p++;
if (isPossibleCell(x)) {
- size_t usedBlocks;
uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
xAsBits &= CELL_ALIGN_MASK;
@@ -254,11 +249,30 @@ void MarkedSpace::markConservatively(MarkStack& markStack, void* start, void* en
continue;
CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
- usedBlocks = m_heap.usedBlocks;
+ size_t usedBlocks = m_heap.usedBlocks;
for (size_t block = 0; block < usedBlocks; block++) {
if (m_heap.collectorBlock(block) != blockAddr)
continue;
- markStack.append(reinterpret_cast<JSCell*>(xAsBits));
+
+ // x is a pointer into the heap. Now, verify that the cell it
+ // points to is live. (If the cell is dead, we must not mark it,
+ // since that would revive it in a zombie state.)
+ if (block < m_heap.nextBlock) {
+ conservativeSet.add(reinterpret_cast<JSCell*>(xAsBits));
+ break;
+ }
+
+ size_t cellOffset = offset / CELL_SIZE;
+
+ if (block == m_heap.nextBlock && cellOffset < m_heap.nextCell) {
+ conservativeSet.add(reinterpret_cast<JSCell*>(xAsBits));
+ break;
+ }
+
+ if (blockAddr->marked.get(cellOffset)) {
+ conservativeSet.add(reinterpret_cast<JSCell*>(xAsBits));
+ break;
+ }
}
}
}
diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h
index 78f918c..af312b5 100644
--- a/Source/JavaScriptCore/runtime/MarkedSpace.h
+++ b/Source/JavaScriptCore/runtime/MarkedSpace.h
@@ -55,15 +55,14 @@ namespace JSC {
size_t numBlocks;
size_t usedBlocks;
- bool didShrink;
-
CollectorBlock* collectorBlock(size_t index) const
{
return static_cast<CollectorBlock*>(blocks[index].base());
}
};
- class MarkedSpace : public Noncopyable {
+ class MarkedSpace {
+ WTF_MAKE_NONCOPYABLE(MarkedSpace);
public:
MarkedSpace(JSGlobalData*);
void destroy(ProtectCountSet&);
@@ -86,7 +85,7 @@ namespace JSC {
WeakGCHandle* addWeakGCHandle(JSCell*);
- void markConservatively(MarkStack&, void* start, void* end);
+ void markConservatively(ConservativeSet&, void* start, void* end);
static bool isNumber(JSCell*);
@@ -114,8 +113,6 @@ namespace JSC {
void markRoots();
- bool didShrink() { return m_heap.didShrink; }
-
private:
CollectorHeap m_heap;
JSGlobalData* m_globalData;
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h
index 58abde5..1714bd3 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h
@@ -31,7 +31,9 @@ namespace JSC {
class RegExpPrototype;
struct RegExpConstructorPrivate;
- struct RegExpConstructorPrivate : FastAllocBase {
+ struct RegExpConstructorPrivate {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
// Global search cache / settings
RegExpConstructorPrivate()
: lastNumSubPatterns(0)
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index 7fda5b1..b969e38 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -128,17 +128,6 @@ JSValue RegExpObject::exec(ExecState* exec)
return jsNull();
}
-static EncodedJSValue JSC_HOST_CALL callRegExpObject(ExecState* exec)
-{
- return JSValue::encode(asRegExpObject(exec->callee())->exec(exec));
-}
-
-CallType RegExpObject::getCallData(CallData& callData)
-{
- callData.native.function = callRegExpObject;
- return CallTypeHost;
-}
-
// Shared implementation used by test and exec.
bool RegExpObject::match(ExecState* exec)
{
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index 19de929..99c84da 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -58,9 +58,9 @@ namespace JSC {
private:
bool match(ExecState*);
- virtual CallType getCallData(CallData&);
-
- struct RegExpObjectData : FastAllocBase {
+ struct RegExpObjectData {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex)
: regExp(regExp)
, lastIndex(lastIndex)
@@ -70,7 +70,9 @@ namespace JSC {
RefPtr<RegExp> regExp;
double lastIndex;
};
-
+#if PLATFORM(WIN)
+ friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*);
+#endif
OwnPtr<RegExpObjectData> d;
};
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
index 04bcc3b..a7c447d 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -34,6 +34,7 @@
#include "RegExpObject.h"
#include "RegExp.h"
#include "RegExpCache.h"
+#include "StringRecursionChecker.h"
#include "UStringConcatenate.h"
namespace JSC {
@@ -111,15 +112,21 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
return throwVMTypeError(exec);
}
+ RegExpObject* thisObject = asRegExpObject(thisValue);
+
+ StringRecursionChecker checker(exec, thisObject);
+ if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+ return earlyReturnValue;
+
char postfix[5] = { '/', 0, 0, 0, 0 };
int index = 1;
- if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec))
+ if (thisObject->get(exec, exec->propertyNames().global).toBoolean(exec))
postfix[index++] = 'g';
- if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
+ if (thisObject->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
postfix[index++] = 'i';
- if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec))
+ if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec))
postfix[index] = 'm';
- UString source = asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec);
+ UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec);
// If source is empty, use "/(?:)/" to avoid colliding with comment syntax
return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix));
}
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h
index 0b15b67..b104e75 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.h
+++ b/Source/JavaScriptCore/runtime/ScopeChain.h
@@ -21,7 +21,7 @@
#ifndef ScopeChain_h
#define ScopeChain_h
-#include "FastAllocBase.h"
+#include <wtf/FastAllocBase.h>
namespace JSC {
@@ -31,7 +31,8 @@ namespace JSC {
class MarkStack;
class ScopeChainIterator;
- class ScopeChainNode : public FastAllocBase {
+ class ScopeChainNode {
+ WTF_MAKE_FAST_ALLOCATED;
public:
ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
: next(next)
diff --git a/Source/JavaScriptCore/runtime/SmallStrings.cpp b/Source/JavaScriptCore/runtime/SmallStrings.cpp
index f358727..5614932 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.cpp
+++ b/Source/JavaScriptCore/runtime/SmallStrings.cpp
@@ -40,7 +40,8 @@ static inline bool isMarked(JSString* string)
return string && Heap::isCellMarked(string);
}
-class SmallStringsStorage : public Noncopyable {
+class SmallStringsStorage {
+ WTF_MAKE_NONCOPYABLE(SmallStringsStorage); WTF_MAKE_FAST_ALLOCATED;
public:
SmallStringsStorage();
diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h
index d1ebfb1..ac84fe8 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.h
+++ b/Source/JavaScriptCore/runtime/SmallStrings.h
@@ -37,7 +37,8 @@ namespace JSC {
class MarkStack;
class SmallStringsStorage;
- class SmallStrings : public Noncopyable {
+ class SmallStrings {
+ WTF_MAKE_NONCOPYABLE(SmallStrings); WTF_MAKE_FAST_ALLOCATED;
public:
SmallStrings();
~SmallStrings();
diff --git a/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp b/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp
new file mode 100644
index 0000000..4e74735
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "StringRecursionChecker.h"
+
+#include "Error.h"
+#include "ExceptionHelpers.h"
+
+namespace JSC {
+
+EncodedJSValue StringRecursionChecker::throwStackOverflowError()
+{
+ return throwVMError(m_exec, createStackOverflowError(m_exec));
+}
+
+EncodedJSValue StringRecursionChecker::emptyString()
+{
+ return JSValue::encode(jsEmptyString(m_exec));
+}
+
+}
diff --git a/Source/JavaScriptCore/runtime/StringRecursionChecker.h b/Source/JavaScriptCore/runtime/StringRecursionChecker.h
new file mode 100644
index 0000000..314f14e
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/StringRecursionChecker.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringRecursionChecker_h
+#define StringRecursionChecker_h
+
+#include "Interpreter.h"
+
+namespace JSC {
+
+class StringRecursionChecker {
+ WTF_MAKE_NONCOPYABLE(StringRecursionChecker);
+
+public:
+ StringRecursionChecker(ExecState*, JSObject* thisObject);
+ ~StringRecursionChecker();
+
+ EncodedJSValue earlyReturnValue() const; // 0 if everything is OK, value to return for failure cases
+
+private:
+ EncodedJSValue throwStackOverflowError();
+ EncodedJSValue emptyString();
+ EncodedJSValue performCheck();
+
+ ExecState* m_exec;
+ JSObject* m_thisObject;
+ EncodedJSValue m_earlyReturnValue;
+};
+
+inline EncodedJSValue StringRecursionChecker::performCheck()
+{
+ int size = m_exec->globalData().stringRecursionCheckVisitedObjects.size();
+ if (size >= MaxSmallThreadReentryDepth && size >= m_exec->globalData().maxReentryDepth)
+ return throwStackOverflowError();
+ bool alreadyVisited = !m_exec->globalData().stringRecursionCheckVisitedObjects.add(m_thisObject).second;
+ if (alreadyVisited)
+ return emptyString(); // Return empty string to avoid infinite recursion.
+ return 0; // Indicate success.
+}
+
+inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject* thisObject)
+ : m_exec(exec)
+ , m_thisObject(thisObject)
+ , m_earlyReturnValue(performCheck())
+{
+}
+
+inline EncodedJSValue StringRecursionChecker::earlyReturnValue() const
+{
+ return m_earlyReturnValue;
+}
+
+inline StringRecursionChecker::~StringRecursionChecker()
+{
+ if (m_earlyReturnValue)
+ return;
+ ASSERT(m_exec->globalData().stringRecursionCheckVisitedObjects.contains(m_thisObject));
+ m_exec->globalData().stringRecursionCheckVisitedObjects.remove(m_thisObject);
+}
+
+}
+
+#endif
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index 1b1636d..2635501 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -122,6 +122,7 @@ namespace JSC {
typedef HashMap<RefPtr<StringImpl>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, SymbolTableIndexHashTraits> SymbolTable;
class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable> {
+ WTF_MAKE_FAST_ALLOCATED;
public:
static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); }
private:
diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h
index 2d4e59d..316794f 100644
--- a/Source/JavaScriptCore/runtime/WeakGCMap.h
+++ b/Source/JavaScriptCore/runtime/WeakGCMap.h
@@ -35,7 +35,8 @@ class JSCell;
// A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
template<typename KeyType, typename MappedType>
-class WeakGCMap : public FastAllocBase {
+class WeakGCMap {
+ WTF_MAKE_FAST_ALLOCATED;
/*
Invariants:
* A value enters the WeakGCMap marked. (Guaranteed by set().)
diff --git a/Source/JavaScriptCore/runtime/WeakGCPtr.h b/Source/JavaScriptCore/runtime/WeakGCPtr.h
index 6cc75a5..4946ee7 100644
--- a/Source/JavaScriptCore/runtime/WeakGCPtr.h
+++ b/Source/JavaScriptCore/runtime/WeakGCPtr.h
@@ -28,12 +28,12 @@
#include "Heap.h"
#include "GCHandle.h"
-#include <wtf/Noncopyable.h>
namespace JSC {
// A smart pointer whose get() function returns 0 for cells awaiting destruction.
-template <typename T> class WeakGCPtr : Noncopyable {
+template <typename T> class WeakGCPtr {
+ WTF_MAKE_NONCOPYABLE(WeakGCPtr);
public:
WeakGCPtr()
: m_ptr(0)