summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-24 11:24:40 +0100
committerBen Murdoch <benm@google.com>2011-06-02 09:53:15 +0100
commit81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch)
tree7a9e5ed86ff429fd347a25153107221543909b19 /Source/JavaScriptCore/runtime
parent94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff)
downloadexternal_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/JavaScriptCore/runtime')
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.h4
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.cpp42
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.h62
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConstructor.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.h5
-rw-r--r--Source/JavaScriptCore/runtime/BooleanObject.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/BooleanObject.h7
-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.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/Completion.h4
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.h2
-rw-r--r--Source/JavaScriptCore/runtime/DateConversion.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.h7
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.cpp70
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.h5
-rw-r--r--Source/JavaScriptCore/runtime/ErrorInstance.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/ErrorInstance.h9
-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.cpp24
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h20
-rw-r--r--Source/JavaScriptCore/runtime/FunctionConstructor.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/FunctionPrototype.cpp17
-rw-r--r--Source/JavaScriptCore/runtime/FunctionPrototype.h6
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.h4
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/GCHandle.cpp86
-rw-r--r--Source/JavaScriptCore/runtime/GCHandle.h116
-rw-r--r--Source/JavaScriptCore/runtime/GetterSetter.h2
-rw-r--r--Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp48
-rw-r--r--Source/JavaScriptCore/runtime/GlobalEvalFunction.h54
-rw-r--r--Source/JavaScriptCore/runtime/Heap.cpp78
-rw-r--r--Source/JavaScriptCore/runtime/Heap.h18
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/InitializeThreading.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/InternalFunction.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/InternalFunction.h9
-rw-r--r--Source/JavaScriptCore/runtime/JSAPIValueWrapper.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.cpp27
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.h13
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp18
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h10
-rw-r--r--Source/JavaScriptCore/runtime/JSByteArray.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSByteArray.h36
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h72
-rw-r--r--Source/JavaScriptCore/runtime/JSChunk.cpp28
-rw-r--r--Source/JavaScriptCore/runtime/JSChunk.h31
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.cpp37
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.h20
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp22
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h15
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp105
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h64
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/JSLock.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSNotAnObject.h6
-rw-r--r--Source/JavaScriptCore/runtime/JSNumberCell.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.cpp25
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.h5
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp50
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h172
-rw-r--r--Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h6
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp16
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.h16
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSString.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSTypeInfo.h13
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.h44
-rw-r--r--Source/JavaScriptCore/runtime/JSWrapperObject.h6
-rw-r--r--Source/JavaScriptCore/runtime/JSZombie.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/JSZombie.h9
-rw-r--r--Source/JavaScriptCore/runtime/Lookup.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/MachineStackMarker.cpp67
-rw-r--r--Source/JavaScriptCore/runtime/MarkedBlock.cpp33
-rw-r--r--Source/JavaScriptCore/runtime/MarkedBlock.h177
-rw-r--r--Source/JavaScriptCore/runtime/MarkedSpace.cpp103
-rw-r--r--Source/JavaScriptCore/runtime/MarkedSpace.h85
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.h5
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorConstructor.h9
-rw-r--r--Source/JavaScriptCore/runtime/NativeFunctionWrapper.h39
-rw-r--r--Source/JavaScriptCore/runtime/NumberConstructor.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/NumberConstructor.h6
-rw-r--r--Source/JavaScriptCore/runtime/NumberObject.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/NumberObject.h6
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/ObjectConstructor.cpp110
-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.h7
-rw-r--r--Source/JavaScriptCore/runtime/PropertyMapHashTable.h554
-rw-r--r--Source/JavaScriptCore/runtime/PropertyNameArray.cpp1
-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/RegExpConstructor.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.h8
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.h9
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChain.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChain.h189
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChainMark.h6
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.h4
-rw-r--r--Source/JavaScriptCore/runtime/StrictEvalActivation.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/StrictEvalActivation.h2
-rw-r--r--Source/JavaScriptCore/runtime/StringConstructor.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/StringConstructor.h2
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.h7
-rw-r--r--Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h2
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.h8
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp1017
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h134
-rw-r--r--Source/JavaScriptCore/runtime/StructureTransitionTable.h65
-rw-r--r--Source/JavaScriptCore/runtime/WeakGCMap.h187
-rw-r--r--Source/JavaScriptCore/runtime/WeakGCPtr.h139
-rw-r--r--Source/JavaScriptCore/runtime/WriteBarrier.h1
137 files changed, 2498 insertions, 2651 deletions
diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp
index a862ea0..25a8916 100644
--- a/Source/JavaScriptCore/runtime/ArgList.cpp
+++ b/Source/JavaScriptCore/runtime/ArgList.cpp
@@ -23,6 +23,7 @@
#include "JSValue.h"
#include "JSCell.h"
+#include "ScopeChain.h"
using std::min;
diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h
index 57e3c20..5564d5b 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;
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..007e0f1 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)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(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->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->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,14 +227,15 @@ 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);
@@ -247,8 +249,8 @@ namespace JSC {
int registerOffset = 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, d()->registers - registerOffset, registerArraySize);
+ 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..af2afc6 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, NonNullPassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* functionStructure)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, arrayPrototype->classInfo()->className))
{
// ECMA 15.4.3.1 Array.prototype
@@ -48,7 +47,7 @@ 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)
@@ -94,7 +93,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/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
index 70c0d06..488effd 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
@@ -117,6 +117,7 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a
ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
: JSArray(structure)
{
+ ASSERT(inherits(&s_info));
putAnonymousValue(globalObject->globalData(), 0, globalObject);
}
@@ -165,7 +166,7 @@ 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);
@@ -224,7 +225,7 @@ 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);
@@ -330,7 +331,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) {
@@ -470,7 +471,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
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)
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h
index 42665e3..e41d8ca 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.h
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h
@@ -33,12 +33,11 @@ namespace JSC {
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)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp
index 71ff2d2..16c4669 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)
: 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..e2af0c2 100644
--- a/Source/JavaScriptCore/runtime/BooleanObject.h
+++ b/Source/JavaScriptCore/runtime/BooleanObject.h
@@ -29,12 +29,11 @@ namespace JSC {
public:
explicit BooleanObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure>);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const ClassInfo s_info;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(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..d0a64af 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, NonNullPassRefPtr<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..d6d3d9f 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*, NonNullPassRefPtr<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..83d8bd8 100644
--- a/Source/JavaScriptCore/runtime/Completion.cpp
+++ b/Source/JavaScriptCore/runtime/Completion.cpp
@@ -47,19 +47,19 @@ 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());
+ JSObject* error = program->compile(exec, scopeChain);
if (error)
return Completion(Throw, error);
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.get(), 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/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp
index f1f3956..efaeb0f 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,16 +57,16 @@ 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, NonNullPassRefPtr<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
@@ -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);
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.h b/Source/JavaScriptCore/runtime/DateConstructor.h
index c8ca456..2adcd08 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.h
+++ b/Source/JavaScriptCore/runtime/DateConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class DateConstructor : public InternalFunction {
public:
- DateConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
+ DateConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure, DatePrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp
index d4b8232..597f1e9 100644
--- a/Source/JavaScriptCore/runtime/DateConversion.cpp
+++ b/Source/JavaScriptCore/runtime/DateConversion.cpp
@@ -44,6 +44,7 @@
#include "DateConversion.h"
#include "CallFrame.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..95d5dc2 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.cpp
+++ b/Source/JavaScriptCore/runtime/DateInstance.cpp
@@ -32,23 +32,26 @@ 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)
: JSWrapperObject(exec->globalData(), structure)
{
+ ASSERT(inherits(&s_info));
setInternalValue(exec->globalData(), jsNaN());
}
DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time)
: JSWrapperObject(exec->globalData(), structure)
{
+ ASSERT(inherits(&s_info));
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..627b9e7 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.h
+++ b/Source/JavaScriptCore/runtime/DateInstance.h
@@ -37,7 +37,7 @@ namespace JSC {
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
{
@@ -55,7 +55,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
@@ -64,7 +64,6 @@ namespace JSC {
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 +72,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..314baa4 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
@@ -432,6 +432,8 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState
DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<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..dca90e3 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.h
+++ b/Source/JavaScriptCore/runtime/DatePrototype.h
@@ -34,12 +34,11 @@ 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;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.cpp b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
index a6208d5..0db2af8 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
@@ -23,19 +23,21 @@
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)
+ : JSNonFinalObject(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)
+ : JSNonFinalObject(structure)
, m_appendSourceToMessage(false)
{
+ ASSERT(inherits(&s_info));
putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
}
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h
index b3bebec..c1beef7 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.h
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.h
@@ -25,11 +25,14 @@
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 PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
static ErrorInstance* create(JSGlobalData*, NonNullPassRefPtr<Structure>, const UString&);
static ErrorInstance* create(ExecState* exec, NonNullPassRefPtr<Structure>, JSValue message);
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
index b4e0a7c..e13251c 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, NonNullPassRefPtr<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..3c2fed3 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*, NonNullPassRefPtr<Structure>, Structure* functionStructure);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
index 4a58800..d3c637e 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->interruptedExecutionErrorStructure)
{
}
@@ -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->terminatedExecutionErrorStructure)
{
}
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 25c551b..607a2c2 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -35,11 +35,9 @@
namespace JSC {
-#if ENABLE(JIT)
NativeExecutable::~NativeExecutable()
{
}
-#endif
VPtrHackExecutable::~VPtrHackExecutable()
{
@@ -103,12 +101,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();
@@ -156,11 +153,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();
@@ -196,12 +192,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();
@@ -242,12 +237,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();
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 544e487..b2565a0 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -92,22 +92,29 @@ namespace JSC {
#endif
};
-#if ENABLE(JIT)
class NativeExecutable : public ExecutableBase {
friend class JIT;
public:
+#if ENABLE(JIT)
static PassRefPtr<NativeExecutable> create(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));
}
+#else
+ static PassRefPtr<NativeExecutable> create(NativeFunction function, NativeFunction constructor)
+ {
+ return adoptRef(new NativeExecutable(function, constructor));
+ }
+#endif
~NativeExecutable();
NativeFunction function() { return m_function; }
private:
+#if ENABLE(JIT)
NativeExecutable(JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor)
: ExecutableBase(NUM_PARAMETERS_IS_HOST)
, m_function(function)
@@ -118,13 +125,20 @@ namespace JSC {
m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
}
+#else
+ NativeExecutable(NativeFunction function, NativeFunction constructor)
+ : ExecutableBase(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:
@@ -398,13 +412,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..e642594 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -106,8 +106,8 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
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
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
index e651538..c2d8ad3 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 {
@@ -44,12 +43,12 @@ FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObje
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..fb0bb48 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);
+ void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction);
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(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..a941cfa 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
@@ -33,10 +33,11 @@
#include "Heap.h"
#include "JSGlobalData.h"
#include "JSLock.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..68a8c70 100644
--- a/Source/JavaScriptCore/runtime/GetterSetter.h
+++ b/Source/JavaScriptCore/runtime/GetterSetter.h
@@ -49,7 +49,7 @@ namespace JSC {
void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.set(globalData, this, setter); }
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount);
+ return Structure::create(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
index c05233c..c52bcfe 100644
--- a/Source/JavaScriptCore/runtime/Heap.cpp
+++ b/Source/JavaScriptCore/runtime/Heap.cpp
@@ -24,7 +24,6 @@
#include "CodeBlock.h"
#include "ConservativeSet.h"
#include "GCActivityCallback.h"
-#include "GCHandle.h"
#include "Interpreter.h"
#include "JSGlobalData.h"
#include "JSGlobalObject.h"
@@ -33,7 +32,7 @@
#include "Tracing.h"
#include <algorithm>
-#define COLLECT_ON_EVERY_ALLOCATION 0
+#define COLLECT_ON_EVERY_SLOW_ALLOCATION 0
using namespace std;
@@ -49,8 +48,10 @@ Heap::Heap(JSGlobalData* globalData)
, m_globalData(globalData)
, m_machineStackMarker(this)
, m_markStack(globalData->jsArrayVPtr)
+ , m_handleHeap(globalData)
, m_extraCost(0)
{
+ m_markedSpace.setHighWaterMark(minBytesPerCycle);
(*m_activityCallback)();
}
@@ -76,7 +77,8 @@ void Heap::destroy()
delete m_markListSet;
m_markListSet = 0;
-
+ m_markedSpace.clearMarks();
+ m_handleHeap.clearWeakPointers();
m_markedSpace.destroy();
m_globalData = 0;
@@ -100,64 +102,29 @@ void Heap::reportExtraMemoryCostSlowCase(size_t cost)
m_extraCost += cost;
}
-void* Heap::allocate(size_t s)
+void* Heap::allocateSlowCase(size_t bytes)
{
ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
ASSERT(JSLock::lockCount() > 0);
ASSERT(JSLock::currentThreadIsHoldingLock());
- ASSERT_UNUSED(s, s <= MarkedBlock::CELL_SIZE);
+ ASSERT(bytes <= MarkedSpace::maxCellSize);
ASSERT(m_operationInProgress == NoOperation);
-#if COLLECT_ON_EVERY_ALLOCATION
+#if COLLECT_ON_EVERY_SLOW_ALLOCATION
collectAllGarbage();
ASSERT(m_operationInProgress == NoOperation);
#endif
+ reset(DoNotSweep);
+
m_operationInProgress = Allocation;
- void* result = m_markedSpace.allocate(s);
+ void* result = m_markedSpace.allocate(bytes);
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);
@@ -269,14 +236,16 @@ void Heap::markRoots()
JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
markStack.drain();
+ m_handleHeap.markStrongHandles(markStack);
+
// 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_handleHeap.updateAfterMark();
m_operationInProgress = NoOperation;
}
@@ -298,18 +267,17 @@ size_t Heap::capacity() const
size_t Heap::globalObjectCount()
{
- return m_globalData->globalObjects.uncheckedSize();
+ return m_globalData->globalObjectCount;
}
size_t Heap::protectedGlobalObjectCount()
{
- size_t count = 0;
+ size_t count = m_handleHeap.protectedGlobalObjectCount();
- 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;
+ ProtectCountSet::iterator end = m_protectedValues.end();
+ for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
+ if (it->first->isObject() && asObject(it->first)->isGlobalObject())
+ count++;
}
return count;
@@ -402,6 +370,10 @@ void Heap::reset(SweepToggle sweepToggle)
m_markedSpace.reset();
m_extraCost = 0;
+#if ENABLE(JSC_ZOMBIES)
+ sweep();
+#endif
+
if (sweepToggle == DoSweep) {
m_markedSpace.sweep();
m_markedSpace.shrink();
diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h
index 6591a5b..eb8af70 100644
--- a/Source/JavaScriptCore/runtime/Heap.h
+++ b/Source/JavaScriptCore/runtime/Heap.h
@@ -22,9 +22,11 @@
#ifndef Heap_h
#define Heap_h
+#include "HandleHeap.h"
#include "MarkStack.h"
#include "MarkedSpace.h"
#include <wtf/Forward.h>
+#include <wtf/HashCountedSet.h>
#include <wtf/HashSet.h>
namespace JSC {
@@ -34,7 +36,6 @@ namespace JSC {
class JSCell;
class JSGlobalData;
class JSValue;
- class JSValue;
class LiveObjectIterator;
class MarkStack;
class MarkedArgumentBuffer;
@@ -89,8 +90,6 @@ namespace JSC {
PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
PassOwnPtr<TypeCountSet> objectTypeCounts();
- WeakGCHandle* addWeakGCHandle(JSCell*);
-
void pushTempSortVector(Vector<ValueStringPair>*);
void popTempSortVector(Vector<ValueStringPair>*);
@@ -100,21 +99,21 @@ namespace JSC {
template <typename Functor> void forEach(Functor&);
+ HandleSlot allocateGlobalHandle() { return m_handleHeap.allocate(); }
+
private:
friend class JSGlobalData;
static const size_t minExtraCost = 256;
static const size_t maxExtraCost = 1024 * 1024;
+ void* allocateSlowCase(size_t);
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);
@@ -124,7 +123,6 @@ namespace JSC {
MarkedSpace m_markedSpace;
ProtectCountSet m_protectedValues;
- Vector<PageAllocationAligned> m_weakGCHandlePools;
Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
HashSet<GlobalCodeBlock*> m_codeBlocks;
@@ -136,6 +134,7 @@ namespace JSC {
MachineStackMarker m_machineStackMarker;
MarkStack m_markStack;
+ HandleHeap m_handleHeap;
size_t m_extraCost;
};
@@ -165,11 +164,6 @@ namespace JSC {
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)
{
diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp
index 28cfd0a..3992418 100644
--- a/Source/JavaScriptCore/runtime/Identifier.cpp
+++ b/Source/JavaScriptCore/runtime/Identifier.cpp
@@ -23,6 +23,7 @@
#include "CallFrame.h"
#include "NumericStrings.h"
+#include "ScopeChain.h"
#include <new> // for placement new
#include <string.h> // for strlen
#include <wtf/Assertions.h>
diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp
index 27611b7..aef60c8 100644
--- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp
+++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp
@@ -59,6 +59,7 @@ static void initializeThreadingOnce()
s_dtoaP5Mutex = new Mutex;
initializeDates();
RegisterFile::initializeThreading();
+ Structure::initializeThreading();
#endif
}
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.cpp b/Source/JavaScriptCore/runtime/InternalFunction.cpp
index f19ae0d..27106a1 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.cpp
+++ b/Source/JavaScriptCore/runtime/InternalFunction.cpp
@@ -29,23 +29,23 @@
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)
{
+ ASSERT(inherits(&s_info));
}
InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, NonNullPassRefPtr<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);
}
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h
index 401f17b..8427b8c 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.h
+++ b/Source/JavaScriptCore/runtime/InternalFunction.h
@@ -33,8 +33,7 @@ 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*);
@@ -42,7 +41,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
@@ -55,13 +54,15 @@ namespace JSC {
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..43dd0d3 100644
--- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
+++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
@@ -37,7 +37,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount, 0);
}
diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp
index 6fb5ced..eb9c7c1 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.cpp
+++ b/Source/JavaScriptCore/runtime/JSActivation.cpp
@@ -37,11 +37,12 @@ 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()))
{
+ ASSERT(inherits(&s_info));
}
JSActivation::~JSActivation()
@@ -54,19 +55,19 @@ 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 = d()->registerArray.get();
if (!registerArray)
return;
size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
size_t count = numParametersMinusThis;
- markStack.deprecatedAppendValues(registerArray, count);
+ markStack.appendValues(registerArray, count);
size_t numVars = d()->functionExecutable->capturedVariableCount();
// Skip the call frame, which sits between the parameters and vars.
- markStack.deprecatedAppendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
+ markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
}
inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
@@ -74,13 +75,13 @@ inline bool JSActivation::symbolTableGet(const Identifier& propertyName, Propert
SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
if (!entry.isNull()) {
ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
- slot.setRegisterSlot(&registerAt(entry.getIndex()));
+ slot.setValue(registerAt(entry.getIndex()).get());
return true;
}
return false;
}
-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));
@@ -90,7 +91,7 @@ inline bool JSActivation::symbolTablePut(const Identifier& propertyName, JSValue
if (entry.isReadOnly())
return true;
ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
- registerAt(entry.getIndex()) = value;
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
@@ -106,7 +107,7 @@ void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& prope
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));
@@ -118,7 +119,7 @@ inline bool JSActivation::symbolTablePutWithAttributes(const Identifier& propert
if (entry.getIndex() >= static_cast<int>(d()->functionExecutable->capturedVariableCount()))
return false;
entry.setAttributes(attributes);
- registerAt(entry.getIndex()) = value;
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
@@ -148,7 +149,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 +164,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
@@ -201,7 +202,7 @@ bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
{
JSActivation* activation = asActivation(slotBase);
- CallFrame* callFrame = CallFrame::create(activation->d()->registers);
+ CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->d()->registers));
int argumentsRegister = activation->d()->functionExecutable->generatedBytecode().argumentsRegister();
if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue())
return arguments;
@@ -211,7 +212,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..6e04041 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.h
+++ b/Source/JavaScriptCore/runtime/JSActivation.h
@@ -62,12 +62,11 @@ 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 PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
@@ -93,8 +92,8 @@ namespace JSC {
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();
@@ -106,7 +105,7 @@ namespace JSC {
inline JSActivation* asActivation(JSValue value)
{
- ASSERT(asObject(value)->inherits(&JSActivation::info));
+ ASSERT(asObject(value)->inherits(&JSActivation::s_info));
return static_cast<JSActivation*>(asObject(value));
}
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index ded6d87..822b84c 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,8 +127,10 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
#endif
JSArray::JSArray(VPtrStealingHackType)
- : JSObject(createStructure(jsNull()))
+ : JSNonFinalObject(createStructure(jsNull()))
{
+ ASSERT(inherits(&s_info));
+
unsigned initialCapacity = 0;
m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
@@ -144,8 +146,10 @@ JSArray::JSArray(VPtrStealingHackType)
}
JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+ : JSNonFinalObject(structure)
{
+ ASSERT(inherits(&s_info));
+
unsigned initialCapacity = 0;
m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
@@ -159,8 +163,10 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
}
JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, ArrayCreationMode creationMode)
- : JSObject(structure)
+ : JSNonFinalObject(structure)
{
+ ASSERT(inherits(&s_info));
+
unsigned initialCapacity;
if (creationMode == CreateCompact)
initialCapacity = initialLength;
@@ -199,8 +205,10 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength,
}
JSArray::JSArray(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, const ArgList& list)
- : JSObject(structure)
+ : JSNonFinalObject(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..ede3c61 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -57,7 +57,7 @@ namespace JSC {
enum ArrayCreationMode { CreateCompact, CreateInitialized };
- class JSArray : public JSObject {
+ class JSArray : public JSNonFinalObject {
friend class JIT;
friend class Walker;
@@ -75,7 +75,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.
@@ -127,7 +127,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
inline void markChildrenDirect(MarkStack& markStack);
@@ -144,8 +144,6 @@ namespace JSC {
void setSubclassData(void*);
private:
- virtual const ClassInfo* classInfo() const { return &info; }
-
bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
void putSlowCase(ExecState*, unsigned propertyName, JSValue);
@@ -167,7 +165,7 @@ namespace JSC {
inline JSArray* asArray(JSCell* cell)
{
- ASSERT(cell->inherits(&JSArray::info));
+ ASSERT(cell->inherits(&JSArray::s_info));
return static_cast<JSArray*>(cell);
}
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp
index 3f7d806..ae735dc 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, NonNullPassRefPtr<Structure> structure, ByteArray* storage)
+ : JSNonFinalObject(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)
+PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype, const JSC::ClassInfo* classInfo)
{
- PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
- return result;
+ return Structure::create(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..6e91594 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*, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage);
+ static PassRefPtr<Structure> createStructure(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(); }
@@ -94,15 +102,13 @@ namespace JSC {
private:
enum VPtrStealingHackType { VPtrStealingHack };
JSByteArray(VPtrStealingHackType)
- : JSObject(createStructure(jsNull()))
- , m_classInfo(0)
+ : JSNonFinalObject(createStructure(jsNull()))
{
}
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..9acb777 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -163,11 +163,6 @@ JSObject* JSCell::toThisObject(ExecState* exec) const
return toObject(exec);
}
-const ClassInfo* JSCell::classInfo() const
-{
- return 0;
-}
-
JSValue JSCell::getJSNumber()
{
return JSValue();
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 66f6197..7313d52 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -27,6 +27,7 @@
#include "ConstructData.h"
#include "Heap.h"
#include "JSImmediate.h"
+#include "JSLock.h"
#include "JSValue.h"
#include "MarkStack.h"
#include "Structure.h"
@@ -65,6 +66,7 @@ namespace JSC {
friend class JSGlobalData;
friend class MarkedSpace;
friend class MarkedBlock;
+ friend class ScopeChainNode;
private:
explicit JSCell(Structure*);
@@ -73,7 +75,7 @@ namespace JSC {
public:
static PassRefPtr<Structure> createDummyStructure()
{
- return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
+ return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0);
}
// Querying the type.
@@ -118,7 +120,7 @@ namespace JSC {
#endif
// Object operations, with the toObject operation included.
- virtual const ClassInfo* classInfo() const;
+ const ClassInfo* classInfo() const { return m_structure->classInfo(); }
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual void put(ExecState*, unsigned propertyName, JSValue);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
@@ -174,16 +176,6 @@ namespace JSC {
{
}
- 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);
- }
-
// --- JSValue inlines ----------------------------
inline bool JSValue::isString() const
@@ -402,21 +394,59 @@ namespace JSC {
}
#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 <= preciseCutoff);
+ return m_preciseSizeClasses[(bytes - 1) / preciseStep];
+ }
+
+ 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/JSChunk.cpp b/Source/JavaScriptCore/runtime/JSChunk.cpp
new file mode 100644
index 0000000..f064de8
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSChunk.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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 "JSChunk.h"
+
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..2ade441 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -42,16 +42,14 @@ 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
{
@@ -61,43 +59,36 @@ bool JSFunction::isHostFunctionNonInline() const
JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
: Base(structure)
, m_executable(adoptRef(new VPtrHackExecutable()))
- , m_scopeChain(NoScopeChain())
{
+ ASSERT(inherits(&s_info));
}
-#if ENABLE(JIT)
JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk)
: Base(globalObject, structure)
, m_executable(thunk)
- , m_scopeChain(globalObject->globalScopeChain())
+ , 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)
: 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));
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())
+ : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure())
, m_executable(executable)
- , m_scopeChain(scopeChainNode)
+ , 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);
}
@@ -159,20 +150,18 @@ void JSFunction::markChildren(MarkStack& markStack)
Base::markChildren(markStack);
if (!isHostFunction()) {
jsExecutable()->markAggregate(markStack);
- scope().markAggregate(markStack);
+ markStack.append(&m_scopeChain);
}
}
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;
}
@@ -206,7 +195,7 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
WriteBarrierBase<Unknown>* location = getDirectLocation(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);
@@ -336,7 +325,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..089f42e 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -45,9 +45,7 @@ namespace JSC {
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*);
virtual ~JSFunction();
@@ -55,15 +53,15 @@ namespace JSC {
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 +70,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)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
NativeFunction nativeFunction();
@@ -100,21 +98,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<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..e25040c 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -75,6 +75,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;
@@ -119,12 +120,13 @@ 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()))
+ , interruptedExecutionErrorStructure(JSNonFinalObject::createStructure(jsNull()))
+ , terminatedExecutionErrorStructure(JSNonFinalObject::createStructure(jsNull()))
, staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
, strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull()))
, stringStructure(JSString::createStructure(jsNull()))
@@ -132,14 +134,16 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
, getterSetterStructure(GetterSetter::createStructure(jsNull()))
, apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
+ , scopeChainNodeStructure(ScopeChainNode::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)
@@ -152,6 +156,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, exclusiveThread(0)
#endif
{
+ interpreter = new Interpreter(*this);
if (globalDataType == Default)
m_stack = wtfThreadData().stack();
@@ -159,7 +164,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
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) {
@@ -201,6 +206,7 @@ JSGlobalData::~JSGlobalData()
jsonTable->deleteTable();
mathTable->deleteTable();
numberTable->deleteTable();
+ objectConstructorTable->deleteTable();
regExpTable->deleteTable();
regExpConstructorTable->deleteTable();
stringTable->deleteTable();
@@ -210,6 +216,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));
@@ -283,6 +290,11 @@ PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction functi
{
return jitStubs->hostFunctionStub(this, function, generator);
}
+#else
+PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
+{
+ return NativeExecutable::create(function, callHostFunctionAsConstructor);
+}
#endif
JSGlobalData::ClientData::~ClientData()
@@ -320,7 +332,7 @@ public:
inline void Recompiler::operator()(JSCell* cell)
{
- if (!cell->inherits(&JSFunction::info))
+ if (!cell->inherits(&JSFunction::s_info))
return;
JSFunction* function = asFunction(cell);
if (function->executable()->isHostFunction())
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index 7b69055..ee3e067 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -39,7 +39,6 @@
#include "SmallStrings.h"
#include "Terminator.h"
#include "TimeoutChecker.h"
-#include "WeakGCMap.h"
#include "WeakRandom.h"
#include <wtf/BumpPointerAllocator.h>
#include <wtf/Forward.h>
@@ -63,6 +62,7 @@ namespace JSC {
class JSGlobalObject;
class JSObject;
class Lexer;
+ class NativeExecutable;
class Parser;
class RegExpCache;
class Stringifier;
@@ -75,8 +75,6 @@ namespace JSC {
struct HashTable;
struct Instruction;
- typedef WeakGCMap<JSGlobalObject*, JSGlobalObject> GlobalObjectMap; // FIXME: Would be nice to use a WeakGCSet here.
-
struct DSTOffsetCache {
DSTOffsetCache()
{
@@ -141,6 +139,7 @@ namespace JSC {
const HashTable* jsonTable;
const HashTable* mathTable;
const HashTable* numberTable;
+ const HashTable* objectConstructorTable;
const HashTable* regExpTable;
const HashTable* regExpConstructorTable;
const HashTable* stringTable;
@@ -155,6 +154,7 @@ namespace JSC {
RefPtr<Structure> propertyNameIteratorStructure;
RefPtr<Structure> getterSetterStructure;
RefPtr<Structure> apiWrapperStructure;
+ RefPtr<Structure> scopeChainNodeStructure;
RefPtr<Structure> dummyMarkableCellStructure;
static void storeVPtrs();
@@ -199,9 +199,10 @@ namespace JSC {
{
return jitStubs->ctiStub(this, generator);
}
- PassRefPtr<NativeExecutable> getHostFunction(NativeFunction function);
- PassRefPtr<NativeExecutable> getHostFunction(NativeFunction function, ThunkGenerator generator);
+ PassRefPtr<NativeExecutable> getHostFunction(NativeFunction, ThunkGenerator);
#endif
+ PassRefPtr<NativeExecutable> getHostFunction(NativeFunction);
+
TimeoutChecker timeoutChecker;
Terminator terminator;
Heap heap;
@@ -213,7 +214,7 @@ namespace JSC {
HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
- GlobalObjectMap globalObjects;
+ unsigned globalObjectCount;
JSGlobalObject* dynamicGlobalObject;
HashSet<JSObject*> stringRecursionCheckVisitedObjects;
@@ -253,6 +254,8 @@ namespace JSC {
void addRegExpToTrace(PassRefPtr<RegExp> regExp);
#endif
void dumpRegExpTrace();
+ HandleSlot allocateGlobalHandle() { return heap.allocateGlobalHandle(); }
+
private:
JSGlobalData(GlobalDataType, ThreadStackType);
static JSGlobalData*& sharedInstanceInternal();
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index f303196..28fc07d 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"
@@ -104,11 +102,6 @@ JSGlobalObject::~JSGlobalObject()
(*profiler)->stopProfiling(globalExec(), UString());
}
- d()->globalData->globalObjects.take(this);
-
- RegisterFile& registerFile = globalData().interpreter->registerFile();
- if (registerFile.clearGlobalObject(this))
- registerFile.setNumGlobals(0);
d()->destructor(d());
}
@@ -119,10 +112,9 @@ 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);
+ d()->globalScopeChain.set(*d()->globalData, this, new (d()->globalData.get()) ScopeChainNode(0, this, d()->globalData.get(), this, thisValue));
- JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0);
+ JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.get(), CallFrame::noCaller(), 0, 0);
d()->debugger = 0;
@@ -135,7 +127,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,7 +136,7 @@ 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);
@@ -186,19 +178,18 @@ 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()->functionStructure = JSFunction::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);
+ JSFunction* callFunction = 0;
+ JSFunction* applyFunction = 0;
+ d()->functionPrototype->addFunctionProperties(exec, this, d()->functionStructure.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()->objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(jsNull()), d()->functionStructure.get()));
d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype.get());
d()->emptyObjectStructure = d()->objectPrototype->inheritorID();
- 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());
@@ -211,32 +202,32 @@ void JSGlobalObject::reset(JSValue prototype)
d()->stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(d()->objectPrototype.get())));
d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype.get());
- d()->booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get()));
+ d()->booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get()));
d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype.get());
- d()->numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get()));
+ d()->numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get()));
d()->numberObjectStructure = NumberObject::createStructure(d()->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());
- d()->regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get()));
+ d()->regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get()));
d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype.get());
d()->methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec));
- ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get());
+ ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get());
d()->errorStructure = ErrorInstance::createStructure(errorPrototype);
// Constructors
- JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(d()->functionPrototype.get()), d()->objectPrototype.get(), d()->prototypeFunctionStructure.get());
+ JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(d()->functionPrototype.get()), d()->objectPrototype.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* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(d()->functionPrototype.get()), d()->arrayPrototype.get(), d()->functionStructure.get());
+ JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(d()->functionPrototype.get()), d()->functionStructure.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());
+ JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(d()->functionPrototype.get()), d()->functionStructure.get(), d()->datePrototype.get());
d()->regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(d()->functionPrototype.get()), d()->regExpPrototype.get()));
@@ -294,20 +285,20 @@ void JSGlobalObject::reset(JSValue prototype)
// 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));
+ d()->evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval));
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);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->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, d()->functionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum);
#endif
resetPrototype(prototype);
@@ -328,6 +319,8 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
{
JSVariableObject::markChildren(markStack);
+ markIfNeeded(markStack, &d()->globalScopeChain);
+
markIfNeeded(markStack, &d()->regExpConstructor);
markIfNeeded(markStack, &d()->errorConstructor);
markIfNeeded(markStack, &d()->evalErrorConstructor);
@@ -364,7 +357,6 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
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);
@@ -375,12 +367,12 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
if (d()->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);
+ markStack.appendValues(d()->registerArray.get(), d()->registerArraySize);
} else if (d()->registers) {
// During execution of global code, when our variables are in the register file,
// the symbol table tells us how many variables there are, and registers
// points to where they end, and the registers used for execution begin.
- markStack.deprecatedAppendValues(d()->registers - symbolTable().size(), symbolTable().size());
+ markStack.appendValues(d()->registers - symbolTable().size(), symbolTable().size());
}
}
@@ -405,8 +397,8 @@ void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
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);
+ WriteBarrier<Unknown>* registers = registerArray.get() + numGlobals;
setRegisters(registers, registerArray.release(), numGlobals);
}
@@ -420,9 +412,32 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
registerFile.setNumGlobals(symbolTable().size());
if (d()->registerArray) {
- memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(Register));
- setRegisters(registerFile.start(), 0, 0);
+ // The register file is always a gc root so no barrier is needed here
+ memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(WriteBarrier<Unknown>));
+ setRegisters(reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.start()), nullptr, 0);
+ }
+}
+
+void JSGlobalObject::resizeRegisters(int oldSize, int newSize)
+{
+ ASSERT(symbolTable().size() == newSize);
+ if (newSize == oldSize)
+ return;
+ ASSERT(newSize && newSize > oldSize);
+ if (d()->registerArray || !d()->registers) {
+ ASSERT(static_cast<size_t>(oldSize) == d()->registerArraySize);
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]);
+ for (int i = 0; i < oldSize; i++)
+ registerArray[newSize - oldSize + i].set(globalData(), this, d()->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)
+ d()->registers[i].setUndefined();
}
void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index d13d2da..03b39fc 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -26,7 +26,6 @@
#include "JSGlobalData.h"
#include "JSVariableObject.h"
#include "JSWeakObjectMapRefInternal.h"
-#include "NativeFunctionWrapper.h"
#include "NumberPrototype.h"
#include "StringPrototype.h"
#include <wtf/HashSet.h>
@@ -42,10 +41,8 @@ namespace JSC {
class ErrorConstructor;
class FunctionPrototype;
class GlobalCodeBlock;
- class GlobalEvalFunction;
class NativeErrorConstructor;
class ProgramCodeBlock;
- class PrototypeFunction;
class RegExpConstructor;
class RegExpPrototype;
class RegisterFile;
@@ -72,7 +69,7 @@ namespace JSC {
: JSVariableObjectData(&symbolTable, 0)
, destructor(destructor)
, registerArraySize(0)
- , globalScopeChain(NoScopeChain())
+ , globalScopeChain()
, weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
{
}
@@ -86,7 +83,7 @@ namespace JSC {
Debugger* debugger;
- ScopeChain globalScopeChain;
+ WriteBarrier<ScopeChainNode> globalScopeChain;
Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
WriteBarrier<RegExpConstructor> regExpConstructor;
@@ -98,9 +95,9 @@ namespace JSC {
WriteBarrier<NativeErrorConstructor> typeErrorConstructor;
WriteBarrier<NativeErrorConstructor> URIErrorConstructor;
- WriteBarrier<GlobalEvalFunction> evalFunction;
- WriteBarrier<NativeFunctionWrapper> callFunction;
- WriteBarrier<NativeFunctionWrapper> applyFunction;
+ WriteBarrier<JSFunction> evalFunction;
+ WriteBarrier<JSFunction> callFunction;
+ WriteBarrier<JSFunction> applyFunction;
WriteBarrier<ObjectPrototype> objectPrototype;
WriteBarrier<FunctionPrototype> functionPrototype;
@@ -124,7 +121,6 @@ namespace JSC {
RefPtr<Structure> errorStructure;
RefPtr<Structure> functionStructure;
RefPtr<Structure> numberObjectStructure;
- RefPtr<Structure> prototypeFunctionStructure;
RefPtr<Structure> regExpMatchesArrayStructure;
RefPtr<Structure> regExpStructure;
RefPtr<Structure> stringObjectStructure;
@@ -181,6 +177,10 @@ 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.
@@ -194,7 +194,7 @@ namespace JSC {
NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor.get(); }
NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor.get(); }
- GlobalEvalFunction* evalFunction() const { return d()->evalFunction.get(); }
+ JSFunction* evalFunction() const { return d()->evalFunction.get(); }
ObjectPrototype* objectPrototype() const { return d()->objectPrototype.get(); }
FunctionPrototype* functionPrototype() const { return d()->functionPrototype.get(); }
@@ -218,7 +218,6 @@ namespace JSC {
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(); }
@@ -233,7 +232,7 @@ namespace JSC {
virtual bool supportsProfiling() const { return false; }
virtual bool supportsRichSourceInfo() const { return true; }
- ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
+ ScopeChainNode* globalScopeChain() { return d()->globalScopeChain.get(); }
virtual bool isGlobalObject() const { return true; }
@@ -247,7 +246,8 @@ namespace JSC {
void copyGlobalsFrom(RegisterFile&);
void copyGlobalsTo(RegisterFile&);
-
+ void resizeRegisters(int oldSize, int newSize);
+
void resetPrototype(JSValue prototype);
JSGlobalData& globalData() const { return *d()->globalData.get(); }
@@ -255,7 +255,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
void registerWeakMap(OpaqueJSWeakObjectMap* map)
@@ -295,7 +295,7 @@ namespace JSC {
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,7 +308,7 @@ 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;
@@ -318,17 +318,21 @@ namespace JSC {
{
size_t oldSize = d()->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 (d()->registerArray) {
+ // memcpy is safe here as we're copying barriers we already own from the existing array
+ memcpy(registerArray.get() + count, d()->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 +359,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)
@@ -401,16 +411,16 @@ 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());
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index 284806e..de1300a 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"
@@ -451,11 +450,11 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
return JSValue::encode(parsedObject);
RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false);
- JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
+ 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.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()));
}
EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
diff --git a/Source/JavaScriptCore/runtime/JSLock.cpp b/Source/JavaScriptCore/runtime/JSLock.cpp
index 918141f..64dcb08 100644
--- a/Source/JavaScriptCore/runtime/JSLock.cpp
+++ b/Source/JavaScriptCore/runtime/JSLock.cpp
@@ -23,14 +23,18 @@
#include "Heap.h"
#include "CallFrame.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 +212,7 @@ JSLock::DropAllLocks::~DropAllLocks()
--lockDropDepth;
}
-#else
+#else // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
JSLock::JSLock(ExecState*)
: m_lockBehavior(SilenceAssertionsOnly)
@@ -255,6 +259,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.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h
index 9f527cf..7e70a98 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().notAnObjectStructure)
{
}
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
private:
diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.cpp b/Source/JavaScriptCore/runtime/JSNumberCell.cpp
index 6fa6b2a..3172cc9 100644
--- a/Source/JavaScriptCore/runtime/JSNumberCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSNumberCell.cpp
@@ -22,6 +22,7 @@
#include "config.h"
#include "JSNumberCell.h"
+#include "ScopeChain.h"
// Keep our exported symbols lists happy.
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index 0f7a576..7d18e08 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -54,6 +54,7 @@ namespace JSC {
JSONObject::JSONObject(JSGlobalObject* globalObject, NonNullPassRefPtr<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.
@@ -134,11 +135,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;
}
@@ -212,7 +213,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
if (!m_replacer.isObject())
return;
- if (asObject(m_replacer)->inherits(&JSArray::info)) {
+ if (asObject(m_replacer)->inherits(&JSArray::s_info)) {
m_usingArrayReplacer = true;
JSObject* array = asObject(m_replacer);
unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
@@ -234,7 +235,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())
@@ -376,7 +377,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
return StringifyFailed;
}
- if (value.isUndefined() && !holder->inherits(&JSArray::info))
+ if (value.isUndefined() && !holder->inherits(&JSArray::s_info))
return StringifyFailedDueToUndefinedValue;
if (value.isNull()) {
@@ -416,7 +417,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;
}
@@ -486,7 +487,7 @@ inline void Stringifier::startNewLine(UStringBuilder& builder) const
inline Stringifier::Holder::Holder(JSObject* object)
: m_object(object)
- , m_isArray(object->inherits(&JSArray::info))
+ , m_isArray(object->inherits(&JSArray::s_info))
, m_index(0)
{
}
@@ -601,7 +602,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
@@ -678,7 +679,7 @@ 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));
@@ -739,7 +740,7 @@ 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));
@@ -806,7 +807,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;
}
diff --git a/Source/JavaScriptCore/runtime/JSONObject.h b/Source/JavaScriptCore/runtime/JSONObject.h
index f64be12..acffeca 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.h
+++ b/Source/JavaScriptCore/runtime/JSONObject.h
@@ -38,7 +38,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
static void markStringifiers(MarkStack&, Stringifier*);
@@ -50,8 +50,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..87fbb67 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_FILLS_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)
@@ -506,6 +509,22 @@ JSObject* JSObject::unwrappedObject()
return this;
}
+void JSObject::seal()
+{
+ setStructure(Structure::sealTransition(m_structure));
+}
+
+void JSObject::freeze()
+{
+ setStructure(Structure::freezeTransition(m_structure));
+}
+
+void JSObject::preventExtensions()
+{
+ if (isExtensible())
+ setStructure(Structure::preventExtensionsTransition(m_structure));
+}
+
void JSObject::removeDirect(const Identifier& propertyName)
{
size_t offset;
@@ -555,13 +574,28 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr
Structure* JSObject::createInheritorID()
{
- m_inheritorID = JSObject::createStructure(this);
+ m_inheritorID = createEmptyObjectStructure(this);
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)
@@ -627,6 +661,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);
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index b79249c..2b4db43 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -80,8 +80,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);
@@ -212,19 +210,19 @@ namespace JSC {
virtual bool isStrictModeFunction() const { return false; }
virtual bool isErrorInstance() const { return false; }
+ void seal();
+ void freeze();
+ void preventExtensions();
+ bool isSealed() { return m_structure->isSealed(); }
+ bool isFrozen() { return m_structure->isFrozen(); }
+ 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;
-
- 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 +244,28 @@ namespace JSC {
ASSERT(index < m_structure->anonymousSlotCount());
return locationForOffset(index)->get();
}
+
+ static size_t offsetOfInlineStorage();
+ static JS_EXPORTDATA const ClassInfo s_info;
+
protected:
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(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(NonNullPassRefPtr<Structure>, PropertyStorage inlineStorage);
+
private:
// Nobody should ever ask any of these questions on something already known to be a JSObject.
using JSCell::isAPIValueWrapper;
@@ -265,8 +276,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
{
@@ -287,14 +298,90 @@ namespace JSC {
const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
Structure* createInheritorID();
- union {
- PropertyStorage m_externalStorage;
- WriteBarrierBase<Unknown> m_inlineStorage[inlineStorageCapacity];
- };
-
+ PropertyStorage m_propertyStorage;
RefPtr<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 PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
+ protected:
+ explicit JSNonFinalObject(NonNullPassRefPtr<Structure> structure)
+ : JSObject(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, NonNullPassRefPtr<Structure> structure)
+ {
+ return new (exec) JSFinalObject(structure);
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
+ private:
+ explicit JSFinalObject(NonNullPassRefPtr<Structure> structure)
+ : JSObject(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, NonNullPassRefPtr<Structure> structure)
+{
+ return JSFinalObject::create(exec, structure);
+}
+
+inline PassRefPtr<Structure> createEmptyObjectStructure(JSValue prototype)
+{
+ return JSFinalObject::createStructure(prototype);
+}
+
inline JSObject* asObject(JSCell* cell)
{
ASSERT(cell->isObject());
@@ -306,20 +393,21 @@ inline JSObject* asObject(JSValue value)
return asObject(value.asCell());
}
-inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure)
+inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure, PropertyStorage inlineStorage)
: JSCell(structure.releaseRef()) // ~JSObject balances this ref()
+ , 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);
}
inline JSObject::~JSObject()
{
ASSERT(m_structure);
if (!isUsingInlineStorage())
- delete [] m_externalStorage;
+ delete [] m_propertyStorage;
m_structure->deref();
}
@@ -363,7 +451,7 @@ inline Structure* JSObject::inheritorID()
inline bool Structure::isUsingInlineStorage() const
{
- return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
+ return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity;
}
inline bool JSCell::inherits(const ClassInfo* info) const
@@ -490,6 +578,9 @@ 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);
if (currentCapacity != m_structure->propertyStorageCapacity())
@@ -551,15 +642,8 @@ 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);
@@ -727,26 +811,6 @@ 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);
diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp
index c16acb1..9370139 100644
--- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp
@@ -31,7 +31,7 @@
namespace JSC {
JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+ : JSNonFinalObject(structure)
{
COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one);
ASSERT(!globalObject || globalObject->isGlobalObject());
diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h
index 9416a62..c5e3047 100644
--- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h
@@ -32,11 +32,11 @@ namespace JSC {
class JSGlobalObject;
-class JSObjectWithGlobalObject : public JSObject {
+class JSObjectWithGlobalObject : public JSNonFinalObject {
public:
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
JSGlobalObject* globalObject() const;
@@ -45,7 +45,7 @@ protected:
JSObjectWithGlobalObject(JSGlobalObject*, NonNullPassRefPtr<Structure>);
JSObjectWithGlobalObject(NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+ : JSNonFinalObject(structure)
{
// 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..0d759cf 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -47,12 +47,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() ||
@@ -85,7 +79,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
jsPropertyNameIterator->setCachedStructure(o->structure());
- o->structure()->setEnumerationCache(jsPropertyNameIterator);
+ o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator);
return jsPropertyNameIterator;
}
@@ -105,4 +99,12 @@ void JSPropertyNameIterator::markChildren(MarkStack& markStack)
markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
}
+#if !ASSERT_DISABLED
+
+JSPropertyNameIterator::~JSPropertyNameIterator()
+{
+ ASSERT(!m_cachedStructure || m_cachedStructure->enumerationCache() != this);
+}
+
+#endif
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
index cd46243..d51cba8 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -47,10 +47,8 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, 0);
}
-
- virtual ~JSPropertyNameIterator();
virtual bool isPropertyNameIterator() const { return true; }
@@ -80,6 +78,10 @@ namespace JSC {
private:
JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
+
+#if !ASSERT_DISABLED
+ virtual ~JSPropertyNameIterator();
+#endif
RefPtr<Structure> m_cachedStructure;
RefPtr<StructureChain> m_cachedPrototypeChain;
@@ -88,15 +90,15 @@ namespace JSC {
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, enumerationCache, 0);
}
- inline void Structure::clearEnumerationCache(JSPropertyNameIterator* enumerationCache)
+ inline void Structure::clearEnumerationCache()
{
- m_enumerationCache.clear(enumerationCache);
+ m_enumerationCache.clear();
}
inline JSPropertyNameIterator* Structure::enumerationCache()
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
index 80b048e..727ac28 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
@@ -47,17 +47,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();
@@ -74,7 +74,7 @@ JSStaticScopeObject::~JSStaticScopeObject()
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..b3c0695 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
@@ -58,7 +58,7 @@ 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 PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index 6696404..3672300 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -349,7 +349,7 @@ 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 PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); }
private:
enum VPtrStealingHackType { VPtrStealingHack };
diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h
index e225bc7..fdcaf31 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);
// 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,12 @@ 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); }
private:
unsigned char m_type;
unsigned char m_flags;
+ unsigned char m_flags2;
};
}
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..e94d277 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -40,7 +40,7 @@ namespace JSC {
class Register;
- class JSVariableObject : public JSObject {
+ class JSVariableObject : public JSNonFinalObject {
friend class JIT;
public:
@@ -54,11 +54,11 @@ 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 d->registers[index]; }
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
@@ -69,14 +69,14 @@ namespace JSC {
struct JSVariableObjectData {
JSVariableObjectData(SymbolTable* symbolTable, Register* registers)
: symbolTable(symbolTable)
- , registers(registers)
+ , registers(reinterpret_cast<WriteBarrier<Unknown>*>(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.
+ WriteBarrier<Unknown>* registers; // "r" in the register file.
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
private:
JSVariableObjectData(const JSVariableObjectData&);
@@ -84,19 +84,20 @@ namespace JSC {
};
JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data)
- : JSObject(structure)
+ : JSNonFinalObject(structure)
, d(data) // Subclass owns this pointer.
{
+ 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);
+ 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;
};
@@ -105,7 +106,7 @@ namespace JSC {
{
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 +116,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 +132,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,19 +146,20 @@ 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)
{
- 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 < 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;
diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h
index 0b0d3fd..6d586df 100644
--- a/Source/JavaScriptCore/runtime/JSWrapperObject.h
+++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h
@@ -28,7 +28,7 @@ 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>);
@@ -38,7 +38,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
@@ -51,7 +51,7 @@ namespace JSC {
};
inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure)
- : JSObject(structure)
+ : JSNonFinalObject(structure)
{
putAnonymousValue(globalData, 0, jsNull());
}
diff --git a/Source/JavaScriptCore/runtime/JSZombie.cpp b/Source/JavaScriptCore/runtime/JSZombie.cpp
index 8a36bda..c0c5f11 100644
--- a/Source/JavaScriptCore/runtime/JSZombie.cpp
+++ b/Source/JavaScriptCore/runtime/JSZombie.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "JSZombie.h"
#include "ClassInfo.h"
+#include "ScopeChain.h"
#if ENABLE(JSC_ZOMBIES)
@@ -37,7 +38,7 @@ Structure* JSZombie::leakedZombieStructure() {
static Structure* structure = 0;
if (!structure) {
Structure::startIgnoringLeaks();
- structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0).leakRef();
+ structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0, &info).leakRef();
Structure::stopIgnoringLeaks();
}
return structure;
diff --git a/Source/JavaScriptCore/runtime/JSZombie.h b/Source/JavaScriptCore/runtime/JSZombie.h
index da45699..5fe6b6d 100644
--- a/Source/JavaScriptCore/runtime/JSZombie.h
+++ b/Source/JavaScriptCore/runtime/JSZombie.h
@@ -37,9 +37,10 @@ public:
: JSCell(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; }
@@ -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 PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), 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..307bceb 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 {
@@ -77,14 +76,14 @@ void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject*
WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(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);
diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
index 4430947..4614a7c 100644
--- a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
+++ b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Acision BV. 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
@@ -70,6 +71,13 @@
#include <errno.h>
#endif
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+#include <signal.h>
+#ifndef SA_RESTART
+#error MachineStackMarker requires SA_RESTART
+#endif
+#endif
+
#endif
namespace JSC {
@@ -92,6 +100,17 @@ UNUSED_PARAM(end);
typedef mach_port_t PlatformThread;
#elif OS(WINDOWS)
typedef HANDLE PlatformThread;
+#elif USE(PTHREADS)
+typedef pthread_t PlatformThread;
+static const int SigThreadSuspendResume = SIGUSR2;
+
+static void pthreadSignalHandlerSuspendResume(int signo)
+{
+ sigset_t signalSet;
+ sigemptyset(&signalSet);
+ sigaddset(&signalSet, SigThreadSuspendResume);
+ sigsuspend(&signalSet);
+}
#endif
class MachineStackMarker::Thread {
@@ -101,6 +120,18 @@ public:
, platformThread(platThread)
, stackBase(base)
{
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+ struct sigaction action;
+ action.sa_handler = pthreadSignalHandlerSuspendResume;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = SA_RESTART;
+ sigaction(SigThreadSuspendResume, &action, 0);
+
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, SigThreadSuspendResume);
+ pthread_sigmask(SIG_UNBLOCK, &mask, 0);
+#endif
}
Thread* next;
@@ -145,6 +176,8 @@ static inline PlatformThread getCurrentPlatformThread()
return pthread_mach_thread_np(pthread_self());
#elif OS(WINDOWS)
return pthread_getw32threadhandle_np(pthread_self());
+#elif USE(PTHREADS)
+ return pthread_self();
#endif
}
@@ -245,6 +278,8 @@ static inline void suspendThread(const PlatformThread& platformThread)
thread_suspend(platformThread);
#elif OS(WINDOWS)
SuspendThread(platformThread);
+#elif USE(PTHREADS)
+ pthread_kill(platformThread, SigThreadSuspendResume);
#else
#error Need a way to suspend threads on this platform
#endif
@@ -256,6 +291,8 @@ static inline void resumeThread(const PlatformThread& platformThread)
thread_resume(platformThread);
#elif OS(WINDOWS)
ResumeThread(platformThread);
+#elif USE(PTHREADS)
+ pthread_kill(platformThread, SigThreadSuspendResume);
#else
#error Need a way to resume threads on this platform
#endif
@@ -281,6 +318,8 @@ typedef arm_thread_state_t PlatformThreadRegisters;
#elif OS(WINDOWS) && CPU(X86)
typedef CONTEXT PlatformThreadRegisters;
+#elif USE(PTHREADS)
+typedef pthread_attr_t PlatformThreadRegisters;
#else
#error Need a thread register struct for this platform
#endif
@@ -321,6 +360,16 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P
regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
GetThreadContext(platformThread, &regs);
return sizeof(CONTEXT);
+#elif USE(PTHREADS)
+ pthread_attr_init(&regs);
+#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
+ // e.g. on FreeBSD 5.4, neundorf@kde.org
+ pthread_attr_get_np(platformThread, &regs);
+#else
+ // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
+ pthread_getattr_np(platformThread, &regs);
+#endif
+ return 0;
#else
#error Need a way to get thread registers on this platform
#endif
@@ -361,11 +410,27 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
// end OS(DARWIN)
#elif CPU(X86) && OS(WINDOWS)
return reinterpret_cast<void*>((uintptr_t) regs.Esp);
+#elif USE(PTHREADS)
+ void* stackBase = 0;
+ size_t stackSize = 0;
+ int rc = pthread_attr_getstack(&regs, &stackBase, &stackSize);
+ (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
+ ASSERT(stackBase);
+ return static_cast<char*>(stackBase) + stackSize;
#else
#error Need a way to get the stack pointer for another thread on this platform
#endif
}
+static void freePlatformThreadRegisters(PlatformThreadRegisters& regs)
+{
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+ pthread_attr_destroy(&regs);
+#else
+ UNUSED_PARAM(regs);
+#endif
+}
+
void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conservativeSet, Thread* thread)
{
suspendThread(thread->platformThread);
@@ -382,6 +447,8 @@ void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conserva
conservativeSet.add(stackPointer, stackBase);
resumeThread(thread->platformThread);
+
+ freePlatformThreadRegisters(regs);
}
#endif
diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.cpp b/Source/JavaScriptCore/runtime/MarkedBlock.cpp
index 16053f2..48dda4c 100644
--- a/Source/JavaScriptCore/runtime/MarkedBlock.cpp
+++ b/Source/JavaScriptCore/runtime/MarkedBlock.cpp
@@ -27,33 +27,38 @@
#include "MarkedBlock.h"
#include "JSCell.h"
+#include "ScopeChain.h"
namespace JSC {
-MarkedBlock* MarkedBlock::create(JSGlobalData* globalData)
+MarkedBlock* MarkedBlock::create(JSGlobalData* globalData, size_t cellSize)
{
- PageAllocationAligned allocation = PageAllocationAligned::allocate(BLOCK_SIZE, BLOCK_SIZE, OSAllocator::JSGCHeapPages);
+ PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockSize, OSAllocator::JSGCHeapPages);
if (!static_cast<bool>(allocation))
CRASH();
- return new (allocation.base()) MarkedBlock(allocation, globalData);
+ return new (allocation.base()) MarkedBlock(allocation, globalData, cellSize);
}
void MarkedBlock::destroy(MarkedBlock* block)
{
- for (size_t i = 0; i < CELLS_PER_BLOCK; ++i)
- reinterpret_cast<JSCell*>(&block->cells[i])->~JSCell();
+ for (size_t i = block->firstAtom(); i < block->m_endAtom; i += block->m_atomsPerCell)
+ reinterpret_cast<JSCell*>(&block->atoms()[i])->~JSCell();
block->m_allocation.deallocate();
}
-MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData* globalData)
- : m_allocation(allocation)
+MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData* globalData, size_t cellSize)
+ : m_nextAtom(firstAtom())
+ , m_allocation(allocation)
, m_heap(&globalData->heap)
+ , m_prev(0)
+ , m_next(0)
{
- marked.set(CELLS_PER_BLOCK - 1);
+ m_atomsPerCell = (cellSize + atomSize - 1) / atomSize;
+ m_endAtom = atomsPerBlock - m_atomsPerCell + 1;
Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get();
- for (size_t i = 0; i < CELLS_PER_BLOCK; ++i)
- new (&cells[i]) JSCell(dummyMarkableCellStructure);
+ for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell)
+ new (&atoms()[i]) JSCell(dummyMarkableCellStructure);
}
void MarkedBlock::sweep()
@@ -62,17 +67,17 @@ void MarkedBlock::sweep()
Structure* dummyMarkableCellStructure = m_heap->globalData()->dummyMarkableCellStructure.get();
#endif
- for (size_t i = 0; i < CELLS_PER_BLOCK; ++i) {
- if (marked.get(i))
+ for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
+ if (m_marks.get(i))
continue;
- JSCell* cell = reinterpret_cast<JSCell*>(&cells[i]);
+ JSCell* cell = reinterpret_cast<JSCell*>(&atoms()[i]);
#if ENABLE(JSC_ZOMBIES)
if (!cell->isZombie()) {
const ClassInfo* info = cell->classInfo();
cell->~JSCell();
new (cell) JSZombie(info, JSZombie::leakedZombieStructure());
- marked.set(i);
+ m_marks.set(i);
}
#else
cell->~JSCell();
diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.h b/Source/JavaScriptCore/runtime/MarkedBlock.h
index f726c25..e80fe82 100644
--- a/Source/JavaScriptCore/runtime/MarkedBlock.h
+++ b/Source/JavaScriptCore/runtime/MarkedBlock.h
@@ -23,89 +23,108 @@
#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;
- };
+ typedef uintptr_t Bits;
+
+ static const size_t KB = 1024;
- // 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);
+ // Efficient implementation that takes advantage of powers of two.
+ template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x)
+ {
+ COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two);
+
+ size_t remainderMask = divisor - 1;
+ return (x + remainderMask) & ~remainderMask;
+ }
+ class MarkedBlock {
public:
- static MarkedBlock* create(JSGlobalData*);
+ static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types.
+
+ static MarkedBlock* create(JSGlobalData*, size_t cellSize);
static void destroy(MarkedBlock*);
- static bool isCellAligned(const void*);
+ static bool isAtomAligned(const void*);
static MarkedBlock* blockFor(const void*);
+ static size_t firstAtom();
Heap* heap() const;
+
+ void setPrev(MarkedBlock*);
+ void setNext(MarkedBlock*);
+ MarkedBlock* prev() const;
+ MarkedBlock* next() const;
- void* allocate(size_t& nextCell);
+ void* allocate();
+ void reset();
void sweep();
bool isEmpty();
void clearMarks();
size_t markCount();
+
+ size_t cellSize();
+
size_t size();
size_t capacity();
- size_t cellNumber(const void*);
+ bool contains(const void*);
+ size_t atomNumber(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*);
+ static const size_t blockSize = 16 * KB;
+ static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two.
+
+ static const size_t atomMask = ~(atomSize - 1); // atomSize must be a power of two.
+
+ static const size_t atomsPerBlock = blockSize / atomSize;
+
+ typedef char Atom[atomSize];
- WTF::Bitmap<BITS_PER_BLOCK> marked;
+ MarkedBlock(const PageAllocationAligned&, JSGlobalData*, size_t cellSize);
+ Atom* atoms();
+
+ size_t m_nextAtom;
+ size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom.
+ size_t m_atomsPerCell;
+ WTF::Bitmap<blockSize / atomSize> m_marks;
PageAllocationAligned m_allocation;
Heap* m_heap;
+ MarkedBlock* m_prev;
+ MarkedBlock* m_next;
};
- inline bool MarkedBlock::isCellAligned(const void* p)
+ inline size_t MarkedBlock::firstAtom()
+ {
+ return roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize;
+ }
+
+ inline MarkedBlock::Atom* MarkedBlock::atoms()
{
- return !((intptr_t)(p) & CELL_MASK);
+ return reinterpret_cast<Atom*>(this);
+ }
+
+ inline bool MarkedBlock::isAtomAligned(const void* p)
+ {
+ return !((intptr_t)(p) & ~atomMask);
}
inline MarkedBlock* MarkedBlock::blockFor(const void* p)
{
- return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & BLOCK_MASK);
+ return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & blockMask);
}
inline Heap* MarkedBlock::heap() const
@@ -113,62 +132,98 @@ namespace JSC {
return m_heap;
}
+ inline void MarkedBlock::setPrev(MarkedBlock* prev)
+ {
+ m_prev = prev;
+ }
+
+ inline void MarkedBlock::setNext(MarkedBlock* next)
+ {
+ m_next = next;
+ }
+
+ inline MarkedBlock* MarkedBlock::prev() const
+ {
+ return m_prev;
+ }
+
+ inline MarkedBlock* MarkedBlock::next() const
+ {
+ return m_next;
+ }
+
+ inline void MarkedBlock::reset()
+ {
+ m_nextAtom = firstAtom();
+ }
+
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;
+ return m_marks.isEmpty();
}
inline void MarkedBlock::clearMarks()
{
- // allocate() assumes that the last mark bit is always set.
- marked.clearAll();
- marked.set(CELLS_PER_BLOCK - 1);
+ m_marks.clearAll();
}
inline size_t MarkedBlock::markCount()
{
- return marked.count() - 1; // The last mark bit is always set.
+ return m_marks.count();
+ }
+
+ inline size_t MarkedBlock::cellSize()
+ {
+ return m_atomsPerCell * atomSize;
}
inline size_t MarkedBlock::size()
{
- return markCount() * CELL_SIZE;
+ return markCount() * cellSize();
}
inline size_t MarkedBlock::capacity()
{
- return BLOCK_SIZE;
+ return m_allocation.size();
+ }
+
+ inline bool MarkedBlock::contains(const void* p)
+ {
+ // Since we mark the first atom of every cell when allocating and/or
+ // marking, any pointer to a marked atom points to the head of a valid,
+ // live cell. Checking the mark bit guards against reviving an object
+ // in a zombie state.
+
+ ASSERT(p && isAtomAligned(p));
+ return isMarked(p);
}
- inline size_t MarkedBlock::cellNumber(const void* cell)
+ inline size_t MarkedBlock::atomNumber(const void* p)
{
- return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
+ return (reinterpret_cast<uintptr_t>(p) - reinterpret_cast<uintptr_t>(this)) / atomSize;
}
- inline bool MarkedBlock::isMarked(const void* cell)
+ inline bool MarkedBlock::isMarked(const void* p)
{
- return marked.get(cellNumber(cell));
+ return m_marks.get(atomNumber(p));
}
- inline bool MarkedBlock::testAndSetMarked(const void* cell)
+ inline bool MarkedBlock::testAndSetMarked(const void* p)
{
- return marked.testAndSet(cellNumber(cell));
+ return m_marks.testAndSet(atomNumber(p));
}
- inline void MarkedBlock::setMarked(const void* cell)
+ inline void MarkedBlock::setMarked(const void* p)
{
- marked.set(cellNumber(cell));
+ m_marks.set(atomNumber(p));
}
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))
+ for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
+ if (!m_marks.get(i))
continue;
- functor(reinterpret_cast<JSCell*>(&cells[i]));
+ functor(reinterpret_cast<JSCell*>(&atoms()[i]));
}
}
diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp
index 2f8075d..15ab514 100644
--- a/Source/JavaScriptCore/runtime/MarkedSpace.cpp
+++ b/Source/JavaScriptCore/runtime/MarkedSpace.cpp
@@ -24,6 +24,7 @@
#include "JSCell.h"
#include "JSGlobalData.h"
#include "JSLock.h"
+#include "ScopeChain.h"
namespace JSC {
@@ -34,105 +35,125 @@ MarkedSpace::MarkedSpace(JSGlobalData* globalData)
, m_highWaterMark(0)
, m_globalData(globalData)
{
- allocateBlock();
+ for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep)
+ sizeClassFor(cellSize).cellSize = cellSize;
}
void MarkedSpace::destroy()
{
- clearMarks(); // Make sure weak pointers appear dead during destruction.
-
- while (m_heap.blocks.size())
- freeBlock(0);
- m_heap.blocks.clear();
+ clearMarks();
+ shrink();
+ ASSERT(!size());
}
-NEVER_INLINE MarkedBlock* MarkedSpace::allocateBlock()
+MarkedBlock* MarkedSpace::allocateBlock(SizeClass& sizeClass)
{
- MarkedBlock* block = MarkedBlock::create(globalData());
- m_heap.blocks.append(block);
+ MarkedBlock* block = MarkedBlock::create(globalData(), sizeClass.cellSize);
+ sizeClass.blockList.append(block);
+ sizeClass.nextBlock = block;
+ m_blocks.add(block);
+
return block;
}
-NEVER_INLINE void MarkedSpace::freeBlock(size_t block)
+void MarkedSpace::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
{
- MarkedBlock::destroy(m_heap.blocks[block]);
+ MarkedBlock* next;
+ for (MarkedBlock* block = blocks.head(); block; block = next) {
+ next = block->next();
- // swap with the last block so we compact as we go
- m_heap.blocks[block] = m_heap.blocks.last();
- m_heap.blocks.removeLast();
+ blocks.remove(block);
+ m_blocks.remove(block);
+ MarkedBlock::destroy(block);
+ }
}
-void* MarkedSpace::allocate(size_t)
+void* MarkedSpace::allocateFromSizeClass(SizeClass& sizeClass)
{
- 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))
+ for (MarkedBlock*& block = sizeClass.nextBlock ; block; block = block->next()) {
+ if (void* result = block->allocate())
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 allocateBlock(sizeClass)->allocate();
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;
+ // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
+ DoublyLinkedList<MarkedBlock> empties;
+
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it) {
+ MarkedBlock* block = *it;
+ if (block->isEmpty()) {
+ SizeClass& sizeClass = sizeClassFor(block->cellSize());
+ sizeClass.blockList.remove(block);
+ sizeClass.nextBlock = sizeClass.blockList.head();
+ empties.append(block);
+ }
}
+
+ freeBlocks(empties);
+ ASSERT(empties.isEmpty());
}
void MarkedSpace::clearMarks()
{
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- m_heap.collectorBlock(i)->clearMarks();
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->clearMarks();
}
void MarkedSpace::sweep()
{
- for (size_t i = 0; i < m_heap.blocks.size(); ++i)
- m_heap.collectorBlock(i)->sweep();
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->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();
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ result += (*it)->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();
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ result += (*it)->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();
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ result += (*it)->capacity();
return result;
}
void MarkedSpace::reset()
{
- m_heap.nextCell = 0;
- m_heap.nextBlock = 0;
m_waterMark = 0;
-#if ENABLE(JSC_ZOMBIES)
- sweep();
-#endif
+
+ for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep)
+ sizeClassFor(cellSize).reset();
+
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->reset();
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h
index fcb93b7..2e88887 100644
--- a/Source/JavaScriptCore/runtime/MarkedSpace.h
+++ b/Source/JavaScriptCore/runtime/MarkedSpace.h
@@ -26,11 +26,15 @@
#include "MarkedBlock.h"
#include "PageAllocationAligned.h"
#include <wtf/Bitmap.h>
+#include <wtf/DoublyLinkedList.h>
#include <wtf/FixedArray.h>
-#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
+#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedSpace::maxCellSize, class_fits_in_cell)
+#define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT(sizeof(class) == MarkedSpace::maxCellSize, class_fills_cell)
+
namespace JSC {
class Heap;
@@ -40,26 +44,12 @@ namespace JSC {
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:
+ // Currently public for use in assertions.
+ static const size_t maxCellSize = 64;
+
static Heap* heap(JSCell*);
static bool isMarked(const JSCell*);
@@ -91,12 +81,32 @@ namespace JSC {
template<typename Functor> void forEach(Functor&);
private:
- NEVER_INLINE MarkedBlock* allocateBlock();
- NEVER_INLINE void freeBlock(size_t);
+ // [ 8, 16... 64 ]
+ static const size_t preciseStep = MarkedBlock::atomSize;
+ static const size_t preciseCutoff = maxCellSize;
+ static const size_t preciseCount = preciseCutoff / preciseStep;
+
+ typedef HashSet<MarkedBlock*>::iterator BlockIterator;
+
+ struct SizeClass {
+ SizeClass();
+ void reset();
+
+ MarkedBlock* nextBlock;
+ DoublyLinkedList<MarkedBlock> blockList;
+ size_t cellSize;
+ };
+
+ MarkedBlock* allocateBlock(SizeClass&);
+ void freeBlocks(DoublyLinkedList<MarkedBlock>&);
+
+ SizeClass& sizeClassFor(size_t);
+ void* allocateFromSizeClass(SizeClass&);
void clearMarks(MarkedBlock*);
- CollectorHeap m_heap;
+ SizeClass m_preciseSizeClasses[preciseCount];
+ HashSet<MarkedBlock*> m_blocks;
size_t m_waterMark;
size_t m_highWaterMark;
JSGlobalData* m_globalData;
@@ -124,31 +134,32 @@ namespace JSC {
inline bool MarkedSpace::contains(const void* x)
{
- if (!MarkedBlock::isCellAligned(x))
+ if (!MarkedBlock::isAtomAligned(x))
return false;
MarkedBlock* block = MarkedBlock::blockFor(x);
- if (!block)
+ if (!block || !m_blocks.contains(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;
+ return block->contains(x);
}
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);
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->forEach(functor);
+ }
+
+ inline MarkedSpace::SizeClass::SizeClass()
+ : nextBlock(0)
+ , cellSize(0)
+ {
+ }
+
+ inline void MarkedSpace::SizeClass::reset()
+ {
+ nextBlock = blockList.head();
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp
index c79316b..7b856a1 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
@@ -89,11 +89,13 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<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..86e7951 100644
--- a/Source/JavaScriptCore/runtime/MathObject.h
+++ b/Source/JavaScriptCore/runtime/MathObject.h
@@ -32,12 +32,11 @@ 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;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
index 421eecf..7949dd9 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
@@ -30,11 +30,13 @@ 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)
: 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
diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
index 1ff8207..e4978cc 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
+++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
@@ -33,7 +33,12 @@ namespace JSC {
public:
NativeErrorConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<Structure> prototypeStructure, const UString&);
- static const ClassInfo info;
+ static const ClassInfo s_info;
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
Structure* errorStructure() { return m_errorStructure.get(); }
@@ -41,8 +46,6 @@ namespace JSC {
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
- virtual const ClassInfo* classInfo() const { return &info; }
-
RefPtr<Structure> m_errorStructure;
};
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..3e4d6c7 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
@@ -55,8 +55,10 @@ const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info,
*/
NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
- : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, numberPrototype->info.className))
+ : 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);
diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.h b/Source/JavaScriptCore/runtime/NumberConstructor.h
index d8a2593..aaf7c32 100644
--- a/Source/JavaScriptCore/runtime/NumberConstructor.h
+++ b/Source/JavaScriptCore/runtime/NumberConstructor.h
@@ -35,11 +35,11 @@ namespace JSC {
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)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(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..4408673 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)
: JSWrapperObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
}
JSValue NumberObject::getJSNumber()
diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h
index 044f490..8a80382 100644
--- a/Source/JavaScriptCore/runtime/NumberObject.h
+++ b/Source/JavaScriptCore/runtime/NumberObject.h
@@ -29,19 +29,17 @@ namespace JSC {
public:
explicit NumberObject(JSGlobalData&, NonNullPassRefPtr<Structure>);
- static const ClassInfo info;
+ static const ClassInfo s_info;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(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();
};
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
index fbe6992..6c027b3 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, NonNullPassRefPtr<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..191ab47 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*, NonNullPassRefPtr<Structure>, Structure* functionStructure);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index f31da67..5080ef8 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,23 +42,56 @@ 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, NonNullPassRefPtr<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
@@ -66,7 +99,7 @@ static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& a
{
JSValue arg = args.at(0);
if (arg.isUndefinedOrNull())
- return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+ return constructEmptyObject(exec);
return arg.toObject(exec);
}
@@ -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();
+ 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();
+ 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();
+ 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()));
+}
+
+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()));
+}
+
+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..895f988 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*, NonNullPassRefPtr<Structure>, ObjectPrototype*);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+
+ static const ClassInfo s_info;
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(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..187456f 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, NonNullPassRefPtr<Structure> stucture, Structure* functionStructure)
+ : JSNonFinalObject(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..61c8f57 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*, NonNullPassRefPtr<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..181f912 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -472,8 +472,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..85a3818 100644
--- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
+++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -22,69 +22,531 @@
#define PropertyMapHashTable_h
#include "UString.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;
+ JSCell* specificValue;
+
+ PropertyMapEntry(StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue)
+ : key(key)
+ , offset(offset)
+ , attributes(attributes)
+ , specificValue(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.
+ PropertyTable(unsigned initialCapacity);
+ PropertyTable(const PropertyTable&);
+ PropertyTable(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(unsigned newCapacity);
+
+#ifndef NDEBUG
+ size_t sizeInMemory();
+ void checkConsistency();
+#endif
+
+private:
+ // 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(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();
+
+ // Copy the m_deletedOffsets vector.
+ Vector<unsigned>* otherDeletedOffsets = other.m_deletedOffsets.get();
+ if (otherDeletedOffsets)
+ m_deletedOffsets.set(new Vector<unsigned>(*otherDeletedOffsets));
+}
+
+inline PropertyTable::PropertyTable(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();
+ }
+
+ // 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->ref();
+
+ 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(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(*this);
+ return new PropertyTable(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..351ecc3 100644
--- a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp
+++ b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include "PropertyNameArray.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/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index 1b30514..c06fdc4 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
@@ -99,6 +99,8 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObje
: 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);
@@ -296,7 +298,7 @@ JSObject* constructRegExp(ExecState* exec, 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);
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h
index 1714bd3..8a8a54a 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h
@@ -61,14 +61,14 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(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,8 +91,6 @@ namespace JSC {
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
- virtual const ClassInfo* classInfo() const { return &info; }
-
OwnPtr<RegExpConstructorPrivate> d;
};
@@ -102,7 +100,7 @@ namespace JSC {
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/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index b969e38..5baf884 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
@@ -65,6 +65,7 @@ RegExpObject::RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Struc
: JSObjectWithGlobalObject(globalObject, structure)
, d(adoptPtr(new RegExpObjectData(regExp, 0)))
{
+ ASSERT(inherits(&s_info));
}
RegExpObject::~RegExpObject()
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index 99c84da..1f89b84 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -44,12 +44,11 @@ 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)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
@@ -70,7 +69,7 @@ namespace JSC {
RefPtr<RegExp> regExp;
double lastIndex;
};
-#if PLATFORM(WIN)
+#if COMPILER(MSVC)
friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*);
#endif
OwnPtr<RegExpObjectData> d;
@@ -80,7 +79,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..106006c 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)
+RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure)
: RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", ""))
{
- 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, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, 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,14 +77,14 @@ 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();
@@ -106,8 +105,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..70d77d9 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*, NonNullPassRefPtr<Structure>, Structure* functionStructure);
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.cpp b/Source/JavaScriptCore/runtime/ScopeChain.cpp
index 976cff6..4615f9a 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,12 @@ void ScopeChainNode::print() const
#endif
-int ScopeChain::localDepth() const
+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 +65,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..fbecd11 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.h
+++ b/Source/JavaScriptCore/runtime/ScopeChain.h
@@ -21,7 +21,7 @@
#ifndef ScopeChain_h
#define ScopeChain_h
-#include "WriteBarrier.h"
+#include "JSCell.h"
#include <wtf/FastAllocBase.h>
namespace JSC {
@@ -32,109 +32,67 @@ 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->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 PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); }
+ virtual void markChildren(MarkStack&);
+ private:
+ static const unsigned StructureFlags = OverridesMarkChildren;
};
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,100 +100,33 @@ namespace JSC {
bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
private:
- const ScopeChainNode* m_node;
+ DeprecatedPtr<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
{
- ScopeChain tmp(c);
- swap(tmp);
- return *this;
+ return scopeChain()->globalThis.get();
}
} // namespace JSC
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.h b/Source/JavaScriptCore/runtime/SmallStrings.h
index ee795b6..cd9c325 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.h
+++ b/Source/JavaScriptCore/runtime/SmallStrings.h
@@ -63,9 +63,9 @@ namespace JSC {
void clear();
unsigned count() const;
-#if ENABLE(JIT)
+
JSCell** singleCharacterStrings() { return m_singleCharacterStrings[0].slot(); }
-#endif
+
private:
void createEmptyString(JSGlobalData*);
void createSingleCharacterString(JSGlobalData*, unsigned char);
diff --git a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
index 5bb013b..24c501e 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().strictEvalActivationStructure)
{
}
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..5398f31 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, NonNullPassRefPtr<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);
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.h b/Source/JavaScriptCore/runtime/StringConstructor.h
index 20f3a52..3a42c7e 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*, NonNullPassRefPtr<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..5fe7544 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)
: JSWrapperObject(exec->globalData(), structure)
{
+ ASSERT(inherits(&s_info));
setInternalValue(exec->globalData(), jsEmptyString(exec));
}
StringObject::StringObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, JSString* string)
: JSWrapperObject(globalData, structure)
{
+ ASSERT(inherits(&s_info));
setInternalValue(globalData, string);
}
StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<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..99f9add 100644
--- a/Source/JavaScriptCore/runtime/StringObject.h
+++ b/Source/JavaScriptCore/runtime/StringObject.h
@@ -41,14 +41,13 @@ 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)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
@@ -60,7 +59,7 @@ namespace JSC {
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..0a44ed3 100644
--- a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
+++ b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
@@ -44,7 +44,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(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..aa37122 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
@@ -134,6 +134,8 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec
StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<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);
@@ -605,7 +607,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
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 {
/*
@@ -658,7 +660,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
UString u = s;
RefPtr<RegExp> reg;
- if (a0.inherits(&RegExpObject::info))
+ if (a0.inherits(&RegExpObject::s_info))
reg = asRegExpObject(a0)->regExp();
else {
/*
@@ -716,7 +718,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..feea2e2 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.h
+++ b/Source/JavaScriptCore/runtime/StringPrototype.h
@@ -34,8 +34,12 @@ namespace JSC {
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 PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+ }
+
+ static const ClassInfo s_info;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index e8f5d7a..829e3db 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -50,23 +50,26 @@
using namespace std;
using namespace WTF;
-namespace JSC {
+#if DUMP_PROPERTYMAP_STATS
-// 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;
+int numProbes;
+int numCollisions;
+int numRehashes;
+int numRemoves;
-// 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;
+#endif
-static const unsigned newTableSize = 16;
+namespace JSC {
#ifndef NDEBUG
static WTF::RefCountedLeakCounter structureCounter("Structure");
#if ENABLE(JSC_MULTIPLE_THREADS)
-static Mutex& ignoreSetMutex = *(new Mutex);
+static Mutex& ignoreSetMutex()
+{
+ DEFINE_STATIC_LOCAL(Mutex, mutex, ());
+ return mutex;
+}
#endif
static bool shouldIgnoreLeaks;
@@ -77,105 +80,67 @@ static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>);
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)
+bool StructureTransitionTable::contains(StringImpl* rep, unsigned attributes) const
{
- 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
-{
- 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));
+ 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);
setSingleTransition(0);
- return;
+ } 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->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(Structure* structure)
{
- if (m_isUsingSingleSlot) {
- if (!singleTransition()) {
+ if (isUsingSingleSlot()) {
+ Structure* existingTransition = singleTransition();
+
+ // This handles the first transition being added.
+ if (!existingTransition) {
setSingleTransition(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(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(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->second->m_specificValueInPrevious);
+ ASSERT(!structure->m_specificValueInPrevious);
+ result.first->second = structure;
}
}
@@ -191,21 +156,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 +189,12 @@ void Structure::dumpStatistics()
#endif
}
-Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
+Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
: m_typeInfo(typeInfo)
, m_prototype(prototype)
, m_specificValueInPrevious(0)
- , m_propertyTable(0)
- , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
+ , m_classInfo(classInfo)
+ , m_propertyStorageCapacity(typeInfo.isFinal() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
, m_offset(noOffset)
, m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
@@ -237,16 +203,48 @@ 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(const Structure* previous)
+ : m_typeInfo(previous->typeInfo())
+ , m_prototype(previous->storedPrototype())
+ , m_specificValueInPrevious(0)
+ , 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)
+{
ASSERT(m_prototype);
ASSERT(m_prototype->isObject() || m_prototype->isNull());
#ifndef NDEBUG
#if ENABLE(JSC_MULTIPLE_THREADS)
- MutexLocker protect(ignoreSetMutex);
+ MutexLocker protect(ignoreSetMutex());
#endif
if (shouldIgnoreLeaks)
ignoreSet.add(this);
@@ -263,28 +261,12 @@ 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);
+ m_previous->m_transitionTable.remove(this);
}
- if (!m_isUsingSingleSlot)
- delete transitionTable();
-
#ifndef NDEBUG
#if ENABLE(JSC_MULTIPLE_THREADS)
- MutexLocker protect(ignoreSetMutex);
+ MutexLocker protect(ignoreSetMutex());
#endif
HashSet<Structure*>::iterator it = ignoreSet.find(this);
if (it != ignoreSet.end())
@@ -312,43 +294,6 @@ void Structure::stopIgnoringLeaks()
#endif
}
-static bool isPowerOf2(unsigned v)
-{
- // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
-
- return !(v & (v - 1)) && v;
-}
-
-static 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;
-}
-
-static unsigned sizeForKeyCount(size_t keyCount)
-{
- if (keyCount == notFound)
- return newTableSize;
-
- if (keyCount < 8)
- return newTableSize;
-
- if (isPowerOf2(keyCount))
- return keyCount * 4;
-
- return nextPowerOf2(keyCount) * 2;
-}
-
void Structure::materializePropertyMap()
{
ASSERT(!m_propertyTable);
@@ -358,13 +303,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(m_offset + 1);
break;
}
@@ -372,72 +317,35 @@ 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(structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious);
+ 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)
{
- const StringImpl* rep = propertyName.impl();
+ StringImpl* rep = propertyName.impl();
materializePropertyMapIfNecessary();
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 = 0;
}
PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
@@ -445,7 +353,10 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
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;
+ if (specificValueInPrevious && specificValueInPrevious != specificValue)
+ return 0;
ASSERT(existingTransition->m_offset != noOffset);
offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount;
ASSERT(offset >= structure->m_anonymousSlotCount);
@@ -458,6 +369,16 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
PassRefPtr<Structure> Structure::addPropertyTransition(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));
@@ -476,30 +397,24 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
return transition.release();
}
- RefPtr<Structure> transition = create(structure->m_prototype.get(), structure->typeInfo(), structure->anonymousSlotCount());
+ RefPtr<Structure> transition = create(structure);
transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
transition->m_previous = 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;
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(structure->m_propertyTable->size() + 1);
+ else
+ transition->m_propertyTable = structure->m_propertyTable.release();
} else {
if (structure->m_previous)
transition->materializePropertyMap();
else
- transition->createPropertyMapHashTable();
+ transition->createPropertyMap();
}
offset = transition->put(propertyName, attributes, specificValue);
@@ -510,7 +425,7 @@ 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);
+ structure->m_transitionTable.add(transition.get());
return transition.release();
}
@@ -529,12 +444,9 @@ PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure,
PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
{
- RefPtr<Structure> transition = create(prototype, structure->typeInfo(), structure->anonymousSlotCount());
+ RefPtr<Structure> transition = create(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 = prototype;
// Don't set m_offset, as one can not transition to this.
@@ -549,12 +461,9 @@ PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure,
PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
{
ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount);
- RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
+ RefPtr<Structure> transition = create(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.
@@ -575,11 +484,7 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur
PassRefPtr<Structure> Structure::getterSetterTransition(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;
+ RefPtr<Structure> transition = create(structure);
// Don't set m_offset, as one can not transition to this.
@@ -595,16 +500,12 @@ PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, Di
{
ASSERT(!structure->isUncacheableDictionary());
- RefPtr<Structure> transition = create(structure->m_prototype.get(), structure->typeInfo(), structure->anonymousSlotCount());
- 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;
-
+ RefPtr<Structure> transition = create(structure);
+
structure->materializePropertyMapIfNecessary();
transition->m_propertyTable = structure->copyPropertyTable();
transition->m_isPinnedPropertyTable = true;
+ transition->m_dictionaryKind = kind;
ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
return transition.release();
@@ -620,43 +521,109 @@ PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* st
return toDictionaryTransition(structure, UncachedDictionaryKind);
}
+// In future we may want to cache this transition.
+PassRefPtr<Structure> Structure::sealTransition(Structure* structure)
+{
+ RefPtr<Structure> transition = preventExtensionsTransition(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.release();
+}
+
+// In future we may want to cache this transition.
+PassRefPtr<Structure> Structure::freezeTransition(Structure* structure)
+{
+ RefPtr<Structure> transition = preventExtensionsTransition(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.release();
+}
+
+// In future we may want to cache this transition.
+PassRefPtr<Structure> Structure::preventExtensionsTransition(Structure* structure)
+{
+ RefPtr<Structure> transition = create(structure);
+
+ // Don't set m_offset, as one can not transition to this.
+
+ structure->materializePropertyMapIfNecessary();
+ transition->m_propertyTable = structure->copyPropertyTable();
+ transition->m_isPinnedPropertyTable = true;
+ transition->m_preventExtensions = true;
+
+ ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+ return transition.release();
+}
+
+// In future we may want to cache this property.
+bool Structure::isSealed()
+{
+ if (isExtensible())
+ return false;
+
+ materializePropertyMapIfNecessary();
+ 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;
+}
+
+// In future we may want to cache this property.
+bool Structure::isFrozen()
+{
+ if (isExtensible())
+ return false;
+
+ materializePropertyMapIfNecessary();
+ 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)
{
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;
@@ -696,11 +663,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 +680,6 @@ PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
#endif
-static const unsigned deletedSentinelIndex = 1;
-
#if !DO_PROPERTYMAP_CONSTENCY_CHECK
inline void Structure::checkConsistency()
@@ -728,126 +688,41 @@ inline void Structure::checkConsistency()
#endif
-PropertyMapHashTable* Structure::copyPropertyTable()
+PropertyTable* Structure::copyPropertyTable()
{
- 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(*m_propertyTable) : 0;
}
-size_t Structure::get(const StringImpl* rep, unsigned& attributes, JSCell*& specificValue)
+size_t Structure::get(StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue)
{
materializePropertyMapIfNecessary();
if (!m_propertyTable)
- return notFound;
+ return WTF::notFound;
- unsigned i = rep->existingHash();
+ PropertyMapEntry* entry = m_propertyTable->find(propertyName).first;
+ if (!entry)
+ return WTF::notFound;
-#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
-
- 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;
- }
- }
+ attributes = entry->attributes;
+ specificValue = entry->specificValue;
+ ASSERT(entry->offset >= m_anonymousSlotCount);
+ return entry->offset;
}
bool Structure::despecifyFunction(const Identifier& propertyName)
{
- ASSERT(!propertyName.isNull());
-
materializePropertyMapIfNecessary();
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 = 0;
+ return true;
}
void Structure::despecifyAllFunctions()
@@ -855,10 +730,10 @@ void Structure::despecifyAllFunctions()
materializePropertyMapIfNecessary();
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 = 0;
}
size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
@@ -867,99 +742,28 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
ASSERT(get(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(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 +775,104 @@ 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)
-{
- ASSERT(m_propertyTable);
- ASSERT(isPowerOf2(newTableSize));
-
- checkConsistency();
-
- PropertyMapHashTable* oldTable = m_propertyTable;
-
- m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
- m_propertyTable->size = newTableSize;
- m_propertyTable->sizeMask = newTableSize - 1;
-
- 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]);
- }
- }
- 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)
{
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);
- }
-
- return;
- }
-
- // Allocate a buffer to use to sort the keys.
- Vector<PropertyMapEntry*, smallMapThreshold> sortedEnumerables(m_propertyTable->keyCount);
+ bool knownUnique = !propertyNames.size();
- // 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];
+ 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);
+ }
}
+}
- 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);
- }
+void Structure::initializeThreading()
+{
+#if !defined(NDEBUG) && ENABLE(JSC_MULTIPLE_THREADS)
+ ignoreSetMutex();
+#endif
}
#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 +881,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..bf27334 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -40,11 +40,6 @@
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
-#ifndef NDEBUG
-#define DUMP_PROPERTYMAP_STATS 0
-#else
-#define DUMP_PROPERTYMAP_STATS 0
-#endif
namespace JSC {
@@ -52,6 +47,8 @@ namespace JSC {
class PropertyNameArray;
class PropertyNameArrayData;
+ struct ClassInfo;
+
enum EnumerationMode {
ExcludeDontEnumProperties,
IncludeDontEnumProperties
@@ -61,9 +58,9 @@ namespace JSC {
public:
friend class JIT;
friend class StructureTransitionTable;
- static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
+ static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
{
- return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount));
+ return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount, classInfo));
}
static void startIgnoringLeaks();
@@ -79,6 +76,13 @@ namespace JSC {
static PassRefPtr<Structure> getterSetterTransition(Structure*);
static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> sealTransition(Structure*);
+ static PassRefPtr<Structure> freezeTransition(Structure*);
+ static PassRefPtr<Structure> preventExtensionsTransition(Structure*);
+
+ bool isSealed();
+ bool isFrozen();
+ bool isExtensible() const { return !m_preventExtensions; }
PassRefPtr<Structure> flattenDictionaryStructure(JSGlobalData&, JSObject*);
@@ -103,25 +107,16 @@ namespace JSC {
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(StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
size_t get(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);
- }
bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
@@ -131,19 +126,28 @@ 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 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.
+ void clearEnumerationCache(); // Defined in JSPropertyNameIterator.h.
JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
void getPropertyNames(PropertyNameArray&, EnumerationMode mode);
-
+
+ const ClassInfo* classInfo() const { return m_classInfo; }
+
+ static void initializeThreading();
+
private:
+ Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*);
+ Structure(const Structure*);
- Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount);
+ static PassRefPtr<Structure> create(const Structure* structure)
+ {
+ return adoptRef(new Structure(structure));
+ }
typedef enum {
NoneDictionaryKind = 0,
@@ -155,24 +159,18 @@ namespace JSC {
size_t put(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();
- PropertyMapHashTable* copyPropertyTable();
+ PropertyTable* copyPropertyTable();
void materializePropertyMap();
void materializePropertyMapIfNecessary()
{
- if (m_propertyTable || !m_previous)
- return;
- materializePropertyMap();
+ if (!m_propertyTable && m_previous)
+ materializePropertyMap();
}
signed char transitionCount() const
@@ -181,24 +179,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;
@@ -214,15 +196,13 @@ namespace JSC {
RefPtr<StringImpl> m_nameInPrevious;
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;
+
+ StructureTransitionTable m_transitionTable;
WeakGCPtr<JSPropertyNameIterator> m_enumerationCache;
- PropertyMapHashTable* m_propertyTable;
+ OwnPtr<PropertyTable> m_propertyTable;
uint32_t m_propertyStorageCapacity;
@@ -243,53 +223,19 @@ 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)
{
- ASSERT(!propertyName.isNull());
-
materializePropertyMapIfNecessary();
if (!m_propertyTable)
- return WTF::notFound;
-
- 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)
- return WTF::notFound;
-
- if (rep == m_propertyTable->entries()[entryIndex - 1].key)
- return m_propertyTable->entries()[entryIndex - 1].offset;
+ return notFound;
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
- unsigned k = 1 | WTF::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 WTF::notFound;
-
- if (rep == m_propertyTable->entries()[entryIndex - 1].key)
- return m_propertyTable->entries()[entryIndex - 1].offset;
- }
+ PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
+ ASSERT(!entry || entry->offset >= m_anonymousSlotCount);
+ return entry ? entry->offset : notFound;
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
index 7e9d7ff..da78e1b 100644
--- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h
+++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
@@ -35,9 +35,12 @@
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,62 @@ namespace JSC {
static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
};
+ typedef HashMap<Hash::Key, Structure*, Hash, HashTraits> TransitionMap;
+
+public:
+ StructureTransitionTable()
+ : m_data(UsingSingleSlotFlag)
+ {
+ }
+
+ ~StructureTransitionTable()
+ {
+ if (!isUsingSingleSlot())
+ delete map();
+ }
+
+ inline void add(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);
+ }
+
+ void setMap(TransitionMap* map)
+ {
+ ASSERT(isUsingSingleSlot());
+
+ // 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());
+ return reinterpret_cast<Structure*>(m_data & ~UsingSingleSlotFlag);
+ }
+
+ void setSingleTransition(Structure* structure)
+ {
+ ASSERT(isUsingSingleSlot());
+ m_data = reinterpret_cast<intptr_t>(structure) | UsingSingleSlotFlag;
+ }
+
+ intptr_t m_data;
+};
+
} // namespace JSC
#endif // StructureTransitionTable_h
diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h
index 7bf4503..a40e684 100644
--- a/Source/JavaScriptCore/runtime/WeakGCMap.h
+++ b/Source/JavaScriptCore/runtime/WeakGCMap.h
@@ -26,110 +26,127 @@
#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 whose get() function returns emptyValue() for cells awaiting destruction.
-template<typename KeyType, typename MappedType>
-class WeakGCMap {
+// A HashMap for GC'd values that removes entries when the associated value
+// dies.
+template<typename KeyType, typename MappedType> class WeakGCMap : private Finalizer {
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> 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 {
+ 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&);
+ ExternalType get(const KeyType& key) const
+ {
+ return HandleTypes<MappedType>::getFromSlot(m_map.get(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(); }
+ HandleSlot getSlot(const KeyType& key) const
+ {
+ return m_map.get(key);
+ }
- MappedType* uncheckedGet(const KeyType& key) const { return m_map.get(key).get(); }
- DeprecatedPtr<MappedType>* uncheckedGetSlot(const KeyType& key)
+ void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
{
- iterator iter = m_map.find(key);
- if (iter == m_map.end())
- return 0;
- return &iter->second;
+ pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
+ HandleSlot slot = iter.first->second;
+ if (iter.second) {
+ slot = globalData.allocateGlobalHandle();
+ iter.first->second = slot;
+ HandleHeap::heapFor(slot)->makeWeak(slot, this, key);
+ }
+ HandleHeap::heapFor(slot)->writeBarrier(slot, value);
+ *slot = value;
}
- bool uncheckedRemove(const KeyType&, MappedType*);
- iterator uncheckedBegin() { return m_map.begin(); }
- iterator uncheckedEnd() { return m_map.end(); }
+ 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;
+ }
- const_iterator uncheckedBegin() const { return m_map.begin(); }
- const_iterator uncheckedEnd() const { return m_map.end(); }
+ size_t size() { return m_map.size(); }
- bool isValid(iterator it) const { return Heap::isMarked(it->second.get()); }
- bool isValid(const_iterator it) const { return Heap::isMarked(it->second.get()); }
+ bool deprecatedRemove(const KeyType& key, ExternalType value)
+ {
+ // This only exists in order to allow some semblance of correctness to
+ // the JSWeakObjectMapClear API
+ typename MapType::iterator iter = m_map.find(key);
+ if (iter == m_map.end())
+ return false;
+ HandleSlot slot = iter->second;
+ ExternalType inmap = HandleTypes<MappedType>::getFromSlot(slot);
+ if (inmap && inmap != value)
+ return false;
+ m_map.remove(iter);
+ HandleHeap::heapFor(slot)->deallocate(slot);
+ return true;
+ }
+ iterator begin() { return iterator(m_map.begin()); }
+ iterator end() { return iterator(m_map.end()); }
+
+ ~WeakGCMap()
+ {
+ clear();
+ }
+
private:
- HashMap<KeyType, DeprecatedPtr<MappedType> > m_map;
-};
-
-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())
- 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;
+ virtual void finalize(Handle<Unknown>, void* key)
+ {
+ HandleSlot slot = m_map.take(static_cast<KeyType>(key));
+ ASSERT(slot);
+ HandleHeap::heapFor(slot)->deallocate(slot);
}
- 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;
-}
+
+ MapType m_map;
+};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/WeakGCPtr.h b/Source/JavaScriptCore/runtime/WeakGCPtr.h
index 4946ee7..3f87b83 100644
--- a/Source/JavaScriptCore/runtime/WeakGCPtr.h
+++ b/Source/JavaScriptCore/runtime/WeakGCPtr.h
@@ -26,128 +26,79 @@
#ifndef WeakGCPtr_h
#define WeakGCPtr_h
+#include "Global.h"
#include "Heap.h"
-#include "GCHandle.h"
namespace JSC {
+// A smart pointer whose get() function returns 0 for cells that have died
-// A smart pointer whose get() function returns 0 for cells awaiting destruction.
-template <typename T> class WeakGCPtr {
+template <typename T> class WeakGCPtr : public HandleConverter<WeakGCPtr<T>, T> {
WTF_MAKE_NONCOPYABLE(WeakGCPtr);
+
public:
+ typedef typename HandleTypes<T>::ExternalType ExternalType;
+
WeakGCPtr()
- : m_ptr(0)
+ : m_slot(0)
{
}
-
- WeakGCPtr(T* ptr) { assign(ptr); }
-
- ~WeakGCPtr()
+
+ WeakGCPtr(JSGlobalData& globalData, Finalizer* finalizer = 0, void* context = 0)
+ : m_slot(globalData.allocateGlobalHandle())
{
- if (m_ptr)
- m_ptr->pool()->free(m_ptr);
+ HandleHeap::heapFor(m_slot)->makeWeak(m_slot, finalizer, context);
}
-
- T* get() const
+
+ WeakGCPtr(JSGlobalData& globalData, ExternalType value, Finalizer* finalizer = 0, void* context = 0)
+ : m_slot(globalData.allocateGlobalHandle())
{
- if (m_ptr && m_ptr->isValidPtr())
- return static_cast<T*>(m_ptr->get());
- return 0;
+ HandleHeap::heapFor(m_slot)->makeWeak(m_slot, finalizer, context);
+ internalSet(value);
}
+
+ ExternalType get() const { return HandleTypes<T>::getFromSlot(m_slot); }
- bool clear(JSCell* p)
+ void clear()
{
- if (!m_ptr || m_ptr->get() != p)
- return false;
-
- m_ptr->pool()->free(m_ptr);
- m_ptr = 0;
- return true;
+ if (m_slot)
+ internalSet(ExternalType());
}
-
- T& operator*() const { return *get(); }
- T* operator->() const { return get(); }
- bool operator!() const { return !get(); }
+ bool operator!() const { return !m_slot || !*m_slot; }
// 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
+ typedef ExternalType (WeakGCPtr::*UnspecifiedBoolType);
+ operator UnspecifiedBoolType*() const { return !*this ? 0 : reinterpret_cast<UnspecifiedBoolType*>(1); }
- WeakGCPtr& operator=(T*);
+ ~WeakGCPtr()
+ {
+ if (!m_slot)
+ return;
+ HandleHeap::heapFor(m_slot)->deallocate(m_slot);
+ }
-#if !ASSERT_DISABLED
- bool hasDeadObject() const { return !!m_ptr; }
-#endif
+ void set(JSGlobalData& globalData, ExternalType value, Finalizer* finalizer)
+ {
+ if (!this->m_slot) {
+ this->m_slot = globalData.allocateGlobalHandle();
+ HandleHeap::heapFor(this->m_slot)->makeWeak(this->m_slot, finalizer, 0);
+ } else
+ ASSERT(HandleHeap::heapFor(this->m_slot)->getFinalizer(this->m_slot) == finalizer);
+ this->internalSet(value);
+ }
private:
- void assign(JSCell* ptr)
+ void internalSet(ExternalType value)
{
- ASSERT(ptr);
- if (m_ptr)
- m_ptr->set(ptr);
- else
- m_ptr = Heap::heap(ptr)->addWeakGCHandle(ptr);
+ ASSERT(m_slot);
+ JSValue newValue(HandleTypes<T>::toJSValue(value));
+ HandleHeap::heapFor(m_slot)->writeBarrier(m_slot, newValue);
+ *m_slot = newValue;
}
- WeakGCHandle* m_ptr;
+ HandleSlot m_slot;
};
-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..44840ad 100644
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
@@ -33,6 +33,7 @@ class JSCell;
class JSGlobalData;
typedef enum { } Unknown;
+typedef JSValue* HandleSlot;
template <class T> class DeprecatedPtr {
public: