1/*
2 * Copyright (C) 2016 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 "ArithProfile.h"
28
29#include "CCallHelpers.h"
30#include "JSCInlines.h"
31
32namespace JSC {
33
34#if ENABLE(JIT)
35void ArithProfile::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode)
36{
37 if (!shouldEmitSetDouble() && !shouldEmitSetNonNumeric() && !shouldEmitSetBigInt())
38 return;
39
40 CCallHelpers::JumpList done;
41 CCallHelpers::JumpList nonNumeric;
42
43 done.append(jit.branchIfInt32(regs, mode));
44 CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode);
45 emitSetDouble(jit);
46 done.append(jit.jump());
47
48 notDouble.link(&jit);
49
50 nonNumeric.append(jit.branchIfNotCell(regs, mode));
51 nonNumeric.append(jit.branchIfNotBigInt(regs.payloadGPR()));
52 emitSetBigInt(jit);
53 done.append(jit.jump());
54
55 nonNumeric.link(&jit);
56 emitSetNonNumeric(jit);
57
58 done.link(&jit);
59}
60
61bool ArithProfile::shouldEmitSetDouble() const
62{
63 uint32_t mask = ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble;
64 return (m_bits & mask) != mask;
65}
66
67void ArithProfile::emitSetDouble(CCallHelpers& jit) const
68{
69 if (shouldEmitSetDouble())
70 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfBits()));
71}
72
73bool ArithProfile::shouldEmitSetNonNumeric() const
74{
75 uint32_t mask = ArithProfile::NonNumeric;
76 return (m_bits & mask) != mask;
77}
78
79bool ArithProfile::shouldEmitSetBigInt() const
80{
81 uint32_t mask = ArithProfile::BigInt;
82 return (m_bits & mask) != mask;
83}
84
85void ArithProfile::emitSetNonNumeric(CCallHelpers& jit) const
86{
87 if (shouldEmitSetNonNumeric())
88 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNumeric), CCallHelpers::AbsoluteAddress(addressOfBits()));
89}
90
91void ArithProfile::emitSetBigInt(CCallHelpers& jit) const
92{
93 if (shouldEmitSetBigInt())
94 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::BigInt), CCallHelpers::AbsoluteAddress(addressOfBits()));
95}
96#endif // ENABLE(JIT)
97
98} // namespace JSC
99
100namespace WTF {
101
102using namespace JSC;
103
104void printInternal(PrintStream& out, const ArithProfile& profile)
105{
106 const char* separator = "";
107
108 out.print("Result:<");
109 if (!profile.didObserveNonInt32()) {
110 out.print("Int32");
111 separator = "|";
112 } else {
113 if (profile.didObserveNegZeroDouble()) {
114 out.print(separator, "NegZeroDouble");
115 separator = "|";
116 }
117 if (profile.didObserveNonNegZeroDouble()) {
118 out.print(separator, "NonNegZeroDouble");
119 separator = "|";
120 }
121 if (profile.didObserveNonNumeric()) {
122 out.print(separator, "NonNumeric");
123 separator = "|";
124 }
125 if (profile.didObserveInt32Overflow()) {
126 out.print(separator, "Int32Overflow");
127 separator = "|";
128 }
129 if (profile.didObserveInt52Overflow()) {
130 out.print(separator, "Int52Overflow");
131 separator = "|";
132 }
133 if (profile.didObserveBigInt()) {
134 out.print(separator, "BigInt");
135 separator = "|";
136 }
137 }
138 if (profile.tookSpecialFastPath())
139 out.print(separator, "Took special fast path.");
140 out.print(">");
141
142 out.print(" LHS ObservedType:<");
143 out.print(profile.lhsObservedType());
144 out.print("> RHS ObservedType:<");
145 out.print(profile.rhsObservedType());
146 out.print(">");
147
148 out.print(" LHS ResultType:<", RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(profile.lhsResultType().bits()))));
149 out.print("> RHS ResultType:<", RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(profile.rhsResultType().bits()))));
150 out.print(">");
151}
152
153void printInternal(PrintStream& out, const JSC::ObservedType& observedType)
154{
155 const char* separator = "";
156 if (observedType.sawInt32()) {
157 out.print(separator, "Int32");
158 separator = "|";
159 }
160 if (observedType.sawNumber()) {
161 out.print(separator, "Number");
162 separator = "|";
163 }
164 if (observedType.sawNonNumber()) {
165 out.print(separator, "NonNumber");
166 separator = "|";
167 }
168}
169
170} // namespace WTF
171