Commit 8b3568f8 authored by Alberto Garcia's avatar Alberto Garcia
Browse files

New upstream version 2.22.3

parent 0bacd9c1
......@@ -14,7 +14,7 @@
<div class="titlepage">
<div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">JavaScriptCore GLib Reference Manual</p></th></tr></table></div>
<div><p class="releaseinfo">for JavaScriptCore 2.22.2</p></div>
<div><p class="releaseinfo">for JavaScriptCore 2.22.3</p></div>
</div>
<hr>
</div>
......
......@@ -175,7 +175,7 @@ have included when compiling your code.</p>
<hr>
<div class="refsect2">
<a name="JSC-MICRO-VERSION:CAPS"></a><h3>JSC_MICRO_VERSION</h3>
<pre class="programlisting">#define JSC_MICRO_VERSION (2)
<pre class="programlisting">#define JSC_MICRO_VERSION (3)
</pre>
</div>
</div>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -14,7 +14,7 @@
<div class="titlepage">
<div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">WebKit2GTK+ Reference Manual</p></th></tr></table></div>
<div><p class="releaseinfo">for WebKit2GTK+ 2.22.2</p></div>
<div><p class="releaseinfo">for WebKit2GTK+ 2.22.3</p></div>
</div>
<hr>
</div>
......
......@@ -213,7 +213,7 @@ against at application run time.</p>
<hr>
<div class="refsect2">
<a name="WEBKIT-MICRO-VERSION:CAPS"></a><h3>WEBKIT_MICRO_VERSION</h3>
<pre class="programlisting">#define WEBKIT_MICRO_VERSION (2)
<pre class="programlisting">#define WEBKIT_MICRO_VERSION (3)
</pre>
<p>Like <a class="link" href="webkit2gtk-4.0-WebKitVersion.html#webkit-get-micro-version" title="webkit_get_micro_version ()"><code class="function">webkit_get_micro_version()</code></a>, but from the headers used at
application compile time, rather than from the library linked
......
......@@ -14,7 +14,7 @@
<div class="titlepage">
<div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">WebKitDOMGTK+ Reference Manual</p></th></tr></table></div>
<div><p class="releaseinfo">for WebKitDOMGTK+ 2.22.2</p></div>
<div><p class="releaseinfo">for WebKitDOMGTK+ 2.22.3</p></div>
</div>
<hr>
</div>
......
=================
WebKitGTK+ 2.22.3
=================
What's new in WebKitGTK+ 2.22.3?
- Many improvements and fixes for video playback with media source
extensions (MSE), which improve the user experience across the board,
and in particular for playback of WebM videos.
- Fix a memory leak during media playback when using playbin3.
- Fix portions of Web views not being rendered after resizing.
- Fix Resource Timing reporting for <iframe> elements.
- Fix the build with the remote Web Inspector disabled.
- Fix the build on ARMv7 with NEON extensions.
- Fix several crashes and rendering issues.
=================
WebKitGTK+ 2.22.2
=================
......
......@@ -36,6 +36,7 @@
#include "BuiltinNames.h"
#include "BytecodeGeneratorification.h"
#include "BytecodeLivenessAnalysis.h"
#include "BytecodeUseDef.h"
#include "CatchScope.h"
#include "DefinePropertyAttributes.h"
#include "Interpreter.h"
......@@ -2912,9 +2913,10 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R
unsigned instIndex = instructions().size();
if (context.type() == ForInContext::IndexedForInContextType) {
static_cast<IndexedForInContext&>(context).addGetInst(instIndex, property->index());
property = static_cast<IndexedForInContext&>(context).index();
if (context.isIndexedForInContext()) {
auto& indexedContext = context.asIndexedForInContext();
indexedContext.addGetInst(instIndex, property->index());
property = indexedContext.index();
break;
}
......@@ -4624,16 +4626,16 @@ void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, Registe
{
if (!localRegister)
return;
m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister)));
unsigned bodyBytecodeStartOffset = instructions().size();
m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister, bodyBytecodeStartOffset)));
}
void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
{
if (!localRegister)
return;
ASSERT(m_forInContextStack.last()->type() == ForInContext::IndexedForInContextType);
static_cast<IndexedForInContext&>(m_forInContextStack.last().get()).finalize(*this);
unsigned bodyBytecodeEndOffset = instructions().size();
m_forInContextStack.last()->asIndexedForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
m_forInContextStack.removeLast();
}
......@@ -4736,38 +4738,19 @@ void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, Regis
{
if (!localRegister)
return;
m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister)));
unsigned bodyBytecodeStartOffset = instructions().size();
m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister, bodyBytecodeStartOffset)));
}
void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
{
if (!localRegister)
return;
ASSERT(m_forInContextStack.last()->type() == ForInContext::StructureForInContextType);
static_cast<StructureForInContext&>(m_forInContextStack.last().get()).finalize(*this);
unsigned bodyBytecodeEndOffset = instructions().size();
m_forInContextStack.last()->asStructureForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
m_forInContextStack.removeLast();
}
void BytecodeGenerator::invalidateForInContextForLocal(RegisterID* localRegister)
{
// Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
// either of the following conditions is true:
//
// (1) The loop iteration variable is re-assigned within the body of the loop.
// (2) The loop iteration variable is captured in the lexical scope of the function.
//
// These two situations occur sufficiently rarely that it's okay to use this style of
// "analysis" to make iteration faster. If we didn't want to do this, we would either have
// to perform some flow-sensitive analysis to see if/when the loop iteration variable was
// reassigned, or we'd have to resort to runtime checks to see if the variable had been
// reassigned from its original value.
for (size_t i = m_forInContextStack.size(); i--; ) {
ForInContext& context = m_forInContextStack[i].get();
if (context.local() == localRegister)
context.invalidate();
}
}
RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip)
{
RefPtr<RegisterID> restArrayLength = newTemporary();
......@@ -5193,8 +5176,37 @@ void BytecodeGenerator::emitJumpIf(OpcodeID compareOpcode, RegisterID* completio
emitJumpIfTrue(equivalenceResult, jumpTarget);
}
void StructureForInContext::finalize(BytecodeGenerator& generator)
void ForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
{
// Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
// either of the following conditions is true:
//
// (1) The loop iteration variable is re-assigned within the body of the loop.
// (2) The loop iteration variable is captured in the lexical scope of the function.
//
// These two situations occur sufficiently rarely that it's okay to use this style of
// "analysis" to make iteration faster. If we didn't want to do this, we would either have
// to perform some flow-sensitive analysis to see if/when the loop iteration variable was
// reassigned, or we'd have to resort to runtime checks to see if the variable had been
// reassigned from its original value.
for (unsigned offset = bodyBytecodeStartOffset(); isValid() && offset < bodyBytecodeEndOffset;) {
UnlinkedInstruction* instruction = &generator.instructions()[offset];
OpcodeID opcodeID = instruction->u.opcode;
unsigned opcodeLength = opcodeLengths[opcodeID];
ASSERT(opcodeID != op_enter);
computeDefsForBytecodeOffset(codeBlock, opcodeID, instruction, [&] (UnlinkedCodeBlock*, UnlinkedInstruction*, OpcodeID, int operand) {
if (local()->index() == operand)
invalidate();
});
offset += opcodeLength;
}
}
void StructureForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
{
Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
if (isValid())
return;
......@@ -5222,8 +5234,9 @@ void StructureForInContext::finalize(BytecodeGenerator& generator)
}
}
void IndexedForInContext::finalize(BytecodeGenerator& generator)
void IndexedForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
{
Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
if (isValid())
return;
......
......@@ -56,6 +56,8 @@ namespace JSC {
class JSImmutableButterfly;
class Identifier;
class IndexedForInContext;
class StructureForInContext;
enum ExpectedFunction {
NoExpectedFunction,
......@@ -193,36 +195,60 @@ namespace JSC {
bool isValid() const { return m_isValid; }
void invalidate() { m_isValid = false; }
enum ForInContextType {
StructureForInContextType,
IndexedForInContextType
enum class Type : uint8_t {
IndexedForIn,
StructureForIn
};
virtual ForInContextType type() const = 0;
Type type() const { return m_type; }
bool isIndexedForInContext() const { return m_type == Type::IndexedForIn; }
bool isStructureForInContext() const { return m_type == Type::StructureForIn; }
IndexedForInContext& asIndexedForInContext()
{
ASSERT(isIndexedForInContext());
return *reinterpret_cast<IndexedForInContext*>(this);
}
StructureForInContext& asStructureForInContext()
{
ASSERT(isStructureForInContext());
return *reinterpret_cast<StructureForInContext*>(this);
}
RegisterID* local() const { return m_localRegister.get(); }
protected:
ForInContext(RegisterID* localRegister, Type type, unsigned bodyBytecodeStartOffset)
: m_localRegister(localRegister)
, m_type(type)
, m_bodyBytecodeStartOffset(bodyBytecodeStartOffset)
{ }
unsigned bodyBytecodeStartOffset() const { return m_bodyBytecodeStartOffset; }
void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset);
private:
RefPtr<RegisterID> m_localRegister;
bool m_isValid;
bool m_isValid { true };
Type m_type;
unsigned m_bodyBytecodeStartOffset;
};
class StructureForInContext : public ForInContext {
using Base = ForInContext;
public:
using GetInst = std::tuple<unsigned, int, UnlinkedValueProfile>;
StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
: ForInContext(localRegister)
StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister, unsigned bodyBytecodeStartOffset)
: ForInContext(localRegister, Type::StructureForIn, bodyBytecodeStartOffset)
, m_indexRegister(indexRegister)
, m_propertyRegister(propertyRegister)
, m_enumeratorRegister(enumeratorRegister)
{
}
ForInContextType type() const override
{
return StructureForInContextType;
}
RegisterID* index() const { return m_indexRegister.get(); }
RegisterID* property() const { return m_propertyRegister.get(); }
RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
......@@ -232,7 +258,7 @@ namespace JSC {
m_getInsts.append(GetInst { instIndex, propertyRegIndex, valueProfile });
}
void finalize(BytecodeGenerator&);
void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset);
private:
RefPtr<RegisterID> m_indexRegister;
......@@ -242,21 +268,17 @@ namespace JSC {
};
class IndexedForInContext : public ForInContext {
using Base = ForInContext;
public:
IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
: ForInContext(localRegister)
IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister, unsigned bodyBytecodeStartOffset)
: ForInContext(localRegister, Type::IndexedForIn, bodyBytecodeStartOffset)
, m_indexRegister(indexRegister)
{
}
ForInContextType type() const override
{
return IndexedForInContextType;
}
RegisterID* index() const { return m_indexRegister.get(); }
void finalize(BytecodeGenerator&);
void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset);
void addGetInst(unsigned instIndex, int propertyIndex) { m_getInsts.append({ instIndex, propertyIndex }); }
private:
......@@ -932,7 +954,6 @@ namespace JSC {
void popIndexedForInScope(RegisterID* local);
void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
void popStructureForInScope(RegisterID* local);
void invalidateForInContextForLocal(RegisterID* local);
LabelScope* breakTarget(const Identifier&);
LabelScope* continueTarget(const Identifier&);
......
......@@ -1556,7 +1556,6 @@ RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* d
generator.emitReadOnlyExceptionIfNeeded(var);
localReg = generator.move(generator.tempDestination(dst), local);
}
generator.invalidateForInContextForLocal(local);
RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
return oldValue.get();
......@@ -1769,7 +1768,6 @@ RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* ds
generator.emitReadOnlyExceptionIfNeeded(var);
localReg = generator.move(generator.tempDestination(dst), localReg.get());
} else if (generator.vm()->typeProfiler()) {
generator.invalidateForInContextForLocal(local);
RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
generator.move(tempDst.get(), localReg.get());
emitIncOrDec(generator, tempDst.get(), m_operator);
......@@ -1777,7 +1775,6 @@ RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* ds
generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
return generator.move(dst, tempDst.get());
}
generator.invalidateForInContextForLocal(local);
emitIncOrDec(generator, localReg.get(), m_operator);
return generator.move(dst, localReg.get());
}
......@@ -2441,13 +2438,11 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
generator.move(result.get(), local);
emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
generator.move(local, result.get());
generator.invalidateForInContextForLocal(local);
generator.emitProfileType(local, divotStart(), divotEnd());
return generator.move(dst, result.get());
}
RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
generator.invalidateForInContextForLocal(local);
generator.emitProfileType(result, divotStart(), divotEnd());
return generator.move(dst, result);
}
......@@ -2505,12 +2500,10 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
generator.emitNode(tempDst.get(), m_right);
generator.move(local, tempDst.get());
generator.emitProfileType(local, var, divotStart(), divotEnd());
generator.invalidateForInContextForLocal(local);
result = generator.move(dst, tempDst.get());
} else {
RegisterID* right = generator.emitNode(local, m_right);
generator.emitProfileType(right, var, divotStart(), divotEnd());
generator.invalidateForInContextForLocal(local);
result = generator.move(dst, right);
}
......@@ -2752,7 +2745,6 @@ RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, Regis
Variable var = generator.variable(m_ident);
if (RegisterID* local = var.local()) {
generator.emitLoad(local, jsUndefined());
generator.invalidateForInContextForLocal(local);
generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
} else {
RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
......@@ -2966,7 +2958,6 @@ void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propert
if (var.isReadOnly())
generator.emitReadOnlyExceptionIfNeeded(var);
generator.move(local, propertyName);
generator.invalidateForInContextForLocal(local);
} else {
if (generator.isStrictMode())
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
......@@ -3034,7 +3025,6 @@ void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propert
return;
}
generator.move(var.local(), propertyName);
generator.invalidateForInContextForLocal(var.local());
generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
return;
}
......@@ -3225,7 +3215,6 @@ void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
if (var.isReadOnly())
generator.emitReadOnlyExceptionIfNeeded(var);
generator.move(local, value);
generator.invalidateForInContextForLocal(local);
} else {
if (generator.isStrictMode())
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
......@@ -4399,7 +4388,6 @@ void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) con
return;
}
generator.move(local, value);
generator.invalidateForInContextForLocal(local);
generator.emitProfileType(local, var, divotStart(), divotEnd());
if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
generator.liftTDZCheckIfPossible(var);
......@@ -4448,7 +4436,6 @@ void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID*
if (isReadOnly)
generator.emitReadOnlyExceptionIfNeeded(var);
else {
generator.invalidateForInContextForLocal(local);
generator.move(local, value);
generator.emitProfileType(local, divotStart(), divotEnd());
}
......
......@@ -60,7 +60,7 @@ void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobber
m_arrayModes = ALL_ARRAY_MODES;
m_structure.clobber();
} else
m_arrayModes = asArrayModes(structure->indexingType());
m_arrayModes = asArrayModes(structure->indexingMode());
} else {
m_structure.makeTop();
m_arrayModes = ALL_ARRAY_MODES;
......@@ -87,7 +87,7 @@ void AbstractValue::set(Graph& graph, RegisteredStructure structure)
RELEASE_ASSERT(structure);
m_structure = structure;
m_arrayModes = asArrayModes(structure->indexingType());
m_arrayModes = asArrayModes(structure->indexingMode());
m_type = speculationFromStructure(structure.get());
m_value = JSValue();
......@@ -228,7 +228,7 @@ bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
FrozenValue* frozenValue = graph.freeze(value);
if (frozenValue->pointsToHeap()) {
m_structure = graph.registerStructure(frozenValue->structure());
m_arrayModes = asArrayModes(frozenValue->structure()->indexingType());
m_arrayModes = asArrayModes(frozenValue->structure()->indexingMode());
} else {
m_structure.clear();
m_arrayModes = 0;
......@@ -240,7 +240,7 @@ bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
mergeSpeculation(m_type, speculationFromValue(value));
if (!!value && value.isCell()) {
RegisteredStructure structure = graph.registerStructure(value.asCell()->structure(graph.m_vm));
mergeArrayModes(m_arrayModes, asArrayModes(structure->indexingType()));
mergeArrayModes(m_arrayModes, asArrayModes(structure->indexingMode()));
m_structure.merge(RegisteredStructureSet(structure));
}
if (m_value != value)
......
......@@ -397,7 +397,7 @@ struct AbstractValue {
ASSERT(m_type & SpecCell);
Structure* structure = value.asCell()->structure();
return m_structure.contains(structure)
&& (m_arrayModes & asArrayModes(structure->indexingType()));
&& (m_arrayModes & asArrayModes(structure->indexingMode()));
}
return true;
......
......@@ -248,7 +248,6 @@ bool doesGC(Graph& graph, Node* node)
case GetSetter:
case GetByVal:
case GetByValWithThis:
case GetIndexedPropertyStorage:
case GetArrayLength:
case GetVectorLength:
case ArrayPush:
......@@ -375,6 +374,11 @@ bool doesGC(Graph& graph, Node* node)
case MapSet:
return true;
case GetIndexedPropertyStorage:
if (node->arrayMode().type() == Array::String)
return true;
return false;
case MapHash:
switch (node->child1().useKind()) {
case BooleanUse:
......
......@@ -499,7 +499,7 @@ void OSRExit::executeOSRExit(Context& context)
ASSERT(exit.m_kind == BadCache || exit.m_kind == BadIndexingType);
Structure* structure = profiledValue.asCell()->structure(vm);
arrayProfile->observeStructure(structure);
arrayProfile->observeArrayMode(asArrayModes(structure->indexingType()));
arrayProfile->observeArrayMode(asArrayModes(structure->indexingMode()));
}
if (extraInitializationLevel <= ExtraInitializationLevel::ArrayProfileUpdate)
break;
......
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
* Copyright (C) 2017-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -79,7 +79,7 @@ ArrayModes RegisteredStructureSet::arrayModesFromStructures() const
ArrayModes result = 0;
forEach(
[&] (RegisteredStructure structure) {
mergeArrayModes(result, asArrayModes(structure->indexingType()));
mergeArrayModes(result, asArrayModes(structure->indexingMode()));
});
return result;
}
......
......@@ -12113,7 +12113,7 @@ void SpeculativeJIT::compileNewArrayBuffer(Node* node)
flushRegisters();
GPRFlushedCallResult result(this);
callOperation(operationNewArrayBuffer, result.gpr(), m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())), TrustedImmPtr(node->cellOperand()));
callOperation(operationNewArrayBuffer, result.gpr(), structure, TrustedImmPtr(node->cellOperand()));
m_jit.exceptionCheck();
cellResult(result.gpr(), node);
......
......@@ -801,6 +801,7 @@ SLOW_PATH_DECL(slow_path_has_generic_property)
JSObject* base = OP(2).jsValue().toObject(exec);
CHECK_EXCEPTION();
JSValue property = OP(3).jsValue();
ASSERT(property.isString());
JSString* string = asString(property);
auto propertyName = string->toIdentifier(exec);
CHECK_EXCEPTION();
......@@ -812,6 +813,7 @@ SLOW_PATH_DECL(slow_path_get_direct_pname)
BEGIN();
JSValue baseValue = OP_C(2).jsValue();
JSValue property = OP(3).jsValue();
ASSERT(property.isString());
JSString* string = asString(property);
auto propertyName = string->toIdentifier(exec);
CHECK_EXCEPTION();
......
......@@ -811,7 +811,7 @@ bool JSArray::shiftCountWithArrayStorage(VM& vm, unsigned startIndex, unsigned c
// If the array contains holes or is otherwise in an abnormal state,
// use the generic algorithm in ArrayPrototype.
if ((storage->hasHoles() && this->structure(vm)->holesMustForwardToPrototype(vm, this))
if (storage->hasHoles()
|| hasSparseMap()
|| shouldUseSlowPut(indexingType())) {
return false;
......@@ -852,22 +852,9 @@ bool JSArray::shiftCountWithArrayStorage(VM& vm, unsigned startIndex, unsigned c
// after the shift region, so we move the elements before to the right.
if (numElementsBeforeShiftRegion) {
RELEASE_ASSERT(count + startIndex <= vectorLength);
if (storage->hasHoles()) {
for (unsigned i = startIndex; i-- > 0;) {
unsigned destinationIndex = count + i;
JSValue source = storage->m_vector[i].get();
JSValue dest = storage->m_vector[destinationIndex].get();
// Any time we overwrite a hole we know we overcounted the number of values we removed
// when we subtracted count from m_numValuesInVector above.
if (!dest && destinationIndex >= firstIndexAfterShiftRegion)
storage->m_numValuesInVector++;
storage->m_vector[count + i].setWithoutWriteBarrier(source);
}
} else {
memmove(storage->m_vector + count,
storage->m_vector,
sizeof(JSValue) * startIndex);
}
memmove(storage->m_vector + count,
storage->m_vector,
sizeof(JSValue) * startIndex);
}
// Adjust the Butterfly and the index bias. We only need to do this here because we're changing
// the start of the Butterfly, which needs to point at the first indexed property in the used
......@@ -883,22 +870,10 @@ bool JSArray::shiftCountWithArrayStorage(VM& vm, unsigned startIndex, unsigned c
} else {
// The number of elements before the shift region is greater than or equal to the number