summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime')
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.h6
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.cpp42
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.h72
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConstructor.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConstructor.h2
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.cpp159
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.h9
-rw-r--r--Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h2
-rw-r--r--Source/JavaScriptCore/runtime/BooleanConstructor.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/BooleanConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/BooleanObject.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/BooleanObject.h11
-rw-r--r--Source/JavaScriptCore/runtime/BooleanPrototype.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/BooleanPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/CallData.h1
-rw-r--r--Source/JavaScriptCore/runtime/CommonIdentifiers.h7
-rw-r--r--Source/JavaScriptCore/runtime/Completion.cpp16
-rw-r--r--Source/JavaScriptCore/runtime/Completion.h4
-rw-r--r--Source/JavaScriptCore/runtime/ConservativeSet.h80
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.cpp21
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/DateConversion.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.h17
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.cpp72
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.h11
-rw-r--r--Source/JavaScriptCore/runtime/Error.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/ErrorConstructor.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/ErrorConstructor.h2
-rw-r--r--Source/JavaScriptCore/runtime/ErrorInstance.cpp16
-rw-r--r--Source/JavaScriptCore/runtime/ErrorInstance.h17
-rw-r--r--Source/JavaScriptCore/runtime/ErrorPrototype.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/ErrorPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/ExceptionHelpers.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp104
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h102
-rw-r--r--Source/JavaScriptCore/runtime/FunctionConstructor.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/FunctionConstructor.h6
-rw-r--r--Source/JavaScriptCore/runtime/FunctionPrototype.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/FunctionPrototype.h10
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.h4
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/GCHandle.cpp86
-rw-r--r--Source/JavaScriptCore/runtime/GCHandle.h116
-rw-r--r--Source/JavaScriptCore/runtime/GetterSetter.h7
-rw-r--r--Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp48
-rw-r--r--Source/JavaScriptCore/runtime/GlobalEvalFunction.h54
-rw-r--r--Source/JavaScriptCore/runtime/Heap.cpp428
-rw-r--r--Source/JavaScriptCore/runtime/Heap.h181
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/InternalFunction.cpp21
-rw-r--r--Source/JavaScriptCore/runtime/InternalFunction.h15
-rw-r--r--Source/JavaScriptCore/runtime/JSAPIValueWrapper.h7
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.cpp78
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.h42
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp34
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h108
-rw-r--r--Source/JavaScriptCore/runtime/JSByteArray.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSByteArray.h37
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.cpp31
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h203
-rw-r--r--Source/JavaScriptCore/runtime/JSChunk.cpp (renamed from Source/JavaScriptCore/runtime/ConservativeSet.cpp)39
-rw-r--r--Source/JavaScriptCore/runtime/JSChunk.h31
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.cpp85
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.h33
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp149
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h63
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp366
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h328
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/JSImmediate.cpp26
-rw-r--r--Source/JavaScriptCore/runtime/JSImmediate.h568
-rw-r--r--Source/JavaScriptCore/runtime/JSLock.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/JSNotAnObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSNotAnObject.h10
-rw-r--r--Source/JavaScriptCore/runtime/JSNumberCell.cpp38
-rw-r--r--Source/JavaScriptCore/runtime/JSNumberCell.h171
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.cpp150
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.h11
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp117
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h286
-rw-r--r--Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h20
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.h29
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.h22
-rw-r--r--Source/JavaScriptCore/runtime/JSString.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSString.h43
-rw-r--r--Source/JavaScriptCore/runtime/JSType.h7
-rw-r--r--Source/JavaScriptCore/runtime/JSTypeInfo.h25
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.h590
-rw-r--r--Source/JavaScriptCore/runtime/JSValueInlineMethods.h532
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.h83
-rw-r--r--Source/JavaScriptCore/runtime/JSWrapperObject.h23
-rw-r--r--Source/JavaScriptCore/runtime/JSZombie.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSZombie.h15
-rw-r--r--Source/JavaScriptCore/runtime/Lookup.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/MachineStackMarker.cpp418
-rw-r--r--Source/JavaScriptCore/runtime/MachineStackMarker.h74
-rw-r--r--Source/JavaScriptCore/runtime/MarkStack.cpp40
-rw-r--r--Source/JavaScriptCore/runtime/MarkStack.h202
-rw-r--r--Source/JavaScriptCore/runtime/MarkStackPosix.cpp43
-rw-r--r--Source/JavaScriptCore/runtime/MarkStackSymbian.cpp38
-rw-r--r--Source/JavaScriptCore/runtime/MarkStackWin.cpp44
-rw-r--r--Source/JavaScriptCore/runtime/MarkedBlock.cpp84
-rw-r--r--Source/JavaScriptCore/runtime/MarkedBlock.h177
-rw-r--r--Source/JavaScriptCore/runtime/MarkedSpace.cpp138
-rw-r--r--Source/JavaScriptCore/runtime/MarkedSpace.h156
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.h9
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp18
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorConstructor.h15
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/NativeFunctionWrapper.h39
-rw-r--r--Source/JavaScriptCore/runtime/NumberConstructor.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/NumberConstructor.h10
-rw-r--r--Source/JavaScriptCore/runtime/NumberObject.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/NumberObject.h15
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/ObjectConstructor.cpp120
-rw-r--r--Source/JavaScriptCore/runtime/ObjectConstructor.h15
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.cpp25
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/Operations.h12
-rw-r--r--Source/JavaScriptCore/runtime/PropertyMapHashTable.h559
-rw-r--r--Source/JavaScriptCore/runtime/PropertyNameArray.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/PropertySlot.h9
-rw-r--r--Source/JavaScriptCore/runtime/Protect.h149
-rw-r--r--Source/JavaScriptCore/runtime/PrototypeFunction.cpp57
-rw-r--r--Source/JavaScriptCore/runtime/PrototypeFunction.h45
-rw-r--r--Source/JavaScriptCore/runtime/PutPropertySlot.h9
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.cpp49
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.h18
-rw-r--r--Source/JavaScriptCore/runtime/RegExpCache.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/RegExpCache.h4
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.cpp32
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.h14
-rw-r--r--Source/JavaScriptCore/runtime/RegExpKey.h49
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp49
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.h41
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.cpp37
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChain.cpp21
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChain.h200
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChainMark.h6
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.cpp35
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.h24
-rw-r--r--Source/JavaScriptCore/runtime/StrictEvalActivation.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/StrictEvalActivation.h2
-rw-r--r--Source/JavaScriptCore/runtime/StringConstructor.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/StringConstructor.h2
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.h21
-rw-r--r--Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h8
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.cpp35
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.h16
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp1187
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h260
-rw-r--r--Source/JavaScriptCore/runtime/StructureChain.cpp22
-rw-r--r--Source/JavaScriptCore/runtime/StructureChain.h19
-rw-r--r--Source/JavaScriptCore/runtime/StructureTransitionTable.h110
-rw-r--r--Source/JavaScriptCore/runtime/TimeoutChecker.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/UString.h5
-rw-r--r--Source/JavaScriptCore/runtime/WeakGCMap.h221
-rw-r--r--Source/JavaScriptCore/runtime/WeakGCPtr.h153
-rw-r--r--Source/JavaScriptCore/runtime/WriteBarrier.h155
173 files changed, 4491 insertions, 7351 deletions
diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp
index a862ea0..f46d108 100644
--- a/Source/JavaScriptCore/runtime/ArgList.cpp
+++ b/Source/JavaScriptCore/runtime/ArgList.cpp
@@ -23,6 +23,8 @@
#include "JSValue.h"
#include "JSCell.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
using std::min;
@@ -37,12 +39,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const
result = ArgList(m_args + startIndex, m_argCount - startIndex);
}
-void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet)
+void MarkedArgumentBuffer::markLists(HeapRootMarker& heapRootMarker, ListSet& markSet)
{
ListSet::iterator end = markSet.end();
for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
MarkedArgumentBuffer* list = *it;
- markStack.deprecatedAppendValues(list->m_buffer, list->m_size);
+ heapRootMarker.mark(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size);
}
}
@@ -54,8 +56,8 @@ void MarkedArgumentBuffer::slowAppend(JSValue v)
// our Vector's inline capacity, though, our values move to the
// heap, where they do need explicit marking.
if (!m_markSet) {
- // We can only register for explicit marking once we know which heap
- // is the current one, i.e., when a non-immediate value is appended.
+ // FIXME: Even if v is not a JSCell*, if previous values in the buffer
+ // are, then they won't be marked!
if (Heap* heap = Heap::heap(v)) {
ListSet& markSet = heap->markListSet();
markSet.add(this);
diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h
index 57e3c20..a794a04 100644
--- a/Source/JavaScriptCore/runtime/ArgList.h
+++ b/Source/JavaScriptCore/runtime/ArgList.h
@@ -67,12 +67,12 @@ namespace JSC {
{
}
- void initialize(Register* buffer, size_t size)
+ void initialize(WriteBarrier<Unknown>* buffer, size_t size)
{
ASSERT(!m_markSet);
ASSERT(isEmpty());
- m_buffer = buffer;
+ m_buffer = reinterpret_cast<Register*>(buffer);
m_size = size;
#ifndef NDEBUG
m_isReadOnly = true;
@@ -141,7 +141,7 @@ namespace JSC {
const_iterator begin() const { return m_buffer; }
const_iterator end() const { return m_buffer + m_size; }
- static void markLists(MarkStack&, ListSet&);
+ static void markLists(HeapRootMarker&, ListSet&);
private:
void slowAppend(JSValue);
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp
index 305b247..e201b91 100644
--- a/Source/JavaScriptCore/runtime/Arguments.cpp
+++ b/Source/JavaScriptCore/runtime/Arguments.cpp
@@ -35,7 +35,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(Arguments);
-const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
+const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0 };
Arguments::~Arguments()
{
@@ -48,11 +48,11 @@ void Arguments::markChildren(MarkStack& markStack)
JSObject::markChildren(markStack);
if (d->registerArray)
- markStack.deprecatedAppendValues(d->registerArray.get(), d->numParameters);
+ markStack.appendValues(d->registerArray.get(), d->numParameters);
if (d->extraArguments) {
unsigned numExtraArguments = d->numArguments - d->numParameters;
- markStack.deprecatedAppendValues(d->extraArguments, numExtraArguments);
+ markStack.appendValues(d->extraArguments, numExtraArguments);
}
markStack.append(&d->callee);
@@ -74,9 +74,9 @@ void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxS
unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
unsigned i = 0;
for (; i < parametersLength; ++i)
- buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
+ buffer[i] = d->registers[d->firstParameterIndex + i].get();
for (; i < d->numArguments; ++i)
- buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
+ buffer[i] = d->extraArguments[i - d->numParameters].get();
return;
}
@@ -84,13 +84,13 @@ void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxS
unsigned i = 0;
for (; i < parametersLength; ++i) {
if (!d->deletedArguments[i])
- buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
+ buffer[i] = d->registers[d->firstParameterIndex + i].get();
else
buffer[i] = get(exec, i);
}
for (; i < d->numArguments; ++i) {
if (!d->deletedArguments[i])
- buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
+ buffer[i] = d->extraArguments[i - d->numParameters].get();
else
buffer[i] = get(exec, i);
}
@@ -119,9 +119,9 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
unsigned parametersLength = min(d->numParameters, d->numArguments);
unsigned i = 0;
for (; i < parametersLength; ++i)
- args.append(d->registers[d->firstParameterIndex + i].jsValue());
+ args.append(d->registers[d->firstParameterIndex + i].get());
for (; i < d->numArguments; ++i)
- args.append(d->extraArguments[i - d->numParameters].jsValue());
+ args.append(d->extraArguments[i - d->numParameters].get());
return;
}
@@ -129,13 +129,13 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
unsigned i = 0;
for (; i < parametersLength; ++i) {
if (!d->deletedArguments[i])
- args.append(d->registers[d->firstParameterIndex + i].jsValue());
+ args.append(d->registers[d->firstParameterIndex + i].get());
else
args.append(get(exec, i));
}
for (; i < d->numArguments; ++i) {
if (!d->deletedArguments[i])
- args.append(d->extraArguments[i - d->numParameters].jsValue());
+ args.append(d->extraArguments[i - d->numParameters].get());
else
args.append(get(exec, i));
}
@@ -145,9 +145,9 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& sl
{
if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
if (i < d->numParameters) {
- slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+ slot.setValue(d->registers[d->firstParameterIndex + i].get());
} else
- slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
+ slot.setValue(d->extraArguments[i - d->numParameters].get());
return true;
}
@@ -184,9 +184,9 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa
unsigned i = propertyName.toArrayIndex(isArrayIndex);
if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
if (i < d->numParameters) {
- slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+ slot.setValue(d->registers[d->firstParameterIndex + i].get());
} else
- slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
+ slot.setValue(d->extraArguments[i - d->numParameters].get());
return true;
}
@@ -215,9 +215,9 @@ bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& prop
unsigned i = propertyName.toArrayIndex(isArrayIndex);
if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
if (i < d->numParameters) {
- descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum);
+ descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].get(), DontEnum);
} else
- descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum);
+ descriptor.setDescriptor(d->extraArguments[i - d->numParameters].get(), DontEnum);
return true;
}
@@ -257,9 +257,9 @@ void Arguments::put(ExecState* exec, unsigned i, JSValue value)
{
if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
if (i < d->numParameters)
- d->registers[d->firstParameterIndex + i] = JSValue(value);
+ d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
else
- d->extraArguments[i - d->numParameters] = JSValue(value);
+ d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
return;
}
@@ -273,9 +273,9 @@ void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue val
unsigned i = propertyName.toArrayIndex(isArrayIndex);
if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
if (i < d->numParameters)
- d->registers[d->firstParameterIndex + i] = JSValue(value);
+ d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
else
- d->extraArguments[i - d->numParameters] = JSValue(value);
+ d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
return;
}
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h
index 658538b..b5aa46b 100644
--- a/Source/JavaScriptCore/runtime/Arguments.h
+++ b/Source/JavaScriptCore/runtime/Arguments.h
@@ -29,7 +29,6 @@
#include "JSGlobalObject.h"
#include "Interpreter.h"
#include "ObjectConstructor.h"
-#include "PrototypeFunction.h"
namespace JSC {
@@ -43,12 +42,12 @@ namespace JSC {
ptrdiff_t firstParameterIndex;
unsigned numArguments;
- Register* registers;
- OwnArrayPtr<Register> registerArray;
+ WriteBarrier<Unknown>* registers;
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
- Register* extraArguments;
+ WriteBarrier<Unknown>* extraArguments;
OwnArrayPtr<bool> deletedArguments;
- Register extraArgumentsFixedBuffer[4];
+ WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
WriteBarrier<JSFunction> callee;
bool overrodeLength : 1;
@@ -58,7 +57,7 @@ namespace JSC {
};
- class Arguments : public JSObject {
+ class Arguments : public JSNonFinalObject {
public:
// Use an enum because otherwise gcc insists on doing a memory
// read.
@@ -70,7 +69,7 @@ namespace JSC {
Arguments(CallFrame*, NoParametersType);
virtual ~Arguments();
- static const ClassInfo info;
+ static const ClassInfo s_info;
virtual void markChildren(MarkStack&);
@@ -84,17 +83,18 @@ namespace JSC {
}
void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
- void copyRegisters();
+ void copyRegisters(JSGlobalData&);
bool isTornOff() const { return d->registerArray; }
void setActivation(JSGlobalData& globalData, JSActivation* activation)
{
+ ASSERT(!d->registerArray);
d->activation.set(globalData, this, activation);
d->registers = &activation->registerAt(0);
}
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
@@ -113,8 +113,6 @@ namespace JSC {
void createStrictModeCallerIfNecessary(ExecState*);
void createStrictModeCalleeIfNecessary(ExecState*);
- virtual const ClassInfo* classInfo() const { return &info; }
-
void init(CallFrame*);
OwnPtr<ArgumentsData> d;
@@ -124,7 +122,7 @@ namespace JSC {
inline Arguments* asArguments(JSValue value)
{
- ASSERT(asObject(value)->inherits(&Arguments::info));
+ ASSERT(asObject(value)->inherits(&Arguments::s_info));
return static_cast<Arguments*>(asObject(value));
}
@@ -145,9 +143,11 @@ namespace JSC {
}
inline Arguments::Arguments(CallFrame* callFrame)
- : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+ : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
, d(adoptPtr(new ArgumentsData))
{
+ ASSERT(inherits(&s_info));
+
JSFunction* callee;
ptrdiff_t firstParameterIndex;
Register* argv;
@@ -158,19 +158,19 @@ namespace JSC {
d->firstParameterIndex = firstParameterIndex;
d->numArguments = numArguments;
- d->registers = callFrame->registers();
+ d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
- Register* extraArguments;
+ WriteBarrier<Unknown>* extraArguments;
if (d->numArguments <= d->numParameters)
extraArguments = 0;
else {
unsigned numExtraArguments = d->numArguments - d->numParameters;
- if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
- extraArguments = new Register[numExtraArguments];
+ if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
+ extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
else
extraArguments = d->extraArgumentsFixedBuffer;
for (unsigned i = 0; i < numExtraArguments; ++i)
- extraArguments[i] = argv[d->numParameters + i];
+ extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
}
d->extraArguments = extraArguments;
@@ -181,13 +181,14 @@ namespace JSC {
d->overrodeCaller = false;
d->isStrictMode = callFrame->codeBlock()->isStrictMode();
if (d->isStrictMode)
- copyRegisters();
+ copyRegisters(callFrame->globalData());
}
inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
- : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+ : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
, d(adoptPtr(new ArgumentsData))
{
+ ASSERT(inherits(&s_info));
ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
unsigned numArguments = callFrame->argumentCount();
@@ -195,15 +196,15 @@ namespace JSC {
d->numParameters = 0;
d->numArguments = numArguments;
- Register* extraArguments;
+ WriteBarrier<Unknown>* extraArguments;
if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
- extraArguments = new Register[numArguments];
+ extraArguments = new WriteBarrier<Unknown>[numArguments];
else
extraArguments = d->extraArgumentsFixedBuffer;
Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
for (unsigned i = 0; i < numArguments; ++i)
- extraArguments[i] = argv[i];
+ extraArguments[i].set(callFrame->globalData(), this, argv[i].jsValue());
d->extraArguments = extraArguments;
@@ -213,10 +214,10 @@ namespace JSC {
d->overrodeCaller = false;
d->isStrictMode = callFrame->codeBlock()->isStrictMode();
if (d->isStrictMode)
- copyRegisters();
+ copyRegisters(callFrame->globalData());
}
- inline void Arguments::copyRegisters()
+ inline void Arguments::copyRegisters(JSGlobalData& globalData)
{
ASSERT(!isTornOff());
@@ -226,29 +227,28 @@ namespace JSC {
int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
size_t registerArraySize = d->numParameters;
- OwnArrayPtr<Register> registerArray = adoptArrayPtr(new Register[registerArraySize]);
- memcpy(registerArray.get(), d->registers - registerOffset, registerArraySize * sizeof(Register));
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
+ for (size_t i = 0; i < registerArraySize; i++)
+ registerArray[i].set(globalData, this, d->registers[i - registerOffset].get());
d->registers = registerArray.get() + registerOffset;
d->registerArray = registerArray.release();
}
// This JSActivation function is defined here so it can get at Arguments::setRegisters.
- inline void JSActivation::copyRegisters()
+ inline void JSActivation::copyRegisters(JSGlobalData& globalData)
{
- ASSERT(!d()->registerArray);
+ ASSERT(!m_registerArray);
- size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
- size_t numVars = d()->functionExecutable->capturedVariableCount();
- size_t numLocals = numVars + numParametersMinusThis;
+ size_t numLocals = m_numCapturedVars + m_numParametersMinusThis;
if (!numLocals)
return;
- int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
+ int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
- OwnArrayPtr<Register> registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
- Register* registers = registerArray.get() + registerOffset;
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1);
+ WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
setRegisters(registers, registerArray.release());
}
diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
index 5d0adbd..050e989 100644
--- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
@@ -30,7 +30,6 @@
#include "JSArray.h"
#include "JSFunction.h"
#include "Lookup.h"
-#include "PrototypeFunction.h"
namespace JSC {
@@ -38,7 +37,7 @@ ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
static EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*);
-ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* prototypeFunctionStructure)
+ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype, Structure* functionStructure)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, arrayPrototype->classInfo()->className))
{
// ECMA 15.4.3.1 Array.prototype
@@ -48,21 +47,23 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
// ES5
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum);
}
static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
{
+ JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
+
// a single numeric argument denotes the array size (!)
if (args.size() == 1 && args.at(0).isNumber()) {
uint32_t n = args.at(0).toUInt32(exec);
if (n != args.at(0).toNumber(exec))
return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer."));
- return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n, CreateInitialized);
+ return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), n, CreateInitialized);
}
// otherwise the array is constructed with the arguments in it
- return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), args);
+ return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), args);
}
static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec)
@@ -94,7 +95,7 @@ CallType ArrayConstructor::getCallData(CallData& callData)
EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState* exec)
{
- return JSValue::encode(jsBoolean(exec->argument(0).inherits(&JSArray::info)));
+ return JSValue::encode(jsBoolean(exec->argument(0).inherits(&JSArray::s_info)));
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.h b/Source/JavaScriptCore/runtime/ArrayConstructor.h
index 5e1408f..97b26c5 100644
--- a/Source/JavaScriptCore/runtime/ArrayConstructor.h
+++ b/Source/JavaScriptCore/runtime/ArrayConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class ArrayConstructor : public InternalFunction {
public:
- ArrayConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, ArrayPrototype*, Structure*);
+ ArrayConstructor(ExecState*, JSGlobalObject*, Structure*, ArrayPrototype*, Structure*);
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
index 70c0d06..29caece 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -85,7 +85,7 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType,
// ------------------------------ ArrayPrototype ----------------------------
-const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};
+const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecState::arrayTable};
/* Source for ArrayPrototype.lut.h
@begin arrayTable 16
@@ -114,9 +114,10 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a
*/
// ECMA 15.4.4
-ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
- : JSArray(structure)
+ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure)
+ : JSArray(globalObject->globalData(), structure)
{
+ ASSERT(inherits(&s_info));
putAnonymousValue(globalObject->globalData(), 0, globalObject);
}
@@ -164,16 +165,20 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+
bool isRealArray = isJSArray(&exec->globalData(), thisValue);
- if (!isRealArray && !thisValue.inherits(&JSArray::info))
+ if (!isRealArray && !thisValue.inherits(&JSArray::s_info))
return throwVMTypeError(exec);
JSArray* thisObj = asArray(thisValue);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
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;
#if OS(SYMBIAN)
// Symbian has very limited stack size available.
@@ -224,16 +229,20 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&JSArray::info))
+
+ if (!thisValue.inherits(&JSArray::s_info))
return throwVMTypeError(exec);
JSObject* thisObj = asArray(thisValue);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
StringRecursionChecker checker(exec, thisObj);
if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
return earlyReturnValue;
JSStringBuilder strBuffer;
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
for (unsigned k = 0; k < length; k++) {
if (k >= 1)
strBuffer.append(',');
@@ -259,6 +268,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
StringRecursionChecker checker(exec, thisObj);
if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
@@ -270,7 +282,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
if (!exec->argument(0).isUndefined())
separator = exec->argument(0).toString(exec);
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
unsigned k = 0;
if (isJSArray(&exec->globalData(), thisObj)) {
JSArray* array = asArray(thisObj);
@@ -330,7 +341,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
size_t i = 0;
size_t argCount = exec->argumentCount();
while (1) {
- if (curArg.inherits(&JSArray::info)) {
+ if (curArg.inherits(&JSArray::s_info)) {
unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);
JSObject* curObject = curArg.toObject(exec);
for (unsigned k = 0; k < length; ++k) {
@@ -354,12 +365,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+
if (isJSArray(&exec->globalData(), thisValue))
return JSValue::encode(asArray(thisValue)->pop());
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValue result;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
+ JSValue result;
if (length == 0) {
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
result = jsUndefined();
@@ -374,6 +389,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+
if (isJSArray(&exec->globalData(), thisValue) && exec->argumentCount() == 1) {
JSArray* array = asArray(thisValue);
array->push(exec, exec->argument(0));
@@ -382,6 +398,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
JSObject* thisObj = thisValue.toThisObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
for (unsigned n = 0; n < exec->argumentCount(); n++)
thisObj->put(exec, length + n, exec->argument(n));
length += exec->argumentCount();
@@ -393,8 +412,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
- unsigned middle = length / 2;
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ unsigned middle = length / 2;
for (unsigned k = 0; k < middle; k++) {
unsigned lk1 = length - k - 1;
JSValue obj2 = getProperty(exec, thisObj, lk1);
@@ -419,6 +440,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
JSValue result;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
if (length == 0) {
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
result = jsUndefined();
@@ -450,6 +474,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
JSValue result = resObj;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
@@ -465,12 +492,15 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (!length || exec->hadException())
+ return JSValue::encode(thisObj);
JSValue function = exec->argument(0);
CallData callData;
CallType callType = getCallData(function, callData);
- if (thisObj->classInfo() == &JSArray::info) {
+ if (thisObj->classInfo() == &JSArray::s_info) {
if (isNumericCompareFunction(exec, callType, callData))
asArray(thisObj)->sortNumeric(exec, function, callType, callData);
else if (callType != CallTypeNone)
@@ -480,19 +510,18 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
return JSValue::encode(thisObj);
}
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-
- if (!length)
- return JSValue::encode(thisObj);
-
// "Min" sort. Not the fastest, but definitely less code than heapsort
// or quicksort, and much less swapping than bubblesort/insertionsort.
for (unsigned i = 0; i < length - 1; ++i) {
JSValue iObj = thisObj->get(exec, i);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
unsigned themin = i;
JSValue minObj = iObj;
for (unsigned j = i + 1; j < length; ++j) {
JSValue jObj = thisObj->get(exec, j);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
double compareResult;
if (jObj.isUndefined())
compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
@@ -522,14 +551,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
{
- JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
-
// 15.4.4.12
+ JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
if (!exec->argumentCount())
return JSValue::encode(constructEmptyArray(exec));
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
unsigned deleteCount = length - begin;
@@ -543,7 +574,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
deleteCount = static_cast<unsigned>(deleteDouble);
}
- JSArray* resObj = new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact);
+ JSArray* resObj = new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact);
JSValue result = resObj;
JSGlobalData& globalData = exec->globalData();
for (unsigned k = 0; k < deleteCount; k++)
@@ -588,10 +619,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
{
- JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
-
// 15.4.4.13
+
+ JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
unsigned nrArgs = exec->argumentCount();
if ((nrArgs) && (length)) {
if (isJSArray(&exec->globalData(), thisObj))
@@ -615,6 +649,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
JSValue function = exec->argument(0);
CallData callData;
@@ -626,7 +663,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
JSArray* resultArray = constructEmptyArray(exec);
unsigned filterIndex = 0;
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
unsigned k = 0;
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
@@ -650,20 +686,19 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
}
for (; k < length && !exec->hadException(); ++k) {
PropertySlot slot(thisObj);
-
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
-
JSValue v = slot.getValue(exec, k);
- MarkedArgumentBuffer eachArguments;
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ MarkedArgumentBuffer eachArguments;
eachArguments.append(v);
eachArguments.append(jsNumber(k));
eachArguments.append(thisObj);
JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
-
if (result.toBoolean(exec))
resultArray->put(exec, filterIndex++, v);
}
@@ -673,6 +708,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
JSValue function = exec->argument(0);
CallData callData;
@@ -682,8 +720,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-
JSArray* resultArray = constructEmptyArray(exec, length);
unsigned k = 0;
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
@@ -706,15 +742,19 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
PropertySlot slot(thisObj);
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
-
JSValue v = slot.getValue(exec, k);
- MarkedArgumentBuffer eachArguments;
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ MarkedArgumentBuffer eachArguments;
eachArguments.append(v);
eachArguments.append(jsNumber(k));
eachArguments.append(thisObj);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
resultArray->put(exec, k, result);
}
@@ -730,6 +770,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
JSValue function = exec->argument(0);
CallData callData;
@@ -741,7 +784,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
JSValue result = jsBoolean(true);
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
unsigned k = 0;
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
@@ -762,18 +804,18 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
}
for (; k < length && !exec->hadException(); ++k) {
PropertySlot slot(thisObj);
-
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
MarkedArgumentBuffer eachArguments;
-
eachArguments.append(slot.getValue(exec, k));
eachArguments.append(jsNumber(k));
eachArguments.append(thisObj);
- bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
if (!predicateResult) {
result = jsBoolean(false);
break;
@@ -786,6 +828,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
JSValue function = exec->argument(0);
CallData callData;
@@ -795,7 +840,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
unsigned k = 0;
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
@@ -823,6 +867,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
eachArguments.append(jsNumber(k));
eachArguments.append(thisObj);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
call(exec, function, callType, callData, applyThis, eachArguments);
}
return JSValue::encode(jsUndefined());
@@ -831,6 +878,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
JSValue function = exec->argument(0);
CallData callData;
@@ -842,7 +892,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
JSValue result = jsBoolean(false);
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
unsigned k = 0;
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
@@ -871,8 +920,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
eachArguments.append(jsNumber(k));
eachArguments.append(thisObj);
- bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
if (predicateResult) {
result = jsBoolean(true);
break;
@@ -884,7 +935,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
-
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
JSValue function = exec->argument(0);
CallData callData;
CallType callType = getCallData(function, callData);
@@ -893,9 +947,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
unsigned i = 0;
JSValue rv;
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (!length && exec->argumentCount() == 1)
return throwVMTypeError(exec);
+
JSArray* array = 0;
if (isJSArray(&exec->globalData(), thisObj))
array = asArray(thisObj);
@@ -937,6 +991,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
for (; i < length && !exec->hadException(); ++i) {
JSValue prop = getProperty(exec, thisObj, i);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
if (!prop)
continue;
@@ -954,7 +1010,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
-
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
JSValue function = exec->argument(0);
CallData callData;
CallType callType = getCallData(function, callData);
@@ -963,9 +1022,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
unsigned i = 0;
JSValue rv;
- unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (!length && exec->argumentCount() == 1)
return throwVMTypeError(exec);
+
JSArray* array = 0;
if (isJSArray(&exec->globalData(), thisObj))
array = asArray(thisObj);
@@ -1006,6 +1065,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
for (; i < length && !exec->hadException(); ++i) {
unsigned idx = length - i - 1;
JSValue prop = getProperty(exec, thisObj, idx);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
if (!prop)
continue;
@@ -1022,13 +1083,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
{
- // JavaScript 1.5 Extension by Mozilla
- // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
+ // 15.4.4.14
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
-
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
- unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
JSValue searchElement = exec->argument(0);
for (; index < length; ++index) {
JSValue e = getProperty(exec, thisObj, index);
@@ -1043,10 +1104,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
{
- // JavaScript 1.6 Extension by Mozilla
- // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
+ // 15.4.4.15
JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
-
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (!length)
return JSValue::encode(jsNumber(-1));
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h
index 42665e3..6dadf51 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.h
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h
@@ -28,17 +28,16 @@ namespace JSC {
class ArrayPrototype : public JSArray {
public:
- explicit ArrayPrototype(JSGlobalObject*, NonNullPassRefPtr<Structure>);
+ explicit ArrayPrototype(JSGlobalObject*, Structure*);
bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
index 0f6a646..df7b7f6 100644
--- a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
+++ b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
@@ -39,7 +39,7 @@ namespace JSC {
, m_object(object)
{
if (!m_object->structure()->isDictionary())
- m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure()));
+ m_object->setStructure(globalData, Structure::toCacheableDictionaryTransition(globalData, m_object->structure()));
}
~BatchedTransitionOptimizer()
diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
index 21ef5bb..a1a4ed4 100644
--- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
@@ -28,7 +28,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
-BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype)
+BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, BooleanPrototype* booleanPrototype)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, booleanPrototype->classInfo()->className))
{
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
@@ -40,7 +40,7 @@ BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalOb
// ECMA 15.6.2
JSObject* constructBoolean(ExecState* exec, const ArgList& args)
{
- BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure());
+ BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure());
obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec)));
return obj;
}
@@ -69,9 +69,9 @@ CallType BooleanConstructor::getCallData(CallData& callData)
return CallTypeHost;
}
-JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue immediateBooleanValue)
+JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSGlobalObject* globalObject, JSValue immediateBooleanValue)
{
- BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure());
+ BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), globalObject->booleanObjectStructure());
obj->setInternalValue(exec->globalData(), immediateBooleanValue);
return obj;
}
diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.h b/Source/JavaScriptCore/runtime/BooleanConstructor.h
index 0f3efa7..fa0d05e 100644
--- a/Source/JavaScriptCore/runtime/BooleanConstructor.h
+++ b/Source/JavaScriptCore/runtime/BooleanConstructor.h
@@ -29,14 +29,14 @@ namespace JSC {
class BooleanConstructor : public InternalFunction {
public:
- BooleanConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, BooleanPrototype*);
+ BooleanConstructor(ExecState*, JSGlobalObject*, Structure*, BooleanPrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
};
- JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue);
+ JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSGlobalObject*, JSValue);
JSObject* constructBoolean(ExecState*, const ArgList&);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp
index 71ff2d2..e24a30a 100644
--- a/Source/JavaScriptCore/runtime/BooleanObject.cpp
+++ b/Source/JavaScriptCore/runtime/BooleanObject.cpp
@@ -25,11 +25,12 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
-const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 };
+const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0 };
-BooleanObject::BooleanObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure)
+BooleanObject::BooleanObject(JSGlobalData& globalData, Structure* structure)
: JSWrapperObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h
index ff10ef6..def44b4 100644
--- a/Source/JavaScriptCore/runtime/BooleanObject.h
+++ b/Source/JavaScriptCore/runtime/BooleanObject.h
@@ -27,14 +27,13 @@ namespace JSC {
class BooleanObject : public JSWrapperObject {
public:
- explicit BooleanObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure>);
+ explicit BooleanObject(JSGlobalData&, Structure*);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
};
@@ -42,7 +41,7 @@ namespace JSC {
inline BooleanObject* asBooleanObject(JSValue value)
{
- ASSERT(asObject(value)->inherits(&BooleanObject::info));
+ ASSERT(asObject(value)->inherits(&BooleanObject::s_info));
return static_cast<BooleanObject*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp
index 54d621c..20990e1 100644
--- a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp
@@ -26,7 +26,6 @@
#include "JSFunction.h"
#include "JSString.h"
#include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
namespace JSC {
@@ -38,13 +37,13 @@ static EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*);
// ECMA 15.6.4
-BooleanPrototype::BooleanPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+BooleanPrototype::BooleanPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure)
: BooleanObject(exec->globalData(), structure)
{
setInternalValue(exec->globalData(), jsBoolean(false));
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
}
@@ -61,7 +60,7 @@ EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec)
if (thisValue == jsBoolean(true))
return JSValue::encode(jsNontrivialString(exec, "true"));
- if (!thisValue.inherits(&BooleanObject::info))
+ if (!thisValue.inherits(&BooleanObject::s_info))
return throwVMTypeError(exec);
if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
@@ -77,7 +76,7 @@ EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec)
if (thisValue.isBoolean())
return JSValue::encode(thisValue);
- if (!thisValue.inherits(&BooleanObject::info))
+ if (!thisValue.inherits(&BooleanObject::s_info))
return throwVMTypeError(exec);
return JSValue::encode(asBooleanObject(thisValue)->internalValue());
diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.h b/Source/JavaScriptCore/runtime/BooleanPrototype.h
index ddadc43..5ccbd2b 100644
--- a/Source/JavaScriptCore/runtime/BooleanPrototype.h
+++ b/Source/JavaScriptCore/runtime/BooleanPrototype.h
@@ -27,7 +27,7 @@ namespace JSC {
class BooleanPrototype : public BooleanObject {
public:
- BooleanPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ BooleanPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/CallData.h b/Source/JavaScriptCore/runtime/CallData.h
index 32e1094..b138f54 100644
--- a/Source/JavaScriptCore/runtime/CallData.h
+++ b/Source/JavaScriptCore/runtime/CallData.h
@@ -30,7 +30,6 @@
#define CallData_h
#include "JSValue.h"
-#include "NativeFunctionWrapper.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
index 6587a8f..478a639 100644
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -39,25 +39,18 @@
macro(compile) \
macro(configurable) \
macro(constructor) \
- macro(create) \
- macro(defineProperty) \
- macro(defineProperties) \
macro(enumerable) \
macro(eval) \
macro(exec) \
macro(fromCharCode) \
macro(global) \
macro(get) \
- macro(getPrototypeOf) \
- macro(getOwnPropertyDescriptor) \
- macro(getOwnPropertyNames) \
macro(hasOwnProperty) \
macro(ignoreCase) \
macro(index) \
macro(input) \
macro(isArray) \
macro(isPrototypeOf) \
- macro(keys) \
macro(length) \
macro(message) \
macro(multiline) \
diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp
index eeb8b0d..ac19705 100644
--- a/Source/JavaScriptCore/runtime/Completion.cpp
+++ b/Source/JavaScriptCore/runtime/Completion.cpp
@@ -39,7 +39,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
JSLock lock(exec);
ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
- RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+ ProgramExecutable* program = ProgramExecutable::create(exec, source);
JSObject* error = program->checkSyntax(exec);
if (error)
return Completion(Throw, error);
@@ -47,19 +47,21 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
return Completion(Normal);
}
-Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
+Completion evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode& source, JSValue thisValue)
{
JSLock lock(exec);
ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
- RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
- JSObject* error = program->compile(exec, scopeChain.node());
- if (error)
- return Completion(Throw, error);
+ ProgramExecutable* program = ProgramExecutable::create(exec, source);
+ if (!program) {
+ JSValue exception = exec->globalData().exception;
+ exec->globalData().exception = JSValue();
+ return Completion(Throw, exception);
+ }
JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
- JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj);
+ JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj);
if (exec->hadException()) {
JSValue exception = exec->exception();
diff --git a/Source/JavaScriptCore/runtime/Completion.h b/Source/JavaScriptCore/runtime/Completion.h
index 63b315e..1dd25fd 100644
--- a/Source/JavaScriptCore/runtime/Completion.h
+++ b/Source/JavaScriptCore/runtime/Completion.h
@@ -28,7 +28,7 @@
namespace JSC {
class ExecState;
- class ScopeChain;
+ class ScopeChainNode;
class SourceCode;
enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted, Terminated };
@@ -56,7 +56,7 @@ namespace JSC {
};
Completion checkSyntax(ExecState*, const SourceCode&);
- Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValue thisValue = JSValue());
+ Completion evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue());
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.h b/Source/JavaScriptCore/runtime/ConservativeSet.h
deleted file mode 100644
index e7c2c4a..0000000
--- a/Source/JavaScriptCore/runtime/ConservativeSet.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
- * 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 ConservativeSet_h
-#define ConservativeSet_h
-
-#include "Heap.h"
-#include "MarkStack.h"
-#include <wtf/Vector.h>
-
-namespace JSC {
-
-class JSCell;
-
-class ConservativeSet {
-public:
- ConservativeSet(Heap*);
- ~ConservativeSet();
-
- void add(void* begin, void* end);
- void mark(MarkStack&);
-
-private:
- static const size_t inlineCapacity = 128;
- static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*);
-
- void grow();
-
- Heap* m_heap;
- DeprecatedPtr<JSCell>* m_set;
- size_t m_size;
- size_t m_capacity;
- DeprecatedPtr<JSCell> m_inlineSet[inlineCapacity];
-};
-
-inline ConservativeSet::ConservativeSet(Heap* heap)
- : m_heap(heap)
- , m_set(m_inlineSet)
- , m_size(0)
- , m_capacity(inlineCapacity)
-{
-}
-
-inline ConservativeSet::~ConservativeSet()
-{
- if (m_set != m_inlineSet)
- OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(DeprecatedPtr<JSCell>*));
-}
-
-inline void ConservativeSet::mark(MarkStack& markStack)
-{
- for (size_t i = 0; i < m_size; ++i)
- markStack.append(&m_set[i]);
-}
-
-} // namespace JSC
-
-#endif // ConservativeSet_h
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp
index f1f3956..9bbb688 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp
@@ -30,7 +30,6 @@
#include "JSString.h"
#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
#include <math.h>
#include <time.h>
#include <wtf/DateMath.h>
@@ -58,20 +57,20 @@ static EncodedJSValue JSC_HOST_CALL dateParse(ExecState*);
static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*);
static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState*);
-DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype)
+DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure, DatePrototype* datePrototype)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, datePrototype->classInfo()->className))
{
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().now, dateNow), DontEnum);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
+ putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
}
// ECMA 15.9.3
-JSObject* constructDate(ExecState* exec, const ArgList& args)
+JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
{
int numArgs = args.size();
@@ -80,7 +79,7 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
if (numArgs == 0) // new Date() ECMA 15.9.3.3
value = jsCurrentTime();
else if (numArgs == 1) {
- if (args.at(0).inherits(&DateInstance::info))
+ if (args.at(0).inherits(&DateInstance::s_info))
value = asDateInstance(args.at(0))->internalNumber();
else {
JSValue primitive = args.at(0).toPrimitive(exec);
@@ -122,13 +121,13 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
}
}
- return new (exec) DateInstance(exec, value);
+ return new (exec) DateInstance(exec, globalObject->dateStructure(), value);
}
static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec)
{
ArgList args(exec);
- return JSValue::encode(constructDate(exec, args));
+ return JSValue::encode(constructDate(exec, asInternalFunction(exec->callee())->globalObject(), args));
}
ConstructType DateConstructor::getConstructData(ConstructData& constructData)
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.h b/Source/JavaScriptCore/runtime/DateConstructor.h
index c8ca456..23a0311 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.h
+++ b/Source/JavaScriptCore/runtime/DateConstructor.h
@@ -29,14 +29,14 @@ namespace JSC {
class DateConstructor : public InternalFunction {
public:
- DateConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
+ DateConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure, DatePrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
};
- JSObject* constructDate(ExecState*, const ArgList&);
+ JSObject* constructDate(ExecState*, JSGlobalObject*, const ArgList&);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp
index d4b8232..1418876 100644
--- a/Source/JavaScriptCore/runtime/DateConversion.cpp
+++ b/Source/JavaScriptCore/runtime/DateConversion.cpp
@@ -44,6 +44,8 @@
#include "DateConversion.h"
#include "CallFrame.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
#include "UString.h"
#include <wtf/DateMath.h>
#include <wtf/StringExtras.h>
diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp
index 44e8b7d..d8ca072 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.cpp
+++ b/Source/JavaScriptCore/runtime/DateInstance.cpp
@@ -32,23 +32,19 @@ using namespace WTF;
namespace JSC {
-const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
+const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0};
-DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure)
+DateInstance::DateInstance(ExecState* exec, Structure* structure)
: JSWrapperObject(exec->globalData(), structure)
{
+ ASSERT(inherits(&s_info));
setInternalValue(exec->globalData(), jsNaN());
}
-DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time)
+DateInstance::DateInstance(ExecState* exec, Structure* structure, double time)
: JSWrapperObject(exec->globalData(), structure)
{
- setInternalValue(exec->globalData(), jsNumber(timeClip(time)));
-}
-
-DateInstance::DateInstance(ExecState* exec, double time)
- : JSWrapperObject(exec->globalData(), exec->lexicalGlobalObject()->dateStructure())
-{
+ ASSERT(inherits(&s_info));
setInternalValue(exec->globalData(), jsNumber(timeClip(time)));
}
diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h
index 77d46de..6195c85 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.h
+++ b/Source/JavaScriptCore/runtime/DateInstance.h
@@ -31,13 +31,12 @@ namespace JSC {
class DateInstance : public JSWrapperObject {
public:
- DateInstance(ExecState*, double);
- DateInstance(ExecState*, NonNullPassRefPtr<Structure>, double);
- explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>);
+ DateInstance(ExecState*, Structure*, double);
+ explicit DateInstance(ExecState*, Structure*);
double internalNumber() const { return internalValue().uncheckedGetNumber(); }
- static JS_EXPORTDATA const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo s_info;
const GregorianDateTime* gregorianDateTime(ExecState* exec) const
{
@@ -53,18 +52,14 @@ namespace JSC {
return calculateGregorianDateTimeUTC(exec);
}
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
- protected:
- static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags;
-
private:
const GregorianDateTime* calculateGregorianDateTime(ExecState*) const;
const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const;
- virtual const ClassInfo* classInfo() const { return &info; }
mutable RefPtr<DateInstanceData> m_data;
};
@@ -73,7 +68,7 @@ namespace JSC {
inline DateInstance* asDateInstance(JSValue value)
{
- ASSERT(asObject(value)->inherits(&DateInstance::info));
+ ASSERT(asObject(value)->inherits(&DateInstance::s_info));
return static_cast<DateInstance*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp
index 5838b60..444fa98 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp
@@ -130,7 +130,7 @@ enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
#if PLATFORM(MAC)
// FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
-// Instead we should consider using this whenever PLATFORM(CF) is true.
+// Instead we should consider using this whenever USE(CF) is true.
static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
{
@@ -374,7 +374,7 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms
return ok;
}
-const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
+const ClassInfo DatePrototype::s_info = {"Date", &DateInstance::s_info, 0, ExecState::dateTable};
/* Source for DatePrototype.lut.h
@begin dateTable
@@ -429,9 +429,11 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState
// ECMA 15.9.4
-DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
+DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
: DateInstance(exec, structure)
{
+ ASSERT(inherits(&s_info));
+
// The constructor will be added later, after DateConstructor has been built.
putAnonymousValue(exec->globalData(), 0, globalObject);
}
@@ -452,7 +454,7 @@ bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier&
EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -470,7 +472,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -488,7 +490,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -507,7 +509,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -523,7 +525,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -539,7 +541,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -549,7 +551,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -559,7 +561,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -569,7 +571,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
return JSValue::encode(asDateInstance(thisValue)->internalValue());
@@ -578,7 +580,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -592,7 +594,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -606,7 +608,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -624,7 +626,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -638,7 +640,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -652,7 +654,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -666,7 +668,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -680,7 +682,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -694,7 +696,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -708,7 +710,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -722,7 +724,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -736,7 +738,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -750,7 +752,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -764,7 +766,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -778,7 +780,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -792,7 +794,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -808,7 +810,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -824,7 +826,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -838,7 +840,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -852,7 +854,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -889,7 +891,7 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -1013,7 +1015,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -1054,7 +1056,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::s_info))
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
diff --git a/Source/JavaScriptCore/runtime/DatePrototype.h b/Source/JavaScriptCore/runtime/DatePrototype.h
index e3672aa..2e1030d 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.h
+++ b/Source/JavaScriptCore/runtime/DatePrototype.h
@@ -29,22 +29,23 @@ namespace JSC {
class DatePrototype : public DateInstance {
public:
- DatePrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>);
+ DatePrototype(ExecState*, JSGlobalObject*, Structure*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags;
+ COMPILE_ASSERT(!DateInstance::AnonymousSlotCount, DatePrototype_stomps_on_your_anonymous_slot);
+ static const unsigned AnonymousSlotCount = 1;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
index b84f5ea..7eda19f 100644
--- a/Source/JavaScriptCore/runtime/Error.cpp
+++ b/Source/JavaScriptCore/runtime/Error.cpp
@@ -167,7 +167,7 @@ JSObject* throwSyntaxError(ExecState* exec)
class StrictModeTypeErrorFunction : public InternalFunction {
public:
- StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& message)
+ StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& message)
: InternalFunction(&exec->globalData(), globalObject, structure, exec->globalData().propertyNames->emptyIdentifier)
, m_message(message)
{
diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
index 2e53b95..df112dd 100644
--- a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
@@ -29,7 +29,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
-ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, ErrorPrototype* errorPrototype)
+ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ErrorPrototype* errorPrototype)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, errorPrototype->classInfo()->className))
{
// ECMA 15.11.3.1 Error.prototype
@@ -42,7 +42,7 @@ ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject
static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState* exec)
{
JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
- Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure();
+ Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure();
return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
}
@@ -55,7 +55,7 @@ ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec)
{
JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
- Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure();
+ Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure();
return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
}
diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.h b/Source/JavaScriptCore/runtime/ErrorConstructor.h
index 3d0d706..ceec005 100644
--- a/Source/JavaScriptCore/runtime/ErrorConstructor.h
+++ b/Source/JavaScriptCore/runtime/ErrorConstructor.h
@@ -30,7 +30,7 @@ namespace JSC {
class ErrorConstructor : public InternalFunction {
public:
- ErrorConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, ErrorPrototype*);
+ ErrorConstructor(ExecState*, JSGlobalObject*, Structure*, ErrorPrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.cpp b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
index a6208d5..ed95ba4 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
@@ -23,28 +23,30 @@
namespace JSC {
-const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
+const ClassInfo ErrorInstance::s_info = { "Error", &JSNonFinalObject::s_info, 0, 0 };
-ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure)
+ : JSNonFinalObject(*globalData, structure)
, m_appendSourceToMessage(false)
{
+ ASSERT(inherits(&s_info));
putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, ""));
}
-ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const UString& message)
- : JSObject(structure)
+ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure, const UString& message)
+ : JSNonFinalObject(*globalData, structure)
, m_appendSourceToMessage(false)
{
+ ASSERT(inherits(&s_info));
putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
}
-ErrorInstance* ErrorInstance::create(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const UString& message)
+ErrorInstance* ErrorInstance::create(JSGlobalData* globalData, Structure* structure, const UString& message)
{
return new (globalData) ErrorInstance(globalData, structure, message);
}
-ErrorInstance* ErrorInstance::create(ExecState* exec, NonNullPassRefPtr<Structure> structure, JSValue message)
+ErrorInstance* ErrorInstance::create(ExecState* exec, Structure* structure, JSValue message)
{
if (message.isUndefined())
return new (exec) ErrorInstance(&exec->globalData(), structure);
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h
index b3bebec..afcf158 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.h
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.h
@@ -25,14 +25,17 @@
namespace JSC {
- class ErrorInstance : public JSObject {
+ class ErrorInstance : public JSNonFinalObject {
public:
+ static const ClassInfo s_info;
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
- static ErrorInstance* create(JSGlobalData*, NonNullPassRefPtr<Structure>, const UString&);
- static ErrorInstance* create(ExecState* exec, NonNullPassRefPtr<Structure>, JSValue message);
+ static ErrorInstance* create(JSGlobalData*, Structure*, const UString&);
+ static ErrorInstance* create(ExecState*, Structure*, JSValue message);
bool appendSourceToMessage() { return m_appendSourceToMessage; }
@@ -42,8 +45,8 @@ namespace JSC {
virtual bool isErrorInstance() const { return true; }
protected:
- explicit ErrorInstance(JSGlobalData*, NonNullPassRefPtr<Structure>);
- explicit ErrorInstance(JSGlobalData*, NonNullPassRefPtr<Structure>, const UString&);
+ explicit ErrorInstance(JSGlobalData*, Structure*);
+ explicit ErrorInstance(JSGlobalData*, Structure*, const UString&);
bool m_appendSourceToMessage;
};
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
index b4e0a7c..a57e947 100644
--- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -25,7 +25,6 @@
#include "JSString.h"
#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
#include "StringRecursionChecker.h"
#include "UString.h"
@@ -36,13 +35,13 @@ ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
static EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*);
// ECMA 15.9.4
-ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure)
: ErrorInstance(&exec->globalData(), structure)
{
// The constructor will be added later in ErrorConstructor's constructor
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
}
EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.h b/Source/JavaScriptCore/runtime/ErrorPrototype.h
index fce2742..9437d3a 100644
--- a/Source/JavaScriptCore/runtime/ErrorPrototype.h
+++ b/Source/JavaScriptCore/runtime/ErrorPrototype.h
@@ -29,7 +29,7 @@ namespace JSC {
class ErrorPrototype : public ErrorInstance {
public:
- ErrorPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ ErrorPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
index 4a58800..1d74315 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -41,10 +41,10 @@
namespace JSC {
-class InterruptedExecutionError : public JSObject {
+class InterruptedExecutionError : public JSNonFinalObject {
public:
InterruptedExecutionError(JSGlobalData* globalData)
- : JSObject(globalData->interruptedExecutionErrorStructure)
+ : JSNonFinalObject(*globalData, globalData->interruptedExecutionErrorStructure.get())
{
}
@@ -58,10 +58,10 @@ JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
return new (globalData) InterruptedExecutionError(globalData);
}
-class TerminatedExecutionError : public JSObject {
+class TerminatedExecutionError : public JSNonFinalObject {
public:
TerminatedExecutionError(JSGlobalData* globalData)
- : JSObject(globalData->terminatedExecutionErrorStructure)
+ : JSNonFinalObject(*globalData, globalData->terminatedExecutionErrorStructure.get())
{
}
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 25c551b..fa14ad5 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -33,20 +33,25 @@
#include "UStringBuilder.h"
#include "Vector.h"
+#if ENABLE(DFG_JIT)
+#include "DFGByteCodeParser.h"
+#include "DFGJITCompiler.h"
+#endif
+
namespace JSC {
-#if ENABLE(JIT)
+const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0 };
+
+const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0 };
+
NativeExecutable::~NativeExecutable()
{
}
-#endif
-VPtrHackExecutable::~VPtrHackExecutable()
-{
-}
+const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0 };
EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
- : ScriptExecutable(exec, source, inStrictContext)
+ : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext)
{
}
@@ -54,8 +59,10 @@ EvalExecutable::~EvalExecutable()
{
}
+const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0 };
+
ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
- : ScriptExecutable(exec, source, false)
+ : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false)
{
}
@@ -63,8 +70,10 @@ ProgramExecutable::~ProgramExecutable()
{
}
+const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0 };
+
FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
- : ScriptExecutable(globalData, source, inStrictContext)
+ : ScriptExecutable(globalData->functionExecutableStructure.get(), globalData, source, inStrictContext)
, m_numCapturedVariables(0)
, m_forceUsesArguments(forceUsesArguments)
, m_parameters(parameters)
@@ -76,7 +85,7 @@ FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifie
}
FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
- : ScriptExecutable(exec, source, inStrictContext)
+ : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
, m_numCapturedVariables(0)
, m_forceUsesArguments(forceUsesArguments)
, m_parameters(parameters)
@@ -87,9 +96,6 @@ FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name,
m_lastLine = lastLine;
}
-FunctionExecutable::~FunctionExecutable()
-{
-}
JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
{
@@ -103,12 +109,11 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
}
recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
- ScopeChain scopeChain(scopeChainNode);
- JSGlobalObject* globalObject = scopeChain.globalObject();
+ JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
ASSERT(!m_evalCodeBlock);
- m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get())));
+ m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChainNode->localDepth()));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChainNode, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get())));
if ((exception = generator->generate())) {
m_evalCodeBlock.clear();
evalNode->destroyData();
@@ -130,6 +135,13 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
return 0;
}
+void EvalExecutable::markChildren(MarkStack& markStack)
+{
+ ScriptExecutable::markChildren(markStack);
+ if (m_evalCodeBlock)
+ m_evalCodeBlock->markAggregate(markStack);
+}
+
JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
{
JSObject* exception = 0;
@@ -156,11 +168,10 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
}
recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
- ScopeChain scopeChain(scopeChainNode);
- JSGlobalObject* globalObject = scopeChain.globalObject();
+ JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock.get())));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scopeChainNode, &globalObject->symbolTable(), m_programCodeBlock.get())));
if ((exception = generator->generate())) {
m_programCodeBlock.clear();
programNode->destroyData();
@@ -182,6 +193,41 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
return 0;
}
+#if ENABLE(JIT)
+static bool tryDFGCompile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+{
+#if ENABLE(DFG_JIT)
+#if ENABLE(DFG_JIT_RESTRICTIONS)
+ // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
+ // FIXME: temporarily disable property accesses until we fix regressions.
+ if (codeBlock->numberOfJumpTargets() || codeBlock->numberOfStructureStubInfos())
+ return false;
+#endif
+
+ DFG::Graph dfg;
+ if (!parse(dfg, globalData, codeBlock))
+ return false;
+
+ DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
+ dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck);
+ return true;
+#else
+ UNUSED_PARAM(globalData);
+ UNUSED_PARAM(codeBlock);
+ UNUSED_PARAM(jitCode);
+ UNUSED_PARAM(jitCodeWithArityCheck);
+ return false;
+#endif
+}
+#endif
+
+void ProgramExecutable::markChildren(MarkStack& markStack)
+{
+ ScriptExecutable::markChildren(markStack);
+ if (m_programCodeBlock)
+ m_programCodeBlock->markAggregate(markStack);
+}
+
JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
{
JSObject* exception = 0;
@@ -196,12 +242,11 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
body->finishParsing(m_parameters, m_name);
recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
- ScopeChain scopeChain(scopeChainNode);
- JSGlobalObject* globalObject = scopeChain.globalObject();
+ JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
ASSERT(!m_codeBlockForCall);
m_codeBlockForCall = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), false));
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall.get())));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChainNode, m_codeBlockForCall->symbolTable(), m_codeBlockForCall.get())));
if ((exception = generator->generate())) {
m_codeBlockForCall.clear();
body->destroyData();
@@ -217,7 +262,10 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
#if ENABLE(JIT)
if (exec->globalData().canUseJIT()) {
- m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
+ bool dfgCompiled = tryDFGCompile(&exec->globalData(), m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
+ if (!dfgCompiled)
+ m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
+
#if !ENABLE(OPCODE_SAMPLING)
if (!BytecodeGenerator::dumpsGeneratedCode())
m_codeBlockForCall->discardBytecode();
@@ -242,12 +290,11 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
body->finishParsing(m_parameters, m_name);
recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
- ScopeChain scopeChain(scopeChainNode);
- JSGlobalObject* globalObject = scopeChain.globalObject();
+ JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
ASSERT(!m_codeBlockForConstruct);
m_codeBlockForConstruct = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), true));
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct.get())));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChainNode, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct.get())));
if ((exception = generator->generate())) {
m_codeBlockForConstruct.clear();
body->destroyData();
@@ -274,8 +321,9 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
return 0;
}
-void FunctionExecutable::markAggregate(MarkStack& markStack)
+void FunctionExecutable::markChildren(MarkStack& markStack)
{
+ ScriptExecutable::markChildren(markStack);
if (m_codeBlockForCall)
m_codeBlockForCall->markAggregate(markStack);
if (m_codeBlockForConstruct)
@@ -294,7 +342,7 @@ void FunctionExecutable::discardCode()
#endif
}
-PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
+FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
{
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception);
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 544e487..fbe33cf 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -44,7 +44,7 @@ namespace JSC {
struct ExceptionInfo;
- class ExecutableBase : public RefCounted<ExecutableBase> {
+ class ExecutableBase : public JSCell {
friend class JIT;
protected:
@@ -52,21 +52,24 @@ namespace JSC {
static const int NUM_PARAMETERS_NOT_COMPILED = -1;
public:
- ExecutableBase(int numParameters)
- : m_numParametersForCall(numParameters)
+ ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters)
+ : JSCell(globalData, structure)
+ , m_numParametersForCall(numParameters)
, m_numParametersForConstruct(numParameters)
{
}
- virtual ~ExecutableBase() {}
-
bool isHostFunction() const
{
ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
}
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
+
protected:
+ static const unsigned StructureFlags = 0;
+ static const ClassInfo s_info;
int m_numParametersForCall;
int m_numParametersForConstruct;
@@ -92,24 +95,33 @@ namespace JSC {
#endif
};
-#if ENABLE(JIT)
class NativeExecutable : public ExecutableBase {
friend class JIT;
public:
- static PassRefPtr<NativeExecutable> create(MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor)
+#if ENABLE(JIT)
+ static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor)
{
if (!callThunk)
- return adoptRef(new NativeExecutable(JITCode(), function, JITCode(), constructor));
- return adoptRef(new NativeExecutable(JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor));
+ return new (&globalData) NativeExecutable(globalData, JITCode(), function, JITCode(), constructor);
+ return new (&globalData) NativeExecutable(globalData, JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor);
}
+#else
+ static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
+ {
+ return new (&globalData) NativeExecutable(globalData, function, constructor);
+ }
+#endif
~NativeExecutable();
NativeFunction function() { return m_function; }
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(LeafType, StructureFlags), AnonymousSlotCount, &s_info); }
+
private:
- NativeExecutable(JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor)
- : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+#if ENABLE(JIT)
+ NativeExecutable(JSGlobalData& globalData, JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor)
+ : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
, m_function(function)
, m_constructor(constructor)
{
@@ -118,28 +130,26 @@ namespace JSC {
m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
}
+#else
+ NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
+ : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
+ , m_function(function)
+ , m_constructor(constructor)
+ {
+ }
+#endif
NativeFunction m_function;
// Probably should be a NativeConstructor, but this will currently require rewriting the JIT
// trampoline. It may be easier to make NativeFunction be passed 'this' as a part of the ArgList.
NativeFunction m_constructor;
- };
-#endif
-
- class VPtrHackExecutable : public ExecutableBase {
- public:
- VPtrHackExecutable()
- : ExecutableBase(NUM_PARAMETERS_IS_HOST)
- {
- }
-
- ~VPtrHackExecutable();
+ static const ClassInfo s_info;
};
class ScriptExecutable : public ExecutableBase {
public:
- ScriptExecutable(JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext)
- : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+ ScriptExecutable(Structure* structure, JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext)
+ : ExecutableBase(*globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
, m_features(isInStrictContext ? StrictModeFeature : 0)
{
@@ -152,8 +162,8 @@ namespace JSC {
#endif
}
- ScriptExecutable(ExecState* exec, const SourceCode& source, bool isInStrictContext)
- : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+ ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
+ : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
, m_features(isInStrictContext ? StrictModeFeature : 0)
{
@@ -200,6 +210,7 @@ namespace JSC {
JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+ ASSERT(exec->globalData().dynamicGlobalObject);
JSObject* error = 0;
if (!m_evalCodeBlock)
error = compileInternal(exec, scopeChainNode);
@@ -213,7 +224,7 @@ namespace JSC {
return *m_evalCodeBlock;
}
- static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return adoptRef(new EvalExecutable(exec, source, isInStrictContext)); }
+ static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return new (exec) EvalExecutable(exec, source, isInStrictContext); }
#if ENABLE(JIT)
JITCode& generatedJITCode()
@@ -221,26 +232,31 @@ namespace JSC {
return generatedJITCodeForCall();
}
#endif
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
private:
+ static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags;
+ static const ClassInfo s_info;
EvalExecutable(ExecState*, const SourceCode&, bool);
JSObject* compileInternal(ExecState*, ScopeChainNode*);
+ virtual void markChildren(MarkStack&);
OwnPtr<EvalCodeBlock> m_evalCodeBlock;
};
class ProgramExecutable : public ScriptExecutable {
public:
- static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source)
+ static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
{
- return adoptRef(new ProgramExecutable(exec, source));
+ return new (exec) ProgramExecutable(exec, source);
}
~ProgramExecutable();
JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+ ASSERT(exec->globalData().dynamicGlobalObject);
JSObject* error = 0;
if (!m_programCodeBlock)
error = compileInternal(exec, scopeChainNode);
@@ -262,11 +278,16 @@ namespace JSC {
return generatedJITCodeForCall();
}
#endif
+
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
private:
+ static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags;
+ static const ClassInfo s_info;
ProgramExecutable(ExecState*, const SourceCode&);
JSObject* compileInternal(ExecState*, ScopeChainNode*);
+ virtual void markChildren(MarkStack&);
OwnPtr<ProgramCodeBlock> m_programCodeBlock;
};
@@ -274,18 +295,16 @@ namespace JSC {
class FunctionExecutable : public ScriptExecutable {
friend class JIT;
public:
- static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+ static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
{
- return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine));
+ return new (exec) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
}
- static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+ static FunctionExecutable* create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
{
- return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine));
+ return new (globalData) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
}
- ~FunctionExecutable();
-
JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
{
return new (exec) JSFunction(exec, this, scopeChain);
@@ -304,6 +323,7 @@ namespace JSC {
JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+ ASSERT(exec->globalData().dynamicGlobalObject);
JSObject* error = 0;
if (!m_codeBlockForCall)
error = compileForCallInternal(exec, scopeChainNode);
@@ -324,6 +344,7 @@ namespace JSC {
JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+ ASSERT(exec->globalData().dynamicGlobalObject);
JSObject* error = 0;
if (!m_codeBlockForConstruct)
error = compileForConstructInternal(exec, scopeChainNode);
@@ -349,8 +370,9 @@ namespace JSC {
SharedSymbolTable* symbolTable() const { return m_symbolTable; }
void discardCode();
- void markAggregate(MarkStack&);
- static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+ void markChildren(MarkStack&);
+ static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
private:
FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
@@ -358,7 +380,9 @@ namespace JSC {
JSObject* compileForCallInternal(ExecState*, ScopeChainNode*);
JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*);
-
+
+ static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags;
+ static const ClassInfo s_info;
unsigned m_numCapturedVariables : 31;
bool m_forceUsesArguments : 1;
@@ -398,13 +422,11 @@ namespace JSC {
return m_executable->isHostFunction();
}
-#if ENABLE(JIT)
inline NativeFunction JSFunction::nativeFunction()
{
ASSERT(isHostFunction());
return static_cast<NativeExecutable*>(m_executable.get())->function();
}
-#endif
}
#endif
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
index 933b11f..9e7d8d5 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -37,7 +37,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
-FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
+FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, FunctionPrototype* functionPrototype)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, functionPrototype->classInfo()->className))
{
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
@@ -49,7 +49,7 @@ FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* global
static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec)
{
ArgList args(exec);
- return JSValue::encode(constructFunction(exec, args));
+ return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
}
ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
@@ -61,7 +61,7 @@ ConstructType FunctionConstructor::getConstructData(ConstructData& constructData
static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec)
{
ArgList args(exec);
- return JSValue::encode(constructFunction(exec, args));
+ return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
}
// ECMA 15.3.1 The Function Constructor Called as a Function
@@ -72,7 +72,7 @@ CallType FunctionConstructor::getCallData(CallData& callData)
}
// ECMA 15.3.2 The Function Constructor
-JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
+JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
{
// Functions need to have a space following the opening { due to for web compatibility
// see https://bugs.webkit.org/show_bug.cgi?id=24350
@@ -96,24 +96,23 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
program = builder.toUString();
}
- JSGlobalObject* globalObject = exec->lexicalGlobalObject();
JSGlobalData& globalData = globalObject->globalData();
SourceCode source = makeSource(program, sourceURL, lineNumber);
JSObject* exception = 0;
- RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
+ FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
if (!function) {
ASSERT(exception);
return throwError(exec, exception);
}
- ScopeChain scopeChain(globalObject, &globalData, globalObject, exec->globalThisValue());
- return new (exec) JSFunction(exec, function, scopeChain.node());
+ ScopeChainNode* scopeChain = new (exec) ScopeChainNode(0, globalObject, &globalData, globalObject, exec->globalThisValue());
+ return new (exec) JSFunction(exec, function, scopeChain);
}
// ECMA 15.3.2 The Function Constructor
-JSObject* constructFunction(ExecState* exec, const ArgList& args)
+JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
{
- return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);
+ return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), UString(), 1);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.h b/Source/JavaScriptCore/runtime/FunctionConstructor.h
index 6af4861..31a04c9 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.h
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.h
@@ -29,15 +29,15 @@ namespace JSC {
class FunctionConstructor : public InternalFunction {
public:
- FunctionConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, FunctionPrototype*);
+ FunctionConstructor(ExecState*, JSGlobalObject*, Structure*, FunctionPrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
};
- JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
- JSObject* constructFunction(ExecState*, const ArgList&);
+ JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+ JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
index e651538..e2a4941 100644
--- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -28,7 +28,6 @@
#include "JSStringBuilder.h"
#include "Interpreter.h"
#include "Lexer.h"
-#include "PrototypeFunction.h"
namespace JSC {
@@ -38,18 +37,18 @@ static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*);
-FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
+FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
: InternalFunction(&exec->globalData(), globalObject, structure, exec->propertyNames().nullIdentifier)
{
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
}
-void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction)
+void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction)
{
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
- *applyFunction = new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
+ *applyFunction = new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply);
putDirectFunctionWithoutTransition(exec, *applyFunction, DontEnum);
- *callFunction = new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall);
+ *callFunction = new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().call, functionProtoFuncCall);
putDirectFunctionWithoutTransition(exec, *callFunction, DontEnum);
}
@@ -86,7 +85,7 @@ static inline void insertSemicolonIfNeeded(UString& functionBody)
EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (thisValue.inherits(&JSFunction::info)) {
+ if (thisValue.inherits(&JSFunction::s_info)) {
JSFunction* function = asFunction(thisValue);
if (function->isHostFunction())
return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}"));
@@ -96,7 +95,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString));
}
- if (thisValue.inherits(&InternalFunction::info)) {
+ if (thisValue.inherits(&InternalFunction::s_info)) {
InternalFunction* function = asInternalFunction(thisValue);
return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}"));
}
@@ -118,11 +117,11 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec)
if (!array.isUndefinedOrNull()) {
if (!array.isObject())
return throwVMTypeError(exec);
- if (asObject(array)->classInfo() == &Arguments::info)
+ if (asObject(array)->classInfo() == &Arguments::s_info)
asArguments(array)->fillArgList(exec, applyArgs);
else if (isJSArray(&exec->globalData(), array))
asArray(array)->fillArgList(exec, applyArgs);
- else if (asObject(array)->inherits(&JSArray::info)) {
+ else if (asObject(array)->inherits(&JSArray::s_info)) {
unsigned length = asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
for (unsigned i = 0; i < length; ++i)
applyArgs.append(asArray(array)->get(exec, i));
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.h b/Source/JavaScriptCore/runtime/FunctionPrototype.h
index 5661194..ab708dd 100644
--- a/Source/JavaScriptCore/runtime/FunctionPrototype.h
+++ b/Source/JavaScriptCore/runtime/FunctionPrototype.h
@@ -25,16 +25,14 @@
namespace JSC {
- class PrototypeFunction;
-
class FunctionPrototype : public InternalFunction {
public:
- FunctionPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>);
- void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction);
+ FunctionPrototype(ExecState*, JSGlobalObject*, Structure*);
+ void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction);
- static PassRefPtr<Structure> createStructure(JSValue proto)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
private:
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
index 161abfb..308d245 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
@@ -34,7 +34,7 @@ namespace JSC {
struct DefaultGCActivityCallbackPlatformData {
};
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap*)
{
}
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.h b/Source/JavaScriptCore/runtime/GCActivityCallback.h
index 9b6ef04..eabb4cc 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallback.h
+++ b/Source/JavaScriptCore/runtime/GCActivityCallback.h
@@ -32,7 +32,7 @@
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
-#if PLATFORM(CF)
+#if USE(CF)
#include <CoreFoundation/CoreFoundation.h>
#endif
@@ -62,7 +62,7 @@ public:
void operator()();
void synchronize();
-#if PLATFORM(CF)
+#if USE(CF)
protected:
DefaultGCActivityCallback(Heap*, CFRunLoopRef);
void commonConstructor(Heap*, CFRunLoopRef);
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
index 211c423..2e878bf 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
@@ -33,10 +33,12 @@
#include "Heap.h"
#include "JSGlobalData.h"
#include "JSLock.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
#include <wtf/RetainPtr.h>
#include <wtf/WTFThreadData.h>
-#if !PLATFORM(CF)
+#if !USE(CF)
#error "This file should only be used on CF platforms."
#endif
diff --git a/Source/JavaScriptCore/runtime/GCHandle.cpp b/Source/JavaScriptCore/runtime/GCHandle.cpp
deleted file mode 100644
index 297de38..0000000
--- a/Source/JavaScriptCore/runtime/GCHandle.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
- */
-
-#include "config.h"
-#include "GCHandle.h"
-
-namespace JSC {
-
-WeakGCHandlePool* WeakGCHandle::pool()
-{
- uintptr_t pool = (reinterpret_cast<uintptr_t>(this) & WeakGCHandlePool::poolMask);
- return reinterpret_cast<WeakGCHandlePool*>(pool);
-}
-
-WeakGCHandlePool::WeakGCHandlePool()
-{
- ASSERT(sizeof(WeakGCHandlePool) <= WeakGCHandlePool::poolSize);
- m_entriesSize = 0;
- m_initialAlloc = 1;
- m_entries[0].setNextInFreeList(0);
-}
-
-WeakGCHandle* WeakGCHandlePool::allocate(JSCell* cell)
-{
- ASSERT(cell);
- ASSERT(m_entries[0].isNext());
- unsigned freeList = m_entries[0].getNextInFreeList();
- ASSERT(freeList < WeakGCHandlePool::numPoolEntries);
- ASSERT(m_entriesSize < WeakGCHandlePool::numPoolEntries);
-
- if (m_entriesSize == WeakGCHandlePool::numPoolEntries - 1)
- return 0;
-
- if (freeList) {
- unsigned i = freeList;
- freeList = m_entries[i].getNextInFreeList();
- m_entries[i].set(cell);
- m_entries[0].setNextInFreeList(freeList);
- ++m_entriesSize;
- return &m_entries[i];
- }
-
- ASSERT(m_initialAlloc < WeakGCHandlePool::numPoolEntries);
-
- unsigned i = m_initialAlloc;
- ++m_initialAlloc;
- m_entries[i].set(cell);
- ++m_entriesSize;
- return &m_entries[i];
-
-}
-
-void WeakGCHandlePool::free(WeakGCHandle* handle)
-{
- ASSERT(handle->pool() == this);
- ASSERT(m_entries[0].isNext());
- unsigned freeList = m_entries[0].getNextInFreeList();
- ASSERT(freeList < WeakGCHandlePool::numPoolEntries);
- handle->setNextInFreeList(freeList);
- m_entries[0].setNextInFreeList(handle - m_entries);
- --m_entriesSize;
-}
-
-}
diff --git a/Source/JavaScriptCore/runtime/GCHandle.h b/Source/JavaScriptCore/runtime/GCHandle.h
deleted file mode 100644
index 8818f79..0000000
--- a/Source/JavaScriptCore/runtime/GCHandle.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 GCHandle_h
-#define GCHandle_h
-
-#include <wtf/Assertions.h>
-
-namespace JSC {
-
-class Heap;
-class JSCell;
-class WeakGCHandle;
-class WeakGCHandlePool;
-
-class WeakGCHandle {
- friend class WeakGCHandlePool;
-
-public:
- // Because JSCell objects are aligned, we can use the lower two bits as
- // status flags. The least significant bit is set when the handle is not a
- // pointer, i.e. when it's used as a offset for the free list in
- // WeakGCHandlePool. The second least significant bit is set when the object
- // the pointer corresponds to has been deleted by a garbage collection
-
- bool isValidPtr() { return !(m_ptr & 3); }
- bool isPtr() { return !(m_ptr & 1); }
- bool isNext() { return (m_ptr & 3) == 1; }
-
- void invalidate()
- {
- ASSERT(isValidPtr());
- m_ptr |= 2;
- }
-
- JSCell* get()
- {
- ASSERT(isPtr());
- return reinterpret_cast<JSCell*>(m_ptr & ~3);
- }
-
- void set(JSCell* p)
- {
- m_ptr = reinterpret_cast<uintptr_t>(p);
- ASSERT(isPtr());
- }
-
- WeakGCHandlePool* pool();
-
-private:
- uintptr_t getNextInFreeList()
- {
- ASSERT(isNext());
- return m_ptr >> 2;
- }
-
- void setNextInFreeList(uintptr_t n)
- {
- m_ptr = (n << 2) | 1;
- ASSERT(isNext());
- }
-
- uintptr_t m_ptr;
-};
-
-class WeakGCHandlePool {
-public:
- static const size_t poolSize = 32 * 1024; // 32k
- static const size_t poolMask = ~(poolSize - 1);
- static const size_t numPoolEntries = (poolSize - sizeof(Heap*) - 3 * sizeof(unsigned)) / sizeof(WeakGCHandle);
-
- WeakGCHandlePool();
-
- WeakGCHandle* allocate(JSCell* cell);
- void free(WeakGCHandle*);
-
- bool isFull()
- {
- ASSERT(m_entriesSize < WeakGCHandlePool::numPoolEntries);
- return m_entriesSize == WeakGCHandlePool::numPoolEntries - 1;
- }
-
- void update();
-
-private:
- Heap* m_heap;
- unsigned m_entriesSize;
- unsigned m_initialAlloc;
-
- WeakGCHandle m_entries[WeakGCHandlePool::numPoolEntries];
-};
-
-}
-#endif
diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h
index ffab94d..a222c7a 100644
--- a/Source/JavaScriptCore/runtime/GetterSetter.h
+++ b/Source/JavaScriptCore/runtime/GetterSetter.h
@@ -26,6 +26,7 @@
#include "JSCell.h"
#include "CallFrame.h"
+#include "Structure.h"
namespace JSC {
@@ -37,7 +38,7 @@ namespace JSC {
friend class JIT;
public:
GetterSetter(ExecState* exec)
- : JSCell(exec->globalData().getterSetterStructure.get())
+ : JSCell(exec->globalData(), exec->globalData().getterSetterStructure.get())
{
}
@@ -47,9 +48,9 @@ namespace JSC {
void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.set(globalData, this, getter); }
JSObject* setter() const { return m_setter.get(); }
void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.set(globalData, this, setter); }
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount, 0);
}
private:
virtual bool isGetterSetter() const;
diff --git a/Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp b/Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp
deleted file mode 100644
index 27207e2..0000000
--- a/Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "GlobalEvalFunction.h"
-
-#include "JSGlobalObject.h"
-#include <wtf/Assertions.h>
-
-namespace JSC {
-
-ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction);
-
-GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
- : PrototypeFunction(exec, globalObject, structure, len, name, function)
- , m_cachedGlobalObject(exec->globalData(), this, cachedGlobalObject)
-{
- ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
-}
-
-void GlobalEvalFunction::markChildren(MarkStack& markStack)
-{
- PrototypeFunction::markChildren(markStack);
- markStack.append(&m_cachedGlobalObject);
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/GlobalEvalFunction.h b/Source/JavaScriptCore/runtime/GlobalEvalFunction.h
deleted file mode 100644
index 13f0946..0000000
--- a/Source/JavaScriptCore/runtime/GlobalEvalFunction.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GlobalEvalFunction_h
-#define GlobalEvalFunction_h
-
-#include "PrototypeFunction.h"
-
-namespace JSC {
-
- class JSGlobalObject;
-
- class GlobalEvalFunction : public PrototypeFunction {
- public:
- GlobalEvalFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
- JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject.get(); }
-
- static PassRefPtr<Structure> createStructure(JSValue prototype)
- {
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
- }
-
- protected:
- static const unsigned StructureFlags = ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | PrototypeFunction::StructureFlags;
-
- private:
- virtual void markChildren(MarkStack&);
-
- WriteBarrier<JSGlobalObject> m_cachedGlobalObject;
- };
-
-} // namespace JSC
-
-#endif // GlobalEvalFunction_h
diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp
deleted file mode 100644
index c05233c..0000000
--- a/Source/JavaScriptCore/runtime/Heap.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * 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 "Heap.h"
-
-#include "CodeBlock.h"
-#include "ConservativeSet.h"
-#include "GCActivityCallback.h"
-#include "GCHandle.h"
-#include "Interpreter.h"
-#include "JSGlobalData.h"
-#include "JSGlobalObject.h"
-#include "JSLock.h"
-#include "JSONObject.h"
-#include "Tracing.h"
-#include <algorithm>
-
-#define COLLECT_ON_EVERY_ALLOCATION 0
-
-using namespace std;
-
-namespace JSC {
-
-const size_t minBytesPerCycle = 512 * 1024;
-
-Heap::Heap(JSGlobalData* globalData)
- : m_operationInProgress(NoOperation)
- , m_markedSpace(globalData)
- , m_markListSet(0)
- , m_activityCallback(DefaultGCActivityCallback::create(this))
- , m_globalData(globalData)
- , m_machineStackMarker(this)
- , m_markStack(globalData->jsArrayVPtr)
- , m_extraCost(0)
-{
- (*m_activityCallback)();
-}
-
-Heap::~Heap()
-{
- // The destroy function must already have been called, so assert this.
- ASSERT(!m_globalData);
-}
-
-void Heap::destroy()
-{
- JSLock lock(SilenceAssertionsOnly);
-
- if (!m_globalData)
- return;
-
- ASSERT(!m_globalData->dynamicGlobalObject);
- ASSERT(m_operationInProgress == NoOperation);
-
- // The global object is not GC protected at this point, so sweeping may delete it
- // (and thus the global data) before other objects that may use the global data.
- RefPtr<JSGlobalData> protect(m_globalData);
-
- delete m_markListSet;
- m_markListSet = 0;
-
- m_markedSpace.destroy();
-
- m_globalData = 0;
-}
-
-void Heap::reportExtraMemoryCostSlowCase(size_t cost)
-{
- // Our frequency of garbage collection tries to balance memory use against speed
- // by collecting based on the number of newly created values. However, for values
- // that hold on to a great deal of memory that's not in the form of other JS values,
- // that is not good enough - in some cases a lot of those objects can pile up and
- // use crazy amounts of memory without a GC happening. So we track these extra
- // memory costs. Only unusually large objects are noted, and we only keep track
- // of this extra cost until the next GC. In garbage collected languages, most values
- // are either very short lived temporaries, or have extremely long lifetimes. So
- // if a large value survives one garbage collection, there is not much point to
- // collecting more frequently as long as it stays alive.
-
- if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.capacity() / 2)
- collectAllGarbage();
- m_extraCost += cost;
-}
-
-void* Heap::allocate(size_t s)
-{
- ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
- ASSERT_UNUSED(s, s <= MarkedBlock::CELL_SIZE);
- ASSERT(m_operationInProgress == NoOperation);
-
-#if COLLECT_ON_EVERY_ALLOCATION
- collectAllGarbage();
- ASSERT(m_operationInProgress == NoOperation);
-#endif
-
- m_operationInProgress = Allocation;
- void* result = m_markedSpace.allocate(s);
- m_operationInProgress = NoOperation;
- if (!result) {
- reset(DoNotSweep);
-
- m_operationInProgress = Allocation;
- result = m_markedSpace.allocate(s);
- m_operationInProgress = NoOperation;
- }
-
- ASSERT(result);
- return result;
-}
-
-void Heap::updateWeakGCHandles()
-{
- for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i)
- weakGCHandlePool(i)->update();
-}
-
-void WeakGCHandlePool::update()
-{
- for (unsigned i = 1; i < WeakGCHandlePool::numPoolEntries; ++i) {
- if (m_entries[i].isValidPtr()) {
- JSCell* cell = m_entries[i].get();
- if (!cell || !Heap::isMarked(cell))
- m_entries[i].invalidate();
- }
- }
-}
-
-WeakGCHandle* Heap::addWeakGCHandle(JSCell* ptr)
-{
- for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i)
- if (!weakGCHandlePool(i)->isFull())
- return weakGCHandlePool(i)->allocate(ptr);
-
- PageAllocationAligned allocation = PageAllocationAligned::allocate(WeakGCHandlePool::poolSize, WeakGCHandlePool::poolSize, OSAllocator::JSGCHeapPages);
- m_weakGCHandlePools.append(allocation);
-
- WeakGCHandlePool* pool = new (allocation.base()) WeakGCHandlePool();
- return pool->allocate(ptr);
-}
-
-void Heap::protect(JSValue k)
-{
- ASSERT(k);
- ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
-
- if (!k.isCell())
- return;
-
- m_protectedValues.add(k.asCell());
-}
-
-bool Heap::unprotect(JSValue k)
-{
- ASSERT(k);
- ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
-
- if (!k.isCell())
- return false;
-
- return m_protectedValues.remove(k.asCell());
-}
-
-void Heap::markProtectedObjects(MarkStack& markStack)
-{
- ProtectCountSet::iterator end = m_protectedValues.end();
- for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
- markStack.deprecatedAppend(&it->first);
-}
-
-void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
-{
- m_tempSortingVectors.append(tempVector);
-}
-
-void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
-{
- ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
- m_tempSortingVectors.removeLast();
-}
-
-void Heap::markTempSortVectors(MarkStack& markStack)
-{
- typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;
-
- VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end();
- for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) {
- Vector<ValueStringPair>* tempSortingVector = *it;
-
- Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
- for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
- if (vectorIt->first)
- markStack.deprecatedAppend(&vectorIt->first);
- }
- }
-}
-
-inline RegisterFile& Heap::registerFile()
-{
- return m_globalData->interpreter->registerFile();
-}
-
-void Heap::markRoots()
-{
-#ifndef NDEBUG
- if (m_globalData->isSharedInstance()) {
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
- }
-#endif
-
- ASSERT(m_operationInProgress == NoOperation);
- if (m_operationInProgress != NoOperation)
- CRASH();
-
- m_operationInProgress = Collection;
-
- // 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(this);
- m_machineStackMarker.markMachineStackConservatively(conservativeSet);
- conservativeSet.add(registerFile().start(), registerFile().end());
-
- m_markedSpace.clearMarks();
-
- 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();
-
- HashSet<GlobalCodeBlock*>::const_iterator end = m_codeBlocks.end();
- for (HashSet<GlobalCodeBlock*>::const_iterator it = m_codeBlocks.begin(); it != end; ++it)
- (*it)->markAggregate(markStack);
- markStack.drain();
-
- // Mark misc. other roots.
- if (m_markListSet && m_markListSet->size())
- MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
- if (m_globalData->exception)
- 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.
- m_globalData->smallStrings.markChildren(markStack);
-
- markStack.drain();
- markStack.compact();
-
- updateWeakGCHandles();
-
- m_operationInProgress = NoOperation;
-}
-
-size_t Heap::objectCount() const
-{
- return m_markedSpace.objectCount();
-}
-
-size_t Heap::size() const
-{
- return m_markedSpace.size();
-}
-
-size_t Heap::capacity() const
-{
- return m_markedSpace.capacity();
-}
-
-size_t Heap::globalObjectCount()
-{
- return m_globalData->globalObjects.uncheckedSize();
-}
-
-size_t Heap::protectedGlobalObjectCount()
-{
- size_t count = 0;
-
- GlobalObjectMap& map = m_globalData->globalObjects;
- GlobalObjectMap::iterator end = map.uncheckedEnd();
- for (GlobalObjectMap::iterator it = map.uncheckedBegin(); it != end; ++it) {
- if (map.isValid(it) && m_protectedValues.contains(it->second.get()))
- ++count;
- }
-
- return count;
-}
-
-size_t Heap::protectedObjectCount()
-{
- return m_protectedValues.size();
-}
-
-class TypeCounter {
-public:
- TypeCounter();
- void operator()(JSCell*);
- PassOwnPtr<TypeCountSet> take();
-
-private:
- const char* typeName(JSCell*);
- OwnPtr<TypeCountSet> m_typeCountSet;
-};
-
-inline TypeCounter::TypeCounter()
- : m_typeCountSet(new TypeCountSet)
-{
-}
-
-inline const char* TypeCounter::typeName(JSCell* cell)
-{
- if (cell->isString())
- return "string";
- if (cell->isGetterSetter())
- return "Getter-Setter";
- if (cell->isAPIValueWrapper())
- return "API wrapper";
- if (cell->isPropertyNameIterator())
- return "For-in iterator";
- if (!cell->isObject())
- return "[empty cell]";
- const ClassInfo* info = cell->classInfo();
- return info ? info->className : "Object";
-}
-
-inline void TypeCounter::operator()(JSCell* cell)
-{
- m_typeCountSet->add(typeName(cell));
-}
-
-inline PassOwnPtr<TypeCountSet> TypeCounter::take()
-{
- return m_typeCountSet.release();
-}
-
-PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts()
-{
- TypeCounter typeCounter;
-
- ProtectCountSet::iterator end = m_protectedValues.end();
- for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
- typeCounter(it->first);
-
- return typeCounter.take();
-}
-
-PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
-{
- TypeCounter typeCounter;
- forEach(typeCounter);
- return typeCounter.take();
-}
-
-bool Heap::isBusy()
-{
- return m_operationInProgress != NoOperation;
-}
-
-void Heap::collectAllGarbage()
-{
- reset(DoSweep);
-}
-
-void Heap::reset(SweepToggle sweepToggle)
-{
- ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
- JAVASCRIPTCORE_GC_BEGIN();
-
- markRoots();
-
- JAVASCRIPTCORE_GC_MARKED();
-
- m_markedSpace.reset();
- m_extraCost = 0;
-
- if (sweepToggle == DoSweep) {
- m_markedSpace.sweep();
- m_markedSpace.shrink();
- }
-
- size_t proportionalBytes = static_cast<size_t>(1.5 * m_markedSpace.size());
- m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle));
-
- JAVASCRIPTCORE_GC_END();
-
- (*m_activityCallback)();
-}
-
-void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
-{
- m_activityCallback = activityCallback;
-}
-
-GCActivityCallback* Heap::activityCallback()
-{
- return m_activityCallback.get();
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h
deleted file mode 100644
index 6591a5b..0000000
--- a/Source/JavaScriptCore/runtime/Heap.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 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 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 Heap_h
-#define Heap_h
-
-#include "MarkStack.h"
-#include "MarkedSpace.h"
-#include <wtf/Forward.h>
-#include <wtf/HashSet.h>
-
-namespace JSC {
-
- class GCActivityCallback;
- class GlobalCodeBlock;
- class JSCell;
- class JSGlobalData;
- class JSValue;
- class JSValue;
- class LiveObjectIterator;
- class MarkStack;
- class MarkedArgumentBuffer;
- class RegisterFile;
- class UString;
- class WeakGCHandlePool;
-
- typedef std::pair<JSValue, UString> ValueStringPair;
- typedef HashCountedSet<JSCell*> ProtectCountSet;
- typedef HashCountedSet<const char*> TypeCountSet;
-
- enum OperationInProgress { NoOperation, Allocation, Collection };
-
- class Heap {
- WTF_MAKE_NONCOPYABLE(Heap);
- public:
- static Heap* heap(JSValue); // 0 for immediate values
- static Heap* heap(JSCell*);
-
- static bool isMarked(const JSCell*);
- static bool testAndSetMarked(const JSCell*);
- static void setMarked(JSCell*);
-
- Heap(JSGlobalData*);
- ~Heap();
- void destroy(); // JSGlobalData must call destroy() before ~Heap().
-
- JSGlobalData* globalData() const { return m_globalData; }
- MarkedSpace& markedSpace() { return m_markedSpace; }
- MachineStackMarker& machineStackMarker() { return m_machineStackMarker; }
-
- GCActivityCallback* activityCallback();
- void setActivityCallback(PassOwnPtr<GCActivityCallback>);
-
- bool isBusy(); // true if an allocation or collection is in progress
- void* allocate(size_t);
- void collectAllGarbage();
-
- void reportExtraMemoryCost(size_t cost);
-
- void protect(JSValue);
- bool unprotect(JSValue); // True when the protect count drops to 0.
-
- bool contains(void*);
-
- size_t size() const;
- size_t capacity() const;
- size_t objectCount() const;
- size_t globalObjectCount();
- size_t protectedObjectCount();
- size_t protectedGlobalObjectCount();
- PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
- PassOwnPtr<TypeCountSet> objectTypeCounts();
-
- WeakGCHandle* addWeakGCHandle(JSCell*);
-
- void pushTempSortVector(Vector<ValueStringPair>*);
- void popTempSortVector(Vector<ValueStringPair>*);
-
- HashSet<GlobalCodeBlock*>& codeBlocks() { return m_codeBlocks; }
-
- HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
-
- template <typename Functor> void forEach(Functor&);
-
- private:
- friend class JSGlobalData;
-
- static const size_t minExtraCost = 256;
- static const size_t maxExtraCost = 1024 * 1024;
-
- void reportExtraMemoryCostSlowCase(size_t);
-
- void markRoots();
- void markProtectedObjects(MarkStack&);
- void markTempSortVectors(MarkStack&);
-
- void updateWeakGCHandles();
- WeakGCHandlePool* weakGCHandlePool(size_t index);
-
- enum SweepToggle { DoNotSweep, DoSweep };
- void reset(SweepToggle);
-
- RegisterFile& registerFile();
-
- OperationInProgress m_operationInProgress;
- MarkedSpace m_markedSpace;
-
- ProtectCountSet m_protectedValues;
- Vector<PageAllocationAligned> m_weakGCHandlePools;
- Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
- HashSet<GlobalCodeBlock*> m_codeBlocks;
-
- HashSet<MarkedArgumentBuffer*>* m_markListSet;
-
- OwnPtr<GCActivityCallback> m_activityCallback;
-
- JSGlobalData* m_globalData;
-
- MachineStackMarker m_machineStackMarker;
- MarkStack m_markStack;
-
- size_t m_extraCost;
- };
-
- inline bool Heap::isMarked(const JSCell* cell)
- {
- return MarkedSpace::isMarked(cell);
- }
-
- inline bool Heap::testAndSetMarked(const JSCell* cell)
- {
- return MarkedSpace::testAndSetMarked(cell);
- }
-
- inline void Heap::setMarked(JSCell* cell)
- {
- MarkedSpace::setMarked(cell);
- }
-
- inline bool Heap::contains(void* p)
- {
- return m_markedSpace.contains(p);
- }
-
- inline void Heap::reportExtraMemoryCost(size_t cost)
- {
- if (cost > minExtraCost)
- reportExtraMemoryCostSlowCase(cost);
- }
-
- inline WeakGCHandlePool* Heap::weakGCHandlePool(size_t index)
- {
- return static_cast<WeakGCHandlePool*>(m_weakGCHandlePools[index].base());
- }
-
- template <typename Functor> inline void Heap::forEach(Functor& functor)
- {
- m_markedSpace.forEach(functor);
- }
-
-} // namespace JSC
-
-#endif // Heap_h
diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp
index 28cfd0a..4a99b19 100644
--- a/Source/JavaScriptCore/runtime/Identifier.cpp
+++ b/Source/JavaScriptCore/runtime/Identifier.cpp
@@ -22,7 +22,9 @@
#include "Identifier.h"
#include "CallFrame.h"
+#include "JSObject.h"
#include "NumericStrings.h"
+#include "ScopeChain.h"
#include <new> // for placement new
#include <string.h> // for strlen
#include <wtf/Assertions.h>
@@ -89,7 +91,7 @@ bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned length)
struct IdentifierCStringTranslator {
static unsigned hash(const char* c)
{
- return WTF::StringHasher::createHash<char>(c);
+ return StringHasher::computeHash<char>(c);
}
static bool equal(StringImpl* r, const char* s)
@@ -149,7 +151,7 @@ struct UCharBuffer {
struct IdentifierUCharBufferTranslator {
static unsigned hash(const UCharBuffer& buf)
{
- return WTF::StringHasher::createHash<UChar>(buf.s, buf.length);
+ return StringHasher::computeHash<UChar>(buf.s, buf.length);
}
static bool equal(StringImpl* str, const UCharBuffer& buf)
@@ -215,7 +217,7 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const UChar* s,
{
if (length == 1) {
UChar c = s[0];
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
}
if (!length)
@@ -242,7 +244,7 @@ PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringI
if (r->length() == 1) {
UChar c = r->characters()[0];
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
r = globalData->smallStrings.singleCharacterStringRep(c);
if (r->isIdentifier())
return r;
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.cpp b/Source/JavaScriptCore/runtime/InternalFunction.cpp
index f19ae0d..c3b07f8 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.cpp
+++ b/Source/JavaScriptCore/runtime/InternalFunction.cpp
@@ -29,34 +29,33 @@
namespace JSC {
-ASSERT_CLASS_FITS_IN_CELL(InternalFunction);
+// Ensure the compiler generates a vtable for InternalFunction!
+void InternalFunction::vtableAnchor() {}
-const ClassInfo InternalFunction::info = { "Function", 0, 0, 0 };
+ASSERT_CLASS_FITS_IN_CELL(InternalFunction);
-const ClassInfo* InternalFunction::classInfo() const
-{
- return &info;
-}
+const ClassInfo InternalFunction::s_info = { "Function", &JSObjectWithGlobalObject::s_info, 0, 0 };
-InternalFunction::InternalFunction(NonNullPassRefPtr<Structure> structure)
- : JSObjectWithGlobalObject(structure)
+InternalFunction::InternalFunction(VPtrStealingHackType)
+ : JSObjectWithGlobalObject(VPtrStealingHack)
{
}
-InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const Identifier& name)
+InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, Structure* structure, const Identifier& name)
: JSObjectWithGlobalObject(globalObject, structure)
{
+ ASSERT(inherits(&s_info));
putDirect(*globalData, globalData->propertyNames->name, jsString(globalData, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
}
const UString& InternalFunction::name(ExecState* exec)
{
- return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue();
+ return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
}
const UString InternalFunction::displayName(ExecState* exec)
{
- JSValue displayName = getDirect(exec->globalData().propertyNames->displayName);
+ JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
if (displayName && isJSString(&exec->globalData(), displayName))
return asString(displayName)->tryGetValue();
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h
index 401f17b..28e260e 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.h
+++ b/Source/JavaScriptCore/runtime/InternalFunction.h
@@ -33,35 +33,36 @@ namespace JSC {
class InternalFunction : public JSObjectWithGlobalObject {
public:
- virtual const ClassInfo* classInfo() const;
- static JS_EXPORTDATA const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo s_info;
const UString& name(ExecState*);
const UString displayName(ExecState*);
const UString calculatedDisplayName(ExecState*);
- static PassRefPtr<Structure> createStructure(JSValue proto)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
// Only used to allow us to determine the JSFunction vptr
- InternalFunction(NonNullPassRefPtr<Structure> structure);
+ InternalFunction(VPtrStealingHackType);
- InternalFunction(JSGlobalData*, JSGlobalObject*, NonNullPassRefPtr<Structure>, const Identifier&);
+ InternalFunction(JSGlobalData*, JSGlobalObject*, Structure*, const Identifier&);
private:
virtual CallType getCallData(CallData&) = 0;
+
+ virtual void vtableAnchor();
};
InternalFunction* asInternalFunction(JSValue);
inline InternalFunction* asInternalFunction(JSValue value)
{
- ASSERT(asObject(value)->inherits(&InternalFunction::info));
+ ASSERT(asObject(value)->inherits(&InternalFunction::s_info));
return static_cast<InternalFunction*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
index a113e91..0165488 100644
--- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
+++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
@@ -25,6 +25,7 @@
#include "JSCell.h"
#include "CallFrame.h"
+#include "Structure.h"
namespace JSC {
@@ -35,15 +36,15 @@ namespace JSC {
virtual bool isAPIValueWrapper() const { return true; }
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount, 0);
}
private:
JSAPIValueWrapper(ExecState* exec, JSValue value)
- : JSCell(exec->globalData().apiWrapperStructure.get())
+ : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get())
{
m_value.set(exec->globalData(), this, value);
ASSERT(!value.isCell());
diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp
index 6fb5ced..4e36641 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.cpp
+++ b/Source/JavaScriptCore/runtime/JSActivation.cpp
@@ -37,16 +37,25 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSActivation);
-const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
+const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 };
-JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable)
- : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers()))
+JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)
+ : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers())
+ , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount()))
+ , m_numCapturedVars(functionExecutable->capturedVariableCount())
+ , m_requiresDynamicChecks(functionExecutable->usesEval())
+ , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())
{
+ ASSERT(inherits(&s_info));
+
+ // We have to manually ref and deref the symbol table as JSVariableObject
+ // doesn't know about SharedSymbolTable
+ static_cast<SharedSymbolTable*>(m_symbolTable)->ref();
}
JSActivation::~JSActivation()
{
- delete d();
+ static_cast<SharedSymbolTable*>(m_symbolTable)->deref();
}
void JSActivation::markChildren(MarkStack& markStack)
@@ -54,33 +63,29 @@ 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();
+ WriteBarrier<Unknown>* registerArray = m_registerArray.get();
if (!registerArray)
return;
- size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
-
- size_t count = numParametersMinusThis;
- markStack.deprecatedAppendValues(registerArray, count);
-
- size_t numVars = d()->functionExecutable->capturedVariableCount();
+ markStack.appendValues(registerArray, m_numParametersMinusThis);
// Skip the call frame, which sits between the parameters and vars.
- markStack.deprecatedAppendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
+ markStack.appendValues(registerArray + m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, m_numCapturedVars, MayContainNullValues);
}
inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
{
SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
- if (!entry.isNull()) {
- ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
- slot.setRegisterSlot(&registerAt(entry.getIndex()));
- return true;
- }
- return false;
+ if (entry.isNull())
+ return false;
+ if (entry.getIndex() >= m_numCapturedVars)
+ return false;
+
+ slot.setValue(registerAt(entry.getIndex()).get());
+ return true;
}
-inline bool JSActivation::symbolTablePut(const Identifier& propertyName, JSValue value)
+inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
@@ -89,8 +94,10 @@ inline bool JSActivation::symbolTablePut(const Identifier& propertyName, JSValue
return false;
if (entry.isReadOnly())
return true;
- ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
- registerAt(entry.getIndex()) = value;
+ if (entry.getIndex() >= m_numCapturedVars)
+ return false;
+
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
@@ -98,15 +105,17 @@ void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& prope
{
SymbolTable::const_iterator end = symbolTable().end();
for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
- ASSERT(it->second.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
- if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
- propertyNames.add(Identifier(exec, it->first.get()));
+ if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
+ continue;
+ if (it->second.getIndex() >= m_numCapturedVars)
+ continue;
+ propertyNames.add(Identifier(exec, it->first.get()));
}
// Skip the JSVariableObject implementation of getOwnPropertyNames
JSObject::getOwnPropertyNames(exec, propertyNames, mode);
}
-inline bool JSActivation::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue value, unsigned attributes)
+inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
@@ -115,10 +124,11 @@ inline bool JSActivation::symbolTablePutWithAttributes(const Identifier& propert
return false;
SymbolTableEntry& entry = iter->second;
ASSERT(!entry.isNull());
- if (entry.getIndex() >= static_cast<int>(d()->functionExecutable->capturedVariableCount()))
+ if (entry.getIndex() >= m_numCapturedVars)
return false;
+
entry.setAttributes(attributes);
- registerAt(entry.getIndex()) = value;
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
@@ -132,7 +142,7 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert
if (symbolTableGet(propertyName, slot))
return true;
- if (WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName)) {
+ if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
slot.setValue(location->get());
return true;
}
@@ -148,7 +158,7 @@ void JSActivation::put(ExecState* exec, const Identifier& propertyName, JSValue
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
- if (symbolTablePut(propertyName, value))
+ if (symbolTablePut(exec->globalData(), propertyName, value))
return;
// We don't call through to JSObject because __proto__ and getter/setter
@@ -163,7 +173,7 @@ void JSActivation::putWithAttributes(ExecState* exec, const Identifier& property
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
- if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
return;
// We don't call through to JSObject because __proto__ and getter/setter
@@ -194,15 +204,15 @@ JSValue JSActivation::toStrictThisObject(ExecState*) const
bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
{
- requiresDynamicChecks = d()->functionExecutable->usesEval();
+ requiresDynamicChecks = m_requiresDynamicChecks;
return false;
}
JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
{
JSActivation* activation = asActivation(slotBase);
- CallFrame* callFrame = CallFrame::create(activation->d()->registers);
- int argumentsRegister = activation->d()->functionExecutable->generatedBytecode().argumentsRegister();
+ CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->m_registers));
+ int argumentsRegister = activation->m_argumentsRegister;
if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue())
return arguments;
int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
@@ -211,7 +221,7 @@ JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identi
callFrame->uncheckedR(argumentsRegister) = arguments;
callFrame->uncheckedR(realArgumentsRegister) = arguments;
- ASSERT(callFrame->uncheckedR(realArgumentsRegister).jsValue().inherits(&Arguments::info));
+ ASSERT(callFrame->uncheckedR(realArgumentsRegister).jsValue().inherits(&Arguments::s_info));
return callFrame->uncheckedR(realArgumentsRegister).jsValue();
}
diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h
index 6dd6d70..65642f1 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.h
+++ b/Source/JavaScriptCore/runtime/JSActivation.h
@@ -42,7 +42,7 @@ namespace JSC {
class JSActivation : public JSVariableObject {
typedef JSVariableObject Base;
public:
- JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>);
+ JSActivation(CallFrame*, FunctionExecutable*);
virtual ~JSActivation();
virtual void markChildren(MarkStack&);
@@ -62,53 +62,43 @@ namespace JSC {
virtual JSObject* toThisObject(ExecState*) const;
virtual JSValue toStrictThisObject(ExecState*) const;
- void copyRegisters();
+ void copyRegisters(JSGlobalData&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); }
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
private:
- struct JSActivationData : public JSVariableObjectData {
- JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers)
- : JSVariableObjectData(_functionExecutable->symbolTable(), registers)
- , functionExecutable(_functionExecutable)
- {
- // We have to manually ref and deref the symbol table as JSVariableObjectData
- // doesn't know about SharedSymbolTable
- functionExecutable->symbolTable()->ref();
- }
- ~JSActivationData()
- {
- static_cast<SharedSymbolTable*>(symbolTable)->deref();
- }
-
- RefPtr<FunctionExecutable> functionExecutable;
- };
-
bool symbolTableGet(const Identifier&, PropertySlot&);
bool symbolTableGet(const Identifier&, PropertyDescriptor&);
bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
- bool symbolTablePut(const Identifier&, JSValue);
- bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
+ bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue);
+ bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
- JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); }
+ int m_numParametersMinusThis;
+ int m_numCapturedVars : 31;
+ bool m_requiresDynamicChecks : 1;
+ int m_argumentsRegister;
};
JSActivation* asActivation(JSValue);
inline JSActivation* asActivation(JSValue value)
{
- ASSERT(asObject(value)->inherits(&JSActivation::info));
+ ASSERT(asObject(value)->inherits(&JSActivation::s_info));
return static_cast<JSActivation*>(asObject(value));
}
+
+ ALWAYS_INLINE JSActivation* Register::activation() const
+ {
+ return asActivation(jsValue());
+ }
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index ded6d87..bf61097 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -92,7 +92,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSArray);
// as long as it is 1/8 full. If more sparse than that, we use a map.
static const unsigned minDensityMultiplier = 8;
-const ClassInfo JSArray::info = {"Array", 0, 0, 0};
+const ClassInfo JSArray::s_info = {"Array", &JSNonFinalObject::s_info, 0, 0};
// We keep track of the size of the last array after it was grown. We use this
// as a simple heuristic for as the value to grow the next array from size 0.
@@ -127,25 +127,15 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
#endif
JSArray::JSArray(VPtrStealingHackType)
- : JSObject(createStructure(jsNull()))
+ : JSNonFinalObject(VPtrStealingHack)
{
- unsigned initialCapacity = 0;
-
- m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
- m_storage->m_allocBase = m_storage;
- m_indexBias = 0;
- m_vectorLength = initialCapacity;
-
- checkConsistency();
-
- // It's not safe to call Heap::heap(this) in order to report extra memory
- // cost here, because the VPtrStealingHackType JSArray is not allocated on
- // the heap. For the same reason, it's OK not to report extra cost.
}
-JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+JSArray::JSArray(JSGlobalData& globalData, Structure* structure)
+ : JSNonFinalObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
+
unsigned initialCapacity = 0;
m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
@@ -158,9 +148,11 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
Heap::heap(this)->reportExtraMemoryCost(storageSize(0));
}
-JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, ArrayCreationMode creationMode)
- : JSObject(structure)
+JSArray::JSArray(JSGlobalData& globalData, Structure* structure, unsigned initialLength, ArrayCreationMode creationMode)
+ : JSNonFinalObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
+
unsigned initialCapacity;
if (creationMode == CreateCompact)
initialCapacity = initialLength;
@@ -198,9 +190,11 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength,
Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
}
-JSArray::JSArray(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, const ArgList& list)
- : JSObject(structure)
+JSArray::JSArray(JSGlobalData& globalData, Structure* structure, const ArgList& list)
+ : JSNonFinalObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
+
unsigned initialCapacity = list.size();
unsigned initialStorage;
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index b5caa47..8be8513 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -57,17 +57,15 @@ namespace JSC {
enum ArrayCreationMode { CreateCompact, CreateInitialized };
- class JSArray : public JSObject {
- friend class JIT;
+ class JSArray : public JSNonFinalObject {
friend class Walker;
public:
- enum VPtrStealingHackType { VPtrStealingHack };
JSArray(VPtrStealingHackType);
- explicit JSArray(NonNullPassRefPtr<Structure>);
- JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength, ArrayCreationMode);
- JSArray(JSGlobalData&, NonNullPassRefPtr<Structure>, const ArgList& initialValues);
+ explicit JSArray(JSGlobalData&, Structure*);
+ JSArray(JSGlobalData&, Structure*, unsigned initialLength, ArrayCreationMode);
+ JSArray(JSGlobalData&, Structure*, const ArgList& initialValues);
virtual ~JSArray();
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
@@ -75,7 +73,7 @@ namespace JSC {
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
- static JS_EXPORTDATA const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo s_info;
unsigned length() const { return m_storage->m_length; }
void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
@@ -125,13 +123,23 @@ namespace JSC {
void fillArgList(ExecState*, MarkedArgumentBuffer&);
void copyToRegisters(ExecState*, Register*, uint32_t);
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
inline void markChildrenDirect(MarkStack& markStack);
+ static ptrdiff_t storageOffset()
+ {
+ return OBJECT_OFFSETOF(JSArray, m_storage);
+ }
+
+ static ptrdiff_t vectorLengthOffset()
+ {
+ return OBJECT_OFFSETOF(JSArray, m_vectorLength);
+ }
+
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
@@ -142,10 +150,8 @@ namespace JSC {
void* subclassData() const;
void setSubclassData(void*);
-
- private:
- virtual const ClassInfo* classInfo() const { return &info; }
+ private:
bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
void putSlowCase(ExecState*, unsigned propertyName, JSValue);
@@ -167,7 +173,7 @@ namespace JSC {
inline JSArray* asArray(JSCell* cell)
{
- ASSERT(cell->inherits(&JSArray::info));
+ ASSERT(cell->inherits(&JSArray::s_info));
return static_cast<JSArray*>(cell);
}
@@ -176,11 +182,8 @@ namespace JSC {
return asArray(value.asCell());
}
- inline bool isJSArray(JSGlobalData* globalData, JSValue v)
- {
- return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr;
- }
inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
+ inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && isJSArray(globalData, v.asCell()); }
inline void JSArray::markChildrenDirect(MarkStack& markStack)
{
@@ -198,77 +201,6 @@ namespace JSC {
}
}
- inline void MarkStack::markChildren(JSCell* cell)
- {
- ASSERT(Heap::isMarked(cell));
- if (!cell->structure()->typeInfo().overridesMarkChildren()) {
-#ifdef NDEBUG
- asObject(cell)->markChildrenDirect(*this);
-#else
- ASSERT(!m_isCheckingForDefaultMarkViolation);
- m_isCheckingForDefaultMarkViolation = true;
- cell->markChildren(*this);
- ASSERT(m_isCheckingForDefaultMarkViolation);
- m_isCheckingForDefaultMarkViolation = false;
-#endif
- return;
- }
- if (cell->vptr() == m_jsArrayVPtr) {
- asArray(cell)->markChildrenDirect(*this);
- return;
- }
- cell->markChildren(*this);
- }
-
- inline void MarkStack::drain()
- {
-#if !ASSERT_DISABLED
- ASSERT(!m_isDraining);
- m_isDraining = true;
-#endif
- while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
- while (!m_markSets.isEmpty() && m_values.size() < 50) {
- ASSERT(!m_markSets.isEmpty());
- MarkSet& current = m_markSets.last();
- ASSERT(current.m_values);
- JSValue* end = current.m_end;
- ASSERT(current.m_values);
- ASSERT(current.m_values != end);
- findNextUnmarkedNullValue:
- ASSERT(current.m_values != end);
- JSValue value = *current.m_values;
- current.m_values++;
-
- JSCell* cell;
- if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
- if (current.m_values == end) {
- m_markSets.removeLast();
- continue;
- }
- goto findNextUnmarkedNullValue;
- }
-
- if (cell->structure()->typeInfo().type() < CompoundType) {
- if (current.m_values == end) {
- m_markSets.removeLast();
- continue;
- }
- goto findNextUnmarkedNullValue;
- }
-
- if (current.m_values == end)
- m_markSets.removeLast();
-
- markChildren(cell);
- }
- while (!m_values.isEmpty())
- markChildren(m_values.removeLast());
- }
-#if !ASSERT_DISABLED
- m_isDraining = false;
-#endif
- }
-
// Rule from ECMA 15.2 about what an array index is.
// Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
inline unsigned Identifier::toArrayIndex(bool& ok) const
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp
index 3f7d806..c2abaee 100644
--- a/Source/JavaScriptCore/runtime/JSByteArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp
@@ -33,12 +33,11 @@ using namespace WTF;
namespace JSC {
-const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 };
+const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", &Base::s_info, 0, 0 };
-JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
- : JSObject(structure)
+JSByteArray::JSByteArray(ExecState* exec, Structure* structure, ByteArray* storage)
+ : JSNonFinalObject(exec->globalData(), structure)
, m_storage(storage)
- , m_classInfo(classInfo)
{
putDirect(exec->globalData(), exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete);
}
@@ -51,10 +50,9 @@ JSByteArray::~JSByteArray()
#endif
-PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
+Structure* JSByteArray::createStructure(JSGlobalData& globalData, JSValue prototype, const JSC::ClassInfo* classInfo)
{
- PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
- return result;
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo);
}
bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h
index 44bae2d..c481bb4 100644
--- a/Source/JavaScriptCore/runtime/JSByteArray.h
+++ b/Source/JavaScriptCore/runtime/JSByteArray.h
@@ -32,9 +32,11 @@
namespace JSC {
- class JSByteArray : public JSObject {
+ class JSByteArray : public JSNonFinalObject {
friend class JSGlobalData;
public:
+ typedef JSNonFinalObject Base;
+
bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
JSValue getIndex(ExecState*, unsigned i)
{
@@ -45,18 +47,25 @@ namespace JSC {
void setIndex(unsigned i, int value)
{
ASSERT(canAccessIndex(i));
+ if (value & ~0xFF) {
+ if (value < 0)
+ value = 0;
+ else
+ value = 255;
+ }
m_storage->data()[i] = static_cast<unsigned char>(value);
}
-
+
void setIndex(unsigned i, double value)
{
ASSERT(canAccessIndex(i));
- // The largest integer value that a double can represent without loss of precision
- // is 2^53. long long is the smallest integral type that gives correct results
- // when casting numbers larger than 2^31 from a value of type double.
- m_storage->data()[i] = static_cast<unsigned char>(static_cast<long long>(value));
+ if (!(value > 0)) // Clamp NaN to 0
+ value = 0;
+ else if (value > 255)
+ value = 255;
+ m_storage->data()[i] = static_cast<unsigned char>(value + 0.5);
}
-
+
void setIndex(ExecState* exec, unsigned i, JSValue value)
{
double byteValue = value.toNumber(exec);
@@ -66,8 +75,8 @@ namespace JSC {
setIndex(i, byteValue);
}
- JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
- static PassRefPtr<Structure> createStructure(JSValue prototype);
+ JSByteArray(ExecState*, Structure*, WTF::ByteArray* storage);
+ static Structure* createStructure(JSGlobalData&, JSValue prototype, const JSC::ClassInfo* = &s_defaultInfo);
virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
@@ -77,9 +86,8 @@ namespace JSC {
virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
- virtual const ClassInfo* classInfo() const { return m_classInfo; }
static const ClassInfo s_defaultInfo;
-
+
size_t length() const { return m_storage->length(); }
WTF::ByteArray* storage() const { return m_storage.get(); }
@@ -92,17 +100,14 @@ namespace JSC {
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
private:
- enum VPtrStealingHackType { VPtrStealingHack };
JSByteArray(VPtrStealingHackType)
- : JSObject(createStructure(jsNull()))
- , m_classInfo(0)
+ : JSNonFinalObject(VPtrStealingHack)
{
}
RefPtr<WTF::ByteArray> m_storage;
- const ClassInfo* m_classInfo;
};
-
+
JSByteArray* asByteArray(JSValue value);
inline JSByteArray* asByteArray(JSValue value)
{
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index 0cc1ab1..afd8450 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -119,7 +119,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, P
// This is not a general purpose implementation of getOwnPropertySlot.
// It should only be called by JSValue::get.
// It calls getPropertySlot, not getOwnPropertySlot.
- JSObject* object = toObject(exec);
+ JSObject* object = toObject(exec, exec->lexicalGlobalObject());
slot.setBase(object);
if (!object->getPropertySlot(exec, identifier, slot))
slot.setUndefined();
@@ -131,7 +131,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl
// This is not a general purpose implementation of getOwnPropertySlot.
// It should only be called by JSValue::get.
// It calls getPropertySlot, not getOwnPropertySlot.
- JSObject* object = toObject(exec);
+ JSObject* object = toObject(exec, exec->lexicalGlobalObject());
slot.setBase(object);
if (!object->getPropertySlot(exec, identifier, slot))
slot.setUndefined();
@@ -140,32 +140,27 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl
void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
{
- toObject(exec)->put(exec, identifier, value, slot);
+ toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value, slot);
}
void JSCell::put(ExecState* exec, unsigned identifier, JSValue value)
{
- toObject(exec)->put(exec, identifier, value);
+ toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value);
}
bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier)
{
- return toObject(exec)->deleteProperty(exec, identifier);
+ return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier);
}
bool JSCell::deleteProperty(ExecState* exec, unsigned identifier)
{
- return toObject(exec)->deleteProperty(exec, identifier);
+ return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier);
}
JSObject* JSCell::toThisObject(ExecState* exec) const
{
- return toObject(exec);
-}
-
-const ClassInfo* JSCell::classInfo() const
-{
- return 0;
+ return toObject(exec, exec->lexicalGlobalObject());
}
JSValue JSCell::getJSNumber()
@@ -208,10 +203,20 @@ UString JSCell::toString(ExecState*) const
return UString();
}
-JSObject* JSCell::toObject(ExecState*) const
+JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const
{
ASSERT_NOT_REACHED();
return 0;
}
+bool isZombie(const JSCell* cell)
+{
+#if ENABLE(JSC_ZOMBIES)
+ return cell && cell->isZombie();
+#else
+ UNUSED_PARAM(cell);
+ return false;
+#endif
+}
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 66f6197..7ee871c 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -24,16 +24,19 @@
#define JSCell_h
#include "CallData.h"
+#include "CallFrame.h"
#include "ConstructData.h"
#include "Heap.h"
-#include "JSImmediate.h"
-#include "JSValue.h"
+#include "JSLock.h"
+#include "JSValueInlineMethods.h"
#include "MarkStack.h"
-#include "Structure.h"
#include <wtf/Noncopyable.h>
namespace JSC {
+ class JSGlobalObject;
+ class Structure;
+
#if COMPILER(MSVC)
// If WTF_MAKE_NONCOPYABLE is applied to JSCell we end up with a bunch of
// undefined references to the JSCell copy constructor and assignment operator
@@ -52,10 +55,9 @@ namespace JSC {
WTF_MAKE_NONCOPYABLE(JSCell);
#endif
+ friend class ExecutableBase;
friend class GetterSetter;
friend class Heap;
- friend class JIT;
- friend class JSNumberCell;
friend class JSObject;
friend class JSPropertyNameIterator;
friend class JSString;
@@ -65,16 +67,20 @@ namespace JSC {
friend class JSGlobalData;
friend class MarkedSpace;
friend class MarkedBlock;
+ friend class ScopeChainNode;
+ friend class Structure;
+ friend class StructureChain;
+
+ protected:
+ enum VPtrStealingHackType { VPtrStealingHack };
private:
- explicit JSCell(Structure*);
+ explicit JSCell(VPtrStealingHackType) { }
+ JSCell(JSGlobalData&, Structure*);
virtual ~JSCell();
public:
- static PassRefPtr<Structure> createDummyStructure()
- {
- return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
- }
+ static Structure* createDummyStructure(JSGlobalData&);
// Querying the type.
bool isString() const;
@@ -105,7 +111,7 @@ namespace JSC {
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
- virtual JSObject* toObject(ExecState*) const;
+ virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
// Garbage collection.
void* operator new(size_t, ExecState*);
@@ -118,7 +124,7 @@ namespace JSC {
#endif
// Object operations, with the toObject operation included.
- virtual const ClassInfo* classInfo() const;
+ const ClassInfo* classInfo() const;
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual void put(ExecState*, unsigned propertyName, JSValue);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
@@ -135,6 +141,16 @@ namespace JSC {
// property names, we want a similar interface with appropriate optimizations.)
bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ static ptrdiff_t structureOffset()
+ {
+ return OBJECT_OFFSETOF(JSCell, m_structure);
+ }
+
+ const void* addressOfStructure() const
+ {
+ return &m_structure;
+ }
+
protected:
static const unsigned AnonymousSlotCount = 0;
@@ -143,45 +159,28 @@ namespace JSC {
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
- Structure* m_structure;
+ WriteBarrier<Structure> m_structure;
};
- inline JSCell::JSCell(Structure* structure)
- : m_structure(structure)
+ inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
+ : m_structure(globalData, this, structure)
{
+ // Very first set of allocations won't have a real structure.
+ ASSERT(m_structure || !globalData.dummyMarkableCellStructure);
}
inline JSCell::~JSCell()
{
}
- inline bool JSCell::isObject() const
- {
- return m_structure->typeInfo().type() == ObjectType;
- }
-
- inline bool JSCell::isString() const
- {
- return m_structure->typeInfo().type() == StringType;
- }
-
inline Structure* JSCell::structure() const
{
- return m_structure;
- }
-
- inline void JSCell::markChildren(MarkStack&)
- {
- }
-
- inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
- {
- return globalData->heap.allocate(size);
+ return m_structure.get();
}
- inline void* JSCell::operator new(size_t size, ExecState* exec)
+ inline void JSCell::markChildren(MarkStack& markStack)
{
- return exec->heap()->allocate(size);
+ markStack.append(&m_structure);
}
// --- JSValue inlines ----------------------------
@@ -211,6 +210,11 @@ namespace JSC {
return isCell() ? asCell()->getString(exec) : UString();
}
+ template <typename Base> UString HandleConverter<Base, Unknown>::getString(ExecState* exec) const
+ {
+ return jsValue().getString(exec);
+ }
+
inline JSObject* JSValue::getObject() const
{
return isCell() ? asCell()->getObject() : 0;
@@ -245,14 +249,6 @@ namespace JSC {
return false;
}
-#if USE(JSVALUE64)
- ALWAYS_INLINE JSCell* JSValue::asCell() const
- {
- ASSERT(isCell());
- return m_ptr;
- }
-#endif // USE(JSVALUE64)
-
inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
{
return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
@@ -312,13 +308,6 @@ namespace JSC {
return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
}
- inline bool JSValue::needsThisConversion() const
- {
- if (UNLIKELY(!isCell()))
- return true;
- return asCell()->structure()->typeInfo().needsThisConversion();
- }
-
inline JSValue JSValue::getJSNumber()
{
if (isInt32() || isDouble())
@@ -330,57 +319,17 @@ namespace JSC {
inline JSObject* JSValue::toObject(ExecState* exec) const
{
- return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec);
+ return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
}
- inline JSObject* JSValue::toThisObject(ExecState* exec) const
- {
- return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
- }
-
- template <typename T> void MarkStack::append(DeprecatedPtr<T>* slot)
+ inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
{
- internalAppend(slot->get());
- }
-
- template <typename T> void MarkStack::append(WriteBarrierBase<T>* slot)
- {
- internalAppend(slot->get());
- }
-
- ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
- {
- ASSERT(!m_isCheckingForDefaultMarkViolation);
- ASSERT(cell);
- if (Heap::testAndSetMarked(cell))
- return;
- if (cell->structure()->typeInfo().type() >= CompoundType)
- m_values.append(cell);
+ return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
}
- ALWAYS_INLINE void MarkStack::deprecatedAppend(JSCell** value)
- {
- ASSERT(value);
- internalAppend(*value);
- }
-
- ALWAYS_INLINE void MarkStack::deprecatedAppend(JSValue* value)
- {
- ASSERT(value);
- internalAppend(*value);
- }
-
- ALWAYS_INLINE void MarkStack::deprecatedAppend(Register* value)
- {
- ASSERT(value);
- internalAppend(value->jsValue());
- }
-
- ALWAYS_INLINE void MarkStack::internalAppend(JSValue value)
+ inline JSObject* JSValue::toThisObject(ExecState* exec) const
{
- ASSERT(value);
- if (value.isCell())
- internalAppend(value.asCell());
+ return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
}
inline Heap* Heap::heap(JSValue v)
@@ -398,25 +347,65 @@ namespace JSC {
#if ENABLE(JSC_ZOMBIES)
inline bool JSValue::isZombie() const
{
- return isCell() && asCell() && asCell()->isZombie();
+ return isCell() && asCell() > (JSCell*)0x1ffffffffL && asCell()->isZombie();
}
#endif
- inline void* MarkedBlock::allocate(size_t& nextCell)
+ inline void* MarkedBlock::allocate()
{
- do {
- ASSERT(nextCell < CELLS_PER_BLOCK);
- if (!marked.testAndSet(nextCell)) { // Always false for the last cell in the block
- JSCell* cell = reinterpret_cast<JSCell*>(&cells[nextCell++]);
+ while (m_nextAtom < m_endAtom) {
+ if (!m_marks.testAndSet(m_nextAtom)) {
+ JSCell* cell = reinterpret_cast<JSCell*>(&atoms()[m_nextAtom]);
+ m_nextAtom += m_atomsPerCell;
cell->~JSCell();
return cell;
}
- nextCell = marked.nextPossiblyUnset(nextCell);
- } while (nextCell != CELLS_PER_BLOCK);
-
- nextCell = 0;
+ m_nextAtom += m_atomsPerCell;
+ }
+
return 0;
}
+
+ inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes)
+ {
+ ASSERT(bytes && bytes < maxCellSize);
+ if (bytes < preciseCutoff)
+ return m_preciseSizeClasses[(bytes - 1) / preciseStep];
+ return m_impreciseSizeClasses[(bytes - 1) / impreciseStep];
+ }
+
+ inline void* MarkedSpace::allocate(size_t bytes)
+ {
+ SizeClass& sizeClass = sizeClassFor(bytes);
+ return allocateFromSizeClass(sizeClass);
+ }
+
+ inline void* Heap::allocate(size_t bytes)
+ {
+ ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
+ ASSERT(JSLock::lockCount() > 0);
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+ ASSERT(bytes <= MarkedSpace::maxCellSize);
+ ASSERT(m_operationInProgress == NoOperation);
+
+ m_operationInProgress = Allocation;
+ void* result = m_markedSpace.allocate(bytes);
+ m_operationInProgress = NoOperation;
+ if (result)
+ return result;
+
+ return allocateSlowCase(bytes);
+ }
+
+ inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
+ {
+ return globalData->heap.allocate(size);
+ }
+
+ inline void* JSCell::operator new(size_t size, ExecState* exec)
+ {
+ return exec->heap()->allocate(size);
+ }
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.cpp b/Source/JavaScriptCore/runtime/JSChunk.cpp
index bc8bd6d..f064de8 100644
--- a/Source/JavaScriptCore/runtime/ConservativeSet.cpp
+++ b/Source/JavaScriptCore/runtime/JSChunk.cpp
@@ -24,42 +24,5 @@
*/
#include "config.h"
-#include "ConservativeSet.h"
+#include "JSChunk.h"
-namespace JSC {
-
-inline bool isPointerAligned(void* p)
-{
- return !((intptr_t)(p) & (sizeof(char*) - 1));
-}
-
-void ConservativeSet::grow()
-{
- size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2;
- DeprecatedPtr<JSCell>* newSet = static_cast<DeprecatedPtr<JSCell>*>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*)));
- memcpy(newSet, m_set, m_size * sizeof(JSCell*));
- if (m_set != m_inlineSet)
- OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(JSCell*));
- m_capacity = newCapacity;
- m_set = newSet;
-}
-
-void ConservativeSet::add(void* begin, void* end)
-{
- ASSERT(begin <= end);
- ASSERT((static_cast<char*>(end) - static_cast<char*>(begin)) < 0x1000000);
- ASSERT(isPointerAligned(begin));
- ASSERT(isPointerAligned(end));
-
- for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it) {
- if (!m_heap->contains(*it))
- continue;
-
- if (m_size == m_capacity)
- grow();
-
- m_set[m_size++] = reinterpret_cast<JSCell*>(*it);
- }
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSChunk.h b/Source/JavaScriptCore/runtime/JSChunk.h
new file mode 100644
index 0000000..bae2bc7
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSChunk.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 JSChunk_h
+#define JSChunk_h
+
+
+
+#endif // JSChunk_h
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index c569722..a18e973 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -42,62 +42,54 @@ using namespace WTF;
using namespace Unicode;
namespace JSC {
-#if ENABLE(JIT)
EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
{
return throwVMError(exec, createNotAConstructorError(exec, exec->callee()));
}
-#endif
ASSERT_CLASS_FITS_IN_CELL(JSFunction);
-const ClassInfo JSFunction::info = { "Function", 0, 0, 0 };
+const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, 0 };
bool JSFunction::isHostFunctionNonInline() const
{
return isHostFunction();
}
-JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
- : Base(structure)
- , m_executable(adoptRef(new VPtrHackExecutable()))
- , m_scopeChain(NoScopeChain())
+JSFunction::JSFunction(VPtrStealingHackType)
+ : Base(VPtrStealingHack)
{
}
-#if ENABLE(JIT)
-JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk)
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeExecutable* thunk)
: Base(globalObject, structure)
- , m_executable(thunk)
- , m_scopeChain(globalObject->globalScopeChain())
+ , m_executable(exec->globalData(), this, thunk)
+ , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
{
+ ASSERT(inherits(&s_info));
putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
}
-#endif
-JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeFunction func)
: Base(globalObject, structure)
-#if ENABLE(JIT)
- , m_executable(exec->globalData().getHostFunction(func))
-#endif
- , m_scopeChain(globalObject->globalScopeChain())
+ , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
{
+ ASSERT(inherits(&s_info));
+ // We separate out intialisation from setting the executable
+ // as getHostFunction may perform a GC allocation, so we have to be able to
+ // mark ourselves safely
+ m_executable.set(exec->globalData(), this, exec->globalData().getHostFunction(func));
putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
-#if ENABLE(JIT)
putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
-#else
- UNUSED_PARAM(length);
- UNUSED_PARAM(func);
- ASSERT_NOT_REACHED();
-#endif
}
-JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
- : Base(scopeChainNode->globalObject, scopeChainNode->globalObject->functionStructure())
- , m_executable(executable)
- , m_scopeChain(scopeChainNode)
+JSFunction::JSFunction(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
+ : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure())
+ , m_executable(exec->globalData(), this, executable)
+ , m_scopeChain(exec->globalData(), this, scopeChainNode)
{
+ ASSERT(inherits(&s_info));
const Identifier& name = static_cast<FunctionExecutable*>(m_executable.get())->name();
putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
}
@@ -105,19 +97,6 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> ex
JSFunction::~JSFunction()
{
ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
-
- // JIT code for other functions may have had calls linked directly to the code for this function; these links
- // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
- // this memory is freed and may be reused (potentially for another, different JSFunction).
- if (!isHostFunction()) {
-#if ENABLE(JIT_OPTIMIZE_CALL)
- ASSERT(m_executable);
- if (jsExecutable()->isGeneratedForCall())
- jsExecutable()->generatedBytecodeForCall().unlinkCallers();
- if (jsExecutable()->isGeneratedForConstruct())
- jsExecutable()->generatedBytecodeForConstruct().unlinkCallers();
-#endif
- }
}
static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function";
@@ -131,12 +110,12 @@ static void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescrip
const UString& JSFunction::name(ExecState* exec)
{
- return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue();
+ return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
}
const UString JSFunction::displayName(ExecState* exec)
{
- JSValue displayName = getDirect(exec->globalData().propertyNames->displayName);
+ JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
if (displayName && isJSString(&exec->globalData(), displayName))
return asString(displayName)->tryGetValue();
@@ -157,22 +136,24 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec)
void JSFunction::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- if (!isHostFunction()) {
- jsExecutable()->markAggregate(markStack);
- scope().markAggregate(markStack);
+
+ markStack.append(&m_scopeChain);
+ if (m_executable) {
+ // Delightful race condition: m_executable may not have been initialised
+ // if this is a host function, as the executable isn't necessarily created
+ // until after the function has been allocated.
+ markStack.append(&m_executable);
}
}
CallType JSFunction::getCallData(CallData& callData)
{
-#if ENABLE(JIT)
if (isHostFunction()) {
callData.native.function = nativeFunction();
return CallTypeHost;
}
-#endif
callData.js.functionExecutable = jsExecutable();
- callData.js.scopeChain = scope().node();
+ callData.js.scopeChain = scope();
return CallTypeJS;
}
@@ -203,13 +184,13 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
return Base::getOwnPropertySlot(exec, propertyName, slot);
if (propertyName == exec->propertyNames().prototype) {
- WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName);
+ WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName);
if (!location) {
- JSObject* prototype = new (exec) JSObject(scope().globalObject()->emptyObjectStructure());
+ JSObject* prototype = constructEmptyObject(exec, scope()->globalObject->emptyObjectStructure());
prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, this, DontEnum);
putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
- location = getDirectLocation(propertyName);
+ location = getDirectLocation(exec->globalData(), propertyName);
}
slot.setValue(this, location->get(), offsetForLocation(location));
@@ -336,7 +317,7 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData)
if (isHostFunction())
return ConstructTypeNone;
constructData.js.functionExecutable = jsExecutable();
- constructData.js.scopeChain = scope().node();
+ constructData.js.scopeChain = scope();
return ConstructTypeJS;
}
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index 3a2fe30..174cd38 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -34,6 +34,7 @@ namespace JSC {
class JSActivation;
class JSGlobalObject;
class NativeExecutable;
+ class VPtrHackExecutable;
EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
@@ -44,26 +45,24 @@ namespace JSC {
typedef JSObjectWithGlobalObject Base;
public:
- JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
-#if ENABLE(JIT)
- JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, PassRefPtr<NativeExecutable>);
-#endif
- JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*);
+ JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeFunction);
+ JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeExecutable*);
+ JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
virtual ~JSFunction();
const UString& name(ExecState*);
const UString displayName(ExecState*);
const UString calculatedDisplayName(ExecState*);
- ScopeChain& scope()
+ ScopeChainNode* scope()
{
ASSERT(!isHostFunctionNonInline());
- return m_scopeChain;
+ return m_scopeChain.get();
}
- void setScope(const ScopeChain& scopeChain)
+ void setScope(JSGlobalData& globalData, ScopeChainNode* scopeChain)
{
ASSERT(!isHostFunctionNonInline());
- m_scopeChain = scopeChain;
+ m_scopeChain.set(globalData, this, scopeChain);
}
ExecutableBase* executable() const { return m_executable.get(); }
@@ -72,11 +71,11 @@ namespace JSC {
inline bool isHostFunction() const;
FunctionExecutable* jsExecutable() const;
- static JS_EXPORTDATA const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
NativeFunction nativeFunction();
@@ -88,7 +87,7 @@ namespace JSC {
const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
private:
- JSFunction(NonNullPassRefPtr<Structure>);
+ explicit JSFunction(VPtrStealingHackType);
bool isHostFunctionNonInline() const;
@@ -100,21 +99,19 @@ namespace JSC {
virtual void markChildren(MarkStack&);
- virtual const ClassInfo* classInfo() const { return &info; }
-
static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
static JSValue callerGetter(ExecState*, JSValue, const Identifier&);
static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
- RefPtr<ExecutableBase> m_executable;
- ScopeChain m_scopeChain;
+ WriteBarrier<ExecutableBase> m_executable;
+ WriteBarrier<ScopeChainNode> m_scopeChain;
};
JSFunction* asFunction(JSValue);
inline JSFunction* asFunction(JSValue value)
{
- ASSERT(asObject(value)->inherits(&JSFunction::info));
+ ASSERT(asObject(value)->inherits(&JSFunction::s_info));
return static_cast<JSFunction*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index ff88048..d9e5df0 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -45,6 +45,7 @@
#include "JSNotAnObject.h"
#include "JSPropertyNameIterator.h"
#include "JSStaticScopeObject.h"
+#include "JSZombie.h"
#include "Lexer.h"
#include "Lookup.h"
#include "Nodes.h"
@@ -68,6 +69,27 @@
using namespace WTF;
+namespace {
+
+using namespace JSC;
+
+class Recompiler {
+public:
+ void operator()(JSCell*);
+};
+
+inline void Recompiler::operator()(JSCell* cell)
+{
+ if (!cell->inherits(&JSFunction::s_info))
+ return;
+ JSFunction* function = asFunction(cell);
+ if (function->executable()->isHostFunction())
+ return;
+ function->jsExecutable()->discardCode();
+}
+
+} // namespace
+
namespace JSC {
extern JSC_CONST_HASHTABLE HashTable arrayTable;
@@ -75,6 +97,7 @@ extern JSC_CONST_HASHTABLE HashTable jsonTable;
extern JSC_CONST_HASHTABLE HashTable dateTable;
extern JSC_CONST_HASHTABLE HashTable mathTable;
extern JSC_CONST_HASHTABLE HashTable numberTable;
+extern JSC_CONST_HASHTABLE HashTable objectConstructorTable;
extern JSC_CONST_HASHTABLE HashTable regExpTable;
extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
extern JSC_CONST_HASHTABLE HashTable stringTable;
@@ -84,6 +107,15 @@ void* JSGlobalData::jsByteArrayVPtr;
void* JSGlobalData::jsStringVPtr;
void* JSGlobalData::jsFunctionVPtr;
+#if COMPILER(GCC)
+// Work around for gcc trying to coalesce our reads of the various cell vptrs
+#define CLOBBER_MEMORY() do { \
+ asm volatile ("" : : : "memory"); \
+} while (false)
+#else
+#define CLOBBER_MEMORY() do { } while (false)
+#endif
+
void JSGlobalData::storeVPtrs()
{
// Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
@@ -92,23 +124,23 @@ void JSGlobalData::storeVPtrs()
COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
+ CLOBBER_MEMORY();
JSGlobalData::jsArrayVPtr = jsArray->vptr();
- jsArray->~JSCell();
COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
+ CLOBBER_MEMORY();
JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
- jsByteArray->~JSCell();
COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
+ CLOBBER_MEMORY();
JSGlobalData::jsStringVPtr = jsString->vptr();
- jsString->~JSCell();
COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
- JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
+ JSCell* jsFunction = new (storage) JSFunction(JSCell::VPtrStealingHack);
+ CLOBBER_MEMORY();
JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
- jsFunction->~JSCell();
}
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType)
@@ -119,29 +151,19 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, jsonTable(fastNew<HashTable>(JSC::jsonTable))
, mathTable(fastNew<HashTable>(JSC::mathTable))
, numberTable(fastNew<HashTable>(JSC::numberTable))
+ , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
, regExpTable(fastNew<HashTable>(JSC::regExpTable))
, regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
, stringTable(fastNew<HashTable>(JSC::stringTable))
- , activationStructure(JSActivation::createStructure(jsNull()))
- , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
- , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull()))
- , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
- , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull()))
- , stringStructure(JSString::createStructure(jsNull()))
- , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
- , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
- , getterSetterStructure(GetterSetter::createStructure(jsNull()))
- , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
- , dummyMarkableCellStructure(JSCell::createDummyStructure())
, identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
, propertyNames(new CommonIdentifiers(this))
, emptyList(new MarkedArgumentBuffer)
, lexer(new Lexer(this))
, parser(new Parser)
- , interpreter(new Interpreter)
+ , interpreter(0)
, heap(this)
+ , globalObjectCount(0)
, dynamicGlobalObject(0)
- , firstStringifierToMark(0)
, cachedUTCOffset(NaN)
, maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
, m_regExpCache(new RegExpCache(this))
@@ -152,14 +174,44 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, exclusiveThread(0)
#endif
{
+ interpreter = new Interpreter(*this);
if (globalDataType == Default)
m_stack = wtfThreadData().stack();
+ // Need to be careful to keep everything consistent here
+ IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
+ JSLock lock(SilenceAssertionsOnly);
+ structureStructure.set(*this, Structure::createStructure(*this));
+ activationStructure.set(*this, JSActivation::createStructure(*this, jsNull()));
+ interruptedExecutionErrorStructure.set(*this, JSNonFinalObject::createStructure(*this, jsNull()));
+ terminatedExecutionErrorStructure.set(*this, JSNonFinalObject::createStructure(*this, jsNull()));
+ staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, jsNull()));
+ strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, jsNull()));
+ stringStructure.set(*this, JSString::createStructure(*this, jsNull()));
+ notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, jsNull()));
+ propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, jsNull()));
+ getterSetterStructure.set(*this, GetterSetter::createStructure(*this, jsNull()));
+ apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, jsNull()));
+ scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, jsNull()));
+ executableStructure.set(*this, ExecutableBase::createStructure(*this, jsNull()));
+ nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, jsNull()));
+ evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, jsNull()));
+ programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, jsNull()));
+ functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, jsNull()));
+ dummyMarkableCellStructure.set(*this, JSCell::createDummyStructure(*this));
+ structureChainStructure.set(*this, StructureChain::createStructure(*this, jsNull()));
+
+#if ENABLE(JSC_ZOMBIES)
+ zombieStructure.set(*this, JSZombie::createStructure(*this, jsNull()));
+#endif
+
+ wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
+
#if PLATFORM(MAC)
startProfilerServerIfNeeded();
#endif
#if ENABLE(JIT) && ENABLE(INTERPRETER)
-#if PLATFORM(CF)
+#if USE(CF)
CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
if (canUseJIT) {
@@ -186,6 +238,33 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
#endif
}
+void JSGlobalData::clearBuiltinStructures()
+{
+ structureStructure.clear();
+ activationStructure.clear();
+ interruptedExecutionErrorStructure.clear();
+ terminatedExecutionErrorStructure.clear();
+ staticScopeStructure.clear();
+ strictEvalActivationStructure.clear();
+ stringStructure.clear();
+ notAnObjectStructure.clear();
+ propertyNameIteratorStructure.clear();
+ getterSetterStructure.clear();
+ apiWrapperStructure.clear();
+ scopeChainNodeStructure.clear();
+ executableStructure.clear();
+ nativeExecutableStructure.clear();
+ evalExecutableStructure.clear();
+ programExecutableStructure.clear();
+ functionExecutableStructure.clear();
+ dummyMarkableCellStructure.clear();
+ structureChainStructure.clear();
+
+#if ENABLE(JSC_ZOMBIES)
+ zombieStructure.clear();
+#endif
+}
+
JSGlobalData::~JSGlobalData()
{
// By the time this is destroyed, heap.destroy() must already have been called.
@@ -201,6 +280,7 @@ JSGlobalData::~JSGlobalData()
jsonTable->deleteTable();
mathTable->deleteTable();
numberTable->deleteTable();
+ objectConstructorTable->deleteTable();
regExpTable->deleteTable();
regExpConstructorTable->deleteTable();
stringTable->deleteTable();
@@ -210,6 +290,7 @@ JSGlobalData::~JSGlobalData()
fastDelete(const_cast<HashTable*>(jsonTable));
fastDelete(const_cast<HashTable*>(mathTable));
fastDelete(const_cast<HashTable*>(numberTable));
+ fastDelete(const_cast<HashTable*>(objectConstructorTable));
fastDelete(const_cast<HashTable*>(regExpTable));
fastDelete(const_cast<HashTable*>(regExpConstructorTable));
fastDelete(const_cast<HashTable*>(stringTable));
@@ -244,10 +325,7 @@ PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type)
{
- Structure::startIgnoringLeaks();
- RefPtr<JSGlobalData> data = create(type);
- Structure::stopIgnoringLeaks();
- return data.release();
+ return create(type);
}
bool JSGlobalData::sharedInstanceExists()
@@ -275,14 +353,19 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal()
}
#if ENABLE(JIT)
-PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
{
return jitStubs->hostFunctionStub(this, function);
}
-PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
{
return jitStubs->hostFunctionStub(this, function, generator);
}
+#else
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
+{
+ return NativeExecutable::create(*this, function, callHostFunctionAsConstructor);
+}
#endif
JSGlobalData::ClientData::~ClientData()
@@ -313,22 +396,6 @@ void JSGlobalData::dumpSampleData(ExecState* exec)
interpreter->dumpSampleData(exec);
}
-class Recompiler {
-public:
- void operator()(JSCell*);
-};
-
-inline void Recompiler::operator()(JSCell* cell)
-{
- if (!cell->inherits(&JSFunction::info))
- return;
- JSFunction* function = asFunction(cell);
- if (function->executable()->isHostFunction())
- return;
- function->jsExecutable()->discardCode();
-}
-
-
void JSGlobalData::recompileAllJSFunctions()
{
// If JavaScript is running, it's not safe to recompile, since we'll end
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index 7b69055..f1085af 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -33,13 +33,13 @@
#include "Heap.h"
#include "DateInstanceCache.h"
#include "ExecutableAllocator.h"
+#include "Strong.h"
#include "JITStubs.h"
#include "JSValue.h"
#include "NumericStrings.h"
#include "SmallStrings.h"
#include "Terminator.h"
#include "TimeoutChecker.h"
-#include "WeakGCMap.h"
#include "WeakRandom.h"
#include <wtf/BumpPointerAllocator.h>
#include <wtf/Forward.h>
@@ -58,11 +58,13 @@ namespace JSC {
class CodeBlock;
class CommonIdentifiers;
+ class HandleStack;
class IdentifierTable;
class Interpreter;
class JSGlobalObject;
class JSObject;
class Lexer;
+ class NativeExecutable;
class Parser;
class RegExpCache;
class Stringifier;
@@ -75,8 +77,6 @@ namespace JSC {
struct HashTable;
struct Instruction;
- typedef WeakGCMap<JSGlobalObject*, JSGlobalObject> GlobalObjectMap; // FIXME: Would be nice to use a WeakGCSet here.
-
struct DSTOffsetCache {
DSTOffsetCache()
{
@@ -130,7 +130,7 @@ namespace JSC {
#if ENABLE(JSC_MULTIPLE_THREADS)
// Will start tracking threads that use the heap, which is resource-heavy.
- void makeUsableFromMultipleThreads() { heap.machineStackMarker().makeUsableFromMultipleThreads(); }
+ void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
#endif
GlobalDataType globalDataType;
@@ -141,21 +141,34 @@ namespace JSC {
const HashTable* jsonTable;
const HashTable* mathTable;
const HashTable* numberTable;
+ const HashTable* objectConstructorTable;
const HashTable* regExpTable;
const HashTable* regExpConstructorTable;
const HashTable* stringTable;
- RefPtr<Structure> activationStructure;
- RefPtr<Structure> interruptedExecutionErrorStructure;
- RefPtr<Structure> terminatedExecutionErrorStructure;
- RefPtr<Structure> staticScopeStructure;
- RefPtr<Structure> strictEvalActivationStructure;
- RefPtr<Structure> stringStructure;
- RefPtr<Structure> notAnObjectStructure;
- RefPtr<Structure> propertyNameIteratorStructure;
- RefPtr<Structure> getterSetterStructure;
- RefPtr<Structure> apiWrapperStructure;
- RefPtr<Structure> dummyMarkableCellStructure;
+ Strong<Structure> structureStructure;
+ Strong<Structure> activationStructure;
+ Strong<Structure> interruptedExecutionErrorStructure;
+ Strong<Structure> terminatedExecutionErrorStructure;
+ Strong<Structure> staticScopeStructure;
+ Strong<Structure> strictEvalActivationStructure;
+ Strong<Structure> stringStructure;
+ Strong<Structure> notAnObjectStructure;
+ Strong<Structure> propertyNameIteratorStructure;
+ Strong<Structure> getterSetterStructure;
+ Strong<Structure> apiWrapperStructure;
+ Strong<Structure> scopeChainNodeStructure;
+ Strong<Structure> executableStructure;
+ Strong<Structure> nativeExecutableStructure;
+ Strong<Structure> evalExecutableStructure;
+ Strong<Structure> programExecutableStructure;
+ Strong<Structure> functionExecutableStructure;
+ Strong<Structure> dummyMarkableCellStructure;
+ Strong<Structure> structureChainStructure;
+
+#if ENABLE(JSC_ZOMBIES)
+ Strong<Structure> zombieStructure;
+#endif
static void storeVPtrs();
static JS_EXPORTDATA void* jsArrayVPtr;
@@ -199,27 +212,26 @@ namespace JSC {
{
return jitStubs->ctiStub(this, generator);
}
- PassRefPtr<NativeExecutable> getHostFunction(NativeFunction function);
- PassRefPtr<NativeExecutable> getHostFunction(NativeFunction function, ThunkGenerator generator);
+ NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator);
#endif
+ NativeExecutable* getHostFunction(NativeFunction);
+
TimeoutChecker timeoutChecker;
Terminator terminator;
Heap heap;
- DeprecatedPtr<Unknown> exception;
+ JSValue exception;
#if ENABLE(JIT)
ReturnAddressPtr exceptionLocation;
#endif
HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
- GlobalObjectMap globalObjects;
+ unsigned globalObjectCount;
JSGlobalObject* dynamicGlobalObject;
HashSet<JSObject*> stringRecursionCheckVisitedObjects;
- Stringifier* firstStringifierToMark;
-
double cachedUTCOffset;
DSTOffsetCache dstOffsetCache;
@@ -253,6 +265,10 @@ namespace JSC {
void addRegExpToTrace(PassRefPtr<RegExp> regExp);
#endif
void dumpRegExpTrace();
+ HandleSlot allocateGlobalHandle() { return heap.allocateGlobalHandle(); }
+ HandleSlot allocateLocalHandle() { return heap.allocateLocalHandle(); }
+ void clearBuiltinStructures();
+
private:
JSGlobalData(GlobalDataType, ThreadStackType);
static JSGlobalData*& sharedInstanceInternal();
@@ -263,6 +279,11 @@ namespace JSC {
StackBounds m_stack;
};
+ inline HandleSlot allocateGlobalHandle(JSGlobalData& globalData)
+ {
+ return globalData.allocateGlobalHandle();
+ }
+
} // namespace JSC
#endif // JSGlobalData_h
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index f303196..b82949a 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -46,7 +46,6 @@
#include "ErrorPrototype.h"
#include "FunctionConstructor.h"
#include "FunctionPrototype.h"
-#include "GlobalEvalFunction.h"
#include "JSFunction.h"
#include "JSGlobalObjectFunctions.h"
#include "JSLock.h"
@@ -60,7 +59,6 @@
#include "ObjectConstructor.h"
#include "ObjectPrototype.h"
#include "Profiler.h"
-#include "PrototypeFunction.h"
#include "RegExpConstructor.h"
#include "RegExpMatchesArray.h"
#include "RegExpObject.h"
@@ -86,30 +84,17 @@ template <typename T> static inline void markIfNeeded(MarkStack& markStack, Writ
markStack.append(v);
}
-static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s)
-{
- if (s && s->storedPrototype())
- markStack.append(s->storedPrototypeSlot());
-}
-
JSGlobalObject::~JSGlobalObject()
{
ASSERT(JSLock::currentThreadIsHoldingLock());
- if (d()->debugger)
- d()->debugger->detach(this);
+ if (m_debugger)
+ m_debugger->detach(this);
Profiler** profiler = Profiler::enabledProfilerReference();
if (UNLIKELY(*profiler != 0)) {
- (*profiler)->stopProfiling(globalExec(), UString());
+ (*profiler)->stopProfiling(this);
}
-
- d()->globalData->globalObjects.take(this);
-
- RegisterFile& registerFile = globalData().interpreter->registerFile();
- if (registerFile.clearGlobalObject(this))
- registerFile.setNumGlobals(0);
- d()->destructor(d());
}
void JSGlobalObject::init(JSObject* thisValue)
@@ -118,15 +103,14 @@ void JSGlobalObject::init(JSObject* thisValue)
structure()->disableSpecificFunctionTracking();
- d()->globalData = Heap::heap(this)->globalData();
- d()->globalData->globalObjects.set(this, this);
- d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), this, thisValue);
+ m_globalData = Heap::heap(this)->globalData();
+ m_globalScopeChain.set(*m_globalData, this, new (m_globalData.get()) ScopeChainNode(0, this, m_globalData.get(), this, thisValue));
- JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0);
+ JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0);
- d()->debugger = 0;
+ m_debugger = 0;
- d()->profileGroup = 0;
+ m_profileGroup = 0;
reset(prototype());
}
@@ -135,7 +119,7 @@ void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValu
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
- if (symbolTablePut(propertyName, value))
+ if (symbolTablePut(exec->globalData(), propertyName, value))
return;
JSVariableObject::put(exec, propertyName, value, slot);
}
@@ -144,14 +128,14 @@ void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& proper
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
- if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
return;
- JSValue valueBefore = getDirect(propertyName);
+ JSValue valueBefore = getDirect(exec->globalData(), propertyName);
PutPropertySlot slot;
JSVariableObject::put(exec, propertyName, value, slot);
if (!valueBefore) {
- JSValue valueAfter = getDirect(propertyName);
+ JSValue valueAfter = getDirect(exec->globalData(), propertyName);
if (valueAfter)
JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes);
}
@@ -185,81 +169,80 @@ void JSGlobalObject::reset(JSValue prototype)
// Prototypes
- d()->functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull()))); // The real prototype will be set once ObjectPrototype is created.
- d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype.get());
- d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype.get());
- NativeFunctionWrapper* callFunction = 0;
- NativeFunctionWrapper* applyFunction = 0;
- d()->functionPrototype->addFunctionProperties(exec, this, d()->prototypeFunctionStructure.get(), &callFunction, &applyFunction);
- d()->callFunction.set(exec->globalData(), this, callFunction);
- d()->applyFunction.set(exec->globalData(), this, applyFunction);
- d()->objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get()));
- d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype.get());
+ m_functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(exec->globalData(), jsNull()))); // The real prototype will be set once ObjectPrototype is created.
+ m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), m_functionPrototype.get()));
+ m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), m_functionPrototype.get()));
+ JSFunction* callFunction = 0;
+ JSFunction* applyFunction = 0;
+ m_functionPrototype->addFunctionProperties(exec, this, m_functionStructure.get(), &callFunction, &applyFunction);
+ m_callFunction.set(exec->globalData(), this, callFunction);
+ m_applyFunction.set(exec->globalData(), this, applyFunction);
+ m_objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(exec->globalData(), jsNull()), m_functionStructure.get()));
+ m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get());
- d()->emptyObjectStructure = d()->objectPrototype->inheritorID();
+ m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));
- d()->functionStructure = JSFunction::createStructure(d()->functionPrototype.get());
- d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype.get());
- d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype.get());
- d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype.get());
- d()->callbackObjectStructure = JSCallbackObject<JSObjectWithGlobalObject>::createStructure(d()->objectPrototype.get());
+ m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), m_functionPrototype.get()));
+ m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), m_objectPrototype.get()));
+ m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), m_objectPrototype.get()));
+ m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSObjectWithGlobalObject>::createStructure(exec->globalData(), m_objectPrototype.get()));
- d()->arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(d()->objectPrototype.get())));
- d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype.get());
- d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype.get());
+ m_arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+ m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), m_arrayPrototype.get()));
+ m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), m_arrayPrototype.get()));
- d()->stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(d()->objectPrototype.get())));
- d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype.get());
+ m_stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+ m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), m_stringPrototype.get()));
- d()->booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get()));
- d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype.get());
+ m_booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get()));
+ m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), m_booleanPrototype.get()));
- d()->numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get()));
- d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype.get());
+ m_numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get()));
+ m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), m_numberPrototype.get()));
- d()->datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(d()->objectPrototype.get())));
- d()->dateStructure = DateInstance::createStructure(d()->datePrototype.get());
+ m_datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+ m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), m_datePrototype.get()));
- d()->regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get()));
- d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype.get());
+ m_regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get()));
+ m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), m_regExpPrototype.get()));
- d()->methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec));
+ m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec));
- ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get());
- d()->errorStructure = ErrorInstance::createStructure(errorPrototype);
+ ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get());
+ m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), errorPrototype));
// Constructors
- JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(d()->functionPrototype.get()), d()->objectPrototype.get(), d()->prototypeFunctionStructure.get());
- JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(d()->functionPrototype.get()), d()->functionPrototype.get());
- JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(d()->functionPrototype.get()), d()->arrayPrototype.get(), d()->prototypeFunctionStructure.get());
- JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(d()->functionPrototype.get()), d()->prototypeFunctionStructure.get(), d()->stringPrototype.get());
- JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(d()->functionPrototype.get()), d()->booleanPrototype.get());
- JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(d()->functionPrototype.get()), d()->numberPrototype.get());
- JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(d()->functionPrototype.get()), d()->prototypeFunctionStructure.get(), d()->datePrototype.get());
-
- d()->regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(d()->functionPrototype.get()), d()->regExpPrototype.get()));
-
- d()->errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(d()->functionPrototype.get()), errorPrototype));
-
- RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(errorPrototype);
- RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype.get());
- d()->evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError"));
- d()->rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError"));
- d()->referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError"));
- d()->syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError"));
- d()->typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError"));
- d()->URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError"));
-
- d()->objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum);
- d()->functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum);
- d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum);
- d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum);
- d()->stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum);
- d()->numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum);
- d()->datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum);
- d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->regExpConstructor.get(), DontEnum);
- errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->errorConstructor.get(), DontEnum);
+ JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_objectPrototype.get());
+ JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionPrototype.get());
+ JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_arrayPrototype.get(), m_functionStructure.get());
+ JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionStructure.get(), m_stringPrototype.get());
+ JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_booleanPrototype.get());
+ JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_numberPrototype.get());
+ JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionStructure.get(), m_datePrototype.get());
+
+ m_regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_regExpPrototype.get()));
+
+ m_errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), errorPrototype));
+
+ Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), errorPrototype);
+ Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get());
+ m_evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError"));
+ m_rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError"));
+ m_referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError"));
+ m_syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError"));
+ m_typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError"));
+ m_URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError"));
+
+ m_objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum);
+ m_functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum);
+ m_arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum);
+ m_booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum);
+ m_stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum);
+ m_numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum);
+ m_datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum);
+ m_regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum);
+ errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum);
// Set global constructors
@@ -272,121 +255,118 @@ void JSGlobalObject::reset(JSValue prototype)
putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum);
putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum);
putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), d()->regExpConstructor.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), d()->errorConstructor.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), d()->evalErrorConstructor.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), d()->rangeErrorConstructor.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), d()->typeErrorConstructor.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), d()->URIErrorConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum);
// Set global values.
GlobalPropertyInfo staticGlobals[] = {
- GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete),
GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(Inf), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly),
- GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete)
+ GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete)
};
addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
// Set global functions.
- d()->evalFunction.set(exec->globalData(), this, new (exec) GlobalEvalFunction(exec, this, GlobalEvalFunction::createStructure(d()->functionPrototype.get()), 1, exec->propertyNames().eval, globalFuncEval, this));
- putDirectFunctionWithoutTransition(exec, d()->evalFunction.get(), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum);
+ m_evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval));
+ putDirectFunctionWithoutTransition(exec, m_evalFunction.get(), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum);
#ifndef NDEBUG
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum);
#endif
- resetPrototype(prototype);
+ resetPrototype(exec->globalData(), prototype);
}
// Set prototype, and also insert the object prototype at the end of the chain.
-void JSGlobalObject::resetPrototype(JSValue prototype)
+void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
{
- setPrototype(prototype);
+ setPrototype(globalData, prototype);
JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this);
- JSObject* objectPrototype = d()->objectPrototype.get();
+ JSObject* objectPrototype = m_objectPrototype.get();
if (oldLastInPrototypeChain != objectPrototype)
- oldLastInPrototypeChain->setPrototype(objectPrototype);
+ oldLastInPrototypeChain->setPrototype(globalData, objectPrototype);
}
void JSGlobalObject::markChildren(MarkStack& markStack)
{
JSVariableObject::markChildren(markStack);
-
- markIfNeeded(markStack, &d()->regExpConstructor);
- markIfNeeded(markStack, &d()->errorConstructor);
- markIfNeeded(markStack, &d()->evalErrorConstructor);
- markIfNeeded(markStack, &d()->rangeErrorConstructor);
- markIfNeeded(markStack, &d()->referenceErrorConstructor);
- markIfNeeded(markStack, &d()->syntaxErrorConstructor);
- markIfNeeded(markStack, &d()->typeErrorConstructor);
- markIfNeeded(markStack, &d()->URIErrorConstructor);
-
- markIfNeeded(markStack, &d()->evalFunction);
- markIfNeeded(markStack, &d()->callFunction);
- markIfNeeded(markStack, &d()->applyFunction);
-
- markIfNeeded(markStack, &d()->objectPrototype);
- markIfNeeded(markStack, &d()->functionPrototype);
- markIfNeeded(markStack, &d()->arrayPrototype);
- markIfNeeded(markStack, &d()->booleanPrototype);
- markIfNeeded(markStack, &d()->stringPrototype);
- markIfNeeded(markStack, &d()->numberPrototype);
- markIfNeeded(markStack, &d()->datePrototype);
- markIfNeeded(markStack, &d()->regExpPrototype);
-
- markIfNeeded(markStack, &d()->methodCallDummy);
-
- markIfNeeded(markStack, d()->errorStructure);
- markIfNeeded(markStack, d()->argumentsStructure);
- markIfNeeded(markStack, d()->arrayStructure);
- markIfNeeded(markStack, d()->booleanObjectStructure);
- markIfNeeded(markStack, d()->callbackConstructorStructure);
- markIfNeeded(markStack, d()->callbackFunctionStructure);
- markIfNeeded(markStack, d()->callbackObjectStructure);
- markIfNeeded(markStack, d()->dateStructure);
- markIfNeeded(markStack, d()->emptyObjectStructure);
- markIfNeeded(markStack, d()->errorStructure);
- markIfNeeded(markStack, d()->functionStructure);
- markIfNeeded(markStack, d()->numberObjectStructure);
- markIfNeeded(markStack, d()->prototypeFunctionStructure);
- markIfNeeded(markStack, d()->regExpMatchesArrayStructure);
- markIfNeeded(markStack, d()->regExpStructure);
- markIfNeeded(markStack, d()->stringObjectStructure);
-
- // No need to mark the other structures, because their prototypes are all
- // guaranteed to be referenced elsewhere.
-
- if (d()->registerArray) {
+
+ markIfNeeded(markStack, &m_globalScopeChain);
+ markIfNeeded(markStack, &m_methodCallDummy);
+
+ markIfNeeded(markStack, &m_regExpConstructor);
+ markIfNeeded(markStack, &m_errorConstructor);
+ markIfNeeded(markStack, &m_evalErrorConstructor);
+ markIfNeeded(markStack, &m_rangeErrorConstructor);
+ markIfNeeded(markStack, &m_referenceErrorConstructor);
+ markIfNeeded(markStack, &m_syntaxErrorConstructor);
+ markIfNeeded(markStack, &m_typeErrorConstructor);
+ markIfNeeded(markStack, &m_URIErrorConstructor);
+
+ markIfNeeded(markStack, &m_evalFunction);
+ markIfNeeded(markStack, &m_callFunction);
+ markIfNeeded(markStack, &m_applyFunction);
+
+ markIfNeeded(markStack, &m_objectPrototype);
+ markIfNeeded(markStack, &m_functionPrototype);
+ markIfNeeded(markStack, &m_arrayPrototype);
+ markIfNeeded(markStack, &m_booleanPrototype);
+ markIfNeeded(markStack, &m_stringPrototype);
+ markIfNeeded(markStack, &m_numberPrototype);
+ markIfNeeded(markStack, &m_datePrototype);
+ markIfNeeded(markStack, &m_regExpPrototype);
+
+ markIfNeeded(markStack, &m_argumentsStructure);
+ markIfNeeded(markStack, &m_arrayStructure);
+ markIfNeeded(markStack, &m_booleanObjectStructure);
+ markIfNeeded(markStack, &m_callbackConstructorStructure);
+ markIfNeeded(markStack, &m_callbackFunctionStructure);
+ markIfNeeded(markStack, &m_callbackObjectStructure);
+ markIfNeeded(markStack, &m_dateStructure);
+ markIfNeeded(markStack, &m_emptyObjectStructure);
+ markIfNeeded(markStack, &m_errorStructure);
+ markIfNeeded(markStack, &m_functionStructure);
+ markIfNeeded(markStack, &m_numberObjectStructure);
+ markIfNeeded(markStack, &m_regExpMatchesArrayStructure);
+ markIfNeeded(markStack, &m_regExpStructure);
+ markIfNeeded(markStack, &m_stringObjectStructure);
+ markIfNeeded(markStack, &m_internalFunctionStructure);
+
+ if (m_registerArray) {
// Outside the execution of global code, when our variables are torn off,
// we can mark the torn-off array.
- markStack.deprecatedAppendValues(d()->registerArray.get(), d()->registerArraySize);
- } else if (d()->registers) {
+ markStack.appendValues(m_registerArray.get(), m_registerArraySize);
+ } else if (m_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.deprecatedAppendValues(d()->registers - symbolTable().size(), symbolTable().size());
+ markStack.appendValues(m_registers - symbolTable().size(), symbolTable().size());
}
}
ExecState* JSGlobalObject::globalExec()
{
- return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize);
+ return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize);
}
bool JSGlobalObject::isDynamicScope(bool&) const
@@ -396,17 +376,17 @@ bool JSGlobalObject::isDynamicScope(bool&) const
void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
{
- ASSERT(!d()->registerArray);
- ASSERT(!d()->registerArraySize);
+ ASSERT(!m_registerArray);
+ ASSERT(!m_registerArraySize);
int numGlobals = registerFile.numGlobals();
if (!numGlobals) {
- d()->registers = 0;
+ m_registers = 0;
return;
}
- OwnArrayPtr<Register> registerArray = copyRegisterArray(registerFile.lastGlobal(), numGlobals);
- Register* registers = registerArray.get() + numGlobals;
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData(), reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.lastGlobal()), numGlobals, numGlobals);
+ WriteBarrier<Unknown>* registers = registerArray.get() + numGlobals;
setRegisters(registers, registerArray.release(), numGlobals);
}
@@ -419,37 +399,55 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
registerFile.setGlobalObject(this);
registerFile.setNumGlobals(symbolTable().size());
- if (d()->registerArray) {
- memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(Register));
- setRegisters(registerFile.start(), 0, 0);
+ if (m_registerArray) {
+ // The register file is always a gc root so no barrier is needed here
+ memcpy(registerFile.start() - m_registerArraySize, m_registerArray.get(), m_registerArraySize * sizeof(WriteBarrier<Unknown>));
+ setRegisters(reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.start()), nullptr, 0);
}
}
-void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
+void JSGlobalObject::resizeRegisters(int oldSize, int newSize)
{
- return globalData->heap.allocate(size);
+ ASSERT(oldSize <= newSize);
+ if (newSize == oldSize)
+ return;
+ ASSERT(newSize && newSize > oldSize);
+ if (m_registerArray || !m_registers) {
+ ASSERT(static_cast<size_t>(oldSize) == m_registerArraySize);
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]);
+ for (int i = 0; i < oldSize; i++)
+ registerArray[newSize - oldSize + i].set(globalData(), this, m_registerArray[i].get());
+ WriteBarrier<Unknown>* registers = registerArray.get() + newSize;
+ setRegisters(registers, registerArray.release(), newSize);
+ } else {
+ ASSERT(static_cast<size_t>(newSize) < globalData().interpreter->registerFile().maxGlobals());
+ globalData().interpreter->registerFile().setNumGlobals(newSize);
+ }
+
+ for (int i = -newSize; i < -oldSize; ++i)
+ m_registers[i].setUndefined();
}
-void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData)
+void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
{
- delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData);
+ return globalData->heap.allocate(size);
}
-DynamicGlobalObjectScope::DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
- : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
+DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject)
+ : m_dynamicGlobalObjectSlot(globalData.dynamicGlobalObject)
, m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
{
if (!m_dynamicGlobalObjectSlot) {
#if ENABLE(ASSEMBLER)
if (ExecutableAllocator::underMemoryPressure())
- callFrame->globalData().recompileAllJSFunctions();
+ globalData.recompileAllJSFunctions();
#endif
m_dynamicGlobalObjectSlot = dynamicGlobalObject;
// Reset the date cache between JS invocations to force the VM
// to observe time zone changes.
- callFrame->globalData().resetDateCache();
+ globalData.resetDateCache();
}
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index d13d2da..0e36920 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -26,9 +26,9 @@
#include "JSGlobalData.h"
#include "JSVariableObject.h"
#include "JSWeakObjectMapRefInternal.h"
-#include "NativeFunctionWrapper.h"
#include "NumberPrototype.h"
#include "StringPrototype.h"
+#include "StructureChain.h"
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/RandomNumber.h>
@@ -42,10 +42,8 @@ namespace JSC {
class ErrorConstructor;
class FunctionPrototype;
class GlobalCodeBlock;
- class GlobalEvalFunction;
class NativeErrorConstructor;
class ProgramCodeBlock;
- class PrototypeFunction;
class RegExpConstructor;
class RegExpPrototype;
class RegisterFile;
@@ -57,101 +55,81 @@ namespace JSC {
class JSGlobalObject : public JSVariableObject {
protected:
- using JSVariableObject::JSVariableObjectData;
typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
- struct JSGlobalObjectData : public JSVariableObjectData {
- // We use an explicit destructor function pointer instead of a
- // virtual destructor because we want to avoid adding a vtable
- // pointer to this struct. Adding a vtable pointer would force the
- // compiler to emit costly pointer fixup code when casting from
- // JSVariableObjectData* to JSGlobalObjectData*.
- typedef void (*Destructor)(void*);
-
- JSGlobalObjectData(Destructor destructor)
- : JSVariableObjectData(&symbolTable, 0)
- , destructor(destructor)
- , registerArraySize(0)
- , globalScopeChain(NoScopeChain())
- , weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
- {
- }
-
- Destructor destructor;
-
- size_t registerArraySize;
-
- JSGlobalObject* next;
- JSGlobalObject* prev;
-
- Debugger* debugger;
-
- ScopeChain globalScopeChain;
- Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
-
- WriteBarrier<RegExpConstructor> regExpConstructor;
- WriteBarrier<ErrorConstructor> errorConstructor;
- WriteBarrier<NativeErrorConstructor> evalErrorConstructor;
- WriteBarrier<NativeErrorConstructor> rangeErrorConstructor;
- WriteBarrier<NativeErrorConstructor> referenceErrorConstructor;
- WriteBarrier<NativeErrorConstructor> syntaxErrorConstructor;
- WriteBarrier<NativeErrorConstructor> typeErrorConstructor;
- WriteBarrier<NativeErrorConstructor> URIErrorConstructor;
-
- WriteBarrier<GlobalEvalFunction> evalFunction;
- WriteBarrier<NativeFunctionWrapper> callFunction;
- WriteBarrier<NativeFunctionWrapper> applyFunction;
-
- WriteBarrier<ObjectPrototype> objectPrototype;
- WriteBarrier<FunctionPrototype> functionPrototype;
- WriteBarrier<ArrayPrototype> arrayPrototype;
- WriteBarrier<BooleanPrototype> booleanPrototype;
- WriteBarrier<StringPrototype> stringPrototype;
- WriteBarrier<NumberPrototype> numberPrototype;
- WriteBarrier<DatePrototype> datePrototype;
- WriteBarrier<RegExpPrototype> regExpPrototype;
-
- WriteBarrier<JSObject> methodCallDummy;
-
- RefPtr<Structure> argumentsStructure;
- RefPtr<Structure> arrayStructure;
- RefPtr<Structure> booleanObjectStructure;
- RefPtr<Structure> callbackConstructorStructure;
- RefPtr<Structure> callbackFunctionStructure;
- RefPtr<Structure> callbackObjectStructure;
- RefPtr<Structure> dateStructure;
- RefPtr<Structure> emptyObjectStructure;
- RefPtr<Structure> errorStructure;
- RefPtr<Structure> functionStructure;
- RefPtr<Structure> numberObjectStructure;
- RefPtr<Structure> prototypeFunctionStructure;
- RefPtr<Structure> regExpMatchesArrayStructure;
- RefPtr<Structure> regExpStructure;
- RefPtr<Structure> stringObjectStructure;
- RefPtr<Structure> internalFunctionStructure;
-
- SymbolTable symbolTable;
- unsigned profileGroup;
-
- RefPtr<JSGlobalData> globalData;
-
- WeakMapSet weakMaps;
- WeakRandom weakRandom;
- };
+ RefPtr<JSGlobalData> m_globalData;
+
+ size_t m_registerArraySize;
+ Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize];
+
+ WriteBarrier<ScopeChainNode> m_globalScopeChain;
+ WriteBarrier<JSObject> m_methodCallDummy;
+
+ WriteBarrier<RegExpConstructor> m_regExpConstructor;
+ WriteBarrier<ErrorConstructor> m_errorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor;
+
+ WriteBarrier<JSFunction> m_evalFunction;
+ WriteBarrier<JSFunction> m_callFunction;
+ WriteBarrier<JSFunction> m_applyFunction;
+
+ WriteBarrier<ObjectPrototype> m_objectPrototype;
+ WriteBarrier<FunctionPrototype> m_functionPrototype;
+ WriteBarrier<ArrayPrototype> m_arrayPrototype;
+ WriteBarrier<BooleanPrototype> m_booleanPrototype;
+ WriteBarrier<StringPrototype> m_stringPrototype;
+ WriteBarrier<NumberPrototype> m_numberPrototype;
+ WriteBarrier<DatePrototype> m_datePrototype;
+ WriteBarrier<RegExpPrototype> m_regExpPrototype;
+
+ WriteBarrier<Structure> m_argumentsStructure;
+ WriteBarrier<Structure> m_arrayStructure;
+ WriteBarrier<Structure> m_booleanObjectStructure;
+ WriteBarrier<Structure> m_callbackConstructorStructure;
+ WriteBarrier<Structure> m_callbackFunctionStructure;
+ WriteBarrier<Structure> m_callbackObjectStructure;
+ WriteBarrier<Structure> m_dateStructure;
+ WriteBarrier<Structure> m_emptyObjectStructure;
+ WriteBarrier<Structure> m_errorStructure;
+ WriteBarrier<Structure> m_functionStructure;
+ WriteBarrier<Structure> m_numberObjectStructure;
+ WriteBarrier<Structure> m_regExpMatchesArrayStructure;
+ WriteBarrier<Structure> m_regExpStructure;
+ WriteBarrier<Structure> m_stringObjectStructure;
+ WriteBarrier<Structure> m_internalFunctionStructure;
+
+ unsigned m_profileGroup;
+ Debugger* m_debugger;
+
+ WeakMapSet m_weakMaps;
+ WeakRandom m_weakRandom;
+
+ SymbolTable m_symbolTable;
public:
void* operator new(size_t, JSGlobalData*);
- explicit JSGlobalObject()
- : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData))
+ explicit JSGlobalObject(JSGlobalData& globalData)
+ : JSVariableObject(globalData, JSGlobalObject::createStructure(globalData, jsNull()), &m_symbolTable, 0)
+ , m_registerArraySize(0)
+ , m_globalScopeChain()
+ , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
{
COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot);
putThisToAnonymousValue(0);
init(this);
}
- explicit JSGlobalObject(NonNullPassRefPtr<Structure> structure)
- : JSVariableObject(structure, new JSGlobalObjectData(destroyJSGlobalObjectData))
+ explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure)
+ : JSVariableObject(globalData, structure, &m_symbolTable, 0)
+ , m_registerArraySize(0)
+ , m_globalScopeChain()
+ , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
{
COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot);
putThisToAnonymousValue(0);
@@ -159,8 +137,11 @@ namespace JSC {
}
protected:
- JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
- : JSVariableObject(structure, data)
+ JSGlobalObject(JSGlobalData& globalData, Structure* structure, JSObject* thisValue)
+ : JSVariableObject(globalData, structure, &m_symbolTable, 0)
+ , m_registerArraySize(0)
+ , m_globalScopeChain()
+ , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
{
COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot);
putThisToAnonymousValue(0);
@@ -181,59 +162,64 @@ namespace JSC {
virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
+ // We use this in the code generator as we perform symbol table
+ // lookups prior to initializing the properties
+ bool symbolTableHasProperty(const Identifier& propertyName);
+
// The following accessors return pristine values, even if a script
// replaces the global object's associated property.
- RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor.get(); }
-
- ErrorConstructor* errorConstructor() const { return d()->errorConstructor.get(); }
- NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor.get(); }
- NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor.get(); }
- NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor.get(); }
- NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor.get(); }
- NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor.get(); }
- NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor.get(); }
-
- GlobalEvalFunction* evalFunction() const { return d()->evalFunction.get(); }
-
- ObjectPrototype* objectPrototype() const { return d()->objectPrototype.get(); }
- FunctionPrototype* functionPrototype() const { return d()->functionPrototype.get(); }
- ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype.get(); }
- BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype.get(); }
- StringPrototype* stringPrototype() const { return d()->stringPrototype.get(); }
- NumberPrototype* numberPrototype() const { return d()->numberPrototype.get(); }
- DatePrototype* datePrototype() const { return d()->datePrototype.get(); }
- RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype.get(); }
-
- JSObject* methodCallDummy() const { return d()->methodCallDummy.get(); }
-
- Structure* argumentsStructure() const { return d()->argumentsStructure.get(); }
- Structure* arrayStructure() const { return d()->arrayStructure.get(); }
- Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); }
- Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); }
- Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); }
- Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); }
- Structure* dateStructure() const { return d()->dateStructure.get(); }
- Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); }
- Structure* errorStructure() const { return d()->errorStructure.get(); }
- Structure* functionStructure() const { return d()->functionStructure.get(); }
- Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
- Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
- Structure* internalFunctionStructure() const { return d()->internalFunctionStructure.get(); }
- Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
- Structure* regExpStructure() const { return d()->regExpStructure.get(); }
- Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); }
-
- void setProfileGroup(unsigned value) { d()->profileGroup = value; }
- unsigned profileGroup() const { return d()->profileGroup; }
-
- Debugger* debugger() const { return d()->debugger; }
- void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
+ RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); }
+
+ ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); }
+ NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); }
+ NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); }
+ NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); }
+ NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); }
+ NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); }
+ NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); }
+
+ JSFunction* evalFunction() const { return m_evalFunction.get(); }
+ JSFunction* callFunction() const { return m_callFunction.get(); }
+ JSFunction* applyFunction() const { return m_applyFunction.get(); }
+
+ ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
+ FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
+ ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); }
+ BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); }
+ StringPrototype* stringPrototype() const { return m_stringPrototype.get(); }
+ NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); }
+ DatePrototype* datePrototype() const { return m_datePrototype.get(); }
+ RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
+
+ JSObject* methodCallDummy() const { return m_methodCallDummy.get(); }
+
+ Structure* argumentsStructure() const { return m_argumentsStructure.get(); }
+ Structure* arrayStructure() const { return m_arrayStructure.get(); }
+ Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); }
+ Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); }
+ Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
+ Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); }
+ Structure* dateStructure() const { return m_dateStructure.get(); }
+ Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); }
+ Structure* errorStructure() const { return m_errorStructure.get(); }
+ Structure* functionStructure() const { return m_functionStructure.get(); }
+ Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); }
+ Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); }
+ Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
+ Structure* regExpStructure() const { return m_regExpStructure.get(); }
+ Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
+
+ void setProfileGroup(unsigned value) { m_profileGroup = value; }
+ unsigned profileGroup() const { return m_profileGroup; }
+
+ Debugger* debugger() const { return m_debugger; }
+ void setDebugger(Debugger* debugger) { m_debugger = debugger; }
virtual bool supportsProfiling() const { return false; }
virtual bool supportsRichSourceInfo() const { return true; }
- ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
+ ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); }
virtual bool isGlobalObject() const { return true; }
@@ -247,28 +233,28 @@ namespace JSC {
void copyGlobalsFrom(RegisterFile&);
void copyGlobalsTo(RegisterFile&);
-
- void resetPrototype(JSValue prototype);
+ void resizeRegisters(int oldSize, int newSize);
- JSGlobalData& globalData() const { return *d()->globalData.get(); }
- JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
+ void resetPrototype(JSGlobalData&, JSValue prototype);
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ JSGlobalData& globalData() const { return *m_globalData.get(); }
+
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
void registerWeakMap(OpaqueJSWeakObjectMap* map)
{
- d()->weakMaps.add(map);
+ m_weakMaps.add(map);
}
void deregisterWeakMap(OpaqueJSWeakObjectMap* map)
{
- d()->weakMaps.remove(map);
+ m_weakMaps.remove(map);
}
- double weakRandomNumber() { return d()->weakRandom.get(); }
+ double weakRandomNumber() { return m_weakRandom.get(); }
protected:
static const unsigned AnonymousSlotCount = JSVariableObject::AnonymousSlotCount + 1;
@@ -289,13 +275,11 @@ namespace JSC {
void addStaticGlobals(GlobalPropertyInfo*, int count);
private:
- static void destroyJSGlobalObjectData(void*);
-
// FIXME: Fold reset into init.
void init(JSObject* thisValue);
void reset(JSValue prototype);
- void setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray, size_t count);
+ void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
void* operator new(size_t); // can only be allocated with JSGlobalData
};
@@ -308,27 +292,31 @@ namespace JSC {
return static_cast<JSGlobalObject*>(asObject(value));
}
- inline void JSGlobalObject::setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray, size_t count)
+ inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count)
{
JSVariableObject::setRegisters(registers, registerArray);
- d()->registerArraySize = count;
+ m_registerArraySize = count;
}
inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
{
- size_t oldSize = d()->registerArraySize;
+ size_t oldSize = m_registerArraySize;
size_t newSize = oldSize + count;
- Register* registerArray = new Register[newSize];
- if (d()->registerArray)
- memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
- setRegisters(registerArray + newSize, registerArray, newSize);
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]);
+ if (m_registerArray) {
+ // memcpy is safe here as we're copying barriers we already own from the existing array
+ memcpy(registerArray.get() + count, m_registerArray.get(), oldSize * sizeof(Register));
+ }
+
+ WriteBarrier<Unknown>* registers = registerArray.get() + newSize;
+ setRegisters(registers, registerArray.release(), newSize);
for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
GlobalPropertyInfo& global = globals[i];
ASSERT(global.attributes & DontDelete);
SymbolTableEntry newEntry(index, global.attributes);
symbolTable().add(global.identifier.impl(), newEntry);
- registerAt(index) = global.value;
+ registerAt(index).set(globalData(), this, global.value);
}
}
@@ -355,6 +343,12 @@ namespace JSC {
return symbolTableGet(propertyName, slot, slotIsWriteable);
}
+ inline bool JSGlobalObject::symbolTableHasProperty(const Identifier& propertyName)
+ {
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+ return !entry.isNull();
+ }
+
inline JSValue Structure::prototypeForLookup(ExecState* exec) const
{
if (typeInfo().type() == ObjectType)
@@ -369,7 +363,7 @@ namespace JSC {
// We cache our prototype chain so our clients can share it.
if (!isValid(exec, m_cachedPrototypeChain.get())) {
JSValue prototype = prototypeForLookup(exec);
- m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
+ m_cachedPrototypeChain.set(exec->globalData(), this, StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure()));
}
return m_cachedPrototypeChain.get();
}
@@ -380,9 +374,9 @@ namespace JSC {
return false;
JSValue prototype = prototypeForLookup(exec);
- RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
+ WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
while(*cachedStructure && !prototype.isNull()) {
- if (asObject(prototype)->structure() != *cachedStructure)
+ if (asObject(prototype)->structure() != cachedStructure->get())
return false;
++cachedStructure;
prototype = asObject(prototype)->prototype();
@@ -401,29 +395,29 @@ namespace JSC {
return globalData().dynamicGlobalObject;
}
- inline JSObject* constructEmptyObject(ExecState* exec)
- {
- return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
- }
-
inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
{
- return new (exec) JSObject(globalObject->emptyObjectStructure());
+ return constructEmptyObject(exec, globalObject->emptyObjectStructure());
}
+ inline JSObject* constructEmptyObject(ExecState* exec)
+ {
+ return constructEmptyObject(exec, exec->lexicalGlobalObject());
+ }
+
inline JSArray* constructEmptyArray(ExecState* exec)
{
- return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
+ return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure());
}
inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject)
{
- return new (exec) JSArray(globalObject->arrayStructure());
+ return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure());
}
inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
{
- return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength, CreateInitialized);
+ return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), initialLength, CreateInitialized);
}
inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
@@ -441,7 +435,7 @@ namespace JSC {
class DynamicGlobalObjectScope {
WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
public:
- DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject);
+ DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
~DynamicGlobalObjectScope()
{
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index 284806e..f0da773 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -26,7 +26,6 @@
#include "JSGlobalObjectFunctions.h"
#include "CallFrame.h"
-#include "GlobalEvalFunction.h"
#include "Interpreter.h"
#include "JSGlobalObject.h"
#include "JSString.h"
@@ -450,12 +449,12 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
if (JSValue parsedObject = preparser.tryLiteralParse())
return JSValue::encode(parsedObject);
- RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false);
- JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
+ EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
+ JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain());
if (error)
return throwVMError(exec, error);
- return JSValue::encode(exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node()));
+ return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()));
}
EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
diff --git a/Source/JavaScriptCore/runtime/JSImmediate.cpp b/Source/JavaScriptCore/runtime/JSImmediate.cpp
deleted file mode 100644
index 846238d..0000000
--- a/Source/JavaScriptCore/runtime/JSImmediate.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2003-2006, 2008 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
- * 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "JSImmediate.h"
-
-namespace JSC {
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSImmediate.h b/Source/JavaScriptCore/runtime/JSImmediate.h
deleted file mode 100644
index 68ba75c..0000000
--- a/Source/JavaScriptCore/runtime/JSImmediate.h
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef JSImmediate_h
-#define JSImmediate_h
-
-#if USE(JSVALUE64)
-
-#include <wtf/Assertions.h>
-#include <wtf/AlwaysInline.h>
-#include <wtf/MathExtras.h>
-#include <wtf/StdLibExtras.h>
-#include "JSValue.h"
-#include <limits>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-namespace JSC {
-
- class ExecState;
- class JSCell;
- class JSGlobalData;
- class JSObject;
- class UString;
-
- inline intptr_t reinterpretDoubleToIntptr(double value)
- {
- return WTF::bitwise_cast<intptr_t>(value);
- }
-
- inline double reinterpretIntptrToDouble(intptr_t value)
- {
- return WTF::bitwise_cast<double>(value);
- }
-
- /*
- * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
- * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
- * because allocator alignment guarantees they will be 00 in cell pointers.
- *
- * For example, on a 32 bit system:
- *
- * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00
- * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ]
- * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT
- * [ high 30 bits: 'payload' ] [ low 2 bits -- tag ]
- *
- * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
- * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
- * tag used to indicate the exact type.
- *
- * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
- * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
- * two bits will form an extended tag.
- *
- * 31 bit signed int: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X1
- * [ high 30 bits of the value ] [ high bit part of value ]
- * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZ 10
- * [ extended 'payload' ] [ extended tag ] [ tag 'other' ]
- *
- * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
- * bit would flag the value as undefined. If neither bits are set, the value is null.
- *
- * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY UB 10
- * [ extended 'payload' ] [ undefined | bool ] [ tag 'other' ]
- *
- * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
- * For undefined or null immediates the payload is zero.
- *
- * Boolean: 000000000000000000000000000V 01 10
- * [ boolean value ] [ bool ] [ tag 'other' ]
- * Undefined: 0000000000000000000000000000 10 10
- * [ zero ] [ undefined ] [ tag 'other' ]
- * Null: 0000000000000000000000000000 00 10
- * [ zero ] [ zero ] [ tag 'other' ]
- */
-
- /*
- * On 64-bit platforms, we support an alternative encoding form for immediates, if
- * USE(JSVALUE64) is defined. When this format is used, double precision
- * floating point values may also be encoded as JSImmediates.
- *
- * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
- * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
- * can encode a 51-bit payload. Hardware produced and C-library payloads typically
- * have a payload of zero. We assume that non-zero payloads are available to encode
- * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
- * all set represents a NaN with a non-zero payload, we can use this space in the NaN
- * ranges to encode other values (however there are also other ranges of NaN space that
- * could have been selected). This range of NaN space is represented by 64-bit numbers
- * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
- * valid double-precision numbers will begin fall in these ranges.
- *
- * The scheme we have implemented encodes double precision values by adding 2^48 to the
- * 64-bit integer representation of the number. After this manipulation, no encoded
- * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
- *
- * The top 16-bits denote the type of the encoded JSImmediate:
- *
- * Pointer: 0000:PPPP:PPPP:PPPP
- * 0001:****:****:****
- * Double:{ ...
- * FFFE:****:****:****
- * Integer: FFFF:0000:IIII:IIII
- *
- * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. The tag 0x0000
- * denotes a pointer, or another form of tagged immediate. Boolean, null and undefined
- * values are encoded in the same manner as the default format.
- */
-
- class JSImmediate {
- private:
- friend class JIT;
- friend class JSValue;
- friend class JSInterfaceJIT;
- friend class SpecializedThunkJIT;
- friend JSValue jsNumber(ExecState* exec, double d);
- friend JSValue jsNumber(ExecState*, char i);
- friend JSValue jsNumber(ExecState*, unsigned char i);
- friend JSValue jsNumber(ExecState*, short i);
- friend JSValue jsNumber(ExecState*, unsigned short i);
- friend JSValue jsNumber(ExecState* exec, int i);
- friend JSValue jsNumber(ExecState* exec, unsigned i);
- friend JSValue jsNumber(ExecState* exec, long i);
- friend JSValue jsNumber(ExecState* exec, unsigned long i);
- friend JSValue jsNumber(ExecState* exec, long long i);
- friend JSValue jsNumber(ExecState* exec, unsigned long long i);
- friend JSValue jsNumber(JSGlobalData* globalData, double d);
- friend JSValue jsNumber(JSGlobalData* globalData, short i);
- friend JSValue jsNumber(JSGlobalData* globalData, unsigned short i);
- friend JSValue jsNumber(JSGlobalData* globalData, int i);
- friend JSValue jsNumber(JSGlobalData* globalData, unsigned i);
- friend JSValue jsNumber(JSGlobalData* globalData, long i);
- friend JSValue jsNumber(JSGlobalData* globalData, unsigned long i);
- friend JSValue jsNumber(JSGlobalData* globalData, long long i);
- friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i);
-
- // If all bits in the mask are set, this indicates an integer number,
- // if any but not all are set this value is a double precision number.
- static const intptr_t TagTypeNumber = 0xffff000000000000ll;
- // This value is 2^48, used to encode doubles such that the encoded value will begin
- // with a 16-bit pattern within the range 0x0001..0xFFFE.
- static const intptr_t DoubleEncodeOffset = 0x1000000000000ll;
- static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer
- static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther;
-
- static const intptr_t ExtendedTagMask = 0xC; // extended tag holds a further two bits
- static const intptr_t ExtendedTagBitBool = 0x4;
- static const intptr_t ExtendedTagBitUndefined = 0x8;
-
- static const intptr_t FullTagTypeMask = TagMask | ExtendedTagMask;
- static const intptr_t FullTagTypeBool = TagBitTypeOther | ExtendedTagBitBool;
- static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
- static const intptr_t FullTagTypeNull = TagBitTypeOther;
-
- static const int32_t IntegerPayloadShift = 0;
- static const int32_t ExtendedPayloadShift = 4;
-
- static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
-
- static const int32_t signBit = 0x80000000;
-
- static ALWAYS_INLINE bool isImmediate(JSValue v)
- {
- return rawValue(v) & TagMask;
- }
-
- static ALWAYS_INLINE bool isNumber(JSValue v)
- {
- return rawValue(v) & TagTypeNumber;
- }
-
- static ALWAYS_INLINE bool isIntegerNumber(JSValue v)
- {
- return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
- }
-
- static ALWAYS_INLINE bool isDouble(JSValue v)
- {
- return isNumber(v) && !isIntegerNumber(v);
- }
-
- static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v)
- {
- // A single mask to check for the sign bit and the number tag all at once.
- return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber;
- }
-
- static ALWAYS_INLINE bool isBoolean(JSValue v)
- {
- return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
- }
-
- static ALWAYS_INLINE bool isUndefinedOrNull(JSValue v)
- {
- // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
- return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
- }
-
- static JSValue from(char);
- static JSValue from(signed char);
- static JSValue from(unsigned char);
- static JSValue from(short);
- static JSValue from(unsigned short);
- static JSValue from(int);
- static JSValue from(unsigned);
- static JSValue from(long);
- static JSValue from(unsigned long);
- static JSValue from(long long);
- static JSValue from(unsigned long long);
- static JSValue from(double);
-
- static ALWAYS_INLINE bool isEitherImmediate(JSValue v1, JSValue v2)
- {
- return (rawValue(v1) | rawValue(v2)) & TagMask;
- }
-
- static ALWAYS_INLINE bool areBothImmediate(JSValue v1, JSValue v2)
- {
- return isImmediate(v1) & isImmediate(v2);
- }
-
- static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2)
- {
- return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber;
- }
-
- static double toDouble(JSValue);
- static bool toBoolean(JSValue);
-
- static bool getUInt32(JSValue, uint32_t&);
- static bool getTruncatedInt32(JSValue, int32_t&);
- static bool getTruncatedUInt32(JSValue, uint32_t&);
-
- static int32_t getTruncatedInt32(JSValue);
- static uint32_t getTruncatedUInt32(JSValue);
-
- static JSValue trueImmediate();
- static JSValue falseImmediate();
- static JSValue undefinedImmediate();
- static JSValue nullImmediate();
- static JSValue zeroImmediate();
- static JSValue oneImmediate();
-
- private:
- static const int minImmediateInt = ((-INT_MAX) - 1);
- static const int maxImmediateInt = INT_MAX;
- static const unsigned maxImmediateUInt = maxImmediateInt;
-
- static ALWAYS_INLINE JSValue makeValue(intptr_t integer)
- {
- return JSValue::makeImmediate(integer);
- }
-
- // With USE(JSVALUE64) we want the argument to be zero extended, so the
- // integer doesn't interfere with the tag bits in the upper word. In the default encoding,
- // if intptr_t id larger then int32_t we sign extend the value through the upper word.
- static ALWAYS_INLINE JSValue makeInt(uint32_t value)
- {
- return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber);
- }
-
- static ALWAYS_INLINE JSValue makeDouble(double value)
- {
- return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
- }
-
- static ALWAYS_INLINE JSValue makeBool(bool b)
- {
- return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
- }
-
- static ALWAYS_INLINE JSValue makeUndefined()
- {
- return makeValue(FullTagTypeUndefined);
- }
-
- static ALWAYS_INLINE JSValue makeNull()
- {
- return makeValue(FullTagTypeNull);
- }
-
- template<typename T>
- static JSValue fromNumberOutsideIntegerRange(T);
-
- static ALWAYS_INLINE double doubleValue(JSValue v)
- {
- return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
- }
-
- static ALWAYS_INLINE int32_t intValue(JSValue v)
- {
- return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
- }
-
- static ALWAYS_INLINE uint32_t uintValue(JSValue v)
- {
- return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
- }
-
- static ALWAYS_INLINE bool boolValue(JSValue v)
- {
- return rawValue(v) & ExtendedPayloadBitBoolValue;
- }
-
- static ALWAYS_INLINE intptr_t rawValue(JSValue v)
- {
- return v.immediateValue();
- }
- };
-
- ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); }
- ALWAYS_INLINE JSValue JSImmediate::falseImmediate() { return makeBool(false); }
- ALWAYS_INLINE JSValue JSImmediate::undefinedImmediate() { return makeUndefined(); }
- ALWAYS_INLINE JSValue JSImmediate::nullImmediate() { return makeNull(); }
- ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); }
- ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); }
-
- inline bool doubleToBoolean(double value)
- {
- return value < 0.0 || value > 0.0;
- }
-
- ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
- {
- ASSERT(isImmediate(v));
- return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
- : doubleToBoolean(doubleValue(v)) : v == trueImmediate();
- }
-
- ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v)
- {
- // FIXME: should probably be asserting isPositiveIntegerNumber here.
- ASSERT(isIntegerNumber(v));
- return intValue(v);
- }
-
- template<typename T>
- inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value)
- {
- return makeDouble(static_cast<double>(value));
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(char i)
- {
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(signed char i)
- {
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(unsigned char i)
- {
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(short i)
- {
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(unsigned short i)
- {
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(int i)
- {
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(unsigned i)
- {
- if (i > maxImmediateUInt)
- return fromNumberOutsideIntegerRange(i);
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(long i)
- {
- if ((i < minImmediateInt) | (i > maxImmediateInt))
- return fromNumberOutsideIntegerRange(i);
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(unsigned long i)
- {
- if (i > maxImmediateUInt)
- return fromNumberOutsideIntegerRange(i);
- return makeInt(i);
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(long long i)
- {
- if ((i < minImmediateInt) | (i > maxImmediateInt))
- return JSValue();
- return makeInt(static_cast<intptr_t>(i));
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(unsigned long long i)
- {
- if (i > maxImmediateUInt)
- return fromNumberOutsideIntegerRange(i);
- return makeInt(static_cast<intptr_t>(i));
- }
-
- ALWAYS_INLINE JSValue JSImmediate::from(double d)
- {
- const int intVal = static_cast<int>(d);
-
- // Check for data loss from conversion to int.
- if (intVal != d || (!intVal && signbit(d)))
- return fromNumberOutsideIntegerRange(d);
-
- return from(intVal);
- }
-
- ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue v)
- {
- ASSERT(isIntegerNumber(v));
- return intValue(v);
- }
-
- ALWAYS_INLINE double JSImmediate::toDouble(JSValue v)
- {
- ASSERT(isImmediate(v));
-
- if (isIntegerNumber(v))
- return intValue(v);
-
- if (isNumber(v)) {
- ASSERT(isDouble(v));
- return doubleValue(v);
- }
-
- if (rawValue(v) == FullTagTypeUndefined)
- return nonInlineNaN();
-
- ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate()));
- return rawValue(v) >> ExtendedPayloadShift;
- }
-
- ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue v, uint32_t& i)
- {
- i = uintValue(v);
- return isPositiveIntegerNumber(v);
- }
-
- ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue v, int32_t& i)
- {
- i = intValue(v);
- return isIntegerNumber(v);
- }
-
- ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue v, uint32_t& i)
- {
- return getUInt32(v, i);
- }
-
- inline JSValue::JSValue(JSNullTag)
- {
- *this = JSImmediate::nullImmediate();
- }
-
- inline JSValue::JSValue(JSUndefinedTag)
- {
- *this = JSImmediate::undefinedImmediate();
- }
-
- inline JSValue::JSValue(JSTrueTag)
- {
- *this = JSImmediate::trueImmediate();
- }
-
- inline JSValue::JSValue(JSFalseTag)
- {
- *this = JSImmediate::falseImmediate();
- }
-
- inline bool JSValue::isUndefinedOrNull() const
- {
- return JSImmediate::isUndefinedOrNull(asValue());
- }
-
- inline bool JSValue::isBoolean() const
- {
- return JSImmediate::isBoolean(asValue());
- }
-
- inline bool JSValue::isTrue() const
- {
- return asValue() == JSImmediate::trueImmediate();
- }
-
- inline bool JSValue::isFalse() const
- {
- return asValue() == JSImmediate::falseImmediate();
- }
-
- inline bool JSValue::getBoolean(bool& v) const
- {
- if (JSImmediate::isBoolean(asValue())) {
- v = JSImmediate::toBoolean(asValue());
- return true;
- }
-
- return false;
- }
-
- inline bool JSValue::getBoolean() const
- {
- return asValue() == jsBoolean(true);
- }
-
- inline bool JSValue::isCell() const
- {
- return !JSImmediate::isImmediate(asValue());
- }
-
- inline bool JSValue::isInt32() const
- {
- return JSImmediate::isIntegerNumber(asValue());
- }
-
- inline int32_t JSValue::asInt32() const
- {
- ASSERT(isInt32());
- return JSImmediate::getTruncatedInt32(asValue());
- }
-
- inline bool JSValue::isUInt32() const
- {
- return JSImmediate::isPositiveIntegerNumber(asValue());
- }
-
- inline uint32_t JSValue::asUInt32() const
- {
- ASSERT(isUInt32());
- return JSImmediate::getTruncatedUInt32(asValue());
- }
-
-} // namespace JSC
-
-#endif // USE(JSVALUE64)
-
-#endif // JSImmediate_h
diff --git a/Source/JavaScriptCore/runtime/JSLock.cpp b/Source/JavaScriptCore/runtime/JSLock.cpp
index 918141f..fc543f0 100644
--- a/Source/JavaScriptCore/runtime/JSLock.cpp
+++ b/Source/JavaScriptCore/runtime/JSLock.cpp
@@ -23,14 +23,19 @@
#include "Heap.h"
#include "CallFrame.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if USE(PTHREADS)
#include <pthread.h>
#endif
namespace JSC {
-#if ENABLE(JSC_MULTIPLE_THREADS)
+// JSLock is only needed to support an obsolete execution model where JavaScriptCore
+// automatically protected against concurrent access from multiple threads.
+// So it's safe to disable it on non-mac platforms where we don't have native pthreads.
+#if ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
// Acquire this mutex before accessing lock-related data.
static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -208,7 +213,7 @@ JSLock::DropAllLocks::~DropAllLocks()
--lockDropDepth;
}
-#else
+#else // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
JSLock::JSLock(ExecState*)
: m_lockBehavior(SilenceAssertionsOnly)
@@ -255,6 +260,6 @@ JSLock::DropAllLocks::~DropAllLocks()
{
}
-#endif // USE(MULTIPLE_THREADS)
+#endif // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
index e01b401..1115dc0 100644
--- a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
@@ -67,7 +67,7 @@ UString JSNotAnObject::toString(ExecState* exec) const
return "";
}
-JSObject* JSNotAnObject::toObject(ExecState* exec) const
+JSObject* JSNotAnObject::toObject(ExecState* exec, JSGlobalObject*) const
{
ASSERT_UNUSED(exec, exec->hadException());
return const_cast<JSNotAnObject*>(this);
diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h
index 9f527cf..4c6806a 100644
--- a/Source/JavaScriptCore/runtime/JSNotAnObject.h
+++ b/Source/JavaScriptCore/runtime/JSNotAnObject.h
@@ -36,16 +36,16 @@ namespace JSC {
// This unholy class is used to allow us to avoid multiple exception checks
// in certain SquirrelFish bytecodes -- effectively it just silently consumes
// any operations performed on the result of a failed toObject call.
- class JSNotAnObject : public JSObject {
+ class JSNotAnObject : public JSNonFinalObject {
public:
JSNotAnObject(ExecState* exec)
- : JSObject(exec->globalData().notAnObjectStructure)
+ : JSNonFinalObject(exec->globalData(), exec->globalData().notAnObjectStructure.get())
{
}
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
private:
@@ -58,7 +58,7 @@ namespace JSC {
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
- virtual JSObject* toObject(ExecState*) const;
+ virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
// JSObject methods
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.cpp b/Source/JavaScriptCore/runtime/JSNumberCell.cpp
deleted file mode 100644
index 6fa6b2a..0000000
--- a/Source/JavaScriptCore/runtime/JSNumberCell.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2004, 2007, 2008 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
- * 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "JSNumberCell.h"
-
-// Keep our exported symbols lists happy.
-namespace JSC {
-
-JSValue jsNumberCell(ExecState*, double);
-
-JSValue jsNumberCell(ExecState*, double)
-{
- ASSERT_NOT_REACHED();
- return JSValue();
-}
-
-} // namespace JSC
-
diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.h b/Source/JavaScriptCore/runtime/JSNumberCell.h
deleted file mode 100644
index 1ccdf50..0000000
--- a/Source/JavaScriptCore/runtime/JSNumberCell.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2007, 2008 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
- * 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef JSNumberCell_h
-#define JSNumberCell_h
-
-#include "CallFrame.h"
-#include "JSCell.h"
-#include "JSImmediate.h"
-#include "Heap.h"
-#include "UString.h"
-#include <stddef.h> // for size_t
-
-namespace JSC {
-
- extern const double NaN;
- extern const double Inf;
-
-#if USE(JSVALUE64)
- ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
- {
- *this = JSImmediate::fromNumberOutsideIntegerRange(d);
- }
-
- inline JSValue::JSValue(double d)
- {
- JSValue v = JSImmediate::from(d);
- ASSERT(v);
- *this = v;
- }
-
- inline JSValue::JSValue(int i)
- {
- JSValue v = JSImmediate::from(i);
- ASSERT(v);
- *this = v;
- }
-
- inline JSValue::JSValue(unsigned i)
- {
- JSValue v = JSImmediate::from(i);
- ASSERT(v);
- *this = v;
- }
-
- inline JSValue::JSValue(long i)
- {
- JSValue v = JSImmediate::from(i);
- ASSERT(v);
- *this = v;
- }
-
- inline JSValue::JSValue(unsigned long i)
- {
- JSValue v = JSImmediate::from(i);
- ASSERT(v);
- *this = v;
- }
-
- inline JSValue::JSValue(long long i)
- {
- JSValue v = JSImmediate::from(static_cast<double>(i));
- ASSERT(v);
- *this = v;
- }
-
- inline JSValue::JSValue(unsigned long long i)
- {
- JSValue v = JSImmediate::from(static_cast<double>(i));
- ASSERT(v);
- *this = v;
- }
-
- inline bool JSValue::isDouble() const
- {
- return JSImmediate::isDouble(asValue());
- }
-
- inline double JSValue::asDouble() const
- {
- return JSImmediate::doubleValue(asValue());
- }
-
- inline bool JSValue::isNumber() const
- {
- return JSImmediate::isNumber(asValue());
- }
-
- inline double JSValue::uncheckedGetNumber() const
- {
- ASSERT(isNumber());
- return JSImmediate::toDouble(asValue());
- }
-
-#endif // USE(JSVALUE64)
-
-#if USE(JSVALUE64)
-
- inline JSValue::JSValue(char i)
- {
- ASSERT(JSImmediate::from(i));
- *this = JSImmediate::from(i);
- }
-
- inline JSValue::JSValue(unsigned char i)
- {
- ASSERT(JSImmediate::from(i));
- *this = JSImmediate::from(i);
- }
-
- inline JSValue::JSValue(short i)
- {
- ASSERT(JSImmediate::from(i));
- *this = JSImmediate::from(i);
- }
-
- inline JSValue::JSValue(unsigned short i)
- {
- ASSERT(JSImmediate::from(i));
- *this = JSImmediate::from(i);
- }
-
- inline JSValue jsNaN()
- {
- return jsNumber(NaN);
- }
-
- // --- JSValue inlines ----------------------------
-
- ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
- {
- return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
- }
-
- inline bool JSValue::getNumber(double &result) const
- {
- if (isInt32())
- result = asInt32();
- else if (LIKELY(isDouble()))
- result = asDouble();
- else {
- ASSERT(!isNumber());
- return false;
- }
- return true;
- }
-
-#endif // USE(JSVALUE64)
-
-} // namespace JSC
-
-#endif // JSNumberCell_h
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index 0f7a576..27fc569 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -32,6 +32,8 @@
#include "JSArray.h"
#include "JSGlobalObject.h"
#include "LiteralParser.h"
+#include "Local.h"
+#include "LocalScope.h"
#include "Lookup.h"
#include "PropertyNameArray.h"
#include "UStringBuilder.h"
@@ -51,9 +53,10 @@ static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*);
namespace JSC {
-JSONObject::JSONObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
+JSONObject::JSONObject(JSGlobalObject* globalObject, Structure* structure)
: JSObjectWithGlobalObject(globalObject, structure)
{
+ ASSERT(inherits(&s_info));
}
// PropertyNameForFunctionCall objects must be on the stack, since the JSValue that they create is not marked.
@@ -73,24 +76,22 @@ private:
class Stringifier {
WTF_MAKE_NONCOPYABLE(Stringifier);
public:
- Stringifier(ExecState*, JSValue replacer, JSValue space);
- ~Stringifier();
- JSValue stringify(JSValue);
+ Stringifier(ExecState*, const Local<Unknown>& replacer, const Local<Unknown>& space);
+ Local<Unknown> stringify(Handle<Unknown>);
void markAggregate(MarkStack&);
private:
class Holder {
public:
- Holder(JSObject*);
+ Holder(JSGlobalData&, JSObject*);
JSObject* object() const { return m_object.get(); }
- DeprecatedPtr<JSObject>* objectSlot() { return &m_object; }
bool appendNextProperty(Stringifier&, UStringBuilder&);
private:
- DeprecatedPtr<JSObject> m_object;
+ Local<JSObject> m_object;
const bool m_isArray;
bool m_isJSArray;
unsigned m_index;
@@ -112,16 +113,14 @@ private:
void unindent();
void startNewLine(UStringBuilder&) const;
- Stringifier* const m_nextStringifierToMark;
ExecState* const m_exec;
- const JSValue m_replacer;
+ const Local<Unknown> m_replacer;
bool m_usingArrayReplacer;
PropertyNameArray m_arrayReplacerPropertyNames;
CallType m_replacerCallType;
CallData m_replacerCallData;
const UString m_gap;
- HashSet<JSObject*> m_holderCycleDetector;
Vector<Holder, 16> m_holderStack;
UString m_repeatedGap;
UString m_indent;
@@ -134,11 +133,11 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value)
if (!value.isObject())
return value;
JSObject* object = asObject(value);
- if (object->inherits(&NumberObject::info))
+ if (object->inherits(&NumberObject::s_info))
return jsNumber(object->toNumber(exec));
- if (object->inherits(&StringObject::info))
+ if (object->inherits(&StringObject::s_info))
return jsString(exec, object->toString(exec));
- if (object->inherits(&BooleanObject::info))
+ if (object->inherits(&BooleanObject::s_info))
return object->toPrimitive(exec);
return value;
}
@@ -198,23 +197,20 @@ JSValue PropertyNameForFunctionCall::value(ExecState* exec) const
// ------------------------------ Stringifier --------------------------------
-Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
- : m_nextStringifierToMark(exec->globalData().firstStringifierToMark)
- , m_exec(exec)
+Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const Local<Unknown>& space)
+ : m_exec(exec)
, m_replacer(replacer)
, m_usingArrayReplacer(false)
, m_arrayReplacerPropertyNames(exec)
, m_replacerCallType(CallTypeNone)
- , m_gap(gap(exec, space))
+ , m_gap(gap(exec, space.get()))
{
- exec->globalData().firstStringifierToMark = this;
-
if (!m_replacer.isObject())
return;
- if (asObject(m_replacer)->inherits(&JSArray::info)) {
+ if (m_replacer.asObject()->inherits(&JSArray::s_info)) {
m_usingArrayReplacer = true;
- JSObject* array = asObject(m_replacer);
+ Handle<JSObject> array = m_replacer.asObject();
unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
for (unsigned i = 0; i < length; ++i) {
JSValue name = array->get(exec, i);
@@ -234,7 +230,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
}
if (name.isObject()) {
- if (!asObject(name)->inherits(&NumberObject::info) && !asObject(name)->inherits(&StringObject::info))
+ if (!asObject(name)->inherits(&NumberObject::s_info) && !asObject(name)->inherits(&StringObject::s_info))
continue;
propertyName = name.toString(exec);
if (exec->hadException())
@@ -245,40 +241,25 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
return;
}
- m_replacerCallType = asObject(m_replacer)->getCallData(m_replacerCallData);
-}
-
-Stringifier::~Stringifier()
-{
- ASSERT(m_exec->globalData().firstStringifierToMark == this);
- m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark;
-}
-
-void Stringifier::markAggregate(MarkStack& markStack)
-{
- for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) {
- size_t size = m_holderStack.size();
- for (size_t i = 0; i < size; ++i)
- markStack.append(m_holderStack[i].objectSlot());
- }
+ m_replacerCallType = m_replacer.asObject()->getCallData(m_replacerCallData);
}
-JSValue Stringifier::stringify(JSValue value)
+Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
{
JSObject* object = constructEmptyObject(m_exec);
if (m_exec->hadException())
- return jsNull();
+ return Local<Unknown>(m_exec->globalData(), jsNull());
PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier);
- object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value);
+ object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value.get());
UStringBuilder result;
- if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded)
- return jsUndefined();
+ if (appendStringifiedValue(result, value.get(), object, emptyPropertyName) != StringifySucceeded)
+ return Local<Unknown>(m_exec->globalData(), jsUndefined());
if (m_exec->hadException())
- return jsNull();
+ return Local<Unknown>(m_exec->globalData(), jsNull());
- return jsString(m_exec, result.toUString());
+ return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toUString()));
}
void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value)
@@ -371,12 +352,12 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
if (m_replacerCallType != CallTypeNone) {
JSValue list[] = { propertyName.value(m_exec), value };
ArgList args(list, WTF_ARRAY_LENGTH(list));
- value = call(m_exec, m_replacer, m_replacerCallType, m_replacerCallData, holder, args);
+ value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder, args);
if (m_exec->hadException())
return StringifyFailed;
}
- if (value.isUndefined() && !holder->inherits(&JSArray::info))
+ if (value.isUndefined() && !holder->inherits(&JSArray::s_info))
return StringifyFailedDueToUndefinedValue;
if (value.isNull()) {
@@ -416,7 +397,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
CallData callData;
if (object->getCallData(callData) != CallTypeNone) {
- if (holder->inherits(&JSArray::info)) {
+ if (holder->inherits(&JSArray::s_info)) {
builder.append("null");
return StringifySucceeded;
}
@@ -424,12 +405,14 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
}
// Handle cycle detection, and put the holder on the stack.
- if (!m_holderCycleDetector.add(object).second) {
- throwError(m_exec, createTypeError(m_exec, "JSON.stringify cannot serialize cyclic structures."));
- return StringifyFailed;
+ for (unsigned i = 0; i < m_holderStack.size(); i++) {
+ if (m_holderStack[i].object() == object) {
+ throwError(m_exec, createTypeError(m_exec, "JSON.stringify cannot serialize cyclic structures."));
+ return StringifyFailed;
+ }
}
bool holderStackWasEmpty = m_holderStack.isEmpty();
- m_holderStack.append(object);
+ m_holderStack.append(Holder(m_exec->globalData(), object));
if (!holderStackWasEmpty)
return StringifySucceeded;
@@ -449,7 +432,6 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
tickCount = localTimeoutChecker.ticksUntilNextCheck();
}
}
- m_holderCycleDetector.remove(m_holderStack.last().object());
m_holderStack.removeLast();
} while (!m_holderStack.isEmpty());
return StringifySucceeded;
@@ -484,9 +466,9 @@ inline void Stringifier::startNewLine(UStringBuilder& builder) const
builder.append(m_indent);
}
-inline Stringifier::Holder::Holder(JSObject* object)
- : m_object(object)
- , m_isArray(object->inherits(&JSArray::info))
+inline Stringifier::Holder::Holder(JSGlobalData& globalData, JSObject* object)
+ : m_object(globalData, object)
+ , m_isArray(object->inherits(&JSArray::s_info))
, m_index(0)
{
}
@@ -601,7 +583,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu
// ------------------------------ JSONObject --------------------------------
-const ClassInfo JSONObject::info = { "JSON", 0, 0, ExecState::jsonTable };
+const ClassInfo JSONObject::s_info = { "JSON", &JSObjectWithGlobalObject::s_info, 0, ExecState::jsonTable };
/* Source for JSONObject.lut.h
@begin jsonTable
@@ -622,16 +604,11 @@ bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro
return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
}
-void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier)
-{
- stringifier->markAggregate(markStack);
-}
-
class Walker {
public:
- Walker(ExecState* exec, JSObject* function, CallType callType, CallData callData)
+ Walker(ExecState* exec, Handle<JSObject> function, CallType callType, CallData callData)
: m_exec(exec)
- , m_function(function)
+ , m_function(exec->globalData(), function)
, m_callType(callType)
, m_callData(callData)
{
@@ -648,7 +625,7 @@ private:
friend class Holder;
ExecState* m_exec;
- DeprecatedPtr<JSObject> m_function;
+ Local<JSObject> m_function;
CallType m_callType;
CallData m_callData;
};
@@ -662,8 +639,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
{
Vector<PropertyNameArray, 16> propertyStack;
Vector<uint32_t, 16> indexStack;
- Vector<JSObject*, 16> objectStack;
- Vector<JSArray*, 16> arrayStack;
+ LocalStack<JSObject, 16> objectStack(m_exec->globalData());
+ LocalStack<JSArray, 16> arrayStack(m_exec->globalData());
Vector<WalkerState, 16> stateStack;
WalkerState state = StateUnknown;
@@ -678,12 +655,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
arrayStartState:
case ArrayStartState: {
ASSERT(inValue.isObject());
- ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::info));
+ ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::s_info));
if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
return throwError(m_exec, createStackOverflowError(m_exec));
JSArray* array = asArray(inValue);
- arrayStack.append(array);
+ arrayStack.push(array);
indexStack.append(0);
// fallthrough
}
@@ -695,11 +672,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
tickCount = localTimeoutChecker.ticksUntilNextCheck();
}
- JSArray* array = arrayStack.last();
+ JSArray* array = arrayStack.peek();
uint32_t index = indexStack.last();
if (index == array->length()) {
outValue = array;
- arrayStack.removeLast();
+ arrayStack.pop();
indexStack.removeLast();
break;
}
@@ -721,7 +698,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
// fallthrough
}
case ArrayEndVisitMember: {
- JSArray* array = arrayStack.last();
+ JSArray* array = arrayStack.peek();
JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue);
if (filteredValue.isUndefined())
array->deleteProperty(m_exec, indexStack.last());
@@ -739,12 +716,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
objectStartState:
case ObjectStartState: {
ASSERT(inValue.isObject());
- ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::info));
+ ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::s_info));
if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
return throwError(m_exec, createStackOverflowError(m_exec));
JSObject* object = asObject(inValue);
- objectStack.append(object);
+ objectStack.push(object);
indexStack.append(0);
propertyStack.append(PropertyNameArray(m_exec));
object->getOwnPropertyNames(m_exec, propertyStack.last());
@@ -758,12 +735,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
tickCount = localTimeoutChecker.ticksUntilNextCheck();
}
- JSObject* object = objectStack.last();
+ JSObject* object = objectStack.peek();
uint32_t index = indexStack.last();
PropertyNameArray& properties = propertyStack.last();
if (index == properties.size()) {
outValue = object;
- objectStack.removeLast();
+ objectStack.pop();
indexStack.removeLast();
propertyStack.removeLast();
break;
@@ -786,7 +763,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
// fallthrough
}
case ObjectEndVisitMember: {
- JSObject* object = objectStack.last();
+ JSObject* object = objectStack.peek();
Identifier prop = propertyStack.last()[indexStack.last()];
PutPropertySlot slot;
JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue);
@@ -806,7 +783,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
break;
}
JSObject* object = asObject(inValue);
- if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::info))
+ if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::s_info))
goto arrayStartState;
goto objectStartState;
}
@@ -837,7 +814,8 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
UString source = value.toString(exec);
if (exec->hadException())
return JSValue::encode(jsNull());
-
+
+ LocalScope scope(exec->globalData());
LiteralParser jsonParser(exec, source, LiteralParser::StrictJSON);
JSValue unfiltered = jsonParser.tryLiteralParse();
if (!unfiltered)
@@ -851,7 +829,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
CallType callType = getCallData(function, callData);
if (callType == CallTypeNone)
return JSValue::encode(unfiltered);
- return JSValue::encode(Walker(exec, asObject(function), callType, callData).walk(unfiltered));
+ return JSValue::encode(Walker(exec, Local<JSObject>(exec->globalData(), asObject(function)), callType, callData).walk(unfiltered));
}
// ECMA-262 v5 15.12.3
@@ -859,15 +837,17 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec)
{
if (!exec->argumentCount())
return throwVMError(exec, createError(exec, "No input to stringify"));
- JSValue value = exec->argument(0);
- JSValue replacer = exec->argument(1);
- JSValue space = exec->argument(2);
- return JSValue::encode(Stringifier(exec, replacer, space).stringify(value));
+ LocalScope scope(exec->globalData());
+ Local<Unknown> value(exec->globalData(), exec->argument(0));
+ Local<Unknown> replacer(exec->globalData(), exec->argument(1));
+ Local<Unknown> space(exec->globalData(), exec->argument(2));
+ return JSValue::encode(Stringifier(exec, replacer, space).stringify(value).get());
}
UString JSONStringify(ExecState* exec, JSValue value, unsigned indent)
{
- JSValue result = Stringifier(exec, jsNull(), jsNumber(indent)).stringify(value);
+ LocalScope scope(exec->globalData());
+ Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->globalData(), jsNull()), Local<Unknown>(exec->globalData(), jsNumber(indent))).stringify(Local<Unknown>(exec->globalData(), value));
if (result.isUndefinedOrNull())
return UString();
return result.getString(exec);
diff --git a/Source/JavaScriptCore/runtime/JSONObject.h b/Source/JavaScriptCore/runtime/JSONObject.h
index f64be12..c87c641 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.h
+++ b/Source/JavaScriptCore/runtime/JSONObject.h
@@ -34,15 +34,13 @@ namespace JSC {
class JSONObject : public JSObjectWithGlobalObject {
public:
- JSONObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure);
+ JSONObject(JSGlobalObject*, Structure*);
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
- static void markStringifiers(MarkStack&, Stringifier*);
-
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
@@ -50,8 +48,7 @@ namespace JSC {
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const ClassInfo s_info;
};
UString JSONStringify(ExecState* exec, JSValue value, unsigned indent);
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 277ffff..9677f23 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -42,9 +42,13 @@
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSObject);
+ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
+ASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
+const ClassInfo JSObject::s_info = { "Object", 0, 0, 0 };
+
static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
{
// Add properties from the static hashtables of properties
@@ -81,9 +85,8 @@ void JSObject::markChildren(MarkStack& markStack)
UString JSObject::className() const
{
const ClassInfo* info = classInfo();
- if (info)
- return info->className;
- return "Object";
+ ASSERT(info);
+ return info->className;
}
bool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
@@ -106,7 +109,7 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu
// Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
if (!value.isObject() && !value.isNull())
return;
- if (!setPrototypeWithCycleCheck(value))
+ if (!setPrototypeWithCycleCheck(exec->globalData(), value))
throwError(exec, createError(exec, "cyclic __proto__ value"));
return;
}
@@ -124,14 +127,14 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu
unsigned attributes;
JSCell* specificValue;
- if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) {
+ if ((m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) {
if (slot.isStrictMode())
throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
return;
}
for (JSObject* obj = this; ; obj = asObject(prototype)) {
- if (JSValue gs = obj->getDirect(propertyName)) {
+ if (JSValue gs = obj->getDirect(exec->globalData(), propertyName)) {
if (gs.isGetterSetter()) {
JSObject* setterFunc = asGetterSetter(gs)->setter();
if (!setterFunc) {
@@ -215,10 +218,10 @@ bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
{
unsigned attributes;
JSCell* specificValue;
- if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) {
+ if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) {
if ((attributes & DontDelete))
return false;
- removeDirect(propertyName);
+ removeDirect(exec->globalData(), propertyName);
return true;
}
@@ -309,34 +312,33 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi
void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
{
- JSValue object = getDirect(propertyName);
+ JSValue object = getDirect(exec->globalData(), propertyName);
if (object && object.isGetterSetter()) {
ASSERT(m_structure->hasGetterSetterProperties());
asGetterSetter(object)->setGetter(exec->globalData(), getterFunction);
return;
}
+ JSGlobalData& globalData = exec->globalData();
PutPropertySlot slot;
GetterSetter* getterSetter = new (exec) GetterSetter(exec);
- putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot);
+ putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
// if we override an existing non-getter or non-setter.
if (slot.type() != PutPropertySlot::NewProperty) {
- if (!m_structure->isDictionary()) {
- RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure);
- setStructure(structure.release());
- }
+ if (!m_structure->isDictionary())
+ setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, m_structure.get()));
}
m_structure->setHasGetterSetterProperties(true);
- getterSetter->setGetter(exec->globalData(), getterFunction);
+ getterSetter->setGetter(globalData, getterFunction);
}
void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
{
- JSValue object = getDirect(propertyName);
+ JSValue object = getDirect(exec->globalData(), propertyName);
if (object && object.isGetterSetter()) {
ASSERT(m_structure->hasGetterSetterProperties());
asGetterSetter(object)->setSetter(exec->globalData(), setterFunction);
@@ -351,21 +353,19 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO
// getters and setters, though, we also need to change our Structure
// if we override an existing non-getter or non-setter.
if (slot.type() != PutPropertySlot::NewProperty) {
- if (!m_structure->isDictionary()) {
- RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure);
- setStructure(structure.release());
- }
+ if (!m_structure->isDictionary())
+ setStructure(exec->globalData(), Structure::getterSetterTransition(exec->globalData(), m_structure.get()));
}
m_structure->setHasGetterSetterProperties(true);
getterSetter->setSetter(exec->globalData(), setterFunction);
}
-JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
+JSValue JSObject::lookupGetter(ExecState* exec, const Identifier& propertyName)
{
JSObject* object = this;
while (true) {
- if (JSValue value = object->getDirect(propertyName)) {
+ if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
if (!value.isGetterSetter())
return jsUndefined();
JSObject* functionObject = asGetterSetter(value)->getter();
@@ -380,11 +380,11 @@ JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
}
}
-JSValue JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
+JSValue JSObject::lookupSetter(ExecState* exec, const Identifier& propertyName)
{
JSObject* object = this;
while (true) {
- if (JSValue value = object->getDirect(propertyName)) {
+ if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
if (!value.isGetterSetter())
return jsUndefined();
JSObject* functionObject = asGetterSetter(value)->setter();
@@ -425,10 +425,10 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN
return descriptor.enumerable();
}
-bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const
+bool JSObject::getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificValue) const
{
unsigned attributes;
- if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound)
+ if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound)
return true;
// This could be a function within the static table? - should probably
@@ -461,7 +461,7 @@ void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyName
void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
- m_structure->getPropertyNames(propertyNames, mode);
+ m_structure->getPropertyNames(exec->globalData(), propertyNames, mode);
getClassPropertyNames(exec, classInfo(), propertyNames, mode);
}
@@ -486,7 +486,7 @@ UString JSObject::toString(ExecState* exec) const
return primitive.toString(exec);
}
-JSObject* JSObject::toObject(ExecState*) const
+JSObject* JSObject::toObject(ExecState*, JSGlobalObject*) const
{
return const_cast<JSObject*>(this);
}
@@ -506,18 +506,33 @@ JSObject* JSObject::unwrappedObject()
return this;
}
-void JSObject::removeDirect(const Identifier& propertyName)
+void JSObject::seal(JSGlobalData& globalData)
+{
+ setStructure(globalData, Structure::sealTransition(globalData, m_structure.get()));
+}
+
+void JSObject::freeze(JSGlobalData& globalData)
+{
+ setStructure(globalData, Structure::freezeTransition(globalData, m_structure.get()));
+}
+
+void JSObject::preventExtensions(JSGlobalData& globalData)
+{
+ if (isExtensible())
+ setStructure(globalData, Structure::preventExtensionsTransition(globalData, m_structure.get()));
+}
+
+void JSObject::removeDirect(JSGlobalData& globalData, const Identifier& propertyName)
{
size_t offset;
if (m_structure->isUncacheableDictionary()) {
- offset = m_structure->removePropertyWithoutTransition(propertyName);
+ offset = m_structure->removePropertyWithoutTransition(globalData, propertyName);
if (offset != WTF::notFound)
putUndefinedAtDirectOffset(offset);
return;
}
- RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset);
- setStructure(structure.release());
+ setStructure(globalData, Structure::removePropertyTransition(globalData, m_structure.get(), propertyName, offset));
if (offset != WTF::notFound)
putUndefinedAtDirectOffset(offset);
}
@@ -553,22 +568,38 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr
slot.setUndefined();
}
-Structure* JSObject::createInheritorID()
+Structure* JSObject::createInheritorID(JSGlobalData& globalData)
{
- m_inheritorID = JSObject::createStructure(this);
+ m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, this));
+ ASSERT(m_inheritorID->isEmpty());
return m_inheritorID.get();
}
void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
{
- allocatePropertyStorageInline(oldSize, newSize);
+ ASSERT(newSize > oldSize);
+
+ // It's important that this function not rely on m_structure, since
+ // we might be in the middle of a transition.
+ bool wasInline = (oldSize < JSObject::baseExternalStorageCapacity);
+
+ PropertyStorage oldPropertyStorage = m_propertyStorage;
+ PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
+
+ for (unsigned i = 0; i < oldSize; ++i)
+ newPropertyStorage[i] = oldPropertyStorage[i];
+
+ if (!wasInline)
+ delete [] oldPropertyStorage;
+
+ m_propertyStorage = newPropertyStorage;
}
-bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool JSObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
unsigned attributes = 0;
JSCell* cell = 0;
- size_t offset = m_structure->get(propertyName, attributes, cell);
+ size_t offset = m_structure->get(exec->globalData(), propertyName, attributes, cell);
if (offset == WTF::notFound)
return false;
descriptor.setDescriptor(getDirectOffset(offset), attributes);
@@ -627,6 +658,12 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
// If we have a new property we can just put it on normally
PropertyDescriptor current;
if (!getOwnPropertyDescriptor(exec, propertyName, current)) {
+ // unless extensions are prevented!
+ if (!isExtensible()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
+ return false;
+ }
PropertyDescriptor oldDescriptor;
oldDescriptor.setValue(jsUndefined());
return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), oldDescriptor);
@@ -703,18 +740,18 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
// Changing the accessor functions of an existing accessor property
ASSERT(descriptor.isAccessorDescriptor());
if (!current.configurable()) {
- if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) {
+ if (descriptor.setterPresent() && !(current.setterPresent() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) {
if (throwException)
throwError(exec, createTypeError(exec, "Attempting to change the setter of an unconfigurable property."));
return false;
}
- if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) {
+ if (descriptor.getterPresent() && !(current.getterPresent() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) {
if (throwException)
throwError(exec, createTypeError(exec, "Attempting to change the getter of an unconfigurable property."));
return false;
}
}
- JSValue accessor = getDirect(propertyName);
+ JSValue accessor = getDirect(exec->globalData(), propertyName);
if (!accessor)
return false;
GetterSetter* getterSetter = asGetterSetter(accessor);
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index b79249c..80735f8 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -29,7 +29,6 @@
#include "Completion.h"
#include "CallFrame.h"
#include "JSCell.h"
-#include "JSNumberCell.h"
#include "MarkStack.h"
#include "PropertySlot.h"
#include "PutPropertySlot.h"
@@ -80,8 +79,6 @@ namespace JSC {
friend void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot);
public:
- explicit JSObject(NonNullPassRefPtr<Structure>);
-
virtual void markChildren(MarkStack&);
ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack);
@@ -90,11 +87,11 @@ namespace JSC {
virtual ~JSObject();
JSValue prototype() const;
- void setPrototype(JSValue prototype);
- bool setPrototypeWithCycleCheck(JSValue prototype);
+ void setPrototype(JSGlobalData&, JSValue prototype);
+ bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype);
- void setStructure(NonNullPassRefPtr<Structure>);
- Structure* inheritorID();
+ void setStructure(JSGlobalData&, Structure*);
+ Structure* inheritorID(JSGlobalData&);
virtual UString className() const;
@@ -140,7 +137,7 @@ namespace JSC {
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
- virtual JSObject* toObject(ExecState*) const;
+ virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
virtual JSObject* toThisObject(ExecState*) const;
virtual JSValue toStrictThisObject(ExecState*) const;
@@ -149,22 +146,22 @@ namespace JSC {
bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
// This get function only looks at the property map.
- JSValue getDirect(const Identifier& propertyName) const
+ JSValue getDirect(JSGlobalData& globalData, const Identifier& propertyName) const
{
- size_t offset = m_structure->get(propertyName);
+ size_t offset = m_structure->get(globalData, propertyName);
return offset != WTF::notFound ? getDirectOffset(offset) : JSValue();
}
- WriteBarrierBase<Unknown>* getDirectLocation(const Identifier& propertyName)
+ WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName)
{
- size_t offset = m_structure->get(propertyName);
+ size_t offset = m_structure->get(globalData, propertyName);
return offset != WTF::notFound ? locationForOffset(offset) : 0;
}
- WriteBarrierBase<Unknown>* getDirectLocation(const Identifier& propertyName, unsigned& attributes)
+ WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes)
{
JSCell* specificFunction;
- size_t offset = m_structure->get(propertyName, attributes, specificFunction);
+ size_t offset = m_structure->get(globalData, propertyName, attributes, specificFunction);
return offset != WTF::notFound ? locationForOffset(offset) : 0;
}
@@ -173,9 +170,9 @@ namespace JSC {
return location - propertyStorage();
}
- void transitionTo(Structure*);
+ void transitionTo(JSGlobalData&, Structure*);
- void removeDirect(const Identifier& propertyName);
+ void removeDirect(JSGlobalData&, const Identifier& propertyName);
bool hasCustomProperties() { return !m_structure->isEmpty(); }
bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
@@ -212,19 +209,19 @@ namespace JSC {
virtual bool isStrictModeFunction() const { return false; }
virtual bool isErrorInstance() const { return false; }
+ void seal(JSGlobalData&);
+ void freeze(JSGlobalData&);
+ void preventExtensions(JSGlobalData&);
+ bool isSealed(JSGlobalData& globalData) { return m_structure->isSealed(globalData); }
+ bool isFrozen(JSGlobalData& globalData) { return m_structure->isFrozen(globalData); }
+ bool isExtensible() { return m_structure->isExtensible(); }
+
virtual ComplType exceptionType() const { return Throw; }
void allocatePropertyStorage(size_t oldSize, size_t newSize);
- void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
- bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
-
- static const unsigned inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
- static const unsigned nonInlineBaseStorageCapacity = 16;
+ bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage) == static_cast<const void*>(this + 1); }
- static PassRefPtr<Structure> createStructure(JSValue prototype)
- {
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
- }
+ static const unsigned baseExternalStorageCapacity = 16;
void flattenDictionaryObject(JSGlobalData& globalData)
{
@@ -246,15 +243,33 @@ namespace JSC {
ASSERT(index < m_structure->anonymousSlotCount());
return locationForOffset(index)->get();
}
+
+ static size_t offsetOfInlineStorage();
+ static JS_EXPORTDATA const ClassInfo s_info;
+
protected:
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
static const unsigned StructureFlags = 0;
-
+
void putThisToAnonymousValue(unsigned index)
{
locationForOffset(index)->setWithoutWriteBarrier(this);
}
-
+
+ // To instantiate objects you likely want JSFinalObject, below.
+ // To create derived types you likely want JSNonFinalObject, below.
+ JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
+ JSObject(VPtrStealingHackType, PropertyStorage inlineStorage)
+ : JSCell(VPtrStealingHack)
+ , m_propertyStorage(inlineStorage)
+ {
+ }
+
private:
// Nobody should ever ask any of these questions on something already known to be a JSObject.
using JSCell::isAPIValueWrapper;
@@ -265,8 +280,8 @@ namespace JSC {
void isObject();
void isString();
- ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
- PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
+ ConstPropertyStorage propertyStorage() const { return m_propertyStorage; }
+ PropertyStorage propertyStorage() { return m_propertyStorage; }
const WriteBarrierBase<Unknown>* locationForOffset(size_t offset) const
{
@@ -285,16 +300,97 @@ namespace JSC {
bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
- Structure* createInheritorID();
-
- union {
- PropertyStorage m_externalStorage;
- WriteBarrierBase<Unknown> m_inlineStorage[inlineStorageCapacity];
- };
+ Structure* createInheritorID(JSGlobalData&);
- RefPtr<Structure> m_inheritorID;
+ PropertyStorage m_propertyStorage;
+ WriteBarrier<Structure> m_inheritorID;
};
+
+
+#if USE(JSVALUE32_64)
+#define JSNonFinalObject_inlineStorageCapacity 4
+#define JSFinalObject_inlineStorageCapacity 6
+#else
+#define JSNonFinalObject_inlineStorageCapacity 2
+#define JSFinalObject_inlineStorageCapacity 4
+#endif
+
+COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineStorageCapacity), final_storage_is_at_least_as_large_as_non_final);
+
+ // JSNonFinalObject is a type of JSObject that has some internal storage,
+ // but also preserves some space in the collector cell for additional
+ // data members in derived types.
+ class JSNonFinalObject : public JSObject {
+ friend class JSObject;
+
+ public:
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
+ protected:
+ explicit JSNonFinalObject(VPtrStealingHackType)
+ : JSObject(VPtrStealingHack, m_inlineStorage)
+ {
+ }
+ explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
+ : JSObject(globalData, structure, m_inlineStorage)
+ {
+ ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
+ ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
+ }
+
+ private:
+ WriteBarrierBase<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity];
+ };
+
+ // JSFinalObject is a type of JSObject that contains sufficent internal
+ // storage to fully make use of the colloctor cell containing it.
+ class JSFinalObject : public JSObject {
+ friend class JSObject;
+
+ public:
+ static JSFinalObject* create(ExecState* exec, Structure* structure)
+ {
+ return new (exec) JSFinalObject(exec->globalData(), structure);
+ }
+
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
+ private:
+ explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
+ : JSObject(globalData, structure, m_inlineStorage)
+ {
+ ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double) == 0);
+ ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity);
+ }
+
+ static const unsigned StructureFlags = JSObject::StructureFlags | IsJSFinalObject;
+
+ WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity];
+ };
+
+inline size_t JSObject::offsetOfInlineStorage()
+{
+ ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage));
+ return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage);
+}
+
+inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure)
+{
+ return JSFinalObject::create(exec, structure);
+}
+
+inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSValue prototype)
+{
+ return JSFinalObject::createStructure(globalData, prototype);
+}
+
inline JSObject* asObject(JSCell* cell)
{
ASSERT(cell->isObject());
@@ -306,21 +402,22 @@ inline JSObject* asObject(JSValue value)
return asObject(value.asCell());
}
-inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure)
- : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
+inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, PropertyStorage inlineStorage)
+ : JSCell(globalData, structure)
+ , m_propertyStorage(inlineStorage)
{
- ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity);
+ ASSERT(inherits(&s_info));
+ ASSERT(m_structure->propertyStorageCapacity() < baseExternalStorageCapacity);
ASSERT(m_structure->isEmpty());
ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
- ASSERT(OBJECT_OFFSETOF(JSObject, m_inlineStorage) % sizeof(double) == 0);
+ ASSERT(static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1));
+ ASSERT(m_structure->typeInfo().type() == ObjectType);
}
inline JSObject::~JSObject()
{
- ASSERT(m_structure);
if (!isUsingInlineStorage())
- delete [] m_externalStorage;
- m_structure->deref();
+ delete [] m_propertyStorage;
}
inline JSValue JSObject::prototype() const
@@ -328,7 +425,7 @@ inline JSValue JSObject::prototype() const
return m_structure->storedPrototype();
}
-inline bool JSObject::setPrototypeWithCycleCheck(JSValue prototype)
+inline bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype)
{
JSValue nextPrototypeValue = prototype;
while (nextPrototypeValue && nextPrototypeValue.isObject()) {
@@ -337,33 +434,33 @@ inline bool JSObject::setPrototypeWithCycleCheck(JSValue prototype)
return false;
nextPrototypeValue = nextPrototype->prototype();
}
- setPrototype(prototype);
+ setPrototype(globalData, prototype);
return true;
}
-inline void JSObject::setPrototype(JSValue prototype)
+inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
{
ASSERT(prototype);
- RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype);
- setStructure(newStructure.release());
+ setStructure(globalData, Structure::changePrototypeTransition(globalData, m_structure.get(), prototype));
}
-inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure)
+inline void JSObject::setStructure(JSGlobalData& globalData, Structure* structure)
{
- m_structure->deref();
- m_structure = structure.leakRef(); // ~JSObject balances this ref()
+ m_structure.set(globalData, this, structure);
}
-inline Structure* JSObject::inheritorID()
+inline Structure* JSObject::inheritorID(JSGlobalData& globalData)
{
- if (m_inheritorID)
+ if (m_inheritorID) {
+ ASSERT(m_inheritorID->isEmpty());
return m_inheritorID.get();
- return createInheritorID();
+ }
+ return createInheritorID(globalData);
}
inline bool Structure::isUsingInlineStorage() const
{
- return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
+ return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity;
}
inline bool JSCell::inherits(const ClassInfo* info) const
@@ -383,7 +480,7 @@ inline bool JSValue::inherits(const ClassInfo* classInfo) const
ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
- if (WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName)) {
+ if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
if (m_structure->hasGetterSetterProperties() && location->isGetterSetter())
fillGetterPropertySlot(slot, location);
else
@@ -469,12 +566,12 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
if (m_structure->isDictionary()) {
unsigned currentAttributes;
JSCell* currentSpecificFunction;
- size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
+ size_t offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
if (offset != WTF::notFound) {
// If there is currently a specific function, and there now either isn't,
// or the new value is different, then despecify.
if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
- m_structure->despecifyDictionaryFunction(propertyName);
+ m_structure->despecifyDictionaryFunction(globalData, propertyName);
if (checkReadOnly && currentAttributes & ReadOnly)
return false;
@@ -490,8 +587,11 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
return true;
}
+ if (!isExtensible())
+ return false;
+
size_t currentCapacity = m_structure->propertyStorageCapacity();
- offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction);
+ offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
if (currentCapacity != m_structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
@@ -505,12 +605,12 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
size_t offset;
size_t currentCapacity = m_structure->propertyStorageCapacity();
- if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, specificFunction, offset)) {
+ if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(m_structure.get(), propertyName, attributes, specificFunction, offset)) {
if (currentCapacity != structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
ASSERT(offset < structure->propertyStorageCapacity());
- setStructure(structure.release());
+ setStructure(globalData, structure);
putDirectOffset(globalData, offset, value);
// This is a new property; transitions with specific values are not currently cachable,
// so leave the slot in an uncachable state.
@@ -521,7 +621,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
unsigned currentAttributes;
JSCell* currentSpecificFunction;
- offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
+ offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
if (offset != WTF::notFound) {
if (checkReadOnly && currentAttributes & ReadOnly)
return false;
@@ -542,7 +642,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
return true;
}
// case (2) Despecify, fall through to (3).
- setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName));
+ setStructure(globalData, Structure::despecifyFunctionTransition(globalData, m_structure.get(), propertyName));
}
// case (3) set the slot, do the put, return.
@@ -551,23 +651,16 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
return true;
}
- // If we have a specific function, we may have got to this point if there is
- // already a transition with the correct property name and attributes, but
- // specialized to a different function. In this case we just want to give up
- // and despecialize the transition.
- // In this case we clear the value of specificFunction which will result
- // in us adding a non-specific transition, and any subsequent lookup in
- // Structure::addPropertyTransitionToExistingStructure will just use that.
- if (specificFunction && m_structure->hasTransition(propertyName, attributes))
- specificFunction = 0;
+ if (!isExtensible())
+ return false;
- RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset);
+ Structure* structure = Structure::addPropertyTransition(globalData, m_structure.get(), propertyName, attributes, specificFunction, offset);
if (currentCapacity != structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
ASSERT(offset < structure->propertyStorageCapacity());
- setStructure(structure.release());
+ setStructure(globalData, structure);
putDirectOffset(globalData, offset, value);
// This is a new property; transitions with specific values are not currently cachable,
// so leave the slot in an uncachable state.
@@ -623,7 +716,7 @@ inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifi
inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
size_t currentCapacity = m_structure->propertyStorageCapacity();
- size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, 0);
+ size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, 0);
if (currentCapacity != m_structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
putDirectOffset(globalData, offset, value);
@@ -632,17 +725,17 @@ inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const
inline void JSObject::putDirectFunctionWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attributes)
{
size_t currentCapacity = m_structure->propertyStorageCapacity();
- size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, value);
+ size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, value);
if (currentCapacity != m_structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
putDirectOffset(globalData, offset, value);
}
-inline void JSObject::transitionTo(Structure* newStructure)
+inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
{
if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
- setStructure(newStructure);
+ setStructure(globalData, newStructure);
}
inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
@@ -727,34 +820,15 @@ inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
asCell()->put(exec, propertyName, value);
}
-ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_t newSize)
-{
- ASSERT(newSize > oldSize);
-
- // It's important that this function not rely on m_structure, since
- // we might be in the middle of a transition.
- bool wasInline = (oldSize == JSObject::inlineStorageCapacity);
-
- PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage);
- PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
-
- for (unsigned i = 0; i < oldSize; ++i)
- newPropertyStorage[i] = oldPropertyStorage[i];
-
- if (!wasInline)
- delete [] oldPropertyStorage;
-
- m_externalStorage = newPropertyStorage;
-}
-
ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack)
{
JSCell::markChildren(markStack);
- markStack.append(m_structure->storedPrototypeSlot());
PropertyStorage storage = propertyStorage();
size_t storageSize = m_structure->propertyStorageSize();
markStack.appendValues(storage, storageSize);
+ if (m_inheritorID)
+ markStack.append(&m_inheritorID);
}
// --- JSValue inlines ----------------------------
@@ -776,6 +850,20 @@ inline JSValue JSValue::toStrictThisObject(ExecState* exec) const
return asObject(asCell())->toStrictThisObject(exec);
}
+ALWAYS_INLINE JSObject* Register::function() const
+{
+ if (!jsValue())
+ return 0;
+ return asObject(jsValue());
+}
+
+ALWAYS_INLINE Register Register::withCallee(JSObject* callee)
+{
+ Register r;
+ r = JSValue(callee);
+ return r;
+}
+
} // namespace JSC
#endif // JSObject_h
diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp
index c16acb1..2b489a2 100644
--- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp
@@ -30,8 +30,8 @@
namespace JSC {
-JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, Structure* structure)
+ : JSNonFinalObject(globalObject->globalData(), structure)
{
COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one);
ASSERT(!globalObject || globalObject->isGlobalObject());
@@ -41,9 +41,15 @@ JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject,
putAnonymousValue(globalObject->globalData(), GlobalObjectSlot, globalObject);
}
-JSGlobalObject* JSObjectWithGlobalObject::globalObject() const
+JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject, Structure* structure)
+ : JSNonFinalObject(globalData, structure)
{
- return asGlobalObject((getAnonymousValue(GlobalObjectSlot).asCell()));
+ COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one);
+ ASSERT(!globalObject || globalObject->isGlobalObject());
+ if (!globalObject)
+ clearAnonymousValue(GlobalObjectSlot);
+ else
+ putAnonymousValue(globalData, GlobalObjectSlot, globalObject);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h
index 9416a62..844bcd8 100644
--- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h
@@ -26,26 +26,30 @@
#ifndef JSObjectWithGlobalObject_h
#define JSObjectWithGlobalObject_h
-#include "JSObject.h"
+#include "JSGlobalObject.h"
namespace JSC {
class JSGlobalObject;
-class JSObjectWithGlobalObject : public JSObject {
+class JSObjectWithGlobalObject : public JSNonFinalObject {
public:
- static PassRefPtr<Structure> createStructure(JSValue proto)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
- JSGlobalObject* globalObject() const;
+ JSGlobalObject* globalObject() const
+ {
+ return asGlobalObject((getAnonymousValue(GlobalObjectSlot).asCell()));
+ }
protected:
- JSObjectWithGlobalObject(JSGlobalObject*, NonNullPassRefPtr<Structure>);
+ JSObjectWithGlobalObject(JSGlobalObject*, Structure*);
+ JSObjectWithGlobalObject(JSGlobalData&, JSGlobalObject*, Structure*);
- JSObjectWithGlobalObject(NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+ JSObjectWithGlobalObject(VPtrStealingHackType)
+ : JSNonFinalObject(VPtrStealingHack)
{
// Should only be used by JSFunction when we aquire the JSFunction vptr.
}
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index 6fd28e3..d5af044 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -35,9 +35,10 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
+const ClassInfo JSPropertyNameIterator::s_info = { "JSPropertyNameIterator", 0, 0, 0 };
+
inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
- : JSCell(exec->globalData().propertyNameIteratorStructure.get())
- , m_cachedStructure(0)
+ : JSCell(exec->globalData(), exec->globalData().propertyNameIteratorStructure.get())
, m_numCacheableSlots(numCacheableSlots)
, m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
, m_jsStrings(adoptArrayPtr(new WriteBarrier<Unknown>[m_jsStringsSize]))
@@ -47,12 +48,6 @@ inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyN
m_jsStrings[i].set(exec->globalData(), this, jsOwnedString(exec, propertyNameVector[i].ustring()));
}
-JSPropertyNameIterator::~JSPropertyNameIterator()
-{
- if (m_cachedStructure)
- m_cachedStructure->clearEnumerationCache(this);
-}
-
JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
{
ASSERT(!o->structure()->enumerationCache() ||
@@ -77,22 +72,22 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
size_t count = normalizePrototypeChain(exec, o);
StructureChain* structureChain = o->structure()->prototypeChain(exec);
- RefPtr<Structure>* structure = structureChain->head();
+ WriteBarrier<Structure>* structure = structureChain->head();
for (size_t i = 0; i < count; ++i) {
if (structure[i]->typeInfo().overridesGetPropertyNames())
return jsPropertyNameIterator;
}
- jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
- jsPropertyNameIterator->setCachedStructure(o->structure());
- o->structure()->setEnumerationCache(jsPropertyNameIterator);
+ jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain);
+ jsPropertyNameIterator->setCachedStructure(exec->globalData(), o->structure());
+ o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator);
return jsPropertyNameIterator;
}
JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
{
JSValue identifier = m_jsStrings[i].get();
- if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec))
+ if (m_cachedStructure.get() == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec))
return identifier;
if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec))))
@@ -103,6 +98,8 @@ JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
void JSPropertyNameIterator::markChildren(MarkStack& markStack)
{
markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
+ if (m_cachedPrototypeChain)
+ markStack.append(&m_cachedPrototypeChain);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
index cd46243..b857dc0 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -45,12 +45,10 @@ namespace JSC {
public:
static JSPropertyNameIterator* create(ExecState*, JSObject*);
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, &s_info);
}
-
- virtual ~JSPropertyNameIterator();
virtual bool isPropertyNameIterator() const { return true; }
@@ -67,41 +65,42 @@ namespace JSC {
JSValue get(ExecState*, JSObject*, size_t i);
size_t size() { return m_jsStringsSize; }
- void setCachedStructure(Structure* structure)
+ void setCachedStructure(JSGlobalData& globalData, Structure* structure)
{
ASSERT(!m_cachedStructure);
ASSERT(structure);
- m_cachedStructure = structure;
+ m_cachedStructure.set(globalData, this, structure);
}
Structure* cachedStructure() { return m_cachedStructure.get(); }
- void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+ void setCachedPrototypeChain(JSGlobalData& globalData, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(globalData, this, cachedPrototypeChain); }
StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
private:
+ static const ClassInfo s_info;
JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
- RefPtr<Structure> m_cachedStructure;
- RefPtr<StructureChain> m_cachedPrototypeChain;
+ WriteBarrier<Structure> m_cachedStructure;
+ WriteBarrier<StructureChain> m_cachedPrototypeChain;
uint32_t m_numCacheableSlots;
uint32_t m_jsStringsSize;
OwnArrayPtr<WriteBarrier<Unknown> > m_jsStrings;
};
- inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache)
+ inline void Structure::setEnumerationCache(JSGlobalData& globalData, JSPropertyNameIterator* enumerationCache)
{
ASSERT(!isDictionary());
- m_enumerationCache = enumerationCache;
+ m_enumerationCache.set(globalData, this, enumerationCache);
}
- inline void Structure::clearEnumerationCache(JSPropertyNameIterator* enumerationCache)
+ inline JSPropertyNameIterator* Structure::enumerationCache()
{
- m_enumerationCache.clear(enumerationCache);
+ return m_enumerationCache.get();
}
- inline JSPropertyNameIterator* Structure::enumerationCache()
+ ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
{
- return m_enumerationCache.get();
+ return static_cast<JSPropertyNameIterator*>(jsValue().asCell());
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
index 80b048e..3d4dc7c 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
@@ -28,13 +28,12 @@
#include "JSStaticScopeObject.h"
namespace JSC {
-
ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
void JSStaticScopeObject::markChildren(MarkStack& markStack)
{
JSVariableObject::markChildren(markStack);
- markStack.deprecatedAppend(&d()->registerStore);
+ markStack.append(&m_registerStore);
}
JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
@@ -47,17 +46,17 @@ JSValue JSStaticScopeObject::toStrictThisObject(ExecState*) const
return jsNull();
}
-void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&)
+void JSStaticScopeObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&)
{
- if (symbolTablePut(propertyName, value))
+ if (symbolTablePut(exec->globalData(), propertyName, value))
return;
ASSERT_NOT_REACHED();
}
-void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSStaticScopeObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
- if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
return;
ASSERT_NOT_REACHED();
@@ -68,13 +67,7 @@ bool JSStaticScopeObject::isDynamicScope(bool&) const
return false;
}
-JSStaticScopeObject::~JSStaticScopeObject()
-{
- ASSERT(d());
- delete d();
-}
-
-inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
+bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
{
return symbolTableGet(propertyName, slot);
}
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
index e69356a..8c3a249 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
@@ -31,25 +31,14 @@
namespace JSC{
class JSStaticScopeObject : public JSVariableObject {
- protected:
- using JSVariableObject::JSVariableObjectData;
- struct JSStaticScopeObjectData : public JSVariableObjectData {
- JSStaticScopeObjectData()
- : JSVariableObjectData(&symbolTable, &registerStore + 1)
- {
- }
- SymbolTable symbolTable;
- Register registerStore;
- };
-
public:
JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes)
- : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData())
+ : JSVariableObject(exec->globalData(), exec->globalData().staticScopeStructure.get(), &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1))
{
- d()->registerStore = value;
+ m_registerStore.set(exec->globalData(), this, value);
symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes));
}
- virtual ~JSStaticScopeObject();
+
virtual void markChildren(MarkStack&);
bool isDynamicScope(bool& requiresDynamicChecks) const;
virtual JSObject* toThisObject(ExecState*) const;
@@ -58,13 +47,14 @@ namespace JSC{
virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes);
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); }
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
private:
- JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
+ SymbolTable m_symbolTable;
+ WriteBarrier<Unknown> m_registerStore;
};
}
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index 848c431..d9c4d46 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -152,7 +152,7 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart,
if (substringLength == 1) {
ASSERT(substringFiberCount == 1);
UChar c = substringFibers[0].characters()[0];
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
if (substringFiberCount == 1)
@@ -253,19 +253,19 @@ UString JSString::toString(ExecState* exec) const
return value(exec);
}
-inline StringObject* StringObject::create(ExecState* exec, JSString* string)
+inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
{
- return new (exec) StringObject(exec->globalData(), exec->lexicalGlobalObject()->stringObjectStructure(), string);
+ return new (exec) StringObject(exec->globalData(), globalObject->stringObjectStructure(), string);
}
-JSObject* JSString::toObject(ExecState* exec) const
+JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const
{
- return StringObject::create(exec, const_cast<JSString*>(this));
+ return StringObject::create(exec, globalObject, const_cast<JSString*>(this));
}
JSObject* JSString::toThisObject(ExecState* exec) const
{
- return StringObject::create(exec, const_cast<JSString*>(this));
+ return StringObject::create(exec, exec->lexicalGlobalObject(), const_cast<JSString*>(this));
}
bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index 6696404..3422dad 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -26,10 +26,10 @@
#include "CallFrame.h"
#include "CommonIdentifiers.h"
#include "Identifier.h"
-#include "JSNumberCell.h"
#include "PropertyDescriptor.h"
#include "PropertySlot.h"
#include "RopeImpl.h"
+#include "Structure.h"
namespace JSC {
@@ -185,7 +185,7 @@ namespace JSC {
};
ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(value.length())
, m_value(value)
, m_fiberCount(0)
@@ -196,7 +196,7 @@ namespace JSC {
enum HasOtherOwnerType { HasOtherOwner };
JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(value.length())
, m_value(value)
, m_fiberCount(0)
@@ -204,7 +204,7 @@ namespace JSC {
ASSERT(!m_value.isNull());
}
JSString(JSGlobalData* globalData, PassRefPtr<StringImpl> value, HasOtherOwnerType)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(value->length())
, m_value(value)
, m_fiberCount(0)
@@ -212,7 +212,7 @@ namespace JSC {
ASSERT(!m_value.isNull());
}
JSString(JSGlobalData* globalData, PassRefPtr<RopeImpl> rope)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(rope->length())
, m_fiberCount(1)
{
@@ -221,7 +221,7 @@ namespace JSC {
// This constructor constructs a new string by concatenating s1 & s2.
// This should only be called with fiberCount <= 3.
JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, JSString* s2)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(s1->length() + s2->length())
, m_fiberCount(fiberCount)
{
@@ -234,7 +234,7 @@ namespace JSC {
// This constructor constructs a new string by concatenating s1 & s2.
// This should only be called with fiberCount <= 3.
JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, const UString& u2)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(s1->length() + u2.length())
, m_fiberCount(fiberCount)
{
@@ -247,7 +247,7 @@ namespace JSC {
// This constructor constructs a new string by concatenating s1 & s2.
// This should only be called with fiberCount <= 3.
JSString(JSGlobalData* globalData, unsigned fiberCount, const UString& u1, JSString* s2)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(u1.length() + s2->length())
, m_fiberCount(fiberCount)
{
@@ -262,7 +262,7 @@ namespace JSC {
// value must require a fiberCount of at least one implies that the length
// for each value must be exactly 1!
JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3)
- : JSCell(exec->globalData().stringStructure.get())
+ : JSCell(exec->globalData(), exec->globalData().stringStructure.get())
, m_length(0)
, m_fiberCount(s_maxInternalRopeLength)
{
@@ -275,7 +275,7 @@ namespace JSC {
// This constructor constructs a new string by concatenating u1 & u2.
JSString(JSGlobalData* globalData, const UString& u1, const UString& u2)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(u1.length() + u2.length())
, m_fiberCount(2)
{
@@ -287,7 +287,7 @@ namespace JSC {
// This constructor constructs a new string by concatenating u1, u2 & u3.
JSString(JSGlobalData* globalData, const UString& u1, const UString& u2, const UString& u3)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(u1.length() + u2.length() + u3.length())
, m_fiberCount(s_maxInternalRopeLength)
{
@@ -299,7 +299,7 @@ namespace JSC {
}
JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context)
- : JSCell(globalData->stringStructure.get())
+ : JSCell(*globalData, globalData->stringStructure.get())
, m_length(value.length())
, m_value(value)
, m_fiberCount(0)
@@ -349,12 +349,11 @@ namespace JSC {
JSValue replaceCharacter(ExecState*, UChar, const UString& replacement);
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); }
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); }
private:
- enum VPtrStealingHackType { VPtrStealingHack };
JSString(VPtrStealingHackType)
- : JSCell(0)
+ : JSCell(VPtrStealingHack)
, m_fiberCount(0)
{
}
@@ -402,7 +401,7 @@ namespace JSC {
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
- virtual JSObject* toObject(ExecState*) const;
+ virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toThisObject(ExecState*) const;
@@ -468,7 +467,7 @@ namespace JSC {
inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
{
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1)));
}
@@ -478,7 +477,7 @@ namespace JSC {
JSGlobalData* globalData = &exec->globalData();
ASSERT(offset < static_cast<unsigned>(s.length()));
UChar c = s.characters()[offset];
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, 1))));
}
@@ -513,7 +512,7 @@ namespace JSC {
return globalData->smallStrings.emptyString(globalData);
if (size == 1) {
UChar c = s.characters()[0];
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
@@ -521,7 +520,7 @@ namespace JSC {
inline JSString* jsStringWithFinalizer(ExecState* exec, const UString& s, JSStringFinalizerCallback callback, void* context)
{
- ASSERT(s.length() && (s.length() > 1 || s.characters()[0] > 0xFF));
+ ASSERT(s.length() && (s.length() > 1 || s.characters()[0] > maxSingleCharacterString));
JSGlobalData* globalData = &exec->globalData();
return fixupVPtr(globalData, new (globalData) JSString(globalData, s, callback, context));
}
@@ -548,7 +547,7 @@ namespace JSC {
return globalData->smallStrings.emptyString(globalData);
if (length == 1) {
UChar c = s.characters()[offset];
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, length)), JSString::HasOtherOwner));
@@ -561,7 +560,7 @@ namespace JSC {
return globalData->smallStrings.emptyString(globalData);
if (size == 1) {
UChar c = s.characters()[0];
- if (c <= 0xFF)
+ if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner));
diff --git a/Source/JavaScriptCore/runtime/JSType.h b/Source/JavaScriptCore/runtime/JSType.h
index 882b218..dba03f6 100644
--- a/Source/JavaScriptCore/runtime/JSType.h
+++ b/Source/JavaScriptCore/runtime/JSType.h
@@ -33,10 +33,11 @@ namespace JSC {
NumberType = 3,
NullType = 4,
StringType = 5,
+ LeafType = 6,
// The CompoundType value must come before any JSType that may have children
- CompoundType = 6,
- ObjectType = 7,
- GetterSetterType = 8
+ CompoundType = 7,
+ ObjectType = 8,
+ GetterSetterType = 9
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h
index e225bc7..acde81f 100644
--- a/Source/JavaScriptCore/runtime/JSTypeInfo.h
+++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h
@@ -43,20 +43,21 @@ namespace JSC {
static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
static const unsigned OverridesMarkChildren = 1 << 6;
static const unsigned OverridesGetPropertyNames = 1 << 7;
+ static const unsigned IsJSFinalObject = 1 << 8;
class TypeInfo {
- friend class JIT;
public:
TypeInfo(JSType type, unsigned flags = 0)
: m_type(type)
+ , m_flags(flags & 0xFF)
+ , m_flags2(flags >> 8)
{
- ASSERT(flags <= 0xFF);
+ ASSERT(flags <= 0x1FF);
ASSERT(type <= 0xFF);
+ ASSERT(type >= CompoundType || !(flags & OverridesMarkChildren));
// ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
- if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
- m_flags = flags | ImplementsDefaultHasInstance;
- else
- m_flags = flags;
+ if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
+ m_flags |= ImplementsDefaultHasInstance;
}
JSType type() const { return (JSType)m_type; }
@@ -69,10 +70,22 @@ namespace JSC {
bool overridesMarkChildren() const { return m_flags & OverridesMarkChildren; }
bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; }
unsigned flags() const { return m_flags; }
+ unsigned isFinal() const { return m_flags2 && (IsJSFinalObject >> 8); }
+
+ static ptrdiff_t flagsOffset()
+ {
+ return OBJECT_OFFSETOF(TypeInfo, m_flags);
+ }
+
+ static ptrdiff_t typeOffset()
+ {
+ return OBJECT_OFFSETOF(TypeInfo, m_type);
+ }
private:
unsigned char m_type;
unsigned char m_flags;
+ unsigned char m_flags2;
};
}
diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp
index f4662db..d3ee89e 100644
--- a/Source/JavaScriptCore/runtime/JSValue.cpp
+++ b/Source/JavaScriptCore/runtime/JSValue.cpp
@@ -54,14 +54,14 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const
return trunc(toNumber(exec));
}
-JSObject* JSValue::toObjectSlowCase(ExecState* exec) const
+JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
{
ASSERT(!isCell());
if (isInt32() || isDouble())
- return constructNumber(exec, asValue());
+ return constructNumber(exec, globalObject, asValue());
if (isTrue() || isFalse())
- return constructBooleanFromImmediateBoolean(exec, asValue());
+ return constructBooleanFromImmediateBoolean(exec, globalObject, asValue());
ASSERT(isUndefinedOrNull());
throwError(exec, createNotAnObjectError(exec, *this));
@@ -73,9 +73,9 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
ASSERT(!isCell());
if (isInt32() || isDouble())
- return constructNumber(exec, asValue());
+ return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
if (isTrue() || isFalse())
- return constructBooleanFromImmediateBoolean(exec, asValue());
+ return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
ASSERT(isUndefinedOrNull());
return exec->globalThisValue();
}
@@ -84,9 +84,9 @@ JSObject* JSValue::synthesizeObject(ExecState* exec) const
{
ASSERT(!isCell());
if (isNumber())
- return constructNumber(exec, asValue());
+ return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
if (isBoolean())
- return constructBooleanFromImmediateBoolean(exec, asValue());
+ return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
ASSERT(isUndefinedOrNull());
throwError(exec, createNotAnObjectError(exec, *this));
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index b2e7a51..de50011 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -30,14 +30,18 @@
#include <wtf/Assertions.h>
#include <wtf/HashTraits.h>
#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
namespace JSC {
+ extern const double NaN;
+ extern const double Inf;
+
class ExecState;
class Identifier;
class JSCell;
class JSGlobalData;
- class JSImmediate;
+ class JSGlobalObject;
class JSObject;
class JSString;
class PropertySlot;
@@ -47,16 +51,37 @@ namespace JSC {
struct ClassInfo;
struct Instruction;
- template <class T> class DeprecatedPtr;
template <class T> class WriteBarrierBase;
enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
+
#if USE(JSVALUE32_64)
typedef int64_t EncodedJSValue;
#else
typedef void* EncodedJSValue;
#endif
+
+ union EncodedValueDescriptor {
+ int64_t asInt64;
+#if USE(JSVALUE32_64)
+ double asDouble;
+#elif USE(JSVALUE64)
+ JSCell* ptr;
+#endif
+
+#if CPU(BIG_ENDIAN)
+ struct {
+ int32_t tag;
+ int32_t payload;
+ } asBits;
+#else
+ struct {
+ int32_t payload;
+ int32_t tag;
+ } asBits;
+#endif
+ };
double nonInlineNaN();
@@ -72,7 +97,6 @@ namespace JSC {
}
class JSValue {
- friend class JSImmediate;
friend struct EncodedJSValueHashTraits;
friend class JIT;
friend class JITStubs;
@@ -81,14 +105,9 @@ namespace JSC {
friend class SpecializedThunkJIT;
public:
- static EncodedJSValue encode(JSValue value);
- static JSValue decode(EncodedJSValue ptr);
-#if USE(JSVALUE64)
- private:
- static JSValue makeImmediate(intptr_t value);
- intptr_t immediateValue();
- public:
-#endif
+ static EncodedJSValue encode(JSValue);
+ static JSValue decode(EncodedJSValue);
+
enum JSNullTag { JSNull };
enum JSUndefinedTag { JSUndefined };
enum JSTrueTag { JSTrue };
@@ -167,6 +186,7 @@ namespace JSC {
UString toString(ExecState*) const;
UString toPrimitiveString(ExecState*) const;
JSObject* toObject(ExecState*) const;
+ JSObject* toObject(ExecState*, JSGlobalObject*) const;
// Integer conversions.
double toInteger(ExecState*) const;
@@ -215,52 +235,133 @@ namespace JSC {
#endif
private:
- template <class T> JSValue(DeprecatedPtr<T>);
template <class T> JSValue(WriteBarrierBase<T>);
enum HashTableDeletedValueTag { HashTableDeletedValue };
JSValue(HashTableDeletedValueTag);
inline const JSValue asValue() const { return *this; }
- JSObject* toObjectSlowCase(ExecState*) const;
+ JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
JSObject* toThisObjectSlowCase(ExecState*) const;
JSObject* synthesizePrototype(ExecState*) const;
JSObject* synthesizeObject(ExecState*) const;
#if USE(JSVALUE32_64)
- enum { NullTag = 0xffffffff };
- enum { UndefinedTag = 0xfffffffe };
- enum { Int32Tag = 0xfffffffd };
- enum { CellTag = 0xfffffffc };
- enum { TrueTag = 0xfffffffb };
- enum { FalseTag = 0xfffffffa };
- enum { EmptyValueTag = 0xfffffff9 };
- enum { DeletedValueTag = 0xfffffff8 };
-
+ /*
+ * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
+ * form for immediates.
+ *
+ * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
+ * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
+ * can encode a 51-bit payload. Hardware produced and C-library payloads typically
+ * have a payload of zero. We assume that non-zero payloads are available to encode
+ * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
+ * all set represents a NaN with a non-zero payload, we can use this space in the NaN
+ * ranges to encode other values (however there are also other ranges of NaN space that
+ * could have been selected).
+ *
+ * For JSValues that do not contain a double value, the high 32 bits contain the tag
+ * values listed in the enums below, which all correspond to NaN-space. In the case of
+ * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
+ * integer or boolean value; in the case of all other tags the payload is 0.
+ */
+ enum { Int32Tag = 0xffffffff };
+ enum { BooleanTag = 0xfffffffe };
+ enum { NullTag = 0xfffffffd };
+ enum { UndefinedTag = 0xfffffffc };
+ enum { CellTag = 0xfffffffb };
+ enum { EmptyValueTag = 0xfffffffa };
+ enum { DeletedValueTag = 0xfffffff9 };
+
enum { LowestTag = DeletedValueTag };
-
+
uint32_t tag() const;
int32_t payload() const;
-
- union {
- EncodedJSValue asEncodedJSValue;
- double asDouble;
-#if CPU(BIG_ENDIAN)
- struct {
- int32_t tag;
- int32_t payload;
- } asBits;
-#else
- struct {
- int32_t payload;
- int32_t tag;
- } asBits;
+#elif USE(JSVALUE64)
+ /*
+ * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
+ * form for immediates.
+ *
+ * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
+ * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
+ * can encode a 51-bit payload. Hardware produced and C-library payloads typically
+ * have a payload of zero. We assume that non-zero payloads are available to encode
+ * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
+ * all set represents a NaN with a non-zero payload, we can use this space in the NaN
+ * ranges to encode other values (however there are also other ranges of NaN space that
+ * could have been selected).
+ *
+ * This range of NaN space is represented by 64-bit numbers begining with the 16-bit
+ * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision
+ * numbers will begin fall in these ranges.
+ *
+ * The top 16-bits denote the type of the encoded JSValue:
+ *
+ * Pointer { 0000:PPPP:PPPP:PPPP
+ * / 0001:****:****:****
+ * Double { ...
+ * \ FFFE:****:****:****
+ * Integer { FFFF:0000:IIII:IIII
+ *
+ * The scheme we have implemented encodes double precision values by performing a
+ * 64-bit integer addition of the value 2^48 to the number. After this manipulation
+ * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF.
+ * Values must be decoded by reversing this operation before subsequent floating point
+ * operations my be peformed.
+ *
+ * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.
+ *
+ * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean,
+ * null and undefined values are represented by specific, invalid pointer values:
+ *
+ * False: 0x06
+ * True: 0x07
+ * Undefined: 0x0a
+ * Null: 0x02
+ *
+ * These values have the following properties:
+ * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
+ * quickly distinguished from all immediate values, including these invalid pointers.
+ * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
+ * same value, allowing null & undefined to be quickly detected.
+ *
+ * No valid JSValue will have the bit pattern 0x0, this is used to represent array
+ * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
+ */
+
+ // These values are #defines since using static const integers here is a ~1% regression!
+
+ // This value is 2^48, used to encode doubles such that the encoded value will begin
+ // with a 16-bit pattern within the range 0x0001..0xFFFE.
+ #define DoubleEncodeOffset 0x1000000000000ll
+ // If all bits in the mask are set, this indicates an integer number,
+ // if any but not all are set this value is a double precision number.
+ #define TagTypeNumber 0xffff000000000000ll
+
+ // All non-numeric (bool, null, undefined) immediates have bit 2 set.
+ #define TagBitTypeOther 0x2ll
+ #define TagBitBool 0x4ll
+ #define TagBitUndefined 0x8ll
+ // Combined integer value for non-numeric immediates.
+ #define ValueFalse (TagBitTypeOther | TagBitBool | false)
+ #define ValueTrue (TagBitTypeOther | TagBitBool | true)
+ #define ValueUndefined (TagBitTypeOther | TagBitUndefined)
+ #define ValueNull (TagBitTypeOther)
+
+ // TagMask is used to check for all types of immediate values (either number or 'other').
+ #define TagMask (TagTypeNumber | TagBitTypeOther)
+
+ // These special values are never visible to JavaScript code; Empty is used to represent
+ // Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
+ // These values would map to cell types in the JSValue encoding, but not valid GC cell
+ // pointer should have either of these values (Empty is null, deleted is at an invalid
+ // alignment for a GC cell, and in the zero page).
+ #define ValueEmpty 0x0ll
+ #define ValueDeleted 0x4ll
#endif
- } u;
-#else // USE(JSVALUE32_64)
- JSCell* m_ptr;
-#endif // USE(JSVALUE32_64)
+
+ EncodedValueDescriptor u;
};
#if USE(JSVALUE32_64)
@@ -363,412 +464,7 @@ namespace JSC {
inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
- ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
- {
- if (isInt32())
- return asInt32();
- return JSC::toInt32(toNumber(exec));
- }
-
- inline uint32_t JSValue::toUInt32(ExecState* exec) const
- {
- // See comment on JSC::toUInt32, above.
- return toInt32(exec);
- }
-
-#if USE(JSVALUE32_64)
- inline JSValue jsNaN()
- {
- return JSValue(nonInlineNaN());
- }
-
- // JSValue member functions.
- inline EncodedJSValue JSValue::encode(JSValue value)
- {
- return value.u.asEncodedJSValue;
- }
-
- inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
- {
- JSValue v;
- v.u.asEncodedJSValue = encodedJSValue;
-#if ENABLE(JSC_ZOMBIES)
- ASSERT(!v.isZombie());
-#endif
- return v;
- }
-
- inline JSValue::JSValue()
- {
- u.asBits.tag = EmptyValueTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSNullTag)
- {
- u.asBits.tag = NullTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSUndefinedTag)
- {
- u.asBits.tag = UndefinedTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSTrueTag)
- {
- u.asBits.tag = TrueTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSFalseTag)
- {
- u.asBits.tag = FalseTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(HashTableDeletedValueTag)
- {
- u.asBits.tag = DeletedValueTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSCell* ptr)
- {
- if (ptr)
- u.asBits.tag = CellTag;
- else
- u.asBits.tag = EmptyValueTag;
- u.asBits.payload = reinterpret_cast<int32_t>(ptr);
-#if ENABLE(JSC_ZOMBIES)
- ASSERT(!isZombie());
-#endif
- }
-
- inline JSValue::JSValue(const JSCell* ptr)
- {
- if (ptr)
- u.asBits.tag = CellTag;
- else
- u.asBits.tag = EmptyValueTag;
- u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
-#if ENABLE(JSC_ZOMBIES)
- ASSERT(!isZombie());
-#endif
- }
-
- inline JSValue::operator bool() const
- {
- ASSERT(tag() != DeletedValueTag);
- return tag() != EmptyValueTag;
- }
-
- inline bool JSValue::operator==(const JSValue& other) const
- {
- return u.asEncodedJSValue == other.u.asEncodedJSValue;
- }
-
- inline bool JSValue::operator!=(const JSValue& other) const
- {
- return u.asEncodedJSValue != other.u.asEncodedJSValue;
- }
-
- inline bool JSValue::isUndefined() const
- {
- return tag() == UndefinedTag;
- }
-
- inline bool JSValue::isNull() const
- {
- return tag() == NullTag;
- }
-
- inline bool JSValue::isUndefinedOrNull() const
- {
- return isUndefined() || isNull();
- }
-
- inline bool JSValue::isCell() const
- {
- return tag() == CellTag;
- }
-
- inline bool JSValue::isInt32() const
- {
- return tag() == Int32Tag;
- }
-
- inline bool JSValue::isUInt32() const
- {
- return tag() == Int32Tag && asInt32() > -1;
- }
-
- inline bool JSValue::isDouble() const
- {
- return tag() < LowestTag;
- }
-
- inline bool JSValue::isTrue() const
- {
- return tag() == TrueTag;
- }
-
- inline bool JSValue::isFalse() const
- {
- return tag() == FalseTag;
- }
-
- inline uint32_t JSValue::tag() const
- {
- return u.asBits.tag;
- }
-
- inline int32_t JSValue::payload() const
- {
- return u.asBits.payload;
- }
-
- inline int32_t JSValue::asInt32() const
- {
- ASSERT(isInt32());
- return u.asBits.payload;
- }
-
- inline uint32_t JSValue::asUInt32() const
- {
- ASSERT(isUInt32());
- return u.asBits.payload;
- }
-
- inline double JSValue::asDouble() const
- {
- ASSERT(isDouble());
- return u.asDouble;
- }
-
- ALWAYS_INLINE JSCell* JSValue::asCell() const
- {
- ASSERT(isCell());
- return reinterpret_cast<JSCell*>(u.asBits.payload);
- }
-
- ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
- {
- u.asDouble = d;
- }
-
- inline JSValue::JSValue(double d)
- {
- const int32_t asInt32 = static_cast<int32_t>(d);
- if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
- u.asDouble = d;
- return;
- }
- *this = JSValue(static_cast<int32_t>(d));
- }
-
- inline JSValue::JSValue(char i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned char i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(short i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned short i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(int i)
- {
- u.asBits.tag = Int32Tag;
- u.asBits.payload = i;
- }
-
- inline JSValue::JSValue(unsigned i)
- {
- if (static_cast<int32_t>(i) < 0) {
- *this = JSValue(static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(long i)
- {
- if (static_cast<int32_t>(i) != i) {
- *this = JSValue(static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned long i)
- {
- if (static_cast<uint32_t>(i) != i) {
- *this = JSValue(static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<uint32_t>(i));
- }
-
- inline JSValue::JSValue(long long i)
- {
- if (static_cast<int32_t>(i) != i) {
- *this = JSValue(static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned long long i)
- {
- if (static_cast<uint32_t>(i) != i) {
- *this = JSValue(static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<uint32_t>(i));
- }
-
- inline bool JSValue::isNumber() const
- {
- return isInt32() || isDouble();
- }
-
- inline bool JSValue::isBoolean() const
- {
- return isTrue() || isFalse();
- }
-
- inline bool JSValue::getBoolean(bool& v) const
- {
- if (isTrue()) {
- v = true;
- return true;
- }
- if (isFalse()) {
- v = false;
- return true;
- }
-
- return false;
- }
-
- inline bool JSValue::getBoolean() const
- {
- ASSERT(isBoolean());
- return tag() == TrueTag;
- }
-
- inline double JSValue::uncheckedGetNumber() const
- {
- ASSERT(isNumber());
- return isInt32() ? asInt32() : asDouble();
- }
-
- ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
- {
- return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
- }
-
- inline bool JSValue::getNumber(double& result) const
- {
- if (isInt32()) {
- result = asInt32();
- return true;
- }
- if (isDouble()) {
- result = asDouble();
- return true;
- }
- return false;
- }
-
-#else // USE(JSVALUE32_64)
-
- // JSValue member functions.
- inline EncodedJSValue JSValue::encode(JSValue value)
- {
- return reinterpret_cast<EncodedJSValue>(value.m_ptr);
- }
-
- inline JSValue JSValue::decode(EncodedJSValue ptr)
- {
- return JSValue(reinterpret_cast<JSCell*>(ptr));
- }
-
- inline JSValue JSValue::makeImmediate(intptr_t value)
- {
- return JSValue(reinterpret_cast<JSCell*>(value));
- }
-
- inline intptr_t JSValue::immediateValue()
- {
- return reinterpret_cast<intptr_t>(m_ptr);
- }
-
- // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
- inline JSValue::JSValue()
- : m_ptr(0)
- {
- }
-
- // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
- inline JSValue::JSValue(HashTableDeletedValueTag)
- : m_ptr(reinterpret_cast<JSCell*>(0x4))
- {
- }
-
- inline JSValue::JSValue(JSCell* ptr)
- : m_ptr(ptr)
- {
-#if ENABLE(JSC_ZOMBIES)
- ASSERT(!isZombie());
-#endif
- }
-
- inline JSValue::JSValue(const JSCell* ptr)
- : m_ptr(const_cast<JSCell*>(ptr))
- {
-#if ENABLE(JSC_ZOMBIES)
- ASSERT(!isZombie());
-#endif
- }
-
- inline JSValue::operator bool() const
- {
- return m_ptr;
- }
-
- inline bool JSValue::operator==(const JSValue& other) const
- {
- return m_ptr == other.m_ptr;
- }
-
- inline bool JSValue::operator!=(const JSValue& other) const
- {
- return m_ptr != other.m_ptr;
- }
-
- inline bool JSValue::isUndefined() const
- {
- return asValue() == jsUndefined();
- }
-
- inline bool JSValue::isNull() const
- {
- return asValue() == jsNull();
- }
-#endif // USE(JSVALUE32_64)
+ bool isZombie(const JSCell*);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
new file mode 100644
index 0000000..b4f6f80
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2011 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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 JSValueInlineMethods_h
+#define JSValueInlineMethods_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+ ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
+ {
+ if (isInt32())
+ return asInt32();
+ return JSC::toInt32(toNumber(exec));
+ }
+
+ inline uint32_t JSValue::toUInt32(ExecState* exec) const
+ {
+ // See comment on JSC::toUInt32, above.
+ return toInt32(exec);
+ }
+
+ inline bool JSValue::isUInt32() const
+ {
+ return isInt32() && asInt32() >= 0;
+ }
+
+ inline uint32_t JSValue::asUInt32() const
+ {
+ ASSERT(isUInt32());
+ return asInt32();
+ }
+
+ inline double JSValue::uncheckedGetNumber() const
+ {
+ ASSERT(isNumber());
+ return isInt32() ? asInt32() : asDouble();
+ }
+
+ ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
+ {
+ return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
+ }
+
+ inline JSValue jsNaN()
+ {
+ return JSValue(nonInlineNaN());
+ }
+
+ inline bool JSValue::getNumber(double& result) const
+ {
+ if (isInt32()) {
+ result = asInt32();
+ return true;
+ }
+ if (isDouble()) {
+ result = asDouble();
+ return true;
+ }
+ return false;
+ }
+
+ inline bool JSValue::getBoolean(bool& v) const
+ {
+ if (isTrue()) {
+ v = true;
+ return true;
+ }
+ if (isFalse()) {
+ v = false;
+ return true;
+ }
+
+ return false;
+ }
+
+ inline JSValue::JSValue(char i)
+ {
+ *this = JSValue(static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(unsigned char i)
+ {
+ *this = JSValue(static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(short i)
+ {
+ *this = JSValue(static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(unsigned short i)
+ {
+ *this = JSValue(static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(unsigned i)
+ {
+ if (static_cast<int32_t>(i) < 0) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(long i)
+ {
+ if (static_cast<int32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(unsigned long i)
+ {
+ if (static_cast<uint32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<uint32_t>(i));
+ }
+
+ inline JSValue::JSValue(long long i)
+ {
+ if (static_cast<int32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(unsigned long long i)
+ {
+ if (static_cast<uint32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<uint32_t>(i));
+ }
+
+ inline JSValue::JSValue(double d)
+ {
+ const int32_t asInt32 = static_cast<int32_t>(d);
+ if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
+ *this = JSValue(EncodeAsDouble, d);
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(d));
+ }
+
+#if USE(JSVALUE32_64)
+ inline EncodedJSValue JSValue::encode(JSValue value)
+ {
+ return value.u.asInt64;
+ }
+
+ inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
+ {
+ JSValue v;
+ v.u.asInt64 = encodedJSValue;
+ return v;
+ }
+
+ inline JSValue::JSValue()
+ {
+ u.asBits.tag = EmptyValueTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSNullTag)
+ {
+ u.asBits.tag = NullTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSUndefinedTag)
+ {
+ u.asBits.tag = UndefinedTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSTrueTag)
+ {
+ u.asBits.tag = BooleanTag;
+ u.asBits.payload = 1;
+ }
+
+ inline JSValue::JSValue(JSFalseTag)
+ {
+ u.asBits.tag = BooleanTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(HashTableDeletedValueTag)
+ {
+ u.asBits.tag = DeletedValueTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSCell* ptr)
+ {
+ if (ptr)
+ u.asBits.tag = CellTag;
+ else
+ u.asBits.tag = EmptyValueTag;
+ u.asBits.payload = reinterpret_cast<int32_t>(ptr);
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!isZombie());
+#endif
+ }
+
+ inline JSValue::JSValue(const JSCell* ptr)
+ {
+ if (ptr)
+ u.asBits.tag = CellTag;
+ else
+ u.asBits.tag = EmptyValueTag;
+ u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!isZombie());
+#endif
+ }
+
+ inline JSValue::operator bool() const
+ {
+ ASSERT(tag() != DeletedValueTag);
+ return tag() != EmptyValueTag;
+ }
+
+ inline bool JSValue::operator==(const JSValue& other) const
+ {
+ return u.asInt64 == other.u.asInt64;
+ }
+
+ inline bool JSValue::operator!=(const JSValue& other) const
+ {
+ return u.asInt64 != other.u.asInt64;
+ }
+
+ inline bool JSValue::isUndefined() const
+ {
+ return tag() == UndefinedTag;
+ }
+
+ inline bool JSValue::isNull() const
+ {
+ return tag() == NullTag;
+ }
+
+ inline bool JSValue::isUndefinedOrNull() const
+ {
+ return isUndefined() || isNull();
+ }
+
+ inline bool JSValue::isCell() const
+ {
+ return tag() == CellTag;
+ }
+
+ inline bool JSValue::isInt32() const
+ {
+ return tag() == Int32Tag;
+ }
+
+ inline bool JSValue::isDouble() const
+ {
+ return tag() < LowestTag;
+ }
+
+ inline bool JSValue::isTrue() const
+ {
+ return tag() == BooleanTag && payload();
+ }
+
+ inline bool JSValue::isFalse() const
+ {
+ return tag() == BooleanTag && !payload();
+ }
+
+ inline uint32_t JSValue::tag() const
+ {
+ return u.asBits.tag;
+ }
+
+ inline int32_t JSValue::payload() const
+ {
+ return u.asBits.payload;
+ }
+
+ inline int32_t JSValue::asInt32() const
+ {
+ ASSERT(isInt32());
+ return u.asBits.payload;
+ }
+
+ inline double JSValue::asDouble() const
+ {
+ ASSERT(isDouble());
+ return u.asDouble;
+ }
+
+ ALWAYS_INLINE JSCell* JSValue::asCell() const
+ {
+ ASSERT(isCell());
+ return reinterpret_cast<JSCell*>(u.asBits.payload);
+ }
+
+ ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
+ {
+ u.asDouble = d;
+ }
+
+ inline JSValue::JSValue(int i)
+ {
+ u.asBits.tag = Int32Tag;
+ u.asBits.payload = i;
+ }
+
+ inline bool JSValue::isNumber() const
+ {
+ return isInt32() || isDouble();
+ }
+
+ inline bool JSValue::isBoolean() const
+ {
+ return isTrue() || isFalse();
+ }
+
+ inline bool JSValue::getBoolean() const
+ {
+ ASSERT(isBoolean());
+ return payload();
+ }
+
+#else // USE(JSVALUE32_64)
+
+ // JSValue member functions.
+ inline EncodedJSValue JSValue::encode(JSValue value)
+ {
+ return value.u.ptr;
+ }
+
+ inline JSValue JSValue::decode(EncodedJSValue ptr)
+ {
+ return JSValue(reinterpret_cast<JSCell*>(ptr));
+ }
+
+ // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
+ inline JSValue::JSValue()
+ {
+ u.asInt64 = ValueEmpty;
+ }
+
+ // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
+ inline JSValue::JSValue(HashTableDeletedValueTag)
+ {
+ u.asInt64 = ValueDeleted;
+ }
+
+ inline JSValue::JSValue(JSCell* ptr)
+ {
+ u.ptr = ptr;
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!isZombie());
+#endif
+ }
+
+ inline JSValue::JSValue(const JSCell* ptr)
+ {
+ u.ptr = const_cast<JSCell*>(ptr);
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!isZombie());
+#endif
+ }
+
+ inline JSValue::operator bool() const
+ {
+ return u.ptr;
+ }
+
+ inline bool JSValue::operator==(const JSValue& other) const
+ {
+ return u.ptr == other.u.ptr;
+ }
+
+ inline bool JSValue::operator!=(const JSValue& other) const
+ {
+ return u.ptr != other.u.ptr;
+ }
+
+ inline bool JSValue::isUndefined() const
+ {
+ return asValue() == jsUndefined();
+ }
+
+ inline bool JSValue::isNull() const
+ {
+ return asValue() == jsNull();
+ }
+
+ inline bool JSValue::isTrue() const
+ {
+ return asValue() == JSValue(JSTrue);
+ }
+
+ inline bool JSValue::isFalse() const
+ {
+ return asValue() == JSValue(JSFalse);
+ }
+
+ inline bool JSValue::getBoolean() const
+ {
+ ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false));
+ return asValue() == jsBoolean(true);
+ }
+
+ inline int32_t JSValue::asInt32() const
+ {
+ ASSERT(isInt32());
+ return static_cast<int32_t>(u.asInt64);
+ }
+
+ inline bool JSValue::isDouble() const
+ {
+ return isNumber() && !isInt32();
+ }
+
+ inline JSValue::JSValue(JSNullTag)
+ {
+ u.asInt64 = ValueNull;
+ }
+
+ inline JSValue::JSValue(JSUndefinedTag)
+ {
+ u.asInt64 = ValueUndefined;
+ }
+
+ inline JSValue::JSValue(JSTrueTag)
+ {
+ u.asInt64 = ValueTrue;
+ }
+
+ inline JSValue::JSValue(JSFalseTag)
+ {
+ u.asInt64 = ValueFalse;
+ }
+
+ inline bool JSValue::isUndefinedOrNull() const
+ {
+ // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
+ return (u.asInt64 & ~TagBitUndefined) == ValueNull;
+ }
+
+ inline bool JSValue::isBoolean() const
+ {
+ return (u.asInt64 & ~1) == ValueFalse;
+ }
+
+ inline bool JSValue::isCell() const
+ {
+ return !(u.asInt64 & TagMask);
+ }
+
+ inline bool JSValue::isInt32() const
+ {
+ return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
+ }
+
+ inline intptr_t reinterpretDoubleToIntptr(double value)
+ {
+ return bitwise_cast<intptr_t>(value);
+ }
+ inline double reinterpretIntptrToDouble(intptr_t value)
+ {
+ return bitwise_cast<double>(value);
+ }
+
+ ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
+ {
+ u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset;
+ }
+
+ inline JSValue::JSValue(int i)
+ {
+ u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
+ }
+
+ inline double JSValue::asDouble() const
+ {
+ return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
+ }
+
+ inline bool JSValue::isNumber() const
+ {
+ return u.asInt64 & TagTypeNumber;
+ }
+
+ ALWAYS_INLINE JSCell* JSValue::asCell() const
+ {
+ ASSERT(isCell());
+ return u.ptr;
+ }
+
+#endif // USE(JSVALUE64)
+
+} // namespace JSC
+
+#endif // JSValueInlineMethods_h
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
index 81d05ba..abe9bbb 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -62,7 +62,7 @@ bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDe
{
SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
if (!entry.isNull()) {
- descriptor.setDescriptor(registerAt(entry.getIndex()).jsValue(), entry.getAttributes() | DontDelete);
+ descriptor.setDescriptor(registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete);
return true;
}
return false;
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h
index 96a0ec4..89bb6b0 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -40,11 +40,11 @@ namespace JSC {
class Register;
- class JSVariableObject : public JSObject {
+ class JSVariableObject : public JSNonFinalObject {
friend class JIT;
public:
- SymbolTable& symbolTable() const { return *d->symbolTable; }
+ SymbolTable& symbolTable() const { return *m_symbolTable; }
virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
@@ -54,58 +54,46 @@ namespace JSC {
virtual bool isVariableObject() const;
virtual bool isDynamicScope(bool& requiresDynamicChecks) const = 0;
- Register& registerAt(int index) const { return d->registers[index]; }
+ WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
+
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags;
- // Subclasses of JSVariableObject can subclass this struct to add data
- // without increasing their own size (since there's a hard limit on the
- // size of a JSCell).
- struct JSVariableObjectData {
- JSVariableObjectData(SymbolTable* symbolTable, Register* registers)
- : symbolTable(symbolTable)
- , registers(registers)
- {
- ASSERT(symbolTable);
- }
-
- SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
- Register* registers; // "r" in the register file.
- OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
-
- private:
- JSVariableObjectData(const JSVariableObjectData&);
- JSVariableObjectData& operator=(const JSVariableObjectData&);
- };
-
- JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data)
- : JSObject(structure)
- , d(data) // Subclass owns this pointer.
+
+ JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
+ : JSNonFinalObject(globalData, structure)
+ , m_symbolTable(symbolTable)
+ , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers))
{
+ ASSERT(m_symbolTable);
+ COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier);
}
- PassOwnArrayPtr<Register> copyRegisterArray(Register* src, size_t count);
- void setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray);
+ PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts);
+ void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
bool symbolTableGet(const Identifier&, PropertySlot&);
bool symbolTableGet(const Identifier&, PropertyDescriptor&);
bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
- bool symbolTablePut(const Identifier&, JSValue);
- bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
+ bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue);
+ bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
- JSVariableObjectData* d;
+ SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file.
+ WriteBarrier<Unknown>* m_registers; // "r" in the register file.
+ OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
};
inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
{
SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
if (!entry.isNull()) {
- slot.setRegisterSlot(&registerAt(entry.getIndex()));
+ slot.setValue(registerAt(entry.getIndex()).get());
return true;
}
return false;
@@ -115,14 +103,14 @@ namespace JSC {
{
SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
if (!entry.isNull()) {
- slot.setRegisterSlot(&registerAt(entry.getIndex()));
+ slot.setValue(registerAt(entry.getIndex()).get());
slotIsWriteable = !entry.isReadOnly();
return true;
}
return false;
}
- inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue value)
+ inline bool JSVariableObject::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
@@ -131,11 +119,11 @@ namespace JSC {
return false;
if (entry.isReadOnly())
return true;
- registerAt(entry.getIndex()) = value;
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
- inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue value, unsigned attributes)
+ inline bool JSVariableObject::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
@@ -145,23 +133,26 @@ namespace JSC {
SymbolTableEntry& entry = iter->second;
ASSERT(!entry.isNull());
entry.setAttributes(attributes);
- registerAt(entry.getIndex()) = value;
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
- inline PassOwnArrayPtr<Register> JSVariableObject::copyRegisterArray(Register* src, size_t count)
+ inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts)
{
- OwnArrayPtr<Register> registerArray = adoptArrayPtr(new Register[count]);
- memcpy(registerArray.get(), src, count * sizeof(Register));
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[count]);
+ for (size_t i = 0; i < callframeStarts; i++)
+ registerArray[i].set(globalData, this, src[i].get());
+ for (size_t i = callframeStarts + RegisterFile::CallFrameHeaderSize; i < count; i++)
+ registerArray[i].set(globalData, this, src[i].get());
return registerArray.release();
}
- inline void JSVariableObject::setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray)
+ inline void JSVariableObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray)
{
- ASSERT(registerArray != d->registerArray);
- d->registerArray = registerArray;
- d->registers = registers;
+ ASSERT(registerArray != m_registerArray);
+ m_registerArray = registerArray;
+ m_registers = registers;
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h
index 0b0d3fd..a7dbe0d 100644
--- a/Source/JavaScriptCore/runtime/JSWrapperObject.h
+++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h
@@ -28,21 +28,21 @@ namespace JSC {
// This class is used as a base for classes such as String,
// Number, Boolean and Date which are wrappers for primitive types.
- class JSWrapperObject : public JSObject {
+ class JSWrapperObject : public JSNonFinalObject {
protected:
- explicit JSWrapperObject(JSGlobalData&, NonNullPassRefPtr<Structure>);
+ explicit JSWrapperObject(JSGlobalData&, Structure*);
public:
- JSValue internalValue() const { return m_internalValue.get(); }
+ JSValue internalValue() const;
void setInternalValue(JSGlobalData&, JSValue);
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
- static const unsigned AnonymousSlotCount = 1 + JSObject::AnonymousSlotCount;
+ static const unsigned StructureFlags = OverridesMarkChildren | JSNonFinalObject::StructureFlags;
private:
virtual void markChildren(MarkStack&);
@@ -50,10 +50,14 @@ namespace JSC {
WriteBarrier<Unknown> m_internalValue;
};
- inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+ inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, Structure* structure)
+ : JSNonFinalObject(globalData, structure)
{
- putAnonymousValue(globalData, 0, jsNull());
+ }
+
+ inline JSValue JSWrapperObject::internalValue() const
+ {
+ return m_internalValue.get();
}
inline void JSWrapperObject::setInternalValue(JSGlobalData& globalData, JSValue value)
@@ -61,7 +65,6 @@ namespace JSC {
ASSERT(value);
ASSERT(!value.isObject());
m_internalValue.set(globalData, this, value);
- putAnonymousValue(globalData, 0, value);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSZombie.cpp b/Source/JavaScriptCore/runtime/JSZombie.cpp
index 8a36bda..efabc93 100644
--- a/Source/JavaScriptCore/runtime/JSZombie.cpp
+++ b/Source/JavaScriptCore/runtime/JSZombie.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "JSZombie.h"
#include "ClassInfo.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
#if ENABLE(JSC_ZOMBIES)
@@ -33,16 +35,6 @@ namespace JSC {
const ClassInfo JSZombie::s_info = { "Zombie", 0, 0, 0 };
-Structure* JSZombie::leakedZombieStructure() {
- static Structure* structure = 0;
- if (!structure) {
- Structure::startIgnoringLeaks();
- structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0).leakRef();
- Structure::stopIgnoringLeaks();
- }
- return structure;
-}
-
}
#endif // ENABLE(JSC_ZOMBIES)
diff --git a/Source/JavaScriptCore/runtime/JSZombie.h b/Source/JavaScriptCore/runtime/JSZombie.h
index da45699..0559b96 100644
--- a/Source/JavaScriptCore/runtime/JSZombie.h
+++ b/Source/JavaScriptCore/runtime/JSZombie.h
@@ -27,20 +27,21 @@
#define JSZombie_h
#include "JSCell.h"
+#include "Structure.h"
#if ENABLE(JSC_ZOMBIES)
namespace JSC {
class JSZombie : public JSCell {
public:
- JSZombie(const ClassInfo* oldInfo, Structure* structure)
- : JSCell(structure)
+ JSZombie(JSGlobalData& globalData, const ClassInfo* oldInfo, Structure* structure)
+ : JSCell(globalData, structure)
, m_oldInfo(oldInfo)
{
+ ASSERT(inherits(&s_info));
}
+
virtual bool isZombie() const { return true; }
- virtual const ClassInfo* classInfo() const { return &s_info; }
- static Structure* leakedZombieStructure();
virtual bool isGetterSetter() const { ASSERT_NOT_REACHED(); return false; }
virtual bool isAPIValueWrapper() const { ASSERT_NOT_REACHED(); return false; }
@@ -65,7 +66,13 @@ public:
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(LeafType, 0), AnonymousSlotCount, &s_info);
+ }
+
static const ClassInfo s_info;
+
private:
const ClassInfo* m_oldInfo;
};
diff --git a/Source/JavaScriptCore/runtime/Lookup.cpp b/Source/JavaScriptCore/runtime/Lookup.cpp
index 3c7d4be..25b516e 100644
--- a/Source/JavaScriptCore/runtime/Lookup.cpp
+++ b/Source/JavaScriptCore/runtime/Lookup.cpp
@@ -22,7 +22,6 @@
#include "Executable.h"
#include "JSFunction.h"
-#include "PrototypeFunction.h"
namespace JSC {
@@ -74,20 +73,20 @@ void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject*
ASSERT(thisObj->structure()->anonymousSlotCount() > 0);
ASSERT(thisObj->getAnonymousValue(0).isCell() && asObject(thisObj->getAnonymousValue(0).asCell())->isGlobalObject());
ASSERT(entry->attributes() & Function);
- WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(propertyName);
+ WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName);
if (!location) {
- NativeFunctionWrapper* function;
+ JSFunction* function;
JSGlobalObject* globalObject = asGlobalObject(thisObj->getAnonymousValue(0).asCell());
#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
if (entry->generator())
- function = new (exec) NativeFunctionWrapper(exec, globalObject, globalObject->prototypeFunctionStructure(), entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator()));
+ function = new (exec) JSFunction(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator()));
else
#endif
- function = new (exec) NativeFunctionWrapper(exec, globalObject, globalObject->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function());
+ function = new (exec) JSFunction(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, entry->function());
thisObj->putDirectFunction(exec->globalData(), propertyName, function, entry->attributes());
- location = thisObj->getDirectLocation(propertyName);
+ location = thisObj->getDirectLocation(exec->globalData(), propertyName);
}
slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location));
diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
deleted file mode 100644
index 4430947..0000000
--- a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * 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 "MachineStackMarker.h"
-
-#include "ConservativeSet.h"
-#include "Heap.h"
-#include "JSArray.h"
-#include "JSGlobalData.h"
-#include <setjmp.h>
-#include <stdlib.h>
-
-#if OS(DARWIN)
-
-#include <mach/mach_init.h>
-#include <mach/mach_port.h>
-#include <mach/task.h>
-#include <mach/thread_act.h>
-#include <mach/vm_map.h>
-
-#elif OS(WINDOWS)
-
-#include <windows.h>
-#include <malloc.h>
-
-#elif OS(HAIKU)
-
-#include <OS.h>
-
-#elif OS(UNIX)
-
-#include <stdlib.h>
-#if !OS(HAIKU)
-#include <sys/mman.h>
-#endif
-#include <unistd.h>
-
-#if OS(SOLARIS)
-#include <thread.h>
-#else
-#include <pthread.h>
-#endif
-
-#if HAVE(PTHREAD_NP_H)
-#include <pthread_np.h>
-#endif
-
-#if OS(QNX)
-#include <fcntl.h>
-#include <sys/procfs.h>
-#include <stdio.h>
-#include <errno.h>
-#endif
-
-#endif
-
-namespace JSC {
-
-static inline void swapIfBackwards(void*& begin, void*& end)
-{
-#if OS(WINCE)
- if (begin <= end)
- return;
- std::swap(begin, end);
-#else
-UNUSED_PARAM(begin);
-UNUSED_PARAM(end);
-#endif
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-#if OS(DARWIN)
-typedef mach_port_t PlatformThread;
-#elif OS(WINDOWS)
-typedef HANDLE PlatformThread;
-#endif
-
-class MachineStackMarker::Thread {
-public:
- Thread(pthread_t pthread, const PlatformThread& platThread, void* base)
- : posixThread(pthread)
- , platformThread(platThread)
- , stackBase(base)
- {
- }
-
- Thread* next;
- pthread_t posixThread;
- PlatformThread platformThread;
- void* stackBase;
-};
-
-#endif
-
-MachineStackMarker::MachineStackMarker(Heap* heap)
- : m_heap(heap)
-#if ENABLE(JSC_MULTIPLE_THREADS)
- , m_registeredThreads(0)
- , m_currentThreadRegistrar(0)
-#endif
-{
-}
-
-MachineStackMarker::~MachineStackMarker()
-{
-#if ENABLE(JSC_MULTIPLE_THREADS)
- if (m_currentThreadRegistrar) {
- int error = pthread_key_delete(m_currentThreadRegistrar);
- ASSERT_UNUSED(error, !error);
- }
-
- MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
- for (Thread* t = m_registeredThreads; t;) {
- Thread* next = t->next;
- delete t;
- t = next;
- }
-#endif
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline PlatformThread getCurrentPlatformThread()
-{
-#if OS(DARWIN)
- return pthread_mach_thread_np(pthread_self());
-#elif OS(WINDOWS)
- return pthread_getw32threadhandle_np(pthread_self());
-#endif
-}
-
-void MachineStackMarker::makeUsableFromMultipleThreads()
-{
- if (m_currentThreadRegistrar)
- return;
-
- int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);
- if (error)
- CRASH();
-}
-
-void MachineStackMarker::registerThread()
-{
- ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread());
-
- if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
- return;
-
- pthread_setspecific(m_currentThreadRegistrar, this);
- Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin());
-
- MutexLocker lock(m_registeredThreadsMutex);
-
- thread->next = m_registeredThreads;
- m_registeredThreads = thread;
-}
-
-void MachineStackMarker::unregisterThread(void* p)
-{
- if (p)
- static_cast<MachineStackMarker*>(p)->unregisterThread();
-}
-
-void MachineStackMarker::unregisterThread()
-{
- pthread_t currentPosixThread = pthread_self();
-
- MutexLocker lock(m_registeredThreadsMutex);
-
- if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
- Thread* t = m_registeredThreads;
- m_registeredThreads = m_registeredThreads->next;
- delete t;
- } else {
- Thread* last = m_registeredThreads;
- Thread* t;
- for (t = m_registeredThreads->next; t; t = t->next) {
- if (pthread_equal(t->posixThread, currentPosixThread)) {
- last->next = t->next;
- break;
- }
- last = t;
- }
- ASSERT(t); // If t is NULL, we never found ourselves in the list.
- delete t;
- }
-}
-
-#endif
-
-void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(ConservativeSet& conservativeSet)
-{
- void* begin = m_heap->globalData()->stack().current();
- void* end = m_heap->globalData()->stack().origin();
- swapIfBackwards(begin, end);
- conservativeSet.add(begin, end);
-}
-
-#if COMPILER(GCC)
-#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
-#else
-#define REGISTER_BUFFER_ALIGNMENT
-#endif
-
-void MachineStackMarker::markCurrentThreadConservatively(ConservativeSet& conservativeSet)
-{
- // setjmp forces volatile registers onto the stack
- jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4611)
-#endif
- setjmp(registers);
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
- markCurrentThreadConservativelyInternal(conservativeSet);
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline void suspendThread(const PlatformThread& platformThread)
-{
-#if OS(DARWIN)
- thread_suspend(platformThread);
-#elif OS(WINDOWS)
- SuspendThread(platformThread);
-#else
-#error Need a way to suspend threads on this platform
-#endif
-}
-
-static inline void resumeThread(const PlatformThread& platformThread)
-{
-#if OS(DARWIN)
- thread_resume(platformThread);
-#elif OS(WINDOWS)
- ResumeThread(platformThread);
-#else
-#error Need a way to resume threads on this platform
-#endif
-}
-
-typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
-
-#if OS(DARWIN)
-
-#if CPU(X86)
-typedef i386_thread_state_t PlatformThreadRegisters;
-#elif CPU(X86_64)
-typedef x86_thread_state64_t PlatformThreadRegisters;
-#elif CPU(PPC)
-typedef ppc_thread_state_t PlatformThreadRegisters;
-#elif CPU(PPC64)
-typedef ppc_thread_state64_t PlatformThreadRegisters;
-#elif CPU(ARM)
-typedef arm_thread_state_t PlatformThreadRegisters;
-#else
-#error Unknown Architecture
-#endif
-
-#elif OS(WINDOWS) && CPU(X86)
-typedef CONTEXT PlatformThreadRegisters;
-#else
-#error Need a thread register struct for this platform
-#endif
-
-static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
-{
-#if OS(DARWIN)
-
-#if CPU(X86)
- unsigned user_count = sizeof(regs)/sizeof(int);
- thread_state_flavor_t flavor = i386_THREAD_STATE;
-#elif CPU(X86_64)
- unsigned user_count = x86_THREAD_STATE64_COUNT;
- thread_state_flavor_t flavor = x86_THREAD_STATE64;
-#elif CPU(PPC)
- unsigned user_count = PPC_THREAD_STATE_COUNT;
- thread_state_flavor_t flavor = PPC_THREAD_STATE;
-#elif CPU(PPC64)
- unsigned user_count = PPC_THREAD_STATE64_COUNT;
- thread_state_flavor_t flavor = PPC_THREAD_STATE64;
-#elif CPU(ARM)
- unsigned user_count = ARM_THREAD_STATE_COUNT;
- thread_state_flavor_t flavor = ARM_THREAD_STATE;
-#else
-#error Unknown Architecture
-#endif
-
- kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
- if (result != KERN_SUCCESS) {
- WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
- "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
- CRASH();
- }
- return user_count * sizeof(usword_t);
-// end OS(DARWIN)
-
-#elif OS(WINDOWS) && CPU(X86)
- regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
- GetThreadContext(platformThread, &regs);
- return sizeof(CONTEXT);
-#else
-#error Need a way to get thread registers on this platform
-#endif
-}
-
-static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
-{
-#if OS(DARWIN)
-
-#if __DARWIN_UNIX03
-
-#if CPU(X86)
- return reinterpret_cast<void*>(regs.__esp);
-#elif CPU(X86_64)
- return reinterpret_cast<void*>(regs.__rsp);
-#elif CPU(PPC) || CPU(PPC64)
- return reinterpret_cast<void*>(regs.__r1);
-#elif CPU(ARM)
- return reinterpret_cast<void*>(regs.__sp);
-#else
-#error Unknown Architecture
-#endif
-
-#else // !__DARWIN_UNIX03
-
-#if CPU(X86)
- return reinterpret_cast<void*>(regs.esp);
-#elif CPU(X86_64)
- return reinterpret_cast<void*>(regs.rsp);
-#elif CPU(PPC) || CPU(PPC64)
- return reinterpret_cast<void*>(regs.r1);
-#else
-#error Unknown Architecture
-#endif
-
-#endif // __DARWIN_UNIX03
-
-// end OS(DARWIN)
-#elif CPU(X86) && OS(WINDOWS)
- return reinterpret_cast<void*>((uintptr_t) regs.Esp);
-#else
-#error Need a way to get the stack pointer for another thread on this platform
-#endif
-}
-
-void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conservativeSet, Thread* thread)
-{
- suspendThread(thread->platformThread);
-
- PlatformThreadRegisters regs;
- size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
-
- // mark the thread's registers
- conservativeSet.add(static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
-
- void* stackPointer = otherThreadStackPointer(regs);
- void* stackBase = thread->stackBase;
- swapIfBackwards(stackPointer, stackBase);
- conservativeSet.add(stackPointer, stackBase);
-
- resumeThread(thread->platformThread);
-}
-
-#endif
-
-void MachineStackMarker::markMachineStackConservatively(ConservativeSet& conservativeSet)
-{
- markCurrentThreadConservatively(conservativeSet);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
- if (m_currentThreadRegistrar) {
-
- MutexLocker lock(m_registeredThreadsMutex);
-
-#ifndef NDEBUG
- // Forbid malloc during the mark phase. Marking a thread suspends it, so
- // a malloc inside markChildren() would risk a deadlock with a thread that had been
- // suspended while holding the malloc lock.
- fastMallocForbid();
-#endif
- // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
- // 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(conservativeSet, thread);
- }
-#ifndef NDEBUG
- fastMallocAllow();
-#endif
- }
-#endif
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.h b/Source/JavaScriptCore/runtime/MachineStackMarker.h
deleted file mode 100644
index 8afdb46..0000000
--- a/Source/JavaScriptCore/runtime/MachineStackMarker.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 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 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 MachineStackMarker_h
-#define MachineStackMarker_h
-
-#include <wtf/Noncopyable.h>
-#include <wtf/ThreadingPrimitives.h>
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
-
-namespace JSC {
-
- class Heap;
- class ConservativeSet;
-
- class MachineStackMarker {
- WTF_MAKE_NONCOPYABLE(MachineStackMarker);
- public:
- MachineStackMarker(Heap*);
- ~MachineStackMarker();
-
- void markMachineStackConservatively(ConservativeSet&);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
- void makeUsableFromMultipleThreads();
- void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
-#endif
-
- private:
- void markCurrentThreadConservatively(ConservativeSet&);
- void markCurrentThreadConservativelyInternal(ConservativeSet&);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
- class Thread;
-
- static void unregisterThread(void*);
-
- void unregisterThread();
- void markOtherThreadConservatively(ConservativeSet&, Thread*);
-#endif
-
- Heap* m_heap;
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
- Mutex m_registeredThreadsMutex;
- Thread* m_registeredThreads;
- pthread_key_t m_currentThreadRegistrar;
-#endif
- };
-
-} // namespace JSC
-
-#endif // MachineStackMarker_h
diff --git a/Source/JavaScriptCore/runtime/MarkStack.cpp b/Source/JavaScriptCore/runtime/MarkStack.cpp
deleted file mode 100644
index a350c35..0000000
--- a/Source/JavaScriptCore/runtime/MarkStack.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
- * 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.
- */
-
-#include "config.h"
-#include "MarkStack.h"
-
-namespace JSC {
-
-size_t MarkStack::s_pageSize = 0;
-
-void MarkStack::compact()
-{
- ASSERT(s_pageSize);
- m_values.shrinkAllocation(s_pageSize);
- m_markSets.shrinkAllocation(s_pageSize);
-}
-
-}
diff --git a/Source/JavaScriptCore/runtime/MarkStack.h b/Source/JavaScriptCore/runtime/MarkStack.h
deleted file mode 100644
index 0b7941e..0000000
--- a/Source/JavaScriptCore/runtime/MarkStack.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
- * 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 MarkStack_h
-#define MarkStack_h
-
-#include "JSValue.h"
-#include "WriteBarrier.h"
-#include <wtf/Vector.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OSAllocator.h>
-
-namespace JSC {
-
- class JSGlobalData;
- class Register;
-
- enum MarkSetProperties { MayContainNullValues, NoNullValues };
-
- class MarkStack {
- WTF_MAKE_NONCOPYABLE(MarkStack);
- public:
- MarkStack(void* jsArrayVPtr)
- : m_jsArrayVPtr(jsArrayVPtr)
-#if !ASSERT_DISABLED
- , m_isCheckingForDefaultMarkViolation(false)
- , m_isDraining(false)
-#endif
- {
- }
-
- void deprecatedAppend(JSValue*);
- void deprecatedAppend(JSCell**);
- void deprecatedAppend(Register*);
- template <typename T> void append(WriteBarrierBase<T>*);
- template <typename T> void append(DeprecatedPtr<T>*);
-
- ALWAYS_INLINE void deprecatedAppendValues(Register* registers, size_t count, MarkSetProperties properties = NoNullValues)
- {
- JSValue* values = reinterpret_cast<JSValue*>(registers);
- if (count)
- m_markSets.append(MarkSet(values, values + count, properties));
- }
-
- void appendValues(WriteBarrierBase<Unknown>* barriers, size_t count, MarkSetProperties properties = NoNullValues)
- {
- JSValue* values = barriers->slot();
- if (count)
- m_markSets.append(MarkSet(values, values + count, properties));
- }
-
- inline void drain();
- void compact();
-
- ~MarkStack()
- {
- ASSERT(m_markSets.isEmpty());
- ASSERT(m_values.isEmpty());
- }
-
- private:
- void internalAppend(JSCell*);
- void internalAppend(JSValue);
- void markChildren(JSCell*);
-
- struct MarkSet {
- MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties)
- : m_values(values)
- , m_end(end)
- , m_properties(properties)
- {
- ASSERT(values);
- }
- JSValue* m_values;
- JSValue* m_end;
- MarkSetProperties m_properties;
- };
-
- static void* allocateStack(size_t size) { return OSAllocator::reserveAndCommit(size); }
- static void releaseStack(void* addr, size_t size) { OSAllocator::decommitAndRelease(addr, size); }
-
- static void initializePagesize();
- static size_t pageSize()
- {
- if (!s_pageSize)
- initializePagesize();
- return s_pageSize;
- }
-
- template <typename T> struct MarkStackArray {
- MarkStackArray()
- : m_top(0)
- , m_allocated(MarkStack::pageSize())
- , m_capacity(m_allocated / sizeof(T))
- {
- m_data = reinterpret_cast<T*>(allocateStack(m_allocated));
- }
-
- ~MarkStackArray()
- {
- releaseStack(m_data, m_allocated);
- }
-
- void expand()
- {
- size_t oldAllocation = m_allocated;
- m_allocated *= 2;
- m_capacity = m_allocated / sizeof(T);
- void* newData = allocateStack(m_allocated);
- memcpy(newData, m_data, oldAllocation);
- releaseStack(m_data, oldAllocation);
- m_data = reinterpret_cast<T*>(newData);
- }
-
- inline void append(const T& v)
- {
- if (m_top == m_capacity)
- expand();
- m_data[m_top++] = v;
- }
-
- inline T removeLast()
- {
- ASSERT(m_top);
- return m_data[--m_top];
- }
-
- inline T& last()
- {
- ASSERT(m_top);
- return m_data[m_top - 1];
- }
-
- inline bool isEmpty()
- {
- return m_top == 0;
- }
-
- inline size_t size() { return m_top; }
-
- inline void shrinkAllocation(size_t size)
- {
- ASSERT(size <= m_allocated);
- ASSERT(0 == (size % MarkStack::pageSize()));
- if (size == m_allocated)
- return;
-#if OS(WINDOWS) || OS(SYMBIAN) || PLATFORM(BREWMP)
- // We cannot release a part of a region with VirtualFree. To get around this,
- // we'll release the entire region and reallocate the size that we want.
- releaseStack(m_data, m_allocated);
- m_data = reinterpret_cast<T*>(allocateStack(size));
-#else
- releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
-#endif
- m_allocated = size;
- m_capacity = m_allocated / sizeof(T);
- }
-
- private:
- size_t m_top;
- size_t m_allocated;
- size_t m_capacity;
- T* m_data;
- };
-
- void* m_jsArrayVPtr;
- MarkStackArray<MarkSet> m_markSets;
- MarkStackArray<JSCell*> m_values;
- static size_t s_pageSize;
-
-#if !ASSERT_DISABLED
- public:
- bool m_isCheckingForDefaultMarkViolation;
- bool m_isDraining;
-#endif
- };
-
-}
-
-#endif
diff --git a/Source/JavaScriptCore/runtime/MarkStackPosix.cpp b/Source/JavaScriptCore/runtime/MarkStackPosix.cpp
deleted file mode 100644
index 2a5b298..0000000
--- a/Source/JavaScriptCore/runtime/MarkStackPosix.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
- * 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.
- */
-
-#include "config.h"
-#include "MarkStack.h"
-
-#if OS(UNIX) && !OS(SYMBIAN)
-
-#include <unistd.h>
-#include <sys/mman.h>
-
-namespace JSC {
-
-void MarkStack::initializePagesize()
-{
- MarkStack::s_pageSize = getpagesize();
-}
-
-}
-
-#endif
diff --git a/Source/JavaScriptCore/runtime/MarkStackSymbian.cpp b/Source/JavaScriptCore/runtime/MarkStackSymbian.cpp
deleted file mode 100644
index a3893d7..0000000
--- a/Source/JavaScriptCore/runtime/MarkStackSymbian.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include "config.h"
-#include "MarkStack.h"
-
-#if OS(SYMBIAN)
-
-#include <e32hal.h>
-
-namespace JSC {
-
-void MarkStack::initializePagesize()
-{
- TInt page_size;
- UserHal::PageSizeInBytes(page_size);
- MarkStack::s_pageSize = page_size;
-}
-
-}
-
-#endif
diff --git a/Source/JavaScriptCore/runtime/MarkStackWin.cpp b/Source/JavaScriptCore/runtime/MarkStackWin.cpp
deleted file mode 100644
index 2d2a1b3..0000000
--- a/Source/JavaScriptCore/runtime/MarkStackWin.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
- * 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.
- */
-
-#include "config.h"
-#include "MarkStack.h"
-
-#if OS(WINDOWS)
-
-#include "windows.h"
-
-namespace JSC {
-
-void MarkStack::initializePagesize()
-{
- SYSTEM_INFO system_info;
- GetSystemInfo(&system_info);
- MarkStack::s_pageSize = system_info.dwPageSize;
-}
-
-}
-
-#endif
diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.cpp b/Source/JavaScriptCore/runtime/MarkedBlock.cpp
deleted file mode 100644
index 16053f2..0000000
--- a/Source/JavaScriptCore/runtime/MarkedBlock.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
- */
-
-#include "config.h"
-#include "MarkedBlock.h"
-
-#include "JSCell.h"
-
-namespace JSC {
-
-MarkedBlock* MarkedBlock::create(JSGlobalData* globalData)
-{
- PageAllocationAligned allocation = PageAllocationAligned::allocate(BLOCK_SIZE, BLOCK_SIZE, OSAllocator::JSGCHeapPages);
- if (!static_cast<bool>(allocation))
- CRASH();
- return new (allocation.base()) MarkedBlock(allocation, globalData);
-}
-
-void MarkedBlock::destroy(MarkedBlock* block)
-{
- for (size_t i = 0; i < CELLS_PER_BLOCK; ++i)
- reinterpret_cast<JSCell*>(&block->cells[i])->~JSCell();
- block->m_allocation.deallocate();
-}
-
-MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData* globalData)
- : m_allocation(allocation)
- , m_heap(&globalData->heap)
-{
- marked.set(CELLS_PER_BLOCK - 1);
-
- Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get();
- for (size_t i = 0; i < CELLS_PER_BLOCK; ++i)
- new (&cells[i]) JSCell(dummyMarkableCellStructure);
-}
-
-void MarkedBlock::sweep()
-{
-#if !ENABLE(JSC_ZOMBIES)
- Structure* dummyMarkableCellStructure = m_heap->globalData()->dummyMarkableCellStructure.get();
-#endif
-
- for (size_t i = 0; i < CELLS_PER_BLOCK; ++i) {
- if (marked.get(i))
- continue;
-
- JSCell* cell = reinterpret_cast<JSCell*>(&cells[i]);
-#if ENABLE(JSC_ZOMBIES)
- if (!cell->isZombie()) {
- const ClassInfo* info = cell->classInfo();
- cell->~JSCell();
- new (cell) JSZombie(info, JSZombie::leakedZombieStructure());
- marked.set(i);
- }
-#else
- cell->~JSCell();
- new (cell) JSCell(dummyMarkableCellStructure);
-#endif
- }
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.h b/Source/JavaScriptCore/runtime/MarkedBlock.h
deleted file mode 100644
index f726c25..0000000
--- a/Source/JavaScriptCore/runtime/MarkedBlock.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 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 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 MarkedBlock_h
-#define MarkedBlock_h
-
-#include <wtf/Bitmap.h>
-#include <wtf/FixedArray.h>
-#include <wtf/PageAllocationAligned.h>
-
-#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedBlock::CELL_SIZE, class_fits_in_cell)
-
-namespace JSC {
-
- class Heap;
- class JSCell;
- class JSGlobalData;
-
- class MarkedBlock {
-#if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP)
- static const size_t BLOCK_SIZE = 64 * 1024; // 64k
-#else
- static const size_t BLOCK_SIZE = 256 * 1024; // 256k
-#endif
-
- static const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
- static const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
- static const size_t MINIMUM_CELL_SIZE = 64;
- static const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
- public:
- // This is still public for now, for use in assertions.
- static const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
- private:
- static const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
- static const size_t CELL_MASK = CELL_SIZE - 1;
- static const size_t CELL_ALIGN_MASK = ~CELL_MASK;
- static const size_t BITS_PER_BLOCK = BLOCK_SIZE / CELL_SIZE;
- static const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*) - sizeof(WTF::Bitmap<BITS_PER_BLOCK>)) / CELL_SIZE; // Division rounds down intentionally.
-
- struct CollectorCell {
- FixedArray<double, CELL_ARRAY_LENGTH> memory;
- };
-
- // Cell size needs to be a power of two for CELL_MASK to be valid.
- COMPILE_ASSERT(!(sizeof(CollectorCell) % 2), Collector_cell_size_is_power_of_two);
-
- public:
- static MarkedBlock* create(JSGlobalData*);
- static void destroy(MarkedBlock*);
-
- static bool isCellAligned(const void*);
- static MarkedBlock* blockFor(const void*);
-
- Heap* heap() const;
-
- void* allocate(size_t& nextCell);
- void sweep();
-
- bool isEmpty();
-
- void clearMarks();
- size_t markCount();
- size_t size();
- size_t capacity();
-
- size_t cellNumber(const void*);
- bool isMarked(const void*);
- bool testAndSetMarked(const void*);
- void setMarked(const void*);
-
- template <typename Functor> void forEach(Functor&);
-
- FixedArray<CollectorCell, CELLS_PER_BLOCK> cells;
-
- private:
- MarkedBlock(const PageAllocationAligned&, JSGlobalData*);
-
- WTF::Bitmap<BITS_PER_BLOCK> marked;
- PageAllocationAligned m_allocation;
- Heap* m_heap;
- };
-
- inline bool MarkedBlock::isCellAligned(const void* p)
- {
- return !((intptr_t)(p) & CELL_MASK);
- }
-
- inline MarkedBlock* MarkedBlock::blockFor(const void* p)
- {
- return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & BLOCK_MASK);
- }
-
- inline Heap* MarkedBlock::heap() const
- {
- return m_heap;
- }
-
- inline bool MarkedBlock::isEmpty()
- {
- marked.clear(CELLS_PER_BLOCK - 1); // Clear the always-set last bit to avoid confusing isEmpty().
- bool result = marked.isEmpty();
- marked.set(CELLS_PER_BLOCK - 1);
- return result;
- }
-
- inline void MarkedBlock::clearMarks()
- {
- // allocate() assumes that the last mark bit is always set.
- marked.clearAll();
- marked.set(CELLS_PER_BLOCK - 1);
- }
-
- inline size_t MarkedBlock::markCount()
- {
- return marked.count() - 1; // The last mark bit is always set.
- }
-
- inline size_t MarkedBlock::size()
- {
- return markCount() * CELL_SIZE;
- }
-
- inline size_t MarkedBlock::capacity()
- {
- return BLOCK_SIZE;
- }
-
- inline size_t MarkedBlock::cellNumber(const void* cell)
- {
- return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
- }
-
- inline bool MarkedBlock::isMarked(const void* cell)
- {
- return marked.get(cellNumber(cell));
- }
-
- inline bool MarkedBlock::testAndSetMarked(const void* cell)
- {
- return marked.testAndSet(cellNumber(cell));
- }
-
- inline void MarkedBlock::setMarked(const void* cell)
- {
- marked.set(cellNumber(cell));
- }
-
- template <typename Functor> inline void MarkedBlock::forEach(Functor& functor)
- {
- for (size_t i = 0; i < CELLS_PER_BLOCK - 1; ++i) { // The last cell is a dummy place-holder.
- if (!marked.get(i))
- continue;
- functor(reinterpret_cast<JSCell*>(&cells[i]));
- }
- }
-
-} // namespace JSC
-
-#endif // MarkedSpace_h
diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp
deleted file mode 100644
index 2f8075d..0000000
--- a/Source/JavaScriptCore/runtime/MarkedSpace.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * 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 "MarkedSpace.h"
-
-#include "JSCell.h"
-#include "JSGlobalData.h"
-#include "JSLock.h"
-
-namespace JSC {
-
-class Structure;
-
-MarkedSpace::MarkedSpace(JSGlobalData* globalData)
- : m_waterMark(0)
- , m_highWaterMark(0)
- , m_globalData(globalData)
-{
- allocateBlock();
-}
-
-void MarkedSpace::destroy()
-{
- clearMarks(); // Make sure weak pointers appear dead during destruction.
-
- while (m_heap.blocks.size())
- freeBlock(0);
- m_heap.blocks.clear();
-}
-
-NEVER_INLINE MarkedBlock* MarkedSpace::allocateBlock()
-{
- MarkedBlock* block = MarkedBlock::create(globalData());
- m_heap.blocks.append(block);
- return block;
-}
-
-NEVER_INLINE void MarkedSpace::freeBlock(size_t block)
-{
- MarkedBlock::destroy(m_heap.blocks[block]);
-
- // swap with the last block so we compact as we go
- m_heap.blocks[block] = m_heap.blocks.last();
- m_heap.blocks.removeLast();
-}
-
-void* MarkedSpace::allocate(size_t)
-{
- do {
- ASSERT(m_heap.nextBlock < m_heap.blocks.size());
- MarkedBlock* block = m_heap.collectorBlock(m_heap.nextBlock);
- if (void* result = block->allocate(m_heap.nextCell))
- return result;
-
- m_waterMark += block->capacity();
- } while (++m_heap.nextBlock != m_heap.blocks.size());
-
- if (m_waterMark < m_highWaterMark)
- return allocateBlock()->allocate(m_heap.nextCell);
-
- return 0;
-}
-
-void MarkedSpace::shrink()
-{
- for (size_t i = 0; i != m_heap.blocks.size() && m_heap.blocks.size() > 1; ) { // We assume at least one block exists at all times.
- if (m_heap.collectorBlock(i)->isEmpty()) {
- freeBlock(i);
- } else
- ++i;
- }
-}
-
-void MarkedSpace::clearMarks()
-{
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- m_heap.collectorBlock(i)->clearMarks();
-}
-
-void MarkedSpace::sweep()
-{
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- m_heap.collectorBlock(i)->sweep();
-}
-
-size_t MarkedSpace::objectCount() const
-{
- size_t result = 0;
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- result += m_heap.collectorBlock(i)->markCount();
- return result;
-}
-
-size_t MarkedSpace::size() const
-{
- size_t result = 0;
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- result += m_heap.collectorBlock(i)->size();
- return result;
-}
-
-size_t MarkedSpace::capacity() const
-{
- size_t result = 0;
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- result += m_heap.collectorBlock(i)->capacity();
- return result;
-}
-
-void MarkedSpace::reset()
-{
- m_heap.nextCell = 0;
- m_heap.nextBlock = 0;
- m_waterMark = 0;
-#if ENABLE(JSC_ZOMBIES)
- sweep();
-#endif
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h
deleted file mode 100644
index fcb93b7..0000000
--- a/Source/JavaScriptCore/runtime/MarkedSpace.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 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 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 MarkedSpace_h
-#define MarkedSpace_h
-
-#include "MachineStackMarker.h"
-#include "MarkedBlock.h"
-#include "PageAllocationAligned.h"
-#include <wtf/Bitmap.h>
-#include <wtf/FixedArray.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/Vector.h>
-
-namespace JSC {
-
- class Heap;
- class JSCell;
- class JSGlobalData;
- class LiveObjectIterator;
- class MarkStack;
- class WeakGCHandle;
-
- struct CollectorHeap {
- CollectorHeap()
- : nextBlock(0)
- , nextCell(0)
- {
- }
-
- MarkedBlock* collectorBlock(size_t index) const
- {
- return blocks[index];
- }
-
- size_t nextBlock;
- size_t nextCell;
- Vector<MarkedBlock*> blocks;
- };
-
- class MarkedSpace {
- WTF_MAKE_NONCOPYABLE(MarkedSpace);
- public:
- static Heap* heap(JSCell*);
-
- static bool isMarked(const JSCell*);
- static bool testAndSetMarked(const JSCell*);
- static void setMarked(const JSCell*);
-
- MarkedSpace(JSGlobalData*);
- void destroy();
-
- JSGlobalData* globalData() { return m_globalData; }
-
- size_t highWaterMark() { return m_highWaterMark; }
- void setHighWaterMark(size_t highWaterMark) { m_highWaterMark = highWaterMark; }
-
- void* allocate(size_t);
-
- void clearMarks();
- void markRoots();
- void reset();
- void sweep();
- void shrink();
-
- size_t size() const;
- size_t capacity() const;
- size_t objectCount() const;
-
- bool contains(const void*);
-
- template<typename Functor> void forEach(Functor&);
-
- private:
- NEVER_INLINE MarkedBlock* allocateBlock();
- NEVER_INLINE void freeBlock(size_t);
-
- void clearMarks(MarkedBlock*);
-
- CollectorHeap m_heap;
- size_t m_waterMark;
- size_t m_highWaterMark;
- JSGlobalData* m_globalData;
- };
-
- inline Heap* MarkedSpace::heap(JSCell* cell)
- {
- return MarkedBlock::blockFor(cell)->heap();
- }
-
- inline bool MarkedSpace::isMarked(const JSCell* cell)
- {
- return MarkedBlock::blockFor(cell)->isMarked(cell);
- }
-
- inline bool MarkedSpace::testAndSetMarked(const JSCell* cell)
- {
- return MarkedBlock::blockFor(cell)->testAndSetMarked(cell);
- }
-
- inline void MarkedSpace::setMarked(const JSCell* cell)
- {
- MarkedBlock::blockFor(cell)->setMarked(cell);
- }
-
- inline bool MarkedSpace::contains(const void* x)
- {
- if (!MarkedBlock::isCellAligned(x))
- return false;
-
- MarkedBlock* block = MarkedBlock::blockFor(x);
- if (!block)
- return false;
-
- size_t size = m_heap.blocks.size();
- for (size_t i = 0; i < size; i++) {
- if (block != m_heap.collectorBlock(i))
- continue;
-
- // 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.)
- return block->isMarked(x);
- }
-
- return false;
- }
-
- template <typename Functor> inline void MarkedSpace::forEach(Functor& functor)
- {
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- m_heap.collectorBlock(i)->forEach(functor);
- }
-
-} // namespace JSC
-
-#endif // MarkedSpace_h
diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp
index c79316b..52bd76a 100644
--- a/Source/JavaScriptCore/runtime/MathObject.cpp
+++ b/Source/JavaScriptCore/runtime/MathObject.cpp
@@ -61,7 +61,7 @@ namespace JSC {
// ------------------------------ MathObject --------------------------------
-const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
+const ClassInfo MathObject::s_info = { "Math", &JSObjectWithGlobalObject::s_info, 0, ExecState::mathTable };
/* Source for MathObject.lut.h
@begin mathTable
@@ -86,14 +86,16 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
@end
*/
-MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
+MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
: JSObjectWithGlobalObject(globalObject, structure)
{
+ ASSERT(inherits(&s_info));
+
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN2"), jsNumber(log(2.0)), DontDelete | DontEnum | ReadOnly);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN10"), jsNumber(log(10.0)), DontDelete | DontEnum | ReadOnly);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG2E"), jsNumber(1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG10E"), jsNumber(1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG10E"), jsNumber(0.4342944819032518), DontDelete | DontEnum | ReadOnly); // See ECMA-262 15.8.1.5
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "PI"), jsNumber(piDouble), DontDelete | DontEnum | ReadOnly);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT1_2"), jsNumber(sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT2"), jsNumber(sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
diff --git a/Source/JavaScriptCore/runtime/MathObject.h b/Source/JavaScriptCore/runtime/MathObject.h
index 31fa2fe..75753be 100644
--- a/Source/JavaScriptCore/runtime/MathObject.h
+++ b/Source/JavaScriptCore/runtime/MathObject.h
@@ -27,17 +27,16 @@ namespace JSC {
class MathObject : public JSObjectWithGlobalObject {
public:
- MathObject(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>);
+ MathObject(ExecState*, JSGlobalObject*, Structure*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
index 421eecf..9cd5dcb 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
@@ -30,22 +30,34 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
-const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 };
+const ClassInfo NativeErrorConstructor::s_info = { "Function", &InternalFunction::s_info, 0, 0 };
-NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<Structure> prototypeStructure, const UString& nameAndMessage)
+NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* prototypeStructure, const UString& nameAndMessage)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, nameAndMessage))
{
+ ASSERT(inherits(&s_info));
+
NativeErrorPrototype* prototype = new (exec) NativeErrorPrototype(exec, globalObject, prototypeStructure, nameAndMessage, this);
putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum);
- m_errorStructure = ErrorInstance::createStructure(prototype);
+ m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), prototype));
+ ASSERT(m_errorStructure);
+ ASSERT(m_errorStructure->typeInfo().type() == ObjectType);
+}
+
+void NativeErrorConstructor::markChildren(MarkStack& markStack)
+{
+ InternalFunction::markChildren(markStack);
+ if (m_errorStructure)
+ markStack.append(&m_errorStructure);
}
static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState* exec)
{
JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
Structure* errorStructure = static_cast<NativeErrorConstructor*>(exec->callee())->errorStructure();
+ ASSERT(errorStructure);
return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
}
diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
index 1ff8207..e96daf6 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
+++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
@@ -31,19 +31,24 @@ namespace JSC {
class NativeErrorConstructor : public InternalFunction {
public:
- NativeErrorConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<Structure> prototypeStructure, const UString&);
+ NativeErrorConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* prototypeStructure, const UString&);
- static const ClassInfo info;
+ static const ClassInfo s_info;
+
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
Structure* errorStructure() { return m_errorStructure.get(); }
private:
+ static const unsigned StructureFlags = OverridesMarkChildren | InternalFunction::StructureFlags;
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
+ virtual void markChildren(MarkStack&);
- virtual const ClassInfo* classInfo() const { return &info; }
-
- RefPtr<Structure> m_errorStructure;
+ WriteBarrier<Structure> m_errorStructure;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp
index 4e10268..de27d59 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp
@@ -31,7 +31,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
-NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& nameAndMessage, NativeErrorConstructor* constructor)
+NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& nameAndMessage, NativeErrorConstructor* constructor)
: JSObjectWithGlobalObject(globalObject, structure)
{
putDirect(exec->globalData(), exec->propertyNames().name, jsString(exec, nameAndMessage), 0);
diff --git a/Source/JavaScriptCore/runtime/NativeErrorPrototype.h b/Source/JavaScriptCore/runtime/NativeErrorPrototype.h
index 30690d5..e1b05ce 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorPrototype.h
+++ b/Source/JavaScriptCore/runtime/NativeErrorPrototype.h
@@ -28,7 +28,7 @@ namespace JSC {
class NativeErrorPrototype : public JSObjectWithGlobalObject {
public:
- NativeErrorPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, const UString&, NativeErrorConstructor*);
+ NativeErrorPrototype(ExecState*, JSGlobalObject*, Structure*, const UString&, NativeErrorConstructor*);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/NativeFunctionWrapper.h b/Source/JavaScriptCore/runtime/NativeFunctionWrapper.h
deleted file mode 100644
index d4eeb3b..0000000
--- a/Source/JavaScriptCore/runtime/NativeFunctionWrapper.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
- * 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 NativeFunctionWrapper_h
-#define NativeFunctionWrapper_h
-
-namespace JSC {
-#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
- class JSFunction;
- typedef JSFunction NativeFunctionWrapper;
-#else
- class PrototypeFunction;
- typedef PrototypeFunction NativeFunctionWrapper;
-#endif
-}
-
-#endif
diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.cpp b/Source/JavaScriptCore/runtime/NumberConstructor.cpp
index 7cec875..4193f79 100644
--- a/Source/JavaScriptCore/runtime/NumberConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NumberConstructor.cpp
@@ -42,7 +42,7 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&)
namespace JSC {
-const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::numberTable };
+const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::numberTable };
/* Source for NumberConstructor.lut.h
@begin numberTable
@@ -54,9 +54,11 @@ const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info,
@end
*/
-NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
- : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, numberPrototype->info.className))
+NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, NumberPrototype* numberPrototype)
+ : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, numberPrototype->s_info.className))
{
+ ASSERT(inherits(&s_info));
+
// Number.Prototype
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
@@ -102,7 +104,7 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&)
// ECMA 15.7.1
static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec)
{
- NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure());
+ NumberObject* object = new (exec) NumberObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure());
double n = exec->argumentCount() ? exec->argument(0).toNumber(exec) : 0;
object->setInternalValue(exec->globalData(), jsNumber(n));
return JSValue::encode(object);
diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.h b/Source/JavaScriptCore/runtime/NumberConstructor.h
index d8a2593..69aa8a1 100644
--- a/Source/JavaScriptCore/runtime/NumberConstructor.h
+++ b/Source/JavaScriptCore/runtime/NumberConstructor.h
@@ -29,17 +29,17 @@ namespace JSC {
class NumberConstructor : public InternalFunction {
public:
- NumberConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, NumberPrototype*);
+ NumberConstructor(ExecState*, JSGlobalObject*, Structure*, NumberPrototype*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
JSValue getValueProperty(ExecState*, int token) const;
- static const ClassInfo info;
+ static const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue proto)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
@@ -50,8 +50,6 @@ namespace JSC {
private:
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
-
- virtual const ClassInfo* classInfo() const { return &info; }
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/NumberObject.cpp b/Source/JavaScriptCore/runtime/NumberObject.cpp
index 603c2f0..6ee103b 100644
--- a/Source/JavaScriptCore/runtime/NumberObject.cpp
+++ b/Source/JavaScriptCore/runtime/NumberObject.cpp
@@ -29,11 +29,12 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(NumberObject);
-const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };
+const ClassInfo NumberObject::s_info = { "Number", &JSWrapperObject::s_info, 0, 0 };
-NumberObject::NumberObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure)
+NumberObject::NumberObject(JSGlobalData& globalData, Structure* structure)
: JSWrapperObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
}
JSValue NumberObject::getJSNumber()
@@ -41,9 +42,9 @@ JSValue NumberObject::getJSNumber()
return internalValue();
}
-NumberObject* constructNumber(ExecState* exec, JSValue number)
+NumberObject* constructNumber(ExecState* exec, JSGlobalObject* globalObject, JSValue number)
{
- NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure());
+ NumberObject* object = new (exec) NumberObject(exec->globalData(), globalObject->numberObjectStructure());
object->setInternalValue(exec->globalData(), number);
return object;
}
diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h
index 044f490..cba65dd 100644
--- a/Source/JavaScriptCore/runtime/NumberObject.h
+++ b/Source/JavaScriptCore/runtime/NumberObject.h
@@ -27,25 +27,20 @@ namespace JSC {
class NumberObject : public JSWrapperObject {
public:
- explicit NumberObject(JSGlobalData&, NonNullPassRefPtr<Structure>);
+ explicit NumberObject(JSGlobalData&, Structure*);
- static const ClassInfo info;
+ static const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
- protected:
- static const unsigned StructureFlags = JSWrapperObject::StructureFlags;
-
private:
- virtual const ClassInfo* classInfo() const { return &info; }
-
virtual JSValue getJSNumber();
};
- NumberObject* constructNumber(ExecState*, JSValue);
+ NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
index fbe6992..24532dd 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -26,7 +26,6 @@
#include "JSFunction.h"
#include "JSString.h"
#include "Operations.h"
-#include "PrototypeFunction.h"
#include "dtoa.h"
#include <wtf/Assertions.h>
#include <wtf/DecimalNumber.h>
@@ -46,19 +45,19 @@ static EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*);
// ECMA 15.7.4
-NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure)
: NumberObject(exec->globalData(), structure)
{
setInternalValue(exec->globalData(), jsNumber(0));
// The constructor will be added later, after NumberConstructor has been constructed
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
}
// ------------------------------ Functions ---------------------------
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.h b/Source/JavaScriptCore/runtime/NumberPrototype.h
index 78b690e..45bdfe7 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.h
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.h
@@ -27,7 +27,7 @@ namespace JSC {
class NumberPrototype : public NumberObject {
public:
- NumberPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ NumberPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index f31da67..aed5e24 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -26,10 +26,10 @@
#include "JSFunction.h"
#include "JSArray.h"
#include "JSGlobalObject.h"
+#include "Lookup.h"
#include "ObjectPrototype.h"
#include "PropertyDescriptor.h"
#include "PropertyNameArray.h"
-#include "PrototypeFunction.h"
namespace JSC {
@@ -42,38 +42,71 @@ static EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState*);
-ObjectConstructor::ObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
-: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "Object"))
+}
+
+#include "ObjectConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::objectConstructorTable };
+
+/* Source for ObjectConstructor.lut.h
+@begin objectConstructorTable
+ getPrototypeOf objectConstructorGetPrototypeOf DontEnum|Function 1
+ getOwnPropertyDescriptor objectConstructorGetOwnPropertyDescriptor DontEnum|Function 2
+ getOwnPropertyNames objectConstructorGetOwnPropertyNames DontEnum|Function 1
+ keys objectConstructorKeys DontEnum|Function 1
+ defineProperty objectConstructorDefineProperty DontEnum|Function 3
+ defineProperties objectConstructorDefineProperties DontEnum|Function 2
+ create objectConstructorCreate DontEnum|Function 2
+ seal objectConstructorSeal DontEnum|Function 1
+ freeze objectConstructorFreeze DontEnum|Function 1
+ preventExtensions objectConstructorPreventExtensions DontEnum|Function 1
+ isSealed objectConstructorIsSealed DontEnum|Function 1
+ isFrozen objectConstructorIsFrozen DontEnum|Function 1
+ isExtensible objectConstructorIsExtensible DontEnum|Function 1
+@end
+*/
+
+ObjectConstructor::ObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ObjectPrototype* objectPrototype)
+ : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "Object"))
{
// ECMA 15.2.3.1
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
-
// no. of arguments for constructor
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
-
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().getOwnPropertyNames, objectConstructorGetOwnPropertyNames), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 2, exec->propertyNames().create, objectConstructorCreate), DontEnum);
+}
+
+bool ObjectConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+ return getStaticFunctionSlot<JSObject>(exec, ExecState::objectConstructorTable(exec), this, propertyName, slot);
+}
+
+bool ObjectConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticFunctionDescriptor<JSObject>(exec, ExecState::objectConstructorTable(exec), this, propertyName, descriptor);
}
// ECMA 15.2.2
-static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args)
+static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
{
JSValue arg = args.at(0);
if (arg.isUndefinedOrNull())
- return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
- return arg.toObject(exec);
+ return constructEmptyObject(exec, globalObject);
+ return arg.toObject(exec, globalObject);
}
static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* exec)
{
ArgList args(exec);
- return JSValue::encode(constructObject(exec, args));
+ return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
}
ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
@@ -85,7 +118,7 @@ ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec)
{
ArgList args(exec);
- return JSValue::encode(constructObject(exec, args));
+ return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
}
CallType ObjectConstructor::getCallData(CallData& callData)
@@ -309,7 +342,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
if (!exec->argument(0).isObject() && !exec->argument(0).isNull())
return throwVMError(exec, createTypeError(exec, "Object prototype may only be an Object or null."));
JSObject* newObject = constructEmptyObject(exec);
- newObject->setPrototype(exec->argument(0));
+ newObject->setPrototype(exec->globalData(), exec->argument(0));
if (exec->argument(1).isUndefined())
return JSValue::encode(newObject);
if (!exec->argument(1).isObject())
@@ -317,4 +350,55 @@ EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
return JSValue::encode(defineProperties(exec, newObject, asObject(exec->argument(1))));
}
+EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
+{
+ JSValue obj = exec->argument(0);
+ if (!obj.isObject())
+ return throwVMError(exec, createTypeError(exec, "Object.seal can only be called on Objects."));
+ asObject(obj)->seal(exec->globalData());
+ return JSValue::encode(obj);
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
+{
+ JSValue obj = exec->argument(0);
+ if (!obj.isObject())
+ return throwVMError(exec, createTypeError(exec, "Object.freeze can only be called on Objects."));
+ asObject(obj)->freeze(exec->globalData());
+ return JSValue::encode(obj);
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec)
+{
+ JSValue obj = exec->argument(0);
+ if (!obj.isObject())
+ return throwVMError(exec, createTypeError(exec, "Object.preventExtensions can only be called on Objects."));
+ asObject(obj)->preventExtensions(exec->globalData());
+ return JSValue::encode(obj);
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
+{
+ JSValue obj = exec->argument(0);
+ if (!obj.isObject())
+ return throwVMError(exec, createTypeError(exec, "Object.isSealed can only be called on Objects."));
+ return JSValue::encode(jsBoolean(asObject(obj)->isSealed(exec->globalData())));
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
+{
+ JSValue obj = exec->argument(0);
+ if (!obj.isObject())
+ return throwVMError(exec, createTypeError(exec, "Object.isFrozen can only be called on Objects."));
+ return JSValue::encode(jsBoolean(asObject(obj)->isFrozen(exec->globalData())));
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
+{
+ JSValue obj = exec->argument(0);
+ if (!obj.isObject())
+ return throwVMError(exec, createTypeError(exec, "Object.isExtensible can only be called on Objects."));
+ return JSValue::encode(jsBoolean(asObject(obj)->isExtensible()));
+}
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.h b/Source/JavaScriptCore/runtime/ObjectConstructor.h
index 04a3c1a..6ebafcd 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.h
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.h
@@ -29,7 +29,20 @@ namespace JSC {
class ObjectConstructor : public InternalFunction {
public:
- ObjectConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure);
+ ObjectConstructor(ExecState*, JSGlobalObject*, Structure*, ObjectPrototype*);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+
+ static const ClassInfo s_info;
+
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
private:
virtual ConstructType getConstructData(ConstructData&);
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
index 57a8a31..7469172 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -25,7 +25,6 @@
#include "JSFunction.h"
#include "JSString.h"
#include "JSStringBuilder.h"
-#include "PrototypeFunction.h"
namespace JSC {
@@ -41,22 +40,22 @@ static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*);
-ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
- : JSObject(stucture)
+ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* stucture, Structure* functionStructure)
+ : JSNonFinalObject(exec->globalData(), stucture)
, m_hasNoPropertiesWithUInt32Names(true)
{
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum);
// Mozilla extensions
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
}
void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.h b/Source/JavaScriptCore/runtime/ObjectPrototype.h
index 0382ae4..9fb7fae 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.h
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.h
@@ -25,9 +25,9 @@
namespace JSC {
- class ObjectPrototype : public JSObject {
+ class ObjectPrototype : public JSNonFinalObject {
public:
- ObjectPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ ObjectPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure);
private:
virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h
index 6e84123..c102eeb 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -24,9 +24,8 @@
#include "ExceptionHelpers.h"
#include "Interpreter.h"
-#include "JSImmediate.h"
-#include "JSNumberCell.h"
#include "JSString.h"
+#include "JSValueInlineMethods.h"
namespace JSC {
@@ -431,7 +430,7 @@ namespace JSC {
if (cell->structure()->isDictionary()) {
asObject(cell)->flattenDictionaryObject(callFrame->globalData());
if (slotBase == cell)
- slotOffset = cell->structure()->get(propertyName);
+ slotOffset = cell->structure()->get(callFrame->globalData(), propertyName);
}
++count;
@@ -472,8 +471,11 @@ namespace JSC {
JSObject* base;
while (true) {
base = iter->get();
- if (next == end)
- return isStrictPut ? JSValue() : base;
+ if (next == end) {
+ if (isStrictPut && !base->getPropertySlot(callFrame, property, slot))
+ return JSValue();
+ return base;
+ }
if (base->getPropertySlot(callFrame, property, slot))
return base;
diff --git a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
index bd452b6..fc195cd 100644
--- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
+++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -22,69 +22,536 @@
#define PropertyMapHashTable_h
#include "UString.h"
+#include "WriteBarrier.h"
+#include <wtf/HashTable.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
+
+#ifndef NDEBUG
+#define DUMP_PROPERTYMAP_STATS 0
+#else
+#define DUMP_PROPERTYMAP_STATS 0
+#endif
+
+#if DUMP_PROPERTYMAP_STATS
+
+extern int numProbes;
+extern int numCollisions;
+extern int numRehashes;
+extern int numRemoves;
+
+#endif
+
+#define PROPERTY_MAP_DELETED_ENTRY_KEY ((StringImpl*)1)
+
namespace JSC {
- struct PropertyMapEntry {
- StringImpl* key;
- unsigned offset;
- unsigned attributes;
- JSCell* specificValue;
- unsigned index;
-
- PropertyMapEntry(StringImpl* key, unsigned attributes, JSCell* specificValue)
- : key(key)
- , offset(0)
- , attributes(attributes)
- , specificValue(specificValue)
- , index(0)
+inline bool isPowerOf2(unsigned v)
+{
+ // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
+
+ return !(v & (v - 1)) && v;
+}
+
+inline unsigned nextPowerOf2(unsigned v)
+{
+ // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
+ // Devised by Sean Anderson, Sepember 14, 2001
+
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+
+ return v;
+}
+
+struct PropertyMapEntry {
+ StringImpl* key;
+ unsigned offset;
+ unsigned attributes;
+ WriteBarrier<JSCell> specificValue;
+
+ PropertyMapEntry(JSGlobalData& globalData, JSCell* owner, StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue)
+ : key(key)
+ , offset(offset)
+ , attributes(attributes)
+ , specificValue(globalData, owner, specificValue)
+ {
+ }
+};
+
+class PropertyTable {
+ WTF_MAKE_FAST_ALLOCATED;
+
+ // This is the implementation for 'iterator' and 'const_iterator',
+ // used for iterating over the table in insertion order.
+ template<typename T>
+ class ordered_iterator {
+ public:
+ ordered_iterator<T>& operator++()
{
+ m_valuePtr = skipDeletedEntries(m_valuePtr + 1);
+ return *this;
}
- PropertyMapEntry(StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue, unsigned index)
- : key(key)
- , offset(offset)
- , attributes(attributes)
- , specificValue(specificValue)
- , index(index)
+ bool operator==(const ordered_iterator<T>& other)
{
+ return m_valuePtr == other.m_valuePtr;
+ }
+
+ bool operator!=(const ordered_iterator<T>& other)
+ {
+ return m_valuePtr != other.m_valuePtr;
+ }
+
+ T& operator*()
+ {
+ return *m_valuePtr;
}
- };
- // lastIndexUsed is an ever-increasing index used to identify the order items
- // were inserted into the property map. It's required that getEnumerablePropertyNames
- // return the properties in the order they were added for compatibility with other
- // browsers' JavaScript implementations.
- struct PropertyMapHashTable {
- unsigned sizeMask;
- unsigned size;
- unsigned keyCount;
- unsigned deletedSentinelCount;
- unsigned lastIndexUsed;
- Vector<unsigned>* deletedOffsets;
- unsigned entryIndices[1];
-
- PropertyMapEntry* entries()
+ T* operator->()
{
- // The entries vector comes after the indices vector.
- // The 0th item in the entries vector is not really used; it has to
- // have a 0 in its key to allow the hash table lookup to handle deleted
- // sentinels without any special-case code, but the other fields are unused.
- return reinterpret_cast<PropertyMapEntry*>(&entryIndices[size]);
+ return m_valuePtr;
}
- static size_t allocationSize(unsigned size)
+ ordered_iterator(T* valuePtr)
+ : m_valuePtr(valuePtr)
{
- // We never let a hash table get more than half full,
- // So the number of indices we need is the size of the hash table.
- // But the number of entries is half that (plus one for the deleted sentinel).
- return sizeof(PropertyMapHashTable)
- + (size - 1) * sizeof(unsigned)
- + (1 + size / 2) * sizeof(PropertyMapEntry);
}
+
+ private:
+ T* m_valuePtr;
};
+public:
+ typedef StringImpl* KeyType;
+ typedef PropertyMapEntry ValueType;
+
+ // The in order iterator provides overloaded * and -> to access the Value at the current position.
+ typedef ordered_iterator<ValueType> iterator;
+ typedef ordered_iterator<const ValueType> const_iterator;
+
+ // The find_iterator is a pair of a pointer to a Value* an the entry in the index.
+ // If 'find' does not find an entry then iter.first will be 0, and iter.second will
+ // give the point in m_index where an entry should be inserted.
+ typedef std::pair<ValueType*, unsigned> find_iterator;
+
+ // Constructor is passed an initial capacity, a PropertyTable to copy, or both.
+ explicit PropertyTable(unsigned initialCapacity);
+ PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&);
+ PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&);
+ ~PropertyTable();
+
+ // Ordered iteration methods.
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ // Find a value in the table.
+ find_iterator find(const KeyType& key);
+ // Add a value to the table
+ std::pair<find_iterator, bool> add(const ValueType& entry);
+ // Remove a value from the table.
+ void remove(const find_iterator& iter);
+ void remove(const KeyType& key);
+
+ // Returns the number of values in the hashtable.
+ unsigned size() const;
+
+ // Checks if there are any values in the hashtable.
+ bool isEmpty() const;
+
+ // Number of slots in the property storage array in use, included deletedOffsets.
+ unsigned propertyStorageSize() const;
+
+ // Used to maintain a list of unused entries in the property storage.
+ void clearDeletedOffsets();
+ bool hasDeletedOffset();
+ unsigned getDeletedOffset();
+ void addDeletedOffset(unsigned offset);
+
+ // Copy this PropertyTable, ensuring the copy has at least the capacity provided.
+ PassOwnPtr<PropertyTable> copy(JSGlobalData&, JSCell* owner, unsigned newCapacity);
+
+#ifndef NDEBUG
+ size_t sizeInMemory();
+ void checkConsistency();
+#endif
+
+private:
+ PropertyTable(const PropertyTable&);
+ // Used to insert a value known not to be in the table, and where we know capacity to be available.
+ void reinsert(const ValueType& entry);
+
+ // Rehash the table. Used to grow, or to recover deleted slots.
+ void rehash(unsigned newCapacity);
+
+ // The capacity of the table of values is half of the size of the index.
+ unsigned tableCapacity() const;
+
+ // We keep an extra deleted slot after the array to make iteration work,
+ // and to use for deleted values. Index values into the array are 1-based,
+ // so this is tableCapacity() + 1.
+ // For example, if m_tableSize is 16, then tableCapacity() is 8 - but the
+ // values array is actually 9 long (the 9th used for the deleted value/
+ // iteration guard). The 8 valid entries are numbered 1..8, so the
+ // deleted index is 9 (0 being reserved for empty).
+ unsigned deletedEntryIndex() const;
+
+ // Used in iterator creation/progression.
+ template<typename T>
+ static T* skipDeletedEntries(T* valuePtr);
+
+ // The table of values lies after the hash index.
+ ValueType* table();
+ const ValueType* table() const;
+
+ // total number of used entries in the values array - by either valid entries, or deleted ones.
+ unsigned usedCount() const;
+
+ // The size in bytes of data needed for by the table.
+ size_t dataSize();
+
+ // Calculates the appropriate table size (rounds up to a power of two).
+ static unsigned sizeForCapacity(unsigned capacity);
+
+ // Check if capacity is available.
+ bool canInsert();
+
+ unsigned m_indexSize;
+ unsigned m_indexMask;
+ unsigned* m_index;
+ unsigned m_keyCount;
+ unsigned m_deletedCount;
+ OwnPtr< Vector<unsigned> > m_deletedOffsets;
+
+ static const unsigned MinimumTableSize = 16;
+ static const unsigned EmptyEntryIndex = 0;
+};
+
+inline PropertyTable::PropertyTable(unsigned initialCapacity)
+ : m_indexSize(sizeForCapacity(initialCapacity))
+ , m_indexMask(m_indexSize - 1)
+ , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
+ , m_keyCount(0)
+ , m_deletedCount(0)
+{
+ ASSERT(isPowerOf2(m_indexSize));
+}
+
+inline PropertyTable::PropertyTable(JSGlobalData& globalData, JSCell* owner, const PropertyTable& other)
+ : m_indexSize(other.m_indexSize)
+ , m_indexMask(other.m_indexMask)
+ , m_index(static_cast<unsigned*>(fastMalloc(dataSize())))
+ , m_keyCount(other.m_keyCount)
+ , m_deletedCount(other.m_deletedCount)
+{
+ ASSERT(isPowerOf2(m_indexSize));
+
+ memcpy(m_index, other.m_index, dataSize());
+
+ iterator end = this->end();
+ for (iterator iter = begin(); iter != end; ++iter) {
+ iter->key->ref();
+ writeBarrier(globalData, owner, iter->specificValue.get());
+ }
+
+ // Copy the m_deletedOffsets vector.
+ Vector<unsigned>* otherDeletedOffsets = other.m_deletedOffsets.get();
+ if (otherDeletedOffsets)
+ m_deletedOffsets.set(new Vector<unsigned>(*otherDeletedOffsets));
+}
+
+inline PropertyTable::PropertyTable(JSGlobalData& globalData, JSCell* owner, unsigned initialCapacity, const PropertyTable& other)
+ : m_indexSize(sizeForCapacity(initialCapacity))
+ , m_indexMask(m_indexSize - 1)
+ , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
+ , m_keyCount(0)
+ , m_deletedCount(0)
+{
+ ASSERT(isPowerOf2(m_indexSize));
+ ASSERT(initialCapacity >= other.m_keyCount);
+
+ const_iterator end = other.end();
+ for (const_iterator iter = other.begin(); iter != end; ++iter) {
+ ASSERT(canInsert());
+ reinsert(*iter);
+ iter->key->ref();
+ writeBarrier(globalData, owner, iter->specificValue.get());
+ }
+
+ // Copy the m_deletedOffsets vector.
+ Vector<unsigned>* otherDeletedOffsets = other.m_deletedOffsets.get();
+ if (otherDeletedOffsets)
+ m_deletedOffsets.set(new Vector<unsigned>(*otherDeletedOffsets));
+}
+
+inline PropertyTable::~PropertyTable()
+{
+ iterator end = this->end();
+ for (iterator iter = begin(); iter != end; ++iter)
+ iter->key->deref();
+
+ fastFree(m_index);
+}
+
+inline PropertyTable::iterator PropertyTable::begin()
+{
+ return iterator(skipDeletedEntries(table()));
+}
+
+inline PropertyTable::iterator PropertyTable::end()
+{
+ return iterator(table() + usedCount());
+}
+
+inline PropertyTable::const_iterator PropertyTable::begin() const
+{
+ return const_iterator(skipDeletedEntries(table()));
+}
+
+inline PropertyTable::const_iterator PropertyTable::end() const
+{
+ return const_iterator(table() + usedCount());
+}
+
+inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
+{
+ ASSERT(key);
+ unsigned hash = key->existingHash();
+ unsigned step = 0;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ while (true) {
+ unsigned entryIndex = m_index[hash & m_indexMask];
+ if (entryIndex == EmptyEntryIndex)
+ return std::make_pair((ValueType*)0, hash & m_indexMask);
+ if (key == table()[entryIndex - 1].key)
+ return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask);
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ if (!step)
+ step =WTF::doubleHash(key->existingHash()) | 1;
+ hash += step;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+ }
+}
+
+inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const ValueType& entry)
+{
+ // Look for a value with a matching key already in the array.
+ find_iterator iter = find(entry.key);
+ if (iter.first)
+ return std::make_pair(iter, false);
+
+ // Ref the key
+ entry.key->ref();
+
+ // ensure capacity is available.
+ if (!canInsert()) {
+ rehash(m_keyCount + 1);
+ iter = find(entry.key);
+ ASSERT(!iter.first);
+ }
+
+ // Allocate a slot in the hashtable, and set the index to reference this.
+ unsigned entryIndex = usedCount() + 1;
+ m_index[iter.second] = entryIndex;
+ iter.first = &table()[entryIndex - 1];
+ *iter.first = entry;
+
+ ++m_keyCount;
+ return std::make_pair(iter, true);
+}
+
+inline void PropertyTable::remove(const find_iterator& iter)
+{
+ // Removing a key that doesn't exist does nothing!
+ if (!iter.first)
+ return;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRemoves;
+#endif
+
+ // Replace this one element with the deleted sentinel. Also clear out
+ // the entry so we can iterate all the entries as needed.
+ m_index[iter.second] = deletedEntryIndex();
+ iter.first->key->deref();
+ iter.first->key = PROPERTY_MAP_DELETED_ENTRY_KEY;
+
+ ASSERT(m_keyCount >= 1);
+ --m_keyCount;
+ ++m_deletedCount;
+
+ if (m_deletedCount * 4 >= m_indexSize)
+ rehash(m_keyCount);
+}
+
+inline void PropertyTable::remove(const KeyType& key)
+{
+ remove(find(key));
+}
+
+// returns the number of values in the hashtable.
+inline unsigned PropertyTable::size() const
+{
+ return m_keyCount;
+}
+
+inline bool PropertyTable::isEmpty() const
+{
+ return !m_keyCount;
+}
+
+inline unsigned PropertyTable::propertyStorageSize() const
+{
+ return size() + (m_deletedOffsets ? m_deletedOffsets->size() : 0);
+}
+
+inline void PropertyTable::clearDeletedOffsets()
+{
+ m_deletedOffsets.clear();
+}
+
+inline bool PropertyTable::hasDeletedOffset()
+{
+ return m_deletedOffsets && !m_deletedOffsets->isEmpty();
+}
+
+inline unsigned PropertyTable::getDeletedOffset()
+{
+ unsigned offset = m_deletedOffsets->last();
+ m_deletedOffsets->removeLast();
+ return offset;
+}
+
+inline void PropertyTable::addDeletedOffset(unsigned offset)
+{
+ if (!m_deletedOffsets)
+ m_deletedOffsets.set(new Vector<unsigned>);
+ m_deletedOffsets->append(offset);
+}
+
+inline PassOwnPtr<PropertyTable> PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity)
+{
+ ASSERT(newCapacity >= m_keyCount);
+
+ // Fast case; if the new table will be the same m_indexSize as this one, we can memcpy it,
+ // save rehashing all keys.
+ if (sizeForCapacity(newCapacity) == m_indexSize)
+ return new PropertyTable(globalData, owner, *this);
+ return new PropertyTable(globalData, owner, newCapacity, *this);
+}
+
+#ifndef NDEBUG
+inline size_t PropertyTable::sizeInMemory()
+{
+ size_t result = sizeof(PropertyTable) + dataSize();
+ if (m_deletedOffsets)
+ result += (m_deletedOffsets->capacity() * sizeof(unsigned));
+ return result;
+}
+#endif
+
+inline void PropertyTable::reinsert(const ValueType& entry)
+{
+ // Used to insert a value known not to be in the table, and where
+ // we know capacity to be available.
+ ASSERT(canInsert());
+ find_iterator iter = find(entry.key);
+ ASSERT(!iter.first);
+
+ unsigned entryIndex = usedCount() + 1;
+ m_index[iter.second] = entryIndex;
+ table()[entryIndex - 1] = entry;
+
+ ++m_keyCount;
+}
+
+inline void PropertyTable::rehash(unsigned newCapacity)
+{
+ unsigned* oldEntryIndices = m_index;
+ iterator iter = this->begin();
+ iterator end = this->end();
+
+ m_indexSize = sizeForCapacity(newCapacity);
+ m_indexMask = m_indexSize - 1;
+ m_keyCount = 0;
+ m_deletedCount = 0;
+ m_index = static_cast<unsigned*>(fastZeroedMalloc(dataSize()));
+
+ for (; iter != end; ++iter) {
+ ASSERT(canInsert());
+ reinsert(*iter);
+ }
+
+ fastFree(oldEntryIndices);
+}
+
+inline unsigned PropertyTable::tableCapacity() const { return m_indexSize >> 1; }
+
+inline unsigned PropertyTable::deletedEntryIndex() const { return tableCapacity() + 1; }
+
+template<typename T>
+inline T* PropertyTable::skipDeletedEntries(T* valuePtr)
+{
+ while (valuePtr->key == PROPERTY_MAP_DELETED_ENTRY_KEY)
+ ++valuePtr;
+ return valuePtr;
+}
+
+inline PropertyTable::ValueType* PropertyTable::table()
+{
+ // The table of values lies after the hash index.
+ return reinterpret_cast<ValueType*>(m_index + m_indexSize);
+}
+
+inline const PropertyTable::ValueType* PropertyTable::table() const
+{
+ // The table of values lies after the hash index.
+ return reinterpret_cast<const ValueType*>(m_index + m_indexSize);
+}
+
+inline unsigned PropertyTable::usedCount() const
+{
+ // Total number of used entries in the values array - by either valid entries, or deleted ones.
+ return m_keyCount + m_deletedCount;
+}
+
+inline size_t PropertyTable::dataSize()
+{
+ // The size in bytes of data needed for by the table.
+ return m_indexSize * sizeof(unsigned) + ((tableCapacity()) + 1) * sizeof(ValueType);
+}
+
+inline unsigned PropertyTable::sizeForCapacity(unsigned capacity)
+{
+ if (capacity < 8)
+ return MinimumTableSize;
+ return nextPowerOf2(capacity + 1) * 2;
+}
+
+inline bool PropertyTable::canInsert()
+{
+ return usedCount() < tableCapacity();
+}
+
} // namespace JSC
#endif // PropertyMapHashTable_h
diff --git a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp
index afb41be..8efb406 100644
--- a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp
+++ b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp
@@ -21,6 +21,8 @@
#include "config.h"
#include "PropertyNameArray.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
#include "Structure.h"
#include "StructureChain.h"
diff --git a/Source/JavaScriptCore/runtime/PropertySlot.h b/Source/JavaScriptCore/runtime/PropertySlot.h
index cdda6ff..ce29ac4 100644
--- a/Source/JavaScriptCore/runtime/PropertySlot.h
+++ b/Source/JavaScriptCore/runtime/PropertySlot.h
@@ -123,15 +123,6 @@ namespace JSC {
m_value = value;
}
- void setRegisterSlot(Register* registerSlot)
- {
- ASSERT(registerSlot);
- clearBase();
- clearOffset();
- m_getValue = JSC_VALUE_MARKER;
- m_value = registerSlot->jsValue();
- }
-
void setCustom(JSValue slotBase, GetValueFunc getValue)
{
ASSERT(slotBase);
diff --git a/Source/JavaScriptCore/runtime/Protect.h b/Source/JavaScriptCore/runtime/Protect.h
index 0c1b5e8..843c9e1 100644
--- a/Source/JavaScriptCore/runtime/Protect.h
+++ b/Source/JavaScriptCore/runtime/Protect.h
@@ -61,155 +61,6 @@ namespace JSC {
gcUnprotect(value.asCell());
}
- // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation
- // and the implicit conversion to raw pointer
- template <class T> class ProtectedPtr {
- public:
- ProtectedPtr() : m_ptr(0) {}
- ProtectedPtr(T* ptr);
- ProtectedPtr(const ProtectedPtr&);
- ~ProtectedPtr();
-
- template <class U> ProtectedPtr(const ProtectedPtr<U>&);
-
- T* get() const { return m_ptr; }
- operator T*() const { return m_ptr; }
- operator JSValue() const { return JSValue(m_ptr); }
- T* operator->() const { return m_ptr; }
-
- operator bool() const { return m_ptr; }
- bool operator!() const { return !m_ptr; }
-
- ProtectedPtr& operator=(const ProtectedPtr&);
- ProtectedPtr& operator=(T*);
-
- private:
- T* m_ptr;
- };
-
- class ProtectedJSValue {
- public:
- ProtectedJSValue() {}
- ProtectedJSValue(JSValue value);
- ProtectedJSValue(const ProtectedJSValue&);
- ~ProtectedJSValue();
-
- template <class U> ProtectedJSValue(const ProtectedPtr<U>&);
-
- JSValue get() const { return m_value; }
- operator JSValue() const { return m_value; }
- JSValue operator->() const { return m_value; }
-
- operator bool() const { return m_value; }
- bool operator!() const { return !m_value; }
-
- ProtectedJSValue& operator=(const ProtectedJSValue&);
- ProtectedJSValue& operator=(JSValue);
-
- private:
- JSValue m_value;
- };
-
- template <class T> inline ProtectedPtr<T>::ProtectedPtr(T* ptr)
- : m_ptr(ptr)
- {
- gcProtectNullTolerant(m_ptr);
- }
-
- template <class T> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o)
- : m_ptr(o.get())
- {
- gcProtectNullTolerant(m_ptr);
- }
-
- template <class T> inline ProtectedPtr<T>::~ProtectedPtr()
- {
- gcUnprotectNullTolerant(m_ptr);
- }
-
- template <class T> template <class U> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o)
- : m_ptr(o.get())
- {
- gcProtectNullTolerant(m_ptr);
- }
-
- template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o)
- {
- T* optr = o.m_ptr;
- gcProtectNullTolerant(optr);
- gcUnprotectNullTolerant(m_ptr);
- m_ptr = optr;
- return *this;
- }
-
- template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr)
- {
- gcProtectNullTolerant(optr);
- gcUnprotectNullTolerant(m_ptr);
- m_ptr = optr;
- return *this;
- }
-
- inline ProtectedJSValue::ProtectedJSValue(JSValue value)
- : m_value(value)
- {
- gcProtect(m_value);
- }
-
- inline ProtectedJSValue::ProtectedJSValue(const ProtectedJSValue& o)
- : m_value(o.get())
- {
- gcProtect(m_value);
- }
-
- inline ProtectedJSValue::~ProtectedJSValue()
- {
- gcUnprotect(m_value);
- }
-
- template <class U> ProtectedJSValue::ProtectedJSValue(const ProtectedPtr<U>& o)
- : m_value(o.get())
- {
- gcProtect(m_value);
- }
-
- inline ProtectedJSValue& ProtectedJSValue::operator=(const ProtectedJSValue& o)
- {
- JSValue ovalue = o.m_value;
- gcProtect(ovalue);
- gcUnprotect(m_value);
- m_value = ovalue;
- return *this;
- }
-
- inline ProtectedJSValue& ProtectedJSValue::operator=(JSValue ovalue)
- {
- gcProtect(ovalue);
- gcUnprotect(m_value);
- m_value = ovalue;
- return *this;
- }
-
- template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); }
- template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; }
- template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); }
-
- template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); }
- template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; }
- template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); }
-
- inline bool operator==(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() == b.get(); }
- inline bool operator==(const ProtectedJSValue& a, const JSValue b) { return a.get() == b; }
- template <class T> inline bool operator==(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() == JSValue(b.get()); }
- inline bool operator==(const JSValue a, const ProtectedJSValue& b) { return a == b.get(); }
- template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) == b.get(); }
-
- inline bool operator!=(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() != b.get(); }
- inline bool operator!=(const ProtectedJSValue& a, const JSValue b) { return a.get() != b; }
- template <class T> inline bool operator!=(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() != JSValue(b.get()); }
- inline bool operator!=(const JSValue a, const ProtectedJSValue& b) { return a != b.get(); }
- template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) != b.get(); }
-
} // namespace JSC
#endif // Protect_h
diff --git a/Source/JavaScriptCore/runtime/PrototypeFunction.cpp b/Source/JavaScriptCore/runtime/PrototypeFunction.cpp
deleted file mode 100644
index 95e1033..0000000
--- a/Source/JavaScriptCore/runtime/PrototypeFunction.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "PrototypeFunction.h"
-
-#include "JSGlobalObject.h"
-#include <wtf/Assertions.h>
-
-namespace JSC {
-
-ASSERT_CLASS_FITS_IN_CELL(PrototypeFunction);
-
-PrototypeFunction::PrototypeFunction(ExecState* exec, JSGlobalObject* globalObject, int length, const Identifier& name, NativeFunction function)
- : InternalFunction(&exec->globalData(), globalObject, exec->lexicalGlobalObject()->prototypeFunctionStructure(), name)
- , m_function(function)
-{
- ASSERT_ARG(function, function);
- putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
-}
-
-PrototypeFunction::PrototypeFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
- : InternalFunction(&exec->globalData(), globalObject, prototypeFunctionStructure, name)
- , m_function(function)
-{
- ASSERT_ARG(function, function);
- putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
-}
-
-CallType PrototypeFunction::getCallData(CallData& callData)
-{
- callData.native.function = m_function;
- return CallTypeHost;
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/PrototypeFunction.h b/Source/JavaScriptCore/runtime/PrototypeFunction.h
deleted file mode 100644
index 6ca2342..0000000
--- a/Source/JavaScriptCore/runtime/PrototypeFunction.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef PrototypeFunction_h
-#define PrototypeFunction_h
-
-#include "InternalFunction.h"
-#include "CallData.h"
-
-namespace JSC {
-
- class PrototypeFunction : public InternalFunction {
- public:
- PrototypeFunction(ExecState*, JSGlobalObject*, int length, const Identifier&, NativeFunction);
- PrototypeFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
-
- private:
- virtual CallType getCallData(CallData&);
-
- const NativeFunction m_function;
- };
-
-} // namespace JSC
-
-#endif // PrototypeFunction_h
diff --git a/Source/JavaScriptCore/runtime/PutPropertySlot.h b/Source/JavaScriptCore/runtime/PutPropertySlot.h
index 4c9e0e6..69d1f8b 100644
--- a/Source/JavaScriptCore/runtime/PutPropertySlot.h
+++ b/Source/JavaScriptCore/runtime/PutPropertySlot.h
@@ -45,14 +45,14 @@ namespace JSC {
{
}
- void setExistingProperty(DeprecatedPtr<JSObject> base, size_t offset)
+ void setExistingProperty(JSObject* base, size_t offset)
{
m_type = ExistingProperty;
m_base = base;
m_offset = offset;
}
- void setNewProperty(DeprecatedPtr<JSObject> base, size_t offset)
+ void setNewProperty(JSObject* base, size_t offset)
{
m_type = NewProperty;
m_base = base;
@@ -60,7 +60,7 @@ namespace JSC {
}
Type type() const { return m_type; }
- JSObject* base() const { return m_base.get(); }
+ JSObject* base() const { return m_base; }
bool isStrictMode() const { return m_isStrictMode; }
bool isCacheable() const { return m_type != Uncachable; }
@@ -68,9 +68,10 @@ namespace JSC {
ASSERT(isCacheable());
return m_offset;
}
+
private:
Type m_type;
- DeprecatedPtr<JSObject> m_base;
+ JSObject* m_base;
size_t m_offset;
bool m_isStrictMode;
};
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index 95ce5e9..25cb2d5 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -34,6 +34,38 @@
namespace JSC {
+RegExpFlags regExpFlags(const UString& string)
+{
+ RegExpFlags flags = NoFlags;
+
+ for (unsigned i = 0; i < string.length(); ++i) {
+ switch (string.characters()[i]) {
+ case 'g':
+ if (flags & FlagGlobal)
+ return InvalidFlags;
+ flags = static_cast<RegExpFlags>(flags | FlagGlobal);
+ break;
+
+ case 'i':
+ if (flags & FlagIgnoreCase)
+ return InvalidFlags;
+ flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase);
+ break;
+
+ case 'm':
+ if (flags & FlagMultiline)
+ return InvalidFlags;
+ flags = static_cast<RegExpFlags>(flags | FlagMultiline);
+ break;
+
+ default:
+ return InvalidFlags;
+ }
+ }
+
+ return flags;
+}
+
struct RegExpRepresentation {
#if ENABLE(YARR_JIT)
Yarr::YarrCodeBlock m_regExpJITCode;
@@ -41,9 +73,9 @@ struct RegExpRepresentation {
OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
};
-inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, const UString& flags)
+inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags)
: m_patternString(patternString)
- , m_flagBits(0)
+ , m_flags(flags)
, m_constructionError(0)
, m_numSubpatterns(0)
#if ENABLE(REGEXP_TRACING)
@@ -52,17 +84,6 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, co
#endif
, m_representation(adoptPtr(new RegExpRepresentation))
{
- // NOTE: The global flag is handled on a case-by-case basis by functions like
- // String::match and RegExpObject::match.
- if (!flags.isNull()) {
- if (flags.find('g') != notFound)
- m_flagBits |= Global;
- if (flags.find('i') != notFound)
- m_flagBits |= IgnoreCase;
- if (flags.find('m') != notFound)
- m_flagBits |= Multiline;
- }
-
m_state = compile(globalData);
}
@@ -70,7 +91,7 @@ RegExp::~RegExp()
{
}
-PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patternString, const UString& flags)
+PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags)
{
RefPtr<RegExp> res = adoptRef(new RegExp(globalData, patternString, flags));
#if ENABLE(REGEXP_TRACING)
diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h
index d99befb..000c33a 100644
--- a/Source/JavaScriptCore/runtime/RegExp.h
+++ b/Source/JavaScriptCore/runtime/RegExp.h
@@ -24,6 +24,7 @@
#include "UString.h"
#include "ExecutableAllocator.h"
+#include "RegExpKey.h"
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
@@ -32,18 +33,20 @@ namespace JSC {
struct RegExpRepresentation;
class JSGlobalData;
+ RegExpFlags regExpFlags(const UString&);
+
class RegExp : public RefCounted<RegExp> {
public:
- static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags);
+ static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, RegExpFlags);
~RegExp();
- bool global() const { return m_flagBits & Global; }
- bool ignoreCase() const { return m_flagBits & IgnoreCase; }
- bool multiline() const { return m_flagBits & Multiline; }
+ bool global() const { return m_flags & FlagGlobal; }
+ bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
+ bool multiline() const { return m_flags & FlagMultiline; }
const UString& pattern() const { return m_patternString; }
- bool isValid() const { return !m_constructionError; }
+ bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
const char* errorMessage() const { return m_constructionError; }
int match(const UString&, int startOffset, Vector<int, 32>* ovector = 0);
@@ -54,7 +57,7 @@ namespace JSC {
#endif
private:
- RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags);
+ RegExp(JSGlobalData* globalData, const UString& pattern, RegExpFlags);
enum RegExpState {
ParseError,
@@ -68,9 +71,8 @@ namespace JSC {
void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult);
#endif
- enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 };
UString m_patternString;
- int m_flagBits;
+ RegExpFlags m_flags;
const char* m_constructionError;
unsigned m_numSubpatterns;
#if ENABLE(REGEXP_TRACING)
diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp
index d101758..c96b047 100644
--- a/Source/JavaScriptCore/runtime/RegExpCache.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp
@@ -31,7 +31,7 @@
namespace JSC {
-PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, const UString& flags)
+PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags flags)
{
if (patternString.length() < maxCacheablePatternLength) {
pair<RegExpCacheMap::iterator, bool> result = m_cacheMap.add(RegExpKey(flags, patternString), 0);
@@ -43,7 +43,7 @@ PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, con
return create(patternString, flags, m_cacheMap.end());
}
-PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UString& flags, RegExpCacheMap::iterator iterator)
+PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, RegExpFlags flags, RegExpCacheMap::iterator iterator)
{
RefPtr<RegExp> regExp = RegExp::create(m_globalData, patternString, flags);
diff --git a/Source/JavaScriptCore/runtime/RegExpCache.h b/Source/JavaScriptCore/runtime/RegExpCache.h
index b5b637f..b4a6ae5 100644
--- a/Source/JavaScriptCore/runtime/RegExpCache.h
+++ b/Source/JavaScriptCore/runtime/RegExpCache.h
@@ -41,8 +41,8 @@ class RegExpCache {
typedef HashMap<RegExpKey, RefPtr<RegExp> > RegExpCacheMap;
public:
- PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, const UString& flags);
- PassRefPtr<RegExp> create(const UString& patternString, const UString& flags, RegExpCacheMap::iterator iterator);
+ PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, RegExpFlags);
+ PassRefPtr<RegExp> create(const UString& patternString, RegExpFlags, RegExpCacheMap::iterator);
RegExpCache(JSGlobalData* globalData);
private:
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index 1b30514..3da0198 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -67,7 +67,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
-const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable };
+const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::regExpConstructorTable };
/* Source for RegExpConstructor.lut.h
@begin regExpConstructorTable
@@ -95,10 +95,12 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info,
@end
*/
-RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
+RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "RegExp"))
, d(adoptPtr(new RegExpConstructorPrivate))
{
+ ASSERT(inherits(&s_info));
+
// ECMA 15.10.5.1 RegExp.prototype
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
@@ -107,7 +109,7 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObje
}
RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
- : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1, CreateInitialized)
+ : JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1, CreateInitialized)
{
RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
d->input = data->lastInput;
@@ -289,32 +291,42 @@ void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValu
{
asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec));
}
-
+
// ECMA 15.10.4
-JSObject* constructRegExp(ExecState* exec, const ArgList& args)
+JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
{
JSValue arg0 = args.at(0);
JSValue arg1 = args.at(1);
- if (arg0.inherits(&RegExpObject::info)) {
+ if (arg0.inherits(&RegExpObject::s_info)) {
if (!arg1.isUndefined())
return throwError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
return asObject(arg0);
}
UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
- UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
+ if (exec->hadException())
+ return 0;
+
+ RegExpFlags flags = NoFlags;
+ if (!arg1.isUndefined()) {
+ flags = regExpFlags(arg1.toString(exec));
+ if (exec->hadException())
+ return 0;
+ if (flags == InvalidFlags)
+ return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
+ }
RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
if (!regExp->isValid())
return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
- return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
+ return new (exec) RegExpObject(exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp.release());
}
static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
{
ArgList args(exec);
- return JSValue::encode(constructRegExp(exec, args));
+ return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
}
ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
@@ -327,7 +339,7 @@ ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec)
{
ArgList args(exec);
- return JSValue::encode(constructRegExp(exec, args));
+ return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
}
CallType RegExpConstructor::getCallData(CallData& callData)
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h
index 1714bd3..548664e 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h
@@ -57,18 +57,18 @@ namespace JSC {
class RegExpConstructor : public InternalFunction {
public:
- RegExpConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, RegExpPrototype*);
+ RegExpConstructor(ExecState*, JSGlobalObject*, Structure*, RegExpPrototype*);
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
- static const ClassInfo info;
+ static const ClassInfo s_info;
void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
JSObject* arrayOfMatches(ExecState*) const;
@@ -91,18 +91,16 @@ namespace JSC {
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
- virtual const ClassInfo* classInfo() const { return &info; }
-
OwnPtr<RegExpConstructorPrivate> d;
};
RegExpConstructor* asRegExpConstructor(JSValue);
- JSObject* constructRegExp(ExecState*, const ArgList&);
+ JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&);
inline RegExpConstructor* asRegExpConstructor(JSValue value)
{
- ASSERT(asObject(value)->inherits(&RegExpConstructor::info));
+ ASSERT(asObject(value)->inherits(&RegExpConstructor::s_info));
return static_cast<RegExpConstructor*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/RegExpKey.h b/Source/JavaScriptCore/runtime/RegExpKey.h
index cd1368d..b4847f9 100644
--- a/Source/JavaScriptCore/runtime/RegExpKey.h
+++ b/Source/JavaScriptCore/runtime/RegExpKey.h
@@ -25,63 +25,54 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "UString.h"
-#include <wtf/text/StringHash.h>
-
#ifndef RegExpKey_h
#define RegExpKey_h
+#include "UString.h"
+#include <wtf/text/StringHash.h>
+
namespace JSC {
+enum RegExpFlags {
+ NoFlags = 0,
+ FlagGlobal = 1,
+ FlagIgnoreCase = 2,
+ FlagMultiline = 4,
+ InvalidFlags = 8,
+ DeletedValueFlags = -1
+};
+
struct RegExpKey {
- int flagsValue;
+ RegExpFlags flagsValue;
RefPtr<StringImpl> pattern;
RegExpKey()
- : flagsValue(0)
+ : flagsValue(NoFlags)
{
}
- RegExpKey(int flags)
+ RegExpKey(RegExpFlags flags)
: flagsValue(flags)
{
}
- RegExpKey(int flags, const UString& pattern)
+ RegExpKey(RegExpFlags flags, const UString& pattern)
: flagsValue(flags)
, pattern(pattern.impl())
{
}
- RegExpKey(int flags, const PassRefPtr<StringImpl> pattern)
+ RegExpKey(RegExpFlags flags, const PassRefPtr<StringImpl> pattern)
: flagsValue(flags)
, pattern(pattern)
{
}
- RegExpKey(int flags, const RefPtr<StringImpl>& pattern)
+ RegExpKey(RegExpFlags flags, const RefPtr<StringImpl>& pattern)
: flagsValue(flags)
, pattern(pattern)
{
}
-
- RegExpKey(const UString& flags, const UString& pattern)
- : pattern(pattern.impl())
- {
- flagsValue = getFlagsValue(flags);
- }
-
- int getFlagsValue(const UString flags)
- {
- flagsValue = 0;
- if (flags.find('g') != notFound)
- flagsValue += 4;
- if (flags.find('i') != notFound)
- flagsValue += 2;
- if (flags.find('m') != notFound)
- flagsValue += 1;
- return flagsValue;
- }
};
inline bool operator==(const RegExpKey& a, const RegExpKey& b)
@@ -112,8 +103,8 @@ template<> struct DefaultHash<JSC::RegExpKey> {
};
template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> {
- static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = -1; }
- static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == -1; }
+ static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; }
+ static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; }
};
} // namespace WTF
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index b969e38..d824ecd 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -49,7 +49,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
-const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
+const ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_info, 0, ExecState::regExpTable };
/* Source for RegExpObject.lut.h
@begin regExpTable
@@ -61,16 +61,24 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
@end
*/
-RegExpObject::RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp)
+RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, NonNullPassRefPtr<RegExp> regExp)
: JSObjectWithGlobalObject(globalObject, structure)
- , d(adoptPtr(new RegExpObjectData(regExp, 0)))
+ , d(adoptPtr(new RegExpObjectData(regExp)))
{
+ ASSERT(inherits(&s_info));
}
RegExpObject::~RegExpObject()
{
}
+void RegExpObject::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+ if (UNLIKELY(!d->lastIndex.get().isInt32()))
+ markStack.append(&d->lastIndex);
+}
+
bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
@@ -103,7 +111,7 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&)
{
- return jsNumber(asRegExpObject(slotBase)->lastIndex());
+ return asRegExpObject(slotBase)->getLastIndex();
}
void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
@@ -113,7 +121,7 @@ void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue
void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
{
- asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec));
+ asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value);
}
JSValue RegExpObject::test(ExecState* exec)
@@ -132,12 +140,7 @@ JSValue RegExpObject::exec(ExecState* exec)
bool RegExpObject::match(ExecState* exec)
{
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
-
- UString input = !exec->argumentCount() ? regExpConstructor->input() : exec->argument(0).toString(exec);
- if (input.isNull()) {
- throwError(exec, createError(exec, makeUString("No input to ", toString(exec), ".")));
- return false;
- }
+ UString input = exec->argument(0).toString(exec);
if (!regExp()->global()) {
int position;
@@ -146,20 +149,32 @@ bool RegExpObject::match(ExecState* exec)
return position >= 0;
}
- if (d->lastIndex < 0 || d->lastIndex > input.length()) {
- d->lastIndex = 0;
- return false;
+ JSValue jsLastIndex = getLastIndex();
+ unsigned lastIndex;
+ if (LIKELY(jsLastIndex.isUInt32())) {
+ lastIndex = jsLastIndex.asUInt32();
+ if (lastIndex > input.length()) {
+ setLastIndex(0);
+ return false;
+ }
+ } else {
+ double doubleLastIndex = jsLastIndex.toInteger(exec);
+ if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
+ setLastIndex(0);
+ return false;
+ }
+ lastIndex = static_cast<unsigned>(doubleLastIndex);
}
int position;
int length = 0;
- regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length);
+ regExpConstructor->performMatch(d->regExp.get(), input, lastIndex, position, length);
if (position < 0) {
- d->lastIndex = 0;
+ setLastIndex(0);
return false;
}
- d->lastIndex = position + length;
+ setLastIndex(position + length);
return true;
}
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index 99c84da..4274fff 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -28,14 +28,26 @@ namespace JSC {
class RegExpObject : public JSObjectWithGlobalObject {
public:
- RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>);
+ typedef JSObjectWithGlobalObject Base;
+
+ RegExpObject(JSGlobalObject*, Structure*, NonNullPassRefPtr<RegExp>);
virtual ~RegExpObject();
void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; }
RegExp* regExp() const { return d->regExp.get(); }
- void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; }
- double lastIndex() const { return d->lastIndex; }
+ void setLastIndex(size_t lastIndex)
+ {
+ d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+ }
+ void setLastIndex(JSGlobalData& globalData, JSValue lastIndex)
+ {
+ d->lastIndex.set(globalData, this, lastIndex);
+ }
+ JSValue getLastIndex() const
+ {
+ return d->lastIndex.get();
+ }
JSValue test(ExecState*);
JSValue exec(ExecState*);
@@ -44,33 +56,34 @@ namespace JSC {
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static JS_EXPORTDATA const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo s_info;
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
- static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags;
-
+ static const unsigned StructureFlags = OverridesMarkChildren | OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags;
+
private:
+ virtual void markChildren(MarkStack&);
+
bool match(ExecState*);
struct RegExpObjectData {
WTF_MAKE_FAST_ALLOCATED;
public:
- RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex)
+ RegExpObjectData(NonNullPassRefPtr<RegExp> regExp)
: regExp(regExp)
- , lastIndex(lastIndex)
{
+ lastIndex.setWithoutWriteBarrier(jsNumber(0));
}
RefPtr<RegExp> regExp;
- double lastIndex;
+ WriteBarrier<Unknown> lastIndex;
};
-#if PLATFORM(WIN)
+#if COMPILER(MSVC)
friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*);
#endif
OwnPtr<RegExpObjectData> d;
@@ -80,7 +93,7 @@ namespace JSC {
inline RegExpObject* asRegExpObject(JSValue value)
{
- ASSERT(asObject(value)->inherits(&RegExpObject::info));
+ ASSERT(asObject(value)->inherits(&RegExpObject::s_info));
return static_cast<RegExpObject*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
index a7c447d..5bb8ad8 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -30,7 +30,6 @@
#include "JSStringBuilder.h"
#include "JSValue.h"
#include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
#include "RegExpObject.h"
#include "RegExp.h"
#include "RegExpCache.h"
@@ -48,13 +47,13 @@ static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*);
// ECMA 15.10.5
-RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
- : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", ""))
+RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure)
+ : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", NoFlags))
{
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
}
// ------------------------------ Functions ---------------------------
@@ -62,7 +61,7 @@ RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject,
EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&RegExpObject::info))
+ if (!thisValue.inherits(&RegExpObject::s_info))
return throwVMTypeError(exec);
return JSValue::encode(asRegExpObject(thisValue)->test(exec));
}
@@ -70,7 +69,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec)
EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&RegExpObject::info))
+ if (!thisValue.inherits(&RegExpObject::s_info))
return throwVMTypeError(exec);
return JSValue::encode(asRegExpObject(thisValue)->exec(exec));
}
@@ -78,20 +77,30 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&RegExpObject::info))
+ if (!thisValue.inherits(&RegExpObject::s_info))
return throwVMTypeError(exec);
RefPtr<RegExp> regExp;
JSValue arg0 = exec->argument(0);
JSValue arg1 = exec->argument(1);
- if (arg0.inherits(&RegExpObject::info)) {
+ if (arg0.inherits(&RegExpObject::s_info)) {
if (!arg1.isUndefined())
return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
regExp = asRegExpObject(arg0)->regExp();
} else {
UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec);
- UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+
+ RegExpFlags flags = NoFlags;
+ if (!arg1.isUndefined()) {
+ flags = regExpFlags(arg1.toString(exec));
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ if (flags == InvalidFlags)
+ return throwVMError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
+ }
regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
}
@@ -106,8 +115,8 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.inherits(&RegExpObject::info)) {
- if (thisValue.inherits(&RegExpPrototype::info))
+ if (!thisValue.inherits(&RegExpObject::s_info)) {
+ if (thisValue.inherits(&RegExpPrototype::s_info))
return JSValue::encode(jsNontrivialString(exec, "//"));
return throwVMTypeError(exec);
}
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.h b/Source/JavaScriptCore/runtime/RegExpPrototype.h
index eb4ae00..2cc5405 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.h
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.h
@@ -28,7 +28,7 @@ namespace JSC {
class RegExpPrototype : public RegExpObject {
public:
- RegExpPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ RegExpPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.cpp b/Source/JavaScriptCore/runtime/ScopeChain.cpp
index 976cff6..026d729 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.cpp
+++ b/Source/JavaScriptCore/runtime/ScopeChain.cpp
@@ -31,16 +31,16 @@ namespace JSC {
#ifndef NDEBUG
-void ScopeChainNode::print() const
+void ScopeChainNode::print()
{
ScopeChainIterator scopeEnd = end();
for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
- DeprecatedPtr<JSObject> o = *scopeIter;
+ JSObject* o = scopeIter->get();
PropertyNameArray propertyNames(globalObject->globalExec());
o->getPropertyNames(globalObject->globalExec(), propertyNames);
PropertyNameArray::const_iterator propEnd = propertyNames.end();
- fprintf(stderr, "----- [scope %p] -----\n", o.get());
+ fprintf(stderr, "----- [scope %p] -----\n", o);
for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
Identifier name = *propIter;
fprintf(stderr, "%s, ", name.ustring().utf8().data());
@@ -51,12 +51,14 @@ void ScopeChainNode::print() const
#endif
-int ScopeChain::localDepth() const
+const ClassInfo ScopeChainNode::s_info = { "ScopeChainNode", 0, 0, 0 };
+
+int ScopeChainNode::localDepth()
{
int scopeDepth = 0;
ScopeChainIterator iter = this->begin();
ScopeChainIterator end = this->end();
- while (!(*iter)->inherits(&JSActivation::info)) {
+ while (!(*iter)->inherits(&JSActivation::s_info)) {
++iter;
if (iter == end)
break;
@@ -65,4 +67,13 @@ int ScopeChain::localDepth() const
return scopeDepth;
}
+void ScopeChainNode::markChildren(MarkStack& markStack)
+{
+ if (next)
+ markStack.append(&next);
+ markStack.append(&object);
+ markStack.append(&globalObject);
+ markStack.append(&globalThis);
+}
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h
index 11f3692..d0a2672 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.h
+++ b/Source/JavaScriptCore/runtime/ScopeChain.h
@@ -21,7 +21,8 @@
#ifndef ScopeChain_h
#define ScopeChain_h
-#include "WriteBarrier.h"
+#include "JSCell.h"
+#include "Structure.h"
#include <wtf/FastAllocBase.h>
namespace JSC {
@@ -32,109 +33,68 @@ namespace JSC {
class MarkStack;
class ScopeChainIterator;
- class ScopeChainNode {
- WTF_MAKE_FAST_ALLOCATED;
+ class ScopeChainNode : public JSCell {
public:
ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
- : next(next)
- , object(object)
+ : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
, globalData(globalData)
- , globalObject(globalObject)
- , globalThis(globalThis)
- , refCount(1)
+ , next(*globalData, this, next)
+ , object(*globalData, this, object)
+ , globalObject(*globalData, this, globalObject)
+ , globalThis(*globalData, this, globalThis)
{
ASSERT(globalData);
ASSERT(globalObject);
}
-#ifndef NDEBUG
- // Due to the number of subtle and timing dependent bugs that have occurred due
- // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the
- // contents in debug builds.
- ~ScopeChainNode()
- {
- next = 0;
- globalData = 0;
- globalObject = 0;
- globalThis = 0;
- }
-#endif
- ScopeChainNode* next;
- DeprecatedPtr<JSObject> object;
JSGlobalData* globalData;
- JSGlobalObject* globalObject;
- JSObject* globalThis;
- int refCount;
-
- void deref() { ASSERT(refCount); if (--refCount == 0) { release();} }
- void ref() { ASSERT(refCount); ++refCount; }
- void release();
-
- // Before calling "push" on a bare ScopeChainNode, a client should
- // logically "copy" the node. Later, the client can "deref" the head
- // of its chain of ScopeChainNodes to reclaim all the nodes it added
- // after the logical copy, leaving nodes added before the logical copy
- // (nodes shared with other clients) untouched.
- ScopeChainNode* copy()
- {
- ref();
- return this;
- }
+ WriteBarrier<ScopeChainNode> next;
+ WriteBarrier<JSObject> object;
+ WriteBarrier<JSGlobalObject> globalObject;
+ WriteBarrier<JSObject> globalThis;
ScopeChainNode* push(JSObject*);
ScopeChainNode* pop();
- ScopeChainIterator begin() const;
- ScopeChainIterator end() const;
+ ScopeChainIterator begin();
+ ScopeChainIterator end();
+
+ int localDepth();
#ifndef NDEBUG
- void print() const;
+ void print();
#endif
+
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
+ virtual void markChildren(MarkStack&);
+ private:
+ static const unsigned StructureFlags = OverridesMarkChildren;
+ static const ClassInfo s_info;
};
inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
{
ASSERT(o);
- return new ScopeChainNode(this, o, globalData, globalObject, globalThis);
+ return new (globalData) ScopeChainNode(this, o, globalData, globalObject.get(), globalThis.get());
}
inline ScopeChainNode* ScopeChainNode::pop()
{
ASSERT(next);
- ScopeChainNode* result = next;
-
- if (--refCount != 0)
- ++result->refCount;
- else
- delete this;
-
- return result;
- }
-
- inline void ScopeChainNode::release()
- {
- // This function is only called by deref(),
- // Deref ensures these conditions are true.
- ASSERT(refCount == 0);
- ScopeChainNode* n = this;
- do {
- ScopeChainNode* next = n->next;
- delete n;
- n = next;
- } while (n && --n->refCount == 0);
+ return next.get();
}
class ScopeChainIterator {
public:
- ScopeChainIterator(const ScopeChainNode* node)
+ ScopeChainIterator(ScopeChainNode* node)
: m_node(node)
{
}
- DeprecatedPtr<JSObject> const & operator*() const { return m_node->object; }
- DeprecatedPtr<JSObject> const * operator->() const { return &(operator*()); }
+ WriteBarrier<JSObject> const & operator*() const { return m_node->object; }
+ WriteBarrier<JSObject> const * operator->() const { return &(operator*()); }
- ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
+ ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; }
// postfix ++ intentionally omitted
@@ -142,99 +102,43 @@ namespace JSC {
bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
private:
- const ScopeChainNode* m_node;
+ ScopeChainNode* m_node;
};
- inline ScopeChainIterator ScopeChainNode::begin() const
+ inline ScopeChainIterator ScopeChainNode::begin()
{
return ScopeChainIterator(this);
}
- inline ScopeChainIterator ScopeChainNode::end() const
+ inline ScopeChainIterator ScopeChainNode::end()
{
return ScopeChainIterator(0);
}
- class NoScopeChain {};
-
- class ScopeChain {
- friend class JIT;
- public:
- ScopeChain(NoScopeChain)
- : m_node(0)
- {
- }
-
- ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
- : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis))
- {
- }
-
- ScopeChain(const ScopeChain& c)
- : m_node(c.m_node->copy())
- {
- }
-
- ScopeChain& operator=(const ScopeChain& c);
-
- explicit ScopeChain(ScopeChainNode* node)
- : m_node(node->copy())
- {
- }
-
- ~ScopeChain()
- {
- if (m_node)
- m_node->deref();
-#ifndef NDEBUG
- m_node = 0;
-#endif
- }
-
- void swap(ScopeChain&);
-
- ScopeChainNode* node() const { return m_node; }
-
- JSObject* top() const { return m_node->object.get(); }
-
- ScopeChainIterator begin() const { return m_node->begin(); }
- ScopeChainIterator end() const { return m_node->end(); }
-
- void push(JSObject* o) { m_node = m_node->push(o); }
-
- void pop() { m_node = m_node->pop(); }
- void clear() { m_node->deref(); m_node = 0; }
-
- JSGlobalObject* globalObject() const { return m_node->globalObject; }
-
- void markAggregate(MarkStack&) const;
-
- // Caution: this should only be used if the codeblock this is being used
- // with needs a full scope chain, otherwise this returns the depth of
- // the preceeding call frame
- //
- // Returns the depth of the current call frame's scope chain
- int localDepth() const;
-
-#ifndef NDEBUG
- void print() const { m_node->print(); }
-#endif
-
- private:
- ScopeChainNode* m_node;
- };
-
- inline void ScopeChain::swap(ScopeChain& o)
+ ALWAYS_INLINE JSGlobalData& ExecState::globalData() const
{
- ScopeChainNode* tmp = m_node;
- m_node = o.m_node;
- o.m_node = tmp;
+ ASSERT(scopeChain()->globalData);
+ return *scopeChain()->globalData;
}
- inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
+ ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const
+ {
+ return scopeChain()->globalObject.get();
+ }
+
+ ALWAYS_INLINE JSObject* ExecState::globalThisValue() const
+ {
+ return scopeChain()->globalThis.get();
+ }
+
+ ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
+ {
+ return static_cast<ScopeChainNode*>(jsValue().asCell());
+ }
+
+ ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
{
- ScopeChain tmp(c);
- swap(tmp);
+ *this = JSValue(scopeChain);
return *this;
}
diff --git a/Source/JavaScriptCore/runtime/ScopeChainMark.h b/Source/JavaScriptCore/runtime/ScopeChainMark.h
index faa4824..35701f1 100644
--- a/Source/JavaScriptCore/runtime/ScopeChainMark.h
+++ b/Source/JavaScriptCore/runtime/ScopeChainMark.h
@@ -25,12 +25,6 @@
namespace JSC {
- inline void ScopeChain::markAggregate(MarkStack& markStack) const
- {
- for (ScopeChainNode* n = m_node; n; n = n->next)
- markStack.append(&n->object);
- }
-
} // namespace JSC
#endif // ScopeChainMark_h
diff --git a/Source/JavaScriptCore/runtime/SmallStrings.cpp b/Source/JavaScriptCore/runtime/SmallStrings.cpp
index 9b193f5..ac67020 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.cpp
+++ b/Source/JavaScriptCore/runtime/SmallStrings.cpp
@@ -33,8 +33,6 @@
namespace JSC {
-static const unsigned numCharactersToStore = 0x100;
-
static inline bool isMarked(JSCell* string)
{
return string && Heap::isMarked(string);
@@ -45,17 +43,22 @@ class SmallStringsStorage {
public:
SmallStringsStorage();
- StringImpl* rep(unsigned char character) { return m_reps[character].get(); }
+ StringImpl* rep(unsigned char character)
+ {
+ return m_reps[character].get();
+ }
private:
- RefPtr<StringImpl> m_reps[numCharactersToStore];
+ static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
+
+ RefPtr<StringImpl> m_reps[singleCharacterStringCount];
};
SmallStringsStorage::SmallStringsStorage()
{
UChar* characterBuffer = 0;
- RefPtr<StringImpl> baseString = StringImpl::createUninitialized(numCharactersToStore, characterBuffer);
- for (unsigned i = 0; i < numCharactersToStore; ++i) {
+ RefPtr<StringImpl> baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer);
+ for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
characterBuffer[i] = i;
m_reps[i] = StringImpl::create(baseString, i, 1);
}
@@ -63,7 +66,7 @@ SmallStringsStorage::SmallStringsStorage()
SmallStrings::SmallStrings()
{
- COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
+ COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
clear();
}
@@ -71,7 +74,7 @@ SmallStrings::~SmallStrings()
{
}
-void SmallStrings::markChildren(MarkStack& markStack)
+void SmallStrings::markChildren(HeapRootMarker& heapRootMarker)
{
/*
Our hypothesis is that small strings are very common. So, we cache them
@@ -83,9 +86,9 @@ void SmallStrings::markChildren(MarkStack& markStack)
so, it's probably reasonable to mark the rest. If not, we clear the cache.
*/
- bool isAnyStringMarked = isMarked(m_emptyString.get());
- for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i)
- isAnyStringMarked = isMarked(m_singleCharacterStrings[i].get());
+ bool isAnyStringMarked = isMarked(m_emptyString);
+ for (unsigned i = 0; i < singleCharacterStringCount && !isAnyStringMarked; ++i)
+ isAnyStringMarked = isMarked(m_singleCharacterStrings[i]);
if (!isAnyStringMarked) {
clear();
@@ -93,17 +96,17 @@ void SmallStrings::markChildren(MarkStack& markStack)
}
if (m_emptyString)
- markStack.append(&m_emptyString);
- for (unsigned i = 0; i < numCharactersToStore; ++i) {
+ heapRootMarker.mark(&m_emptyString);
+ for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
if (m_singleCharacterStrings[i])
- markStack.append(&m_singleCharacterStrings[i]);
+ heapRootMarker.mark(&m_singleCharacterStrings[i]);
}
}
void SmallStrings::clear()
{
m_emptyString = 0;
- for (unsigned i = 0; i < numCharactersToStore; ++i)
+ for (unsigned i = 0; i < singleCharacterStringCount; ++i)
m_singleCharacterStrings[i] = 0;
}
@@ -112,7 +115,7 @@ unsigned SmallStrings::count() const
unsigned count = 0;
if (m_emptyString)
++count;
- for (unsigned i = 0; i < numCharactersToStore; ++i) {
+ for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
if (m_singleCharacterStrings[i])
++count;
}
diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h
index ee795b6..b54d020 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.h
+++ b/Source/JavaScriptCore/runtime/SmallStrings.h
@@ -33,13 +33,16 @@
namespace JSC {
+ class HeapRootMarker;
class JSGlobalData;
class JSString;
class MarkStack;
class SmallStringsStorage;
+ static const unsigned maxSingleCharacterString = 0xFF;
+
class SmallStrings {
- WTF_MAKE_NONCOPYABLE(SmallStrings); WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(SmallStrings);
public:
SmallStrings();
~SmallStrings();
@@ -48,30 +51,33 @@ namespace JSC {
{
if (!m_emptyString)
createEmptyString(globalData);
- return m_emptyString.get();
+ return m_emptyString;
}
+
JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
{
if (!m_singleCharacterStrings[character])
createSingleCharacterString(globalData, character);
- return m_singleCharacterStrings[character].get();
+ return m_singleCharacterStrings[character];
}
StringImpl* singleCharacterStringRep(unsigned char character);
- void markChildren(MarkStack&);
+ void markChildren(HeapRootMarker&);
void clear();
unsigned count() const;
-#if ENABLE(JIT)
- JSCell** singleCharacterStrings() { return m_singleCharacterStrings[0].slot(); }
-#endif
+
+ JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
+
private:
+ static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
+
void createEmptyString(JSGlobalData*);
void createSingleCharacterString(JSGlobalData*, unsigned char);
- DeprecatedPtr<JSString> m_emptyString;
- FixedArray<DeprecatedPtr<JSString>, 0x100> m_singleCharacterStrings;
+ JSString* m_emptyString;
+ JSString* m_singleCharacterStrings[singleCharacterStringCount];
OwnPtr<SmallStringsStorage> m_storage;
};
diff --git a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
index 5bb013b..e666dee 100644
--- a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
+++ b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
@@ -29,7 +29,7 @@
namespace JSC {
StrictEvalActivation::StrictEvalActivation(ExecState* exec)
- : JSObject(exec->globalData().strictEvalActivationStructure)
+ : JSNonFinalObject(exec->globalData(), exec->globalData().strictEvalActivationStructure.get())
{
}
diff --git a/Source/JavaScriptCore/runtime/StrictEvalActivation.h b/Source/JavaScriptCore/runtime/StrictEvalActivation.h
index 1385eec..e2885cc 100644
--- a/Source/JavaScriptCore/runtime/StrictEvalActivation.h
+++ b/Source/JavaScriptCore/runtime/StrictEvalActivation.h
@@ -30,7 +30,7 @@
namespace JSC {
-class StrictEvalActivation : public JSObject {
+class StrictEvalActivation : public JSNonFinalObject {
public:
StrictEvalActivation(ExecState*);
virtual bool deleteProperty(ExecState*, const Identifier&);
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp
index 604473b..560202a 100644
--- a/Source/JavaScriptCore/runtime/StringConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp
@@ -25,7 +25,6 @@
#include "JITCode.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
-#include "PrototypeFunction.h"
#include "StringPrototype.h"
namespace JSC {
@@ -49,7 +48,7 @@ static EncodedJSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec)
ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
-StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype)
+StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure, StringPrototype* stringPrototype)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, stringPrototype->classInfo()->className))
{
// ECMA 15.5.3.1 String.prototype
@@ -57,9 +56,9 @@ StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObje
// ECMA 15.5.3.2 fromCharCode()
#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, exec->globalData().getHostFunction(stringFromCharCode, fromCharCodeThunkGenerator)), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().fromCharCode, exec->globalData().getHostFunction(stringFromCharCode, fromCharCodeThunkGenerator)), DontEnum);
#else
- putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum);
#endif
// no. of arguments for constructor
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
@@ -68,9 +67,10 @@ StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObje
// ECMA 15.5.2
static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* exec)
{
+ JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
if (!exec->argumentCount())
- return JSValue::encode(new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure()));
- return JSValue::encode(new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), exec->argument(0).toString(exec)));
+ return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure()));
+ return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec)));
}
ConstructType StringConstructor::getConstructData(ConstructData& constructData)
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.h b/Source/JavaScriptCore/runtime/StringConstructor.h
index 20f3a52..117cce8 100644
--- a/Source/JavaScriptCore/runtime/StringConstructor.h
+++ b/Source/JavaScriptCore/runtime/StringConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class StringConstructor : public InternalFunction {
public:
- StringConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*);
+ StringConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure, StringPrototype*);
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp
index eb9cfa3..67dc291 100644
--- a/Source/JavaScriptCore/runtime/StringObject.cpp
+++ b/Source/JavaScriptCore/runtime/StringObject.cpp
@@ -27,23 +27,26 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(StringObject);
-const ClassInfo StringObject::info = { "String", 0, 0, 0 };
+const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0 };
-StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
+StringObject::StringObject(ExecState* exec, Structure* structure)
: JSWrapperObject(exec->globalData(), structure)
{
+ ASSERT(inherits(&s_info));
setInternalValue(exec->globalData(), jsEmptyString(exec));
}
-StringObject::StringObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, JSString* string)
+StringObject::StringObject(JSGlobalData& globalData, Structure* structure, JSString* string)
: JSWrapperObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
setInternalValue(globalData, string);
}
-StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
+StringObject::StringObject(ExecState* exec, Structure* structure, const UString& string)
: JSWrapperObject(exec->globalData(), structure)
{
+ ASSERT(inherits(&s_info));
setInternalValue(exec->globalData(), jsString(exec, string));
}
diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h
index 03488f5..4c16044 100644
--- a/Source/JavaScriptCore/runtime/StringObject.h
+++ b/Source/JavaScriptCore/runtime/StringObject.h
@@ -28,10 +28,10 @@ namespace JSC {
class StringObject : public JSWrapperObject {
public:
- StringObject(ExecState*, NonNullPassRefPtr<Structure>);
- StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&);
+ StringObject(ExecState*, Structure*);
+ StringObject(ExecState*, Structure*, const UString&);
- static StringObject* create(ExecState*, JSString*);
+ static StringObject* create(ExecState*, JSGlobalObject*, JSString*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
@@ -41,26 +41,25 @@ namespace JSC {
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const JS_EXPORTDATA ClassInfo info;
+ static const JS_EXPORTDATA ClassInfo s_info;
JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
- static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
- StringObject(JSGlobalData&, NonNullPassRefPtr<Structure>, JSString*);
- };
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
+ StringObject(JSGlobalData&, Structure*, JSString*);
+ };
StringObject* asStringObject(JSValue);
inline StringObject* asStringObject(JSValue value)
{
- ASSERT(asObject(value)->inherits(&StringObject::info));
+ ASSERT(asObject(value)->inherits(&StringObject::s_info));
return static_cast<StringObject*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
index 43c3e38..3133944 100644
--- a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
+++ b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
@@ -33,18 +33,18 @@ namespace JSC {
static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string)
{
return new (exec) StringObjectThatMasqueradesAsUndefined(exec,
- createStructure(exec->lexicalGlobalObject()->stringPrototype()), string);
+ createStructure(exec->globalData(), exec->lexicalGlobalObject()->stringPrototype()), string);
}
private:
- StringObjectThatMasqueradesAsUndefined(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
+ StringObjectThatMasqueradesAsUndefined(ExecState* exec, Structure* structure, const UString& string)
: StringObject(exec, structure, string)
{
}
- static PassRefPtr<Structure> createStructure(JSValue proto)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags;
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 545c93e..91112a5 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -85,7 +85,7 @@ static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*);
namespace JSC {
-const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, ExecState::stringTable };
+const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, ExecState::stringTable };
/* Source for StringPrototype.lut.h
@begin stringTable 26
@@ -131,9 +131,11 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec
*/
// ECMA 15.5.4
-StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
+StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
: StringObject(exec, structure)
{
+ ASSERT(inherits(&s_info));
+
putAnonymousValue(exec->globalData(), 0, globalObject);
// The constructor will be added later, after StringConstructor has been built
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
@@ -305,7 +307,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec)
if (callType == CallTypeNone)
replacementString = replacement.toString(exec);
- if (pattern.inherits(&RegExpObject::info)) {
+ if (pattern.inherits(&RegExpObject::s_info)) {
const UString& source = sourceVal->value(exec);
unsigned sourceLen = source.length();
if (exec->hadException())
@@ -473,7 +475,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec)
if (thisValue.isString())
return JSValue::encode(thisValue);
- if (thisValue.inherits(&StringObject::info))
+ if (thisValue.inherits(&StringObject::s_info))
return JSValue::encode(asStringObject(thisValue)->internalValue());
return throwVMTypeError(exec);
@@ -602,10 +604,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
JSValue a0 = exec->argument(0);
- UString u = s;
RefPtr<RegExp> reg;
- RegExpObject* imp = 0;
- if (a0.inherits(&RegExpObject::info))
+ if (a0.inherits(&RegExpObject::s_info))
reg = asRegExpObject(a0)->regExp();
else {
/*
@@ -613,12 +613,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString());
+ reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), NoFlags);
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
int matchLength = 0;
- regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
+ regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength);
if (!(reg->global())) {
// case without 'g' flag is handled like RegExp.prototype.exec
if (pos < 0)
@@ -628,15 +628,13 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
// return array of matches
MarkedArgumentBuffer list;
- int lastIndex = 0;
+ unsigned lastIndex = 0;
while (pos >= 0) {
- list.append(jsSubstring(exec, u, pos, matchLength));
+ list.append(jsSubstring(exec, s, pos, matchLength));
lastIndex = pos;
pos += matchLength == 0 ? 1 : matchLength;
- regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength);
+ regExpConstructor->performMatch(reg.get(), s, pos, pos, matchLength);
}
- if (imp)
- imp->setLastIndex(lastIndex);
if (list.isEmpty()) {
// if there are no matches at all, it's important to return
// Null instead of an empty array, because this matches
@@ -656,9 +654,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
JSValue a0 = exec->argument(0);
- UString u = s;
RefPtr<RegExp> reg;
- if (a0.inherits(&RegExpObject::info))
+ if (a0.inherits(&RegExpObject::s_info))
reg = asRegExpObject(a0)->regExp();
else {
/*
@@ -666,12 +663,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString());
+ reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), NoFlags);
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
int matchLength = 0;
- regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
+ regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength);
return JSValue::encode(jsNumber(pos));
}
@@ -716,7 +713,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
unsigned i = 0;
unsigned p0 = 0;
unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
- if (a0.inherits(&RegExpObject::info)) {
+ if (a0.inherits(&RegExpObject::s_info)) {
RegExp* reg = asRegExpObject(a0)->regExp();
if (s.isEmpty() && reg->match(s, 0) >= 0) {
// empty string matched by regexp -> empty array
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.h b/Source/JavaScriptCore/runtime/StringPrototype.h
index 4b0f88f..6c4b475 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.h
+++ b/Source/JavaScriptCore/runtime/StringPrototype.h
@@ -29,13 +29,23 @@ namespace JSC {
class StringPrototype : public StringObject {
public:
- StringPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>);
+ StringPrototype(ExecState*, JSGlobalObject*, Structure*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+ {
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
+ static const ClassInfo s_info;
+
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags;
+
+ COMPILE_ASSERT(!StringObject::AnonymousSlotCount, StringPrototype_stomps_on_your_anonymous_slot);
+ static const unsigned AnonymousSlotCount = 1;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index e8f5d7a..dcc8e7c 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -50,132 +50,82 @@
using namespace std;
using namespace WTF;
-namespace JSC {
-
-// Choose a number for the following so that most property maps are smaller,
-// but it's not going to blow out the stack to allocate this number of pointers.
-static const int smallMapThreshold = 1024;
-
-// The point at which the function call overhead of the qsort implementation
-// becomes small compared to the inefficiency of insertion sort.
-static const unsigned tinyMapThreshold = 20;
-
-static const unsigned newTableSize = 16;
+#if DUMP_PROPERTYMAP_STATS
-#ifndef NDEBUG
-static WTF::RefCountedLeakCounter structureCounter("Structure");
+int numProbes;
+int numCollisions;
+int numRehashes;
+int numRemoves;
-#if ENABLE(JSC_MULTIPLE_THREADS)
-static Mutex& ignoreSetMutex = *(new Mutex);
#endif
-static bool shouldIgnoreLeaks;
-static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>);
-#endif
+namespace JSC {
#if DUMP_STRUCTURE_ID_STATISTICS
static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>);
#endif
-static int comparePropertyMapEntryIndices(const void* a, const void* b);
-
-inline void Structure::setTransitionTable(TransitionTable* table)
-{
- ASSERT(m_isUsingSingleSlot);
-#ifndef NDEBUG
- setSingleTransition(0);
-#endif
- m_isUsingSingleSlot = false;
- m_transitions.m_table = table;
- // This implicitly clears the flag that indicates we're using a single transition
- ASSERT(!m_isUsingSingleSlot);
-}
-
-// The contains and get methods accept imprecise matches, so if an unspecialised transition exists
-// for the given key they will consider that transition to be a match. If a specialised transition
-// exists and it matches the provided specificValue, get will return the specific transition.
-inline bool Structure::transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
-{
- if (m_isUsingSingleSlot) {
- Structure* existingTransition = singleTransition();
- return existingTransition && existingTransition->m_nameInPrevious.get() == key.first
- && existingTransition->m_attributesInPrevious == key.second
- && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0);
- }
- TransitionTable::iterator find = transitionTable()->find(key);
- if (find == transitionTable()->end())
- return false;
-
- return find->second.first || find->second.second->transitionedFor(specificValue);
-}
-
-inline Structure* Structure::transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
+bool StructureTransitionTable::contains(StringImpl* rep, unsigned attributes) const
{
- if (m_isUsingSingleSlot) {
- Structure* existingTransition = singleTransition();
- if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first
- && existingTransition->m_attributesInPrevious == key.second
- && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0))
- return existingTransition;
- return 0;
+ if (isUsingSingleSlot()) {
+ Structure* transition = singleTransition();
+ return transition && transition->m_nameInPrevious == rep && transition->m_attributesInPrevious == attributes;
}
-
- Transition transition = transitionTable()->get(key);
- if (transition.second && transition.second->transitionedFor(specificValue))
- return transition.second;
- return transition.first;
+ return map()->contains(make_pair(rep, attributes));
}
-inline bool Structure::transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const
+inline Structure* StructureTransitionTable::get(StringImpl* rep, unsigned attributes) const
{
- if (m_isUsingSingleSlot) {
+ if (isUsingSingleSlot()) {
Structure* transition = singleTransition();
- return transition && transition->m_nameInPrevious == key.first
- && transition->m_attributesInPrevious == key.second;
+ return (transition && transition->m_nameInPrevious == rep && transition->m_attributesInPrevious == attributes) ? transition : 0;
}
- return transitionTable()->contains(key);
+ return map()->get(make_pair(rep, attributes));
}
-inline void Structure::transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
+inline void StructureTransitionTable::remove(Structure* structure)
{
- if (m_isUsingSingleSlot) {
- ASSERT(transitionTableContains(key, specificValue));
- setSingleTransition(0);
- return;
+ if (isUsingSingleSlot()) {
+ // If more than one transition had been added, then we wouldn't be in
+ // single slot mode (even despecifying a from a specific value triggers
+ // map mode).
+ // As such, the passed structure *must* be the existing transition.
+ ASSERT(singleTransition() == structure);
+ clearSingleTransition();
+ } else {
+ // Check whether a mapping exists for structure's key, and whether the
+ // entry is structure (the latter check may fail if we initially had a
+ // transition with a specific value, and this has been despecified).
+ TransitionMap::iterator entry = map()->find(make_pair(structure->m_nameInPrevious, structure->m_attributesInPrevious));
+ if (entry != map()->end() && structure == entry.get().second)
+ map()->remove(entry);
}
- TransitionTable::iterator find = transitionTable()->find(key);
- if (!specificValue)
- find->second.first = 0;
- else
- find->second.second = 0;
- if (!find->second.first && !find->second.second)
- transitionTable()->remove(find);
}
-inline void Structure::transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
+inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* structure)
{
- if (m_isUsingSingleSlot) {
- if (!singleTransition()) {
- setSingleTransition(structure);
+ if (isUsingSingleSlot()) {
+ Structure* existingTransition = singleTransition();
+
+ // This handles the first transition being added.
+ if (!existingTransition) {
+ setSingleTransition(globalData, structure);
return;
}
- Structure* existingTransition = singleTransition();
- TransitionTable* transitionTable = new TransitionTable;
- setTransitionTable(transitionTable);
- if (existingTransition)
- transitionTableAdd(std::make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
+
+ // This handles the second transition being added
+ // (or the first transition being despecified!)
+ setMap(new TransitionMap());
+ add(globalData, existingTransition);
}
- if (!specificValue) {
- TransitionTable::iterator find = transitionTable()->find(key);
- if (find == transitionTable()->end())
- transitionTable()->add(key, Transition(structure, static_cast<Structure*>(0)));
- else
- find->second.first = structure;
- } else {
- // If we're adding a transition to a specific value, then there cannot be
- // an existing transition
- ASSERT(!transitionTable()->contains(key));
- transitionTable()->add(key, Transition(static_cast<Structure*>(0), structure));
+
+ // Add the structure to the map.
+ std::pair<TransitionMap::iterator, bool> result = map()->add(globalData, make_pair(structure->m_nameInPrevious, structure->m_attributesInPrevious), structure);
+ if (!result.second) {
+ // There already is an entry! - we should only hit this when despecifying.
+ ASSERT(result.first.get().second->m_specificValueInPrevious);
+ ASSERT(!structure->m_specificValueInPrevious);
+ map()->set(result.first, structure);
}
}
@@ -191,21 +141,22 @@ void Structure::dumpStatistics()
HashSet<Structure*>::const_iterator end = liveStructureSet.end();
for (HashSet<Structure*>::const_iterator it = liveStructureSet.begin(); it != end; ++it) {
Structure* structure = *it;
- if (structure->m_usingSingleTransitionSlot) {
- if (!structure->m_transitions.singleTransition)
+
+ switch (structure->m_transitionTable.size()) {
+ case 0:
++numberLeaf;
- else
- ++numberUsingSingleSlot;
+ if (!structure->m_previous)
+ ++numberSingletons;
+ break;
- if (!structure->m_previous && !structure->m_transitions.singleTransition)
- ++numberSingletons;
+ case 1:
+ ++numberUsingSingleSlot;
+ break;
}
if (structure->m_propertyTable) {
++numberWithPropertyMaps;
- totalPropertyMapsSize += PropertyMapHashTable::allocationSize(structure->m_propertyTable->size);
- if (structure->m_propertyTable->deletedOffsets)
- totalPropertyMapsSize += (structure->m_propertyTable->deletedOffsets->capacity() * sizeof(unsigned));
+ totalPropertyMapsSize += structure->m_propertyTable->sizeInMemory();
}
}
@@ -223,12 +174,12 @@ void Structure::dumpStatistics()
#endif
}
-Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
- : m_typeInfo(typeInfo)
- , m_prototype(prototype)
- , m_specificValueInPrevious(0)
- , m_propertyTable(0)
- , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
+Structure::Structure(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
+ : JSCell(globalData, globalData.structureStructure.get())
+ , m_typeInfo(typeInfo)
+ , m_prototype(globalData, this, prototype)
+ , m_classInfo(classInfo)
+ , m_propertyStorageCapacity(typeInfo.isFinal() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
, m_offset(noOffset)
, m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
@@ -237,119 +188,60 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anony
, m_attributesInPrevious(0)
, m_specificFunctionThrashCount(0)
, m_anonymousSlotCount(anonymousSlotCount)
- , m_isUsingSingleSlot(true)
+ , m_preventExtensions(false)
{
- m_transitions.m_singleTransition = 0;
-
ASSERT(m_prototype);
- ASSERT(m_prototype->isObject() || m_prototype->isNull());
-
-#ifndef NDEBUG
-#if ENABLE(JSC_MULTIPLE_THREADS)
- MutexLocker protect(ignoreSetMutex);
-#endif
- if (shouldIgnoreLeaks)
- ignoreSet.add(this);
- else
- structureCounter.increment();
-#endif
-
-#if DUMP_STRUCTURE_ID_STATISTICS
- liveStructureSet.add(this);
-#endif
-}
-
-Structure::~Structure()
-{
- if (m_previous) {
- ASSERT(m_nameInPrevious);
- m_previous->transitionTableRemove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
-
- }
- ASSERT(!m_enumerationCache.hasDeadObject());
-
- if (m_propertyTable) {
- unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- if (StringImpl* key = m_propertyTable->entries()[i].key)
- key->deref();
- }
-
- delete m_propertyTable->deletedOffsets;
- fastFree(m_propertyTable);
- }
-
- if (!m_isUsingSingleSlot)
- delete transitionTable();
-
-#ifndef NDEBUG
-#if ENABLE(JSC_MULTIPLE_THREADS)
- MutexLocker protect(ignoreSetMutex);
-#endif
- HashSet<Structure*>::iterator it = ignoreSet.find(this);
- if (it != ignoreSet.end())
- ignoreSet.remove(it);
- else
- structureCounter.decrement();
-#endif
-
-#if DUMP_STRUCTURE_ID_STATISTICS
- liveStructureSet.remove(this);
-#endif
-}
-
-void Structure::startIgnoringLeaks()
-{
-#ifndef NDEBUG
- shouldIgnoreLeaks = true;
-#endif
+ ASSERT(m_prototype.isObject() || m_prototype.isNull());
}
-void Structure::stopIgnoringLeaks()
-{
-#ifndef NDEBUG
- shouldIgnoreLeaks = false;
-#endif
-}
+const ClassInfo Structure::s_info = { "Structure", 0, 0, 0 };
-static bool isPowerOf2(unsigned v)
+Structure::Structure(JSGlobalData& globalData)
+ : JSCell(globalData, this)
+ , m_typeInfo(CompoundType, OverridesMarkChildren)
+ , m_prototype(globalData, this, jsNull())
+ , m_classInfo(&s_info)
+ , m_propertyStorageCapacity(0)
+ , m_offset(noOffset)
+ , m_dictionaryKind(NoneDictionaryKind)
+ , m_isPinnedPropertyTable(false)
+ , m_hasGetterSetterProperties(false)
+ , m_hasNonEnumerableProperties(false)
+ , m_attributesInPrevious(0)
+ , m_specificFunctionThrashCount(0)
+ , m_anonymousSlotCount(0)
+ , m_preventExtensions(false)
{
- // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
-
- return !(v & (v - 1)) && v;
+ ASSERT(m_prototype);
+ ASSERT(m_prototype.isNull());
+ ASSERT(!globalData.structureStructure);
}
-static unsigned nextPowerOf2(unsigned v)
+Structure::Structure(JSGlobalData& globalData, const Structure* previous)
+ : JSCell(globalData, globalData.structureStructure.get())
+ , m_typeInfo(previous->typeInfo())
+ , m_prototype(globalData, this, previous->storedPrototype())
+ , m_classInfo(previous->m_classInfo)
+ , m_propertyStorageCapacity(previous->m_propertyStorageCapacity)
+ , m_offset(noOffset)
+ , m_dictionaryKind(NoneDictionaryKind)
+ , m_isPinnedPropertyTable(false)
+ , m_hasGetterSetterProperties(previous->m_hasGetterSetterProperties)
+ , m_hasNonEnumerableProperties(previous->m_hasNonEnumerableProperties)
+ , m_attributesInPrevious(0)
+ , m_specificFunctionThrashCount(previous->m_specificFunctionThrashCount)
+ , m_anonymousSlotCount(previous->anonymousSlotCount())
+ , m_preventExtensions(previous->m_preventExtensions)
{
- // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
- // Devised by Sean Anderson, Sepember 14, 2001
-
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
-
- return v;
+ ASSERT(m_prototype);
+ ASSERT(m_prototype.isObject() || m_prototype.isNull());
}
-static unsigned sizeForKeyCount(size_t keyCount)
+Structure::~Structure()
{
- if (keyCount == notFound)
- return newTableSize;
-
- if (keyCount < 8)
- return newTableSize;
-
- if (isPowerOf2(keyCount))
- return keyCount * 4;
-
- return nextPowerOf2(keyCount) * 2;
}
-void Structure::materializePropertyMap()
+void Structure::materializePropertyMap(JSGlobalData& globalData)
{
ASSERT(!m_propertyTable);
@@ -358,13 +250,13 @@ void Structure::materializePropertyMap()
Structure* structure = this;
- // Search for the last Structure with a property table.
+ // Search for the last Structure with a property table.
while ((structure = structure->previousID())) {
if (structure->m_isPinnedPropertyTable) {
ASSERT(structure->m_propertyTable);
ASSERT(!structure->m_previous);
- m_propertyTable = structure->copyPropertyTable();
+ m_propertyTable = structure->m_propertyTable->copy(globalData, 0, m_offset + 1);
break;
}
@@ -372,80 +264,46 @@ void Structure::materializePropertyMap()
}
if (!m_propertyTable)
- createPropertyMapHashTable(sizeForKeyCount(m_offset + 1));
- else {
- if (sizeForKeyCount(m_offset + 1) > m_propertyTable->size)
- rehashPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); // This could be made more efficient by combining with the copy above.
- }
+ createPropertyMap(m_offset + 1);
for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
structure = structures[i];
- structure->m_nameInPrevious->ref();
- PropertyMapEntry entry(structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
- insertIntoPropertyMapHashTable(entry);
+ PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
+ m_propertyTable->add(entry);
}
}
void Structure::growPropertyStorageCapacity()
{
- if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
- m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
+ if (isUsingInlineStorage())
+ m_propertyStorageCapacity = JSObject::baseExternalStorageCapacity;
else
m_propertyStorageCapacity *= 2;
}
-void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
+void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Identifier& propertyName)
{
- const StringImpl* rep = propertyName.impl();
+ StringImpl* rep = propertyName.impl();
- materializePropertyMapIfNecessary();
+ materializePropertyMapIfNecessary(globalData);
ASSERT(isDictionary());
ASSERT(m_propertyTable);
- unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- ASSERT(entryIndex != emptyEntryIndex);
-
- if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
- m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
- return;
- }
-
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
- unsigned k = 1 | doubleHash(rep->existingHash());
-
- while (1) {
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
-
- entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- ASSERT(entryIndex != emptyEntryIndex);
-
- if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
- m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
- return;
- }
- }
+ PropertyMapEntry* entry = m_propertyTable->find(rep).first;
+ ASSERT(entry);
+ entry->specificValue.clear();
}
-PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
+Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
ASSERT(!structure->isDictionary());
ASSERT(structure->typeInfo().type() == ObjectType);
- if (Structure* existingTransition = structure->transitionTableGet(make_pair(propertyName.impl(), attributes), specificValue)) {
+ if (Structure* existingTransition = structure->m_transitionTable.get(propertyName.impl(), attributes)) {
+ JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious.get();
+ if (specificValueInPrevious && specificValueInPrevious != specificValue)
+ return 0;
ASSERT(existingTransition->m_offset != noOffset);
offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount;
ASSERT(offset >= structure->m_anonymousSlotCount);
@@ -456,8 +314,18 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
return 0;
}
-PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
+Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
+ // If we have a specific function, we may have got to this point if there is
+ // already a transition with the correct property name and attributes, but
+ // specialized to a different function. In this case we just want to give up
+ // and despecialize the transition.
+ // In this case we clear the value of specificFunction which will result
+ // in us adding a non-specific transition, and any subsequent lookup in
+ // Structure::addPropertyTransitionToExistingStructure will just use that.
+ if (specificValue && structure->m_transitionTable.contains(propertyName.impl(), attributes))
+ specificValue = 0;
+
ASSERT(!structure->isDictionary());
ASSERT(structure->typeInfo().type() == ObjectType);
ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
@@ -466,43 +334,37 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
specificValue = 0;
if (structure->transitionCount() > s_maxTransitionLength) {
- RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
+ Structure* transition = toCacheableDictionaryTransition(globalData, structure);
ASSERT(structure != transition);
- offset = transition->put(propertyName, attributes, specificValue);
+ offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
ASSERT(offset >= structure->m_anonymousSlotCount);
ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
transition->growPropertyStorageCapacity();
- return transition.release();
+ return transition;
}
- RefPtr<Structure> transition = create(structure->m_prototype.get(), structure->typeInfo(), structure->anonymousSlotCount());
+ Structure* transition = create(globalData, structure);
- transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
- transition->m_previous = structure;
+ transition->m_cachedPrototypeChain.set(globalData, transition, structure->m_cachedPrototypeChain.get());
+ transition->m_previous.set(globalData, transition, structure);
transition->m_nameInPrevious = propertyName.impl();
transition->m_attributesInPrevious = attributes;
- transition->m_specificValueInPrevious = specificValue;
- transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
- transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
- transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
- transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
+ transition->m_specificValueInPrevious.set(globalData, transition, specificValue);
if (structure->m_propertyTable) {
if (structure->m_isPinnedPropertyTable)
- transition->m_propertyTable = structure->copyPropertyTable();
- else {
- transition->m_propertyTable = structure->m_propertyTable;
- structure->m_propertyTable = 0;
- }
+ transition->m_propertyTable = structure->m_propertyTable->copy(globalData, 0, structure->m_propertyTable->size() + 1);
+ else
+ transition->m_propertyTable = structure->m_propertyTable.release();
} else {
if (structure->m_previous)
- transition->materializePropertyMap();
+ transition->materializePropertyMap(globalData);
else
- transition->createPropertyMapHashTable();
+ transition->createPropertyMap();
}
- offset = transition->put(propertyName, attributes, specificValue);
+ offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
ASSERT(offset >= structure->m_anonymousSlotCount);
ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
@@ -510,183 +372,235 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
transition->m_offset = offset - structure->m_anonymousSlotCount;
ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
- structure->transitionTableAdd(make_pair(propertyName.impl(), attributes), transition.get(), specificValue);
- return transition.release();
+ structure->m_transitionTable.add(globalData, transition);
+ return transition;
}
-PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset)
+Structure* Structure::removePropertyTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, size_t& offset)
{
ASSERT(!structure->isUncacheableDictionary());
- RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
+ Structure* transition = toUncacheableDictionaryTransition(globalData, structure);
offset = transition->remove(propertyName);
ASSERT(offset >= structure->m_anonymousSlotCount);
ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
- return transition.release();
+ return transition;
}
-PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
+Structure* Structure::changePrototypeTransition(JSGlobalData& globalData, Structure* structure, JSValue prototype)
{
- RefPtr<Structure> transition = create(prototype, structure->typeInfo(), structure->anonymousSlotCount());
+ Structure* transition = create(globalData, structure);
- transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
- transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
- transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
- transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
+ transition->m_prototype.set(globalData, transition, prototype);
// Don't set m_offset, as one can not transition to this.
- structure->materializePropertyMapIfNecessary();
- transition->m_propertyTable = structure->copyPropertyTable();
+ structure->materializePropertyMapIfNecessary(globalData);
+ transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
transition->m_isPinnedPropertyTable = true;
ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
- return transition.release();
+ return transition;
}
-PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
+Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Structure* structure, const Identifier& replaceFunction)
{
ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount);
- RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
+ Structure* transition = create(globalData, structure);
- transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
- transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
- transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
- transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount + 1;
+ ++transition->m_specificFunctionThrashCount;
// Don't set m_offset, as one can not transition to this.
- structure->materializePropertyMapIfNecessary();
- transition->m_propertyTable = structure->copyPropertyTable();
+ structure->materializePropertyMapIfNecessary(globalData);
+ transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
transition->m_isPinnedPropertyTable = true;
if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
- transition->despecifyAllFunctions();
+ transition->despecifyAllFunctions(globalData);
else {
- bool removed = transition->despecifyFunction(replaceFunction);
+ bool removed = transition->despecifyFunction(globalData, replaceFunction);
ASSERT_UNUSED(removed, removed);
}
ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
- return transition.release();
+ return transition;
}
-PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
+Structure* Structure::getterSetterTransition(JSGlobalData& globalData, Structure* structure)
{
- RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
- transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
- transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
- transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
- transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
+ Structure* transition = create(globalData, structure);
// Don't set m_offset, as one can not transition to this.
- structure->materializePropertyMapIfNecessary();
- transition->m_propertyTable = structure->copyPropertyTable();
+ structure->materializePropertyMapIfNecessary(globalData);
+ transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
transition->m_isPinnedPropertyTable = true;
ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
- return transition.release();
+ return transition;
}
-PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind)
+Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind)
{
ASSERT(!structure->isUncacheableDictionary());
- RefPtr<Structure> transition = create(structure->m_prototype.get(), structure->typeInfo(), structure->anonymousSlotCount());
+ Structure* transition = create(globalData, structure);
+
+ structure->materializePropertyMapIfNecessary(globalData);
+ transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
+ transition->m_isPinnedPropertyTable = true;
transition->m_dictionaryKind = kind;
- transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
- transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
- transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
- transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
- structure->materializePropertyMapIfNecessary();
- transition->m_propertyTable = structure->copyPropertyTable();
+ ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+ return transition;
+}
+
+Structure* Structure::toCacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure)
+{
+ return toDictionaryTransition(globalData, structure, CachedDictionaryKind);
+}
+
+Structure* Structure::toUncacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure)
+{
+ return toDictionaryTransition(globalData, structure, UncachedDictionaryKind);
+}
+
+// In future we may want to cache this transition.
+Structure* Structure::sealTransition(JSGlobalData& globalData, Structure* structure)
+{
+ Structure* transition = preventExtensionsTransition(globalData, structure);
+
+ if (transition->m_propertyTable) {
+ PropertyTable::iterator end = transition->m_propertyTable->end();
+ for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
+ iter->attributes |= DontDelete;
+ }
+
+ return transition;
+}
+
+// In future we may want to cache this transition.
+Structure* Structure::freezeTransition(JSGlobalData& globalData, Structure* structure)
+{
+ Structure* transition = preventExtensionsTransition(globalData, structure);
+
+ if (transition->m_propertyTable) {
+ PropertyTable::iterator end = transition->m_propertyTable->end();
+ for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
+ iter->attributes |= (DontDelete | ReadOnly);
+ }
+
+ return transition;
+}
+
+// In future we may want to cache this transition.
+Structure* Structure::preventExtensionsTransition(JSGlobalData& globalData, Structure* structure)
+{
+ Structure* transition = create(globalData, structure);
+
+ // Don't set m_offset, as one can not transition to this.
+
+ structure->materializePropertyMapIfNecessary(globalData);
+ transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
transition->m_isPinnedPropertyTable = true;
-
+ transition->m_preventExtensions = true;
+
ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
- return transition.release();
+ return transition;
}
-PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure)
+// In future we may want to cache this property.
+bool Structure::isSealed(JSGlobalData& globalData)
{
- return toDictionaryTransition(structure, CachedDictionaryKind);
+ if (isExtensible())
+ return false;
+
+ materializePropertyMapIfNecessary(globalData);
+ if (!m_propertyTable)
+ return true;
+
+ PropertyTable::iterator end = m_propertyTable->end();
+ for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ if ((iter->attributes & DontDelete) != DontDelete)
+ return false;
+ }
+ return true;
}
-PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure)
+// In future we may want to cache this property.
+bool Structure::isFrozen(JSGlobalData& globalData)
{
- return toDictionaryTransition(structure, UncachedDictionaryKind);
+ if (isExtensible())
+ return false;
+
+ materializePropertyMapIfNecessary(globalData);
+ if (!m_propertyTable)
+ return true;
+
+ PropertyTable::iterator end = m_propertyTable->end();
+ for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ if ((iter->attributes & (DontDelete | ReadOnly)) != (DontDelete | ReadOnly))
+ return false;
+ }
+ return true;
}
-PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObject* object)
+Structure* Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObject* object)
{
ASSERT(isDictionary());
if (isUncacheableDictionary()) {
ASSERT(m_propertyTable);
- Vector<PropertyMapEntry*> sortedPropertyEntries(m_propertyTable->keyCount);
- PropertyMapEntry** p = sortedPropertyEntries.data();
- unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- if (m_propertyTable->entries()[i].key)
- *p++ = &m_propertyTable->entries()[i];
- }
- size_t propertyCount = p - sortedPropertyEntries.data();
- qsort(sortedPropertyEntries.data(), propertyCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
- sortedPropertyEntries.resize(propertyCount);
- // We now have the properties currently defined on this object
- // in the order that they are expected to be in, but we need to
- // reorder the storage, so we have to copy the current values out
- Vector<JSValue> values(propertyCount);
unsigned anonymousSlotCount = m_anonymousSlotCount;
- for (unsigned i = 0; i < propertyCount; i++) {
- PropertyMapEntry* entry = sortedPropertyEntries[i];
- values[i] = object->getDirectOffset(entry->offset);
+ size_t propertyCount = m_propertyTable->size();
+ Vector<JSValue> values(propertyCount);
+
+ unsigned i = 0;
+ PropertyTable::iterator end = m_propertyTable->end();
+ for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter, ++i) {
+ values[i] = object->getDirectOffset(iter->offset);
// Update property table to have the new property offsets
- entry->offset = anonymousSlotCount + i;
- entry->index = i;
+ iter->offset = anonymousSlotCount + i;
}
// Copy the original property values into their final locations
for (unsigned i = 0; i < propertyCount; i++)
object->putDirectOffset(globalData, anonymousSlotCount + i, values[i]);
- if (m_propertyTable->deletedOffsets) {
- delete m_propertyTable->deletedOffsets;
- m_propertyTable->deletedOffsets = 0;
- }
+ m_propertyTable->clearDeletedOffsets();
}
m_dictionaryKind = NoneDictionaryKind;
return this;
}
-size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
+size_t Structure::addPropertyWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
ASSERT(!m_enumerationCache);
if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
specificValue = 0;
- materializePropertyMapIfNecessary();
+ materializePropertyMapIfNecessary(globalData);
m_isPinnedPropertyTable = true;
- size_t offset = put(propertyName, attributes, specificValue);
+ size_t offset = putSpecificValue(globalData, propertyName, attributes, specificValue);
ASSERT(offset >= m_anonymousSlotCount);
if (propertyStorageSize() > propertyStorageCapacity())
growPropertyStorageCapacity();
return offset;
}
-size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
+size_t Structure::removePropertyWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName)
{
ASSERT(isUncacheableDictionary());
ASSERT(!m_enumerationCache);
- materializePropertyMapIfNecessary();
+ materializePropertyMapIfNecessary(globalData);
m_isPinnedPropertyTable = true;
size_t offset = remove(propertyName);
@@ -696,11 +610,6 @@ size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName
#if DUMP_PROPERTYMAP_STATS
-static int numProbes;
-static int numCollisions;
-static int numRehashes;
-static int numRemoves;
-
struct PropertyMapStatisticsExitLogger {
~PropertyMapStatisticsExitLogger();
};
@@ -718,8 +627,6 @@ PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
#endif
-static const unsigned deletedSentinelIndex = 1;
-
#if !DO_PROPERTYMAP_CONSTENCY_CHECK
inline void Structure::checkConsistency()
@@ -728,238 +635,82 @@ inline void Structure::checkConsistency()
#endif
-PropertyMapHashTable* Structure::copyPropertyTable()
+PropertyTable* Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner)
{
- if (!m_propertyTable)
- return 0;
-
- size_t tableSize = PropertyMapHashTable::allocationSize(m_propertyTable->size);
- PropertyMapHashTable* newTable = static_cast<PropertyMapHashTable*>(fastMalloc(tableSize));
- memcpy(newTable, m_propertyTable, tableSize);
-
- unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; ++i) {
- if (StringImpl* key = newTable->entries()[i].key)
- key->ref();
- }
-
- // Copy the deletedOffsets vector.
- if (m_propertyTable->deletedOffsets)
- newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets);
-
- return newTable;
+ return m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0;
}
-size_t Structure::get(const StringImpl* rep, unsigned& attributes, JSCell*& specificValue)
+size_t Structure::get(JSGlobalData& globalData, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue)
{
- materializePropertyMapIfNecessary();
+ materializePropertyMapIfNecessary(globalData);
if (!m_propertyTable)
- return notFound;
-
- unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return notFound;
-
- if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
- attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
- specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
- ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
- return m_propertyTable->entries()[entryIndex - 1].offset;
- }
-
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
- unsigned k = 1 | doubleHash(rep->existingHash());
-
- while (1) {
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
+ return WTF::notFound;
- entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return notFound;
+ PropertyMapEntry* entry = m_propertyTable->find(propertyName).first;
+ if (!entry)
+ return WTF::notFound;
- if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
- attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
- specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
- ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
- return m_propertyTable->entries()[entryIndex - 1].offset;
- }
- }
+ attributes = entry->attributes;
+ specificValue = entry->specificValue.get();
+ ASSERT(entry->offset >= m_anonymousSlotCount);
+ return entry->offset;
}
-bool Structure::despecifyFunction(const Identifier& propertyName)
+bool Structure::despecifyFunction(JSGlobalData& globalData, const Identifier& propertyName)
{
- ASSERT(!propertyName.isNull());
-
- materializePropertyMapIfNecessary();
+ materializePropertyMapIfNecessary(globalData);
if (!m_propertyTable)
return false;
- StringImpl* rep = propertyName.impl();
-
- unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
+ ASSERT(!propertyName.isNull());
+ PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
+ if (!entry)
return false;
- if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
- ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
- m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
- return true;
- }
-
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
- unsigned k = 1 | doubleHash(rep->existingHash());
-
- while (1) {
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
-
- entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return false;
-
- if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
- ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
- m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
- return true;
- }
- }
+ ASSERT(entry->specificValue);
+ entry->specificValue.clear();
+ return true;
}
-void Structure::despecifyAllFunctions()
+void Structure::despecifyAllFunctions(JSGlobalData& globalData)
{
- materializePropertyMapIfNecessary();
+ materializePropertyMapIfNecessary(globalData);
if (!m_propertyTable)
return;
-
- unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; ++i)
- m_propertyTable->entries()[i].specificValue = 0;
+
+ PropertyTable::iterator end = m_propertyTable->end();
+ for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter)
+ iter->specificValue.clear();
}
-size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
+size_t Structure::putSpecificValue(JSGlobalData& globalData, const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
ASSERT(!propertyName.isNull());
- ASSERT(get(propertyName) == notFound);
+ ASSERT(get(globalData, propertyName) == notFound);
checkConsistency();
-
if (attributes & DontEnum)
m_hasNonEnumerableProperties = true;
StringImpl* rep = propertyName.impl();
if (!m_propertyTable)
- createPropertyMapHashTable();
-
- // FIXME: Consider a fast case for tables with no deleted sentinels.
-
- unsigned i = rep->existingHash();
- unsigned k = 0;
- bool foundDeletedElement = false;
- unsigned deletedElementIndex = 0; // initialize to make the compiler happy
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- while (1) {
- unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- break;
-
- if (entryIndex == deletedSentinelIndex) {
- // If we find a deleted-element sentinel, remember it for use later.
- if (!foundDeletedElement) {
- foundDeletedElement = true;
- deletedElementIndex = i;
- }
- }
-
- if (k == 0) {
- k = 1 | doubleHash(rep->existingHash());
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
- }
-
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
- }
-
- // Figure out which entry to use.
- unsigned entryIndex = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount + 2;
- if (foundDeletedElement) {
- i = deletedElementIndex;
- --m_propertyTable->deletedSentinelCount;
-
- // Since we're not making the table bigger, we can't use the entry one past
- // the end that we were planning on using, so search backwards for the empty
- // slot that we can use. We know it will be there because we did at least one
- // deletion in the past that left an entry empty.
- while (m_propertyTable->entries()[--entryIndex - 1].key) { }
- }
-
- // Create a new hash table entry.
- m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
-
- // Create a new hash table entry.
- rep->ref();
- m_propertyTable->entries()[entryIndex - 1].key = rep;
- m_propertyTable->entries()[entryIndex - 1].attributes = attributes;
- m_propertyTable->entries()[entryIndex - 1].specificValue = specificValue;
- m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed;
+ createPropertyMap();
unsigned newOffset;
- if (m_propertyTable->deletedOffsets && !m_propertyTable->deletedOffsets->isEmpty()) {
- newOffset = m_propertyTable->deletedOffsets->last();
- m_propertyTable->deletedOffsets->removeLast();
- } else
- newOffset = m_propertyTable->keyCount + m_anonymousSlotCount;
- m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
-
+
+ if (m_propertyTable->hasDeletedOffset())
+ newOffset = m_propertyTable->getDeletedOffset();
+ else
+ newOffset = m_propertyTable->size() + m_anonymousSlotCount;
ASSERT(newOffset >= m_anonymousSlotCount);
- ++m_propertyTable->keyCount;
- if ((m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount) * 2 >= m_propertyTable->size)
- expandPropertyMapHashTable();
+ m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue));
checkConsistency();
return newOffset;
}
-bool Structure::hasTransition(StringImpl* rep, unsigned attributes)
-{
- return transitionTableHasTransition(make_pair(rep, attributes));
-}
-
size_t Structure::remove(const Identifier& propertyName)
{
ASSERT(!propertyName.isNull());
@@ -971,289 +722,119 @@ size_t Structure::remove(const Identifier& propertyName)
if (!m_propertyTable)
return notFound;
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
- ++numRemoves;
-#endif
-
- // Find the thing to remove.
- unsigned i = rep->existingHash();
- unsigned k = 0;
- unsigned entryIndex;
- StringImpl* key = 0;
- while (1) {
- entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return notFound;
-
- key = m_propertyTable->entries()[entryIndex - 1].key;
- if (rep == key)
- break;
-
- if (k == 0) {
- k = 1 | doubleHash(rep->existingHash());
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
- }
-
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
- }
-
- // Replace this one element with the deleted sentinel. Also clear out
- // the entry so we can iterate all the entries as needed.
- m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = deletedSentinelIndex;
+ PropertyTable::find_iterator position = m_propertyTable->find(rep);
+ if (!position.first)
+ return notFound;
- size_t offset = m_propertyTable->entries()[entryIndex - 1].offset;
+ size_t offset = position.first->offset;
ASSERT(offset >= m_anonymousSlotCount);
- key->deref();
- m_propertyTable->entries()[entryIndex - 1].key = 0;
- m_propertyTable->entries()[entryIndex - 1].attributes = 0;
- m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
- m_propertyTable->entries()[entryIndex - 1].offset = 0;
-
- if (!m_propertyTable->deletedOffsets)
- m_propertyTable->deletedOffsets = new Vector<unsigned>;
- m_propertyTable->deletedOffsets->append(offset);
-
- ASSERT(m_propertyTable->keyCount >= 1);
- --m_propertyTable->keyCount;
- ++m_propertyTable->deletedSentinelCount;
-
- if (m_propertyTable->deletedSentinelCount * 4 >= m_propertyTable->size)
- rehashPropertyMapHashTable();
+ m_propertyTable->remove(position);
+ m_propertyTable->addDeletedOffset(offset);
checkConsistency();
return offset;
}
-void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
-{
- ASSERT(m_propertyTable);
- ASSERT(entry.offset >= m_anonymousSlotCount);
- unsigned i = entry.key->existingHash();
- unsigned k = 0;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- while (1) {
- unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- break;
-
- if (k == 0) {
- k = 1 | doubleHash(entry.key->existingHash());
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
- }
-
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
- }
-
- unsigned entryIndex = m_propertyTable->keyCount + 2;
- m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
- m_propertyTable->entries()[entryIndex - 1] = entry;
-
- ++m_propertyTable->keyCount;
-}
-
-void Structure::createPropertyMapHashTable()
-{
- ASSERT(sizeForKeyCount(7) == newTableSize);
- createPropertyMapHashTable(newTableSize);
-}
-
-void Structure::createPropertyMapHashTable(unsigned newTableSize)
+void Structure::createPropertyMap(unsigned capacity)
{
ASSERT(!m_propertyTable);
- ASSERT(isPowerOf2(newTableSize));
checkConsistency();
-
- m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
- m_propertyTable->size = newTableSize;
- m_propertyTable->sizeMask = newTableSize - 1;
-
+ m_propertyTable = new PropertyTable(capacity);
checkConsistency();
}
-void Structure::expandPropertyMapHashTable()
-{
- ASSERT(m_propertyTable);
- rehashPropertyMapHashTable(m_propertyTable->size * 2);
-}
-
-void Structure::rehashPropertyMapHashTable()
-{
- ASSERT(m_propertyTable);
- ASSERT(m_propertyTable->size);
- rehashPropertyMapHashTable(m_propertyTable->size);
-}
-
-void Structure::rehashPropertyMapHashTable(unsigned newTableSize)
+void Structure::getPropertyNames(JSGlobalData& globalData, PropertyNameArray& propertyNames, EnumerationMode mode)
{
- ASSERT(m_propertyTable);
- ASSERT(isPowerOf2(newTableSize));
-
- checkConsistency();
-
- PropertyMapHashTable* oldTable = m_propertyTable;
+ materializePropertyMapIfNecessary(globalData);
+ if (!m_propertyTable)
+ return;
- m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
- m_propertyTable->size = newTableSize;
- m_propertyTable->sizeMask = newTableSize - 1;
+ bool knownUnique = !propertyNames.size();
- unsigned lastIndexUsed = 0;
- unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; ++i) {
- if (oldTable->entries()[i].key) {
- lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
- insertIntoPropertyMapHashTable(oldTable->entries()[i]);
+ PropertyTable::iterator end = m_propertyTable->end();
+ for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ ASSERT(m_hasNonEnumerableProperties || !(iter->attributes & DontEnum));
+ if (!(iter->attributes & DontEnum) || (mode == IncludeDontEnumProperties)) {
+ if (knownUnique)
+ propertyNames.addKnownUnique(iter->key);
+ else
+ propertyNames.add(iter->key);
}
}
- m_propertyTable->lastIndexUsed = lastIndexUsed;
- m_propertyTable->deletedOffsets = oldTable->deletedOffsets;
-
- fastFree(oldTable);
-
- checkConsistency();
-}
-
-int comparePropertyMapEntryIndices(const void* a, const void* b)
-{
- unsigned ia = static_cast<PropertyMapEntry* const*>(a)[0]->index;
- unsigned ib = static_cast<PropertyMapEntry* const*>(b)[0]->index;
- if (ia < ib)
- return -1;
- if (ia > ib)
- return +1;
- return 0;
}
-void Structure::getPropertyNames(PropertyNameArray& propertyNames, EnumerationMode mode)
+void Structure::markChildren(MarkStack& markStack)
{
- materializePropertyMapIfNecessary();
- if (!m_propertyTable)
- return;
-
- if (m_propertyTable->keyCount < tinyMapThreshold) {
- PropertyMapEntry* a[tinyMapThreshold];
- int i = 0;
- unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
- for (unsigned k = 1; k <= entryCount; k++) {
- ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[k].attributes & DontEnum));
- if (m_propertyTable->entries()[k].key && (!(m_propertyTable->entries()[k].attributes & DontEnum) || (mode == IncludeDontEnumProperties))) {
- PropertyMapEntry* value = &m_propertyTable->entries()[k];
- int j;
- for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
- a[j + 1] = a[j];
- a[j + 1] = value;
- ++i;
- }
- }
- if (!propertyNames.size()) {
- for (int k = 0; k < i; ++k)
- propertyNames.addKnownUnique(a[k]->key);
- } else {
- for (int k = 0; k < i; ++k)
- propertyNames.add(a[k]->key);
+ JSCell::markChildren(markStack);
+ if (m_prototype)
+ markStack.append(&m_prototype);
+ if (m_cachedPrototypeChain)
+ markStack.append(&m_cachedPrototypeChain);
+ if (m_previous)
+ markStack.append(&m_previous);
+ if (m_specificValueInPrevious)
+ markStack.append(&m_specificValueInPrevious);
+ if (m_enumerationCache)
+ markStack.append(&m_enumerationCache);
+ if (m_propertyTable) {
+ PropertyTable::iterator end = m_propertyTable->end();
+ for (PropertyTable::iterator ptr = m_propertyTable->begin(); ptr != end; ++ptr) {
+ if (ptr->specificValue)
+ markStack.append(&ptr->specificValue);
}
-
- return;
- }
-
- // Allocate a buffer to use to sort the keys.
- Vector<PropertyMapEntry*, smallMapThreshold> sortedEnumerables(m_propertyTable->keyCount);
-
- // Get pointers to the enumerable entries in the buffer.
- PropertyMapEntry** p = sortedEnumerables.data();
- unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- if (m_propertyTable->entries()[i].key && (!(m_propertyTable->entries()[i].attributes & DontEnum) || (mode == IncludeDontEnumProperties)))
- *p++ = &m_propertyTable->entries()[i];
- }
-
- size_t enumerableCount = p - sortedEnumerables.data();
- // Sort the entries by index.
- qsort(sortedEnumerables.data(), enumerableCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
- sortedEnumerables.resize(enumerableCount);
-
- // Put the keys of the sorted entries into the list.
- if (!propertyNames.size()) {
- for (size_t i = 0; i < sortedEnumerables.size(); ++i)
- propertyNames.addKnownUnique(sortedEnumerables[i]->key);
- } else {
- for (size_t i = 0; i < sortedEnumerables.size(); ++i)
- propertyNames.add(sortedEnumerables[i]->key);
}
}
#if DO_PROPERTYMAP_CONSTENCY_CHECK
-void Structure::checkConsistency()
+void PropertyTable::checkConsistency()
{
- if (!m_propertyTable)
- return;
-
- ASSERT(m_propertyTable->size >= newTableSize);
- ASSERT(m_propertyTable->sizeMask);
- ASSERT(m_propertyTable->size == m_propertyTable->sizeMask + 1);
- ASSERT(!(m_propertyTable->size & m_propertyTable->sizeMask));
-
- ASSERT(m_propertyTable->keyCount <= m_propertyTable->size / 2);
- ASSERT(m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 4);
+ ASSERT(m_indexSize >= PropertyTable::MinimumTableSize);
+ ASSERT(m_indexMask);
+ ASSERT(m_indexSize == m_indexMask + 1);
+ ASSERT(!(m_indexSize & m_indexMask));
- ASSERT(m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 2);
+ ASSERT(m_keyCount <= m_indexSize / 2);
+ ASSERT(m_keyCount + m_deletedCount <= m_indexSize / 2);
+ ASSERT(m_deletedCount <= m_indexSize / 4);
unsigned indexCount = 0;
unsigned deletedIndexCount = 0;
- for (unsigned a = 0; a != m_propertyTable->size; ++a) {
- unsigned entryIndex = m_propertyTable->entryIndices[a];
- if (entryIndex == emptyEntryIndex)
+ for (unsigned a = 0; a != m_indexSize; ++a) {
+ unsigned entryIndex = m_index[a];
+ if (entryIndex == PropertyTable::EmptyEntryIndex)
continue;
- if (entryIndex == deletedSentinelIndex) {
+ if (entryIndex == deletedEntryIndex()) {
++deletedIndexCount;
continue;
}
- ASSERT(entryIndex > deletedSentinelIndex);
- ASSERT(entryIndex - 1 <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount);
+ ASSERT(entryIndex < deletedEntryIndex());
+ ASSERT(entryIndex - 1 <= usedCount());
++indexCount;
- for (unsigned b = a + 1; b != m_propertyTable->size; ++b)
- ASSERT(m_propertyTable->entryIndices[b] != entryIndex);
+ for (unsigned b = a + 1; b != m_indexSize; ++b)
+ ASSERT(m_index[b] != entryIndex);
}
- ASSERT(indexCount == m_propertyTable->keyCount);
- ASSERT(deletedIndexCount == m_propertyTable->deletedSentinelCount);
+ ASSERT(indexCount == m_keyCount);
+ ASSERT(deletedIndexCount == m_deletedCount);
- ASSERT(m_propertyTable->entries()[0].key == 0);
+ ASSERT(!table()[deletedEntryIndex() - 1].key);
unsigned nonEmptyEntryCount = 0;
- for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) {
- ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum));
- StringImpl* rep = m_propertyTable->entries()[c].key;
- ASSERT(m_propertyTable->entries()[c].offset >= m_anonymousSlotCount);
- if (!rep)
+ for (unsigned c = 0; c < usedCount(); ++c) {
+ StringImpl* rep = table()[c].key;
+ if (rep == PROPERTY_MAP_DELETED_ENTRY_KEY)
continue;
++nonEmptyEntryCount;
unsigned i = rep->existingHash();
unsigned k = 0;
unsigned entryIndex;
while (1) {
- entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- ASSERT(entryIndex != emptyEntryIndex);
- if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+ entryIndex = m_index[i & m_indexMask];
+ ASSERT(entryIndex != PropertyTable::EmptyEntryIndex);
+ if (rep == table()[entryIndex - 1].key)
break;
if (k == 0)
k = 1 | doubleHash(rep->existingHash());
@@ -1262,7 +843,23 @@ void Structure::checkConsistency()
ASSERT(entryIndex == c + 1);
}
- ASSERT(nonEmptyEntryCount == m_propertyTable->keyCount);
+ ASSERT(nonEmptyEntryCount == m_keyCount);
+}
+
+void Structure::checkConsistency()
+{
+ if (!m_propertyTable)
+ return;
+
+ if (!m_hasNonEnumerableProperties) {
+ PropertyTable::iterator end = m_propertyTable->end();
+ for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ ASSERT(!(iter->attributes & DontEnum));
+ ASSERT(iter->offset >= m_anonymousSlotCount);
+ }
+ }
+
+ m_propertyTable->checkConsistency();
}
#endif // DO_PROPERTYMAP_CONSTENCY_CHECK
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 77724ac..fe9ce6b 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -27,67 +27,69 @@
#define Structure_h
#include "Identifier.h"
+#include "JSCell.h"
#include "JSType.h"
#include "JSValue.h"
#include "PropertyMapHashTable.h"
#include "PropertyNameArray.h"
#include "Protect.h"
-#include "StructureChain.h"
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
#include "UString.h"
-#include "WeakGCPtr.h"
+#include "Weak.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
-#ifndef NDEBUG
-#define DUMP_PROPERTYMAP_STATS 0
-#else
-#define DUMP_PROPERTYMAP_STATS 0
-#endif
namespace JSC {
class MarkStack;
class PropertyNameArray;
class PropertyNameArrayData;
+ class StructureChain;
+
+ struct ClassInfo;
enum EnumerationMode {
ExcludeDontEnumProperties,
IncludeDontEnumProperties
};
- class Structure : public RefCounted<Structure> {
+ class Structure : public JSCell {
public:
- friend class JIT;
friend class StructureTransitionTable;
- static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
+ static Structure* create(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
{
- return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount));
+ ASSERT(globalData.structureStructure);
+ return new (&globalData) Structure(globalData, prototype, typeInfo, anonymousSlotCount, classInfo);
}
- static void startIgnoringLeaks();
- static void stopIgnoringLeaks();
-
static void dumpStatistics();
- static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
- static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
- static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
- static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
- static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);
- static PassRefPtr<Structure> getterSetterTransition(Structure*);
- static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
- static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
+ static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+ static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+ static Structure* removePropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, size_t& offset);
+ static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
+ static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&);
+ static Structure* getterSetterTransition(JSGlobalData&, Structure*);
+ static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
+ static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
+ static Structure* sealTransition(JSGlobalData&, Structure*);
+ static Structure* freezeTransition(JSGlobalData&, Structure*);
+ static Structure* preventExtensionsTransition(JSGlobalData&, Structure*);
- PassRefPtr<Structure> flattenDictionaryStructure(JSGlobalData&, JSObject*);
+ bool isSealed(JSGlobalData&);
+ bool isFrozen(JSGlobalData&);
+ bool isExtensible() const { return !m_preventExtensions; }
+
+ Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
~Structure();
// These should be used with caution.
- size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
- size_t removePropertyWithoutTransition(const Identifier& propertyName);
- void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; }
+ size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
+ size_t removePropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName);
+ void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); }
bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
@@ -95,32 +97,23 @@ namespace JSC {
const TypeInfo& typeInfo() const { return m_typeInfo; }
JSValue storedPrototype() const { return m_prototype.get(); }
- DeprecatedPtr<Unknown>* storedPrototypeSlot() { return &m_prototype; }
JSValue prototypeForLookup(ExecState*) const;
StructureChain* prototypeChain(ExecState*) const;
+ void markChildren(MarkStack&);
Structure* previousID() const { return m_previous.get(); }
void growPropertyStorageCapacity();
unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; }
- unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : static_cast<unsigned>(m_offset + 1)); }
+ unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast<unsigned>(m_offset + 1)); }
bool isUsingInlineStorage() const;
- size_t get(const Identifier& propertyName);
- size_t get(const StringImpl* rep, unsigned& attributes, JSCell*& specificValue);
- size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
+ size_t get(JSGlobalData&, const Identifier& propertyName);
+ size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
+ size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
{
ASSERT(!propertyName.isNull());
- return get(propertyName.impl(), attributes, specificValue);
- }
- bool transitionedFor(const JSCell* specificValue)
- {
- return m_specificValueInPrevious == specificValue;
- }
- bool hasTransition(StringImpl*, unsigned attributes);
- bool hasTransition(const Identifier& propertyName, unsigned attributes)
- {
- return hasTransition(propertyName.impl(), attributes);
+ return get(globalData, propertyName.impl(), attributes, specificValue);
}
bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
@@ -131,48 +124,73 @@ namespace JSC {
bool hasAnonymousSlots() const { return !!m_anonymousSlotCount; }
unsigned anonymousSlotCount() const { return m_anonymousSlotCount; }
- bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
+ bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; }
- void despecifyDictionaryFunction(const Identifier& propertyName);
+ void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName);
void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
- void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
- void clearEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
+ void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
- void getPropertyNames(PropertyNameArray&, EnumerationMode mode);
-
+ void getPropertyNames(JSGlobalData&, PropertyNameArray&, EnumerationMode mode);
+
+ const ClassInfo* classInfo() const { return m_classInfo; }
+
+ static ptrdiff_t prototypeOffset()
+ {
+ return OBJECT_OFFSETOF(Structure, m_prototype);
+ }
+
+ static ptrdiff_t typeInfoFlagsOffset()
+ {
+ return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset();
+ }
+
+ static ptrdiff_t typeInfoTypeOffset()
+ {
+ return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
+ }
+
+ static Structure* createStructure(JSGlobalData& globalData)
+ {
+ ASSERT(!globalData.structureStructure);
+ return new (&globalData) Structure(globalData);
+ }
+
private:
+ Structure(JSGlobalData&, JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*);
+ Structure(JSGlobalData&);
+ Structure(JSGlobalData&, const Structure*);
+
+ static Structure* create(JSGlobalData& globalData, const Structure* structure)
+ {
+ ASSERT(globalData.structureStructure);
+ return new (&globalData) Structure(globalData, structure);
+ }
+
+ static const ClassInfo s_info;
- Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount);
-
typedef enum {
NoneDictionaryKind = 0,
CachedDictionaryKind = 1,
UncachedDictionaryKind = 2
} DictionaryKind;
- static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind);
+ static Structure* toDictionaryTransition(JSGlobalData&, Structure*, DictionaryKind);
- size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
+ size_t putSpecificValue(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t remove(const Identifier& propertyName);
- void expandPropertyMapHashTable();
- void rehashPropertyMapHashTable();
- void rehashPropertyMapHashTable(unsigned newTableSize);
- void createPropertyMapHashTable();
- void createPropertyMapHashTable(unsigned newTableSize);
- void insertIntoPropertyMapHashTable(const PropertyMapEntry&);
+ void createPropertyMap(unsigned keyCount = 0);
void checkConsistency();
- bool despecifyFunction(const Identifier&);
- void despecifyAllFunctions();
+ bool despecifyFunction(JSGlobalData&, const Identifier&);
+ void despecifyAllFunctions(JSGlobalData&);
- PropertyMapHashTable* copyPropertyTable();
- void materializePropertyMap();
- void materializePropertyMapIfNecessary()
+ PropertyTable* copyPropertyTable(JSGlobalData&, Structure* owner);
+ void materializePropertyMap(JSGlobalData&);
+ void materializePropertyMapIfNecessary(JSGlobalData& globalData)
{
- if (m_propertyTable || !m_previous)
- return;
- materializePropertyMap();
+ if (!m_propertyTable && m_previous)
+ materializePropertyMap(globalData);
}
signed char transitionCount() const
@@ -181,24 +199,8 @@ namespace JSC {
return m_offset == noOffset ? 0 : m_offset + 1;
}
- typedef std::pair<Structure*, Structure*> Transition;
- typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
-
- inline bool transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
- inline void transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
- inline void transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue);
- inline bool transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const;
- inline Structure* transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const;
-
- TransitionTable* transitionTable() const { ASSERT(!m_isUsingSingleSlot); return m_transitions.m_table; }
- inline void setTransitionTable(TransitionTable* table);
- Structure* singleTransition() const { ASSERT(m_isUsingSingleSlot); return m_transitions.m_singleTransition; }
- void setSingleTransition(Structure* structure) { ASSERT(m_isUsingSingleSlot); m_transitions.m_singleTransition = structure; }
-
bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
- static const unsigned emptyEntryIndex = 0;
-
static const signed char s_maxTransitionLength = 64;
static const signed char noOffset = -1;
@@ -207,22 +209,20 @@ namespace JSC {
TypeInfo m_typeInfo;
- DeprecatedPtr<Unknown> m_prototype;
- mutable RefPtr<StructureChain> m_cachedPrototypeChain;
+ WriteBarrier<Unknown> m_prototype;
+ mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
- RefPtr<Structure> m_previous;
+ WriteBarrier<Structure> m_previous;
RefPtr<StringImpl> m_nameInPrevious;
- JSCell* m_specificValueInPrevious;
+ WriteBarrier<JSCell> m_specificValueInPrevious;
- // 'm_isUsingSingleSlot' indicates whether we are using the single transition optimisation.
- union {
- TransitionTable* m_table;
- Structure* m_singleTransition;
- } m_transitions;
+ const ClassInfo* m_classInfo;
- WeakGCPtr<JSPropertyNameIterator> m_enumerationCache;
+ StructureTransitionTable m_transitionTable;
- PropertyMapHashTable* m_propertyTable;
+ WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
+
+ OwnPtr<PropertyTable> m_propertyTable;
uint32_t m_propertyStorageCapacity;
@@ -243,53 +243,61 @@ namespace JSC {
#endif
unsigned m_specificFunctionThrashCount : 2;
unsigned m_anonymousSlotCount : 5;
- unsigned m_isUsingSingleSlot : 1;
+ unsigned m_preventExtensions : 1;
// 4 free bits
};
- inline size_t Structure::get(const Identifier& propertyName)
+ inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName)
{
- ASSERT(!propertyName.isNull());
-
- materializePropertyMapIfNecessary();
+ materializePropertyMapIfNecessary(globalData);
if (!m_propertyTable)
- return WTF::notFound;
-
- StringImpl* rep = propertyName.impl();
+ return notFound;
- unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return WTF::notFound;
+ PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
+ ASSERT(!entry || entry->offset >= m_anonymousSlotCount);
+ return entry ? entry->offset : notFound;
+ }
- if (rep == m_propertyTable->entries()[entryIndex - 1].key)
- return m_propertyTable->entries()[entryIndex - 1].offset;
+ inline bool JSCell::isObject() const
+ {
+ return m_structure->typeInfo().type() == ObjectType;
+ }
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
+ inline bool JSCell::isString() const
+ {
+ return m_structure->typeInfo().type() == StringType;
+ }
- unsigned k = 1 | WTF::doubleHash(rep->existingHash());
+ inline const ClassInfo* JSCell::classInfo() const
+ {
+ return m_structure->classInfo();
+ }
- while (1) {
- i += k;
+ inline Structure* JSCell::createDummyStructure(JSGlobalData& globalData)
+ {
+ return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0);
+ }
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
+ inline bool JSValue::needsThisConversion() const
+ {
+ if (UNLIKELY(!isCell()))
+ return true;
+ return asCell()->structure()->typeInfo().needsThisConversion();
+ }
- entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return WTF::notFound;
+ ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
+ {
+ ASSERT(!m_isCheckingForDefaultMarkViolation);
+ ASSERT(cell);
+ if (Heap::testAndSetMarked(cell))
+ return;
+ if (cell->structure()->typeInfo().type() >= CompoundType)
+ m_values.append(cell);
+ }
- if (rep == m_propertyTable->entries()[entryIndex - 1].key)
- return m_propertyTable->entries()[entryIndex - 1].offset;
- }
+ inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)
+ {
+ return Hash::Key(structure->m_nameInPrevious.get(), structure->m_attributesInPrevious);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp
index e4523c3..ad6abff 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.cpp
+++ b/Source/JavaScriptCore/runtime/StructureChain.cpp
@@ -31,19 +31,33 @@
#include <wtf/RefPtr.h>
namespace JSC {
+
+ClassInfo StructureChain::s_info = { "StructureChain", 0, 0, 0 };
-StructureChain::StructureChain(Structure* head)
+StructureChain::StructureChain(JSGlobalData& globalData, Structure* structure, Structure* head)
+ : JSCell(globalData, structure)
{
size_t size = 0;
for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
++size;
- m_vector = adoptArrayPtr(new RefPtr<Structure>[size + 1]);
+ m_vector = adoptArrayPtr(new WriteBarrier<Structure>[size + 1]);
size_t i = 0;
for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
- m_vector[i++] = current;
- m_vector[i] = 0;
+ m_vector[i++].set(globalData, this, current);
+ m_vector[i].clear();
+}
+
+StructureChain::~StructureChain()
+{
+}
+
+void StructureChain::markChildren(MarkStack& markStack)
+{
+ size_t i = 0;
+ while (m_vector[i])
+ markStack.append(&m_vector[i++]);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/StructureChain.h b/Source/JavaScriptCore/runtime/StructureChain.h
index 816b66d..b984be6 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.h
+++ b/Source/JavaScriptCore/runtime/StructureChain.h
@@ -26,6 +26,9 @@
#ifndef StructureChain_h
#define StructureChain_h
+#include "JSCell.h"
+#include "Structure.h"
+
#include <wtf/OwnArrayPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -35,17 +38,21 @@ namespace JSC {
class Structure;
- class StructureChain : public RefCounted<StructureChain> {
+ class StructureChain : public JSCell {
friend class JIT;
public:
- static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
- RefPtr<Structure>* head() { return m_vector.get(); }
+ static StructureChain* create(JSGlobalData& globalData, Structure* head) { return new (&globalData) StructureChain(globalData, globalData.structureChainStructure.get(), head); }
+ WriteBarrier<Structure>* head() { return m_vector.get(); }
+ void markChildren(MarkStack&);
- private:
- StructureChain(Structure* head);
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), 0, &s_info); }
- OwnArrayPtr<RefPtr<Structure> > m_vector;
+ private:
+ StructureChain(JSGlobalData&, Structure*, Structure* head);
+ ~StructureChain();
+ OwnArrayPtr<WriteBarrier<Structure> > m_vector;
+ static ClassInfo s_info;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
index 7e9d7ff..adebad2 100644
--- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h
+++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
@@ -27,17 +27,20 @@
#define StructureTransitionTable_h
#include "UString.h"
+#include "WeakGCMap.h"
#include <wtf/HashFunctions.h>
-#include <wtf/HashMap.h>
#include <wtf/HashTraits.h>
#include <wtf/OwnPtr.h>
#include <wtf/RefPtr.h>
namespace JSC {
- class Structure;
+class Structure;
- struct StructureTransitionTableHash {
+class StructureTransitionTable {
+ static const intptr_t UsingSingleSlotFlag = 1;
+
+ struct Hash {
typedef std::pair<RefPtr<StringImpl>, unsigned> Key;
static unsigned hash(const Key& p)
{
@@ -52,7 +55,7 @@ namespace JSC {
static const bool safeToCompareToEmptyOrDeleted = true;
};
- struct StructureTransitionTableHashTraits {
+ struct HashTraits {
typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits;
typedef WTF::GenericHashTraits<unsigned> SecondTraits;
typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
@@ -66,6 +69,105 @@ namespace JSC {
static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
};
+ struct WeakGCMapFinalizerCallback {
+ static void* finalizerContextFor(Hash::Key)
+ {
+ return 0;
+ }
+
+ static inline Hash::Key keyForFinalizer(void* context, Structure* structure)
+ {
+ return keyForWeakGCMapFinalizer(context, structure);
+ }
+ };
+
+ typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap;
+
+ static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
+
+public:
+ StructureTransitionTable()
+ : m_data(UsingSingleSlotFlag)
+ {
+ }
+
+ ~StructureTransitionTable()
+ {
+ if (!isUsingSingleSlot())
+ delete map();
+ else
+ clearSingleTransition();
+ }
+
+ inline void add(JSGlobalData&, Structure*);
+ inline void remove(Structure*);
+ inline bool contains(StringImpl* rep, unsigned attributes) const;
+ inline Structure* get(StringImpl* rep, unsigned attributes) const;
+
+private:
+ bool isUsingSingleSlot() const
+ {
+ return m_data & UsingSingleSlotFlag;
+ }
+
+ TransitionMap* map() const
+ {
+ ASSERT(!isUsingSingleSlot());
+ return reinterpret_cast<TransitionMap*>(m_data);
+ }
+
+ HandleSlot slot() const
+ {
+ ASSERT(isUsingSingleSlot());
+ return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag);
+ }
+
+ void setMap(TransitionMap* map)
+ {
+ ASSERT(isUsingSingleSlot());
+
+ if (HandleSlot slot = this->slot())
+ HandleHeap::heapFor(slot)->deallocate(slot);
+
+ // This implicitly clears the flag that indicates we're using a single transition
+ m_data = reinterpret_cast<intptr_t>(map);
+
+ ASSERT(!isUsingSingleSlot());
+ }
+
+ Structure* singleTransition() const
+ {
+ ASSERT(isUsingSingleSlot());
+ if (HandleSlot slot = this->slot()) {
+ if (*slot)
+ return reinterpret_cast<Structure*>(slot->asCell());
+ }
+ return 0;
+ }
+
+ void clearSingleTransition()
+ {
+ ASSERT(isUsingSingleSlot());
+ if (HandleSlot slot = this->slot())
+ HandleHeap::heapFor(slot)->deallocate(slot);
+ }
+
+ void setSingleTransition(JSGlobalData& globalData, Structure* structure)
+ {
+ ASSERT(isUsingSingleSlot());
+ HandleSlot slot = this->slot();
+ if (!slot) {
+ slot = globalData.allocateGlobalHandle();
+ HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0);
+ m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag;
+ }
+ HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure));
+ *slot = reinterpret_cast<JSCell*>(structure);
+ }
+
+ intptr_t m_data;
+};
+
} // namespace JSC
#endif // StructureTransitionTable_h
diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp
index 04d904d..d3867d4 100644
--- a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp
+++ b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp
@@ -101,7 +101,7 @@ static inline unsigned getCPUTime()
// use a relative time from first call in order to avoid an overflow
static double firstTime = currentTime();
- return (currentTime() - firstTime) * 1000;
+ return static_cast<unsigned> ((currentTime() - firstTime) * 1000);
#endif
}
diff --git a/Source/JavaScriptCore/runtime/UString.h b/Source/JavaScriptCore/runtime/UString.h
index 8f6c083..b98e7b4 100644
--- a/Source/JavaScriptCore/runtime/UString.h
+++ b/Source/JavaScriptCore/runtime/UString.h
@@ -252,10 +252,7 @@ template<> struct DefaultHash<JSC::UString> {
typedef JSC::UStringHash Hash;
};
-template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits
-{
- static const bool canInitializeWithMemset = true;
-};
+template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits { };
} // namespace WTF
diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h
index 7bf4503..5ad1c62 100644
--- a/Source/JavaScriptCore/runtime/WeakGCMap.h
+++ b/Source/JavaScriptCore/runtime/WeakGCMap.h
@@ -26,110 +26,165 @@
#ifndef WeakGCMap_h
#define WeakGCMap_h
-#include "Heap.h"
+#include "Handle.h"
+#include "JSGlobalData.h"
#include <wtf/HashMap.h>
namespace JSC {
-class JSCell;
+// A HashMap for GC'd values that removes entries when the associated value
+// dies.
+template <typename KeyType, typename MappedType> struct DefaultWeakGCMapFinalizerCallback {
+ static void* finalizerContextFor(KeyType key)
+ {
+ return reinterpret_cast<void*>(key);
+ }
+
+ static KeyType keyForFinalizer(void* context, typename HandleTypes<MappedType>::ExternalType)
+ {
+ return reinterpret_cast<KeyType>(context);
+ }
+};
-// A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
-template<typename KeyType, typename MappedType>
-class WeakGCMap {
+template<typename KeyType, typename MappedType, typename FinalizerCallback = DefaultWeakGCMapFinalizerCallback<KeyType, MappedType>, typename HashArg = typename DefaultHash<KeyType>::Hash, typename KeyTraitsArg = HashTraits<KeyType> >
+class WeakGCMap : private WeakHandleOwner {
WTF_MAKE_FAST_ALLOCATED;
- /*
- Invariants:
- * A value enters the WeakGCMap marked. (Guaranteed by set().)
- * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.)
- * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.)
- * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.)
- */
+ WTF_MAKE_NONCOPYABLE(WeakGCMap);
+
+ typedef HashMap<KeyType, HandleSlot, HashArg, KeyTraitsArg> MapType;
+ typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
+ typedef typename MapType::iterator map_iterator;
public:
- typedef typename HashMap<KeyType, DeprecatedPtr<MappedType> >::iterator iterator;
- typedef typename HashMap<KeyType, DeprecatedPtr<MappedType> >::const_iterator const_iterator;
-
+
+ struct iterator {
+ friend class WeakGCMap;
+ iterator(map_iterator iter)
+ : m_iterator(iter)
+ {
+ }
+
+ std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(m_iterator->second)); }
+ std::pair<KeyType, HandleSlot> getSlot() const { return *m_iterator; }
+
+ iterator& operator++() { ++m_iterator; return *this; }
+
+ // postfix ++ intentionally omitted
+
+ // Comparison.
+ bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
+ bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
+
+ private:
+ map_iterator m_iterator;
+ };
+
+ WeakGCMap()
+ {
+ }
+
bool isEmpty() { return m_map.isEmpty(); }
- void clear() { m_map.clear(); }
+ void clear()
+ {
+ map_iterator end = m_map.end();
+ for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
+ HandleHeap::heapFor(ptr->second)->deallocate(ptr->second);
+ m_map.clear();
+ }
- MappedType* get(const KeyType&) const;
- pair<iterator, bool> set(const KeyType&, MappedType*);
- MappedType* take(const KeyType&);
+ bool contains(const KeyType& key) const
+ {
+ return m_map.contains(key);
+ }
- // These unchecked functions provide access to a value even if the value's
- // mark bit is not set. This is used, among other things, to retrieve values
- // during the GC mark phase, which begins by clearing all mark bits.
-
- size_t uncheckedSize() { return m_map.size(); }
+ iterator find(const KeyType& key)
+ {
+ return m_map.find(key);
+ }
- MappedType* uncheckedGet(const KeyType& key) const { return m_map.get(key).get(); }
- DeprecatedPtr<MappedType>* uncheckedGetSlot(const KeyType& key)
+ void remove(iterator iter)
{
- iterator iter = m_map.find(key);
- if (iter == m_map.end())
- return 0;
- return &iter->second;
+ ASSERT(iter.m_iterator != m_map.end());
+ HandleSlot slot = iter.m_iterator->second;
+ ASSERT(slot);
+ HandleHeap::heapFor(slot)->deallocate(slot);
+ m_map.remove(iter.m_iterator);
}
- bool uncheckedRemove(const KeyType&, MappedType*);
- iterator uncheckedBegin() { return m_map.begin(); }
- iterator uncheckedEnd() { return m_map.end(); }
+ ExternalType get(const KeyType& key) const
+ {
+ return HandleTypes<MappedType>::getFromSlot(m_map.get(key));
+ }
- const_iterator uncheckedBegin() const { return m_map.begin(); }
- const_iterator uncheckedEnd() const { return m_map.end(); }
+ HandleSlot getSlot(const KeyType& key) const
+ {
+ return m_map.get(key);
+ }
- bool isValid(iterator it) const { return Heap::isMarked(it->second.get()); }
- bool isValid(const_iterator it) const { return Heap::isMarked(it->second.get()); }
+ pair<iterator, bool> add(JSGlobalData& globalData, const KeyType& key, ExternalType value)
+ {
+ pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
+ if (iter.second) {
+ HandleSlot slot = globalData.allocateGlobalHandle();
+ iter.first->second = slot;
+ HandleHeap::heapFor(slot)->makeWeak(slot, this, FinalizerCallback::finalizerContextFor(key));
+ HandleHeap::heapFor(slot)->writeBarrier(slot, value);
+ *slot = value;
+ }
+ return iter;
+ }
+
+ void set(iterator iter, ExternalType value)
+ {
+ HandleSlot slot = iter.m_iterator->second;
+ ASSERT(slot);
+ HandleHeap::heapFor(slot)->writeBarrier(slot, value);
+ *slot = value;
+ }
-private:
- HashMap<KeyType, DeprecatedPtr<MappedType> > m_map;
-};
+ void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
+ {
+ pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
+ HandleSlot slot = iter.first->second;
+ if (iter.second) {
+ slot = globalData.allocateGlobalHandle();
+ HandleHeap::heapFor(slot)->makeWeak(slot, this, key);
+ iter.first->second = slot;
+ }
+ HandleHeap::heapFor(slot)->writeBarrier(slot, value);
+ *slot = value;
+ }
-template<typename KeyType, typename MappedType>
-inline MappedType* WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
-{
- MappedType* result = m_map.get(key).get();
- if (result == HashTraits<MappedType*>::emptyValue())
- return result;
- if (!Heap::isMarked(result))
- return HashTraits<MappedType*>::emptyValue();
- return result;
-}
-
-template<typename KeyType, typename MappedType>
-MappedType* WeakGCMap<KeyType, MappedType>::take(const KeyType& key)
-{
- MappedType* result = m_map.take(key).get();
- if (result == HashTraits<MappedType*>::emptyValue())
+ ExternalType take(const KeyType& key)
+ {
+ HandleSlot slot = m_map.take(key);
+ if (!slot)
+ return HashTraits<ExternalType>::emptyValue();
+ ExternalType result = HandleTypes<MappedType>::getFromSlot(slot);
+ HandleHeap::heapFor(slot)->deallocate(slot);
return result;
- if (!Heap::isMarked(result))
- return HashTraits<MappedType*>::emptyValue();
- return result;
-}
-
-template<typename KeyType, typename MappedType>
-pair<typename WeakGCMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, MappedType* value)
-{
- Heap::setMarked(value); // If value is newly allocated, it's not marked, so mark it now.
- pair<iterator, bool> result = m_map.add(key, value);
- if (!result.second) { // pre-existing entry
- result.second = !Heap::isMarked(result.first->second.get());
- result.first->second = value;
}
- return result;
-}
-
-template<typename KeyType, typename MappedType>
-bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, MappedType* value)
-{
- iterator it = m_map.find(key);
- if (it == m_map.end())
- return false;
- if (it->second.get() != value)
- return false;
- m_map.remove(it);
- return true;
-}
+
+ size_t size() { return m_map.size(); }
+
+ iterator begin() { return iterator(m_map.begin()); }
+ iterator end() { return iterator(m_map.end()); }
+
+ ~WeakGCMap()
+ {
+ clear();
+ }
+
+private:
+ virtual void finalize(Handle<Unknown> handle, void* context)
+ {
+ HandleSlot slot = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot())));
+ ASSERT(slot);
+ HandleHeap::heapFor(slot)->deallocate(slot);
+ }
+
+ MapType m_map;
+};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/WeakGCPtr.h b/Source/JavaScriptCore/runtime/WeakGCPtr.h
deleted file mode 100644
index 4946ee7..0000000
--- a/Source/JavaScriptCore/runtime/WeakGCPtr.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 WeakGCPtr_h
-#define WeakGCPtr_h
-
-#include "Heap.h"
-#include "GCHandle.h"
-
-namespace JSC {
-
-// A smart pointer whose get() function returns 0 for cells awaiting destruction.
-template <typename T> class WeakGCPtr {
- WTF_MAKE_NONCOPYABLE(WeakGCPtr);
-public:
- WeakGCPtr()
- : m_ptr(0)
- {
- }
-
- WeakGCPtr(T* ptr) { assign(ptr); }
-
- ~WeakGCPtr()
- {
- if (m_ptr)
- m_ptr->pool()->free(m_ptr);
- }
-
- T* get() const
- {
- if (m_ptr && m_ptr->isValidPtr())
- return static_cast<T*>(m_ptr->get());
- return 0;
- }
-
- bool clear(JSCell* p)
- {
- if (!m_ptr || m_ptr->get() != p)
- return false;
-
- m_ptr->pool()->free(m_ptr);
- m_ptr = 0;
- return true;
- }
-
- T& operator*() const { return *get(); }
- T* operator->() const { return get(); }
-
- bool operator!() const { return !get(); }
-
- // This conversion operator allows implicit conversion to bool but not to other integer types.
-#if COMPILER(WINSCW)
- operator bool() const { return m_ptr; }
-#else
- typedef WeakGCHandle* WeakGCPtr::*UnspecifiedBoolType;
- operator UnspecifiedBoolType() const { return get() ? &WeakGCPtr::m_ptr : 0; }
-#endif
-
- WeakGCPtr& operator=(T*);
-
-#if !ASSERT_DISABLED
- bool hasDeadObject() const { return !!m_ptr; }
-#endif
-
-private:
- void assign(JSCell* ptr)
- {
- ASSERT(ptr);
- if (m_ptr)
- m_ptr->set(ptr);
- else
- m_ptr = Heap::heap(ptr)->addWeakGCHandle(ptr);
- }
-
- WeakGCHandle* m_ptr;
-};
-
-template <typename T> inline WeakGCPtr<T>& WeakGCPtr<T>::operator=(T* optr)
-{
- assign(optr);
- return *this;
-}
-
-template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b)
-{
- return a.get() == b.get();
-}
-
-template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, U* b)
-{
- return a.get() == b;
-}
-
-template <typename T, typename U> inline bool operator==(T* a, const WeakGCPtr<U>& b)
-{
- return a == b.get();
-}
-
-template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b)
-{
- return a.get() != b.get();
-}
-
-template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, U* b)
-{
- return a.get() != b;
-}
-
-template <typename T, typename U> inline bool operator!=(T* a, const WeakGCPtr<U>& b)
-{
- return a != b.get();
-}
-
-template <typename T, typename U> inline WeakGCPtr<T> static_pointer_cast(const WeakGCPtr<U>& p)
-{
- return WeakGCPtr<T>(static_cast<T*>(p.get()));
-}
-
-template <typename T, typename U> inline WeakGCPtr<T> const_pointer_cast(const WeakGCPtr<U>& p)
-{
- return WeakGCPtr<T>(const_cast<T*>(p.get()));
-}
-
-template <typename T> inline T* get(const WeakGCPtr<T>& p)
-{
- return p.get();
-}
-
-} // namespace JSC
-
-#endif // WeakGCPtr_h
diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h
index 64150ed..32cb968 100644
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
@@ -32,62 +32,59 @@ namespace JSC {
class JSCell;
class JSGlobalData;
-typedef enum { } Unknown;
-
-template <class T> class DeprecatedPtr {
-public:
- DeprecatedPtr() : m_cell(0) { }
- DeprecatedPtr(T* cell) : m_cell(reinterpret_cast<JSCell*>(cell)) { }
- T* get() const { return reinterpret_cast<T*>(m_cell); }
- T* operator*() const { return static_cast<T*>(m_cell); }
- T* operator->() const { return static_cast<T*>(m_cell); }
-
- JSCell** slot() { return &m_cell; }
-
- typedef T* (DeprecatedPtr::*UnspecifiedBoolType);
- operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
-
- bool operator!() const { return !m_cell; }
+inline void writeBarrier(JSGlobalData&, const JSCell*, JSValue)
+{
+}
-protected:
- JSCell* m_cell;
-};
+inline void writeBarrier(JSGlobalData&, const JSCell*, JSCell*)
+{
+}
-template <> class DeprecatedPtr<Unknown> {
-public:
- DeprecatedPtr() { }
- DeprecatedPtr(JSValue value) : m_value(value) { }
- DeprecatedPtr(JSCell* value) : m_value(value) { }
- const JSValue& get() const { return m_value; }
- const JSValue* operator*() const { return &m_value; }
- const JSValue* operator->() const { return &m_value; }
-
- JSValue* slot() { return &m_value; }
-
- typedef JSValue (DeprecatedPtr::*UnspecifiedBoolType);
- operator UnspecifiedBoolType*() const { return m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
- bool operator!() const { return !m_value; }
-
-private:
- JSValue m_value;
-};
+typedef enum { } Unknown;
+typedef JSValue* HandleSlot;
-template <typename T> struct WriteBarrierCheck {
+template <typename T> struct JSValueChecker {
static const bool IsJSValue = false;
};
-template <> struct WriteBarrierCheck<JSValue> {
+template <> struct JSValueChecker<JSValue> {
static const bool IsJSValue = true;
};
+// We have a separate base class with no constructors for use in Unions.
template <typename T> class WriteBarrierBase {
public:
- COMPILE_ASSERT(!WriteBarrierCheck<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown);
- void set(JSGlobalData&, const JSCell*, T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); }
+ COMPILE_ASSERT(!JSValueChecker<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown);
+ void set(JSGlobalData& globalData, const JSCell* owner, T* value)
+ {
+ this->m_cell = reinterpret_cast<JSCell*>(value);
+ writeBarrier(globalData, owner, this->m_cell);
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!isZombie(owner));
+ ASSERT(!isZombie(m_cell));
+#endif
+ }
- T* get() const { return reinterpret_cast<T*>(m_cell); }
- T* operator*() const { return static_cast<T*>(m_cell); }
- T* operator->() const { return static_cast<T*>(m_cell); }
+ T* get() const
+ {
+ return reinterpret_cast<T*>(m_cell);
+ }
+
+ T* operator*() const
+ {
+ ASSERT(m_cell);
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!isZombie(m_cell));
+#endif
+ return static_cast<T*>(m_cell);
+ }
+
+ T* operator->() const
+ {
+ ASSERT(m_cell);
+ return static_cast<T*>(m_cell);
+ }
+
void clear() { m_cell = 0; }
JSCell** slot() { return &m_cell; }
@@ -97,30 +94,46 @@ public:
bool operator!() const { return !m_cell; }
- void setWithoutWriteBarrier(T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); }
+ void setWithoutWriteBarrier(T* value)
+ {
+ this->m_cell = reinterpret_cast<JSCell*>(value);
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!m_cell || !isZombie(m_cell));
+#endif
+ }
-protected:
+private:
JSCell* m_cell;
};
-template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
+template <> class WriteBarrierBase<Unknown> {
public:
- WriteBarrier() { this->m_cell = 0; }
- WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
+ void set(JSGlobalData& globalData, const JSCell* owner, JSValue value)
{
- this->set(globalData, owner, value);
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!isZombie(owner));
+ ASSERT(!value.isZombie());
+#endif
+ m_value = JSValue::encode(value);
+ writeBarrier(globalData, owner, value);
+ }
+ void setWithoutWriteBarrier(JSValue value)
+ {
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!value.isZombie());
+#endif
+ m_value = JSValue::encode(value);
}
-};
-
-template <> class WriteBarrierBase<Unknown> {
-public:
- void set(JSGlobalData&, const JSCell*, JSValue value) { m_value = JSValue::encode(value); }
- void setWithoutWriteBarrier(JSValue value) { m_value = JSValue::encode(value); }
- JSValue get() const { return JSValue::decode(m_value); }
+ JSValue get() const
+ {
+ return JSValue::decode(m_value);
+ }
void clear() { m_value = JSValue::encode(JSValue()); }
void setUndefined() { m_value = JSValue::encode(jsUndefined()); }
bool isNumber() const { return get().isNumber(); }
+ bool isObject() const { return get().isObject(); }
+ bool isNull() const { return get().isNull(); }
bool isGetterSetter() const { return get().isGetterSetter(); }
JSValue* slot()
@@ -137,29 +150,41 @@ public:
operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
bool operator!() const { return !get(); }
-protected:
+private:
EncodedJSValue m_value;
};
+template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
+public:
+ WriteBarrier()
+ {
+ this->setWithoutWriteBarrier(0);
+ }
+
+ WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
+ {
+ this->set(globalData, owner, value);
+ }
+};
+
template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
public:
- WriteBarrier() { m_value = JSValue::encode(JSValue()); }
+ WriteBarrier()
+ {
+ this->setWithoutWriteBarrier(JSValue());
+ }
+
WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value)
{
this->set(globalData, owner, value);
}
};
-template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs)
-{
- return lhs.get() == rhs.get();
-}
-
template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs)
{
return lhs.get() == rhs.get();
}
-}
+} // namespace JSC
#endif // WriteBarrier_h