summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/runtime')
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/BatchedTransitionOptimizer.h2
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h3
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp4
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/Executable.cpp2
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/Executable.h58
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp2
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp8
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h4
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp2
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp137
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h5
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/MarkStackPosix.cpp22
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp174
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.cpp116
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.h31
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp44
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h17
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp1
18 files changed, 559 insertions, 73 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/src/3rdparty/webkit/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
index b9f738f..929a5e7 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
@@ -38,7 +38,7 @@ namespace JSC {
: m_object(object)
{
if (!m_object->structure()->isDictionary())
- m_object->setStructure(Structure::toDictionaryTransition(m_object->structure()));
+ m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure()));
}
~BatchedTransitionOptimizer()
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h b/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h
index 8493d73..abe5038 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -39,6 +39,9 @@
macro(compile) \
macro(configurable) \
macro(constructor) \
+ macro(create) \
+ macro(defineProperty) \
+ macro(defineProperties) \
macro(enumerable) \
macro(eval) \
macro(exec) \
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp
index f36de54..ec3e000 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp
@@ -37,7 +37,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
{
JSLock lock(exec);
- ProgramExecutable program(source);
+ ProgramExecutable program(exec, source);
JSObject* error = program.checkSyntax(exec);
if (error)
return Completion(Throw, error);
@@ -49,7 +49,7 @@ Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& s
{
JSLock lock(exec);
- ProgramExecutable program(source);
+ ProgramExecutable program(exec, source);
JSObject* error = program.compile(exec, scopeChain.node());
if (error)
return Completion(Throw, error);
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.cpp
index 5e79794..7586746 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.cpp
@@ -259,7 +259,7 @@ PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifi
FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
ASSERT(body);
- return FunctionExecutable::create(functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+ return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
}
UString FunctionExecutable::paramString() const
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.h
index d437d46..9728775 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.h
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Executable.h
@@ -27,7 +27,9 @@
#define Executable_h
#include "JSFunction.h"
+#include "Interpreter.h"
#include "Nodes.h"
+#include "SamplingTool.h"
namespace JSC {
@@ -102,11 +104,30 @@ namespace JSC {
class ScriptExecutable : public ExecutableBase {
public:
- ScriptExecutable(const SourceCode& source)
+ ScriptExecutable(JSGlobalData* globalData, const SourceCode& source)
: ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
, m_features(0)
{
+#if ENABLE(CODEBLOCK_SAMPLING)
+ if (SamplingTool* sampler = globalData->interpreter->sampler())
+ sampler->notifyOfScope(this);
+#else
+ UNUSED_PARAM(globalData);
+#endif
+ }
+
+ ScriptExecutable(ExecState* exec, const SourceCode& source)
+ : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+ , m_source(source)
+ , m_features(0)
+ {
+#if ENABLE(CODEBLOCK_SAMPLING)
+ if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
+ sampler->notifyOfScope(this);
+#else
+ UNUSED_PARAM(exec);
+#endif
}
const SourceCode& source() { return m_source; }
@@ -137,8 +158,8 @@ namespace JSC {
class EvalExecutable : public ScriptExecutable {
public:
- EvalExecutable(const SourceCode& source)
- : ScriptExecutable(source)
+ EvalExecutable(ExecState* exec, const SourceCode& source)
+ : ScriptExecutable(exec, source)
, m_evalCodeBlock(0)
{
}
@@ -157,7 +178,7 @@ namespace JSC {
JSObject* compile(ExecState*, ScopeChainNode*);
ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
- static PassRefPtr<EvalExecutable> create(const SourceCode& source) { return adoptRef(new EvalExecutable(source)); }
+ static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
private:
EvalCodeBlock* m_evalCodeBlock;
@@ -178,8 +199,8 @@ namespace JSC {
class ProgramExecutable : public ScriptExecutable {
public:
- ProgramExecutable(const SourceCode& source)
- : ScriptExecutable(source)
+ ProgramExecutable(ExecState* exec, const SourceCode& source)
+ : ScriptExecutable(exec, source)
, m_programCodeBlock(0)
{
}
@@ -221,9 +242,14 @@ namespace JSC {
class FunctionExecutable : public ScriptExecutable {
friend class JIT;
public:
- static PassRefPtr<FunctionExecutable> create(const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ {
+ return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine));
+ }
+
+ static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
{
- return adoptRef(new FunctionExecutable(name, source, forceUsesArguments, parameters, firstLine, lastLine));
+ return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine));
}
~FunctionExecutable();
@@ -263,8 +289,20 @@ namespace JSC {
static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
private:
- FunctionExecutable(const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
- : ScriptExecutable(source)
+ FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ : ScriptExecutable(globalData, source)
+ , m_forceUsesArguments(forceUsesArguments)
+ , m_parameters(parameters)
+ , m_codeBlock(0)
+ , m_name(name)
+ , m_numVariables(0)
+ {
+ m_firstLine = firstLine;
+ m_lastLine = lastLine;
+ }
+
+ FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ : ScriptExecutable(exec, source)
, m_forceUsesArguments(forceUsesArguments)
, m_parameters(parameters)
, m_codeBlock(0)
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp
index 1fcca81..101f543 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp
@@ -223,7 +223,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot
}
}
- return false;
+ return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
}
bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp
index 3a1909d..8d71ac3 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -175,18 +175,18 @@ void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& proper
}
}
-void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)
+void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes)
{
PropertySlot slot;
if (!symbolTableGet(propertyName, slot))
- JSVariableObject::defineGetter(exec, propertyName, getterFunc);
+ JSVariableObject::defineGetter(exec, propertyName, getterFunc, attributes);
}
-void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)
+void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes)
{
PropertySlot slot;
if (!symbolTableGet(propertyName, slot))
- JSVariableObject::defineSetter(exec, propertyName, setterFunc);
+ JSVariableObject::defineSetter(exec, propertyName, setterFunc, attributes);
}
static inline JSObject* lastInPrototypeChain(JSObject* object)
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h
index d1150cc..5f7137f 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h
@@ -175,8 +175,8 @@ namespace JSC {
virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
- virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
- virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
// Linked list of all global objects that use the same JSGlobalData.
JSGlobalObject*& head() { return d()->globalData->head; }
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index b11070f..5ded370 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -286,7 +286,7 @@ JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValu
if (JSValue parsedObject = preparser.tryLiteralParse())
return parsedObject;
- EvalExecutable eval(makeSource(s));
+ EvalExecutable eval(exec, makeSource(s));
JSObject* error = eval.compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
if (error)
return throwError(exec, error);
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp
index f910603..74af4b1 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp
@@ -275,7 +275,7 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi
return 0;
}
-void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
{
JSValue object = getDirect(propertyName);
if (object && object.isGetterSetter()) {
@@ -286,7 +286,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO
PutPropertySlot slot;
GetterSetter* getterSetter = new (exec) GetterSetter(exec);
- putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
@@ -302,7 +302,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO
getterSetter->setGetter(getterFunction);
}
-void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
{
JSValue object = getDirect(propertyName);
if (object && object.isGetterSetter()) {
@@ -313,7 +313,7 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO
PutPropertySlot slot;
GetterSetter* getterSetter = new (exec) GetterSetter(exec);
- putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
@@ -471,7 +471,7 @@ JSObject* JSObject::unwrappedObject()
void JSObject::removeDirect(const Identifier& propertyName)
{
size_t offset;
- if (m_structure->isDictionary()) {
+ if (m_structure->isUncacheableDictionary()) {
offset = m_structure->removePropertyWithoutTransition(propertyName);
if (offset != WTF::notFound)
putDirectOffset(offset, jsUndefined());
@@ -541,4 +541,131 @@ bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& property
object = asObject(prototype);
}
}
+
+static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue)
+{
+ if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
+ target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter));
+ return true;
+ }
+ attributes &= ~ReadOnly;
+ if (descriptor.getter() && descriptor.getter().isObject())
+ target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes);
+ if (exec->hadException())
+ return false;
+ if (descriptor.setter() && descriptor.setter().isObject())
+ target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes);
+ return !exec->hadException();
+}
+
+bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+ // If we have a new property we can just put it on normally
+ PropertyDescriptor current;
+ if (!getOwnPropertyDescriptor(exec, propertyName, current))
+ return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined());
+
+ if (descriptor.isEmpty())
+ return true;
+
+ if (current.equalTo(descriptor))
+ return true;
+
+ // Filter out invalid changes
+ if (!current.configurable()) {
+ if (descriptor.configurable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to configurable attribute of unconfigurable property.");
+ return false;
+ }
+ if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change enumerable attribute of unconfigurable property.");
+ return false;
+ }
+ }
+
+ // A generic descriptor is simply changing the attributes of an existing property
+ if (descriptor.isGenericDescriptor()) {
+ if (!current.attributesEqual(descriptor)) {
+ deleteProperty(exec, propertyName);
+ putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+ }
+ return true;
+ }
+
+ // Changing between a normal property or an accessor property
+ if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
+ if (!current.configurable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change access mechanism for an unconfigurable property.");
+ return false;
+ }
+ deleteProperty(exec, propertyName);
+ return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined());
+ }
+
+ // Changing the value and attributes of an existing property
+ if (descriptor.isDataDescriptor()) {
+ if (!current.configurable()) {
+ if (!current.writable() && descriptor.writable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change writable attribute of unconfigurable property.");
+ return false;
+ }
+ if (!current.writable()) {
+ if (descriptor.value() || !JSValue::strictEqual(current.value(), descriptor.value())) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change value of a readonly property.");
+ return false;
+ }
+ }
+ } else if (current.attributesEqual(descriptor)) {
+ if (!descriptor.value())
+ return true;
+ PutPropertySlot slot;
+ put(exec, propertyName, descriptor.value(), slot);
+ if (exec->hadException())
+ return false;
+ return true;
+ }
+ deleteProperty(exec, propertyName);
+ return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+ }
+
+ // Changing the accessor functions of an existing accessor property
+ ASSERT(descriptor.isAccessorDescriptor());
+ if (!current.configurable()) {
+ if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(current.setter(), descriptor.setter()))) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property.");
+ return false;
+ }
+ if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(current.getter(), descriptor.getter()))) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property.");
+ return false;
+ }
+ }
+ JSValue accessor = getDirect(propertyName);
+ if (!accessor)
+ return false;
+ GetterSetter* getterSetter = asGetterSetter(accessor);
+ if (current.attributesEqual(descriptor)) {
+ if (descriptor.setter())
+ getterSetter->setSetter(asObject(descriptor.setter()));
+ if (descriptor.getter())
+ getterSetter->setGetter(asObject(descriptor.getter()));
+ return true;
+ }
+ deleteProperty(exec, propertyName);
+ unsigned attrs = current.attributesWithOverride(descriptor);
+ if (descriptor.setter())
+ attrs |= Setter;
+ if (descriptor.getter())
+ attrs |= Getter;
+ putDirect(propertyName, getterSetter, attrs);
+ return true;
+}
+
} // namespace JSC
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h
index bdc949b..3fd1e3c 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h
@@ -186,10 +186,11 @@ namespace JSC {
void fillGetterPropertySlot(PropertySlot&, JSValue* location);
- virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
- virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
+ virtual bool defineOwnProperty(ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
virtual bool isGlobalObject() const { return false; }
virtual bool isVariableObject() const { return false; }
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/MarkStackPosix.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/MarkStackPosix.cpp
index 8e78ff3..43f8b29 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/MarkStackPosix.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/MarkStackPosix.cpp
@@ -29,22 +29,44 @@
#include "MarkStack.h"
#include <unistd.h>
+#if defined (__SYMBIAN32__)
+#include "wtf/FastMalloc.h"
+#include <e32base.h>
+#include <e32std.h>
+#include <e32hal.h>
+#include <hal.h>
+#else
#include <sys/mman.h>
+#endif
namespace JSC {
void MarkStack::initializePagesize()
{
+#if defined (__SYMBIAN32__)
+ TInt page_size;
+ UserHal::PageSizeInBytes(page_size);
+ MarkStack::s_pageSize = page_size;
+#else
MarkStack::s_pageSize = getpagesize();
+#endif
}
void* MarkStack::allocateStack(size_t size)
{
+#if defined (__SYMBIAN32__)
+ return fastMalloc(size);
+#else
return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#endif
}
void MarkStack::releaseStack(void* addr, size_t size)
{
+#if defined (__SYMBIAN32__)
+ fastFree(addr);
+#else
munmap(addr, size);
+#endif
}
}
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp
index fd45c45..2992f1b 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -37,6 +37,9 @@ ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorCreate(ExecState*, JSObject*, JSValue, const ArgList&);
ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
@@ -50,6 +53,9 @@ ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> stru
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().create, objectConstructorCreate), DontEnum);
}
// ECMA 15.2.2
@@ -103,15 +109,14 @@ JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec,
return jsUndefined();
if (exec->hadException())
return jsUndefined();
- ASSERT(descriptor.isValid());
JSObject* description = constructEmptyObject(exec);
- if (!descriptor.hasAccessors()) {
- description->putDirect(exec->propertyNames().value, descriptor.value(), 0);
+ if (!descriptor.isAccessorDescriptor()) {
+ description->putDirect(exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
} else {
- description->putDirect(exec->propertyNames().get, descriptor.getter(), 0);
- description->putDirect(exec->propertyNames().set, descriptor.setter(), 0);
+ description->putDirect(exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
+ description->putDirect(exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
}
description->putDirect(exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
@@ -133,4 +138,163 @@ JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue,
return keys;
}
+// ES5 8.10.5 ToPropertyDescriptor
+static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
+{
+ if (!in.isObject()) {
+ throwError(exec, TypeError, "Property description must be an object.");
+ return false;
+ }
+ JSObject* description = asObject(in);
+
+ PropertySlot enumerableSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) {
+ desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec));
+ if (exec->hadException())
+ return false;
+ }
+
+ PropertySlot configurableSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) {
+ desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec));
+ if (exec->hadException())
+ return false;
+ }
+
+ JSValue value;
+ PropertySlot valueSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) {
+ desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value));
+ if (exec->hadException())
+ return false;
+ }
+
+ PropertySlot writableSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) {
+ desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec));
+ if (exec->hadException())
+ return false;
+ }
+
+ PropertySlot getSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) {
+ JSValue get = getSlot.getValue(exec, exec->propertyNames().get);
+ if (exec->hadException())
+ return false;
+ if (!get.isUndefined()) {
+ CallData callData;
+ if (get.getCallData(callData) == CallTypeNone) {
+ throwError(exec, TypeError, "Getter must be a function.");
+ return false;
+ }
+ } else
+ get = JSValue();
+ desc.setGetter(get);
+ }
+
+ PropertySlot setSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) {
+ JSValue set = setSlot.getValue(exec, exec->propertyNames().set);
+ if (exec->hadException())
+ return false;
+ if (!set.isUndefined()) {
+ CallData callData;
+ if (set.getCallData(callData) == CallTypeNone) {
+ throwError(exec, TypeError, "Setter must be a function.");
+ return false;
+ }
+ } else
+ set = JSValue();
+
+ desc.setSetter(set);
+ }
+
+ if (!desc.isAccessorDescriptor())
+ return true;
+
+ if (desc.value()) {
+ throwError(exec, TypeError, "Invalid property. 'value' present on property with getter or setter.");
+ return false;
+ }
+
+ if (desc.writablePresent()) {
+ throwError(exec, TypeError, "Invalid property. 'writable' present on property with getter or setter.");
+ return false;
+ }
+ return true;
+}
+
+JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject())
+ return throwError(exec, TypeError, "Properties can only be defined on Objects.");
+ JSObject* O = asObject(args.at(0));
+ UString propertyName = args.at(1).toString(exec);
+ if (exec->hadException())
+ return jsNull();
+ PropertyDescriptor descriptor;
+ if (!toPropertyDescriptor(exec, args.at(2), descriptor))
+ return jsNull();
+ ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor()));
+ ASSERT(!exec->hadException());
+ O->defineOwnProperty(exec, Identifier(exec, propertyName), descriptor, true);
+ return O;
+}
+
+static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
+{
+ PropertyNameArray propertyNames(exec);
+ asObject(properties)->getOwnPropertyNames(exec, propertyNames);
+ size_t numProperties = propertyNames.size();
+ Vector<PropertyDescriptor> descriptors;
+ MarkedArgumentBuffer markBuffer;
+ for (size_t i = 0; i < numProperties; i++) {
+ PropertySlot slot;
+ JSValue prop = properties->get(exec, propertyNames[i]);
+ if (exec->hadException())
+ return jsNull();
+ PropertyDescriptor descriptor;
+ if (!toPropertyDescriptor(exec, prop, descriptor))
+ return jsNull();
+ descriptors.append(descriptor);
+ // Ensure we mark all the values that we're accumulating
+ if (descriptor.isDataDescriptor() && descriptor.value())
+ markBuffer.append(descriptor.value());
+ if (descriptor.isAccessorDescriptor()) {
+ if (descriptor.getter())
+ markBuffer.append(descriptor.getter());
+ if (descriptor.setter())
+ markBuffer.append(descriptor.setter());
+ }
+ }
+ for (size_t i = 0; i < numProperties; i++) {
+ object->defineOwnProperty(exec, propertyNames[i], descriptors[i], true);
+ if (exec->hadException())
+ return jsNull();
+ }
+ return object;
+}
+
+JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject())
+ return throwError(exec, TypeError, "Properties can only be defined on Objects.");
+ if (!args.at(1).isObject())
+ return throwError(exec, TypeError, "Property descriptor list must be an Object.");
+ return defineProperties(exec, asObject(args.at(0)), asObject(args.at(1)));
+}
+
+JSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject() && !args.at(0).isNull())
+ return throwError(exec, TypeError, "Object prototype may only be an Object or null.");
+ JSObject* newObject = constructEmptyObject(exec);
+ newObject->setPrototype(args.at(0));
+ if (args.at(1).isUndefined())
+ return newObject;
+ if (!args.at(1).isObject())
+ return throwError(exec, TypeError, "Property descriptor list must be an Object.");
+ return defineProperties(exec, newObject, asObject(args.at(1)));
+}
+
} // namespace JSC
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.cpp
index d892e0a..4db814f 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.cpp
@@ -30,29 +30,40 @@
#include "GetterSetter.h"
#include "JSObject.h"
+#include "Operations.h"
namespace JSC {
+unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1;
+
bool PropertyDescriptor::writable() const
{
- ASSERT(!hasAccessors());
+ ASSERT(!isAccessorDescriptor());
return !(m_attributes & ReadOnly);
}
bool PropertyDescriptor::enumerable() const
{
- ASSERT(isValid());
return !(m_attributes & DontEnum);
}
bool PropertyDescriptor::configurable() const
{
- ASSERT(isValid());
return !(m_attributes & DontDelete);
}
-bool PropertyDescriptor::hasAccessors() const
+bool PropertyDescriptor::isDataDescriptor() const
{
- return !!(m_attributes & (Getter | Setter));
+ return m_value || (m_seenAttributes & WritablePresent);
+}
+
+bool PropertyDescriptor::isGenericDescriptor() const
+{
+ return !isAccessorDescriptor() && !isDataDescriptor();
+}
+
+bool PropertyDescriptor::isAccessorDescriptor() const
+{
+ return m_getter || m_setter;
}
void PropertyDescriptor::setUndefined()
@@ -63,32 +74,31 @@ void PropertyDescriptor::setUndefined()
JSValue PropertyDescriptor::getter() const
{
- ASSERT(hasAccessors());
- if (!m_getter)
- return jsUndefined();
+ ASSERT(isAccessorDescriptor());
return m_getter;
}
JSValue PropertyDescriptor::setter() const
{
- ASSERT(hasAccessors());
- if (!m_setter)
- return jsUndefined();
+ ASSERT(isAccessorDescriptor());
return m_setter;
}
void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
{
ASSERT(value);
+ m_attributes = attributes;
if (attributes & (Getter | Setter)) {
GetterSetter* accessor = asGetterSetter(value);
m_getter = accessor->getter();
m_setter = accessor->setter();
ASSERT(m_getter || m_setter);
+ m_seenAttributes = EnumerablePresent | ConfigurablePresent;
+ m_attributes &= ~ReadOnly;
} else {
m_value = value;
+ m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
}
- m_attributes = attributes;
}
void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes)
@@ -98,6 +108,88 @@ void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, u
m_attributes = attributes;
m_getter = getter;
m_setter = setter;
+ m_attributes &= ~ReadOnly;
+ m_seenAttributes = EnumerablePresent | ConfigurablePresent;
+}
+
+void PropertyDescriptor::setWritable(bool writable)
+{
+ if (writable)
+ m_attributes &= ~ReadOnly;
+ else
+ m_attributes |= ReadOnly;
+ m_seenAttributes |= WritablePresent;
+}
+
+void PropertyDescriptor::setEnumerable(bool enumerable)
+{
+ if (enumerable)
+ m_attributes &= ~DontEnum;
+ else
+ m_attributes |= DontEnum;
+ m_seenAttributes |= EnumerablePresent;
+}
+
+void PropertyDescriptor::setConfigurable(bool configurable)
+{
+ if (configurable)
+ m_attributes &= ~DontDelete;
+ else
+ m_attributes |= DontDelete;
+ m_seenAttributes |= ConfigurablePresent;
+}
+
+void PropertyDescriptor::setSetter(JSValue setter)
+{
+ m_setter = setter;
+ m_attributes |= Setter;
+ m_attributes &= ~ReadOnly;
+}
+
+void PropertyDescriptor::setGetter(JSValue getter)
+{
+ m_getter = getter;
+ m_attributes |= Getter;
+ m_attributes &= ~ReadOnly;
+}
+
+bool PropertyDescriptor::equalTo(const PropertyDescriptor& other) const
+{
+ if (!other.m_value == m_value ||
+ !other.m_getter == m_getter ||
+ !other.m_setter == m_setter)
+ return false;
+ return (!m_value || JSValue::strictEqual(other.m_value, m_value)) &&
+ (!m_getter || JSValue::strictEqual(other.m_getter, m_getter)) &&
+ (!m_setter || JSValue::strictEqual(other.m_setter, m_setter)) &&
+ attributesEqual(other);
+}
+
+bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
+{
+ unsigned mismatch = other.m_attributes ^ m_attributes;
+ unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
+ if (sharedSeen & WritablePresent && mismatch & ReadOnly)
+ return false;
+ if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
+ return false;
+ if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
+ return false;
+ return true;
+}
+
+unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
+{
+ unsigned mismatch = other.m_attributes ^ m_attributes;
+ unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
+ unsigned newAttributes = m_attributes & defaultAttributes;
+ if (sharedSeen & WritablePresent && mismatch & ReadOnly)
+ newAttributes ^= ReadOnly;
+ if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
+ newAttributes ^= DontDelete;
+ if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
+ newAttributes ^= DontEnum;
+ return newAttributes;
}
}
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.h b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.h
index ad7c056..40bec86 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.h
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyDescriptor.h
@@ -32,29 +32,48 @@ namespace JSC {
class PropertyDescriptor {
public:
PropertyDescriptor()
- : m_attributes(0)
+ : m_attributes(defaultAttributes)
+ , m_seenAttributes(0)
{
}
bool writable() const;
bool enumerable() const;
bool configurable() const;
- bool hasAccessors() const;
+ bool isDataDescriptor() const;
+ bool isGenericDescriptor() const;
+ bool isAccessorDescriptor() const;
unsigned attributes() const { return m_attributes; }
-#ifndef NDEBUG
- bool isValid() const { return m_value || ((m_getter || m_setter) && hasAccessors()); }
-#endif
- JSValue value() const { ASSERT(m_value); return m_value; }
+ JSValue value() const { return m_value; }
JSValue getter() const;
JSValue setter() const;
void setUndefined();
void setDescriptor(JSValue value, unsigned attributes);
void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes);
+ void setWritable(bool);
+ void setEnumerable(bool);
+ void setConfigurable(bool);
+ void setValue(JSValue value) { m_value = value; }
+ void setSetter(JSValue);
+ void setGetter(JSValue);
+ bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); }
+ bool writablePresent() const { return m_seenAttributes & WritablePresent; }
+ bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; }
+ bool configurablePresent() const { return m_seenAttributes & ConfigurablePresent; }
+ bool setterPresent() const { return m_setter; }
+ bool getterPresent() const { return m_getter; }
+ bool equalTo(const PropertyDescriptor& other) const;
+ bool attributesEqual(const PropertyDescriptor& other) const;
+ unsigned attributesWithOverride(const PropertyDescriptor& other) const;
private:
+ static unsigned defaultAttributes;
+ bool operator==(const PropertyDescriptor&){ return false; }
+ enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4};
// May be a getter/setter
JSValue m_value;
JSValue m_getter;
JSValue m_setter;
unsigned m_attributes;
+ unsigned m_seenAttributes;
};
}
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
index 34c27b7..7209b5f 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
@@ -127,7 +127,7 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
, m_propertyTable(0)
, m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
, m_offset(noOffset)
- , m_isDictionary(false)
+ , m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(false)
, m_attributesInPrevious(0)
@@ -290,7 +290,7 @@ void Structure::getOwnEnumerablePropertyNames(ExecState* exec, PropertyNameArray
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
{
- bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary);
+ bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());
if (shouldCache && m_cachedPropertyNameArrayData) {
if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
@@ -349,7 +349,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
materializePropertyMapIfNecessary();
- ASSERT(m_isDictionary);
+ ASSERT(isDictionary());
ASSERT(m_propertyTable);
unsigned i = rep->computedHash();
@@ -391,7 +391,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isDictionary());
ASSERT(structure->typeInfo().type() == ObjectType);
if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
@@ -405,12 +405,12 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isDictionary());
ASSERT(structure->typeInfo().type() == ObjectType);
ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
if (structure->transitionCount() > s_maxTransitionLength) {
- RefPtr<Structure> transition = toDictionaryTransition(structure);
+ RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
ASSERT(structure != transition);
offset = transition->put(propertyName, attributes, specificValue);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
@@ -454,9 +454,9 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isUncacheableDictionary());
- RefPtr<Structure> transition = toDictionaryTransition(structure);
+ RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
offset = transition->remove(propertyName);
@@ -554,25 +554,35 @@ PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
return transition.release();
}
-PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure)
+PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind)
{
- ASSERT(!structure->m_isDictionary);
-
+ ASSERT(!structure->isUncacheableDictionary());
+
RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
- transition->m_isDictionary = true;
+ transition->m_dictionaryKind = kind;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
-
+
structure->materializePropertyMapIfNecessary();
transition->m_propertyTable = structure->copyPropertyTable();
transition->m_isPinnedPropertyTable = true;
-
+
return transition.release();
}
+PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure)
+{
+ return toDictionaryTransition(structure, CachedDictionaryKind);
+}
+
+PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure)
+{
+ return toDictionaryTransition(structure, UncachedDictionaryKind);
+}
+
PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
{
- ASSERT(structure->m_isDictionary);
+ ASSERT(structure->isDictionary());
// Since dictionary Structures are not shared, and no opcodes specialize
// for them, we don't need to allocate a new Structure when transitioning
@@ -581,7 +591,7 @@ PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
// FIMXE: We can make this more efficient by canonicalizing the Structure (draining the
// deleted offsets vector) before transitioning from dictionary.
if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty())
- structure->m_isDictionary = false;
+ structure->m_dictionaryKind = NoneDictionaryKind;
return structure;
}
@@ -600,7 +610,7 @@ size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, u
size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
{
- ASSERT(m_isDictionary);
+ ASSERT(isUncacheableDictionary());
materializePropertyMapIfNecessary();
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h
index f7cb04b..ed9f6e5 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h
@@ -70,7 +70,8 @@ namespace JSC {
static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);
static PassRefPtr<Structure> addAnonymousSlotsTransition(Structure*, unsigned count);
static PassRefPtr<Structure> getterSetterTransition(Structure*);
- static PassRefPtr<Structure> toDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
static PassRefPtr<Structure> fromDictionaryTransition(Structure*);
~Structure();
@@ -81,8 +82,9 @@ namespace JSC {
size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t removePropertyWithoutTransition(const Identifier& propertyName);
void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; }
-
- bool isDictionary() const { return m_isDictionary; }
+
+ bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
+ bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
const TypeInfo& typeInfo() const { return m_typeInfo; }
@@ -127,6 +129,13 @@ namespace JSC {
private:
Structure(JSValue prototype, const TypeInfo&);
+
+ typedef enum {
+ NoneDictionaryKind = 0,
+ CachedDictionaryKind = 1,
+ UncachedDictionaryKind = 2
+ } DictionaryKind;
+ static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind);
size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t remove(const Identifier& propertyName);
@@ -187,7 +196,7 @@ namespace JSC {
size_t m_propertyStorageCapacity;
signed char m_offset;
- bool m_isDictionary : 1;
+ unsigned m_dictionaryKind : 2;
bool m_isPinnedPropertyTable : 1;
bool m_hasGetterSetterProperties : 1;
#if COMPILER(WINSCW)
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp
index eb57a5ac..6e8a0ee 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp
@@ -51,6 +51,7 @@ bool StructureChain::isCacheable() const
uint32_t i = 0;
while (m_vector[i]) {
+ // Both classes of dictionary structure may change arbitrarily so we can't cache them
if (m_vector[i]->isDictionary())
return false;
if (!m_vector[i++]->typeInfo().hasDefaultGetPropertyNames())