X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/a253471d7f8e4d91bf6ebabab00155c3b387d3d0..93a3786624b2768d89bfa27e46598dc64e2fb70a:/bytecode/ArrayProfile.cpp?ds=sidebyside diff --git a/bytecode/ArrayProfile.cpp b/bytecode/ArrayProfile.cpp new file mode 100644 index 0000000..ae3c8f9 --- /dev/null +++ b/bytecode/ArrayProfile.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2012 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. + */ + +#include "config.h" +#include "ArrayProfile.h" + +#include "CodeBlock.h" +#include +#include + +namespace JSC { + +void dumpArrayModes(PrintStream& out, ArrayModes arrayModes) +{ + if (!arrayModes) { + out.print("0:"); + return; + } + + if (arrayModes == ALL_ARRAY_MODES) { + out.print("TOP"); + return; + } + + out.print(arrayModes, ":"); + + if (arrayModes & asArrayModes(NonArray)) + out.print("NonArray"); + if (arrayModes & asArrayModes(NonArrayWithInt32)) + out.print("NonArrayWithInt32"); + if (arrayModes & asArrayModes(NonArrayWithDouble)) + out.print("NonArrayWithDouble"); + if (arrayModes & asArrayModes(NonArrayWithContiguous)) + out.print("NonArrayWithContiguous"); + if (arrayModes & asArrayModes(NonArrayWithArrayStorage)) + out.print("NonArrayWithArrayStorage"); + if (arrayModes & asArrayModes(NonArrayWithSlowPutArrayStorage)) + out.print("NonArrayWithSlowPutArrayStorage"); + if (arrayModes & asArrayModes(ArrayClass)) + out.print("ArrayClass"); + if (arrayModes & asArrayModes(ArrayWithUndecided)) + out.print("ArrayWithUndecided"); + if (arrayModes & asArrayModes(ArrayWithInt32)) + out.print("ArrayWithInt32"); + if (arrayModes & asArrayModes(ArrayWithDouble)) + out.print("ArrayWithDouble"); + if (arrayModes & asArrayModes(ArrayWithContiguous)) + out.print("ArrayWithContiguous"); + if (arrayModes & asArrayModes(ArrayWithArrayStorage)) + out.print("ArrayWithArrayStorage"); + if (arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage)) + out.print("ArrayWithSlowPutArrayStorage"); +} + +ArrayModes ArrayProfile::updatedObservedArrayModes() const +{ + if (m_lastSeenStructure) + return m_observedArrayModes | arrayModeFromStructure(m_lastSeenStructure); + return m_observedArrayModes; +} + +void ArrayProfile::computeUpdatedPrediction(CodeBlock* codeBlock, OperationInProgress operation) +{ + const bool verbose = false; + + if (m_lastSeenStructure) { + m_observedArrayModes |= arrayModeFromStructure(m_lastSeenStructure); + m_mayInterceptIndexedAccesses |= + m_lastSeenStructure->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero(); + if (!codeBlock->globalObject()->isOriginalArrayStructure(m_lastSeenStructure)) + m_usesOriginalArrayStructures = false; + if (!structureIsPolymorphic()) { + if (!m_expectedStructure) + m_expectedStructure = m_lastSeenStructure; + else if (m_expectedStructure != m_lastSeenStructure) { + if (verbose) + dataLog(*codeBlock, " bc#", m_bytecodeOffset, ": making structure polymorphic because ", RawPointer(m_expectedStructure), " (", m_expectedStructure->classInfo()->className, ") != ", RawPointer(m_lastSeenStructure), " (", m_lastSeenStructure->classInfo()->className, ")\n"); + m_expectedStructure = polymorphicStructure(); + } + } + m_lastSeenStructure = 0; + } + + if (hasTwoOrMoreBitsSet(m_observedArrayModes)) { + if (verbose) + dataLog(*codeBlock, " bc#", m_bytecodeOffset, ": making structure polymorphic because two or more bits are set in m_observedArrayModes\n"); + m_expectedStructure = polymorphicStructure(); + } + + if (operation == Collection + && expectedStructure() + && !Heap::isMarked(m_expectedStructure)) { + if (verbose) + dataLog(*codeBlock, " bc#", m_bytecodeOffset, ": making structure during GC\n"); + m_expectedStructure = polymorphicStructure(); + } +} + +CString ArrayProfile::briefDescription(CodeBlock* codeBlock) +{ + computeUpdatedPrediction(codeBlock); + + StringPrintStream out; + + bool hasPrinted = false; + + if (m_observedArrayModes) { + if (hasPrinted) + out.print(", "); + out.print(ArrayModesDump(m_observedArrayModes)); + hasPrinted = true; + } + + if (structureIsPolymorphic()) { + if (hasPrinted) + out.print(", "); + out.print("struct = TOP"); + hasPrinted = true; + } else if (m_expectedStructure) { + if (hasPrinted) + out.print(", "); + out.print("struct = ", RawPointer(m_expectedStructure)); + hasPrinted = true; + } + + if (m_mayStoreToHole) { + if (hasPrinted) + out.print(", "); + out.print("Hole"); + hasPrinted = true; + } + + if (m_outOfBounds) { + if (hasPrinted) + out.print(", "); + out.print("OutOfBounds"); + hasPrinted = true; + } + + if (m_mayInterceptIndexedAccesses) { + if (hasPrinted) + out.print(", "); + out.print("Intercept"); + hasPrinted = true; + } + + if (m_usesOriginalArrayStructures) { + if (hasPrinted) + out.print(", "); + out.print("Original"); + hasPrinted = true; + } + + UNUSED_PARAM(hasPrinted); + + return out.toCString(); +} + +} // namespace JSC +