1/*
2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "ArrayProfile.h"
28
29#include "CodeBlock.h"
30#include "JSCInlines.h"
31#include <wtf/CommaPrinter.h>
32#include <wtf/StringExtras.h>
33#include <wtf/StringPrintStream.h>
34
35namespace JSC {
36
37void dumpArrayModes(PrintStream& out, ArrayModes arrayModes)
38{
39    if (!arrayModes) {
40        out.print("<empty>");
41        return;
42    }
43
44    if (arrayModes == ALL_ARRAY_MODES) {
45        out.print("TOP");
46        return;
47    }
48
49    CommaPrinter comma("|");
50    if (arrayModes & asArrayModes(NonArray))
51        out.print(comma, "NonArray");
52    if (arrayModes & asArrayModes(NonArrayWithInt32))
53        out.print(comma, "NonArrayWithInt32");
54    if (arrayModes & asArrayModes(NonArrayWithDouble))
55        out.print(comma, "NonArrayWithDouble");
56    if (arrayModes & asArrayModes(NonArrayWithContiguous))
57        out.print(comma, "NonArrayWithContiguous");
58    if (arrayModes & asArrayModes(NonArrayWithArrayStorage))
59        out.print(comma, "NonArrayWithArrayStorage");
60    if (arrayModes & asArrayModes(NonArrayWithSlowPutArrayStorage))
61        out.print(comma, "NonArrayWithSlowPutArrayStorage");
62    if (arrayModes & asArrayModes(ArrayClass))
63        out.print(comma, "ArrayClass");
64    if (arrayModes & asArrayModes(ArrayWithUndecided))
65        out.print(comma, "ArrayWithUndecided");
66    if (arrayModes & asArrayModes(ArrayWithInt32))
67        out.print(comma, "ArrayWithInt32");
68    if (arrayModes & asArrayModes(ArrayWithDouble))
69        out.print(comma, "ArrayWithDouble");
70    if (arrayModes & asArrayModes(ArrayWithContiguous))
71        out.print(comma, "ArrayWithContiguous");
72    if (arrayModes & asArrayModes(ArrayWithArrayStorage))
73        out.print(comma, "ArrayWithArrayStorage");
74    if (arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage))
75        out.print(comma, "ArrayWithSlowPutArrayStorage");
76}
77
78void ArrayProfile::computeUpdatedPrediction(const ConcurrentJITLocker&, CodeBlock* codeBlock)
79{
80    if (!m_lastSeenStructureID)
81        return;
82
83    Structure* lastSeenStructure = codeBlock->heap()->structureIDTable().get(m_lastSeenStructureID);
84    m_observedArrayModes |= arrayModeFromStructure(lastSeenStructure);
85
86    if (!m_didPerformFirstRunPruning
87        && hasTwoOrMoreBitsSet(m_observedArrayModes)) {
88        m_observedArrayModes = arrayModeFromStructure(lastSeenStructure);
89        m_didPerformFirstRunPruning = true;
90    }
91
92    m_mayInterceptIndexedAccesses |=
93        lastSeenStructure->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero();
94    JSGlobalObject* globalObject = codeBlock->globalObject();
95    if (!globalObject->isOriginalArrayStructure(lastSeenStructure)
96        && !globalObject->isOriginalTypedArrayStructure(lastSeenStructure))
97        m_usesOriginalArrayStructures = false;
98    m_lastSeenStructureID = 0;
99}
100
101CString ArrayProfile::briefDescription(const ConcurrentJITLocker& locker, CodeBlock* codeBlock)
102{
103    computeUpdatedPrediction(locker, codeBlock);
104    return briefDescriptionWithoutUpdating(locker);
105}
106
107CString ArrayProfile::briefDescriptionWithoutUpdating(const ConcurrentJITLocker&)
108{
109    StringPrintStream out;
110
111    bool hasPrinted = false;
112
113    if (m_observedArrayModes) {
114        if (hasPrinted)
115            out.print(", ");
116        out.print(ArrayModesDump(m_observedArrayModes));
117        hasPrinted = true;
118    }
119
120    if (m_mayStoreToHole) {
121        if (hasPrinted)
122            out.print(", ");
123        out.print("Hole");
124        hasPrinted = true;
125    }
126
127    if (m_outOfBounds) {
128        if (hasPrinted)
129            out.print(", ");
130        out.print("OutOfBounds");
131        hasPrinted = true;
132    }
133
134    if (m_mayInterceptIndexedAccesses) {
135        if (hasPrinted)
136            out.print(", ");
137        out.print("Intercept");
138        hasPrinted = true;
139    }
140
141    if (m_usesOriginalArrayStructures) {
142        if (hasPrinted)
143            out.print(", ");
144        out.print("Original");
145        hasPrinted = true;
146    }
147
148    UNUSED_PARAM(hasPrinted);
149
150    return out.toCString();
151}
152
153} // namespace JSC
154
155