Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

12811281 7905BB691D12050E0019FE57 /* InlineAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 7905BB671D12050E0019FE57 /* InlineAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
12821282 79160DBD1C8E3EC8008C085A /* ProxyRevoke.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79160DBB1C8E3EC8008C085A /* ProxyRevoke.cpp */; };
12831283 79160DBE1C8E3EC8008C085A /* ProxyRevoke.h in Headers */ = {isa = PBXBuildFile; fileRef = 79160DBC1C8E3EC8008C085A /* ProxyRevoke.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1284 79233C2B1D34715700C5A834 /* JITMathIC.h in Headers */ = {isa = PBXBuildFile; fileRef = 79233C291D34715700C5A834 /* JITMathIC.h */; settings = {ATTRIBUTES = (Private, ); }; };
12841285 792CB3491C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */; };
12851286 792CB34A1C4EED5C00D13AF3 /* PCToCodeOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
12861287 7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 796465681B952FF0003059EE /* GetPutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
12871288 797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */; };
12881289 797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
12891290 799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1291 79A228351D35D71E00D8E067 /* ArithProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A228331D35D71E00D8E067 /* ArithProfile.cpp */; };
 1292 79A228361D35D71F00D8E067 /* ArithProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A228341D35D71E00D8E067 /* ArithProfile.h */; };
12901293 79B00CBC1C6AB07E0088C65D /* ProxyConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79B00CB81C6AB07E0088C65D /* ProxyConstructor.cpp */; };
12911294 79B00CBD1C6AB07E0088C65D /* ProxyConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 79B00CB91C6AB07E0088C65D /* ProxyConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
12921295 79B00CBE1C6AB07E0088C65D /* ProxyObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79B00CBA1C6AB07E0088C65D /* ProxyObject.cpp */; settings = {COMPILER_FLAGS = "-fno-optimize-sibling-calls"; }; };
12931296 79B00CBF1C6AB07E0088C65D /* ProxyObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 79B00CBB1C6AB07E0088C65D /* ProxyObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1297 79B1788E1D399B8000B1A567 /* JITMathICForwards.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A899FE1D38612E00D18C73 /* JITMathICForwards.h */; settings = {ATTRIBUTES = (Private, ); }; };
12941298 79C4B15D1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */; };
12951299 79C4B15E1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
12961300 79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */ = {isa = PBXBuildFile; fileRef = 79CFC6EF1C33B10000C768EA /* LLIntPCRanges.h */; settings = {ATTRIBUTES = (Private, ); }; };

34763480 7905BB671D12050E0019FE57 /* InlineAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineAccess.h; sourceTree = "<group>"; };
34773481 79160DBB1C8E3EC8008C085A /* ProxyRevoke.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyRevoke.cpp; sourceTree = "<group>"; };
34783482 79160DBC1C8E3EC8008C085A /* ProxyRevoke.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProxyRevoke.h; sourceTree = "<group>"; };
 3483 79233C291D34715700C5A834 /* JITMathIC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMathIC.h; sourceTree = "<group>"; };
34793484 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCToCodeOriginMap.cpp; sourceTree = "<group>"; };
34803485 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCToCodeOriginMap.h; sourceTree = "<group>"; };
34813486 796465681B952FF0003059EE /* GetPutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetPutInfo.h; sourceTree = "<group>"; };
34823487 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalLexicalEnvironment.cpp; sourceTree = "<group>"; };
34833488 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalLexicalEnvironment.h; sourceTree = "<group>"; };
34843489 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PCToOriginMap.h; path = b3/B3PCToOriginMap.h; sourceTree = "<group>"; };
 3490 79A228331D35D71E00D8E067 /* ArithProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArithProfile.cpp; sourceTree = "<group>"; };
 3491 79A228341D35D71E00D8E067 /* ArithProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArithProfile.h; sourceTree = "<group>"; };
 3492 79A899FE1D38612E00D18C73 /* JITMathICForwards.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMathICForwards.h; sourceTree = "<group>"; };
34853493 79B00CB81C6AB07E0088C65D /* ProxyConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyConstructor.cpp; sourceTree = "<group>"; };
34863494 79B00CB91C6AB07E0088C65D /* ProxyConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProxyConstructor.h; sourceTree = "<group>"; };
34873495 79B00CBA1C6AB07E0088C65D /* ProxyObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyObject.cpp; sourceTree = "<group>"; };

50575065 DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */,
50585066 1429D92D0ED22D7000B89619 /* JIT.cpp */,
50595067 1429D92E0ED22D7000B89619 /* JIT.h */,
 5068 79233C291D34715700C5A834 /* JITMathIC.h */,
 5069 79A899FE1D38612E00D18C73 /* JITMathICForwards.h */,
50605070 FE1220251BE7F5640039E6F2 /* JITAddGenerator.cpp */,
50615071 FE1220261BE7F5640039E6F2 /* JITAddGenerator.h */,
50625072 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */,

65566566 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */,
65576567 0F63945115D07051006A597C /* ArrayProfile.cpp */,
65586568 0F63945215D07051006A597C /* ArrayProfile.h */,
 6569 79A228331D35D71E00D8E067 /* ArithProfile.cpp */,
 6570 79A228341D35D71E00D8E067 /* ArithProfile.h */,
65596571 C2FCAE0C17A9C24E0034C735 /* BytecodeBasicBlock.cpp */,
65606572 C2FCAE0D17A9C24E0034C735 /* BytecodeBasicBlock.h */,
65616573 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */,

70687080 A5EA70E819F5B1010098F5EC /* AugmentableInspectorControllerClient.h in Headers */,
70697081 0FEC84FF1BDACDAC0080FF74 /* B3ArgumentRegValue.h in Headers */,
70707082 0FEC85011BDACDAC0080FF74 /* B3BasicBlock.h in Headers */,
 7083 79233C2B1D34715700C5A834 /* JITMathIC.h in Headers */,
70717084 0FEC85021BDACDAC0080FF74 /* B3BasicBlockInlines.h in Headers */,
70727085 0FEC85031BDACDAC0080FF74 /* B3BasicBlockUtils.h in Headers */,
70737086 0FEC85041BDACDAC0080FF74 /* B3BlockWorklist.h in Headers */,

77547767 A51007C1187CC3C600B38879 /* JSGlobalObjectInspectorController.h in Headers */,
77557768 A50E4B6418809DD50068A46D /* JSGlobalObjectRuntimeAgent.h in Headers */,
77567769 A503FA2A188F105900110F14 /* JSGlobalObjectScriptDebugServer.h in Headers */,
 7770 79A228361D35D71F00D8E067 /* ArithProfile.h in Headers */,
77577771 A513E5C0185BFACC007E95AD /* JSInjectedScriptHost.h in Headers */,
77587772 A513E5C2185BFACC007E95AD /* JSInjectedScriptHostPrototype.h in Headers */,
77597773 C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,

81798193 0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */,
81808194 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */,
81818195 9959E92E1BD17FA4001AA413 /* xxd.pl in Headers */,
 8196 79B1788E1D399B8000B1A567 /* JITMathICForwards.h in Headers */,
81828197 451539B912DC994500EF7AC4 /* Yarr.h in Headers */,
81838198 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */,
81848199 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */,

92639278 0FEB3ECF16237F6C00AB67AD /* MacroAssembler.cpp in Sources */,
92649279 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
92659280 FEB137571BB11EF900CD5100 /* MacroAssemblerARM64.cpp in Sources */,
 9281 79A228351D35D71E00D8E067 /* ArithProfile.cpp in Sources */,
92669282 A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
92679283 FE68C6381B90DE0B0042BCB3 /* MacroAssemblerPrinter.cpp in Sources */,
92689284 A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
203351

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
 32namespace JSC {
 33
 34#if ENABLE(JIT)
 35void ArithProfile::emitDetectNumericness(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode)
 36{
 37 CCallHelpers::Jump isInt32 = jit.branchIfInt32(regs, mode);
 38 CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode);
 39 // FIXME: We could be more precise here.
 40 emitSetDouble(jit);
 41 CCallHelpers::Jump done = jit.jump();
 42 notDouble.link(&jit);
 43 emitSetNonNumber(jit);
 44 done.link(&jit);
 45 isInt32.link(&jit);
 46}
 47
 48void ArithProfile::emitSetDouble(CCallHelpers& jit)
 49{
 50 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfBits()));
 51}
 52
 53void ArithProfile::emitSetNonNumber(CCallHelpers& jit)
 54{
 55 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNumber), CCallHelpers::AbsoluteAddress(addressOfBits()));
 56}
 57#endif // ENABLE(JIT)
 58
 59} // namespace JSC
 60
 61namespace WTF {
 62
 63using namespace JSC;
 64
 65void printInternal(PrintStream& out, const ArithProfile& profile)
 66{
 67 const char* separator = "";
 68
 69 if (!profile.didObserveNonInt32()) {
 70 out.print("Int32");
 71 separator = "|";
 72 } else {
 73 if (profile.didObserveNegZeroDouble()) {
 74 out.print(separator, "NegZeroDouble");
 75 separator = "|";
 76 }
 77 if (profile.didObserveNonNegZeroDouble()) {
 78 out.print("NonNegZeroDouble");
 79 separator = "|";
 80 }
 81 if (profile.didObserveNonNumber()) {
 82 out.print("NonNumber");
 83 separator = "|";
 84 }
 85 if (profile.didObserveInt32Overflow()) {
 86 out.print("Int32Overflow");
 87 separator = "|";
 88 }
 89 if (profile.didObserveInt52Overflow()) {
 90 out.print("Int52Overflow");
 91 separator = "|";
 92 }
 93 }
 94 if (profile.specialFastPathCount()) {
 95 out.print(" special fast path: ");
 96 out.print(profile.specialFastPathCount());
 97 }
 98}
 99
 100} // namespace WTF
0

Source/JavaScriptCore/bytecode/ArithProfile.h

 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 *
 8 * 1. Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * 2. Redistributions in binary form must reproduce the above copyright
 11 * notice, this list of conditions and the following disclaimer in the
 12 * documentation and/or other materials provided with the distribution.
 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
 14 * its contributors may be used to endorse or promote products derived
 15 * from this software without specific prior written permission.
 16 *
 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27 */
 28
 29#ifndef ArithProfile_h
 30#define ArithProfile_h
 31
 32#include "GPRInfo.h"
 33#include "JSCJSValue.h"
 34#include "ResultType.h"
 35#include "TagRegistersMode.h"
 36
 37namespace JSC {
 38
 39class CCallHelpers;
 40
 41struct ObservedType {
 42 ObservedType(uint8_t bits = TypeEmpty)
 43 : m_bits(bits)
 44 { }
 45
 46 bool sawInt32() const { return m_bits & TypeInt32; }
 47 bool isOnlyInt32() const { return m_bits == TypeInt32; }
 48 bool sawNumber() const { return m_bits & TypeNumber; }
 49 bool isOnlyNumber() const { return m_bits == TypeNumber; }
 50 bool sawNonNumber() const { return m_bits & TypeNonNumber; }
 51 bool isOnlyNonNumber() const { return m_bits == TypeNonNumber; }
 52 bool isEmpty() const { return !m_bits; }
 53 uint8_t bits() const { return m_bits; }
 54
 55 ObservedType withInt32() const { return ObservedType(m_bits | TypeInt32); }
 56 ObservedType withNumber() const { return ObservedType(m_bits | TypeNumber); }
 57 ObservedType withNonNumber() const { return ObservedType(m_bits | TypeNonNumber); }
 58 ObservedType withoutNonNumber() const { return ObservedType(m_bits & ~TypeNonNumber); }
 59
 60 bool operator==(const ObservedType& other) const { return m_bits == other.m_bits; }
 61
 62 static const uint8_t TypeEmpty = 0x0;
 63 static const uint8_t TypeInt32 = 0x1;
 64 static const uint8_t TypeNumber = 0x02;
 65 static const uint8_t TypeNonNumber = 0x04;
 66
 67private:
 68 uint8_t m_bits;
 69};
 70
 71struct ArithProfile {
 72private:
 73 static const uint32_t numberOfFlagBits = 5;
 74 static const uint32_t rhsResultTypeShift = 5;
 75 static const uint32_t lhsResultTypeShift = 11;
 76 static const uint32_t rhsObservedTypeShift = 17;
 77 static const uint32_t lhsObservedTypeShift = 20;
 78 static const uint32_t bottom6Bits = (1 << 6) - 1;
 79 static const uint32_t bottom3Bits = (1 << 3) - 1;
 80 static const uint32_t clearRhsObservedTypeBits = ~((1 << 17) | (1 << 18) | (1 << 19));
 81 static const uint32_t clearLhsObservedTypeBits = ~((1 << 20) | (1 << 21) | (1 << 22));
 82
 83 static_assert(ResultType::numBitsNeeded == 6, "We make a strong assumption here that ResultType fits in 6 bis.");
 84
 85public:
 86 static const uint32_t specialFastPathBit = 1 << 23;
 87
 88 ArithProfile(ResultType lhs, ResultType rhs)
 89 {
 90 m_bits = (lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift);
 91 ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits());
 92 ASSERT(lhsObservedType().isEmpty());
 93 ASSERT(rhsObservedType().isEmpty());
 94 }
 95 ArithProfile()
 96 { }
 97
 98 static ArithProfile fromInt(uint32_t bits)
 99 {
 100 ArithProfile result;
 101 result.m_bits = bits;
 102 return result;
 103 }
 104
 105 enum ObservedResults {
 106 NonNegZeroDouble = 1 << 0,
 107 NegZeroDouble = 1 << 1,
 108 NonNumber = 1 << 2,
 109 Int32Overflow = 1 << 3,
 110 Int52Overflow = 1 << 4,
 111 };
 112
 113 ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & bottom6Bits); }
 114 ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & bottom6Bits); }
 115
 116 ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & bottom3Bits); }
 117 ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & bottom3Bits); }
 118 void setLhsObservedType(ObservedType type)
 119 {
 120 uint32_t bits = m_bits;
 121 bits &= clearLhsObservedTypeBits;
 122 bits |= type.bits() << lhsObservedTypeShift;
 123 m_bits = bits;
 124 ASSERT(lhsObservedType() == type);
 125 }
 126
 127 void setRhsObservedType(ObservedType type)
 128 {
 129 uint32_t bits = m_bits;
 130 bits &= clearRhsObservedTypeBits;
 131 bits |= type.bits() << rhsObservedTypeShift;
 132 m_bits = bits;
 133 ASSERT(rhsObservedType() == type);
 134 }
 135
 136 unsigned specialFastPathCount() const
 137 {
 138 // FIXME:
 139 return m_bits & specialFastPathBit ? UINT_MAX : 0;
 140 }
 141
 142 bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); }
 143 bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); }
 144 bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); }
 145 bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); }
 146 bool didObserveNonNumber() const { return hasBits(NonNumber); }
 147 bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); }
 148 bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); }
 149
 150 void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); }
 151 void setObservedNegZeroDouble() { setBit(NegZeroDouble); }
 152 void setObservedNonNumber() { setBit(NonNumber); }
 153 void setObservedInt32Overflow() { setBit(Int32Overflow); }
 154 void setObservedInt52Overflow() { setBit(Int52Overflow); }
 155
 156 void* addressOfBits() { return &m_bits; }
 157
 158 void detectNumericness(JSValue value)
 159 {
 160 if (value.isInt32())
 161 return;
 162 if (value.isNumber()) {
 163 m_bits |= Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble;
 164 return;
 165 }
 166 m_bits |= NonNumber;
 167 }
 168
 169 void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); }
 170 void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); }
 171 void lhsSawNonNumber() { setLhsObservedType(lhsObservedType().withNonNumber()); }
 172 void rhsSawInt32() { setRhsObservedType(rhsObservedType().withInt32()); }
 173 void rhsSawNumber() { setRhsObservedType(rhsObservedType().withNumber()); }
 174 void rhsSawNonNumber() { setRhsObservedType(rhsObservedType().withNonNumber()); }
 175
 176 void observeLHSAndRHS(JSValue lhs, JSValue rhs)
 177 {
 178 ArithProfile newProfile = *this;
 179 if (lhs.isNumber()) {
 180 if (lhs.isInt32())
 181 newProfile.lhsSawInt32();
 182 else
 183 newProfile.lhsSawNumber();
 184 } else
 185 newProfile.lhsSawNonNumber();
 186
 187 if (rhs.isNumber()) {
 188 if (rhs.isInt32())
 189 newProfile.rhsSawInt32();
 190 else
 191 newProfile.rhsSawNumber();
 192 } else
 193 newProfile.rhsSawNonNumber();
 194
 195 m_bits = newProfile.bits();
 196 }
 197
 198#if ENABLE(JIT)
 199 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
 200 // double. Sets NonNumber if it sees a non-number.
 201 void emitDetectNumericness(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
 202
 203 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
 204 void emitSetDouble(CCallHelpers&);
 205
 206 // Sets NonNumber.
 207 void emitSetNonNumber(CCallHelpers&);
 208#endif // ENABLE(JIT)
 209
 210 uint32_t bits() const { return m_bits; }
 211
 212private:
 213 bool hasBits(int mask) const { return m_bits & mask; }
 214 void setBit(int mask) { m_bits |= mask; }
 215
 216 uint32_t m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it.
 217};
 218
 219} // namespace JSC
 220
 221namespace WTF {
 222
 223void printInternal(PrintStream&, const JSC::ArithProfile&);
 224
 225} // namespace WTF
 226
 227#endif // ArithProfile_h
0

Source/JavaScriptCore/bytecode/CodeBlock.cpp

3030#include "config.h"
3131#include "CodeBlock.h"
3232
 33#include "ArithProfile.h"
3334#include "BasicBlockLocation.h"
3435#include "BytecodeGenerator.h"
3536#include "BytecodeUseDef.h"

4546#include "InlineCallFrame.h"
4647#include "Interpreter.h"
4748#include "JIT.h"
 49#include "JITMathIC.h"
4850#include "JSCJSValue.h"
4951#include "JSFunction.h"
5052#include "JSLexicalEnvironment.h"

@@void CodeBlock::dumpRareCaseProfile(Prin
767769 out.print(name, profile->m_counter);
768770}
769771
770 void CodeBlock::dumpResultProfile(PrintStream& out, ResultProfile* profile, bool& hasPrintedProfiling)
 772void CodeBlock::dumpArithProfile(PrintStream& out, ArithProfile* profile, bool& hasPrintedProfiling)
771773{
772774 if (!profile)
773775 return;

@@void CodeBlock::dumpBytecode(
17671769 dumpRareCaseProfile(out, "rare case: ", rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
17681770 {
17691771 ConcurrentJITLocker locker(m_lock);
1770  dumpResultProfile(out, resultProfileForBytecodeOffset(locker, location), hasPrintedProfiling);
 1772 dumpArithProfile(out, arithProfileForBytecodeOffset(location), hasPrintedProfiling);
17711773 }
17721774
17731775#if ENABLE(DFG_JIT)

@@StructureStubInfo* CodeBlock::addStubInf
30003002 return m_stubInfos.add(accessType);
30013003}
30023004
 3005JITAddIC* CodeBlock::addJITAddIC()
 3006{
 3007 ConcurrentJITLocker locker(m_lock);
 3008 return m_addICs.add();
 3009}
 3010
 3011#include <stdio.h>
 3012#include <sys/types.h>
 3013
 3014void CodeBlock::dumpJITAddICStats()
 3015{
 3016 return;
 3017
 3018 /*
 3019 double size = 0.0;
 3020 double outOfLine = 0.0;
 3021 auto func = [&] (CodeBlock* codeBlock) -> bool {
 3022 for (JITAddIC* addIC : codeBlock->m_addICs) {
 3023 ++size;
 3024 if (addIC->m_code)
 3025 ++outOfLine;
 3026 }
 3027 return false;
 3028 };
 3029 vm()->heap.forEachCodeBlock(func);
 3030 auto pid = getpid();
 3031 dataLog("PID: ", pid, " CodeBlock has outOfLine ratio: ", outOfLine/size, "\n");
 3032 dataLog("PID: ", pid, " Total num add ICs:", size, ". Total num out of line: ", outOfLine, "\n");
 3033 */
 3034
 3035 static double peakSize = 0.0;
 3036 double size = 0.0;
 3037 double numAdds = 0.0;
 3038 size_t smallestSize = UINT_MAX;
 3039 size_t largestSize = 0;
 3040 auto func = [&] (CodeBlock* codeBlock) -> bool {
 3041 for (JITAddIC* addIC : codeBlock->m_addICs) {
 3042 ++numAdds;
 3043 size += addIC->codeSize();
 3044 largestSize = std::max(addIC->codeSize(), largestSize);
 3045 smallestSize = std::min(addIC->codeSize(), smallestSize);
 3046 }
 3047 return false;
 3048 };
 3049 vm()->heap.forEachCodeBlock(func);
 3050 peakSize = std::max(size, peakSize);
 3051 auto pid = getpid();
 3052 dataLog("PID: ", pid, " CodeBlock has size ratio: ", size/numAdds, "\n");
 3053 dataLog("PID: ", pid, " Total num add ICs:", numAdds, ". Total num size: ", size, "\n");
 3054 dataLog("PID: ", pid, " Peak size: ", peakSize, "\n");
 3055 dataLog("PID: ", pid, " largest size:", largestSize, " Smallest size:", smallestSize, "\n");
 3056}
 3057
30033058StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
30043059{
30053060 for (StructureStubInfo* stubInfo : m_stubInfos) {

@@void CodeBlock::resetJITData()
30463101 // We can clear this because the DFG's queries to these data structures are guarded by whether
30473102 // there is JIT code.
30483103 m_rareCaseProfiles.clear();
3049 
3050  // We can clear these because the DFG only accesses members of this data structure when
3051  // holding the lock or after querying whether we have JIT code.
3052  m_resultProfiles.clear();
3053  m_bytecodeOffsetToResultProfileIndexMap = nullptr;
30543104}
30553105#endif
30563106

@@void CodeBlock::shrinkToFit(ShrinkMode s
32803330 ConcurrentJITLocker locker(m_lock);
32813331
32823332 m_rareCaseProfiles.shrinkToFit();
3283  m_resultProfiles.shrinkToFit();
32843333
32853334 if (shrinkMode == EarlyShrink) {
32863335 m_constantRegisters.shrinkToFit();

@@void CodeBlock::dumpValueProfiles()
41564205 RareCaseProfile* profile = rareCaseProfile(i);
41574206 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
41584207 }
4159  dataLog("ResultProfile for ", *this, ":\n");
4160  for (unsigned i = 0; i < numberOfResultProfiles(); ++i) {
4161  const ResultProfile& profile = *resultProfile(i);
 4208 /* FIXME:
 4209 dataLog("ArithProfile for ", *this, ":\n");
 4210 for (unsigned i = 0; i < numberOfArithProfiles(); ++i) {
 4211 const ArithProfile& profile = *arithProfile(i);
41624212 dataLog(" bc = ", profile.bytecodeOffset(), ": ", profile, "\n");
41634213 }
 4214 */
41644215}
41654216#endif // ENABLE(VERBOSE_VALUE_PROFILE)
41664217

@@unsigned CodeBlock::rareCaseProfileCount
43634414 return 0;
43644415}
43654416
4366 ResultProfile* CodeBlock::resultProfileForBytecodeOffset(const ConcurrentJITLocker&, int bytecodeOffset)
 4417ArithProfile* CodeBlock::arithProfileForBytecodeOffset(int bytecodeOffset)
43674418{
4368  if (!m_bytecodeOffsetToResultProfileIndexMap)
4369  return nullptr;
4370  auto iterator = m_bytecodeOffsetToResultProfileIndexMap->find(bytecodeOffset);
4371  if (iterator == m_bytecodeOffsetToResultProfileIndexMap->end())
 4419 auto opcodeID = vm()->interpreter->getOpcodeID(instructions()[bytecodeOffset].u.opcode);
 4420 switch (opcodeID) {
 4421 case op_bitor:
 4422 case op_bitand:
 4423 case op_bitxor:
 4424 case op_add:
 4425 case op_mul:
 4426 case op_sub:
 4427 case op_div:
 4428 break;
 4429 default:
43724430 return nullptr;
4373  return &m_resultProfiles[iterator->value];
 4431 }
 4432
 4433 Instruction* instruction = &instructions()[bytecodeOffset + 4];
 4434 return bitwise_cast<ArithProfile*>(&instruction->u.operand);
 4435}
 4436
 4437ArithProfile& CodeBlock::arithProfileForPC(Instruction* pc)
 4438{
 4439 if (!ASSERT_DISABLED) {
 4440 ASSERT(pc >= instructions().begin() && pc < instructions().end());
 4441 auto opcodeID = vm()->interpreter->getOpcodeID(pc[0].u.opcode);
 4442 switch (opcodeID) {
 4443 case op_bitor:
 4444 case op_bitand:
 4445 case op_bitxor:
 4446 case op_add:
 4447 case op_mul:
 4448 case op_sub:
 4449 case op_div:
 4450 break;
 4451 default:
 4452 ASSERT_NOT_REACHED();
 4453 }
 4454 }
 4455
 4456 return *bitwise_cast<ArithProfile*>(&pc[4].u.operand);
43744457}
43754458
43764459unsigned CodeBlock::specialFastCaseProfileCountForBytecodeOffset(int bytecodeOffset)

@@unsigned CodeBlock::specialFastCaseProfi
43794462 return specialFastCaseProfileCountForBytecodeOffset(locker, bytecodeOffset);
43804463}
43814464
4382 unsigned CodeBlock::specialFastCaseProfileCountForBytecodeOffset(const ConcurrentJITLocker& locker, int bytecodeOffset)
 4465unsigned CodeBlock::specialFastCaseProfileCountForBytecodeOffset(const ConcurrentJITLocker&, int bytecodeOffset)
43834466{
4384  ResultProfile* profile = resultProfileForBytecodeOffset(locker, bytecodeOffset);
 4467 ArithProfile* profile = arithProfileForBytecodeOffset(bytecodeOffset);
43854468 if (!profile)
43864469 return 0;
43874470 return profile->specialFastPathCount();

@@bool CodeBlock::couldTakeSpecialFastCase
43954478 return specialFastCaseCount >= Options::couldTakeSlowCaseMinimumCount();
43964479}
43974480
4398 ResultProfile* CodeBlock::ensureResultProfile(int bytecodeOffset)
4399 {
4400  ConcurrentJITLocker locker(m_lock);
4401  return ensureResultProfile(locker, bytecodeOffset);
4402 }
4403 
4404 ResultProfile* CodeBlock::ensureResultProfile(const ConcurrentJITLocker& locker, int bytecodeOffset)
4405 {
4406  ResultProfile* profile = resultProfileForBytecodeOffset(locker, bytecodeOffset);
4407  if (!profile) {
4408  m_resultProfiles.append(ResultProfile(bytecodeOffset));
4409  profile = &m_resultProfiles.last();
4410  ASSERT(&m_resultProfiles.last() == &m_resultProfiles[m_resultProfiles.size() - 1]);
4411  if (!m_bytecodeOffsetToResultProfileIndexMap)
4412  m_bytecodeOffsetToResultProfileIndexMap = std::make_unique<BytecodeOffsetToResultProfileIndexMap>();
4413  m_bytecodeOffsetToResultProfileIndexMap->add(bytecodeOffset, m_resultProfiles.size() - 1);
4414  }
4415  return profile;
4416 }
4417 
44184481#if ENABLE(JIT)
44194482DFG::CapabilityLevel CodeBlock::capabilityLevel()
44204483{
203351

Source/JavaScriptCore/bytecode/CodeBlock.h

5151#include "HandlerInfo.h"
5252#include "Instruction.h"
5353#include "JITCode.h"
 54#include "JITMathICForwards.h"
5455#include "JITWriteBarrier.h"
5556#include "JSCell.h"
5657#include "JSGlobalObject.h"

7980namespace JSC {
8081
8182class ExecState;
 83class JITAddGenerator;
8284class JSModuleEnvironment;
8385class LLIntOffsetsExtractor;
8486class PCToCodeOriginMap;

@@class TypeLocation;
8890
8991enum class AccessType : int8_t;
9092
 93struct ArithProfile;
 94
9195typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
9296
9397enum ReoptimizationMode { DontCountReoptimization, CountReoptimization };

@@public:
245249
246250#if ENABLE(JIT)
247251 StructureStubInfo* addStubInfo(AccessType);
 252 JITAddIC* addJITAddIC();
 253 void dumpJITAddICStats();
248254 Bag<StructureStubInfo>::iterator stubInfoBegin() { return m_stubInfos.begin(); }
249255 Bag<StructureStubInfo>::iterator stubInfoEnd() { return m_stubInfos.end(); }
250256

@@public:
440446 return value >= Options::couldTakeSlowCaseMinimumCount();
441447 }
442448
443  ResultProfile* ensureResultProfile(int bytecodeOffset);
444  ResultProfile* ensureResultProfile(const ConcurrentJITLocker&, int bytecodeOffset);
445  unsigned numberOfResultProfiles() { return m_resultProfiles.size(); }
446  ResultProfile* resultProfileForBytecodeOffset(const ConcurrentJITLocker&, int bytecodeOffset);
 449 ArithProfile* arithProfileForBytecodeOffset(int bytecodeOffset);
 450 ArithProfile& arithProfileForPC(Instruction*);
447451
448452 unsigned specialFastCaseProfileCountForBytecodeOffset(const ConcurrentJITLocker&, int bytecodeOffset);
449453 unsigned specialFastCaseProfileCountForBytecodeOffset(int bytecodeOffset);

@@private:
957961 void dumpValueProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling);
958962 void dumpArrayProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling);
959963 void dumpRareCaseProfile(PrintStream&, const char* name, RareCaseProfile*, bool& hasPrintedProfiling);
960  void dumpResultProfile(PrintStream&, ResultProfile*, bool& hasPrintedProfiling);
 964 void dumpArithProfile(PrintStream&, ArithProfile*, bool& hasPrintedProfiling);
961965
962966 bool shouldVisitStrongly();
963967 bool shouldJettisonDueToWeakReference();

@@private:
10131017#if ENABLE(JIT)
10141018 std::unique_ptr<RegisterAtOffsetList> m_calleeSaveRegisters;
10151019 Bag<StructureStubInfo> m_stubInfos;
 1020 Bag<JITAddIC> m_addICs;
10161021 Bag<ByValInfo> m_byValInfos;
10171022 Bag<CallLinkInfo> m_callLinkInfos;
10181023 SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo>> m_incomingCalls;

@@private:
10291034 RefCountedArray<ValueProfile> m_argumentValueProfiles;
10301035 RefCountedArray<ValueProfile> m_valueProfiles;
10311036 SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
1032  SegmentedVector<ResultProfile, 8> m_resultProfiles;
1033  typedef HashMap<unsigned, unsigned, IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> BytecodeOffsetToResultProfileIndexMap;
1034  std::unique_ptr<BytecodeOffsetToResultProfileIndexMap> m_bytecodeOffsetToResultProfileIndexMap;
10351037 RefCountedArray<ArrayAllocationProfile> m_arrayAllocationProfiles;
10361038 ArrayProfileVector m_arrayProfiles;
10371039 RefCountedArray<ObjectAllocationProfile> m_objectAllocationProfiles;
203351

Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp

2828
2929#if ENABLE(DFG_JIT)
3030
 31#include "ArithProfile.h"
3132#include "CCallHelpers.h"
3233#include "CodeBlock.h"
3334#include "JSCInlines.h"

@@void MethodOfGettingAValueProfile::emitR
6566 return;
6667 }
6768
68  case ResultProfileReady: {
69  u.resultProfile->emitDetectNumericness(jit, regs, DoNotHaveTagRegisters);
 69 case ArithProfileReady: {
 70 u.arithProfile->emitDetectNumericness(jit, regs, DoNotHaveTagRegisters);
7071 return;
7172 } }
7273
203351

Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h

@@namespace JSC {
4040class CCallHelpers;
4141class CodeBlock;
4242class LazyOperandValueProfileKey;
43 struct ResultProfile;
 43struct ArithProfile;
4444struct ValueProfile;
4545
4646class MethodOfGettingAValueProfile {

@@public:
5959 m_kind = None;
6060 }
6161
62  MethodOfGettingAValueProfile(ResultProfile* profile)
 62 MethodOfGettingAValueProfile(ArithProfile* profile)
6363 {
6464 if (profile) {
65  m_kind = ResultProfileReady;
66  u.resultProfile = profile;
 65 m_kind = ArithProfileReady;
 66 u.arithProfile = profile;
6767 } else
6868 m_kind = None;
6969 }

@@private:
7979 enum Kind {
8080 None,
8181 Ready,
82  ResultProfileReady,
 82 ArithProfileReady,
8383 LazyOperand
8484 };
8585
8686 Kind m_kind;
8787 union {
8888 ValueProfile* profile;
89  ResultProfile* resultProfile;
 89 ArithProfile* arithProfile;
9090 struct {
9191 CodeBlock* codeBlock;
9292 unsigned bytecodeOffset;
203351

Source/JavaScriptCore/bytecode/ValueProfile.cpp

3131
3232namespace JSC {
3333
34 #if ENABLE(JIT)
35 void ResultProfile::emitDetectNumericness(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode)
36 {
37  CCallHelpers::Jump isInt32 = jit.branchIfInt32(regs, mode);
38  CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode);
39  // FIXME: We could be more precise here.
40  emitSetDouble(jit);
41  CCallHelpers::Jump done = jit.jump();
42  notDouble.link(&jit);
43  emitSetNonNumber(jit);
44  done.link(&jit);
45  isInt32.link(&jit);
46 }
47 
48 void ResultProfile::emitSetDouble(CCallHelpers& jit)
49 {
50  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::Int32Overflow | ResultProfile::Int52Overflow | ResultProfile::NegZeroDouble | ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfFlags()));
51 }
52 
53 void ResultProfile::emitSetNonNumber(CCallHelpers& jit)
54 {
55  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNumber), CCallHelpers::AbsoluteAddress(addressOfFlags()));
56 }
57 #endif // ENABLE(JIT)
58 
5934} // namespace JSC
60 
61 namespace WTF {
62 
63 using namespace JSC;
64 
65 void printInternal(PrintStream& out, const ResultProfile& profile)
66 {
67  const char* separator = "";
68 
69  if (!profile.didObserveNonInt32()) {
70  out.print("Int32");
71  separator = "|";
72  } else {
73  if (profile.didObserveNegZeroDouble()) {
74  out.print(separator, "NegZeroDouble");
75  separator = "|";
76  }
77  if (profile.didObserveNonNegZeroDouble()) {
78  out.print("NonNegZeroDouble");
79  separator = "|";
80  }
81  if (profile.didObserveNonNumber()) {
82  out.print("NonNumber");
83  separator = "|";
84  }
85  if (profile.didObserveInt32Overflow()) {
86  out.print("Int32Overflow");
87  separator = "|";
88  }
89  if (profile.didObserveInt52Overflow()) {
90  out.print("Int52Overflow");
91  separator = "|";
92  }
93  }
94  if (profile.specialFastPathCount()) {
95  out.print(" special fast path: ");
96  out.print(profile.specialFastPathCount());
97  }
98 }
99 
100 } // namespace WTF
203351

Source/JavaScriptCore/bytecode/ValueProfile.h

@@inline int getRareCaseProfileBytecodeOff
209209 return rareCaseProfile->m_bytecodeOffset;
210210}
211211
212 struct ResultProfile {
213 private:
214  static const int numberOfFlagBits = 5;
215 
216 public:
217  ResultProfile(int bytecodeOffset)
218  : m_bytecodeOffsetAndFlags(bytecodeOffset << numberOfFlagBits)
219  {
220  ASSERT(((bytecodeOffset << numberOfFlagBits) >> numberOfFlagBits) == bytecodeOffset);
221  }
222 
223  enum ObservedResults {
224  NonNegZeroDouble = 1 << 0,
225  NegZeroDouble = 1 << 1,
226  NonNumber = 1 << 2,
227  Int32Overflow = 1 << 3,
228  Int52Overflow = 1 << 4,
229  };
230 
231  int bytecodeOffset() const { return m_bytecodeOffsetAndFlags >> numberOfFlagBits; }
232  unsigned specialFastPathCount() const { return m_specialFastPathCount; }
233 
234  bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); }
235  bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); }
236  bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); }
237  bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); }
238  bool didObserveNonNumber() const { return hasBits(NonNumber); }
239  bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); }
240  bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); }
241 
242  void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); }
243  void setObservedNegZeroDouble() { setBit(NegZeroDouble); }
244  void setObservedNonNumber() { setBit(NonNumber); }
245  void setObservedInt32Overflow() { setBit(Int32Overflow); }
246  void setObservedInt52Overflow() { setBit(Int52Overflow); }
247 
248  void* addressOfFlags() { return &m_bytecodeOffsetAndFlags; }
249  void* addressOfSpecialFastPathCount() { return &m_specialFastPathCount; }
250 
251  void detectNumericness(JSValue value)
252  {
253  if (value.isInt32())
254  return;
255  if (value.isNumber()) {
256  m_bytecodeOffsetAndFlags |= Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble;
257  return;
258  }
259  m_bytecodeOffsetAndFlags |= NonNumber;
260  }
261 
262 #if ENABLE(JIT)
263  // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
264  // double. Sets NonNumber if it sees a non-number.
265  void emitDetectNumericness(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
266 
267  // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
268  void emitSetDouble(CCallHelpers&);
269 
270  // Sets NonNumber.
271  void emitSetNonNumber(CCallHelpers&);
272 #endif // ENABLE(JIT)
273 
274 private:
275  bool hasBits(int mask) const { return m_bytecodeOffsetAndFlags & mask; }
276  void setBit(int mask) { m_bytecodeOffsetAndFlags |= mask; }
277 
278  int m_bytecodeOffsetAndFlags;
279  unsigned m_specialFastPathCount { 0 };
280 };
281 
282 inline int getResultProfileBytecodeOffset(ResultProfile* profile)
283 {
284  return profile->bytecodeOffset();
285 }
286 
287212} // namespace JSC
288213
289 namespace WTF {
290 
291 void printInternal(PrintStream&, const JSC::ResultProfile&);
292 
293 } // namespace WTF
294 
295214#endif // ValueProfile_h
296 
203351

Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

3131#include "config.h"
3232#include "BytecodeGenerator.h"
3333
 34#include "ArithProfile.h"
3435#include "BuiltinExecutables.h"
3536#include "BytecodeLivenessAnalysis.h"
3637#include "Interpreter.h"

@@RegisterID* BytecodeGenerator::emitBinar
15981599
15991600 if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
16001601 opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
1601  instructions().append(types.toInt());
 1602 instructions().append(ArithProfile(types.first(), types.second()).bits());
16021603
16031604 return dst;
16041605}
203351

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

2828
2929#if ENABLE(DFG_JIT)
3030
 31#include "ArithProfile.h"
3132#include "ArrayConstructor.h"
3233#include "BasicBlockLocation.h"
3334#include "CallLinkStatus.h"

@@private:
910911 return node;
911912
912913 {
913  ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
914  ResultProfile* resultProfile = m_inlineStackTop->m_profiledBlock->resultProfileForBytecodeOffset(locker, m_currentIndex);
915  if (resultProfile) {
 914 ArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->arithProfileForBytecodeOffset(m_currentIndex);
 915 if (arithProfile) {
916916 switch (node->op()) {
917917 case ArithAdd:
918918 case ArithSub:
919919 case ValueAdd:
920  if (resultProfile->didObserveDouble())
 920 if (arithProfile->didObserveDouble())
921921 node->mergeFlags(NodeMayHaveDoubleResult);
922  if (resultProfile->didObserveNonNumber())
 922 if (arithProfile->didObserveNonNumber())
923923 node->mergeFlags(NodeMayHaveNonNumberResult);
924924 break;
925925
926926 case ArithMul: {
927  if (resultProfile->didObserveInt52Overflow())
 927 if (arithProfile->didObserveInt52Overflow())
928928 node->mergeFlags(NodeMayOverflowInt52);
929  if (resultProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
 929 if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
930930 node->mergeFlags(NodeMayOverflowInt32InBaseline);
931  if (resultProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
 931 if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
932932 node->mergeFlags(NodeMayNegZeroInBaseline);
933  if (resultProfile->didObserveDouble())
 933 if (arithProfile->didObserveDouble())
934934 node->mergeFlags(NodeMayHaveDoubleResult);
935  if (resultProfile->didObserveNonNumber())
 935 if (arithProfile->didObserveNonNumber())
936936 node->mergeFlags(NodeMayHaveNonNumberResult);
937937 break;
938938 }
203351

Source/JavaScriptCore/dfg/DFGGraph.cpp

@@MethodOfGettingAValueProfile Graph::meth
15481548 return profiledBlock->valueProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
15491549
15501550 {
1551  ConcurrentJITLocker locker(profiledBlock->m_lock);
15521551 if (profiledBlock->hasBaselineJITProfiling()) {
1553  if (ResultProfile* result = profiledBlock->resultProfileForBytecodeOffset(locker, node->origin.semantic.bytecodeIndex))
 1552 if (ArithProfile* result = profiledBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex))
15541553 return result;
15551554 }
15561555 }
203351

Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

@@void JITCompiler::exceptionCheck()
604604 HandlerInfo* exceptionHandler;
605605 bool willCatchException = m_graph.willCatchExceptionInMachineFrame(m_speculative->m_currentNode->origin.forExit, opCatchOrigin, exceptionHandler);
606606 if (willCatchException) {
607  unsigned streamIndex = m_speculative->m_outOfLineStreamIndex != UINT_MAX ? m_speculative->m_outOfLineStreamIndex : m_speculative->m_stream->size();
 607 unsigned streamIndex = m_speculative->m_outOfLineStreamIndex ? *m_speculative->m_outOfLineStreamIndex : m_speculative->m_stream->size();
608608 MacroAssembler::Jump hadException = emitNonPatchableExceptionCheck();
609609 // We assume here that this is called after callOpeartion()/appendCall() is called.
610610 appendExceptionHandlingOSRExit(ExceptionCheck, streamIndex, opCatchOrigin, exceptionHandler, m_jitCode->common.lastCallSite(), hadException);
203351

Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h

@@public:
5252 jit->m_outOfLineStreamIndex = m_streamIndex;
5353 jit->m_origin = m_origin;
5454 generateInternal(jit);
55  jit->m_outOfLineStreamIndex = UINT_MAX;
 55 jit->m_outOfLineStreamIndex = Nullopt;
5656 if (!ASSERT_DISABLED)
5757 jit->m_jit.abortWithReason(DFGSlowPathGeneratorFellThrough);
5858 }
203351

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

3838#include "DFGSaneStringGetByValSlowPathGenerator.h"
3939#include "DFGSlowPathGenerator.h"
4040#include "DirectArguments.h"
 41#include "JITMathIC.h"
4142#include "JITAddGenerator.h"
4243#include "JITBitAndGenerator.h"
4344#include "JITBitOrGenerator.h"

5657#include "ScopedArguments.h"
5758#include "ScratchRegisterAllocator.h"
5859#include "WriteBarrierBuffer.h"
 60#include <wtf/Box.h>
5961#include <wtf/MathExtras.h>
6062
6163namespace JSC { namespace DFG {

@@void SpeculativeJIT::addSlowPathGenerato
362364
363365void SpeculativeJIT::addSlowPathGenerator(std::function<void()> lambda)
364366{
365  m_slowPathLambdas.append(std::make_pair(lambda, m_currentNode));
 367 m_slowPathLambdas.append(SlowPathLambda{ lambda, m_currentNode, static_cast<unsigned>(m_stream->size()) });
366368}
367369
368370void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder& pcToCodeOriginMapBuilder)

@@void SpeculativeJIT::runSlowPathGenerato
371373 pcToCodeOriginMapBuilder.appendItem(m_jit.label(), slowPathGenerator->origin().semantic);
372374 slowPathGenerator->generate(this);
373375 }
374  for (auto& generatorPair : m_slowPathLambdas) {
375  Node* currentNode = generatorPair.second;
 376 for (auto& slowPathLambda : m_slowPathLambdas) {
 377 Node* currentNode = slowPathLambda.m_currentNode;
376378 m_currentNode = currentNode;
 379 m_outOfLineStreamIndex = slowPathLambda.m_streamIndex;
377380 pcToCodeOriginMapBuilder.appendItem(m_jit.label(), currentNode->origin.semantic);
378  generatorPair.first();
 381 slowPathLambda.m_generator();
 382 m_outOfLineStreamIndex = Nullopt;
379383 }
380384}
381385

@@void SpeculativeJIT::compileValueAdd(Nod
33793383 rightRegs = right->jsValueRegs();
33803384 }
33813385
3382  JITAddGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
3383  leftFPR, rightFPR, scratchGPR, scratchFPR);
3384  gen.generateFastPath(m_jit);
 3386 auto start = m_jit.label();
33853387
3386  ASSERT(gen.didEmitFastPath());
3387  gen.endJumpList().append(m_jit.jump());
 3388 JITAddIC* addIC = m_jit.codeBlock()->addJITAddIC();
 3389 Box<MathICGenerationState> addICGenerationState = Box<MathICGenerationState>::create();
 3390 ArithProfile* arithProfile = m_jit.graph().baselineCodeBlockFor(node->origin.semantic)->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
 3391 addIC->m_generator = JITAddGenerator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, leftFPR, rightFPR, scratchGPR, scratchFPR, arithProfile);
33883392
3389  gen.slowPathJumpList().link(&m_jit);
 3393 bool generatedInline = addIC->generateInline(m_jit, *addICGenerationState);
33903394
3391  silentSpillAllRegisters(resultRegs);
 3395 if (generatedInline) {
 3396 ASSERT(!addICGenerationState->m_slowPathJumps.empty());
33923397
3393  if (leftOperand.isConst()) {
3394  leftRegs = resultRegs;
3395  m_jit.moveValue(leftChild->asJSValue(), leftRegs);
3396  } else if (rightOperand.isConst()) {
3397  rightRegs = resultRegs;
3398  m_jit.moveValue(rightChild->asJSValue(), rightRegs);
3399  }
 3398 Vector<SilentRegisterSavePlan, 4> savePlans;
 3399 silentSpillAllRegistersImpl(false, savePlans, resultRegs);
34003400
3401  callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
 3401 auto done = m_jit.label();
34023402
3403  silentFillAllRegisters(resultRegs);
3404  m_jit.exceptionCheck();
 3403 addSlowPathGenerator([=] () {
 3404 addICGenerationState->m_slowPathJumps.link(&m_jit);
 3405 addICGenerationState->m_slowPathStart = m_jit.label();
 3406
 3407 auto slowStart = m_jit.label();
 3408
 3409 silentSpill(savePlans);
 3410
 3411 auto innerLeftRegs = leftRegs;
 3412 auto innerRightRegs = rightRegs;
 3413 if (leftOperand.isConst()) {
 3414 innerLeftRegs = resultRegs;
 3415 m_jit.moveValue(leftChild->asJSValue(), innerLeftRegs);
 3416 } else if (rightOperand.isConst()) {
 3417 innerRightRegs = resultRegs;
 3418 m_jit.moveValue(rightChild->asJSValue(), innerRightRegs);
 3419 }
 3420
 3421 if (addICGenerationState->m_shouldSlowPathRepatch)
 3422 addICGenerationState->m_slowPathCall = callOperation(operationValueAddOptimize, resultRegs, innerLeftRegs, innerRightRegs, addIC);
 3423 else
 3424 addICGenerationState->m_slowPathCall = callOperation(operationValueAdd, resultRegs, innerLeftRegs, innerRightRegs);
 3425
 3426 silentFill(savePlans);
 3427 m_jit.exceptionCheck();
 3428 m_jit.jump().linkTo(done, &m_jit);
 3429
 3430 auto slowEnd = m_jit.label();
 3431
 3432 m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
 3433 addIC->finalizeInlineCode(*addICGenerationState, linkBuffer);
 3434 addIC->m_codeSize += (char*)linkBuffer.locationOf(slowEnd).executableAddress() - (char*)linkBuffer.locationOf(slowStart).executableAddress();
 3435 });
 3436 });
 3437 } else {
 3438 if (leftOperand.isConst()) {
 3439 left = JSValueOperand(this, leftChild);
 3440 leftRegs = left->jsValueRegs();
 3441 } else if (rightOperand.isConst()) {
 3442 right = JSValueOperand(this, rightChild);
 3443 rightRegs = right->jsValueRegs();
 3444 }
 3445
 3446 silentSpillAllRegisters(resultRegs);
 3447 callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
 3448 silentFillAllRegisters(resultRegs);
 3449 m_jit.exceptionCheck();
 3450 }
 3451
 3452 auto done = m_jit.label();
 3453 m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
 3454 addIC->m_codeSize += (char*)linkBuffer.locationOf(done).executableAddress() - (char*)linkBuffer.locationOf(start).executableAddress();
 3455 });
34053456
3406  gen.endJumpList().link(&m_jit);
34073457 jsValueResult(resultRegs, node);
34083458 return;
34093459}
203351

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

@@public:
12851285
12861286
12871287#if USE(JSVALUE64)
 1288
 1289 JITCompiler::Call callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, JITAddIC* addIC)
 1290 {
 1291 m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), TrustedImmPtr(addIC));
 1292 return appendCallSetResult(operation, result.gpr());
 1293 }
 1294
12881295 JITCompiler::Call callOperation(J_JITOperation_EJJI operation, GPRReg result, GPRReg arg1, GPRReg arg2, UniquedStringImpl* uid)
12891296 {
12901297 m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(uid));

@@public:
17021709 }
17031710#else // USE(JSVALUE32_64)
17041711
 1712 JITCompiler::Call callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, JITAddIC* addIC)
 1713 {
 1714 m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), TrustedImmPtr(addIC));
 1715 return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
 1716 }
 1717
17051718 JITCompiler::Call callOperation(J_JITOperation_EJJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, UniquedStringImpl* uid)
17061719 {
17071720 m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2Payload, arg2Tag, TrustedImmPtr(uid));

@@public:
28302843 MinifiedGraph* m_minifiedGraph;
28312844
28322845 Vector<std::unique_ptr<SlowPathGenerator>, 8> m_slowPathGenerators;
2833  Vector<std::pair<std::function<void()>, Node*>, 8> m_slowPathLambdas;
 2846 struct SlowPathLambda {
 2847 std::function<void()> m_generator;
 2848 Node* m_currentNode;
 2849 unsigned m_streamIndex;
 2850 };
 2851 Vector<SlowPathLambda> m_slowPathLambdas;
28342852 Vector<SilentRegisterSavePlan> m_plans;
2835  unsigned m_outOfLineStreamIndex { UINT_MAX };
 2853 Optional<unsigned> m_outOfLineStreamIndex;
28362854};
28372855
28382856
203351

Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

5252#include "FTLThunks.h"
5353#include "FTLWeightedTarget.h"
5454#include "JITAddGenerator.h"
 55#include "JITMathIC.h"
5556#include "JITBitAndGenerator.h"
5657#include "JITBitOrGenerator.h"
5758#include "JITBitXorGenerator.h"

@@private:
15281529
15291530 void compileValueAdd()
15301531 {
1531  emitBinarySnippet<JITAddGenerator>(operationValueAdd);
 1532 emitAddSnippet();
15321533 }
15331534
15341535 void compileStrCat()

@@private:
80588059 setJSValue(patchpoint);
80598060 }
80608061
 8062 void emitAddSnippet()
 8063 {
 8064 Node* node = m_node;
 8065
 8066 LValue left = lowJSValue(node->child1());
 8067 LValue right = lowJSValue(node->child2());
 8068
 8069 SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType());
 8070 SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType());
 8071
 8072 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
 8073 patchpoint->appendSomeRegister(left);
 8074 patchpoint->appendSomeRegister(right);
 8075 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
 8076 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
 8077 RefPtr<PatchpointExceptionHandle> exceptionHandle =
 8078 preparePatchpointForExceptions(patchpoint);
 8079 patchpoint->numGPScratchRegisters = 1;
 8080 patchpoint->numFPScratchRegisters = 2;
 8081 patchpoint->clobber(RegisterSet::macroScratchRegisters());
 8082 State* state = &m_ftlState;
 8083 patchpoint->setGenerator(
 8084 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
 8085 AllowMacroScratchRegisterUsage allowScratch(jit);
 8086
 8087 Box<CCallHelpers::JumpList> exceptions =
 8088 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
 8089
 8090 JITAddIC* addIC = jit.codeBlock()->addJITAddIC();
 8091 Box<MathICGenerationState> addICGenerationState = Box<MathICGenerationState>::create();
 8092 ArithProfile* arithProfile = state->graph.baselineCodeBlockFor(node->origin.semantic)->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
 8093 addIC->m_generator = JITAddGenerator(leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
 8094 JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()), params.fpScratch(0),
 8095 params.fpScratch(1), params.gpScratch(0), InvalidFPRReg, arithProfile);
 8096
 8097 auto start = jit.label();
 8098 bool generatedInline = addIC->generateInline(jit, *addICGenerationState);
 8099
 8100 if (generatedInline) {
 8101 ASSERT(!addICGenerationState->m_slowPathJumps.empty());
 8102 auto done = jit.label();
 8103 params.addLatePath([=] (CCallHelpers& jit) {
 8104 AllowMacroScratchRegisterUsage allowScratch(jit);
 8105 addICGenerationState->m_slowPathJumps.link(&jit);
 8106 addICGenerationState->m_slowPathStart = jit.label();
 8107
 8108 auto start = jit.label();
 8109
 8110 if (addICGenerationState->m_shouldSlowPathRepatch) {
 8111 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(),
 8112 operationValueAddOptimize, params[0].gpr(), params[1].gpr(), params[2].gpr(), CCallHelpers::TrustedImmPtr(addIC));
 8113 addICGenerationState->m_slowPathCall = call.call();
 8114 } else {
 8115 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic,
 8116 exceptions.get(), operationValueAdd, params[0].gpr(), params[1].gpr(), params[2].gpr());
 8117 addICGenerationState->m_slowPathCall = call.call();
 8118 }
 8119 jit.jump().linkTo(done, &jit);
 8120
 8121 auto end = jit.label();
 8122
 8123 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
 8124 addIC->finalizeInlineCode(*addICGenerationState, linkBuffer);
 8125 addIC->m_codeSize += (char*)linkBuffer.locationOf(end).executableAddress() - (char*)linkBuffer.locationOf(start).executableAddress();
 8126 });
 8127 });
 8128 } else {
 8129 callOperation(
 8130 *state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(),
 8131 operationValueAdd, params[0].gpr(), params[1].gpr(), params[2].gpr());
 8132 }
 8133 auto end = jit.label();
 8134 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
 8135 addIC->m_codeSize += (char*)linkBuffer.locationOf(end).executableAddress() - (char*)linkBuffer.locationOf(start).executableAddress();
 8136 });
 8137 });
 8138
 8139 setJSValue(patchpoint);
 8140 }
 8141
80618142 template<typename BinaryBitOpGenerator>
80628143 void emitBinaryBitOpSnippet(J_JITOperation_EJJ slowPathFunction)
80638144 {
203351

Source/JavaScriptCore/jit/CCallHelpers.h

@@public:
826826 addCallArgument(arg6);
827827 }
828828
 829 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5, TrustedImmPtr arg6)
 830 {
 831 resetCallArguments();
 832 addCallArgument(GPRInfo::callFrameRegister);
 833 addCallArgument(arg1);
 834 addCallArgument(arg2);
 835 addCallArgument(arg3);
 836 addCallArgument(arg4);
 837 addCallArgument(arg5);
 838 addCallArgument(arg6);
 839 }
 840
829841 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, GPRReg arg6, TrustedImmPtr arg7)
830842 {
831843 resetCallArguments();

@@public:
20992111 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
21002112 }
21012113
 2114 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImmPtr arg4)
 2115 {
 2116 setupTwoStubArgsGPR<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
 2117 move(arg3, GPRInfo::argumentGPR3);
 2118 move(arg4, GPRInfo::argumentGPR4);
 2119 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
 2120 }
 2121
21022122 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
21032123 {
21042124 setupThreeStubArgsGPR<GPRInfo::argumentGPR1, GPRInfo::argumentGPR4, GPRInfo::argumentGPR5>(arg1, arg4, arg5);

@@public:
22072227 }
22082228#endif
22092229
 2230 void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2)
 2231 {
 2232#if USE(JSVALUE64)
 2233 setupArgumentsWithExecState(arg1.gpr(), arg2.gpr());
 2234#else
 2235 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR());
 2236#endif
 2237 }
 2238
22102239 void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3)
22112240 {
22122241#if USE(JSVALUE64)

@@public:
22152244 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3);
22162245#endif
22172246 }
 2247
 2248 void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3, TrustedImmPtr arg4)
 2249 {
 2250#if USE(JSVALUE64)
 2251 setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), arg3, arg4);
 2252#else
 2253 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3, arg4);
 2254#endif
 2255 }
22182256
22192257 void setupArguments(JSValueRegs arg1)
22202258 {
203351

Source/JavaScriptCore/jit/JIT.h

4141#include "CodeBlock.h"
4242#include "CompactJITCodeMap.h"
4343#include "Interpreter.h"
 44#include "JITMathIC.h"
4445#include "JITDisassembler.h"
4546#include "JITInlineCacheGenerator.h"
4647#include "JSInterfaceJIT.h"
4748#include "Opcode.h"
4849#include "PCToCodeOriginMap.h"
49 #include "ResultType.h"
5050#include "UnusedPointer.h"
5151
5252namespace JSC {

@@namespace JSC {
435435 void compileGetByIdHotPath(const Identifier*);
436436
437437 // Arithmetic opcode helpers
438  void emitSub32Constant(int dst, int op, int32_t constant, ResultType opType);
439438 void emitBinaryDoubleOp(OpcodeID, int dst, int op1, int op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
440439
441440#else // USE(JSVALUE32_64)

@@namespace JSC {
763762#endif
764763 MacroAssembler::Call callOperation(J_JITOperation_EJI, int, GPRReg, UniquedStringImpl*);
765764 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg);
766  MacroAssembler::Call callOperation(J_JITOperation_EJJRp, JSValueRegs, JSValueRegs, JSValueRegs, ResultProfile*);
 765 MacroAssembler::Call callOperation(J_JITOperation_EJJRp, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*);
 766 MacroAssembler::Call callOperation(J_JITOperation_EJJ, JSValueRegs, JSValueRegs, JSValueRegs);
 767 MacroAssembler::Call callOperation(J_JITOperation_EJJRpJaic, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*, JITAddIC*);
 768 MacroAssembler::Call callOperation(J_JITOperation_EJJJaic, JSValueRegs, JSValueRegs, JSValueRegs, JITAddIC*);
767769 MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*);
768770 MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*);
769771 MacroAssembler::Call callOperation(Z_JITOperation_EJOJ, GPRReg, GPRReg, GPRReg);

@@namespace JSC {
953955
954956 PCToCodeOriginMapBuilder m_pcToCodeOriginMapBuilder;
955957
 958 HashMap<Instruction*, JITAddIC*> m_instructionToJITAddIC;
 959 HashMap<Instruction*, MathICGenerationState> m_instructionToJITAddICGenerationState;
 960
956961 bool m_canBeOptimized;
957962 bool m_canBeOptimizedOrInlined;
958963 bool m_shouldEmitProfiling;
203351

Source/JavaScriptCore/jit/JITAddGenerator.cpp

2626#include "config.h"
2727#include "JITAddGenerator.h"
2828
 29#include "ArithProfile.h"
 30#include "JITMathIC.h"
 31#include "LinkBuffer.h"
 32
2933#if ENABLE(JIT)
3034
3135namespace JSC {
3236
33 void JITAddGenerator::generateFastPath(CCallHelpers& jit)
 37#include <stdio.h>
 38#include <sys/types.h>
 39bool JITAddGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state)
 40{
 41 // We default to guessing int32
 42 ObservedType lhs = ObservedType().withInt32();
 43 ObservedType rhs = ObservedType().withInt32();
 44 static double numICs = 0;
 45 static double numInts = 0;
 46 numICs++;
 47 if (m_arithProfile) {
 48 lhs = m_arithProfile->lhsObservedType();
 49 rhs = m_arithProfile->rhsObservedType();
 50 if (lhs.isEmpty() || rhs.isEmpty()) {
 51 lhs = ObservedType().withInt32();
 52 rhs = ObservedType().withInt32();
 53 }
 54 }
 55
 56 if (lhs.isOnlyNonNumber() && rhs.isOnlyNonNumber())
 57 return false;
 58
 59 if ((lhs.isOnlyInt32() || m_leftOperand.isConstInt32()) && (rhs.isOnlyInt32() || m_rightOperand.isConstInt32())) {
 60 state.m_shouldSlowPathRepatch = true;
 61
 62 ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
 63 if (!m_leftOperand.isConstInt32())
 64 state.m_slowPathJumps.append(jit.branchIfNotInt32(m_left));
 65 if (!m_rightOperand.isConstInt32())
 66 state.m_slowPathJumps.append(jit.branchIfNotInt32(m_right));
 67
 68 if (m_leftOperand.isConstInt32() || m_rightOperand.isConstInt32()) {
 69 JSValueRegs var = m_leftOperand.isConstInt32() ? m_right : m_left;
 70 int32_t constValue = m_leftOperand.isConstInt32() ? m_leftOperand.asConstInt32() : m_rightOperand.asConstInt32();
 71 state.m_slowPathJumps.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constValue), m_scratchGPR));
 72 } else
 73 state.m_slowPathJumps.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
 74 jit.boxInt32(m_scratchGPR, m_result);
 75 numInts++;
 76 //dataLog("IC as int percentage: ", numInts/numICs, "\n");
 77 return true;
 78 }
 79
 80 state.m_shouldSlowPathRepatch = false;
 81 MacroAssembler::JumpList endJumpList;
 82 bool result = generateFastPath(jit, endJumpList, state.m_slowPathJumps);
 83 if (result)
 84 endJumpList.link(&jit);
 85 return result;
 86}
 87
 88bool JITAddGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList)
3489{
3590 ASSERT(m_scratchGPR != InvalidGPRReg);
3691 ASSERT(m_scratchGPR != m_left.payloadGPR());

@@void JITAddGenerator::generateFastPath(C
4398
4499 ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
45100
46  if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber()) {
47  ASSERT(!m_didEmitFastPath);
48  return;
49  }
50 
51  m_didEmitFastPath = true;
 101 if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber())
 102 return false;
52103
53104 if (m_leftOperand.isConstInt32() || m_rightOperand.isConstInt32()) {
54105 JSValueRegs var = m_leftOperand.isConstInt32() ? m_right : m_left;

@@void JITAddGenerator::generateFastPath(C
58109 // Try to do intVar + intConstant.
59110 CCallHelpers::Jump notInt32 = jit.branchIfNotInt32(var);
60111
61  m_slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), m_scratchGPR));
 112 slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), m_scratchGPR));
62113
63114 jit.boxInt32(m_scratchGPR, m_result);
64  m_endJumpList.append(jit.jump());
 115 endJumpList.append(jit.jump());
65116
66117 if (!jit.supportsFloatingPoint()) {
67  m_slowPathJumpList.append(notInt32);
68  return;
 118 slowPathJumpList.append(notInt32);
 119 return true;
69120 }
70121
71122 // Try to do doubleVar + double(intConstant).
72123 notInt32.link(&jit);
73124 if (!varOpr.definitelyIsNumber())
74  m_slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR));
 125 slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR));
75126
76127 jit.unboxDoubleNonDestructive(var, m_leftFPR, m_scratchGPR, m_scratchFPR);
77128

@@void JITAddGenerator::generateFastPath(C
89140 leftNotInt = jit.branchIfNotInt32(m_left);
90141 rightNotInt = jit.branchIfNotInt32(m_right);
91142
92  m_slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
 143
 144 slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
93145
94146 jit.boxInt32(m_scratchGPR, m_result);
95  m_endJumpList.append(jit.jump());
 147 endJumpList.append(jit.jump());
 148
96149
97150 if (!jit.supportsFloatingPoint()) {
98  m_slowPathJumpList.append(leftNotInt);
99  m_slowPathJumpList.append(rightNotInt);
100  return;
 151 slowPathJumpList.append(leftNotInt);
 152 slowPathJumpList.append(rightNotInt);
 153 return true;
101154 }
102155
103156 leftNotInt.link(&jit);
104157 if (!m_leftOperand.definitelyIsNumber())
105  m_slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
 158 slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
106159 if (!m_rightOperand.definitelyIsNumber())
107  m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
 160 slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
108161
109162 jit.unboxDoubleNonDestructive(m_left, m_leftFPR, m_scratchGPR, m_scratchFPR);
110163 CCallHelpers::Jump rightIsDouble = jit.branchIfNotInt32(m_right);

@@void JITAddGenerator::generateFastPath(C
114167
115168 rightNotInt.link(&jit);
116169 if (!m_rightOperand.definitelyIsNumber())
117  m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
 170 slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
118171
119172 jit.convertInt32ToDouble(m_left.payloadGPR(), m_leftFPR);
120173

@@void JITAddGenerator::generateFastPath(C
128181
129182 // Do doubleVar + doubleVar.
130183 jit.addDouble(m_rightFPR, m_leftFPR);
131  if (m_resultProfile)
132  m_resultProfile->emitSetDouble(jit);
 184 if (m_arithProfile)
 185 m_arithProfile->emitSetDouble(jit);
133186
134187 jit.boxDouble(m_leftFPR, m_result);
 188
 189 return true;
135190}
136191
137192} // namespace JSC
203351

Source/JavaScriptCore/jit/JITAddGenerator.h

2929#if ENABLE(JIT)
3030
3131#include "CCallHelpers.h"
 32#include "JITOperations.h"
3233#include "SnippetOperand.h"
3334
3435namespace JSC {
3536
 37struct MathICGenerationState;
 38
3639class JITAddGenerator {
3740public:
 41 JITAddGenerator()
 42 { }
 43
3844 JITAddGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
3945 JSValueRegs result, JSValueRegs left, JSValueRegs right,
4046 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
41  ResultProfile* resultProfile = nullptr)
 47 ArithProfile* arithProfile = nullptr)
4248 : m_leftOperand(leftOperand)
4349 , m_rightOperand(rightOperand)
4450 , m_result(result)

@@public:
4854 , m_rightFPR(rightFPR)
4955 , m_scratchGPR(scratchGPR)
5056 , m_scratchFPR(scratchFPR)
51  , m_resultProfile(resultProfile)
 57 , m_arithProfile(arithProfile)
5258 {
5359 ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
5460 }
5561
56  void generateFastPath(CCallHelpers&);
57 
58  bool didEmitFastPath() const { return m_didEmitFastPath; }
59  CCallHelpers::JumpList& endJumpList() { return m_endJumpList; }
60  CCallHelpers::JumpList& slowPathJumpList() { return m_slowPathJumpList; }
 62 bool generateInline(CCallHelpers&, MathICGenerationState&);
 63 bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList);
6164
6265private:
6366 SnippetOperand m_leftOperand;

@@private:
6972 FPRReg m_rightFPR;
7073 GPRReg m_scratchGPR;
7174 FPRReg m_scratchFPR;
72  ResultProfile* m_resultProfile;
73  bool m_didEmitFastPath { false };
74 
75  CCallHelpers::JumpList m_endJumpList;
76  CCallHelpers::JumpList m_slowPathJumpList;
 75 ArithProfile* m_arithProfile;
7776};
7877
7978} // namespace JSC
203351

Source/JavaScriptCore/jit/JITArithmetic.cpp

2828#if ENABLE(JIT)
2929#include "JIT.h"
3030
 31#include "ArithProfile.h"
3132#include "CodeBlock.h"
 33#include "JITMathIC.h"
3234#include "JITAddGenerator.h"
3335#include "JITBitAndGenerator.h"
3436#include "JITBitOrGenerator.h"

4850#include "ResultType.h"
4951#include "SlowPathCall.h"
5052
 53#include "LinkBuffer.h"
5154
5255namespace JSC {
5356

@@void JIT::emitSlow_op_urshift(Instructio
675678 slowPathCall.call();
676679}
677680
 681ALWAYS_INLINE static OperandTypes getOperandTypes(Instruction* instruction)
 682{
 683 return OperandTypes(ArithProfile::fromInt(instruction[4].u.operand).lhsResultType(), ArithProfile::fromInt(instruction[4].u.operand).rhsResultType());
 684}
 685
678686void JIT::emit_op_add(Instruction* currentInstruction)
679687{
680688 int result = currentInstruction[1].u.operand;
681689 int op1 = currentInstruction[2].u.operand;
682690 int op2 = currentInstruction[3].u.operand;
683  OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
684691
685692#if USE(JSVALUE64)
 693 OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
686694 JSValueRegs leftRegs = JSValueRegs(regT0);
687695 JSValueRegs rightRegs = JSValueRegs(regT1);
688696 JSValueRegs resultRegs = leftRegs;
689697 GPRReg scratchGPR = regT2;
690698 FPRReg scratchFPR = InvalidFPRReg;
691699#else
 700 OperandTypes types = getOperandTypes(currentInstruction);
692701 JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
693702 JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
694703 JSValueRegs resultRegs = leftRegs;

@@void JIT::emit_op_add(Instruction* curre
696705 FPRReg scratchFPR = fpRegT2;
697706#endif
698707
699  ResultProfile* resultProfile = nullptr;
 708 ArithProfile* arithProfile = nullptr;
700709 if (shouldEmitProfiling())
701  resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset);
 710 arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction);
702711
703712 SnippetOperand leftOperand(types.first());
704713 SnippetOperand rightOperand(types.second());

@@void JIT::emit_op_add(Instruction* curre
710719
711720 RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
712721
 722 auto start = label();
 723
713724 if (!leftOperand.isConst())
714725 emitGetVirtualRegister(op1, leftRegs);
715726 if (!rightOperand.isConst())
716727 emitGetVirtualRegister(op2, rightRegs);
717728
718  JITAddGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
719  fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
 729 JITAddIC* addIC = m_codeBlock->addJITAddIC();
720730
721  gen.generateFastPath(*this);
 731 m_instructionToJITAddIC.add(currentInstruction, addIC);
 732 MathICGenerationState& addICGenerationState = m_instructionToJITAddICGenerationState.add(currentInstruction, MathICGenerationState()).iterator->value;
722733
723  if (gen.didEmitFastPath()) {
724  gen.endJumpList().link(this);
725  emitPutVirtualRegister(result, resultRegs);
726 
727  addSlowCase(gen.slowPathJumpList());
728  } else {
729  ASSERT(gen.endJumpList().empty());
730  ASSERT(gen.slowPathJumpList().empty());
731  if (resultProfile) {
732  if (leftOperand.isConst())
733  emitGetVirtualRegister(op1, leftRegs);
734  if (rightOperand.isConst())
735  emitGetVirtualRegister(op2, rightRegs);
736  callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
737  emitPutVirtualRegister(result, resultRegs);
738  } else {
739  JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add);
740  slowPathCall.call();
741  }
742  }
 734 addIC->m_generator = JITAddGenerator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
 735
 736 bool generatedInlineCode = addIC->generateInline(*this, addICGenerationState);
 737 if (!generatedInlineCode) {
 738 if (leftOperand.isConst())
 739 emitGetVirtualRegister(op1, leftRegs);
 740 else if (rightOperand.isConst())
 741 emitGetVirtualRegister(op2, rightRegs);
 742
 743 if (arithProfile)
 744 callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, arithProfile);
 745 else
 746 callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
 747 } else
 748 addSlowCase(addICGenerationState.m_slowPathJumps);
 749 emitPutVirtualRegister(result, resultRegs);
 750 auto end = label();
 751 addLinkTask([=] (LinkBuffer& linkBuffer) {
 752 addIC->m_codeSize += (char*)linkBuffer.locationOf(end).executableAddress() - (char*)linkBuffer.locationOf(start).executableAddress();
 753 });
743754}
744755
745756void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
746757{
747758 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
748759
 760 MathICGenerationState& addICGenerationState = m_instructionToJITAddICGenerationState.find(currentInstruction)->value;
 761 addICGenerationState.m_slowPathStart = label();
 762
749763 int result = currentInstruction[1].u.operand;
750764 int op1 = currentInstruction[2].u.operand;
751765 int op2 = currentInstruction[3].u.operand;
752  OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
753766
754767#if USE(JSVALUE64)
 768 OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
755769 JSValueRegs leftRegs = JSValueRegs(regT0);
756770 JSValueRegs rightRegs = JSValueRegs(regT1);
757771 JSValueRegs resultRegs = leftRegs;
758772#else
 773 OperandTypes types = getOperandTypes(currentInstruction);
759774 JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
760775 JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
761776 JSValueRegs resultRegs = leftRegs;

@@void JIT::emitSlow_op_add(Instruction* c
769784 else if (isOperandConstantInt(op2))
770785 rightOperand.setConstInt32(getOperandConstantInt(op2));
771786
 787 auto start = label();
 788
 789 if (leftOperand.isConst())
 790 emitGetVirtualRegister(op1, leftRegs);
 791 if (rightOperand.isConst())
 792 emitGetVirtualRegister(op2, rightRegs);
 793
 794 JITAddIC* addIC = m_instructionToJITAddIC.get(currentInstruction);
772795 if (shouldEmitProfiling()) {
773  if (leftOperand.isConst())
774  emitGetVirtualRegister(op1, leftRegs);
775  if (rightOperand.isConst())
776  emitGetVirtualRegister(op2, rightRegs);
777  ResultProfile* resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset);
778  callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
779  emitPutVirtualRegister(result, resultRegs);
780  } else {
781  JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add);
782  slowPathCall.call();
783  }
 796 ArithProfile& arithProfile = m_codeBlock->arithProfileForPC(currentInstruction);
 797 if (addICGenerationState.m_shouldSlowPathRepatch)
 798 addICGenerationState.m_slowPathCall = callOperation(operationValueAddProfiledOptimize, resultRegs, leftRegs, rightRegs, &arithProfile, addIC);
 799 else
 800 addICGenerationState.m_slowPathCall = callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, &arithProfile);
 801 } else
 802 addICGenerationState.m_slowPathCall = callOperation(operationValueAddOptimize, resultRegs, leftRegs, rightRegs, addIC);
 803 emitPutVirtualRegister(result, resultRegs);
 804 auto end = label();
 805
 806 addLinkTask([=] (LinkBuffer& linkBuffer) {
 807 MathICGenerationState& addICGenerationState = m_instructionToJITAddICGenerationState.find(currentInstruction)->value;
 808 addIC->finalizeInlineCode(addICGenerationState, linkBuffer);
 809 addIC->m_codeSize += (char*)linkBuffer.locationOf(end).executableAddress() - (char*)linkBuffer.locationOf(start).executableAddress();
 810 });
784811}
785812
786813void JIT::emit_op_div(Instruction* currentInstruction)

