[JSC] Shrink the Math inline caches some more
[WebKit-https.git] / Source / JavaScriptCore / bytecode / ArithProfile.cpp
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
32 namespace JSC {
33
34 #if ENABLE(JIT)
35 void ArithProfile::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode)
36 {
37     if (!shouldEmitSetDouble() && !shouldEmitSetNonNumber())
38         return;
39
40     CCallHelpers::Jump isInt32 = jit.branchIfInt32(regs, mode);
41     CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode);
42     emitSetDouble(jit);
43     CCallHelpers::Jump done = jit.jump();
44     notDouble.link(&jit);
45     emitSetNonNumber(jit);
46     done.link(&jit);
47     isInt32.link(&jit);
48 }
49
50 bool ArithProfile::shouldEmitSetDouble() const
51 {
52     uint32_t mask = ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble;
53     return (m_bits & mask) != mask;
54 }
55
56 void ArithProfile::emitSetDouble(CCallHelpers& jit) const
57 {
58     if (shouldEmitSetDouble())
59         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfBits()));
60 }
61
62 bool ArithProfile::shouldEmitSetNonNumber() const
63 {
64     uint32_t mask = ArithProfile::NonNumber;
65     return (m_bits & mask) != mask;
66 }
67
68 void ArithProfile::emitSetNonNumber(CCallHelpers& jit) const
69 {
70     if (shouldEmitSetNonNumber())
71         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNumber), CCallHelpers::AbsoluteAddress(addressOfBits()));
72 }
73 #endif // ENABLE(JIT)
74
75 } // namespace JSC
76
77 namespace WTF {
78     
79 using namespace JSC;
80
81 void printInternal(PrintStream& out, const ArithProfile& profile)
82 {
83     const char* separator = "";
84
85     out.print("Result:<");
86     if (!profile.didObserveNonInt32()) {
87         out.print("Int32");
88         separator = "|";
89     } else {
90         if (profile.didObserveNegZeroDouble()) {
91             out.print(separator, "NegZeroDouble");
92             separator = "|";
93         }
94         if (profile.didObserveNonNegZeroDouble()) {
95             out.print(separator, "NonNegZeroDouble");
96             separator = "|";
97         }
98         if (profile.didObserveNonNumber()) {
99             out.print(separator, "NonNumber");
100             separator = "|";
101         }
102         if (profile.didObserveInt32Overflow()) {
103             out.print(separator, "Int32Overflow");
104             separator = "|";
105         }
106         if (profile.didObserveInt52Overflow()) {
107             out.print(separator, "Int52Overflow");
108             separator = "|";
109         }
110     }
111     if (profile.tookSpecialFastPath())
112         out.print(separator, "Took special fast path.");
113     out.print(">");
114
115     out.print(" LHS ObservedType:<");
116     out.print(profile.lhsObservedType());
117     out.print("> RHS ObservedType:<");
118     out.print(profile.rhsObservedType());
119     out.print(">");
120
121     out.print(" LHS ResultType:<", RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(profile.lhsResultType().bits()))));
122     out.print("> RHS ResultType:<", RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(profile.rhsResultType().bits()))));
123     out.print(">");
124 }
125
126 void printInternal(PrintStream& out, const JSC::ObservedType& observedType)
127 {
128     const char* separator = "";
129     if (observedType.sawInt32()) {
130         out.print(separator, "Int32");
131         separator = "|";
132     }
133     if (observedType.sawNumber()) {
134         out.print(separator, "Number");
135         separator = "|";
136     }
137     if (observedType.sawNonNumber()) {
138         out.print(separator, "NonNumber");
139         separator = "|";
140     }
141 }
142
143 } // namespace WTF