Changeset 200606 in webkit
- Timestamp:
- May 9, 2016 7:01:28 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 17 added
- 42 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r200604 r200606 1 2016-05-09 Filip Pizlo <fpizlo@apple.com> 2 3 Polymorphic operands in operators coerces downstream values to double. 4 https://bugs.webkit.org/show_bug.cgi?id=151793 5 6 Reviewed by Mark Lam. 7 8 * js/regress/object-int-add-array-expected.txt: Added. 9 * js/regress/object-int-add-array.html: Added. 10 * js/regress/object-int-add-expected.txt: Added. 11 * js/regress/object-int-add.html: Added. 12 * js/regress/object-int-mul-array-expected.txt: Added. 13 * js/regress/object-int-mul-array.html: Added. 14 * js/regress/object-int-sub-array-expected.txt: Added. 15 * js/regress/object-int-sub-array.html: Added. 16 * js/regress/object-int-sub-expected.txt: Added. 17 * js/regress/object-int-sub.html: Added. 18 * js/regress/script-tests/object-int-add-array.js: Added. 19 (i.o.valueOf): 20 * js/regress/script-tests/object-int-add.js: Added. 21 (i.o.valueOf): 22 * js/regress/script-tests/object-int-mul-array.js: Added. 23 (i.o.valueOf): 24 * js/regress/script-tests/object-int-sub-array.js: Added. 25 (i.o.valueOf): 26 * js/regress/script-tests/object-int-sub.js: Added. 27 (i.o.valueOf): 28 1 29 2016-05-09 Simon Fraser <simon.fraser@apple.com> 2 30 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r200543 r200606 564 564 jit/ScratchRegisterAllocator.cpp 565 565 jit/SetupVarargsFrame.cpp 566 jit/TagRegistersMode.cpp 566 567 jit/TempRegisterSet.cpp 567 568 jit/ThunkGenerators.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r200597 r200606 1 2016-05-09 Filip Pizlo <fpizlo@apple.com> 2 3 Polymorphic operands in operators coerces downstream values to double. 4 https://bugs.webkit.org/show_bug.cgi?id=151793 5 6 Reviewed by Mark Lam. 7 8 Previously if an object flowed into arithmetic, the prediction propagation phase would either 9 assume that the output of the arithmetic had to be double or sometimes it would assume that it 10 couldn't be double. We want it to only assume that the output is double if it actually had been. 11 12 The first part of this patch is to roll out http://trac.webkit.org/changeset/200502. That removed 13 some of the machinery that we had in place to detect whether the output of an operation is int or 14 double. That changeset claimed that the machinery was "fundamentally broken". It actually wasn't. 15 The reason why it didn't work was that ByteCodeParser was ignoring it if likelyToTakeSlowCase was 16 false. I think this was a complete goof-up: the code in ByteCodeParser::makeSafe was structured 17 in a way that made it non-obvious that the method is a no-op if !likelyToTakeSlowCase. So, this 18 change rolls out r200502 and makes ResultProfile do its job by reshaping how makeSafe processes 19 it. 20 21 This also makes two other changes to shore up ResultProfile: 22 - OSR exit can now refine a ResultProfile the same way that it refines ValueProfile. 23 - Baseline JIT slow paths now set bits in ResultProfile. 24 25 Based on this stuff, the DFG now predicts int/double/string in op_add/op_sub/op_mul based on 26 ResultProfiles. To be conservative, we still only use the ResultProfiles if the incoming 27 prediction is not number-or-boolean. This ensures that we exactly retain our old behavior in 28 those cases for which it was tuned. But I hope to remove this soon. I believe that ResultProfile 29 is already strictly better than what prediction propagation was doing before. 30 31 This can be an enormous win. This patch adds some simple microbenchmarks that demonstrate the 32 problem of assuming that arithmetic on objects returns double. The most extreme of these speeds 33 up 8x with this change (object-int-add-array). 34 35 * CMakeLists.txt: 36 * JavaScriptCore.xcodeproj/project.pbxproj: 37 * bytecode/CodeBlock.h: 38 (JSC::CodeBlock::addFrequentExitSite): 39 (JSC::CodeBlock::hasExitSite): 40 * bytecode/DFGExitProfile.cpp: 41 (JSC::DFG::FrequentExitSite::dump): 42 (JSC::DFG::ExitProfile::ExitProfile): 43 (JSC::DFG::ExitProfile::~ExitProfile): 44 (JSC::DFG::ExitProfile::add): 45 * bytecode/DFGExitProfile.h: 46 (JSC::DFG::FrequentExitSite::isHashTableDeletedValue): 47 * bytecode/MethodOfGettingAValueProfile.cpp: 48 (JSC::MethodOfGettingAValueProfile::fromLazyOperand): 49 (JSC::MethodOfGettingAValueProfile::emitReportValue): 50 (JSC::MethodOfGettingAValueProfile::getSpecFailBucket): Deleted. 51 * bytecode/MethodOfGettingAValueProfile.h: 52 (JSC::MethodOfGettingAValueProfile::MethodOfGettingAValueProfile): 53 (JSC::MethodOfGettingAValueProfile::operator bool): 54 (JSC::MethodOfGettingAValueProfile::operator!): Deleted. 55 * bytecode/PolymorphicAccess.cpp: 56 (JSC::AccessCase::generateImpl): 57 * bytecode/ValueProfile.cpp: 58 (JSC::ResultProfile::emitDetectBitsLight): 59 (JSC::ResultProfile::emitSetDouble): 60 (JSC::ResultProfile::emitSetNonNumber): 61 (WTF::printInternal): 62 * bytecode/ValueProfile.h: 63 (JSC::ResultProfile::ResultProfile): 64 (JSC::ResultProfile::bytecodeOffset): 65 (JSC::ResultProfile::specialFastPathCount): 66 (JSC::ResultProfile::didObserveNonInt32): 67 (JSC::ResultProfile::didObserveDouble): 68 (JSC::ResultProfile::didObserveNonNegZeroDouble): 69 (JSC::ResultProfile::didObserveNegZeroDouble): 70 (JSC::ResultProfile::didObserveNonNumber): 71 (JSC::ResultProfile::didObserveInt32Overflow): 72 (JSC::ResultProfile::didObserveInt52Overflow): 73 (JSC::ResultProfile::setObservedNonNegZeroDouble): 74 (JSC::ResultProfile::setObservedNegZeroDouble): 75 (JSC::ResultProfile::setObservedNonNumber): 76 (JSC::ResultProfile::setObservedInt32Overflow): 77 (JSC::ResultProfile::addressOfFlags): 78 (JSC::ResultProfile::addressOfSpecialFastPathCount): 79 (JSC::ResultProfile::detectBitsLight): 80 (JSC::ResultProfile::hasBits): 81 * dfg/DFGByteCodeParser.cpp: 82 (JSC::DFG::ByteCodeParser::makeSafe): 83 * dfg/DFGFixupPhase.cpp: 84 (JSC::DFG::FixupPhase::fixupNode): 85 * dfg/DFGGraph.cpp: 86 (JSC::DFG::Graph::ensureNaturalLoops): 87 (JSC::DFG::Graph::methodOfGettingAValueProfileFor): 88 (JSC::DFG::Graph::valueProfileFor): Deleted. 89 * dfg/DFGGraph.h: 90 (JSC::DFG::Graph::hasExitSite): 91 (JSC::DFG::Graph::numBlocks): 92 * dfg/DFGNode.h: 93 (JSC::DFG::Node::arithNodeFlags): 94 (JSC::DFG::Node::mayHaveNonIntResult): 95 (JSC::DFG::Node::mayHaveDoubleResult): 96 (JSC::DFG::Node::mayHaveNonNumberResult): 97 (JSC::DFG::Node::hasConstantBuffer): 98 * dfg/DFGNodeFlags.cpp: 99 (JSC::DFG::dumpNodeFlags): 100 * dfg/DFGNodeFlags.h: 101 * dfg/DFGOSRExitCompiler32_64.cpp: 102 (JSC::DFG::OSRExitCompiler::compileExit): 103 * dfg/DFGOSRExitCompiler64.cpp: 104 (JSC::DFG::OSRExitCompiler::compileExit): 105 * dfg/DFGOperations.cpp: 106 * dfg/DFGOperations.h: 107 * dfg/DFGPredictionPropagationPhase.cpp: 108 * dfg/DFGSpeculativeJIT.h: 109 (JSC::DFG::SpeculativeJIT::callOperation): 110 * ftl/FTLOSRExitCompiler.cpp: 111 (JSC::FTL::compileStub): 112 * jit/AssemblyHelpers.h: 113 (JSC::AssemblyHelpers::branchIfEqual): 114 (JSC::AssemblyHelpers::branchIfNotCell): 115 (JSC::AssemblyHelpers::branchIfNotNumber): 116 (JSC::AssemblyHelpers::branchIfNotDoubleKnownNotInt32): 117 (JSC::AssemblyHelpers::branchIfBoolean): 118 (JSC::AssemblyHelpers::branchIfEmpty): 119 (JSC::AssemblyHelpers::branchStructure): 120 * jit/CCallHelpers.h: 121 (JSC::CCallHelpers::CCallHelpers): 122 (JSC::CCallHelpers::setupArguments): 123 (JSC::CCallHelpers::setupArgumentsWithExecState): 124 * jit/IntrinsicEmitter.cpp: 125 (JSC::AccessCase::emitIntrinsicGetter): 126 * jit/JIT.h: 127 * jit/JITAddGenerator.cpp: 128 (JSC::JITAddGenerator::generateFastPath): 129 * jit/JITAddGenerator.h: 130 (JSC::JITAddGenerator::JITAddGenerator): 131 * jit/JITArithmetic.cpp: 132 (JSC::JIT::emit_op_add): 133 (JSC::JIT::emitSlow_op_add): 134 (JSC::JIT::emit_op_div): 135 (JSC::JIT::emit_op_mul): 136 (JSC::JIT::emitSlow_op_mul): 137 (JSC::JIT::emit_op_sub): 138 (JSC::JIT::emitSlow_op_sub): 139 * jit/JITInlines.h: 140 (JSC::JIT::callOperation): 141 (JSC::JIT::callOperationNoExceptionCheck): 142 * jit/JITMulGenerator.cpp: 143 (JSC::JITMulGenerator::generateFastPath): 144 * jit/JITOperations.cpp: 145 * jit/JITOperations.h: 146 * jit/JITSubGenerator.cpp: 147 (JSC::JITSubGenerator::generateFastPath): 148 * jit/JITSubGenerator.h: 149 (JSC::JITSubGenerator::JITSubGenerator): 150 * jit/TagRegistersMode.cpp: Added. 151 (WTF::printInternal): 152 * jit/TagRegistersMode.h: Added. 153 * runtime/CommonSlowPaths.cpp: 154 (JSC::updateResultProfileForBinaryArithOp): 155 1 156 2016-05-09 Keith Miller <keith_miller@apple.com> 2 157 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r200568 r200606 1993 1993 DC2143071CA32E55000A8869 /* ICStats.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2143061CA32E52000A8869 /* ICStats.h */; }; 1994 1994 DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC2143051CA32E52000A8869 /* ICStats.cpp */; }; 1995 DC7997831CDE9FA0004D4A09 /* TagRegistersMode.h in Headers */ = {isa = PBXBuildFile; fileRef = DC7997821CDE9F9E004D4A09 /* TagRegistersMode.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1996 DC7997841CDE9FA2004D4A09 /* TagRegistersMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC7997811CDE9F9E004D4A09 /* TagRegistersMode.cpp */; }; 1995 1997 DCF3D5691CD2946D003D5C65 /* LazyClassStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCF3D5641CD29468003D5C65 /* LazyClassStructure.cpp */; }; 1996 1998 DCF3D56A1CD29470003D5C65 /* LazyClassStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF3D5651CD29468003D5C65 /* LazyClassStructure.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 4205 4207 DC2143051CA32E52000A8869 /* ICStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ICStats.cpp; sourceTree = "<group>"; }; 4206 4208 DC2143061CA32E52000A8869 /* ICStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICStats.h; sourceTree = "<group>"; }; 4209 DC7997811CDE9F9E004D4A09 /* TagRegistersMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TagRegistersMode.cpp; sourceTree = "<group>"; }; 4210 DC7997821CDE9F9E004D4A09 /* TagRegistersMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagRegistersMode.h; sourceTree = "<group>"; }; 4207 4211 DCF3D5641CD29468003D5C65 /* LazyClassStructure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyClassStructure.cpp; sourceTree = "<group>"; }; 4208 4212 DCF3D5651CD29468003D5C65 /* LazyClassStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyClassStructure.h; sourceTree = "<group>"; }; … … 5085 5089 A7386551118697B400540279 /* SpecializedThunkJIT.h */, 5086 5090 A7FF647A18C52E8500B55307 /* SpillRegistersMode.h */, 5091 DC7997811CDE9F9E004D4A09 /* TagRegistersMode.cpp */, 5092 DC7997821CDE9F9E004D4A09 /* TagRegistersMode.h */, 5087 5093 0FC314111814559100033232 /* TempRegisterSet.cpp */, 5088 5094 0F24E54817EE274900ABB217 /* TempRegisterSet.h */, … … 7862 7868 14CA958D16AB50FA00938A06 /* ObjectAllocationProfile.h in Headers */, 7863 7869 DCF3D56C1CD29475003D5C65 /* LazyProperty.h in Headers */, 7870 DC7997831CDE9FA0004D4A09 /* TagRegistersMode.h in Headers */, 7864 7871 BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */, 7865 7872 996B73221BDA08EF00331B84 /* ObjectConstructor.lut.h in Headers */, … … 9017 9024 A57D23E51890CEBF0031C7FA /* InspectorDebuggerAgent.cpp in Sources */, 9018 9025 A532438918568335002ED692 /* InspectorFrontendDispatchers.cpp in Sources */, 9026 DC7997841CDE9FA2004D4A09 /* TagRegistersMode.cpp in Sources */, 9019 9027 99F1A6FE1B8E6D9400463B26 /* InspectorFrontendRouter.cpp in Sources */, 9020 9028 A5339EC71BB399A90054F005 /* InspectorHeapAgent.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r199394 r200606 501 501 ASSERT(JITCode::isBaselineCode(jitType())); 502 502 ConcurrentJITLocker locker(m_lock); 503 return m_exitProfile.add(locker, site);503 return m_exitProfile.add(locker, this, site); 504 504 } 505 505 -
trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp
r185618 r200606 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "CodeBlock.h" 32 31 33 namespace JSC { namespace DFG { 34 35 void FrequentExitSite::dump(PrintStream& out) const 36 { 37 out.print("bc#", m_bytecodeOffset, ": ", m_kind, "/", m_jitType); 38 } 32 39 33 40 ExitProfile::ExitProfile() { } 34 41 ExitProfile::~ExitProfile() { } 35 42 36 bool ExitProfile::add(const ConcurrentJITLocker&, const FrequentExitSite& site)43 bool ExitProfile::add(const ConcurrentJITLocker&, CodeBlock* owner, const FrequentExitSite& site) 37 44 { 38 45 ASSERT(site.jitType() != ExitFromAnything); 46 47 if (Options::verboseExitProfile()) 48 dataLog(pointerDump(owner), ": Adding exit site: ", site, "\n"); 39 49 40 50 // If we've never seen any frequent exits then create the list and put this site -
trunk/Source/JavaScriptCore/bytecode/DFGExitProfile.h
r185618 r200606 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011-2014, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 117 117 return m_kind == ExitKindUnset && m_bytecodeOffset; 118 118 } 119 120 void dump(PrintStream& out) const; 119 121 120 122 private: … … 160 162 // rare to begin with, and implies doing O(n) operations on the CodeBlock 161 163 // anyway. 162 bool add(const ConcurrentJITLocker&, const FrequentExitSite&);164 bool add(const ConcurrentJITLocker&, CodeBlock* owner, const FrequentExitSite&); 163 165 164 166 // Get the frequent exit sites for a bytecode index. This is O(n), and is -
trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp
r163844 r200606 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "CCallHelpers.h" 31 32 #include "CodeBlock.h" 32 33 #include "JSCInlines.h" … … 45 46 } 46 47 47 EncodedJSValue* MethodOfGettingAValueProfile::getSpecFailBucket(unsigned index) const48 void MethodOfGettingAValueProfile::emitReportValue(CCallHelpers& jit, JSValueRegs regs) const 48 49 { 49 50 switch (m_kind) { 50 51 case None: 51 return 0;52 return; 52 53 53 54 case Ready: 54 return u.profile->specFailBucket(index); 55 jit.storeValue(regs, u.profile->specFailBucket(0)); 56 return; 55 57 56 58 case LazyOperand: { … … 60 62 LazyOperandValueProfile* profile = 61 63 u.lazyOperand.codeBlock->lazyOperandValueProfiles().add(locker, key); 62 return profile->specFailBucket(index); 64 jit.storeValue(regs, profile->specFailBucket(0)); 65 return; 63 66 } 64 67 65 default: 66 RELEASE_ASSERT_NOT_REACHED(); 67 return 0; 68 } 68 case ResultProfileReady: { 69 u.resultProfile->emitDetectNumericness(jit, regs, DoNotHaveTagRegisters); 70 return; 71 } } 72 73 RELEASE_ASSERT_NOT_REACHED(); 69 74 } 70 75 -
trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h
r164424 r200606 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 #if ENABLE(DFG_JIT) 34 34 35 #include "GPRInfo.h" 35 36 #include "JSCJSValue.h" 36 37 37 38 namespace JSC { 38 39 40 class CCallHelpers; 39 41 class CodeBlock; 40 42 class LazyOperandValueProfileKey; 43 struct ResultProfile; 41 44 struct ValueProfile; 42 45 … … 48 51 } 49 52 50 explicitMethodOfGettingAValueProfile(ValueProfile* profile)53 MethodOfGettingAValueProfile(ValueProfile* profile) 51 54 { 52 55 if (profile) { … … 57 60 } 58 61 62 MethodOfGettingAValueProfile(ResultProfile* profile) 63 { 64 if (profile) { 65 m_kind = ResultProfileReady; 66 u.resultProfile = profile; 67 } else 68 m_kind = None; 69 } 70 59 71 static MethodOfGettingAValueProfile fromLazyOperand( 60 72 CodeBlock*, const LazyOperandValueProfileKey&); 61 73 62 bool operator!() const { return m_kind == None; }74 explicit operator bool() const { return m_kind != None; } 63 75 64 // This logically has a pointer to a "There exists X such that 65 // ValueProfileBase<X>". But since C++ does not have existential 66 // templates, I cannot return it. So instead, for any methods that 67 // users of this class would like to call, we'll just have to provide 68 // a method here that does it through an indirection. Or we could 69 // possibly just make ValueProfile less template-based. But last I 70 // tried that, it felt more yucky than this class. 71 72 EncodedJSValue* getSpecFailBucket(unsigned index) const; 76 void emitReportValue(CCallHelpers&, JSValueRegs) const; 73 77 74 78 private: … … 76 80 None, 77 81 Ready, 82 ResultProfileReady, 78 83 LazyOperand 79 84 }; … … 82 87 union { 83 88 ValueProfile* profile; 89 ResultProfile* resultProfile; 84 90 struct { 85 91 CodeBlock* codeBlock; -
trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp
r200405 r200606 1147 1147 dataLog("Have type: ", type->descriptor(), "\n"); 1148 1148 state.failAndRepatch.append( 1149 jit.branchIfNotType( 1150 valueRegs, scratchGPR, type->descriptor(), CCallHelpers::HaveTagRegisters)); 1149 jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor())); 1151 1150 } else if (verbose) 1152 1151 dataLog("Don't have type.\n"); … … 1178 1177 dataLog("Have type: ", type->descriptor(), "\n"); 1179 1178 state.failAndRepatch.append( 1180 jit.branchIfNotType( 1181 valueRegs, scratchGPR, type->descriptor(), CCallHelpers::HaveTagRegisters)); 1179 jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor())); 1182 1180 } else if (verbose) 1183 1181 dataLog("Don't have type.\n"); -
trunk/Source/JavaScriptCore/bytecode/ValueProfile.cpp
r200502 r200606 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #include "ValueProfile.h" 28 28 29 #include "CCallHelpers.h" 30 #include "JSCInlines.h" 31 32 namespace JSC { 33 34 void ResultProfile::emitDetectNumericness(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode) 35 { 36 CCallHelpers::Jump isInt32 = jit.branchIfInt32(regs, mode); 37 CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode); 38 // FIXME: We could be more precise here. 39 emitSetDouble(jit); 40 CCallHelpers::Jump done = jit.jump(); 41 notDouble.link(&jit); 42 emitSetNonNumber(jit); 43 done.link(&jit); 44 isInt32.link(&jit); 45 } 46 47 void ResultProfile::emitSetDouble(CCallHelpers& jit) 48 { 49 jit.or32(CCallHelpers::TrustedImm32(ResultProfile::Int32Overflow | ResultProfile::Int52Overflow | ResultProfile::NegZeroDouble | ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfFlags())); 50 } 51 52 void ResultProfile::emitSetNonNumber(CCallHelpers& jit) 53 { 54 jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNumber), CCallHelpers::AbsoluteAddress(addressOfFlags())); 55 } 56 57 } // namespace JSC 58 29 59 namespace WTF { 30 60 … … 35 65 const char* separator = ""; 36 66 37 if ( profile.didObserveNegZeroDouble()) {38 out.print( separator, "NegZeroDouble");67 if (!profile.didObserveNonInt32()) { 68 out.print("Int32"); 39 69 separator = "|"; 70 } else { 71 if (profile.didObserveNegZeroDouble()) { 72 out.print(separator, "NegZeroDouble"); 73 separator = "|"; 74 } 75 if (profile.didObserveNonNegZeroDouble()) { 76 out.print("NonNegZeroDouble"); 77 separator = "|"; 78 } 79 if (profile.didObserveNonNumber()) { 80 out.print("NonNumber"); 81 separator = "|"; 82 } 83 if (profile.didObserveInt32Overflow()) { 84 out.print("Int32Overflow"); 85 separator = "|"; 86 } 87 if (profile.didObserveInt52Overflow()) { 88 out.print("Int52Overflow"); 89 separator = "|"; 90 } 40 91 } 41 if (profile.didObserveNonNumber()) {42 out.print("NonNumber");43 separator = "|";44 }45 if (profile.didObserveInt32Overflow()) {46 out.print("Int32Overflow");47 separator = "|";48 }49 if (profile.didObserveInt52Overflow()) {50 out.print("Int52Overflow");51 separator = "|";52 }53 54 92 if (profile.specialFastPathCount()) { 55 93 out.print(" special fast path: "); -
trunk/Source/JavaScriptCore/bytecode/ValueProfile.h
r200502 r200606 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013Apple Inc. All rights reserved.2 * Copyright (C) 2011-2013, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 35 35 #include "SpeculatedType.h" 36 36 #include "Structure.h" 37 #include "TagRegistersMode.h" 37 38 #include "WriteBarrier.h" 38 39 #include <wtf/PrintStream.h> … … 40 41 41 42 namespace JSC { 43 44 class CCallHelpers; 42 45 43 46 template<unsigned numberOfBucketsArgument> … … 219 222 220 223 enum ObservedResults { 221 NegZeroDouble = 1 << 0, 222 NonNumber = 1 << 1, 223 Int32Overflow = 1 << 2, 224 Int52Overflow = 1 << 3, 224 NonNegZeroDouble = 1 << 0, 225 NegZeroDouble = 1 << 1, 226 NonNumber = 1 << 2, 227 Int32Overflow = 1 << 3, 228 Int52Overflow = 1 << 4, 225 229 }; 226 230 … … 228 232 unsigned specialFastPathCount() const { return m_specialFastPathCount; } 229 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); } 230 237 bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); } 231 238 bool didObserveNonNumber() const { return hasBits(NonNumber); } … … 233 240 bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); } 234 241 242 void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); } 235 243 void setObservedNegZeroDouble() { setBit(NegZeroDouble); } 236 244 void setObservedNonNumber() { setBit(NonNumber); } … … 240 248 void* addressOfFlags() { return &m_bytecodeOffsetAndFlags; } 241 249 void* addressOfSpecialFastPathCount() { return &m_specialFastPathCount; } 250 251 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a 252 // double. Sets NonNumber if it sees a non-number. 253 void emitDetectNumericness(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters); 254 255 void detectNumericness(JSValue value) 256 { 257 if (value.isInt32()) 258 return; 259 if (value.isNumber()) { 260 m_bytecodeOffsetAndFlags |= Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble; 261 return; 262 } 263 m_bytecodeOffsetAndFlags |= NonNumber; 264 } 265 266 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble). 267 void emitSetDouble(CCallHelpers&); 268 269 // Sets NonNumber. 270 void emitSetNonNumber(CCallHelpers&); 242 271 243 272 private: -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r200586 r200606 907 907 return node; 908 908 909 if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) 910 return node; 911 912 switch (node->op()) { 913 case UInt32ToNumber: 914 case ArithAdd: 915 case ArithSub: 916 case ValueAdd: 917 case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double. 918 node->mergeFlags(NodeMayOverflowInt32InBaseline); 919 break; 920 921 case ArithNegate: 922 // Currently we can't tell the difference between a negation overflowing 923 // (i.e. -(1 << 31)) or generating negative zero (i.e. -0). If it took slow 924 // path then we assume that it did both of those things. 925 node->mergeFlags(NodeMayOverflowInt32InBaseline); 926 node->mergeFlags(NodeMayNegZeroInBaseline); 927 break; 928 929 case ArithMul: { 930 ResultProfile& resultProfile = *m_inlineStackTop->m_profiledBlock->resultProfileForBytecodeOffset(m_currentIndex); 931 if (resultProfile.didObserveInt52Overflow()) 932 node->mergeFlags(NodeMayOverflowInt52); 933 if (resultProfile.didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) 909 ResultProfile* resultProfile = m_inlineStackTop->m_profiledBlock->resultProfileForBytecodeOffset(m_currentIndex); 910 if (resultProfile) { 911 switch (node->op()) { 912 case ArithAdd: 913 case ArithSub: 914 case ValueAdd: 915 if (resultProfile->didObserveDouble()) 916 node->mergeFlags(NodeMayHaveDoubleResult); 917 if (resultProfile->didObserveNonNumber()) 918 node->mergeFlags(NodeMayHaveNonNumberResult); 919 break; 920 921 case ArithMul: { 922 if (resultProfile->didObserveInt52Overflow()) 923 node->mergeFlags(NodeMayOverflowInt52); 924 if (resultProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) 925 node->mergeFlags(NodeMayOverflowInt32InBaseline); 926 if (resultProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) 927 node->mergeFlags(NodeMayNegZeroInBaseline); 928 if (resultProfile->didObserveDouble()) 929 node->mergeFlags(NodeMayHaveDoubleResult); 930 if (resultProfile->didObserveNonNumber()) 931 node->mergeFlags(NodeMayHaveNonNumberResult); 932 break; 933 } 934 935 default: 936 break; 937 } 938 } 939 940 if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) { 941 switch (node->op()) { 942 case UInt32ToNumber: 943 case ArithAdd: 944 case ArithSub: 945 case ValueAdd: 946 case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double. 934 947 node->mergeFlags(NodeMayOverflowInt32InBaseline); 935 if (resultProfile.didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) 948 break; 949 950 case ArithNegate: 951 // Currently we can't tell the difference between a negation overflowing 952 // (i.e. -(1 << 31)) or generating negative zero (i.e. -0). If it took slow 953 // path then we assume that it did both of those things. 954 node->mergeFlags(NodeMayOverflowInt32InBaseline); 936 955 node->mergeFlags(NodeMayNegZeroInBaseline); 937 break; 938 } 939 940 default: 941 RELEASE_ASSERT_NOT_REACHED(); 942 break; 956 break; 957 958 default: 959 break; 960 } 943 961 } 944 962 -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r200586 r200606 193 193 case ArithSub: { 194 194 if (op == ArithSub 195 && Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node()) 196 && m_graph.hasExitSite(node->origin.semantic, BadType)) { 197 195 && Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) { 198 196 fixEdge<UntypedUse>(node->child1()); 199 197 fixEdge<UntypedUse>(node->child2()); … … 237 235 Edge& leftChild = node->child1(); 238 236 Edge& rightChild = node->child2(); 239 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node()) 240 && m_graph.hasExitSite(node->origin.semantic, BadType)) { 237 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) { 241 238 fixEdge<UntypedUse>(leftChild); 242 239 fixEdge<UntypedUse>(rightChild); -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r200117 r200606 1447 1447 } 1448 1448 1449 ValueProfile* Graph::valueProfileFor(Node* node)1450 {1451 if (!node)1452 return nullptr;1453 1454 CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic);1455 1456 if (node->hasLocal(*this)) {1457 if (!node->local().isArgument())1458 return nullptr;1459 int argument = node->local().toArgument();1460 Node* argumentNode = m_arguments[argument];1461 if (!argumentNode)1462 return nullptr;1463 if (node->variableAccessData() != argumentNode->variableAccessData())1464 return nullptr;1465 return profiledBlock->valueProfileForArgument(argument);1466 }1467 1468 if (node->hasHeapPrediction())1469 return profiledBlock->valueProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);1470 1471 return nullptr;1472 }1473 1474 1449 MethodOfGettingAValueProfile Graph::methodOfGettingAValueProfileFor(Node* node) 1475 1450 { 1476 if (!node) 1477 return MethodOfGettingAValueProfile(); 1478 1479 if (ValueProfile* valueProfile = valueProfileFor(node)) 1480 return MethodOfGettingAValueProfile(valueProfile); 1481 1482 if (node->op() == GetLocal) { 1451 while (node) { 1483 1452 CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic); 1484 1453 1485 return MethodOfGettingAValueProfile::fromLazyOperand( 1486 profiledBlock, 1487 LazyOperandValueProfileKey( 1488 node->origin.semantic.bytecodeIndex, node->local())); 1454 if (node->hasLocal(*this)) { 1455 ValueProfile* result = [&] () -> ValueProfile* { 1456 if (!node->local().isArgument()) 1457 return nullptr; 1458 int argument = node->local().toArgument(); 1459 Node* argumentNode = m_arguments[argument]; 1460 if (!argumentNode) 1461 return nullptr; 1462 if (node->variableAccessData() != argumentNode->variableAccessData()) 1463 return nullptr; 1464 return profiledBlock->valueProfileForArgument(argument); 1465 }(); 1466 if (result) 1467 return result; 1468 1469 if (node->op() == GetLocal) { 1470 return MethodOfGettingAValueProfile::fromLazyOperand( 1471 profiledBlock, 1472 LazyOperandValueProfileKey( 1473 node->origin.semantic.bytecodeIndex, node->local())); 1474 } 1475 } 1476 1477 if (node->hasHeapPrediction()) 1478 return profiledBlock->valueProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex); 1479 1480 if (ResultProfile* result = profiledBlock->resultProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex)) 1481 return result; 1482 1483 switch (node->op()) { 1484 case Identity: 1485 case ValueRep: 1486 case DoubleRep: 1487 case Int52Rep: 1488 node = node->child1().node(); 1489 break; 1490 default: 1491 node = nullptr; 1492 } 1489 1493 } 1490 1494 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r200117 r200606 401 401 } 402 402 403 ValueProfile* valueProfileFor(Node*);404 403 MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node*); 405 404 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r200586 r200606 951 951 return result; 952 952 return result & ~NodeBytecodeNeedsNegZero; 953 } 954 955 bool mayHaveNonIntResult() 956 { 957 return m_flags & NodeMayHaveNonIntResult; 958 } 959 960 bool mayHaveDoubleResult() 961 { 962 return m_flags & NodeMayHaveDoubleResult; 963 } 964 965 bool mayHaveNonNumberResult() 966 { 967 return m_flags & NodeMayHaveNonNumberResult; 953 968 } 954 969 -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
r200502 r200606 86 86 } 87 87 88 if (flags & NodeMayHaveDoubleResult) 89 out.print(comma, "MayHaveDoubleResult"); 90 91 if (flags & NodeMayHaveNonNumberResult) 92 out.print(comma, "MayHaveNonNumberResult"); 93 88 94 if (flags & NodeMayOverflowInt52) 89 95 out.print(comma, "MayOverflowInt52"); -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h
r200502 r200606 49 49 50 50 #define NodeBehaviorMask 0x07e0 51 #define NodeMayHaveDoubleResult 0x0020 51 52 #define NodeMayOverflowInt52 0x0040 52 53 #define NodeMayOverflowInt32InBaseline 0x0080 … … 54 55 #define NodeMayNegZeroInBaseline 0x0200 55 56 #define NodeMayNegZeroInDFG 0x0400 57 #define NodeMayHaveNonNumberResult 0x0800 58 #define NodeMayHaveNonIntResult (NodeMayHaveDoubleResult | NodeMayHaveNonNumberResult) 56 59 57 #define NodeBytecodeBackPropMask 0xf80058 #define NodeBytecodeUseBottom 0x000059 #define NodeBytecodeUsesAsNumber 0x0800 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.60 #define NodeBytecodeNeedsNegZero 0x1000 // The result of this computation may be used in a context that observes -0.61 #define NodeBytecodeUsesAsOther 0x2000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).62 #define NodeBytecodeUsesAsValue 63 #define NodeBytecodeUsesAsInt 0x4000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.64 #define NodeBytecodeUsesAsArrayIndex 0x8000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible.60 #define NodeBytecodeBackPropMask 0x1f000 61 #define NodeBytecodeUseBottom 0x00000 62 #define NodeBytecodeUsesAsNumber 0x01000 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results. 63 #define NodeBytecodeNeedsNegZero 0x02000 // The result of this computation may be used in a context that observes -0. 64 #define NodeBytecodeUsesAsOther 0x04000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined). 65 #define NodeBytecodeUsesAsValue (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther) 66 #define NodeBytecodeUsesAsInt 0x08000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values. 67 #define NodeBytecodeUsesAsArrayIndex 0x10000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible. 65 68 66 69 #define NodeArithFlagsMask (NodeBehaviorMask | NodeBytecodeBackPropMask) 67 70 68 #define NodeIsFlushed 0x 10000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush.71 #define NodeIsFlushed 0x20000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush. 69 72 70 #define NodeMiscFlag1 0x20000 71 #define NodeMiscFlag2 0x40000 72 #define NodeMiscFlag3 0x80000 73 #define NodeMiscFlag1 0x40000 74 #define NodeMiscFlag2 0x80000 73 75 74 76 typedef uint32_t NodeFlags; -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
r199792 r200606 1 1 /* 2 * Copyright (C) 2011, 2013-201 5Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 129 129 } 130 130 131 if (!!exit.m_valueProfile) { 132 EncodedJSValue* bucket = exit.m_valueProfile.getSpecFailBucket(0); 133 131 if (MethodOfGettingAValueProfile profile = exit.m_valueProfile) { 134 132 if (exit.m_jsValueSource.isAddress()) { 135 133 // Save a register so we can use it. 136 GPRReg scratch = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base()); 137 138 m_jit.push(scratch); 139 140 m_jit.load32(exit.m_jsValueSource.asAddress(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), scratch); 141 m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag); 142 m_jit.load32(exit.m_jsValueSource.asAddress(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), scratch); 143 m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload); 144 145 m_jit.pop(scratch); 134 GPRReg scratchPayload = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base()); 135 GPRReg scratchTag = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base(), scratchPayload); 136 m_jit.pushToSave(scratchPayload); 137 m_jit.pushToSave(scratchTag); 138 139 JSValueRegs scratch(scratchTag, scratchPayload); 140 141 m_jit.loadValue(exit.m_jsValueSource.asAddress(), scratch); 142 profile.emitReportValue(m_jit, scratch); 143 144 m_jit.popToRestore(scratchTag); 145 m_jit.popToRestore(scratchPayload); 146 146 } else if (exit.m_jsValueSource.hasKnownTag()) { 147 m_jit.store32(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag); 148 m_jit.store32(exit.m_jsValueSource.payloadGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload); 149 } else { 150 m_jit.store32(exit.m_jsValueSource.tagGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag); 151 m_jit.store32(exit.m_jsValueSource.payloadGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload); 152 } 147 GPRReg scratchTag = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.payloadGPR()); 148 m_jit.pushToSave(scratchTag); 149 m_jit.move(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), scratchTag); 150 JSValueRegs value(scratchTag, exit.m_jsValueSource.payloadGPR()); 151 profile.emitReportValue(m_jit, value); 152 m_jit.popToRestore(scratchTag); 153 } else 154 profile.emitReportValue(m_jit, exit.m_jsValueSource.regs()); 153 155 } 154 156 } -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
r199792 r200606 1 1 /* 2 * Copyright (C) 2011, 2013-201 5Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 135 135 } 136 136 137 if (!!exit.m_valueProfile) { 138 EncodedJSValue* bucket = exit.m_valueProfile.getSpecFailBucket(0); 139 137 if (MethodOfGettingAValueProfile profile = exit.m_valueProfile) { 140 138 if (exit.m_jsValueSource.isAddress()) { 141 139 // We can't be sure that we have a spare register. So use the tagTypeNumberRegister, 142 140 // since we know how to restore it. 143 141 m_jit.load64(AssemblyHelpers::Address(exit.m_jsValueSource.asAddress()), GPRInfo::tagTypeNumberRegister); 144 m_jit.store64(GPRInfo::tagTypeNumberRegister, bucket);142 profile.emitReportValue(m_jit, JSValueRegs(GPRInfo::tagTypeNumberRegister)); 145 143 m_jit.move(AssemblyHelpers::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister); 146 144 } else 147 m_jit.store64(exit.m_jsValueSource.gpr(), bucket);145 profile.emitReportValue(m_jit, JSValueRegs(exit.m_jsValueSource.gpr())); 148 146 } 149 147 } -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r200586 r200606 279 279 } 280 280 281 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)282 {283 VM* vm = &exec->vm();284 NativeCallFrameTracer tracer(vm, exec);285 286 JSValue op1 = JSValue::decode(encodedOp1);287 JSValue op2 = JSValue::decode(encodedOp2);288 289 return JSValue::encode(jsAdd(exec, op1, op2));290 }291 292 281 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 293 282 { … … 317 306 double b = op2.toNumber(exec); 318 307 return JSValue::encode(jsNumber(a / b)); 319 }320 321 EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)322 {323 VM* vm = &exec->vm();324 NativeCallFrameTracer tracer(vm, exec);325 326 JSValue op1 = JSValue::decode(encodedOp1);327 JSValue op2 = JSValue::decode(encodedOp2);328 329 double a = op1.toNumber(exec);330 double b = op2.toNumber(exec);331 return JSValue::encode(jsNumber(a * b));332 }333 334 EncodedJSValue JIT_OPERATION operationValueSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)335 {336 VM* vm = &exec->vm();337 NativeCallFrameTracer tracer(vm, exec);338 339 JSValue op1 = JSValue::decode(encodedOp1);340 JSValue op2 = JSValue::decode(encodedOp2);341 342 double a = op1.toNumber(exec);343 double b = op2.toNumber(exec);344 return JSValue::encode(jsNumber(a - b));345 308 } 346 309 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r200586 r200606 52 52 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 53 53 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 54 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;55 54 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 56 55 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 57 EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;58 EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;59 56 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL; 60 57 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r200586 r200606 192 192 else 193 193 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 194 } else if ( 195 !(left & (SpecFullNumber | SpecBoolean)) 196 || !(right & (SpecFullNumber | SpecBoolean))) { 194 } else if (isStringOrStringObjectSpeculation(left) && isStringOrStringObjectSpeculation(right)) { 197 195 // left or right is definitely something other than a number. 198 196 changed |= mergePrediction(SpecString); 199 } else 200 changed |= mergePrediction(SpecString | SpecInt32Only | SpecBytecodeDouble); 197 } else { 198 changed |= mergePrediction(SpecInt32Only); 199 if (node->mayHaveDoubleResult()) 200 changed |= mergePrediction(SpecBytecodeDouble); 201 if (node->mayHaveNonNumberResult()) 202 changed |= mergePrediction(SpecString); 203 } 201 204 } 202 205 break; … … 212 215 else if (m_graph.addShouldSpeculateAnyInt(node)) 213 216 changed |= mergePrediction(SpecInt52Only); 217 else if (isFullNumberOrBooleanSpeculation(left) && isFullNumberOrBooleanSpeculation(right)) 218 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 219 else if (node->mayHaveNonIntResult() || (left & SpecBytecodeDouble) || (right & SpecBytecodeDouble)) 220 changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble); 214 221 else 215 changed |= mergePrediction( speculatedDoubleTypeForPredictions(left, right));222 changed |= mergePrediction(SpecInt32Only); 216 223 } 217 224 break; … … 231 238 else 232 239 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 233 } else 240 } else if (node->mayHaveNonIntResult() || (left & SpecBytecodeDouble) || (right & SpecBytecodeDouble)) 234 241 changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble); 242 else 243 changed |= mergePrediction(SpecInt32Only); 235 244 } 236 245 break; … … 268 277 269 278 if (left && right) { 279 // FIXME: We're currently relying on prediction propagation and backwards propagation 280 // whenever we can, and only falling back on result flags if that fails. And the result 281 // flags logic doesn't know how to use backwards propagation. We should get rid of the 282 // prediction propagation logic and rely solely on the result type. 270 283 if (isFullNumberOrBooleanSpeculationExpectingDefined(left) 271 284 && isFullNumberOrBooleanSpeculationExpectingDefined(right)) { … … 276 289 else 277 290 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 278 } else 279 changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble); 291 } else { 292 if (node->mayHaveNonIntResult() 293 || (left & SpecBytecodeDouble) 294 || (right & SpecBytecodeDouble)) 295 changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble); 296 else 297 changed |= mergePrediction(SpecInt32Only); 298 } 280 299 } 281 300 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r200586 r200606 1688 1688 #else // USE(JSVALUE32_64) 1689 1689 1690 // EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned on an even-numbered register (r0, r2 or [sp]).1691 // To prevent the assembler from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary.1692 #if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS)1693 #define EABI_32BIT_DUMMY_ARG TrustedImm32(0),1694 #else1695 #define EABI_32BIT_DUMMY_ARG1696 #endif1697 1698 // JSVALUE32_64 is a 64-bit integer that cannot be put half in an argument register and half on stack when using SH4 architecture.1699 // To avoid this, let's occupy the 4th argument register (r7) with a dummy argument when necessary. This must only be done when there1700 // is no other 32-bit value argument behind this 64-bit JSValue.1701 #if CPU(SH4)1702 #define SH4_32BIT_DUMMY_ARG TrustedImm32(0),1703 #else1704 #define SH4_32BIT_DUMMY_ARG1705 #endif1706 1707 1690 JITCompiler::Call callOperation(J_JITOperation_EJJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, UniquedStringImpl* uid) 1708 1691 { … … 2145 2128 return appendCall(operation); 2146 2129 } 2147 #undef EABI_32BIT_DUMMY_ARG2148 #undef SH4_32BIT_DUMMY_ARG2149 2130 2150 2131 template<typename FunctionType> -
trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
r198364 r200606 1 1 /* 2 * Copyright (C) 2013-201 5Apple Inc. All rights reserved.2 * Copyright (C) 2013-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 285 285 } 286 286 287 if ( !!exit.m_descriptor->m_valueProfile)288 jit.store64(GPRInfo::regT0, exit.m_descriptor->m_valueProfile.getSpecFailBucket(0));287 if (exit.m_descriptor->m_valueProfile) 288 exit.m_descriptor->m_valueProfile.emitReportValue(jit, JSValueRegs(GPRInfo::regT0)); 289 289 } 290 290 -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r199946 r200606 654 654 } 655 655 656 enum TagRegistersMode {657 DoNotHaveTagRegisters,658 HaveTagRegisters659 };660 661 656 Jump branchIfNotCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters) 662 657 { … … 781 776 add32(TrustedImm32(1), regs.tagGPR(), tempGPR); 782 777 return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1)); 778 #endif 779 } 780 781 Jump branchIfNotDoubleKnownNotInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters) 782 { 783 #if USE(JSVALUE64) 784 if (mode == HaveTagRegisters) 785 return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister); 786 return branchTest64(Zero, regs.gpr(), TrustedImm64(TagTypeNumber)); 787 #else 788 UNUSED_PARAM(mode); 789 return branch32(AboveOrEqual, regs.tagGPR(), TrustedImm32(JSValue::LowestTag)); 783 790 #endif 784 791 } … … 849 856 850 857 JumpList branchIfNotType( 851 JSValueRegs, GPRReg tempGPR, const InferredType::Descriptor&, TagRegistersMode); 858 JSValueRegs, GPRReg tempGPR, const InferredType::Descriptor&, 859 TagRegistersMode = HaveTagRegisters); 852 860 853 861 template<typename T> -
trunk/Source/JavaScriptCore/jit/CCallHelpers.h
r200586 r200606 40 40 #else 41 41 #define POKE_ARGUMENT_OFFSET 0 42 #endif 43 44 // EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]). 45 // To avoid assemblies from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary. 46 #if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS) 47 #define EABI_32BIT_DUMMY_ARG TrustedImm32(0), 48 #else 49 #define EABI_32BIT_DUMMY_ARG 50 #endif 51 52 // JSVALUE32_64 is a 64-bit integer that cannot be put half in an argument register and half on stack when using SH4 architecture. 53 // To avoid this, let's occupy the 4th argument register (r7) with a dummy argument when necessary. This must only be done when there 54 // is no other 32-bit value argument behind this 64-bit JSValue. 55 #if CPU(SH4) 56 #define SH4_32BIT_DUMMY_ARG TrustedImm32(0), 57 #else 58 #define SH4_32BIT_DUMMY_ARG 42 59 #endif 43 60 … … 2168 2185 #endif 2169 2186 2187 void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3) 2188 { 2189 #if USE(JSVALUE64) 2190 setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), arg3); 2191 #else 2192 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3); 2193 #endif 2194 } 2195 2170 2196 void setupArguments(JSValueRegs arg1) 2171 2197 { -
trunk/Source/JavaScriptCore/jit/GPRInfo.h
r200586 r200606 1 1 /* 2 * Copyright (C) 2011, 2013-201 5Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 140 140 } 141 141 142 JSValueRegs regs() const 143 { 144 return JSValueRegs(gpr()); 145 } 146 142 147 MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); } 143 148 … … 305 310 { 306 311 return static_cast<int32_t>(m_tagType); 312 } 313 314 JSValueRegs regs() const 315 { 316 return JSValueRegs(tagGPR(), payloadGPR()); 307 317 } 308 318 -
trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp
r199303 r200606 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 79 79 case TypedArrayLengthIntrinsic: { 80 80 jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR); 81 jit.boxInt32(valueGPR, valueRegs , CCallHelpers::DoNotHaveTagRegisters);81 jit.boxInt32(valueGPR, valueRegs); 82 82 state.succeed(); 83 83 return; … … 94 94 } 95 95 96 jit.boxInt32(valueGPR, valueRegs , CCallHelpers::DoNotHaveTagRegisters);96 jit.boxInt32(valueGPR, valueRegs); 97 97 state.succeed(); 98 98 return; … … 120 120 done.link(&jit); 121 121 122 jit.boxInt32(valueGPR, valueRegs , CCallHelpers::DoNotHaveTagRegisters);122 jit.boxInt32(valueGPR, valueRegs); 123 123 state.succeed(); 124 124 return; -
trunk/Source/JavaScriptCore/jit/JIT.h
r200586 r200606 757 757 MacroAssembler::Call callOperation(J_JITOperation_EJI, int, GPRReg, UniquedStringImpl*); 758 758 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg); 759 MacroAssembler::Call callOperation(J_JITOperation_EJJRp, JSValueRegs, JSValueRegs, JSValueRegs, ResultProfile*); 759 760 MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*); 760 761 MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*); -
trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp
r192842 r200606 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 129 129 // Do doubleVar + doubleVar. 130 130 jit.addDouble(m_rightFPR, m_leftFPR); 131 if (m_resultProfile) 132 m_resultProfile->emitSetDouble(jit); 133 131 134 jit.boxDouble(m_leftFPR, m_result); 132 135 } -
trunk/Source/JavaScriptCore/jit/JITAddGenerator.h
r192842 r200606 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 38 38 JITAddGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand, 39 39 JSValueRegs result, JSValueRegs left, JSValueRegs right, 40 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR) 40 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR, 41 ResultProfile* resultProfile = nullptr) 41 42 : m_leftOperand(leftOperand) 42 43 , m_rightOperand(rightOperand) … … 48 49 , m_scratchGPR(scratchGPR) 49 50 , m_scratchFPR(scratchFPR) 51 , m_resultProfile(resultProfile) 50 52 { 51 53 ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32()); … … 68 70 GPRReg m_scratchGPR; 69 71 FPRReg m_scratchFPR; 72 ResultProfile* m_resultProfile; 70 73 bool m_didEmitFastPath { false }; 71 74 -
trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp
r198364 r200606 1 1 /* 2 * Copyright (C) 2008, 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 697 697 #endif 698 698 699 ResultProfile* resultProfile = nullptr; 700 if (shouldEmitProfiling()) 701 resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset); 702 699 703 SnippetOperand leftOperand(types.first()); 700 704 SnippetOperand rightOperand(types.second()); … … 713 717 714 718 JITAddGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, 715 fpRegT0, fpRegT1, scratchGPR, scratchFPR );719 fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile); 716 720 717 721 gen.generateFastPath(*this); … … 725 729 ASSERT(gen.endJumpList().empty()); 726 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 } 743 } 744 745 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 746 { 747 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); 748 749 int result = currentInstruction[1].u.operand; 750 int op1 = currentInstruction[2].u.operand; 751 int op2 = currentInstruction[3].u.operand; 752 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 753 754 #if USE(JSVALUE64) 755 JSValueRegs leftRegs = JSValueRegs(regT0); 756 JSValueRegs rightRegs = JSValueRegs(regT1); 757 JSValueRegs resultRegs = leftRegs; 758 #else 759 JSValueRegs leftRegs = JSValueRegs(regT1, regT0); 760 JSValueRegs rightRegs = JSValueRegs(regT3, regT2); 761 JSValueRegs resultRegs = leftRegs; 762 #endif 763 764 SnippetOperand leftOperand(types.first()); 765 SnippetOperand rightOperand(types.second()); 766 767 if (isOperandConstantInt(op1)) 768 leftOperand.setConstInt32(getOperandConstantInt(op1)); 769 else if (isOperandConstantInt(op2)) 770 rightOperand.setConstInt32(getOperandConstantInt(op2)); 771 772 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 { 727 781 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add); 728 782 slowPathCall.call(); 729 783 } 730 }731 732 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)733 {734 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);735 736 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add);737 slowPathCall.call();738 784 } 739 785 … … 865 911 ASSERT(gen.endJumpList().empty()); 866 912 ASSERT(gen.slowPathJumpList().empty()); 913 if (resultProfile) { 914 if (leftOperand.isPositiveConstInt32()) 915 emitGetVirtualRegister(op1, leftRegs); 916 if (rightOperand.isPositiveConstInt32()) 917 emitGetVirtualRegister(op2, rightRegs); 918 callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, resultProfile); 919 emitPutVirtualRegister(result, resultRegs); 920 } else { 921 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul); 922 slowPathCall.call(); 923 } 924 } 925 } 926 927 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 928 { 929 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); 930 931 int result = currentInstruction[1].u.operand; 932 int op1 = currentInstruction[2].u.operand; 933 int op2 = currentInstruction[3].u.operand; 934 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 935 936 #if USE(JSVALUE64) 937 JSValueRegs leftRegs = JSValueRegs(regT0); 938 JSValueRegs rightRegs = JSValueRegs(regT1); 939 JSValueRegs resultRegs = leftRegs; 940 #else 941 JSValueRegs leftRegs = JSValueRegs(regT1, regT0); 942 JSValueRegs rightRegs = JSValueRegs(regT3, regT2); 943 JSValueRegs resultRegs = leftRegs; 944 #endif 945 946 SnippetOperand leftOperand(types.first()); 947 SnippetOperand rightOperand(types.second()); 948 949 if (isOperandConstantInt(op1)) 950 leftOperand.setConstInt32(getOperandConstantInt(op1)); 951 else if (isOperandConstantInt(op2)) 952 rightOperand.setConstInt32(getOperandConstantInt(op2)); 953 954 if (shouldEmitProfiling()) { 955 if (leftOperand.isPositiveConstInt32()) 956 emitGetVirtualRegister(op1, leftRegs); 957 if (rightOperand.isPositiveConstInt32()) 958 emitGetVirtualRegister(op2, rightRegs); 959 ResultProfile* resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset); 960 callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, resultProfile); 961 emitPutVirtualRegister(result, resultRegs); 962 } else { 867 963 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul); 868 964 slowPathCall.call(); 869 965 } 870 }871 872 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)873 {874 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);875 876 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);877 slowPathCall.call();878 966 } 879 967 … … 899 987 #endif 900 988 989 ResultProfile* resultProfile = nullptr; 990 if (shouldEmitProfiling()) 991 resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset); 992 901 993 SnippetOperand leftOperand(types.first()); 902 994 SnippetOperand rightOperand(types.second()); … … 906 998 907 999 JITSubGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, 908 fpRegT0, fpRegT1, scratchGPR, scratchFPR );1000 fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile); 909 1001 910 1002 gen.generateFastPath(*this); … … 921 1013 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); 922 1014 923 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub); 924 slowPathCall.call(); 1015 int result = currentInstruction[1].u.operand; 1016 #if USE(JSVALUE64) 1017 JSValueRegs leftRegs = JSValueRegs(regT0); 1018 JSValueRegs rightRegs = JSValueRegs(regT1); 1019 JSValueRegs resultRegs = leftRegs; 1020 #else 1021 JSValueRegs leftRegs = JSValueRegs(regT1, regT0); 1022 JSValueRegs rightRegs = JSValueRegs(regT3, regT2); 1023 JSValueRegs resultRegs = leftRegs; 1024 #endif 1025 1026 if (shouldEmitProfiling()) { 1027 ResultProfile* resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset); 1028 callOperation(operationValueSubProfiled, resultRegs, leftRegs, rightRegs, resultProfile); 1029 emitPutVirtualRegister(result, resultRegs); 1030 } else { 1031 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub); 1032 slowPathCall.call(); 1033 } 925 1034 } 926 1035 -
trunk/Source/JavaScriptCore/jit/JITInlines.h
r199710 r200606 417 417 } 418 418 419 inline MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJRp operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ResultProfile* resultProfile) 420 { 421 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(resultProfile)); 422 Call call = appendCallWithExceptionCheck(operation); 423 setupResults(result); 424 return call; 425 } 426 419 427 #if USE(JSVALUE64) 420 428 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3) … … 603 611 #else // USE(JSVALUE32_64) 604 612 605 // EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).606 // To avoid assemblies from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary.607 #if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS)608 #define EABI_32BIT_DUMMY_ARG TrustedImm32(0),609 #else610 #define EABI_32BIT_DUMMY_ARG611 #endif612 613 // JSVALUE32_64 is a 64-bit integer that cannot be put half in an argument register and half on stack when using SH4 architecture.614 // To avoid this, let's occupy the 4th argument register (r7) with a dummy argument when necessary. This must only be done when there615 // is no other 32-bit value argument behind this 64-bit JSValue.616 #if CPU(SH4)617 #define SH4_32BIT_DUMMY_ARG TrustedImm32(0),618 #else619 #define SH4_32BIT_DUMMY_ARG620 #endif621 622 613 ALWAYS_INLINE MacroAssembler::Call JIT::callOperationNoExceptionCheck(V_JITOperation_EJ operation, GPRReg arg1Tag, GPRReg arg1Payload) 623 614 { … … 800 791 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 801 792 } 802 803 #undef EABI_32BIT_DUMMY_ARG804 #undef SH4_32BIT_DUMMY_ARG805 793 806 794 #endif // USE(JSVALUE32_64) -
trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp
r200502 r200606 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 154 154 155 155 notNegativeZero.link(&jit); 156 jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags())); 156 157 157 158 jit.move(m_result.payloadGPR(), m_scratchGPR); … … 175 176 176 177 notNegativeZero.link(&jit); 178 jit.or32(CCallHelpers::TrustedImm32(ResultProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfFlags())); 177 179 178 180 jit.move(m_result.tagGPR(), m_scratchGPR); -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r200459 r200606 2244 2244 } 2245 2245 2246 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 2247 { 2248 VM* vm = &exec->vm(); 2249 NativeCallFrameTracer tracer(vm, exec); 2250 2251 JSValue op1 = JSValue::decode(encodedOp1); 2252 JSValue op2 = JSValue::decode(encodedOp2); 2253 2254 return JSValue::encode(jsAdd(exec, op1, op2)); 2255 } 2256 2257 EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile) 2258 { 2259 VM* vm = &exec->vm(); 2260 NativeCallFrameTracer tracer(vm, exec); 2261 2262 JSValue op1 = JSValue::decode(encodedOp1); 2263 JSValue op2 = JSValue::decode(encodedOp2); 2264 2265 JSValue result = jsAdd(exec, op1, op2); 2266 resultProfile->detectNumericness(result); 2267 return JSValue::encode(result); 2268 } 2269 2270 EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 2271 { 2272 VM* vm = &exec->vm(); 2273 NativeCallFrameTracer tracer(vm, exec); 2274 2275 JSValue op1 = JSValue::decode(encodedOp1); 2276 JSValue op2 = JSValue::decode(encodedOp2); 2277 2278 double a = op1.toNumber(exec); 2279 double b = op2.toNumber(exec); 2280 return JSValue::encode(jsNumber(a * b)); 2281 } 2282 2283 EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile) 2284 { 2285 VM* vm = &exec->vm(); 2286 NativeCallFrameTracer tracer(vm, exec); 2287 2288 JSValue op1 = JSValue::decode(encodedOp1); 2289 JSValue op2 = JSValue::decode(encodedOp2); 2290 2291 double a = op1.toNumber(exec); 2292 double b = op2.toNumber(exec); 2293 2294 JSValue result = jsNumber(a * b); 2295 resultProfile->detectNumericness(result); 2296 return JSValue::encode(result); 2297 } 2298 2299 EncodedJSValue JIT_OPERATION operationValueSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 2300 { 2301 VM* vm = &exec->vm(); 2302 NativeCallFrameTracer tracer(vm, exec); 2303 2304 JSValue op1 = JSValue::decode(encodedOp1); 2305 JSValue op2 = JSValue::decode(encodedOp2); 2306 2307 double a = op1.toNumber(exec); 2308 double b = op2.toNumber(exec); 2309 return JSValue::encode(jsNumber(a - b)); 2310 } 2311 2312 EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile* resultProfile) 2313 { 2314 VM* vm = &exec->vm(); 2315 NativeCallFrameTracer tracer(vm, exec); 2316 2317 JSValue op1 = JSValue::decode(encodedOp1); 2318 JSValue op2 = JSValue::decode(encodedOp2); 2319 2320 double a = op1.toNumber(exec); 2321 double b = op2.toNumber(exec); 2322 2323 JSValue result = jsNumber(a - b); 2324 resultProfile->detectNumericness(result); 2325 return JSValue::encode(result); 2326 } 2327 2246 2328 void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec) 2247 2329 { -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r200586 r200606 54 54 struct ByValInfo; 55 55 struct InlineCallFrame; 56 struct ResultProfile; 56 57 57 58 typedef ExecState CallFrame; … … 97 98 R: Register 98 99 Reo: RegExpObject* 100 Rp: ResultProfile* 99 101 S: size_t 100 102 Sprt: SlowPathReturnType … … 137 139 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, ByValInfo*); 138 140 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue); 141 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJRp)(ExecState*, EncodedJSValue, EncodedJSValue, ResultProfile*); 139 142 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t); 140 143 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssReo)(ExecState*, JSString*, RegExpObject*); … … 410 413 JSCell* JIT_OPERATION operationToIndexString(ExecState*, int32_t); 411 414 415 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 416 EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL; 417 EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 418 EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL; 419 EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 420 EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ResultProfile*) WTF_INTERNAL; 421 412 422 void JIT_OPERATION operationProcessTypeProfilerLog(ExecState*) WTF_INTERNAL; 413 423 void JIT_OPERATION operationProcessShadowChickenLog(ExecState*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/jit/JITSubGenerator.cpp
r192842 r200606 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 84 84 85 85 jit.subDouble(m_rightFPR, m_leftFPR); 86 if (m_resultProfile) 87 m_resultProfile->emitSetDouble(jit); 88 86 89 jit.boxDouble(m_leftFPR, m_result); 87 90 } -
trunk/Source/JavaScriptCore/jit/JITSubGenerator.h
r192842 r200606 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 38 38 JITSubGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand, 39 39 JSValueRegs result, JSValueRegs left, JSValueRegs right, 40 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR) 40 FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR, 41 ResultProfile* resultProfile = nullptr) 41 42 : m_leftOperand(leftOperand) 42 43 , m_rightOperand(rightOperand) … … 48 49 , m_scratchGPR(scratchGPR) 49 50 , m_scratchFPR(scratchFPR) 51 , m_resultProfile(resultProfile) 50 52 { } 51 53 … … 66 68 GPRReg m_scratchGPR; 67 69 FPRReg m_scratchFPR; 70 ResultProfile* m_resultProfile; 68 71 bool m_didEmitFastPath { false }; 69 72 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r200586 r200606 379 379 profile->setObservedNegZeroDouble(); 380 380 else { 381 profile->setObservedNonNegZeroDouble(); 382 381 383 // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value. 382 384 // Therefore, we will get a false positive if the result is that value. This is intentionally -
trunk/Source/JavaScriptCore/runtime/Options.h
r200543 r200606 176 176 v(bool, reportFTLCompileTimes, false, Normal, "dumps JS function signature and the time it took to FTL compile") \ 177 177 v(bool, reportTotalCompileTimes, false, Normal, nullptr) \ 178 v(bool, verboseExitProfile, false, Normal, nullptr) \ 178 179 v(bool, verboseCFA, false, Normal, nullptr) \ 179 180 v(bool, verboseFTLToJSThunk, false, Normal, nullptr) \
Note: See TracChangeset
for help on using the changeset viewer.