@@void JIT::emit_op_div(Instruction* curre
788815 int result = currentInstruction[1].u.operand;
789816 int op1 = currentInstruction[2].u.operand;
790817 int op2 = currentInstruction[3].u.operand;
791  OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
792818
793819#if USE(JSVALUE64)
 820 OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
794821 JSValueRegs leftRegs = JSValueRegs(regT0);
795822 JSValueRegs rightRegs = JSValueRegs(regT1);
796823 JSValueRegs resultRegs = leftRegs;
797824 GPRReg scratchGPR = regT2;
798825#else
 826 OperandTypes types = getOperandTypes(currentInstruction);
799827 JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
800828 JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
801829 JSValueRegs resultRegs = leftRegs;

@@void JIT::emit_op_div(Instruction* curre
803831#endif
804832 FPRReg scratchFPR = fpRegT2;
805833
806  ResultProfile* resultProfile = nullptr;
 834 ArithProfile* arithProfile = nullptr;
807835 if (shouldEmitProfiling())
808  resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset);
 836 arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction);
809837
810838 SnippetOperand leftOperand(types.first());
811839 SnippetOperand rightOperand(types.second());

@@void JIT::emit_op_div(Instruction* curre
831859 emitGetVirtualRegister(op2, rightRegs);
832860
833861 JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
834  fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
 862 fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
835863
836864 gen.generateFastPath(*this);
837865

@@void JIT::emit_op_mul(Instruction* curre
861889 int result = currentInstruction[1].u.operand;
862890 int op1 = currentInstruction[2].u.operand;
863891 int op2 = currentInstruction[3].u.operand;
864  OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
865892
866893#if USE(JSVALUE64)
 894 OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
867895 JSValueRegs leftRegs = JSValueRegs(regT0);
868896 JSValueRegs rightRegs = JSValueRegs(regT1);
869897 JSValueRegs resultRegs = JSValueRegs(regT2);
870898 GPRReg scratchGPR = regT3;
871899 FPRReg scratchFPR = InvalidFPRReg;
872900#else
 901 OperandTypes types = getOperandTypes(currentInstruction);
873902 JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
874903 JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
875904 JSValueRegs resultRegs = leftRegs;

@@void JIT::emit_op_mul(Instruction* curre
877906 FPRReg scratchFPR = fpRegT2;
878907#endif
879908
880  ResultProfile* resultProfile = nullptr;
 909 ArithProfile* arithProfile = nullptr;
881910 if (shouldEmitProfiling())
882  resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset);
 911 arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction);
883912
884913 SnippetOperand leftOperand(types.first());
885914 SnippetOperand rightOperand(types.second());

@@void JIT::emit_op_mul(Instruction* curre
897926 emitGetVirtualRegister(op2, rightRegs);
898927
899928 JITMulGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
900  fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
 929 fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
901930
902931 gen.generateFastPath(*this);
903932

@@void JIT::emit_op_mul(Instruction* curre
909938 } else {
910939 ASSERT(gen.endJumpList().empty());
911940 ASSERT(gen.slowPathJumpList().empty());
912  if (resultProfile) {
 941 if (arithProfile) {
913942 if (leftOperand.isPositiveConstInt32())
914943 emitGetVirtualRegister(op1, leftRegs);
915944 if (rightOperand.isPositiveConstInt32())
916945 emitGetVirtualRegister(op2, rightRegs);
917  callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
 946 callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, arithProfile);
918947 emitPutVirtualRegister(result, resultRegs);
919948 } else {
920949 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);

@@void JIT::emitSlow_op_mul(Instruction* c
930959 int result = currentInstruction[1].u.operand;
931960 int op1 = currentInstruction[2].u.operand;
932961 int op2 = currentInstruction[3].u.operand;
933  OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
934962
935963#if USE(JSVALUE64)
 964 OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
936965 JSValueRegs leftRegs = JSValueRegs(regT0);
937966 JSValueRegs rightRegs = JSValueRegs(regT1);
938967 JSValueRegs resultRegs = leftRegs;
939968#else
 969 OperandTypes types = getOperandTypes(currentInstruction);
940970 JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
941971 JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
942972 JSValueRegs resultRegs = leftRegs;

@@void JIT::emitSlow_op_mul(Instruction* c
955985 emitGetVirtualRegister(op1, leftRegs);
956986 if (rightOperand.isPositiveConstInt32())
957987 emitGetVirtualRegister(op2, rightRegs);
958  ResultProfile* resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset);
959  callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
 988 ArithProfile& arithProfile = m_codeBlock->arithProfileForPC(currentInstruction);
 989 callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, &arithProfile);
960990 emitPutVirtualRegister(result, resultRegs);
961991 } else {
962992 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);

@@void JIT::emit_op_sub(Instruction* curre
969999 int result = currentInstruction[1].u.operand;
9701000 int op1 = currentInstruction[2].u.operand;
9711001 int op2 = currentInstruction[3].u.operand;
972  OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
9731002
9741003#if USE(JSVALUE64)
 1004 OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
9751005 JSValueRegs leftRegs = JSValueRegs(regT0);
9761006 JSValueRegs rightRegs = JSValueRegs(regT1);
9771007 JSValueRegs resultRegs = leftRegs;
9781008 GPRReg scratchGPR = regT2;
9791009 FPRReg scratchFPR = InvalidFPRReg;
9801010#else
 1011 OperandTypes types = getOperandTypes(currentInstruction);
9811012 JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
9821013 JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
9831014 JSValueRegs resultRegs = leftRegs;

@@void JIT::emit_op_sub(Instruction* curre
9851016 FPRReg scratchFPR = fpRegT2;
9861017#endif
9871018
988  ResultProfile* resultProfile = nullptr;
 1019 ArithProfile* arithProfile = nullptr;
9891020 if (shouldEmitProfiling())
990  resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset);
 1021 arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction);
9911022
9921023 SnippetOperand leftOperand(types.first());
9931024 SnippetOperand rightOperand(types.second());

@@void JIT::emit_op_sub(Instruction* curre
9961027 emitGetVirtualRegister(op2, rightRegs);
9971028
9981029 JITSubGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
999  fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile);
 1030 fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
10001031
10011032 gen.generateFastPath(*this);
10021033

@@void JIT::emitSlow_op_sub(Instruction* c
10231054#endif
10241055
10251056 if (shouldEmitProfiling()) {
1026  ResultProfile* resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset);
1027  callOperation(operationValueSubProfiled, resultRegs, leftRegs, rightRegs, resultProfile);
 1057 ArithProfile& arithProfile = m_codeBlock->arithProfileForPC(currentInstruction);
 1058 callOperation(operationValueSubProfiled, resultRegs, leftRegs, rightRegs, &arithProfile);
10281059 emitPutVirtualRegister(result, resultRegs);
10291060 } else {
10301061 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub);
203351

Source/JavaScriptCore/jit/JITDivGenerator.cpp

2828
2929#if ENABLE(JIT)
3030
 31#include "ArithProfile.h"
3132#include "JSCJSValueInlines.h"
3233#include "MathCommon.h"
3334

@@void JITDivGenerator::generateFastPath(C
128129
129130 notDoubleZero.link(&jit);
130131#endif
131  if (m_resultProfile)
132  jit.add32(CCallHelpers::TrustedImm32(1), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfSpecialFastPathCount()));
 132 if (m_arithProfile)
 133 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::specialFastPathBit), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
133134 jit.boxDouble(m_leftFPR, m_result);
134135}
135136
203351

Source/JavaScriptCore/jit/JITDivGenerator.h

@@public:
3838 JITDivGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
3939 JSValueRegs result, JSValueRegs left, JSValueRegs right,
4040 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
41  ResultProfile* resultProfile = nullptr)
 41 ArithProfile* arithProfile = nullptr)
4242 : m_leftOperand(leftOperand)
4343 , m_rightOperand(rightOperand)
4444 , m_result(result)

@@public:
4848 , m_rightFPR(rightFPR)
4949 , m_scratchGPR(scratchGPR)
5050 , m_scratchFPR(scratchFPR)
51  , m_resultProfile(resultProfile)
 51 , m_arithProfile(arithProfile)
5252 {
5353 ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
5454 }

@@private:
7171 FPRReg m_rightFPR;
7272 GPRReg m_scratchGPR;
7373 FPRReg m_scratchFPR;
74  ResultProfile* m_resultProfile;
 74 ArithProfile* m_arithProfile;
7575 bool m_didEmitFastPath { false };
7676
7777 CCallHelpers::JumpList m_endJumpList;
203351

Source/JavaScriptCore/jit/JITInlines.h

@@ALWAYS_INLINE MacroAssembler::Call JIT::
416416 return appendCallWithExceptionCheck(operation);
417417}
418418
419 inline MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJRp operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ResultProfile* resultProfile)
 419ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2)
420420{
421  setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(resultProfile));
 421 setupArgumentsWithExecState(arg1, arg2);
 422 Call call = appendCallWithExceptionCheck(operation);
 423 setupResults(result);
 424 return call;
 425}
 426
 427ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJRp operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ArithProfile* arithProfile)
 428{
 429 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arithProfile));
 430 Call call = appendCallWithExceptionCheck(operation);
 431 setupResults(result);
 432 return call;
 433}
 434
 435ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJRpJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ArithProfile* arithProfile, JITAddIC* addIC)
 436{
 437 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arithProfile), TrustedImmPtr(addIC));
 438 Call call = appendCallWithExceptionCheck(operation);
 439 setupResults(result);
 440 return call;
 441}
 442
 443ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, JITAddIC* addIC)
 444{
 445 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(addIC));
422446 Call call = appendCallWithExceptionCheck(operation);
423447 setupResults(result);
424448 return call;
203351

Source/JavaScriptCore/jit/JITMathIC.h

 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#ifndef JITAddIC_h
 27#define JITAddIC_h
 28
 29#if ENABLE(JIT)
 30
 31#include "CCallHelpers.h"
 32#include "JITAddGenerator.h"
 33#include "LinkBuffer.h"
 34#include "Repatch.h"
 35#include "SnippetOperand.h"
 36
 37namespace JSC {
 38
 39class LinkBuffer;
 40
 41struct MathICGenerationState {
 42 MacroAssembler::Label m_fastPathStart;
 43 MacroAssembler::Label m_fastPathEnd;
 44 MacroAssembler::Label m_slowPathStart;
 45 MacroAssembler::Call m_slowPathCall;
 46 MacroAssembler::JumpList m_slowPathJumps;
 47 bool m_shouldSlowPathRepatch;
 48};
 49
 50template <typename GeneratorType>
 51class JITMathIC {
 52public:
 53 CodeLocationLabel doneLocation() { return m_inlineStart.labelAtOffset(m_inlineSize); }
 54 CodeLocationLabel slowPathStartLocation() { return m_inlineStart.labelAtOffset(m_deltaFromStartToSlowPathStart); }
 55 CodeLocationCall slowPathCallLocation() { return m_inlineStart.callAtOffset(m_deltaFromStartToSlowPathCallLocation); }
 56
 57 bool generateInline(CCallHelpers& jit, MathICGenerationState& state)
 58 {
 59 state.m_fastPathStart = jit.label();
 60 bool result = m_generator.generateInline(jit, state);
 61 state.m_fastPathEnd = jit.label();
 62 return result;
 63 }
 64
 65 void generateOutOfLine(VM& vm, CodeBlock* codeBlock, FunctionPtr callReplacement)
 66 {
 67 // We rewire to the alternate regardless of whether or not we can allocate the out of line path
 68 // because if we fail allocating the out of line path, we don't want to try to allocate it
 69 // again. It's not important enough to warrant that.
 70 thunkAwareRepatchCall(codeBlock, slowPathCallLocation(), callReplacement);
 71
 72 {
 73 CCallHelpers jit(&vm, codeBlock);
 74
 75 MacroAssembler::JumpList endJumpList;
 76 MacroAssembler::JumpList slowPathJumpList;
 77 bool emittedFastPath = m_generator.generateFastPath(jit, endJumpList, slowPathJumpList);
 78 if (!emittedFastPath)
 79 return;
 80 endJumpList.append(jit.jump());
 81
 82 LinkBuffer linkBuffer(vm, jit, codeBlock, JITCompilationCanFail);
 83 if (linkBuffer.didFailToAllocate())
 84 return;
 85
 86 linkBuffer.link(endJumpList, doneLocation());
 87 linkBuffer.link(slowPathJumpList, slowPathStartLocation());
 88
 89 m_code = FINALIZE_CODE_FOR(
 90 codeBlock, linkBuffer, ("JITMathIC: generating out of line IC snippet"));
 91 }
 92
 93 {
 94 CCallHelpers jit(&vm, codeBlock);
 95 auto jump = jit.jump();
 96 // We don't need a nop sled here because nobody should be jumping into the middle of an IC.
 97 bool needsBranchCompaction = false;
 98 LinkBuffer linkBuffer(jit, m_inlineStart.dataLocation(), jit.m_assembler.buffer().codeSize(), JITCompilationMustSucceed, needsBranchCompaction);
 99 RELEASE_ASSERT(linkBuffer.isValid());
 100 linkBuffer.link(jump, CodeLocationLabel(m_code.code().executableAddress()));
 101 FINALIZE_CODE(linkBuffer, ("JITMathIC: linking constant jump to out of line jit add generator"));
 102 }
 103 }
 104
 105 void finalizeInlineCode(const MathICGenerationState& state, LinkBuffer& linkBuffer)
 106 {
 107 CodeLocationLabel start = linkBuffer.locationOf(state.m_fastPathStart);
 108 m_inlineStart = start;
 109
 110 int32_t inlineSize = MacroAssembler::differenceBetweenCodePtr(
 111 start, linkBuffer.locationOf(state.m_fastPathEnd));
 112 ASSERT(inlineSize > 0);
 113 m_inlineSize = inlineSize;
 114
 115 m_deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr(
 116 start, linkBuffer.locationOf(state.m_slowPathCall));
 117 m_deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr(
 118 start, linkBuffer.locationOf(state.m_slowPathStart));
 119 }
 120
 121 MacroAssemblerCodeRef m_code;
 122 CodeLocationLabel m_inlineStart;
 123 int32_t m_inlineSize;
 124 int32_t m_deltaFromStartToSlowPathCallLocation;
 125 int32_t m_deltaFromStartToSlowPathStart;
 126
 127 size_t m_codeSize { 0 };
 128
 129 size_t codeSize()
 130 {
 131 return m_codeSize + m_code.size();
 132 }
 133
 134 GeneratorType m_generator;
 135};
 136
 137typedef JITMathIC<JITAddGenerator> JITAddIC;
 138
 139} // namespace JSC
 140
 141#endif // ENABLE(JIT)
 142
 143#endif // JITAddIC_h
0

Source/JavaScriptCore/jit/JITMathICForwards.h

 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#ifndef JITMathICForwards_h
 27#define JITMathICForwards_h
 28
 29#if ENABLE(JIT)
 30
 31namespace JSC {
 32
 33template <typename Generator> class JITMathIC;
 34class JITAddGenerator;
 35
 36typedef JITMathIC<JITAddGenerator> JITAddIC;
 37
 38} // namespace JSC
 39
 40#endif // ENABLE(JIT)
 41
 42#endif // JITMathICForwards_h
0

Source/JavaScriptCore/jit/JITMulGenerator.cpp

2828
2929#if ENABLE(JIT)
3030
 31#include "ArithProfile.h"
 32
3133namespace JSC {
3234
3335void JITMulGenerator::generateFastPath(CCallHelpers& jit)

@@void JITMulGenerator::generateFastPath(C
137139 // Do doubleVar * doubleVar.
138140 jit.mulDouble(m_rightFPR, m_leftFPR);
139141
140  if (!m_resultProfile)
 142 if (!m_arithProfile)
141143 jit.boxDouble(m_leftFPR, m_result);
142144 else {
143145 // The Int52 overflow check below intentionally omits 1ll << 51 as a valid negative Int52 value.

@@void JITMulGenerator::generateFastPath(C
149151 jit.moveDoubleTo64(m_leftFPR, m_result.payloadGPR());
150152 CCallHelpers::Jump notNegativeZero = jit.branch64(CCallHelpers::NotEqual, m_result.payloadGPR(), CCallHelpers::TrustedImm64(negativeZeroBits));
151153
152  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags()));
 154 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
153155 CCallHelpers::Jump done = jit.jump();
154156
155157 notNegativeZero.link(&jit);
156  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags()));
 158 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
157159
158160 jit.move(m_result.payloadGPR(), m_scratchGPR);
159161 jit.urshiftPtr(CCallHelpers::Imm32(52), m_scratchGPR);
160162 jit.and32(CCallHelpers::Imm32(0x7ff), m_scratchGPR);
161163 CCallHelpers::Jump noInt52Overflow = jit.branch32(CCallHelpers::LessThanOrEqual, m_scratchGPR, CCallHelpers::TrustedImm32(0x431));
162164
163  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags()));
 165 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
164166 noInt52Overflow.link(&jit);
165167
166168 done.link(&jit);

@@void JITMulGenerator::generateFastPath(C
171173 notNegativeZero.append(jit.branch32(CCallHelpers::NotEqual, m_result.payloadGPR(), CCallHelpers::TrustedImm32(0)));
172174 notNegativeZero.append(jit.branch32(CCallHelpers::NotEqual, m_result.tagGPR(), CCallHelpers::TrustedImm32(negativeZeroBits >> 32)));
173175
174  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags()));
 176 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
175177 CCallHelpers::Jump done = jit.jump();
176178
177179 notNegativeZero.link(&jit);
178  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags()));
 180 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
179181
180182 jit.move(m_result.tagGPR(), m_scratchGPR);
181183 jit.urshiftPtr(CCallHelpers::Imm32(52 - 32), m_scratchGPR);
182184 jit.and32(CCallHelpers::Imm32(0x7ff), m_scratchGPR);
183185 CCallHelpers::Jump noInt52Overflow = jit.branch32(CCallHelpers::LessThanOrEqual, m_scratchGPR, CCallHelpers::TrustedImm32(0x431));
184186
185  jit.or32(CCallHelpers::TrustedImm32(ResultProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags()));
 187 jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
186188
187189 m_endJumpList.append(noInt52Overflow);
188190 if (m_scratchGPR == m_result.tagGPR() || m_scratchGPR == m_result.payloadGPR())
203351

Source/JavaScriptCore/jit/JITMulGenerator.h

@@public:
3838 JITMulGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
3939 JSValueRegs result, JSValueRegs left, JSValueRegs right,
4040 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
41  ResultProfile* resultProfile = nullptr)
 41 ArithProfile* arithProfile = nullptr)
4242 : m_leftOperand(leftOperand)
4343 , m_rightOperand(rightOperand)
4444 , m_result(result)

@@public:
4848 , m_rightFPR(rightFPR)
4949 , m_scratchGPR(scratchGPR)
5050 , m_scratchFPR(scratchFPR)
51  , m_resultProfile(resultProfile)
 51 , m_arithProfile(arithProfile)
5252 {
5353 ASSERT(!m_leftOperand.isPositiveConstInt32() || !m_rightOperand.isPositiveConstInt32());
5454 }

@@private:
6969 FPRReg m_rightFPR;
7070 GPRReg m_scratchGPR;
7171 FPRReg m_scratchFPR;
72  ResultProfile* m_resultProfile;
 72 ArithProfile* m_arithProfile;
7373 bool m_didEmitFastPath { false };
7474
7575 CCallHelpers::JumpList m_endJumpList;
203351

Source/JavaScriptCore/jit/JITOperations.cpp

2828
2929#if ENABLE(JIT)
3030
 31#include "ArithProfile.h"
3132#include "ArrayConstructor.h"
3233#include "CommonSlowPaths.h"
3334#include "DFGCompilationMode.h"

@@JSCell* JIT_OPERATION operationToIndexSt
22472248 return jsString(exec, Identifier::from(exec, index).string());
22482249}
22492250
 2251ALWAYS_INLINE static EncodedJSValue unprofiledAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 2252{
 2253 VM* vm = &exec->vm();
 2254 NativeCallFrameTracer tracer(vm, exec);
 2255
 2256 exec->codeBlock()->dumpJITAddICStats();
 2257
 2258 JSValue op1 = JSValue::decode(encodedOp1);
 2259 JSValue op2 = JSValue::decode(encodedOp2);
 2260
 2261 return JSValue::encode(jsAdd(exec, op1, op2));
 2262}
 2263
 2264ALWAYS_INLINE static EncodedJSValue profiledAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
 2265{
 2266 VM* vm = &exec->vm();
 2267 NativeCallFrameTracer tracer(vm, exec);
 2268
 2269 JSValue op1 = JSValue::decode(encodedOp1);
 2270 JSValue op2 = JSValue::decode(encodedOp2);
 2271
 2272 ASSERT(arithProfile);
 2273 arithProfile->observeLHSAndRHS(op1, op2);
 2274
 2275 JSValue result = jsAdd(exec, op1, op2);
 2276 arithProfile->detectNumericness(result);
 2277
 2278 exec->codeBlock()->dumpJITAddICStats();
 2279
 2280 return JSValue::encode(result);
 2281}
 2282
22502283EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
22512284{
 2285 return unprofiledAdd(exec, encodedOp1, encodedOp2);
 2286}
 2287
 2288EncodedJSValue JIT_OPERATION operationValueAddNotProfiledNotOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITAddIC*)
 2289{
 2290 return unprofiledAdd(exec, encodedOp1, encodedOp2);
 2291}
 2292
 2293EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
 2294{
 2295 return profiledAdd(exec, encodedOp1, encodedOp2, arithProfile);
 2296}
 2297
 2298EncodedJSValue JIT_OPERATION operationValueAddProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITAddIC* addIC)
 2299{
22522300 VM* vm = &exec->vm();
22532301 NativeCallFrameTracer tracer(vm, exec);
22542302
22552303 JSValue op1 = JSValue::decode(encodedOp1);
22562304 JSValue op2 = JSValue::decode(encodedOp2);
 2305
 2306 ASSERT(arithProfile);
 2307 arithProfile->observeLHSAndRHS(op1, op2);
 2308 auto nonOptimizeVariant = operationValueAddProfiledNonOptimize;
 2309 addIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
 2310
 2311 JSValue result = jsAdd(exec, op1, op2);
 2312 arithProfile->detectNumericness(result);
 2313
 2314 return JSValue::encode(result);
 2315}
 2316
 2317EncodedJSValue JIT_OPERATION operationValueAddProfiledNonOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITAddIC*)
 2318{
 2319 return profiledAdd(exec, encodedOp1, encodedOp2, arithProfile);
 2320}
 2321
 2322EncodedJSValue JIT_OPERATION operationValueAddOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC)
 2323{
 2324 VM* vm = &exec->vm();
 2325 NativeCallFrameTracer tracer(vm, exec);
 2326
 2327 auto nonOptimizeVariant = operationValueAddNonOptimize;
 2328 addIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
 2329
 2330 exec->codeBlock()->dumpJITAddICStats();
22572331
 2332 JSValue op1 = JSValue::decode(encodedOp1);
 2333 JSValue op2 = JSValue::decode(encodedOp2);
22582334 return JSValue::encode(jsAdd(exec, op1, op2));
22592335}
22602336
2261 EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile)
 2337EncodedJSValue JIT_OPERATION operationValueAddNonOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*)
22622338{
22632339 VM* vm = &exec->vm();
22642340 NativeCallFrameTracer tracer(vm, exec);

@@EncodedJSValue JIT_OPERATION operationVa
22662342 JSValue op1 = JSValue::decode(encodedOp1);
22672343 JSValue op2 = JSValue::decode(encodedOp2);
22682344
 2345 exec->codeBlock()->dumpJITAddICStats();
 2346
22692347 JSValue result = jsAdd(exec, op1, op2);
2270  resultProfile->detectNumericness(result);
 2348
22712349 return JSValue::encode(result);
22722350}
22732351

@@EncodedJSValue JIT_OPERATION operationVa
22842362 return JSValue::encode(jsNumber(a * b));
22852363}
22862364
2287 EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile)
 2365EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
22882366{
22892367 VM* vm = &exec->vm();
22902368 NativeCallFrameTracer tracer(vm, exec);

@@EncodedJSValue JIT_OPERATION operationVa
22962374 double b = op2.toNumber(exec);
22972375
22982376 JSValue result = jsNumber(a * b);
2299  resultProfile->detectNumericness(result);
 2377 arithProfile->detectNumericness(result);
23002378 return JSValue::encode(result);
23012379}
23022380

@@EncodedJSValue JIT_OPERATION operationVa
23132391 return JSValue::encode(jsNumber(a - b));
23142392}
23152393
2316 EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile)
 2394EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
23172395{
23182396 VM* vm = &exec->vm();
23192397 NativeCallFrameTracer tracer(vm, exec);

@@EncodedJSValue JIT_OPERATION operationVa
23252403 double b = op2.toNumber(exec);
23262404
23272405 JSValue result = jsNumber(a - b);
2328  resultProfile->detectNumericness(result);
 2406 arithProfile->detectNumericness(result);
23292407 return JSValue::encode(result);
23302408}
23312409
203351

Source/JavaScriptCore/jit/JITOperations.h

@@class ArrayProfile;
4242class CallLinkInfo;
4343class CodeBlock;
4444class ExecState;
 45class JITAddGenerator;
4546class JSArray;
4647class JSFunction;
4748class JSLexicalEnvironment;

@@class WatchpointSet;
5455
5556struct ByValInfo;
5657struct InlineCallFrame;
57 struct ResultProfile;
 58struct ArithProfile;
5859
5960typedef ExecState CallFrame;
6061
 62template <typename GeneratorType> class JITMathIC;
 63typedef JITMathIC<JITAddGenerator> JITAddIC;
 64
6165extern "C" {
6266
6367typedef char* UnusedPtr;

@@typedef char* UnusedPtr;
8185 Icf: InlineCallFrame*
8286 Idc: const Identifier*
8387 J: EncodedJSValue
 88 Jaic: JITAddIC*
8489 Jcp: const JSValue*
8590 Jsc: JSScope*
8691 Jsf: JSFunction*

@@typedef char* UnusedPtr;
9297 Q: int64_t
9398 R: Register
9499 Reo: RegExpObject*
95  Rp: ResultProfile*
 100 Rp: ArithProfile*
96101 S: size_t
97102 Sprt: SlowPathReturnType
98103 Ssi: StructureStubInfo*

@@typedef EncodedJSValue (JIT_OPERATION *J
133138typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, ArrayProfile*);
134139typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, ByValInfo*);
135140typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
136 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJRp)(ExecState*, EncodedJSValue, EncodedJSValue, ResultProfile*);
 141typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJRp)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*);
 142typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJRpJaic)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*, JITAddIC*);
 143typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJJaic)(ExecState*, EncodedJSValue, EncodedJSValue, JITAddIC*);
137144typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t);
138145typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReo)(ExecState*, JSString*, RegExpObject*);
139146typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReoJss)(ExecState*, JSString*, RegExpObject*, JSString*);

@@EncodedJSValue JIT_OPERATION operationNe
408415JSCell* JIT_OPERATION operationToIndexString(ExecState*, int32_t);
409416
410417EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
411 EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL;
 418EncodedJSValue JIT_OPERATION operationValueAddNotProfiledNotOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITAddIC*) WTF_INTERNAL;
 419EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
 420EncodedJSValue JIT_OPERATION operationValueAddProfiledOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITAddIC*) WTF_INTERNAL;
 421EncodedJSValue JIT_OPERATION operationValueAddProfiledNonOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITAddIC*) WTF_INTERNAL;
 422EncodedJSValue JIT_OPERATION operationValueAddOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
 423EncodedJSValue JIT_OPERATION operationValueAddNonOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
412424EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
413 EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL;
 425EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
414426EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
415 EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL;
 427EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
416428
417429void JIT_OPERATION operationProcessTypeProfilerLog(ExecState*) WTF_INTERNAL;
418430void JIT_OPERATION operationProcessShadowChickenLog(ExecState*) WTF_INTERNAL;
203351

Source/JavaScriptCore/jit/JITSubGenerator.cpp

2626#include "config.h"
2727#include "JITSubGenerator.h"
2828
 29#include "ArithProfile.h"
 30
2931#if ENABLE(JIT)
3032
3133namespace JSC {

@@void JITSubGenerator::generateFastPath(C
8385 rightWasInteger.link(&jit);
8486
8587 jit.subDouble(m_rightFPR, m_leftFPR);
86  if (m_resultProfile)
87  m_resultProfile->emitSetDouble(jit);
 88 if (m_arithProfile)
 89 m_arithProfile->emitSetDouble(jit);
8890
8991 jit.boxDouble(m_leftFPR, m_result);
9092}
203351

Source/JavaScriptCore/jit/JITSubGenerator.h

@@public:
3838 JITSubGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
3939 JSValueRegs result, JSValueRegs left, JSValueRegs right,
4040 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
41  ResultProfile* resultProfile = nullptr)
 41 ArithProfile* arithProfile = nullptr)
4242 : m_leftOperand(leftOperand)
4343 , m_rightOperand(rightOperand)
4444 , m_result(result)

@@public:
4848 , m_rightFPR(rightFPR)
4949 , m_scratchGPR(scratchGPR)
5050 , m_scratchFPR(scratchFPR)
51  , m_resultProfile(resultProfile)
 51 , m_arithProfile(arithProfile)
5252 { }
5353
5454 void generateFastPath(CCallHelpers&);

@@private:
6767 FPRReg m_rightFPR;
6868 GPRReg m_scratchGPR;
6969 FPRReg m_scratchFPR;
70  ResultProfile* m_resultProfile;
 70 ArithProfile* m_arithProfile;
7171 bool m_didEmitFastPath { false };
7272
7373 CCallHelpers::JumpList m_endJumpList;
203351

Source/JavaScriptCore/jit/Repatch.cpp

@@static FunctionPtr readCallTarget(CodeBl
7272 return result;
7373}
7474
75 static void repatchCall(CodeBlock* codeBlock, CodeLocationCall call, FunctionPtr newCalleeFunction)
 75void thunkAwareRepatchCall(CodeBlock* codeBlock, CodeLocationCall call, FunctionPtr newCalleeFunction)
