Commit 3fbbc4f8 authored by fpizlo@apple.com's avatar fpizlo@apple.com

JSArray::putDirectIndex should by default behave like JSObject::putDirect

https://bugs.webkit.org/show_bug.cgi?id=95630

Reviewed by Gavin Barraclough.

Source/JavaScriptCore: 

* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* jsc.cpp:
(GlobalObject::finishCreation):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSArray.cpp:
(JSC::SparseArrayValueMap::putDirect):
(JSC::JSArray::defineOwnNumericProperty):
(JSC::JSArray::putDirectIndexBeyondVectorLength):
* runtime/JSArray.h:
(SparseArrayValueMap):
(JSArray):
(JSC::JSArray::putDirectIndex):
* runtime/JSONObject.cpp:
(JSC::Walker::walk):
* runtime/RegExpMatchesArray.cpp:
(JSC::RegExpMatchesArray::reifyAllProperties):
(JSC::RegExpMatchesArray::reifyMatchProperty):
* runtime/StringPrototype.cpp:
(JSC::splitStringByOneCharacterImpl):
(JSC::stringProtoFuncSplit):

Source/WebCore: 

No new tests because no change in behavior.

* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneDeserializer::putProperty):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@127349 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a62184de
2012-08-31 Filip Pizlo <fpizlo@apple.com>
JSArray::putDirectIndex should by default behave like JSObject::putDirect
https://bugs.webkit.org/show_bug.cgi?id=95630
Reviewed by Gavin Barraclough.
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* jsc.cpp:
(GlobalObject::finishCreation):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSArray.cpp:
(JSC::SparseArrayValueMap::putDirect):
(JSC::JSArray::defineOwnNumericProperty):
(JSC::JSArray::putDirectIndexBeyondVectorLength):
* runtime/JSArray.h:
(SparseArrayValueMap):
(JSArray):
(JSC::JSArray::putDirectIndex):
* runtime/JSONObject.cpp:
(JSC::Walker::walk):
* runtime/RegExpMatchesArray.cpp:
(JSC::RegExpMatchesArray::reifyAllProperties):
(JSC::RegExpMatchesArray::reifyMatchProperty):
* runtime/StringPrototype.cpp:
(JSC::splitStringByOneCharacterImpl):
(JSC::stringProtoFuncSplit):
2012-08-31 Geoffrey Garen <ggaren@apple.com>
Rolled back in a piece of <http://trac.webkit.org/changeset/127293>.
......
......@@ -3701,7 +3701,7 @@ skip_id_custom_self:
JSValue arrayValue = callFrame->r(base).jsValue();
ASSERT(isJSArray(arrayValue));
asArray(arrayValue)->putDirectIndex(callFrame, property, callFrame->r(value).jsValue(), false);
asArray(arrayValue)->putDirectIndex(callFrame, property, callFrame->r(value).jsValue());
vPC += OPCODE_LENGTH(op_put_by_index);
NEXT_INSTRUCTION();
......
......@@ -3291,7 +3291,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_index)
JSValue arrayValue = stackFrame.args[0].jsValue();
ASSERT(isJSArray(arrayValue));
asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue(), false);
asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue());
}
DEFINE_STUB_FUNCTION(void*, op_switch_imm)
......
......@@ -224,7 +224,7 @@ protected:
JSArray* array = constructEmptyArray(globalExec());
for (size_t i = 0; i < arguments.size(); ++i)
array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]), false);
array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
putDirect(globalData, Identifier(globalExec(), "arguments"), array);
}
......
......@@ -1104,7 +1104,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
LLINT_BEGIN();
JSValue arrayValue = LLINT_OP_C(1).jsValue();
ASSERT(isJSArray(arrayValue));
asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue(), false);
asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
LLINT_END();
}
......
......@@ -244,7 +244,7 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i
call(exec, setter, callType, callData, array, args);
}
inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow)
inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSArray* array, unsigned i, JSValue value, PutDirectIndexMode mode)
{
AddResult result = add(array, i);
SparseArrayEntry& entry = result.iterator->second;
......@@ -252,9 +252,9 @@ inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSArray* array, unsi
// To save a separate find & add, we first always add to the sparse map.
// In the uncommon case that this is a new property, and the array is not
// extensible, this is not the right thing to have done - so remove again.
if (result.isNewEntry && !array->isExtensible()) {
if (mode != PutDirectIndexLikePutDirect && result.isNewEntry && !array->isExtensible()) {
remove(result.iterator);
return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible.");
return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible.");
}
entry.attributes = 0;
......@@ -414,7 +414,7 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property
// state (i.e. defineOwnProperty could be used to set a value without needing to entering 'SparseMode').
if (!descriptor.attributes()) {
ASSERT(!descriptor.isAccessorDescriptor());
return putDirectIndex(exec, index, descriptor.value(), throwException);
return putDirectIndex(exec, index, descriptor.value(), throwException ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
}
enterDictionaryMode(exec->globalData());
......@@ -844,7 +844,7 @@ void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue
valueSlot.set(globalData, this, value);
}
bool JSArray::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
bool JSArray::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, PutDirectIndexMode mode)
{
JSGlobalData& globalData = exec->globalData();
......@@ -875,17 +875,19 @@ bool JSArray::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSVa
// We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
allocateSparseMap(exec->globalData());
map = m_sparseValueMap;
return map->putDirect(exec, this, i, value, shouldThrow);
return map->putDirect(exec, this, i, value, mode);
}
// Update m_length if necessary.
unsigned length = storage->m_length;
if (i >= length) {
// Prohibit growing the array if length is not writable.
if (map->lengthIsReadOnly())
return reject(exec, shouldThrow, StrictModeReadonlyPropertyWriteError);
if (!isExtensible())
return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible.");
if (mode != PutDirectIndexLikePutDirect) {
if (map->lengthIsReadOnly())
return reject(exec, mode == PutDirectIndexShouldThrow, StrictModeReadonlyPropertyWriteError);
if (!isExtensible())
return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible.");
}
length = i + 1;
storage->m_length = length;
}
......@@ -894,7 +896,7 @@ bool JSArray::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSVa
// We will continue to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length))
return map->putDirect(exec, this, i, value, shouldThrow);
return map->putDirect(exec, this, i, value, mode);
// Reread m_storage afterincreaseVectorLength, update m_numValuesInVector.
storage = m_storage;
......
......@@ -30,6 +30,8 @@ namespace JSC {
class JSArray;
class LLIntOffsetsExtractor;
enum PutDirectIndexMode { PutDirectIndexLikePutDirect, PutDirectIndexShouldNotThrow, PutDirectIndexShouldThrow };
struct SparseArrayEntry : public WriteBarrier<Unknown> {
typedef WriteBarrier<Unknown> Base;
......@@ -87,7 +89,7 @@ namespace JSC {
// These methods may mutate the contents of the map
void put(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow);
bool putDirect(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow);
bool putDirect(ExecState*, JSArray*, unsigned, JSValue, PutDirectIndexMode);
AddResult add(JSArray*, unsigned);
iterator find(unsigned i) { return m_map.find(i); }
// This should ASSERT the remove is valid (check the result of the find).
......@@ -173,14 +175,15 @@ namespace JSC {
// This is similar to the JSObject::putDirect* methods:
// - the prototype chain is not consulted
// - accessors are not called.
// - it will ignore extensibility and read-only properties if PutDirectIndexLikePutDirect is passed as the mode (the default).
// This method creates a property with attributes writable, enumerable and configurable all set to true.
bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow = true)
bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, PutDirectIndexMode mode = PutDirectIndexLikePutDirect)
{
if (canSetIndex(propertyName)) {
setIndex(exec->globalData(), propertyName, value);
return true;
}
return putDirectIndexBeyondVectorLength(exec, propertyName, value, shouldThrow);
return putDirectIndexBeyondVectorLength(exec, propertyName, value, mode);
}
static JS_EXPORTDATA const ClassInfo s_info;
......@@ -302,7 +305,7 @@ namespace JSC {
void deallocateSparseMap();
void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, PutDirectIndexMode);
unsigned getNewVectorLength(unsigned desiredLength);
bool increaseVectorLength(JSGlobalData&, unsigned newLength);
......
......@@ -707,7 +707,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
if (filteredValue.isUndefined())
array->methodTable()->deletePropertyByIndex(array, m_exec, indexStack.last());
else
array->putDirectIndex(m_exec, indexStack.last(), filteredValue, false);
array->putDirectIndex(m_exec, indexStack.last(), filteredValue);
if (m_exec->hadException())
return jsNull();
indexStack.last()++;
......
......@@ -66,9 +66,9 @@ void RegExpMatchesArray::reifyAllProperties(ExecState* exec)
for (unsigned i = 1; i <= numSubpatterns; ++i) {
int start = subpatternResults[2 * i];
if (start >= 0)
putDirectIndex(exec, i, jsSubstring(exec, m_input.get(), start, subpatternResults[2 * i + 1] - start), false);
putDirectIndex(exec, i, jsSubstring(exec, m_input.get(), start, subpatternResults[2 * i + 1] - start));
else
putDirectIndex(exec, i, jsUndefined(), false);
putDirectIndex(exec, i, jsUndefined());
}
}
......@@ -83,7 +83,7 @@ void RegExpMatchesArray::reifyMatchProperty(ExecState* exec)
{
ASSERT(m_state == ReifiedNone);
ASSERT(m_result);
putDirectIndex(exec, 0, jsSubstring(exec, m_input.get(), m_result.start, m_result.end - m_result.start), false);
putDirectIndex(exec, 0, jsSubstring(exec, m_input.get(), m_result.start, m_result.end - m_result.start));
m_state = ReifiedMatch;
}
......
......@@ -939,7 +939,7 @@ static ALWAYS_INLINE bool splitStringByOneCharacterImpl(ExecState* exec, JSArray
// through q (exclusive).
// 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
// Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position));
// 3. Increment lengthA by 1.
// 4. If lengthA == lim, return A.
if (++resultLength == limitLength)
......@@ -993,7 +993,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
if (separatorValue.isUndefined()) {
// a. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input));
// b. Return A.
return JSValue::encode(result);
}
......@@ -1006,7 +1006,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
// d. Return A.
if (!reg->match(*globalData, input, 0))
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input));
return JSValue::encode(result);
}
......@@ -1037,7 +1037,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// through q (exclusive).
// 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
// Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position));
// 3. Increment lengthA by 1.
// 4. If lengthA == lim, return A.
if (++resultLength == limit)
......@@ -1056,7 +1056,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// ToString(lengthA), Property Descriptor {[[Value]]: cap[i], [[Writable]]:
// true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
int sub = ovector[i * 2];
result->putDirectIndex(exec, resultLength, sub < 0 ? jsUndefined() : jsSubstring(exec, input, sub, ovector[i * 2 + 1] - sub), false);
result->putDirectIndex(exec, resultLength, sub < 0 ? jsUndefined() : jsSubstring(exec, input, sub, ovector[i * 2 + 1] - sub));
// c Increment lengthA by 1.
// d If lengthA == lim, return A.
if (++resultLength == limit)
......@@ -1075,7 +1075,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
if (separatorValue.isUndefined()) {
// a. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input));
// b. Return A.
return JSValue::encode(result);
}
......@@ -1088,7 +1088,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
// d. Return A.
if (!separator.isEmpty())
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input));
return JSValue::encode(result);
}
......@@ -1099,7 +1099,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
ASSERT(limit);
do {
result->putDirectIndex(exec, position, jsSingleCharacterSubstring(exec, input, position), false);
result->putDirectIndex(exec, position, jsSingleCharacterSubstring(exec, input, position));
} while (++position < limit);
return JSValue::encode(result);
......@@ -1139,7 +1139,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// through q (exclusive).
// 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
// Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position));
// 3. Increment lengthA by 1.
// 4. If lengthA == lim, return A.
if (++resultLength == limit)
......@@ -1156,7 +1156,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// through s (exclusive).
// 15. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), Property Descriptor
// {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
result->putDirectIndex(exec, resultLength++, jsSubstring(exec, input, position, input.length() - position), false);
result->putDirectIndex(exec, resultLength++, jsSubstring(exec, input, position, input.length() - position));
// 16. Return A.
return JSValue::encode(result);
......
2012-08-31 Filip Pizlo <fpizlo@apple.com>
JSArray::putDirectIndex should by default behave like JSObject::putDirect
https://bugs.webkit.org/show_bug.cgi?id=95630
Reviewed by Gavin Barraclough.
No new tests because no change in behavior.
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneDeserializer::putProperty):
2012-08-31 Nate Chapin <japhet@chromium.org>
fast/loader/document-destruction-within-unload.html causes assertion failures on mac and qt.
......@@ -1315,7 +1315,7 @@ private:
void putProperty(JSArray* array, unsigned index, JSValue value)
{
array->putDirectIndex(m_exec, index, value, false);
array->putDirectIndex(m_exec, index, value);
}
void putProperty(JSObject* object, const Identifier& property, JSValue value)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment