summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/DateConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/MathObject.cpp3
-rw-r--r--JavaScriptCore/runtime/PropertyMapHashTable.h1
-rw-r--r--JavaScriptCore/runtime/Structure.cpp56
-rw-r--r--JavaScriptCore/runtime/Structure.h27
5 files changed, 49 insertions, 40 deletions
diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp
index 2e476b3..e9a5c29 100644
--- a/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/JavaScriptCore/runtime/DateConstructor.cpp
@@ -177,7 +177,7 @@ static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const
t.minute = args.at(4).toInt32(exec);
t.second = args.at(5).toInt32(exec);
double ms = (n >= 7) ? args.at(6).toNumber(exec) : 0;
- return jsNumber(exec, gregorianDateTimeToMS(exec, t, ms, true));
+ return jsNumber(exec, timeClip(gregorianDateTimeToMS(exec, t, ms, true)));
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp
index 98ff3ba..8f22fba 100644
--- a/JavaScriptCore/runtime/MathObject.cpp
+++ b/JavaScriptCore/runtime/MathObject.cpp
@@ -218,7 +218,8 @@ JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, co
double arg = args.at(0).toNumber(exec);
if (signbit(arg) && arg >= -0.5)
return jsNumber(exec, -0.0);
- return jsNumber(exec, floor(arg + 0.5));
+ double integer = ceil(arg);
+ return jsNumber(exec, integer - (integer - arg > 0.5));
}
JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
diff --git a/JavaScriptCore/runtime/PropertyMapHashTable.h b/JavaScriptCore/runtime/PropertyMapHashTable.h
index 5b63f79..44dc2b8 100644
--- a/JavaScriptCore/runtime/PropertyMapHashTable.h
+++ b/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -61,7 +61,6 @@ namespace JSC {
unsigned size;
unsigned keyCount;
unsigned deletedSentinelCount;
- unsigned anonymousSlotCount;
unsigned lastIndexUsed;
Vector<unsigned>* deletedOffsets;
unsigned entryIndices[1];
diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp
index 77330aa..546e2bf 100644
--- a/JavaScriptCore/runtime/Structure.cpp
+++ b/JavaScriptCore/runtime/Structure.cpp
@@ -123,7 +123,7 @@ void Structure::dumpStatistics()
#endif
}
-Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
+Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
: m_typeInfo(typeInfo)
, m_prototype(prototype)
, m_specificValueInPrevious(0)
@@ -135,6 +135,7 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
, m_hasGetterSetterProperties(false)
, m_attributesInPrevious(0)
, m_specificFunctionThrashCount(0)
+ , m_anonymousSlotCount(anonymousSlotCount)
{
ASSERT(m_prototype);
ASSERT(m_prototype.isObject() || m_prototype.isNull());
@@ -275,7 +276,7 @@ void Structure::materializePropertyMap()
for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
structure = structures[i];
structure->m_nameInPrevious->ref();
- PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
+ PropertyMapEntry entry(structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
insertIntoPropertyMapHashTable(entry);
}
}
@@ -341,7 +342,9 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
ASSERT(existingTransition->m_offset != noOffset);
- offset = existingTransition->m_offset;
+ offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount;
+ ASSERT(offset >= structure->m_anonymousSlotCount);
+ ASSERT(structure->m_anonymousSlotCount == existingTransition->m_anonymousSlotCount);
return existingTransition;
}
@@ -361,12 +364,14 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
ASSERT(structure != transition);
offset = transition->put(propertyName, attributes, specificValue);
+ ASSERT(offset >= structure->m_anonymousSlotCount);
+ ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
transition->growPropertyStorageCapacity();
return transition.release();
}
- RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+ RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
transition->m_previous = structure;
@@ -393,11 +398,13 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
}
offset = transition->put(propertyName, attributes, specificValue);
+ ASSERT(offset >= structure->m_anonymousSlotCount);
+ ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
transition->growPropertyStorageCapacity();
- transition->m_offset = offset;
-
+ transition->m_offset = offset - structure->m_anonymousSlotCount;
+ ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
return transition.release();
}
@@ -409,13 +416,15 @@ PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure,
RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
offset = transition->remove(propertyName);
+ ASSERT(offset >= structure->m_anonymousSlotCount);
+ ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
return transition.release();
}
PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
{
- RefPtr<Structure> transition = create(prototype, structure->typeInfo());
+ RefPtr<Structure> transition = create(prototype, structure->typeInfo(), structure->anonymousSlotCount());
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
@@ -427,14 +436,15 @@ PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure,
structure->materializePropertyMapIfNecessary();
transition->m_propertyTable = structure->copyPropertyTable();
transition->m_isPinnedPropertyTable = true;
-
+
+ ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
return transition.release();
}
PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
{
ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount);
- RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
+ RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
@@ -453,13 +463,14 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur
bool removed = transition->despecifyFunction(replaceFunction);
ASSERT_UNUSED(removed, removed);
}
-
+
+ ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
return transition.release();
}
PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
{
- RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
+ RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
@@ -470,7 +481,8 @@ PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
structure->materializePropertyMapIfNecessary();
transition->m_propertyTable = structure->copyPropertyTable();
transition->m_isPinnedPropertyTable = true;
-
+
+ ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
return transition.release();
}
@@ -478,7 +490,7 @@ PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, Di
{
ASSERT(!structure->isUncacheableDictionary());
- RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+ RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
transition->m_dictionaryKind = kind;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
@@ -489,6 +501,7 @@ PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, Di
transition->m_propertyTable = structure->copyPropertyTable();
transition->m_isPinnedPropertyTable = true;
+ ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
return transition.release();
}
@@ -522,7 +535,7 @@ PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object)
// in the order that they are expected to be in, but we need to
// reorder the storage, so we have to copy the current values out
Vector<JSValue> values(propertyCount);
- unsigned anonymousSlotCount = m_propertyTable->anonymousSlotCount;
+ unsigned anonymousSlotCount = m_anonymousSlotCount;
for (unsigned i = 0; i < propertyCount; i++) {
PropertyMapEntry* entry = sortedPropertyEntries[i];
values[i] = object->getDirectOffset(entry->offset);
@@ -557,6 +570,7 @@ size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, u
m_isPinnedPropertyTable = true;
size_t offset = put(propertyName, attributes, specificValue);
+ ASSERT(offset >= m_anonymousSlotCount);
if (propertyStorageSize() > propertyStorageCapacity())
growPropertyStorageCapacity();
return offset;
@@ -571,6 +585,7 @@ size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName
m_isPinnedPropertyTable = true;
size_t offset = remove(propertyName);
+ ASSERT(offset >= m_anonymousSlotCount);
return offset;
}
@@ -627,7 +642,6 @@ PropertyMapHashTable* Structure::copyPropertyTable()
if (m_propertyTable->deletedOffsets)
newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets);
- newTable->anonymousSlotCount = m_propertyTable->anonymousSlotCount;
return newTable;
}
@@ -650,6 +664,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp
if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
+ ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
return m_propertyTable->entries()[entryIndex - 1].offset;
}
@@ -673,6 +688,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp
if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
+ ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
return m_propertyTable->entries()[entryIndex - 1].offset;
}
}
@@ -821,9 +837,10 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
newOffset = m_propertyTable->deletedOffsets->last();
m_propertyTable->deletedOffsets->removeLast();
} else
- newOffset = m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount;
+ newOffset = m_propertyTable->keyCount + m_anonymousSlotCount;
m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
-
+
+ ASSERT(newOffset >= m_anonymousSlotCount);
++m_propertyTable->keyCount;
if ((m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount) * 2 >= m_propertyTable->size)
@@ -887,6 +904,7 @@ size_t Structure::remove(const Identifier& propertyName)
m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = deletedSentinelIndex;
size_t offset = m_propertyTable->entries()[entryIndex - 1].offset;
+ ASSERT(offset >= m_anonymousSlotCount);
key->deref();
m_propertyTable->entries()[entryIndex - 1].key = 0;
@@ -912,7 +930,7 @@ size_t Structure::remove(const Identifier& propertyName)
void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
{
ASSERT(m_propertyTable);
-
+ ASSERT(entry.offset >= m_anonymousSlotCount);
unsigned i = entry.key->existingHash();
unsigned k = 0;
@@ -991,7 +1009,6 @@ void Structure::rehashPropertyMapHashTable(unsigned newTableSize)
m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
m_propertyTable->size = newTableSize;
m_propertyTable->sizeMask = newTableSize - 1;
- m_propertyTable->anonymousSlotCount = oldTable->anonymousSlotCount;
unsigned lastIndexUsed = 0;
unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
@@ -1121,6 +1138,7 @@ void Structure::checkConsistency()
for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) {
ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum));
UString::Rep* rep = m_propertyTable->entries()[c].key;
+ ASSERT(m_propertyTable->entries()[c].offset >= m_anonymousSlotCount);
if (!rep)
continue;
++nonEmptyEntryCount;
diff --git a/JavaScriptCore/runtime/Structure.h b/JavaScriptCore/runtime/Structure.h
index f73f9b8..1353a5a 100644
--- a/JavaScriptCore/runtime/Structure.h
+++ b/JavaScriptCore/runtime/Structure.h
@@ -62,15 +62,7 @@ namespace JSC {
friend class StructureTransitionTable;
static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
{
- Structure* structure = (new Structure(prototype, typeInfo));
- if (anonymousSlotCount) {
- structure->materializePropertyMap();
- structure->m_isPinnedPropertyTable = true;
- structure->m_propertyTable->anonymousSlotCount = anonymousSlotCount;
- // Currently we don't allow more anonymous slots than fit in the inline capacity
- ASSERT(structure->propertyStorageSize() <= structure->propertyStorageCapacity());
- }
- return adoptRef(structure);
+ return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount));
}
static void startIgnoringLeaks();
@@ -109,7 +101,7 @@ namespace JSC {
void growPropertyStorageCapacity();
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; }
+ unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1); }
bool isUsingInlineStorage() const;
size_t get(const Identifier& propertyName);
@@ -134,8 +126,8 @@ namespace JSC {
bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
- bool hasAnonymousSlots() const { return m_propertyTable && m_propertyTable->anonymousSlotCount; }
- unsigned anonymousSlotCount() const { return m_propertyTable ? m_propertyTable->anonymousSlotCount : 0; }
+ bool hasAnonymousSlots() const { return !!m_anonymousSlotCount; }
+ unsigned anonymousSlotCount() const { return m_anonymousSlotCount; }
bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
@@ -147,12 +139,8 @@ namespace JSC {
void getPropertyNames(PropertyNameArray&, EnumerationMode mode);
private:
- static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo)
- {
- return adoptRef(new Structure(prototype, typeInfo));
- }
- Structure(JSValue prototype, const TypeInfo&);
+ Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount);
typedef enum {
NoneDictionaryKind = 0,
@@ -216,6 +204,8 @@ namespace JSC {
PropertyMapHashTable* m_propertyTable;
uint32_t m_propertyStorageCapacity;
+
+ // m_offset does not account for anonymous slots
signed char m_offset;
unsigned m_dictionaryKind : 2;
@@ -231,7 +221,8 @@ namespace JSC {
unsigned m_attributesInPrevious : 7;
#endif
unsigned m_specificFunctionThrashCount : 2;
- // 10 free bits
+ unsigned m_anonymousSlotCount : 5;
+ // 5 free bits
};
inline size_t Structure::get(const Identifier& propertyName)