7676{
7777#if ENABLE(FTL_JIT)
7878 if (codeBlock->jitType() == JITCode::FTLJIT) {

@@static InlineCacheAction tryCacheGetByID
167167
168168 bool generatedCodeInline = InlineAccess::generateArrayLength(*codeBlock->vm(), stubInfo, jsCast<JSArray*>(baseValue));
169169 if (generatedCodeInline) {
170  repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
 170 thunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
171171 stubInfo.initArrayLength();
172172 return RetryCacheLater;
173173 }

@@static InlineCacheAction tryCacheGetByID
220220 if (generatedCodeInline) {
221221 LOG_IC((ICEvent::GetByIdSelfPatch, structure->classInfo(), propertyName));
222222 structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
223  repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
 223 thunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
224224 stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset());
225225 return RetryCacheLater;
226226 }

@@void repatchGetByID(ExecState* exec, JSV
314314 GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
315315
316316 if (tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo, kind) == GiveUpOnCache)
317  repatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericGetByIdFunction(kind));
 317 thunkAwareRepatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericGetByIdFunction(kind));
318318}
319319
320320static V_JITOperation_ESsiJJI appropriateGenericPutByIdFunction(const PutPropertySlot &slot, PutKind putKind)

@@static InlineCacheAction tryCachePutByID
372372 bool generatedCodeInline = InlineAccess::generateSelfPropertyReplace(vm, stubInfo, structure, slot.cachedOffset());
373373 if (generatedCodeInline) {
374374 LOG_IC((ICEvent::PutByIdSelfPatch, structure->classInfo(), ident));
375  repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingPutByIdFunction(slot, putKind));
 375 thunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingPutByIdFunction(slot, putKind));
376376 stubInfo.initPutByIdReplace(codeBlock, structure, slot.cachedOffset());
377377 return RetryCacheLater;
378378 }

@@void repatchPutByID(ExecState* exec, JSV
468468 GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
469469
470470 if (tryCachePutByID(exec, baseValue, structure, propertyName, slot, stubInfo, putKind) == GiveUpOnCache)
471  repatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericPutByIdFunction(slot, putKind));
 471 thunkAwareRepatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), appropriateGenericPutByIdFunction(slot, putKind));
472472}
473473
474474static InlineCacheAction tryRepatchIn(

@@void repatchIn(
529529{
530530 SuperSamplerScope superSamplerScope(false);
531531 if (tryRepatchIn(exec, base, ident, wasFound, slot, stubInfo) == GiveUpOnCache)
532  repatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), operationIn);
 532 thunkAwareRepatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), operationIn);
533533}
534534
535535static void linkSlowFor(VM*, CallLinkInfo& callLinkInfo, MacroAssemblerCodeRef codeRef)

@@void linkPolymorphicCall(
901901
902902void resetGetByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo, GetByIDKind kind)
903903{
904  repatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
 904 thunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
905905 InlineAccess::rewireStubAsJump(*codeBlock->vm(), stubInfo, stubInfo.slowPathStartLocation());
906906}
907907

@@void resetPutByID(CodeBlock* codeBlock,
920920 optimizedFunction = operationPutByIdDirectNonStrictOptimize;
921921 }
922922
923  repatchCall(codeBlock, stubInfo.slowPathCallLocation(), optimizedFunction);
 923 thunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), optimizedFunction);
924924 InlineAccess::rewireStubAsJump(*codeBlock->vm(), stubInfo, stubInfo.slowPathStartLocation());
925925}
926926
203351

Source/JavaScriptCore/jit/Repatch.h

@@void linkPolymorphicCall(ExecState*, Cal
5454void resetGetByID(CodeBlock*, StructureStubInfo&, GetByIDKind);
5555void resetPutByID(CodeBlock*, StructureStubInfo&);
5656void resetIn(CodeBlock*, StructureStubInfo&);
 57void thunkAwareRepatchCall(CodeBlock*, CodeLocationCall call, FunctionPtr newCalleeFunction);
5758
5859} // namespace JSC
5960
203351

Source/JavaScriptCore/llint/LLIntData.cpp

2626#include "config.h"
2727#include "LLIntData.h"
2828
 29#include "ArithProfile.h"
2930#include "BytecodeConventions.h"
3031#include "CodeBlock.h"
3132#include "CodeType.h"

@@void Data::performAssertions(VM& vm)
223224#endif
224225
225226 ASSERT(StringImpl::s_hashFlag8BitBuffer == 8);
 227
 228 {
 229 uint32_t bits = 0x120000;
 230 UNUSED_PARAM(bits);
 231 ArithProfile arithProfile;
 232 arithProfile.lhsSawInt32();
 233 arithProfile.rhsSawInt32();
 234 ASSERT(arithProfile.bits() == bits);
 235 ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyInt32());
 236 ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyInt32());
 237 }
 238 {
 239 uint32_t bits = 0x220000;
 240 UNUSED_PARAM(bits);
 241 ArithProfile arithProfile;
 242 arithProfile.lhsSawNumber();
 243 arithProfile.rhsSawInt32();
 244 ASSERT(arithProfile.bits() == bits);
 245 ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyNumber());
 246 ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyInt32());
 247 }
 248 {
 249 uint32_t bits = 0x240000;
 250 UNUSED_PARAM(bits);
 251 ArithProfile arithProfile;
 252 arithProfile.lhsSawNumber();
 253 arithProfile.rhsSawNumber();
 254 ASSERT(arithProfile.bits() == bits);
 255 ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyNumber());
 256 ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyNumber());
 257 }
 258 {
 259 uint32_t bits = 0x140000;
 260 UNUSED_PARAM(bits);
 261 ArithProfile arithProfile;
 262 arithProfile.lhsSawInt32();
 263 arithProfile.rhsSawNumber();
 264 ASSERT(arithProfile.bits() == bits);
 265 ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyInt32());
 266 ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyNumber());
 267 }
226268}
227269#if COMPILER(CLANG)
228270#pragma clang diagnostic pop
203351

Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

@@macro binaryOpCustomStore(integerOperati
893893 bqb t1, tagTypeNumber, .op2NotInt
894894 loadisFromInstruction(1, t2)
895895 integerOperationAndStore(t1, t0, .slow, t2)
 896 loadisFromInstruction(4, t1)
 897 ori 0x120000, t1 # Both are ints.
 898 storeisToInstruction(t1, 4)
896899 dispatch(5)
897900
898901.op1NotInt:

@@macro binaryOpCustomStore(integerOperati
902905 btqz t1, tagTypeNumber, .slow
903906 addq tagTypeNumber, t1
904907 fq2d t1, ft1
 908 loadisFromInstruction(4, t2)
 909 ori 0x240000, t2 # Both are doubles.
 910 storeisToInstruction(t2, 4)
905911 jmp .op1NotIntReady
906912.op1NotIntOp2Int:
 913 loadisFromInstruction(4, t2)
 914 ori 0x220000, t2 # First is double, second is int.
 915 storeisToInstruction(t2, 4)
907916 ci2d t1, ft1
908917.op1NotIntReady:
909918 loadisFromInstruction(1, t2)

@@macro binaryOpCustomStore(integerOperati
919928 # First operand is definitely an int, the second is definitely not.
920929 loadisFromInstruction(1, t2)
921930 btqz t1, tagTypeNumber, .slow
 931 loadisFromInstruction(4, t3)
 932 ori 0x140000, t3 # First is int, secoond is double
 933 storeisToInstruction(t3, 4)
922934 ci2d t0, ft0
923935 addq tagTypeNumber, t1
924936 fq2d t1, ft1
203351

Source/JavaScriptCore/llint/LowLevelInterpreter.asm

@@if JSVALUE64
286286 loadp offset * 8[PB, PC, 8], dest
287287 end
288288
 289 macro storeisToInstruction(value, offset)
 290 storei value, offset * 8[PB, PC, 8]
 291 end
 292
289293 macro storepToInstruction(value, offset)
290294 storep value, offset * 8[PB, PC, 8]
291295 end
203351

Source/JavaScriptCore/parser/ResultType.h

@@namespace JSC {
3232 private:
3333 friend struct OperandTypes;
3434
35  typedef char Type;
 35 typedef uint8_t Type;
3636 static const Type TypeInt32 = 1;
37 
38  static const Type TypeMaybeNumber = 0x04;
39  static const Type TypeMaybeString = 0x08;
40  static const Type TypeMaybeNull = 0x10;
41  static const Type TypeMaybeBool = 0x20;
42  static const Type TypeMaybeOther = 0x40;
 37 static const Type TypeMaybeNumber = 0x02;
 38 static const Type TypeMaybeString = 0x04;
 39 static const Type TypeMaybeNull = 0x08;
 40 static const Type TypeMaybeBool = 0x10;
 41 static const Type TypeMaybeOther = 0x20;
4342
4443 static const Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther;
4544
 45 public:
 46 static const int numBitsNeeded = 6;
 47 static_assert((TypeBits & ((1 << numBitsNeeded) - 1)) == TypeBits, "This is necessary for correctness.");
 48
4649 explicit ResultType(Type type)
47  : m_type(type)
 50 : m_bits(type)
4851 {
4952 }
5053
51  public:
5254 bool isInt32() const
5355 {
54  return m_type & TypeInt32;
 56 return m_bits & TypeInt32;
5557 }
5658
5759 bool definitelyIsNumber() const
5860 {
59  return (m_type & TypeBits) == TypeMaybeNumber;
 61 return (m_bits & TypeBits) == TypeMaybeNumber;
6062 }
6163
6264 bool definitelyIsString() const
6365 {
64  return (m_type & TypeBits) == TypeMaybeString;
 66 return (m_bits & TypeBits) == TypeMaybeString;
6567 }
6668
6769 bool definitelyIsBoolean() const
6870 {
69  return (m_type & TypeBits) == TypeMaybeBool;
 71 return (m_bits & TypeBits) == TypeMaybeBool;
7072 }
7173
7274 bool mightBeNumber() const
7375 {
74  return m_type & TypeMaybeNumber;
 76 return m_bits & TypeMaybeNumber;
7577 }
7678
7779 bool isNotNumber() const

@@namespace JSC {
141143 return numberTypeIsInt32();
142144 }
143145
 146 Type bits() const { return m_bits; }
 147
144148 private:
145  Type m_type;
 149 Type m_bits;
146150 };
147151
148152 struct OperandTypes

@@namespace JSC {
152156 // We have to initialize one of the int to ensure that
153157 // the entire struct is initialized.
154158 m_u.i = 0;
155  m_u.rds.first = first.m_type;
156  m_u.rds.second = second.m_type;
 159 m_u.rds.first = first.m_bits;
 160 m_u.rds.second = second.m_bits;
157161 }
158162
159163 union {
203351

Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

2626#include "config.h"
2727#include "CommonSlowPaths.h"
2828
 29#include "ArithProfile.h"
2930#include "ArrayConstructor.h"
3031#include "BuiltinNames.h"
3132#include "CallFrame.h"

5859#include "TypeProfilerLog.h"
5960#include <wtf/StringPrintStream.h>
6061
 62#include "ResultType.h"
 63
6164namespace JSC {
6265
6366#define BEGIN_NO_SET_PC() \

@@SLOW_PATH_DECL(slow_path_negate)
359362}
360363
361364#if ENABLE(DFG_JIT)
362 static void updateResultProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right)
 365static void updateArithProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right)
363366{
364367 CodeBlock* codeBlock = exec->codeBlock();
365  unsigned bytecodeOffset = codeBlock->bytecodeOffset(pc);
366  ResultProfile* profile = codeBlock->ensureResultProfile(bytecodeOffset);
 368 ArithProfile& profile = codeBlock->arithProfileForPC(pc);
367369
368370 if (result.isNumber()) {
369371 if (!result.isInt32()) {
370372 if (left.isInt32() && right.isInt32())
371  profile->setObservedInt32Overflow();
 373 profile.setObservedInt32Overflow();
372374
373375 double doubleVal = result.asNumber();
374376 if (!doubleVal && std::signbit(doubleVal))
375  profile->setObservedNegZeroDouble();
 377 profile.setObservedNegZeroDouble();
376378 else {
377  profile->setObservedNonNegZeroDouble();
 379 profile.setObservedNonNegZeroDouble();
378380
379381 // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value.
380382 // Therefore, we will get a false positive if the result is that value. This is intentionally

@@static void updateResultProfileForBinary
382384 static const int64_t int52OverflowPoint = (1ll << 51);
383385 int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal));
384386 if (int64Val >= int52OverflowPoint)
385  profile->setObservedInt52Overflow();
 387 profile.setObservedInt52Overflow();
386388 }
387389 }
388390 } else
389  profile->setObservedNonNumber();
 391 profile.setObservedNonNumber();
390392}
391393#else
392 static void updateResultProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { }
 394static void updateArithProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { }
393395#endif
394396
395397SLOW_PATH_DECL(slow_path_to_number)

@@SLOW_PATH_DECL(slow_path_add)
407409 JSValue v2 = OP_C(3).jsValue();
408410 JSValue result;
409411
 412 ArithProfile& arithProfile = exec->codeBlock()->arithProfileForPC(pc);
 413 arithProfile.observeLHSAndRHS(v1, v2);
 414
 415 exec->codeBlock()->dumpJITAddICStats();
 416
 417 /*
 418 dataLog("slow_path_add\n");
 419 dataLog("V1: ", runtimeTypeAsString(runtimeTypeForValue(v1)), "\n");
 420 dataLog("V2: ", runtimeTypeAsString(runtimeTypeForValue(v2)), "\n");
 421 dataLog("Stats: ", pc[4].u.operand, "\n");
 422 OperandTypes types = OperandTypes::fromInt(pc[4].u.operand);
 423 ResultType a = types.first();
 424 ResultType b = types.second();
 425 dataLog(*bitwise_cast<uint8_t*>(&a), "\n");
 426 dataLog(*bitwise_cast<uint8_t*>(&b), "\n");
 427 */
 428
 429
410430 if (v1.isString() && !v2.isObject())
411431 result = jsString(exec, asString(v1), v2.toString(exec));
412432 else if (v1.isNumber() && v2.isNumber())

@@SLOW_PATH_DECL(slow_path_add)
415435 result = jsAddSlowCase(exec, v1, v2);
416436
417437 RETURN_WITH_PROFILING(result, {
418  updateResultProfileForBinaryArithOp(exec, pc, result, v1, v2);
 438 updateArithProfileForBinaryArithOp(exec, pc, result, v1, v2);
419439 });
420440}
421441

@@SLOW_PATH_DECL(slow_path_mul)
432452 double b = right.toNumber(exec);
433453 JSValue result = jsNumber(a * b);
434454 RETURN_WITH_PROFILING(result, {
435  updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
 455 updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
436456 });
437457}
438458

@@SLOW_PATH_DECL(slow_path_sub)
445465 double b = right.toNumber(exec);
446466 JSValue result = jsNumber(a - b);
447467 RETURN_WITH_PROFILING(result, {
448  updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
 468 updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
449469 });
450470}
451471

@@SLOW_PATH_DECL(slow_path_div)
458478 double b = right.toNumber(exec);
459479 JSValue result = jsNumber(a / b);
460480 RETURN_WITH_PROFILING(result, {
461  updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
 481 updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
462482 });
463483}
464484
203351

Source/WebCore/ForwardingHeaders/jit/JITMathICForwards.h

 1#ifndef WebCore_FWD_JITMathICForwards_h
 2#define WebCore_FWD_JITMathICForwards_h
 3#include <JavaScriptCore/JITMathICForwards.h>
 4#endif
0