Commit 570483e7 authored by ggaren@apple.com's avatar ggaren@apple.com

Removed the concept of a "fast access cutoff" in arrays, because it

punished some patterns of array access too much, and made things too
complex for inlining in some cases.
        
Patch by Geoffrey Garen <ggaren@apple.com> on 2009-10-02
Reviewed by Sam Weinig.

1.3% speedup on SunSpider.

* jit/JITOpcodes.cpp:
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
* jit/JITStubs.cpp:
* jit/JITStubs.h:
(JSC::): Check m_vectorLength instead of m_fastAccessCutoff when
getting / putting from / to an array. Inline putting past the end of
the array.

* runtime/JSArray.cpp:
(JSC::JSArray::JSArray):
(JSC::JSArray::getOwnPropertySlot):
(JSC::JSArray::getOwnPropertyDescriptor):
(JSC::JSArray::put):
(JSC::JSArray::putSlowCase):
(JSC::JSArray::deleteProperty):
(JSC::JSArray::getOwnPropertyNames):
(JSC::JSArray::increaseVectorLength):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::sort):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToRegisters):
(JSC::JSArray::compactForSorting):
(JSC::JSArray::checkConsistency):
* runtime/JSArray.h:
(JSC::JSArray::canGetIndex):
(JSC::JSArray::canSetIndex):
(JSC::JSArray::setIndex):
(JSC::JSArray::markChildrenDirect): Removed m_fastAccessCutoff, and
replaced with checks for JSValue() to detect reads and writes from / to
uninitialized parts of the array.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49065 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9ed9884e
2009-10-02 Geoffrey Garen <ggaren@apple.com>
Reviewed by Sam Weinig.
Removed the concept of a "fast access cutoff" in arrays, because it
punished some patterns of array access too much, and made things too
complex for inlining in some cases.
1.3% speedup on SunSpider.
* jit/JITOpcodes.cpp:
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
* jit/JITStubs.cpp:
* jit/JITStubs.h:
(JSC::): Check m_vectorLength instead of m_fastAccessCutoff when
getting / putting from / to an array. Inline putting past the end of
the array.
* runtime/JSArray.cpp:
(JSC::JSArray::JSArray):
(JSC::JSArray::getOwnPropertySlot):
(JSC::JSArray::getOwnPropertyDescriptor):
(JSC::JSArray::put):
(JSC::JSArray::putSlowCase):
(JSC::JSArray::deleteProperty):
(JSC::JSArray::getOwnPropertyNames):
(JSC::JSArray::increaseVectorLength):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::sort):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToRegisters):
(JSC::JSArray::compactForSorting):
(JSC::JSArray::checkConsistency):
* runtime/JSArray.h:
(JSC::JSArray::canGetIndex):
(JSC::JSArray::canSetIndex):
(JSC::JSArray::setIndex):
(JSC::JSArray::markChildrenDirect): Removed m_fastAccessCutoff, and
replaced with checks for JSValue() to detect reads and writes from / to
uninitialized parts of the array.
2009-10-02 Jonni Rainisto <jonni.rainisto@nokia.com>
Reviewed by Darin Adler.
......
......@@ -2691,32 +2691,20 @@ void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowC
void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
// The slow void JIT::emitSlow_that handles accesses to arrays (below) may jump back up to here.
Label beginGetByValSlow(this);
unsigned dst = currentInstruction[1].u.operand;
unsigned base = currentInstruction[2].u.operand;
unsigned property = currentInstruction[3].u.operand;
Jump notImm = getSlowCase(iter);
linkSlowCase(iter);
linkSlowCase(iter);
emitFastArithIntToImmNoCheck(regT1, regT1);
linkSlowCase(iter); // property int32 check
linkSlowCaseIfNotJSCell(iter, base); // base cell check
linkSlowCase(iter); // base array check
linkSlowCase(iter); // vector length check
linkSlowCase(iter); // empty value
notImm.link(this);
JITStubCall stubCall(this, cti_op_get_by_val);
stubCall.addArgument(regT0);
stubCall.addArgument(regT1);
stubCall.call(currentInstruction[1].u.operand);
emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
// This is slow void JIT::emitSlow_that handles accesses to arrays above the fast cut-off.
// First, check if this is an access to the vector
linkSlowCase(iter);
branch32(AboveOrEqual, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength)), beginGetByValSlow);
// okay, missed the fast region, but it is still in the vector. Get the value.
loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT2);
// Check whether the value loaded is zero; if so we need to return undefined.
branchTestPtr(Zero, regT2, beginGetByValSlow);
move(regT2, regT0);
emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
stubCall.addArgument(base, regT2);
stubCall.addArgument(property, regT2);
stubCall.call(dst);
}
void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
......@@ -2773,30 +2761,20 @@ void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<Slo
void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
// Normal slow cases - either is not an immediate imm, or is an array.
Jump notImm = getSlowCase(iter);
linkSlowCase(iter);
linkSlowCase(iter);
emitFastArithIntToImmNoCheck(regT1, regT1);
unsigned base = currentInstruction[1].u.operand;
unsigned property = currentInstruction[2].u.operand;
unsigned value = currentInstruction[3].u.operand;
notImm.link(this); {
JITStubCall stubCall(this, cti_op_put_by_val);
stubCall.addArgument(regT0);
stubCall.addArgument(regT1);
stubCall.addArgument(currentInstruction[3].u.operand, regT2);
stubCall.call();
emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_put_by_val));
}
linkSlowCase(iter); // property int32 check
linkSlowCaseIfNotJSCell(iter, base); // base cell check
linkSlowCase(iter); // base not array check
linkSlowCase(iter); // in vector check
// slow cases for immediate int accesses to arrays
linkSlowCase(iter);
linkSlowCase(iter); {
JITStubCall stubCall(this, cti_op_put_by_val_array);
stubCall.addArgument(regT0);
stubCall.addArgument(regT1);
stubCall.addArgument(currentInstruction[3].u.operand, regT2);
stubCall.call();
}
JITStubCall stubPutByValCall(this, cti_op_put_by_val);
stubPutByValCall.addArgument(regT0);
stubPutByValCall.addArgument(property, regT2);
stubPutByValCall.addArgument(value, regT2);
stubPutByValCall.call();
}
void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
......
This diff is collapsed.
......@@ -1942,28 +1942,6 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val)
CHECK_FOR_EXCEPTION_AT_END();
}
DEFINE_STUB_FUNCTION(void, op_put_by_val_array)
{
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
JSValue baseValue = stackFrame.args[0].jsValue();
int i = stackFrame.args[1].int32();
JSValue value = stackFrame.args[2].jsValue();
ASSERT(isJSArray(stackFrame.globalData, baseValue));
if (LIKELY(i >= 0))
asArray(baseValue)->JSArray::put(callFrame, i, value);
else {
Identifier property(callFrame, UString::from(i));
PutPropertySlot slot;
baseValue.put(callFrame, property, value, slot);
}
CHECK_FOR_EXCEPTION_AT_END();
}
DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
{
STUB_INIT_STACK_FRAME(stackFrame);
......
......@@ -345,7 +345,6 @@ extern "C" {
void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_val_array(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION);
......
This diff is collapsed.
......@@ -29,7 +29,6 @@ namespace JSC {
struct ArrayStorage {
unsigned m_length;
unsigned m_vectorLength;
unsigned m_numValuesInVector;
SparseArrayValueMap* m_sparseValueMap;
void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
......@@ -63,18 +62,24 @@ namespace JSC {
void push(ExecState*, JSValue);
JSValue pop();
bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; }
bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
JSValue getIndex(unsigned i)
{
ASSERT(canGetIndex(i));
return m_storage->m_vector[i];
}
bool canSetIndex(unsigned i) { return i < m_fastAccessCutoff; }
JSValue setIndex(unsigned i, JSValue v)
bool canSetIndex(unsigned i) { return i < m_vectorLength; }
void setIndex(unsigned i, JSValue v)
{
ASSERT(canSetIndex(i));
return m_storage->m_vector[i] = v;
JSValue& x = m_storage->m_vector[i];
if (!x) {
++m_storage->m_numValuesInVector;
if (i >= m_storage->m_length)
m_storage->m_length = i + 1;
}
x = v;
}
void fillArgList(ExecState*, MarkedArgumentBuffer&);
......@@ -110,7 +115,7 @@ namespace JSC {
enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
unsigned m_fastAccessCutoff;
unsigned m_vectorLength;
ArrayStorage* m_storage;
};
......@@ -139,7 +144,7 @@ namespace JSC {
ArrayStorage* storage = m_storage;
unsigned usedVectorLength = std::min(storage->m_length, storage->m_vectorLength);
unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
......
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