summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-11-05 09:23:40 +0000
committerSteve Block <steveblock@google.com>2009-11-10 22:41:12 +0000
commitcac0f67c402d107cdb10971b95719e2ff9c7c76b (patch)
treed182c7f87211c6f201a5f038e332336493ebdbe7 /JavaScriptCore/runtime
parent4b2ef0f288e7c6c4602f621b7a0e9feed304b70e (diff)
downloadexternal_webkit-cac0f67c402d107cdb10971b95719e2ff9c7c76b.zip
external_webkit-cac0f67c402d107cdb10971b95719e2ff9c7c76b.tar.gz
external_webkit-cac0f67c402d107cdb10971b95719e2ff9c7c76b.tar.bz2
Merge webkit.org at r50258 : Initial merge by git.
Change-Id: I1a9e1dc4ed654b69174ad52a4f031a07240f37b0
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/Arguments.h5
-rw-r--r--JavaScriptCore/runtime/ArrayConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/BooleanObject.h2
-rw-r--r--JavaScriptCore/runtime/Collector.cpp4
-rw-r--r--JavaScriptCore/runtime/Collector.h8
-rw-r--r--JavaScriptCore/runtime/DateConstructor.cpp4
-rw-r--r--JavaScriptCore/runtime/DateInstance.cpp84
-rw-r--r--JavaScriptCore/runtime/DateInstance.h23
-rw-r--r--JavaScriptCore/runtime/DateInstanceCache.h89
-rw-r--r--JavaScriptCore/runtime/DatePrototype.cpp235
-rw-r--r--JavaScriptCore/runtime/DatePrototype.h6
-rw-r--r--JavaScriptCore/runtime/FunctionPrototype.h2
-rw-r--r--JavaScriptCore/runtime/GetterSetter.h2
-rw-r--r--JavaScriptCore/runtime/GlobalEvalFunction.h5
-rw-r--r--JavaScriptCore/runtime/InternalFunction.h4
-rw-r--r--JavaScriptCore/runtime/JSAPIValueWrapper.h2
-rw-r--r--JavaScriptCore/runtime/JSActivation.h5
-rw-r--r--JavaScriptCore/runtime/JSArray.h5
-rw-r--r--JavaScriptCore/runtime/JSByteArray.cpp2
-rw-r--r--JavaScriptCore/runtime/JSByteArray.h3
-rw-r--r--JavaScriptCore/runtime/JSCell.cpp4
-rw-r--r--JavaScriptCore/runtime/JSCell.h18
-rw-r--r--JavaScriptCore/runtime/JSFunction.h13
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.h4
-rw-r--r--JavaScriptCore/runtime/JSGlobalObject.cpp21
-rw-r--r--JavaScriptCore/runtime/JSGlobalObject.h5
-rw-r--r--JavaScriptCore/runtime/JSNotAnObject.h5
-rw-r--r--JavaScriptCore/runtime/JSNumberCell.h10
-rw-r--r--JavaScriptCore/runtime/JSONObject.h5
-rw-r--r--JavaScriptCore/runtime/JSObject.cpp40
-rw-r--r--JavaScriptCore/runtime/JSObject.h12
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.cpp53
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.h93
-rw-r--r--JavaScriptCore/runtime/JSStaticScopeObject.h5
-rw-r--r--JavaScriptCore/runtime/JSString.cpp41
-rw-r--r--JavaScriptCore/runtime/JSString.h43
-rw-r--r--JavaScriptCore/runtime/JSTypeInfo.h12
-rw-r--r--JavaScriptCore/runtime/JSValue.h8
-rw-r--r--JavaScriptCore/runtime/JSVariableObject.h3
-rw-r--r--JavaScriptCore/runtime/JSWrapperObject.h2
-rw-r--r--JavaScriptCore/runtime/MarkStack.h2
-rw-r--r--JavaScriptCore/runtime/MathObject.h5
-rw-r--r--JavaScriptCore/runtime/NumberConstructor.h5
-rw-r--r--JavaScriptCore/runtime/NumberObject.h14
-rw-r--r--JavaScriptCore/runtime/ObjectConstructor.cpp1
-rw-r--r--JavaScriptCore/runtime/Operations.h27
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.cpp5
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.h35
-rw-r--r--JavaScriptCore/runtime/Protect.h2
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.cpp46
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.h52
-rw-r--r--JavaScriptCore/runtime/RegExpObject.cpp2
-rw-r--r--JavaScriptCore/runtime/RegExpObject.h5
-rw-r--r--JavaScriptCore/runtime/StringObject.h3
-rw-r--r--JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h4
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp63
-rw-r--r--JavaScriptCore/runtime/Structure.cpp96
-rw-r--r--JavaScriptCore/runtime/Structure.h28
-rw-r--r--JavaScriptCore/runtime/StructureChain.cpp14
-rw-r--r--JavaScriptCore/runtime/StructureChain.h3
60 files changed, 686 insertions, 615 deletions
diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h
index 5be84a2..9b674a2 100644
--- a/JavaScriptCore/runtime/Arguments.h
+++ b/JavaScriptCore/runtime/Arguments.h
@@ -85,9 +85,12 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+
private:
void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
diff --git a/JavaScriptCore/runtime/ArrayConstructor.cpp b/JavaScriptCore/runtime/ArrayConstructor.cpp
index 0237fd4..fb44494 100644
--- a/JavaScriptCore/runtime/ArrayConstructor.cpp
+++ b/JavaScriptCore/runtime/ArrayConstructor.cpp
@@ -50,7 +50,7 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, NonNullPassRefPtr<Structure>
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum);
}
-static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
+static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
{
// a single numeric argument denotes the array size (!)
if (args.size() == 1 && args.at(0).isNumber()) {
diff --git a/JavaScriptCore/runtime/BooleanObject.h b/JavaScriptCore/runtime/BooleanObject.h
index 28f796a..69c2e51 100644
--- a/JavaScriptCore/runtime/BooleanObject.h
+++ b/JavaScriptCore/runtime/BooleanObject.h
@@ -34,7 +34,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
};
diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp
index 1a5eb89..1b238d9 100644
--- a/JavaScriptCore/runtime/Collector.cpp
+++ b/JavaScriptCore/runtime/Collector.cpp
@@ -1228,6 +1228,10 @@ static const char* typeName(JSCell* cell)
#endif
if (cell->isGetterSetter())
return "gettersetter";
+ if (cell->isAPIValueWrapper())
+ return "value wrapper";
+ if (cell->isPropertyNameIterator())
+ return "for-in iterator";
ASSERT(cell->isObject());
const ClassInfo* info = cell->classInfo();
return info ? info->className : "Object";
diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h
index 2ce13dc..9ca9d18 100644
--- a/JavaScriptCore/runtime/Collector.h
+++ b/JavaScriptCore/runtime/Collector.h
@@ -71,14 +71,6 @@ namespace JSC {
void destroy();
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
- // We can inline these functions because everything is compiled as
- // one file, so the heapAllocate template definitions are available.
- // However, allocateNumber is used via jsNumberCell outside JavaScriptCore.
- // Thus allocateNumber needs to provide a non-inline version too.
- void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); }
- void* inlineAllocate(size_t s) { return heapAllocate<PrimaryHeap>(s); }
-#endif
void* allocateNumber(size_t);
void* allocate(size_t);
diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp
index f9b7d84..9908fef 100644
--- a/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/JavaScriptCore/runtime/DateConstructor.cpp
@@ -112,9 +112,7 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
}
}
- DateInstance* result = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure());
- result->setInternalValue(jsNumber(exec, timeClip(value)));
- return result;
+ return new (exec) DateInstance(exec, value);
}
static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args)
diff --git a/JavaScriptCore/runtime/DateInstance.cpp b/JavaScriptCore/runtime/DateInstance.cpp
index 4cd58f5..d4c9ef7 100644
--- a/JavaScriptCore/runtime/DateInstance.cpp
+++ b/JavaScriptCore/runtime/DateInstance.cpp
@@ -32,95 +32,43 @@ using namespace WTF;
namespace JSC {
-struct DateInstance::Cache {
- double m_gregorianDateTimeCachedForMS;
- GregorianDateTime m_cachedGregorianDateTime;
- double m_gregorianDateTimeUTCCachedForMS;
- GregorianDateTime m_cachedGregorianDateTimeUTC;
-};
-
const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
-DateInstance::DateInstance(NonNullPassRefPtr<Structure> structure)
+DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure)
: JSWrapperObject(structure)
- , m_cache(0)
{
+ setInternalValue(jsNaN(exec));
}
DateInstance::DateInstance(ExecState* exec, double time)
: JSWrapperObject(exec->lexicalGlobalObject()->dateStructure())
- , m_cache(0)
{
setInternalValue(jsNumber(exec, timeClip(time)));
}
-DateInstance::~DateInstance()
+bool DateInstance::getGregorianDateTime(ExecState* exec, bool outputIsUTC, GregorianDateTime& t) const
{
- delete m_cache;
-}
+ double milli = internalNumber();
+ if (isnan(milli))
+ return false;
-void DateInstance::msToGregorianDateTime(double milli, bool outputIsUTC, GregorianDateTime& t) const
-{
- if (!m_cache) {
- m_cache = new Cache;
- m_cache->m_gregorianDateTimeCachedForMS = NaN;
- m_cache->m_gregorianDateTimeUTCCachedForMS = NaN;
- }
+ if (!m_data)
+ m_data = exec->globalData().dateInstanceCache.add(milli);
if (outputIsUTC) {
- if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) {
- WTF::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC);
- m_cache->m_gregorianDateTimeUTCCachedForMS = milli;
+ if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) {
+ WTF::msToGregorianDateTime(internalNumber(), true, m_data->m_cachedGregorianDateTimeUTC);
+ m_data->m_gregorianDateTimeUTCCachedForMS = milli;
}
- t.copyFrom(m_cache->m_cachedGregorianDateTimeUTC);
+ t.copyFrom(m_data->m_cachedGregorianDateTimeUTC);
} else {
- if (m_cache->m_gregorianDateTimeCachedForMS != milli) {
- WTF::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime);
- m_cache->m_gregorianDateTimeCachedForMS = milli;
+ if (m_data->m_gregorianDateTimeCachedForMS != milli) {
+ WTF::msToGregorianDateTime(internalNumber(), false, m_data->m_cachedGregorianDateTime);
+ m_data->m_gregorianDateTimeCachedForMS = milli;
}
- t.copyFrom(m_cache->m_cachedGregorianDateTime);
+ t.copyFrom(m_data->m_cachedGregorianDateTime);
}
-}
-bool DateInstance::getTime(GregorianDateTime& t, int& offset) const
-{
- double milli = internalNumber();
- if (isnan(milli))
- return false;
-
- msToGregorianDateTime(milli, false, t);
- offset = gmtoffset(t);
- return true;
-}
-
-bool DateInstance::getUTCTime(GregorianDateTime& t) const
-{
- double milli = internalNumber();
- if (isnan(milli))
- return false;
-
- msToGregorianDateTime(milli, true, t);
- return true;
-}
-
-bool DateInstance::getTime(double& milli, int& offset) const
-{
- milli = internalNumber();
- if (isnan(milli))
- return false;
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, false, t);
- offset = gmtoffset(t);
- return true;
-}
-
-bool DateInstance::getUTCTime(double& milli) const
-{
- milli = internalNumber();
- if (isnan(milli))
- return false;
-
return true;
}
diff --git a/JavaScriptCore/runtime/DateInstance.h b/JavaScriptCore/runtime/DateInstance.h
index 36d90b1..38b321c 100644
--- a/JavaScriptCore/runtime/DateInstance.h
+++ b/JavaScriptCore/runtime/DateInstance.h
@@ -32,27 +32,26 @@ namespace JSC {
class DateInstance : public JSWrapperObject {
public:
DateInstance(ExecState*, double);
- explicit DateInstance(NonNullPassRefPtr<Structure>);
- virtual ~DateInstance();
+ explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>);
double internalNumber() const { return internalValue().uncheckedGetNumber(); }
- bool getTime(WTF::GregorianDateTime&, int& offset) const;
- bool getUTCTime(WTF::GregorianDateTime&) const;
- bool getTime(double& milliseconds, int& offset) const;
- bool getUTCTime(double& milliseconds) const;
-
static JS_EXPORTDATA const ClassInfo info;
- void msToGregorianDateTime(double, bool outputIsUTC, WTF::GregorianDateTime&) const;
+ bool getGregorianDateTime(ExecState*, bool outputIsUTC, WTF::GregorianDateTime&) const;
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
+ }
+
+ protected:
+ static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags;
private:
virtual const ClassInfo* classInfo() const { return &info; }
- using JSWrapperObject::internalValue;
-
- struct Cache;
- mutable Cache* m_cache;
+ mutable RefPtr<DateInstanceData> m_data;
};
DateInstance* asDateInstance(JSValue);
diff --git a/JavaScriptCore/runtime/DateInstanceCache.h b/JavaScriptCore/runtime/DateInstanceCache.h
new file mode 100644
index 0000000..b626c1d
--- /dev/null
+++ b/JavaScriptCore/runtime/DateInstanceCache.h
@@ -0,0 +1,89 @@
+/*
+ * 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 DateInstanceCache_h
+#define DateInstanceCache_h
+
+#include <wtf/DateMath.h>
+#include <wtf/HashFunctions.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+ extern const double NaN;
+
+ class DateInstanceData : public RefCounted<DateInstanceData> {
+ public:
+ static PassRefPtr<DateInstanceData> create() { return adoptRef(new DateInstanceData); }
+
+ double m_gregorianDateTimeCachedForMS;
+ WTF::GregorianDateTime m_cachedGregorianDateTime;
+ double m_gregorianDateTimeUTCCachedForMS;
+ WTF::GregorianDateTime m_cachedGregorianDateTimeUTC;
+
+ private:
+ DateInstanceData()
+ : m_gregorianDateTimeCachedForMS(NaN)
+ , m_gregorianDateTimeUTCCachedForMS(NaN)
+ {
+ }
+ };
+
+ class DateInstanceCache {
+ public:
+ DateInstanceCache()
+ {
+ for (size_t i = 0; i < cacheSize; ++i)
+ m_cache[i].key = NaN;
+ }
+
+ DateInstanceData* add(double d)
+ {
+ CacheEntry& entry = lookup(d);
+ if (d == entry.key)
+ return entry.value.get();
+
+ entry.key = d;
+ entry.value = DateInstanceData::create();
+ return entry.value.get();
+ }
+
+ private:
+ static const size_t cacheSize = 64;
+
+ struct CacheEntry {
+ double key;
+ RefPtr<DateInstanceData> value;
+ };
+
+ CacheEntry& lookup(double d) { return m_cache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
+
+ CacheEntry m_cache[cacheSize];
+ };
+
+} // namespace JSC
+
+#endif // DateInstanceCache_h
diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp
index e46ab67..3f3e1f9 100644
--- a/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/JavaScriptCore/runtime/DatePrototype.cpp
@@ -251,11 +251,12 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L
return jsNontrivialString(exec, timebuffer);
}
-static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList&)
+static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double, LocaleDateTimeFormat format, const ArgList&)
{
GregorianDateTime gregorianDateTime;
- const bool notUTC = false;
- dateObject->msToGregorianDateTime(timeInMilliseconds, notUTC, gregorianDateTime);
+ const bool outputIsUTC = false;
+ if (!dateObject->getGregorianDateTime(exec, outputIsUTC, gregorianDateTime))
+ return jsNontrivialString(exec, "Invalid Date");
return formatLocaleDate(exec, gregorianDateTime, format);
}
@@ -396,9 +397,8 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState
// ECMA 15.9.4
DatePrototype::DatePrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
- : DateInstance(structure)
+ : DateInstance(exec, structure)
{
- setInternalValue(jsNaN(exec));
// The constructor will be added later, after DateConstructor has been built.
}
@@ -420,16 +420,14 @@ JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
- return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNontrivialString(exec, "Invalid Date");
+ return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, outputIsUTC));
}
JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -437,16 +435,14 @@ JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSVal
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
- return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNontrivialString(exec, "Invalid Date");
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, outputIsUTC));
}
JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -454,19 +450,17 @@ JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSVal
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (!isfinite(milli))
- return jsNontrivialString(exec, "Invalid Date");
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNontrivialString(exec, "Invalid Date");
// Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
// 6 for formatting and one for null termination = 27. We add one extra character to allow us to force null termination.
char buffer[28];
- snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second, static_cast<int>(fmod(milli, 1000)));
+ snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000)));
buffer[sizeof(buffer) - 1] = 0;
return jsNontrivialString(exec, buffer);
}
@@ -476,15 +470,13 @@ JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSVa
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNontrivialString(exec, "Invalid Date");
return jsNontrivialString(exec, formatDate(t));
}
@@ -493,16 +485,14 @@ JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSVa
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
- return jsNontrivialString(exec, formatTime(t, utc));
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNontrivialString(exec, "Invalid Date");
+ return jsNontrivialString(exec, formatTime(t, outputIsUTC));
}
JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -511,11 +501,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JS
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
-
- return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args);
+ return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime, args);
}
JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -524,11 +510,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
-
- return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args);
+ return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate, args);
}
JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -537,11 +519,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
-
- return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args);
+ return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime, args);
}
JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -549,12 +527,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue t
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
-
- return jsNumber(exec, milli);
+ return asDateInstance(thisValue)->internalValue();
}
JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -562,15 +535,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSVal
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, 1900 + t.year);
}
@@ -579,15 +550,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JS
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, 1900 + t.year);
}
@@ -596,16 +565,14 @@ JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSVal
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNontrivialString(exec, "Invalid Date");
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
- return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNontrivialString(exec, "Invalid Date");
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, outputIsUTC));
}
JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
@@ -613,15 +580,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.month);
}
@@ -630,15 +595,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSVal
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.month);
}
@@ -647,15 +610,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue t
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.monthDay);
}
@@ -664,15 +625,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValu
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.monthDay);
}
@@ -681,15 +640,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue th
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.weekDay);
}
@@ -698,15 +655,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.weekDay);
}
@@ -715,15 +670,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.hour);
}
@@ -732,15 +685,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSVal
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.hour);
}
@@ -749,15 +700,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValu
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.minute);
}
@@ -766,15 +715,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSV
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.minute);
}
@@ -783,15 +730,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValu
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.second);
}
@@ -800,15 +745,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSV
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = true;
+ const bool outputIsUTC = true;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, t.second);
}
@@ -847,15 +790,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*,
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
}
@@ -890,7 +831,7 @@ static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const
double ms = milli - secs * msPerSecond;
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+ thisDateObj->getGregorianDateTime(exec, inputIsUTC, t);
if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
JSValue result = jsNaN(exec);
@@ -922,11 +863,11 @@ static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const
if (numArgsToUse == 3 && isnan(milli))
// Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
// the time must be reset to +0 if it is NaN.
- thisDateObj->msToGregorianDateTime(0, true, t);
+ WTF::msToGregorianDateTime(0, true, t);
else {
double secs = floor(milli / msPerSecond);
ms = milli - secs * msPerSecond;
- thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+ thisDateObj->getGregorianDateTime(exec, inputIsUTC, t);
}
if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
@@ -1029,7 +970,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
if (args.isEmpty()) {
@@ -1045,11 +986,11 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
if (isnan(milli))
// Based on ECMA 262 B.2.5 (setYear)
// the time must be reset to +0 if it is NaN.
- thisDateObj->msToGregorianDateTime(0, true, t);
+ WTF::msToGregorianDateTime(0, true, t);
else {
double secs = floor(milli / msPerSecond);
ms = milli - secs * msPerSecond;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ thisDateObj->getGregorianDateTime(exec, outputIsUTC, t);
}
bool ok = true;
@@ -1061,7 +1002,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
}
t.year = (year > 99 || year < 0) ? year - 1900 : year;
- JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
+ JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, outputIsUTC));
thisDateObj->setInternalValue(result);
return result;
}
@@ -1071,15 +1012,13 @@ JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue t
if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
- const bool utc = false;
+ const bool outputIsUTC = false;
DateInstance* thisDateObj = asDateInstance(thisValue);
- double milli = thisDateObj->internalNumber();
- if (isnan(milli))
- return jsNaN(exec);
GregorianDateTime t;
- thisDateObj->msToGregorianDateTime(milli, utc, t);
+ if (!thisDateObj->getGregorianDateTime(exec, outputIsUTC, t))
+ return jsNaN(exec);
// NOTE: IE returns the full year even in getYear.
return jsNumber(exec, t.year);
diff --git a/JavaScriptCore/runtime/DatePrototype.h b/JavaScriptCore/runtime/DatePrototype.h
index caed2d4..f565775 100644
--- a/JavaScriptCore/runtime/DatePrototype.h
+++ b/JavaScriptCore/runtime/DatePrototype.h
@@ -39,8 +39,12 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
+
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags;
+
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/FunctionPrototype.h b/JavaScriptCore/runtime/FunctionPrototype.h
index 0e38549..d1d6a1d 100644
--- a/JavaScriptCore/runtime/FunctionPrototype.h
+++ b/JavaScriptCore/runtime/FunctionPrototype.h
@@ -34,7 +34,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(proto, TypeInfo(ObjectType, StructureFlags));
}
private:
diff --git a/JavaScriptCore/runtime/GetterSetter.h b/JavaScriptCore/runtime/GetterSetter.h
index 73dd854..68e9ea3 100644
--- a/JavaScriptCore/runtime/GetterSetter.h
+++ b/JavaScriptCore/runtime/GetterSetter.h
@@ -50,7 +50,7 @@ namespace JSC {
void setSetter(JSObject* setter) { m_setter = setter; }
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(GetterSetterType));
+ return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren));
}
private:
virtual bool isGetterSetter() const;
diff --git a/JavaScriptCore/runtime/GlobalEvalFunction.h b/JavaScriptCore/runtime/GlobalEvalFunction.h
index b62ad3e..389b1c3 100644
--- a/JavaScriptCore/runtime/GlobalEvalFunction.h
+++ b/JavaScriptCore/runtime/GlobalEvalFunction.h
@@ -37,9 +37,12 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
+ protected:
+ static const unsigned StructureFlags = ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | PrototypeFunction::StructureFlags;
+
private:
virtual void markChildren(MarkStack&);
diff --git a/JavaScriptCore/runtime/InternalFunction.h b/JavaScriptCore/runtime/InternalFunction.h
index fdd5cc1..de9a1d6 100644
--- a/JavaScriptCore/runtime/InternalFunction.h
+++ b/JavaScriptCore/runtime/InternalFunction.h
@@ -42,10 +42,12 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot | HasDefaultMark));
+ return Structure::create(proto, TypeInfo(ObjectType, StructureFlags));
}
protected:
+ static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
+
InternalFunction(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { }
InternalFunction(JSGlobalData*, NonNullPassRefPtr<Structure>, const Identifier&);
diff --git a/JavaScriptCore/runtime/JSAPIValueWrapper.h b/JavaScriptCore/runtime/JSAPIValueWrapper.h
index 88a8493..aca550e 100644
--- a/JavaScriptCore/runtime/JSAPIValueWrapper.h
+++ b/JavaScriptCore/runtime/JSAPIValueWrapper.h
@@ -39,7 +39,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(CompoundType));
+ return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames));
}
diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h
index 583b988..ee98191 100644
--- a/JavaScriptCore/runtime/JSActivation.h
+++ b/JavaScriptCore/runtime/JSActivation.h
@@ -66,7 +66,10 @@ namespace JSC {
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); }
+
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
private:
struct JSActivationData : public JSVariableObjectData {
diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h
index 66b5a1d..8c22451 100644
--- a/JavaScriptCore/runtime/JSArray.h
+++ b/JavaScriptCore/runtime/JSArray.h
@@ -87,12 +87,13 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
inline void markChildrenDirect(MarkStack& markStack);
protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
@@ -157,7 +158,7 @@ namespace JSC {
inline void MarkStack::markChildren(JSCell* cell)
{
ASSERT(Heap::isCellMarked(cell));
- if (cell->structure()->typeInfo().hasDefaultMark()) {
+ if (!cell->structure()->typeInfo().overridesMarkChildren()) {
#ifdef NDEBUG
asObject(cell)->markChildrenDirect(*this);
#else
diff --git a/JavaScriptCore/runtime/JSByteArray.cpp b/JavaScriptCore/runtime/JSByteArray.cpp
index 90d39f0..5e5003b 100644
--- a/JavaScriptCore/runtime/JSByteArray.cpp
+++ b/JavaScriptCore/runtime/JSByteArray.cpp
@@ -45,7 +45,7 @@ JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure
PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
{
- PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark));
+ PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
return result;
}
diff --git a/JavaScriptCore/runtime/JSByteArray.h b/JavaScriptCore/runtime/JSByteArray.h
index 006f4a2..fe6e124 100644
--- a/JavaScriptCore/runtime/JSByteArray.h
+++ b/JavaScriptCore/runtime/JSByteArray.h
@@ -91,6 +91,9 @@ namespace JSC {
WTF::ByteArray* storage() const { return m_storage.get(); }
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
+
private:
enum VPtrStealingHackType { VPtrStealingHack };
JSByteArray(VPtrStealingHackType)
diff --git a/JavaScriptCore/runtime/JSCell.cpp b/JavaScriptCore/runtime/JSCell.cpp
index aa93252..fae056e 100644
--- a/JavaScriptCore/runtime/JSCell.cpp
+++ b/JavaScriptCore/runtime/JSCell.cpp
@@ -78,11 +78,7 @@ extern const double Inf = NaNInf.doubles.Inf_Double;
void* JSCell::operator new(size_t size, ExecState* exec)
{
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
- return exec->heap()->inlineAllocate(size);
-#else
return exec->heap()->allocate(size);
-#endif
}
bool JSCell::getUInt32(uint32_t&) const
diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h
index 503c6c4..722ae33 100644
--- a/JavaScriptCore/runtime/JSCell.h
+++ b/JavaScriptCore/runtime/JSCell.h
@@ -59,6 +59,7 @@ namespace JSC {
virtual bool isGetterSetter() const;
bool inherits(const ClassInfo*) const;
virtual bool isAPIValueWrapper() const { return false; }
+ virtual bool isPropertyNameIterator() const { return false; }
Structure* structure() const;
@@ -112,14 +113,6 @@ namespace JSC {
Structure* m_structure;
};
- // FIXME: We should deprecate this and just use JSValue::asCell() instead.
- JSCell* asCell(JSValue);
-
- inline JSCell* asCell(JSValue value)
- {
- return value.asCell();
- }
-
inline JSCell::JSCell(Structure* structure)
: m_structure(structure)
{
@@ -162,11 +155,7 @@ namespace JSC {
inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
{
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
- return globalData->heap.inlineAllocate(size);
-#else
return globalData->heap.allocate(size);
-#endif
}
// --- JSValue inlines ----------------------------
@@ -342,11 +331,6 @@ namespace JSC {
append(value.asCell());
}
- inline void Structure::markAggregate(MarkStack& markStack)
- {
- markStack.append(m_prototype);
- }
-
inline Heap* Heap::heap(JSValue v)
{
if (!v.isCell())
diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h
index a9ac63e..fcac9aa 100644
--- a/JavaScriptCore/runtime/JSFunction.h
+++ b/JavaScriptCore/runtime/JSFunction.h
@@ -61,17 +61,20 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
NativeFunction nativeFunction()
{
- return *reinterpret_cast<NativeFunction*>(m_data);
+ return *WTF::bitwise_cast<NativeFunction*>(m_data);
}
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
+ protected:
+ const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | InternalFunction::StructureFlags;
+
private:
JSFunction(NonNullPassRefPtr<Structure>);
@@ -94,7 +97,7 @@ namespace JSC {
ScopeChain& scopeChain()
{
ASSERT(!isHostFunctionNonInline());
- return *reinterpret_cast<ScopeChain*>(m_data);
+ return *WTF::bitwise_cast<ScopeChain*>(m_data);
}
void clearScopeChain()
{
@@ -109,11 +112,11 @@ namespace JSC {
void setScopeChain(const ScopeChain& sc)
{
ASSERT(!isHostFunctionNonInline());
- *reinterpret_cast<ScopeChain*>(m_data) = sc;
+ *WTF::bitwise_cast<ScopeChain*>(m_data) = sc;
}
void setNativeFunction(NativeFunction func)
{
- *reinterpret_cast<NativeFunction*>(m_data) = func;
+ *WTF::bitwise_cast<NativeFunction*>(m_data) = func;
}
unsigned char m_data[sizeof(void*)];
};
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index 3ad90ad..d2aa2da 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -30,6 +30,7 @@
#define JSGlobalData_h
#include "Collector.h"
+#include "DateInstanceCache.h"
#include "ExecutableAllocator.h"
#include "JITStubs.h"
#include "JSValue.h"
@@ -116,7 +117,8 @@ namespace JSC {
const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
SmallStrings smallStrings;
NumericStrings numericStrings;
-
+ DateInstanceCache dateInstanceCache;
+
#if ENABLE(ASSEMBLER)
ExecutableAllocator executableAllocator;
#endif
diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp
index 3bb281e..cf3f1d1 100644
--- a/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -89,7 +89,7 @@ static inline void markIfNeeded(MarkStack& markStack, JSValue v)
static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s)
{
if (s)
- s->markAggregate(markStack);
+ markIfNeeded(markStack, s->storedPrototype());
}
JSGlobalObject::~JSGlobalObject()
@@ -394,6 +394,21 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
markIfNeeded(markStack, d()->methodCallDummy);
markIfNeeded(markStack, d()->errorStructure);
+ markIfNeeded(markStack, d()->argumentsStructure);
+ markIfNeeded(markStack, d()->arrayStructure);
+ markIfNeeded(markStack, d()->booleanObjectStructure);
+ markIfNeeded(markStack, d()->callbackConstructorStructure);
+ markIfNeeded(markStack, d()->callbackFunctionStructure);
+ markIfNeeded(markStack, d()->callbackObjectStructure);
+ markIfNeeded(markStack, d()->dateStructure);
+ markIfNeeded(markStack, d()->emptyObjectStructure);
+ markIfNeeded(markStack, d()->errorStructure);
+ markIfNeeded(markStack, d()->functionStructure);
+ markIfNeeded(markStack, d()->numberObjectStructure);
+ markIfNeeded(markStack, d()->prototypeFunctionStructure);
+ markIfNeeded(markStack, d()->regExpMatchesArrayStructure);
+ markIfNeeded(markStack, d()->regExpStructure);
+ markIfNeeded(markStack, d()->stringObjectStructure);
// No need to mark the other structures, because their prototypes are all
// guaranteed to be referenced elsewhere.
@@ -448,11 +463,7 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
{
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
- return globalData->heap.inlineAllocate(size);
-#else
return globalData->heap.allocate(size);
-#endif
}
void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData)
diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h
index 2106783..720d3a5 100644
--- a/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/JavaScriptCore/runtime/JSGlobalObject.h
@@ -267,10 +267,13 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
protected:
+
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+
struct GlobalPropertyInfo {
GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
: identifier(i)
diff --git a/JavaScriptCore/runtime/JSNotAnObject.h b/JavaScriptCore/runtime/JSNotAnObject.h
index 0d9aca6..a271c4e 100644
--- a/JavaScriptCore/runtime/JSNotAnObject.h
+++ b/JavaScriptCore/runtime/JSNotAnObject.h
@@ -62,10 +62,13 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
private:
+
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+
// JSValue methods
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h
index 6a48081..309488f 100644
--- a/JavaScriptCore/runtime/JSNumberCell.h
+++ b/JavaScriptCore/runtime/JSNumberCell.h
@@ -68,23 +68,15 @@ namespace JSC {
void* operator new(size_t size, ExecState* exec)
{
- #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
- return exec->heap()->inlineAllocateNumber(size);
- #else
return exec->heap()->allocateNumber(size);
- #endif
}
void* operator new(size_t size, JSGlobalData* globalData)
{
- #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
- return globalData->heap.inlineAllocateNumber(size);
- #else
return globalData->heap.allocateNumber(size);
- #endif
}
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion | HasDefaultMark)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, OverridesGetOwnPropertySlot | NeedsThisConversion)); }
private:
JSNumberCell(JSGlobalData* globalData, double value)
diff --git a/JavaScriptCore/runtime/JSONObject.h b/JavaScriptCore/runtime/JSONObject.h
index 65c9803..ec3fa40 100644
--- a/JavaScriptCore/runtime/JSONObject.h
+++ b/JavaScriptCore/runtime/JSONObject.h
@@ -41,11 +41,14 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
static void markStringifiers(MarkStack&, Stringifier*);
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+
private:
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp
index db2a9b2..6932ded 100644
--- a/JavaScriptCore/runtime/JSObject.cpp
+++ b/JavaScriptCore/runtime/JSObject.cpp
@@ -42,6 +42,25 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSObject);
+static inline void getEnumerablePropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames)
+{
+ // Add properties from the static hashtables of properties
+ for (; classInfo; classInfo = classInfo->parentClass) {
+ const HashTable* table = classInfo->propHashTable(exec);
+ if (!table)
+ continue;
+ table->initializeIfNeeded(exec);
+ ASSERT(table->table);
+
+ int hashSizeMask = table->compactSize - 1;
+ const HashEntry* entry = table->table;
+ for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
+ if (entry->key() && !(entry->attributes() & DontEnum))
+ propertyNames.add(entry->key());
+ }
+ }
+}
+
void JSObject::markChildren(MarkStack& markStack)
{
#ifndef NDEBUG
@@ -424,12 +443,29 @@ bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyNa
void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
- m_structure->getEnumerablePropertyNames(exec, propertyNames, this);
+ getOwnPropertyNames(exec, propertyNames);
+
+ if (prototype().isNull())
+ return;
+
+ JSObject* prototype = asObject(this->prototype());
+ while(1) {
+ if (prototype->structure()->typeInfo().overridesGetPropertyNames()) {
+ prototype->getPropertyNames(exec, propertyNames);
+ break;
+ }
+ prototype->getOwnPropertyNames(exec, propertyNames);
+ JSValue nextProto = prototype->prototype();
+ if (nextProto.isNull())
+ break;
+ prototype = asObject(nextProto);
+ }
}
void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
- m_structure->getOwnEnumerablePropertyNames(exec, propertyNames, this);
+ m_structure->getEnumerablePropertyNames(propertyNames);
+ getEnumerablePropertyNames(exec, classInfo(), propertyNames);
}
bool JSObject::toBoolean(ExecState*) const
diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h
index 84b5f4b..5a89c40 100644
--- a/JavaScriptCore/runtime/JSObject.h
+++ b/JavaScriptCore/runtime/JSObject.h
@@ -202,15 +202,17 @@ namespace JSC {
void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
- static const size_t inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
- static const size_t nonInlineBaseStorageCapacity = 16;
+ 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, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
protected:
+ static const unsigned StructureFlags = 0;
+
void addAnonymousSlots(unsigned count);
void putAnonymousValue(unsigned index, JSValue value)
{
@@ -368,7 +370,7 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifie
ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
- if (structure()->typeInfo().hasStandardGetOwnPropertySlot())
+ if (!structure()->typeInfo().overridesGetOwnPropertySlot())
return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
return getOwnPropertySlot(exec, propertyName, slot);
}
@@ -682,7 +684,7 @@ ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack)
{
JSCell::markChildren(markStack);
- m_structure->markAggregate(markStack);
+ markStack.append(prototype());
PropertyStorage storage = propertyStorage();
size_t storageSize = m_structure->propertyStorageSize();
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index e08a3d9..6fd0344 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -29,26 +29,61 @@
#include "config.h"
#include "JSPropertyNameIterator.h"
+#include "JSGlobalObject.h"
+
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
-JSPropertyNameIterator::~JSPropertyNameIterator()
+JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
{
+ ASSERT(!o->structure()->enumerationCache() ||
+ o->structure()->enumerationCache()->cachedStructure() != o->structure() ||
+ o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec));
+
+ PropertyNameArray propertyNames(exec);
+ o->getPropertyNames(exec, propertyNames);
+ size_t numCacheableSlots = 0;
+ if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasAnonymousSlots() &&
+ !o->structure()->isUncacheableDictionary() && !o->structure()->typeInfo().overridesGetPropertyNames())
+ numCacheableSlots = o->structure()->propertyStorageSize();
+
+ JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots);
+
+ if (o->structure()->isDictionary())
+ return jsPropertyNameIterator;
+
+ if (o->structure()->typeInfo().overridesGetPropertyNames())
+ return jsPropertyNameIterator;
+
+ size_t count = normalizePrototypeChain(exec, o);
+ StructureChain* structureChain = o->structure()->prototypeChain(exec);
+ RefPtr<Structure>* structure = structureChain->head();
+ for (size_t i = 0; i < count; ++i) {
+ if (structure[i]->typeInfo().overridesGetPropertyNames())
+ return jsPropertyNameIterator;
+ }
+
+ jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
+ jsPropertyNameIterator->setCachedStructure(o->structure());
+ o->structure()->setEnumerationCache(jsPropertyNameIterator);
+ return jsPropertyNameIterator;
}
-void JSPropertyNameIterator::markChildren(MarkStack& markStack)
+JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
{
- JSCell::markChildren(markStack);
- if (m_object)
- markStack.append(m_object);
+ JSValue& identifier = m_jsStrings[i];
+ if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec))
+ return identifier;
+
+ if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value())))
+ return JSValue();
+ return identifier;
}
-void JSPropertyNameIterator::invalidate()
+void JSPropertyNameIterator::markChildren(MarkStack& markStack)
{
- ASSERT(m_position == m_end);
- m_object = 0;
- m_data.clear();
+ markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h
index d2849a8..529ae8b 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -31,6 +31,7 @@
#include "JSObject.h"
#include "JSString.h"
+#include "Operations.h"
#include "PropertyNameArray.h"
namespace JSC {
@@ -39,73 +40,63 @@ namespace JSC {
class JSObject;
class JSPropertyNameIterator : public JSCell {
+ friend class JIT;
+
public:
- static JSPropertyNameIterator* create(ExecState*, JSValue);
+ static JSPropertyNameIterator* create(ExecState*, JSObject*);
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren));
+ }
- virtual ~JSPropertyNameIterator();
+ virtual bool isPropertyNameIterator() const { return true; }
virtual void markChildren(MarkStack&);
- JSValue next(ExecState*);
- void invalidate();
-
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ bool getOffset(size_t i, int& offset)
{
- return Structure::create(prototype, TypeInfo(CompoundType));
+ if (i >= m_numCacheableSlots)
+ return false;
+ offset = i;
+ return true;
}
+
+ JSValue get(ExecState*, JSObject*, size_t i);
+ size_t size() { return m_jsStringsSize; }
+
+ void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
+ Structure* cachedStructure() { return m_cachedStructure; }
+
+ void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+ StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
+
private:
- JSPropertyNameIterator(ExecState*);
- JSPropertyNameIterator(ExecState*, JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData);
+ JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
- JSObject* m_object;
- RefPtr<PropertyNameArrayData> m_data;
- PropertyNameArrayData::const_iterator m_position;
- PropertyNameArrayData::const_iterator m_end;
+ Structure* m_cachedStructure;
+ RefPtr<StructureChain> m_cachedPrototypeChain;
+ uint32_t m_numCacheableSlots;
+ uint32_t m_jsStringsSize;
+ OwnArrayPtr<JSValue> m_jsStrings;
};
-inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec)
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
: JSCell(exec->globalData().propertyNameIteratorStructure.get())
- , m_object(0)
- , m_position(0)
- , m_end(0)
+ , m_cachedStructure(0)
+ , m_numCacheableSlots(numCacheableSlots)
+ , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
+ , m_jsStrings(new JSValue[m_jsStringsSize])
{
+ PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
+ for (size_t i = 0; i < m_jsStringsSize; ++i)
+ m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring());
}
-inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData)
- : JSCell(exec->globalData().propertyNameIteratorStructure.get())
- , m_object(object)
- , m_data(propertyNameArrayData)
- , m_position(m_data->begin())
- , m_end(m_data->end())
-{
-}
-
-inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v)
+inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache)
{
- if (v.isUndefinedOrNull())
- return new (exec) JSPropertyNameIterator(exec);
-
- JSObject* o = v.toObject(exec);
- PropertyNameArray propertyNames(exec);
- o->getPropertyNames(exec, propertyNames);
- return new (exec) JSPropertyNameIterator(exec, o, propertyNames.releaseData());
-}
-
-inline JSValue JSPropertyNameIterator::next(ExecState* exec)
-{
- if (m_position == m_end)
- return JSValue();
-
- if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec))
- return jsOwnedString(exec, (*m_position++).ustring());
-
- do {
- if (m_object->hasProperty(exec, *m_position))
- return jsOwnedString(exec, (*m_position++).ustring());
- m_position++;
- } while (m_position != m_end);
-
- return JSValue();
+ ASSERT(!isDictionary());
+ m_enumerationCache = enumerationCache;
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.h b/JavaScriptCore/runtime/JSStaticScopeObject.h
index 5eb0e4b..2542878 100644
--- a/JavaScriptCore/runtime/JSStaticScopeObject.h
+++ b/JavaScriptCore/runtime/JSStaticScopeObject.h
@@ -57,7 +57,10 @@ 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, NeedsThisConversion)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); }
+
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
private:
JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp
index 91ddaeb..20ba868 100644
--- a/JavaScriptCore/runtime/JSString.cpp
+++ b/JavaScriptCore/runtime/JSString.cpp
@@ -139,45 +139,4 @@ bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Proper
return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
}
-JSString* jsString(JSGlobalData* globalData, const UString& s)
-{
- int size = s.size();
- if (!size)
- return globalData->smallStrings.emptyString(globalData);
- if (size == 1) {
- UChar c = s.data()[0];
- if (c <= 0xFF)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- }
- return new (globalData) JSString(globalData, s);
-}
-
-JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
-{
- ASSERT(offset <= static_cast<unsigned>(s.size()));
- ASSERT(length <= static_cast<unsigned>(s.size()));
- ASSERT(offset + length <= static_cast<unsigned>(s.size()));
- if (!length)
- return globalData->smallStrings.emptyString(globalData);
- if (length == 1) {
- UChar c = s.data()[offset];
- if (c <= 0xFF)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- }
- return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, length));
-}
-
-JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
-{
- int size = s.size();
- if (!size)
- return globalData->smallStrings.emptyString(globalData);
- if (size == 1) {
- UChar c = s.data()[0];
- if (c <= 0xFF)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- }
- return new (globalData) JSString(globalData, s, JSString::HasOtherOwner);
-}
-
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h
index 1e46551..39dfe75 100644
--- a/JavaScriptCore/runtime/JSString.h
+++ b/JavaScriptCore/runtime/JSString.h
@@ -92,7 +92,7 @@ namespace JSC {
bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
JSString* getIndex(JSGlobalData*, unsigned);
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion | HasDefaultMark)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion)); }
private:
enum VPtrStealingHackType { VPtrStealingHack };
@@ -169,6 +169,47 @@ namespace JSC {
return jsSingleCharacterSubstring(globalData, m_value, i);
}
+ inline JSString* jsString(JSGlobalData* globalData, const UString& s)
+ {
+ int size = s.size();
+ if (!size)
+ return globalData->smallStrings.emptyString(globalData);
+ if (size == 1) {
+ UChar c = s.data()[0];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, s);
+ }
+
+ inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
+ {
+ ASSERT(offset <= static_cast<unsigned>(s.size()));
+ ASSERT(length <= static_cast<unsigned>(s.size()));
+ ASSERT(offset + length <= static_cast<unsigned>(s.size()));
+ if (!length)
+ return globalData->smallStrings.emptyString(globalData);
+ if (length == 1) {
+ UChar c = s.data()[offset];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, length));
+ }
+
+ inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
+ {
+ int size = s.size();
+ if (!size)
+ return globalData->smallStrings.emptyString(globalData);
+ if (size == 1) {
+ UChar c = s.data()[0];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, s, JSString::HasOtherOwner);
+ }
+
inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
diff --git a/JavaScriptCore/runtime/JSTypeInfo.h b/JavaScriptCore/runtime/JSTypeInfo.h
index 279510b..7c89600 100644
--- a/JavaScriptCore/runtime/JSTypeInfo.h
+++ b/JavaScriptCore/runtime/JSTypeInfo.h
@@ -40,9 +40,9 @@ namespace JSC {
static const unsigned OverridesHasInstance = 1 << 2;
static const unsigned ImplementsDefaultHasInstance = 1 << 3;
static const unsigned NeedsThisConversion = 1 << 4;
- static const unsigned HasStandardGetOwnPropertySlot = 1 << 5;
- static const unsigned HasDefaultMark = 1 << 6;
- static const unsigned HasDefaultGetPropertyNames = 1 << 7;
+ static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
+ static const unsigned OverridesMarkChildren = 1 << 6;
+ static const unsigned OverridesGetPropertyNames = 1 << 7;
class TypeInfo {
friend class JIT;
@@ -63,9 +63,9 @@ namespace JSC {
bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; }
bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
bool needsThisConversion() const { return m_flags & NeedsThisConversion; }
- bool hasStandardGetOwnPropertySlot() const { return m_flags & HasStandardGetOwnPropertySlot; }
- bool hasDefaultMark() const { return m_flags & HasDefaultMark; }
- bool hasDefaultGetPropertyNames() const { return m_flags & HasDefaultGetPropertyNames; }
+ bool overridesGetOwnPropertySlot() const { return m_flags & OverridesGetOwnPropertySlot; }
+ bool overridesMarkChildren() const { return m_flags & OverridesMarkChildren; }
+ bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; }
unsigned flags() const { return m_flags; }
private:
diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h
index 3c511d8..1063cdc 100644
--- a/JavaScriptCore/runtime/JSValue.h
+++ b/JavaScriptCore/runtime/JSValue.h
@@ -373,6 +373,14 @@ namespace JSC {
return static_cast<uint32_t>(val);
}
+ // FIXME: We should deprecate this and just use JSValue::asCell() instead.
+ JSCell* asCell(JSValue);
+
+ inline JSCell* asCell(JSValue value)
+ {
+ return value.asCell();
+ }
+
ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
{
if (isInt32())
diff --git a/JavaScriptCore/runtime/JSVariableObject.h b/JavaScriptCore/runtime/JSVariableObject.h
index 66e78c3..d8b1479 100644
--- a/JavaScriptCore/runtime/JSVariableObject.h
+++ b/JavaScriptCore/runtime/JSVariableObject.h
@@ -60,10 +60,11 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
protected:
+ static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags;
// Subclasses of JSVariableObject can subclass this struct to add data
// without increasing their own size (since there's a hard limit on the
// size of a JSCell).
diff --git a/JavaScriptCore/runtime/JSWrapperObject.h b/JavaScriptCore/runtime/JSWrapperObject.h
index 723b75d..191ff3b 100644
--- a/JavaScriptCore/runtime/JSWrapperObject.h
+++ b/JavaScriptCore/runtime/JSWrapperObject.h
@@ -38,7 +38,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames | HasDefaultMark));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
private:
diff --git a/JavaScriptCore/runtime/MarkStack.h b/JavaScriptCore/runtime/MarkStack.h
index ba00057..ea09f54 100644
--- a/JavaScriptCore/runtime/MarkStack.h
+++ b/JavaScriptCore/runtime/MarkStack.h
@@ -47,7 +47,7 @@ namespace JSC {
}
ALWAYS_INLINE void append(JSValue);
- ALWAYS_INLINE void append(JSCell*);
+ void append(JSCell*);
ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues)
{
diff --git a/JavaScriptCore/runtime/MathObject.h b/JavaScriptCore/runtime/MathObject.h
index fee5ec5..7f474b8 100644
--- a/JavaScriptCore/runtime/MathObject.h
+++ b/JavaScriptCore/runtime/MathObject.h
@@ -37,8 +37,11 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
+
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/NumberConstructor.h b/JavaScriptCore/runtime/NumberConstructor.h
index 908c55f..cf19b6f 100644
--- a/JavaScriptCore/runtime/NumberConstructor.h
+++ b/JavaScriptCore/runtime/NumberConstructor.h
@@ -39,11 +39,14 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(proto, TypeInfo(ObjectType, StructureFlags));
}
enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags;
+
private:
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
diff --git a/JavaScriptCore/runtime/NumberObject.h b/JavaScriptCore/runtime/NumberObject.h
index ca3923d..8223a90 100644
--- a/JavaScriptCore/runtime/NumberObject.h
+++ b/JavaScriptCore/runtime/NumberObject.h
@@ -30,17 +30,19 @@ namespace JSC {
explicit NumberObject(NonNullPassRefPtr<Structure>);
static const ClassInfo info;
-#if USE(JSVALUE32)
+
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
+
+ protected:
+#if USE(JSVALUE32)
+ static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags;
#else
- static PassRefPtr<Structure> createStructure(JSValue prototype)
- {
- return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
- }
+ static const unsigned StructureFlags = JSWrapperObject::StructureFlags;
#endif
+
private:
virtual const ClassInfo* classInfo() const { return &info; }
diff --git a/JavaScriptCore/runtime/ObjectConstructor.cpp b/JavaScriptCore/runtime/ObjectConstructor.cpp
index a456423..837d5a6 100644
--- a/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -125,6 +125,7 @@ JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec,
return description;
}
+// FIXME: Use the enumeration cache.
JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
if (!args.at(0).isObject())
diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h
index 5da9e38..1aa68b3 100644
--- a/JavaScriptCore/runtime/Operations.h
+++ b/JavaScriptCore/runtime/Operations.h
@@ -224,15 +224,15 @@ namespace JSC {
return jsAddSlowCase(callFrame, v1, v2);
}
- inline size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue baseValue, const PropertySlot& slot)
+ inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase)
{
- JSCell* cell = asCell(baseValue);
+ JSCell* cell = asCell(base);
size_t count = 0;
- while (slot.slotBase() != cell) {
+ while (slotBase != cell) {
JSValue v = cell->structure()->prototypeForLookup(callFrame);
- // If we didn't find slotBase in baseValue's prototype chain, then baseValue
+ // If we didn't find slotBase in base's prototype chain, then base
// must be a proxy for another object.
if (v.isNull())
@@ -252,6 +252,25 @@ namespace JSC {
return count;
}
+ inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
+ {
+ size_t count = 0;
+ while (1) {
+ JSValue v = base->structure()->prototypeForLookup(callFrame);
+ if (v.isNull())
+ return count;
+
+ base = asCell(v);
+
+ // Since we're accessing a prototype in a loop, it's a good bet that it
+ // should not be treated as a dictionary.
+ if (base->structure()->isDictionary())
+ asObject(base)->setStructure(Structure::fromDictionaryTransition(base->structure()));
+
+ ++count;
+ }
+ }
+
ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
{
ScopeChainIterator iter = scopeChain->begin();
diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp
index 0878e73..c28b6a4 100644
--- a/JavaScriptCore/runtime/PropertyNameArray.cpp
+++ b/JavaScriptCore/runtime/PropertyNameArray.cpp
@@ -21,6 +21,9 @@
#include "config.h"
#include "PropertyNameArray.h"
+#include "Structure.h"
+#include "StructureChain.h"
+
namespace JSC {
static const size_t setThreshold = 20;
@@ -44,7 +47,7 @@ void PropertyNameArray::add(UString::Rep* identifier)
return;
}
- m_data->propertyNameVector().append(Identifier(m_globalData, identifier));
+ addKnownUnique(identifier);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/PropertyNameArray.h b/JavaScriptCore/runtime/PropertyNameArray.h
index afcc83f..3dbcc9d 100644
--- a/JavaScriptCore/runtime/PropertyNameArray.h
+++ b/JavaScriptCore/runtime/PropertyNameArray.h
@@ -23,45 +23,35 @@
#include "CallFrame.h"
#include "Identifier.h"
-#include "Structure.h"
#include <wtf/HashSet.h>
+#include <wtf/OwnArrayPtr.h>
#include <wtf/Vector.h>
namespace JSC {
+
+ class Structure;
+ class StructureChain;
+ // FIXME: Rename to PropertyNameArray.
class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
public:
typedef Vector<Identifier, 20> PropertyNameVector;
- typedef PropertyNameVector::const_iterator const_iterator;
static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); }
- const_iterator begin() const { return m_propertyNameVector.begin(); }
- const_iterator end() const { return m_propertyNameVector.end(); }
-
PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
- void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
- Structure* cachedStructure() const { return m_cachedStructure; }
-
- void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
- StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
-
private:
PropertyNameArrayData()
- : m_cachedStructure(0)
{
}
PropertyNameVector m_propertyNameVector;
- Structure* m_cachedStructure;
- RefPtr<StructureChain> m_cachedPrototypeChain;
};
+ // FIXME: Rename to PropertyNameArrayBuilder.
class PropertyNameArray {
public:
- typedef PropertyNameArrayData::const_iterator const_iterator;
-
PropertyNameArray(JSGlobalData* globalData)
: m_data(PropertyNameArrayData::create())
, m_globalData(globalData)
@@ -82,21 +72,18 @@ namespace JSC {
void add(UString::Rep*);
void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
- size_t size() const { return m_data->propertyNameVector().size(); }
-
Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
- const_iterator begin() const { return m_data->begin(); }
- const_iterator end() const { return m_data->end(); }
-
void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
PropertyNameArrayData* data() { return m_data.get(); }
-
PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
- void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; }
- bool shouldCache() const { return m_shouldCache; }
+ // FIXME: Remove these functions.
+ typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
+ size_t size() const { return m_data->propertyNameVector().size(); }
+ const_iterator begin() const { return m_data->propertyNameVector().begin(); }
+ const_iterator end() const { return m_data->propertyNameVector().end(); }
private:
typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
diff --git a/JavaScriptCore/runtime/Protect.h b/JavaScriptCore/runtime/Protect.h
index 224164d..a0d5443 100644
--- a/JavaScriptCore/runtime/Protect.h
+++ b/JavaScriptCore/runtime/Protect.h
@@ -22,8 +22,8 @@
#ifndef Protect_h
#define Protect_h
-#include "JSCell.h"
#include "Collector.h"
+#include "JSValue.h"
namespace JSC {
diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp
index dbf2d44..c609e08 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -90,28 +90,6 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info,
@end
*/
-struct RegExpConstructorPrivate : FastAllocBase {
- // Global search cache / settings
- RegExpConstructorPrivate()
- : lastNumSubPatterns(0)
- , multiline(false)
- , lastOvectorIndex(0)
- {
- }
-
- const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; }
- Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; }
- Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; }
- void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; }
-
- UString input;
- UString lastInput;
- Vector<int, 32> ovector[2];
- unsigned lastNumSubPatterns : 30;
- bool multiline : 1;
- unsigned lastOvectorIndex : 1;
-};
-
RegExpConstructor::RegExpConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp"))
, d(new RegExpConstructorPrivate)
@@ -123,30 +101,6 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, NonNullPassRefPtr<Structur
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum);
}
-/*
- To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
- expression matching through the performMatch function. We use cached results to calculate,
- e.g., RegExp.lastMatch and RegExp.leftParen.
-*/
-void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
-{
- position = r->match(s, startOffset, &d->tempOvector());
-
- if (ovector)
- *ovector = d->tempOvector().data();
-
- if (position != -1) {
- ASSERT(!d->tempOvector().isEmpty());
-
- length = d->tempOvector()[1] - d->tempOvector()[0];
-
- d->input = s;
- d->lastInput = s;
- d->changeLastOvector();
- d->lastNumSubPatterns = r->numSubpatterns();
- }
-}
-
RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
: JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1)
{
diff --git a/JavaScriptCore/runtime/RegExpConstructor.h b/JavaScriptCore/runtime/RegExpConstructor.h
index f8bccf4..f9ca9cf 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/JavaScriptCore/runtime/RegExpConstructor.h
@@ -22,6 +22,7 @@
#define RegExpConstructor_h
#include "InternalFunction.h"
+#include "RegExp.h"
#include <wtf/OwnPtr.h>
namespace JSC {
@@ -30,13 +31,35 @@ namespace JSC {
class RegExpPrototype;
struct RegExpConstructorPrivate;
+ struct RegExpConstructorPrivate : FastAllocBase {
+ // Global search cache / settings
+ RegExpConstructorPrivate()
+ : lastNumSubPatterns(0)
+ , multiline(false)
+ , lastOvectorIndex(0)
+ {
+ }
+
+ const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; }
+ Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; }
+ Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; }
+ void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; }
+
+ UString input;
+ UString lastInput;
+ Vector<int, 32> ovector[2];
+ unsigned lastNumSubPatterns : 30;
+ bool multiline : 1;
+ unsigned lastOvectorIndex : 1;
+ };
+
class RegExpConstructor : public InternalFunction {
public:
RegExpConstructor(ExecState*, NonNullPassRefPtr<Structure>, RegExpPrototype*);
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
@@ -59,6 +82,9 @@ namespace JSC {
JSValue getLeftContext(ExecState*) const;
JSValue getRightContext(ExecState*) const;
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags;
+
private:
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
@@ -78,6 +104,30 @@ namespace JSC {
return static_cast<RegExpConstructor*>(asObject(value));
}
+ /*
+ To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
+ expression matching through the performMatch function. We use cached results to calculate,
+ e.g., RegExp.lastMatch and RegExp.leftParen.
+ */
+ inline void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
+ {
+ position = r->match(s, startOffset, &d->tempOvector());
+
+ if (ovector)
+ *ovector = d->tempOvector().data();
+
+ if (position != -1) {
+ ASSERT(!d->tempOvector().isEmpty());
+
+ length = d->tempOvector()[1] - d->tempOvector()[0];
+
+ d->input = s;
+ d->lastInput = s;
+ d->changeLastOvector();
+ d->lastNumSubPatterns = r->numSubpatterns();
+ }
+ }
+
} // namespace JSC
#endif // RegExpConstructor_h
diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp
index 877d7b6..679d072 100644
--- a/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/JavaScriptCore/runtime/RegExpObject.cpp
@@ -159,7 +159,7 @@ bool RegExpObject::match(ExecState* exec, const ArgList& args)
}
int position;
- int length;
+ int length = 0;
regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length);
if (position < 0) {
d->lastIndex = 0;
diff --git a/JavaScriptCore/runtime/RegExpObject.h b/JavaScriptCore/runtime/RegExpObject.h
index f5a9340..3117c86 100644
--- a/JavaScriptCore/runtime/RegExpObject.h
+++ b/JavaScriptCore/runtime/RegExpObject.h
@@ -49,9 +49,12 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+
private:
bool match(ExecState*, const ArgList&);
diff --git a/JavaScriptCore/runtime/StringObject.h b/JavaScriptCore/runtime/StringObject.h
index 944f6ba..84e1ad2 100644
--- a/JavaScriptCore/runtime/StringObject.h
+++ b/JavaScriptCore/runtime/StringObject.h
@@ -48,10 +48,11 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
}
protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
StringObject(NonNullPassRefPtr<Structure>, JSString*);
};
diff --git a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
index 0cba83d..69e1939 100644
--- a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
+++ b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
@@ -44,9 +44,11 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined | HasDefaultMark));
+ return Structure::create(proto, TypeInfo(ObjectType, StructureFlags));
}
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags;
+
virtual bool toBoolean(ExecState*) const { return false; }
};
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
index b57732a..a0713b8 100644
--- a/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -25,6 +25,7 @@
#include "CachedCall.h"
#include "Error.h"
#include "Executable.h"
+#include "JSGlobalObjectFunctions.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "ObjectPrototype.h"
@@ -72,6 +73,10 @@ static JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState*, JSObject*, JSVa
static JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*, JSObject*, JSValue, const ArgList&);
+
}
#include "StringPrototype.lut.h"
@@ -117,6 +122,9 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec
fontsize stringProtoFuncFontsize DontEnum|Function 1
anchor stringProtoFuncAnchor DontEnum|Function 1
link stringProtoFuncLink DontEnum|Function 1
+ trim stringProtoFuncTrim DontEnum|Function 0
+ trimLeft stringProtoFuncTrimLeft DontEnum|Function 0
+ trimRight stringProtoFuncTrimRight DontEnum|Function 0
@end
*/
@@ -249,7 +257,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
return jsNull();
while (true) {
int matchIndex;
- int matchLen;
+ int matchLen = 0;
int* ovector;
regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
if (matchIndex < 0)
@@ -290,7 +298,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
} else {
do {
int matchIndex;
- int matchLen;
+ int matchLen = 0;
int* ovector;
regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
if (matchIndex < 0)
@@ -485,7 +493,7 @@ JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue t
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
- int matchLength;
+ int matchLength = 0;
regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
if (!(reg->global())) {
// case without 'g' flag is handled like RegExp.prototype.exec
@@ -535,7 +543,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
- int matchLength;
+ int matchLength = 0;
regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
return jsNumber(exec, pos);
}
@@ -899,4 +907,51 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th
return jsNontrivialString(exec, UString(buffer, bufferSize, false));
}
+enum {
+ TrimLeft = 1,
+ TrimRight = 2
+};
+
+static inline bool isTrimWhitespace(UChar c)
+{
+ return isStrWhiteSpace(c) || c == 0x200b;
+}
+
+static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKind)
+{
+ UString str = thisValue.toThisString(exec);
+ int left = 0;
+ if (trimKind & TrimLeft) {
+ while (left < str.size() && isTrimWhitespace(str[left]))
+ left++;
+ }
+ int right = str.size();
+ if (trimKind & TrimRight) {
+ while (right > left && isTrimWhitespace(str[right - 1]))
+ right--;
+ }
+
+ // Don't gc allocate a new string if we don't have to.
+ if (left == 0 && right == str.size() && thisValue.isString())
+ return thisValue;
+
+ return jsString(exec, str.substr(left, right - left));
+}
+
+JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+{
+ return trimString(exec, thisValue, TrimLeft | TrimRight);
+}
+
+JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+{
+ return trimString(exec, thisValue, TrimLeft);
+}
+
+JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+{
+ return trimString(exec, thisValue, TrimRight);
+}
+
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp
index 7209b5f..65b62f9 100644
--- a/JavaScriptCore/runtime/Structure.cpp
+++ b/JavaScriptCore/runtime/Structure.cpp
@@ -28,9 +28,10 @@
#include "Identifier.h"
#include "JSObject.h"
+#include "JSPropertyNameIterator.h"
+#include "Lookup.h"
#include "PropertyNameArray.h"
#include "StructureChain.h"
-#include "Lookup.h"
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/RefPtr.h>
@@ -159,9 +160,9 @@ Structure::~Structure()
m_previous->table.removeAnonymousSlotTransition(m_anonymousSlotsInPrevious);
}
-
- if (m_cachedPropertyNameArrayData)
- m_cachedPropertyNameArrayData->setCachedStructure(0);
+
+ if (m_enumerationCache)
+ m_enumerationCache->setCachedStructure(0);
if (m_propertyTable) {
unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
@@ -282,59 +283,6 @@ void Structure::materializePropertyMap()
}
}
-void Structure::getOwnEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
-{
- getEnumerableNamesFromPropertyTable(propertyNames);
- getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);
-}
-
-void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
-{
- bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());
-
- if (shouldCache && m_cachedPropertyNameArrayData) {
- if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
- propertyNames.setData(m_cachedPropertyNameArrayData);
- return;
- }
- clearEnumerationCache();
- }
-
- baseObject->getOwnPropertyNames(exec, propertyNames);
-
- if (m_prototype.isObject()) {
- propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
- JSObject* prototype = asObject(m_prototype);
- while(1) {
- if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) {
- prototype->getPropertyNames(exec, propertyNames);
- break;
- }
- prototype->getOwnPropertyNames(exec, propertyNames);
- JSValue nextProto = prototype->prototype();
- if (!nextProto.isObject())
- break;
- prototype = asObject(nextProto);
- }
- }
-
- if (shouldCache) {
- StructureChain* protoChain = prototypeChain(exec);
- m_cachedPropertyNameArrayData = propertyNames.data();
- if (!protoChain->isCacheable())
- return;
- m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain);
- m_cachedPropertyNameArrayData->setCachedStructure(this);
- }
-}
-
-void Structure::clearEnumerationCache()
-{
- if (m_cachedPropertyNameArrayData)
- m_cachedPropertyNameArrayData->setCachedStructure(0);
- m_cachedPropertyNameArrayData.clear();
-}
-
void Structure::growPropertyStorageCapacity()
{
if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
@@ -427,6 +375,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
transition->m_specificValueInPrevious = specificValue;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+ transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
if (structure->m_propertyTable) {
if (structure->m_isPinnedPropertyTable)
@@ -469,6 +418,7 @@ PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure,
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+ transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
// Don't set m_offset, as one can not transition to this.
@@ -485,6 +435,7 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+ transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
// Don't set m_offset, as one can not transition to this.
@@ -516,6 +467,7 @@ PassRefPtr<Structure> Structure::addAnonymousSlotsTransition(Structure* structur
transition->m_specificValueInPrevious = 0;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+ transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
if (structure->m_propertyTable) {
if (structure->m_isPinnedPropertyTable)
@@ -544,6 +496,7 @@ PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
+ transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
// Don't set m_offset, as one can not transition to this.
@@ -562,6 +515,7 @@ PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, Di
transition->m_dictionaryKind = kind;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+ transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
structure->materializePropertyMapIfNecessary();
transition->m_propertyTable = structure->copyPropertyTable();
@@ -598,25 +552,28 @@ PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
+ ASSERT(!m_enumerationCache);
materializePropertyMapIfNecessary();
m_isPinnedPropertyTable = true;
+ if (attributes & DontEnum)
+ m_hasNonEnumerableProperties = true;
+
size_t offset = put(propertyName, attributes, specificValue);
if (propertyStorageSize() > propertyStorageCapacity())
growPropertyStorageCapacity();
- clearEnumerationCache();
return offset;
}
size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
{
ASSERT(isUncacheableDictionary());
+ ASSERT(!m_enumerationCache);
materializePropertyMapIfNecessary();
m_isPinnedPropertyTable = true;
size_t offset = remove(propertyName);
- clearEnumerationCache();
return offset;
}
@@ -1057,7 +1014,7 @@ static int comparePropertyMapEntryIndices(const void* a, const void* b)
return 0;
}
-void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyNames)
+void Structure::getEnumerablePropertyNames(PropertyNameArray& propertyNames)
{
materializePropertyMapIfNecessary();
if (!m_propertyTable)
@@ -1114,25 +1071,6 @@ void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyN
}
}
-void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames)
-{
- // Add properties from the static hashtables of properties
- for (; classInfo; classInfo = classInfo->parentClass) {
- const HashTable* table = classInfo->propHashTable(exec);
- if (!table)
- continue;
- table->initializeIfNeeded(exec);
- ASSERT(table->table);
-
- int hashSizeMask = table->compactSize - 1;
- const HashEntry* entry = table->table;
- for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
- if (entry->key() && !(entry->attributes() & DontEnum))
- propertyNames.add(entry->key());
- }
- }
-}
-
#if DO_PROPERTYMAP_CONSTENCY_CHECK
void Structure::checkConsistency()
diff --git a/JavaScriptCore/runtime/Structure.h b/JavaScriptCore/runtime/Structure.h
index ed9f6e5..f355c53 100644
--- a/JavaScriptCore/runtime/Structure.h
+++ b/JavaScriptCore/runtime/Structure.h
@@ -30,6 +30,8 @@
#include "JSType.h"
#include "JSValue.h"
#include "PropertyMapHashTable.h"
+#include "PropertyNameArray.h"
+#include "Protect.h"
#include "StructureChain.h"
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
@@ -76,8 +78,6 @@ namespace JSC {
~Structure();
- void markAggregate(MarkStack&);
-
// These should be used with caution.
size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t removePropertyWithoutTransition(const Identifier& propertyName);
@@ -95,8 +95,8 @@ namespace JSC {
Structure* previousID() const { return m_previous.get(); }
void growPropertyStorageCapacity();
- size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
- size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
+ unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; }
+ unsigned propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
bool isUsingInlineStorage() const;
size_t get(const Identifier& propertyName);
@@ -116,17 +116,22 @@ namespace JSC {
return hasTransition(propertyName._ustring.rep(), attributes);
}
- void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
- void getOwnEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
-
bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
+ bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
+
+ bool hasAnonymousSlots() const { return m_propertyTable && m_propertyTable->anonymousSlotCount; }
+
bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
JSCell* specificValue() { return m_specificValueInPrevious; }
void despecifyDictionaryFunction(const Identifier& propertyName);
+ void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
+ JSPropertyNameIterator* enumerationCache() { return m_enumerationCache.get(); }
+ void getEnumerablePropertyNames(PropertyNameArray&);
+
private:
Structure(JSValue prototype, const TypeInfo&);
@@ -140,8 +145,6 @@ namespace JSC {
size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t remove(const Identifier& propertyName);
void addAnonymousSlots(unsigned slotCount);
- void getEnumerableNamesFromPropertyTable(PropertyNameArray&);
- void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&);
void expandPropertyMapHashTable();
void rehashPropertyMapHashTable();
@@ -162,8 +165,6 @@ namespace JSC {
materializePropertyMap();
}
- void clearEnumerationCache();
-
signed char transitionCount() const
{
// Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
@@ -189,16 +190,17 @@ namespace JSC {
StructureTransitionTable table;
- RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
+ ProtectedPtr<JSPropertyNameIterator> m_enumerationCache;
PropertyMapHashTable* m_propertyTable;
- size_t m_propertyStorageCapacity;
+ uint32_t m_propertyStorageCapacity;
signed char m_offset;
unsigned m_dictionaryKind : 2;
bool m_isPinnedPropertyTable : 1;
bool m_hasGetterSetterProperties : 1;
+ bool m_hasNonEnumerableProperties : 1;
#if COMPILER(WINSCW)
// Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared
// bitfield, when used as argument in make_pair() function calls in structure.ccp.
diff --git a/JavaScriptCore/runtime/StructureChain.cpp b/JavaScriptCore/runtime/StructureChain.cpp
index 6e8a0ee..085876c 100644
--- a/JavaScriptCore/runtime/StructureChain.cpp
+++ b/JavaScriptCore/runtime/StructureChain.cpp
@@ -46,18 +46,4 @@ StructureChain::StructureChain(Structure* head)
m_vector[i] = 0;
}
-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())
- return false;
- }
- return true;
-}
-
} // namespace JSC
diff --git a/JavaScriptCore/runtime/StructureChain.h b/JavaScriptCore/runtime/StructureChain.h
index c48749d..816b66d 100644
--- a/JavaScriptCore/runtime/StructureChain.h
+++ b/JavaScriptCore/runtime/StructureChain.h
@@ -36,10 +36,11 @@ namespace JSC {
class Structure;
class StructureChain : public RefCounted<StructureChain> {
+ friend class JIT;
+
public:
static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
RefPtr<Structure>* head() { return m_vector.get(); }
- bool isCacheable() const;
private:
StructureChain(Structure* head);